diff options
Diffstat (limited to 'services')
21 files changed, 493 insertions, 210 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b785d3d..7d8e9de 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -18,7 +18,6 @@ package com.android.server; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_VPN; @@ -1386,7 +1385,6 @@ public class ConnectivityService extends IConnectivityManager.Stub public void sendConnectedBroadcast(NetworkInfo info) { enforceConnectivityInternalPermission(); - sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE); sendGeneralBroadcast(info, CONNECTIVITY_ACTION); } @@ -3456,7 +3454,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public boolean requestBwUpdate(Network network) { + public boolean requestBandwidthUpdate(Network network) { enforceAccessPermission(); NetworkAgentInfo nai = null; if (network == null) { @@ -3520,10 +3518,34 @@ public class ConnectivityService extends IConnectivityManager.Stub getCallingUid(), 0, operation)); } + // In order to implement the compatibility measure for pre-M apps that call + // WifiManager.enableNetwork(..., true) without also binding to that network explicitly, + // WifiManager registers a network listen for the purpose of calling setProcessDefaultNetwork. + // This ensures it has permission to do so. + private boolean hasWifiNetworkListenPermission(NetworkCapabilities nc) { + if (nc == null) { + return false; + } + int[] transportTypes = nc.getTransportTypes(); + if (transportTypes.length != 1 || transportTypes[0] != NetworkCapabilities.TRANSPORT_WIFI) { + return false; + } + try { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_WIFI_STATE, + "ConnectivityService"); + } catch (SecurityException e) { + return false; + } + return true; + } + @Override public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, IBinder binder) { - enforceAccessPermission(); + if (!hasWifiNetworkListenPermission(networkCapabilities)) { + enforceAccessPermission(); + } NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities( networkCapabilities), TYPE_NONE, nextNetworkRequestId()); @@ -4365,9 +4387,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); - final Intent immediateIntent = new Intent(intent); - immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE); - sendStickyBroadcast(immediateIntent); sendStickyBroadcast(intent); if (newDefaultAgent != null) { sendConnectedBroadcast(newDefaultAgent.networkInfo); @@ -4444,4 +4463,30 @@ public class ConnectivityService extends IConnectivityManager.Stub } return success; } + + @Override + public void factoryReset() { + enforceConnectivityInternalPermission(); + // Turn airplane mode off + setAirplaneMode(false); + + // Untether + for (String tether : getTetheredIfaces()) { + untether(tether); + } + + // Turn VPN off + VpnConfig vpnConfig = getVpnConfig(); + if (vpnConfig != null) { + if (vpnConfig.legacy) { + prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); + } else { + // Prevent this app from initiating VPN connections in the future without + // user intervention. + setVpnPackageAuthorization(false); + + prepareVpn(vpnConfig.user, VpnConfig.LEGACY_VPN); + } + } + } } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 649fcde..f88802a 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -823,7 +823,10 @@ class MountService extends IMountService.Stub case VoldResponseCode.DISK_CREATED: { if (cooked.length != 3) break; final String id = cooked[1]; - final int flags = Integer.parseInt(cooked[2]); + int flags = Integer.parseInt(cooked[2]); + if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)) { + flags |= DiskInfo.FLAG_ADOPTABLE; + } mDisks.put(id, new DiskInfo(id, flags)); break; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index b658932..1a94037 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -114,6 +114,7 @@ import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerInternal; +import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityManagerNative; import android.app.ActivityOptions; import android.app.ActivityThread; @@ -1013,6 +1014,13 @@ public final class ActivityManagerService extends ActivityManagerNative */ private int mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE; + /** + * A list of tokens that cause the top activity to be put to sleep. + * They are used by components that may hide and block interaction with underlying + * activities. + */ + final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>(); + static final int LOCK_SCREEN_HIDDEN = 0; static final int LOCK_SCREEN_LEAVING = 1; static final int LOCK_SCREEN_SHOWN = 2; @@ -1312,10 +1320,11 @@ public final class ActivityManagerService extends ActivityManagerNative final ServiceThread mHandlerThread; final MainHandler mHandler; + final UiHandler mUiHandler; - final class MainHandler extends Handler { - public MainHandler(Looper looper) { - super(looper, null, true); + final class UiHandler extends Handler { + public UiHandler() { + super(com.android.server.UiThread.get().getLooper(), null, true); } @Override @@ -1428,15 +1437,6 @@ public final class ActivityManagerService extends ActivityManagerNative d.show(); ensureBootCompleted(); } break; - case UPDATE_CONFIGURATION_MSG: { - final ContentResolver resolver = mContext.getContentResolver(); - Settings.System.putConfiguration(resolver, (Configuration)msg.obj); - } break; - case GC_BACKGROUND_PROCESSES_MSG: { - synchronized (ActivityManagerService.this) { - performAppGcsIfAppropriateLocked(); - } - } break; case WAIT_FOR_DEBUGGER_MSG: { synchronized (ActivityManagerService.this) { ProcessRecord app = (ProcessRecord)msg.obj; @@ -1457,6 +1457,88 @@ public final class ActivityManagerService extends ActivityManagerNative } } } break; + case SHOW_UID_ERROR_MSG: { + if (mShowDialogs) { + AlertDialog d = new BaseErrorDialog(mContext); + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + d.setCancelable(false); + d.setTitle(mContext.getText(R.string.android_system_label)); + d.setMessage(mContext.getText(R.string.system_error_wipe_data)); + d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), + obtainMessage(DISMISS_DIALOG_MSG, d)); + d.show(); + } + } break; + case SHOW_FINGERPRINT_ERROR_MSG: { + if (mShowDialogs) { + AlertDialog d = new BaseErrorDialog(mContext); + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + d.setCancelable(false); + d.setTitle(mContext.getText(R.string.android_system_label)); + d.setMessage(mContext.getText(R.string.system_error_manufacturer)); + d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), + obtainMessage(DISMISS_DIALOG_MSG, d)); + d.show(); + } + } break; + case SHOW_COMPAT_MODE_DIALOG_MSG: { + synchronized (ActivityManagerService.this) { + ActivityRecord ar = (ActivityRecord) msg.obj; + if (mCompatModeDialog != null) { + if (mCompatModeDialog.mAppInfo.packageName.equals( + ar.info.applicationInfo.packageName)) { + return; + } + mCompatModeDialog.dismiss(); + mCompatModeDialog = null; + } + if (ar != null && false) { + if (mCompatModePackages.getPackageAskCompatModeLocked( + ar.packageName)) { + int mode = mCompatModePackages.computeCompatModeLocked( + ar.info.applicationInfo); + if (mode == ActivityManager.COMPAT_MODE_DISABLED + || mode == ActivityManager.COMPAT_MODE_ENABLED) { + mCompatModeDialog = new CompatModeDialog( + ActivityManagerService.this, mContext, + ar.info.applicationInfo); + mCompatModeDialog.show(); + } + } + } + } + break; + } + case START_USER_SWITCH_MSG: { + showUserSwitchDialog(msg.arg1, (String) msg.obj); + break; + } + case DISMISS_DIALOG_MSG: { + final Dialog d = (Dialog) msg.obj; + d.dismiss(); + break; + } + } + } + } + + final class MainHandler extends Handler { + public MainHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case UPDATE_CONFIGURATION_MSG: { + final ContentResolver resolver = mContext.getContentResolver(); + Settings.System.putConfiguration(resolver, (Configuration) msg.obj); + } break; + case GC_BACKGROUND_PROCESSES_MSG: { + synchronized (ActivityManagerService.this) { + performAppGcsIfAppropriateLocked(); + } + } break; case SERVICE_TIMEOUT_MSG: { if (mDidDexOpt) { mDidDexOpt = false; @@ -1521,30 +1603,6 @@ public final class ActivityManagerService extends ActivityManagerNative } } } break; - case SHOW_UID_ERROR_MSG: { - if (mShowDialogs) { - AlertDialog d = new BaseErrorDialog(mContext); - d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); - d.setCancelable(false); - d.setTitle(mContext.getText(R.string.android_system_label)); - d.setMessage(mContext.getText(R.string.system_error_wipe_data)); - d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), - mHandler.obtainMessage(DISMISS_DIALOG_MSG, d)); - d.show(); - } - } break; - case SHOW_FINGERPRINT_ERROR_MSG: { - if (mShowDialogs) { - AlertDialog d = new BaseErrorDialog(mContext); - d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); - d.setCancelable(false); - d.setTitle(mContext.getText(R.string.android_system_label)); - d.setMessage(mContext.getText(R.string.system_error_manufacturer)); - d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok), - mHandler.obtainMessage(DISMISS_DIALOG_MSG, d)); - d.show(); - } - } break; case PROC_START_TIMEOUT_MSG: { if (mDidDexOpt) { mDidDexOpt = false; @@ -1645,34 +1703,6 @@ public final class ActivityManagerService extends ActivityManagerNative sendMessageDelayed(nmsg, POWER_CHECK_DELAY); } } break; - case SHOW_COMPAT_MODE_DIALOG_MSG: { - synchronized (ActivityManagerService.this) { - ActivityRecord ar = (ActivityRecord)msg.obj; - if (mCompatModeDialog != null) { - if (mCompatModeDialog.mAppInfo.packageName.equals( - ar.info.applicationInfo.packageName)) { - return; - } - mCompatModeDialog.dismiss(); - mCompatModeDialog = null; - } - if (ar != null && false) { - if (mCompatModePackages.getPackageAskCompatModeLocked( - ar.packageName)) { - int mode = mCompatModePackages.computeCompatModeLocked( - ar.info.applicationInfo); - if (mode == ActivityManager.COMPAT_MODE_DISABLED - || mode == ActivityManager.COMPAT_MODE_ENABLED) { - mCompatModeDialog = new CompatModeDialog( - ActivityManagerService.this, mContext, - ar.info.applicationInfo); - mCompatModeDialog.show(); - } - } - } - } - break; - } case DISPATCH_PROCESSES_CHANGED: { dispatchProcessesChanged(); break; @@ -1693,10 +1723,6 @@ public final class ActivityManagerService extends ActivityManagerNative thread.start(); break; } - case START_USER_SWITCH_MSG: { - showUserSwitchDialog(msg.arg1, (String) msg.obj); - break; - } case REPORT_USER_SWITCH_MSG: { dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); break; @@ -1803,11 +1829,6 @@ public final class ActivityManagerService extends ActivityManagerNative } break; } - case DISMISS_DIALOG_MSG: { - final Dialog d = (Dialog) msg.obj; - d.dismiss(); - break; - } case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG: { synchronized (ActivityManagerService.this) { int i = mTaskStackListeners.beginBroadcast(); @@ -2196,6 +2217,7 @@ public final class ActivityManagerService extends ActivityManagerNative android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/); mHandlerThread.start(); mHandler = new MainHandler(mHandlerThread.getLooper()); + mUiHandler = new UiHandler(); mFgBroadcastQueue = new BroadcastQueue(this, mHandler, "foreground", BROADCAST_FG_TIMEOUT, false); @@ -2596,7 +2618,7 @@ public final class ActivityManagerService extends ActivityManagerNative Message msg = Message.obtain(); msg.what = SHOW_COMPAT_MODE_DIALOG_MSG; msg.obj = r.task.askedCompatMode ? null : r; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } private int updateLruProcessInternalLocked(ProcessRecord app, long now, int index, @@ -4778,20 +4800,20 @@ public final class ActivityManagerService extends ActivityManagerNative map.put("activity", activity); } - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } } final void showLaunchWarningLocked(final ActivityRecord cur, final ActivityRecord next) { if (!mLaunchWarningShown) { mLaunchWarningShown = true; - mHandler.post(new Runnable() { + mUiHandler.post(new Runnable() { @Override public void run() { synchronized (ActivityManagerService.this) { final Dialog d = new LaunchWarningWindow(mContext, cur, next); d.show(); - mHandler.postDelayed(new Runnable() { + mUiHandler.postDelayed(new Runnable() { @Override public void run() { synchronized (ActivityManagerService.this) { @@ -7750,7 +7772,7 @@ public final class ActivityManagerService extends ActivityManagerNative msg.what = WAIT_FOR_DEBUGGER_MSG; msg.obj = app; msg.arg1 = waiting ? 1 : 0; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } } @@ -9813,15 +9835,14 @@ public final class ActivityManagerService extends ActivityManagerNative return false; } + // TODO: Transform the lock screen state into a sleep token instead. switch (mWakefulness) { case PowerManagerInternal.WAKEFULNESS_AWAKE: case PowerManagerInternal.WAKEFULNESS_DREAMING: - // If we're interactive but applications are already paused then defer - // resuming them until the lock screen is hidden. - return mSleeping && mLockScreenShown != LOCK_SCREEN_HIDDEN; case PowerManagerInternal.WAKEFULNESS_DOZING: - // If we're dozing then pause applications whenever the lock screen is shown. - return mLockScreenShown != LOCK_SCREEN_HIDDEN; + // Pause applications whenever the lock screen is shown or any sleep + // tokens have been acquired. + return (mLockScreenShown != LOCK_SCREEN_HIDDEN || !mSleepTokens.isEmpty()); case PowerManagerInternal.WAKEFULNESS_ASLEEP: default: // If we're asleep then pause applications unconditionally. @@ -11177,7 +11198,7 @@ public final class ActivityManagerService extends ActivityManagerNative Message msg = Message.obtain(); msg.what = SHOW_FACTORY_ERROR_MSG; msg.getData().putCharSequence("msg", errorMsg); - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); } } } @@ -11227,14 +11248,14 @@ public final class ActivityManagerService extends ActivityManagerNative if (AppGlobals.getPackageManager().hasSystemUidErrors()) { Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your" + " data partition or your device will be unstable."); - mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget(); + mUiHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget(); } } catch (RemoteException e) { } if (!Build.isBuildConsistent()) { Slog.e(TAG, "Build fingerprint is not consistent, warning user"); - mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget(); + mUiHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget(); } long ident = Binder.clearCallingIdentity(); @@ -11521,7 +11542,7 @@ public final class ActivityManagerService extends ActivityManagerNative data.put("violationMask", violationMask); data.put("info", info); msg.obj = data; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); Binder.restoreCallingIdentity(origId); } @@ -11976,7 +11997,7 @@ public final class ActivityManagerService extends ActivityManagerNative data.put("result", result); data.put("app", r); msg.obj = data; - mHandler.sendMessage(msg); + mUiHandler.sendMessage(msg); Binder.restoreCallingIdentity(origId); } @@ -12950,6 +12971,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (dumpPackage == null) { pw.println(" mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness)); + pw.println(" mSleepTokens=" + mSleepTokens); pw.println(" mSleeping=" + mSleeping + " mLockScreenShown=" + lockScreenShownToString()); pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode); @@ -14754,7 +14776,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - for (int i=0; i<cpr.connections.size(); i++) { + for (int i = cpr.connections.size() - 1; i >= 0; i--) { ContentProviderConnection conn = cpr.connections.get(i); if (conn.waiting) { // If this connection is waiting for the provider, then we don't @@ -14846,10 +14868,11 @@ public final class ActivityManagerService extends ActivityManagerNative boolean restart = false; // Remove published content providers. - for (int i=app.pubProviders.size()-1; i>=0; i--) { + for (int i = app.pubProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = app.pubProviders.valueAt(i); final boolean always = app.bad || !allowRestart; - if (removeDyingProviderLocked(app, cpr, always) || always) { + boolean inLaunching = removeDyingProviderLocked(app, cpr, always); + if ((inLaunching || always) && !cpr.connections.isEmpty()) { // We left the provider in the launching list, need to // restart it. restart = true; @@ -14867,7 +14890,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Unregister from connected content providers. if (!app.conProviders.isEmpty()) { - for (int i=0; i<app.conProviders.size(); i++) { + for (int i = app.conProviders.size() - 1; i >= 0; i--) { ContentProviderConnection conn = app.conProviders.get(i); conn.provider.connections.remove(conn); stopAssociationLocked(app.uid, app.processName, conn.provider.uid, @@ -14882,9 +14905,8 @@ public final class ActivityManagerService extends ActivityManagerNative // XXX Commented out for now. Trying to figure out a way to reproduce // the actual situation to identify what is actually going on. if (false) { - for (int i=0; i<mLaunchingProviders.size(); i++) { - ContentProviderRecord cpr = (ContentProviderRecord) - mLaunchingProviders.get(i); + for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) { + ContentProviderRecord cpr = mLaunchingProviders.get(i); if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) { synchronized (cpr) { cpr.launchingApp = null; @@ -14897,7 +14919,7 @@ public final class ActivityManagerService extends ActivityManagerNative skipCurrentReceiverLocked(app); // Unregister any receivers. - for (int i=app.receivers.size()-1; i>=0; i--) { + for (int i = app.receivers.size() - 1; i >= 0; i--) { removeReceiverLocked(app.receivers.valueAt(i)); } app.receivers.clear(); @@ -14915,7 +14937,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - for (int i = mPendingProcessChanges.size()-1; i>=0; i--) { + for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) { ProcessChangeItem item = mPendingProcessChanges.get(i); if (item.pid == app.pid) { mPendingProcessChanges.remove(i); @@ -14990,18 +15012,14 @@ public final class ActivityManagerService extends ActivityManagerNative // and if any run in this process then either schedule a restart of // the process or kill the client waiting for it if this process has // gone bad. - int NL = mLaunchingProviders.size(); boolean restart = false; - for (int i=0; i<NL; i++) { + for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = mLaunchingProviders.get(i); if (cpr.launchingApp == app) { - if (!alwaysBad && !app.bad) { + if (!alwaysBad && !app.bad && !cpr.connections.isEmpty()) { restart = true; } else { removeDyingProviderLocked(app, cpr, true); - // cpr should have been removed from mLaunchingProviders - NL = mLaunchingProviders.size(); - i--; } } } @@ -18966,8 +18984,8 @@ public final class ActivityManagerService extends ActivityManagerNative userName = userInfo.name; mTargetUserId = userId; } - mHandler.removeMessages(START_USER_SWITCH_MSG); - mHandler.sendMessage(mHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); + mUiHandler.removeMessages(START_USER_SWITCH_MSG); + mUiHandler.sendMessage(mUiHandler.obtainMessage(START_USER_SWITCH_MSG, userId, 0, userName)); return true; } @@ -19723,6 +19741,42 @@ public final class ActivityManagerService extends ActivityManagerNative return ActivityManagerService.this.startIsolatedProcess(entryPoint, entryPointArgs, processName, abiOverride, uid, crashHandler); } + + @Override + public SleepToken acquireSleepToken(String tag) { + Preconditions.checkNotNull(tag); + + synchronized (ActivityManagerService.this) { + SleepTokenImpl token = new SleepTokenImpl(tag); + mSleepTokens.add(token); + updateSleepIfNeededLocked(); + return token; + } + } + } + + private final class SleepTokenImpl extends SleepToken { + private final String mTag; + private final long mAcquireTime; + + public SleepTokenImpl(String tag) { + mTag = tag; + mAcquireTime = SystemClock.uptimeMillis(); + } + + @Override + public void release() { + synchronized (ActivityManagerService.this) { + if (mSleepTokens.remove(this)) { + updateSleepIfNeededLocked(); + } + } + } + + @Override + public String toString() { + return "{\"" + mTag + "\", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; + } } /** diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 5b5ebef..f62f08d 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -765,7 +765,8 @@ public final class BroadcastQueue { try { perm = AppGlobals.getPackageManager(). checkPermission(r.requiredPermission, - info.activityInfo.applicationInfo.packageName, r.userId); + info.activityInfo.applicationInfo.packageName, + UserHandle.getUserId(info.activityInfo.applicationInfo.uid)); } catch (RemoteException e) { perm = PackageManager.PERMISSION_DENIED; } diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 770df82..ac488e3 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -67,6 +67,9 @@ public class FingerprintService extends SystemService { private static final int FINGERPRINT_TEMPLATE_ENROLLING = 3; private static final int FINGERPRINT_TEMPLATE_REMOVED = 4; private static final int FINGERPRINT_AUTHENTICATED = 5; + private static final long MS_PER_SEC = 1000; + private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; + private static final int MAX_FAILED_ATTEMPTS = 5; Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { @@ -91,14 +94,6 @@ public class FingerprintService extends SystemService { } }; - private static final int STATE_IDLE = 0; - private static final int STATE_AUTHENTICATING = 1; - private static final int STATE_ENROLLING = 2; - private static final int STATE_REMOVING = 3; - private static final long MS_PER_SEC = 1000; - private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; - private static final int MAX_FAILED_ATTEMPTS = 5; - public FingerprintService(Context context) { super(context); mContext = context; @@ -427,6 +422,7 @@ public class FingerprintService extends SystemService { private boolean sendEnrollResult(int fpId, int groupId, int remaining) { IFingerprintServiceReceiver rx = receiver.get(); if (rx == null) return true; // client not listening + FingerprintUtils.vibrateFingerprintSuccess(getContext()); try { rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining); return remaining == 0; @@ -453,8 +449,10 @@ public class FingerprintService extends SystemService { result = true; // client not listening } if (fpId <= 0) { + FingerprintUtils.vibrateFingerprintError(getContext()); result |= handleFailedAttempt(this); } else { + FingerprintUtils.vibrateFingerprintSuccess(getContext()); result |= true; // we have a valid fingerprint mLockoutReset.run(); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index b24bc65..8031c05 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -176,6 +176,7 @@ abstract class HdmiCecLocalDevice { void init() { assertRunOnServiceThread(); mPreferredAddress = getPreferredAddress(); + mPendingActionClearedCallback = null; } /** @@ -837,16 +838,16 @@ abstract class HdmiCecLocalDevice { * * @param initiatedByCec true if this sequence is initiated * by the reception the CEC messages like <Standby> - * @param origialCallback callback interface to get notified when all pending actions are + * @param originalCallback callback interface to get notified when all pending actions are * cleared */ protected void disableDevice(boolean initiatedByCec, - final PendingActionClearedCallback origialCallback) { + final PendingActionClearedCallback originalCallback) { mPendingActionClearedCallback = new PendingActionClearedCallback() { @Override public void onCleared(HdmiCecLocalDevice device) { mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT); - origialCallback.onCleared(device); + originalCallback.onCleared(device); } }; mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_DISABLE_DEVICE_TIMEOUT), @@ -865,6 +866,9 @@ abstract class HdmiCecLocalDevice { action.finish(false); iter.remove(); } + if (mPendingActionClearedCallback != null) { + mPendingActionClearedCallback.onCleared(this); + } } /** diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 94f8dee..c4f410f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -1109,11 +1109,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleTerminateArc(HdmiCecMessage message) { assertRunOnServiceThread(); - // In cast of termination, do not check ARC configuration in that AVR device - // might be removed already. - - // In case where <Terminate Arc> is started by <Request ARC Termination> - // need to clean up RequestArcInitiationAction. + if (mService .isPowerStandbyOrTransient()) { + setArcStatus(false); + return true; + } + // Do not check ARC configuration since the AVR might have been already removed. + // Clean up RequestArcTerminationAction in case <Terminate Arc> was started by + // <Request ARC Termination>. removeAction(RequestArcTerminationAction.class); SetArcTransmissionStateAction action = new SetArcTransmissionStateAction(this, message.getSource(), false); diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index d0b25f7..a72c77e 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -2012,7 +2012,7 @@ public class GpsLocationProvider implements LocationProviderInterface { intentFilter = new IntentFilter(); intentFilter.addAction(ALARM_WAKEUP); intentFilter.addAction(ALARM_TIMEOUT); - intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE); + intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); intentFilter.addAction(Intent.ACTION_SCREEN_ON); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index d765816..818f0aa 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -2301,4 +2301,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } fout.print("]"); } + + @Override + public void factoryReset(String subscriber) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + // Turn mobile data limit off + NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName()); + NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriber); + for (NetworkPolicy policy : policies) { + if (policy.template.equals(template)) { + policy.limitBytes = NetworkPolicy.LIMIT_DISABLED; + policy.inferred = false; + policy.clearSnooze(); + } + } + setNetworkPolicies(policies); + + // Turn restrict background data off + setRestrictBackground(false); + + // Remove app's "restrict background data" flag + for (int uid : getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) { + setUidPolicy(uid, POLICY_NONE); + } + } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 997d546..2df79b2 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1282,6 +1282,44 @@ public class NotificationManagerService extends SystemService { } /** + * Public API for getting a list of current notifications for the calling package/uid. + * + * @returns A list of all the package's notifications, in natural order. + */ + @Override + public ParceledListSlice<StatusBarNotification> getAppActiveNotifications(String pkg, + int incomingUserId) { + checkCallerIsSystemOrSameApp(pkg); + int userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), + Binder.getCallingUid(), incomingUserId, true, false, + "getAppActiveNotifications", pkg); + + final int N = mNotificationList.size(); + final ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>(N); + + synchronized (mNotificationList) { + for (int i = 0; i < N; i++) { + final StatusBarNotification sbn = mNotificationList.get(i).sbn; + if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId) { + // We could pass back a cloneLight() but clients might get confused and + // try to send this thing back to notify() again, which would not work + // very well. + final StatusBarNotification sbnOut = new StatusBarNotification( + sbn.getPackageName(), + sbn.getOpPkg(), + sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(), + 0, // hide score from apps + sbn.getNotification().clone(), + sbn.getUser(), sbn.getPostTime()); + list.add(sbnOut); + } + } + } + + return new ParceledListSlice<StatusBarNotification>(list); + } + + /** * System-only API for getting a list of recent (cleared, no longer shown) notifications. * * Requires ACCESS_NOTIFICATIONS which is signature|system. @@ -1610,6 +1648,18 @@ public class NotificationManagerService extends SystemService { return mConditionProviders.isSystemProviderEnabled(path); } + // Backup/restore interface + @Override + public byte[] getBackupPayload(int user) { + // TODO: build a payload of whatever is appropriate + return null; + } + + @Override + public void applyRestore(byte[] payload, int user) { + // TODO: apply the restored payload as new current state + } + @Override public Policy.Token getPolicyTokenFromListener(INotificationListener listener) { final long identity = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java index fbb5090..3749957 100644 --- a/services/core/java/com/android/server/pm/PermissionsState.java +++ b/services/core/java/com/android/server/pm/PermissionsState.java @@ -61,6 +61,9 @@ public final class PermissionsState { private static final int[] NO_GIDS = {}; + private static final int FLAG_INSTALL_PERMISSIONS = 1 << 0; + private static final int FLAG_RUNTIME_PERMISSIONS = 1 << 1; + private ArrayMap<String, PermissionData> mPermissions; private int[] mGlobalGids = NO_GIDS; @@ -90,6 +93,9 @@ public final class PermissionsState { * @param other The other instance. */ public void copyFrom(PermissionsState other) { + if (other == this) { + return; + } if (mPermissions != null) { if (other.mPermissions == null) { mPermissions = null; @@ -274,29 +280,7 @@ public final class PermissionsState { * @return The permissions or an empty set. */ public Set<String> getPermissions(int userId) { - enforceValidUserId(userId); - - if (mPermissions == null) { - return Collections.emptySet(); - } - - Set<String> permissions = new ArraySet<>(); - - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - String permission = mPermissions.keyAt(i); - if (userId == UserHandle.USER_ALL) { - if (hasInstallPermission(permission)) { - permissions.add(permission); - } - } else { - if (hasRuntimePermission(permission, userId)) { - permissions.add(permission); - } - } - } - - return permissions; + return getPermissionsInternal(FLAG_INSTALL_PERMISSIONS | FLAG_RUNTIME_PERMISSIONS, userId); } /** @@ -305,7 +289,7 @@ public final class PermissionsState { * @return The permissions or an empty set. */ public Set<String> getRuntimePermissions(int userId) { - return getPermissions(userId); + return getPermissionsInternal(FLAG_RUNTIME_PERMISSIONS, userId); } /** @@ -314,7 +298,7 @@ public final class PermissionsState { * @return The permissions or an empty set. */ public Set<String> getInstallPermissions() { - return getPermissions(UserHandle.USER_ALL); + return getPermissionsInternal(FLAG_INSTALL_PERMISSIONS, UserHandle.USER_ALL); } /** @@ -373,6 +357,38 @@ public final class PermissionsState { mPermissions = null; } + private Set<String> getPermissionsInternal(int flags, int userId) { + enforceValidUserId(userId); + + if (mPermissions == null) { + return Collections.emptySet(); + } + + if (userId == UserHandle.USER_ALL) { + flags = FLAG_INSTALL_PERMISSIONS; + } + + Set<String> permissions = new ArraySet<>(); + + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + String permission = mPermissions.keyAt(i); + + if ((flags & FLAG_INSTALL_PERMISSIONS) != 0) { + if (hasInstallPermission(permission)) { + permissions.add(permission); + } + } + if ((flags & FLAG_RUNTIME_PERMISSIONS) != 0) { + if (hasRuntimePermission(permission, userId)) { + permissions.add(permission); + } + } + } + + return permissions; + } + private int grantPermission(BasePermission permission, int userId) { if (hasPermission(permission.name, userId)) { return PERMISSION_OPERATION_FAILURE; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fce01e5..25857c5 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -17,6 +17,8 @@ package com.android.server.policy; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; +import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.IUiModeManager; @@ -252,6 +254,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManagerFuncs mWindowManagerFuncs; WindowManagerInternal mWindowManagerInternal; PowerManager mPowerManager; + ActivityManagerInternal mActivityManagerInternal; DreamManagerInternal mDreamManagerInternal; IStatusBarService mStatusBarService; boolean mPreloadedRecentApps; @@ -493,6 +496,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mShowingLockscreen; boolean mShowingDream; boolean mDreamingLockscreen; + boolean mDreamingSleepTokenNeeded; + SleepToken mDreamingSleepToken; boolean mKeyguardSecure; boolean mKeyguardSecureIncludingHidden; volatile boolean mKeyguardOccluded; @@ -599,6 +604,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; private static final int MSG_POWER_DELAYED_PRESS = 13; private static final int MSG_POWER_LONG_PRESS = 14; + private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15; private class PolicyHandler extends Handler { @Override @@ -647,6 +653,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_POWER_LONG_PRESS: powerLongPress(); break; + case MSG_UPDATE_DREAMING_SLEEP_TOKEN: + updateDreamingSleepToken(msg.arg1 != 0); + break; } } } @@ -1220,6 +1229,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mWindowManager = windowManager; mWindowManagerFuncs = windowManagerFuncs; mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); + mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); // Init display burn-in protection @@ -4215,8 +4225,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public int finishPostLayoutPolicyLw() { - if (mWinShowWhenLocked != null && - mWinShowWhenLocked != mTopFullscreenOpaqueWindowState) { + if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null && + mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken() + && isKeyguardLocked()) { // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the // fullscreen window. // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not. @@ -4238,6 +4249,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { // while the dream is showing. if (!mShowingDream) { mDreamingLockscreen = mShowingLockscreen; + if (mDreamingSleepTokenNeeded) { + mDreamingSleepTokenNeeded = false; + mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); + } + } else { + if (!mDreamingSleepTokenNeeded) { + mDreamingSleepTokenNeeded = true; + mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); + } } if (mStatusBar != null) { @@ -5850,6 +5870,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void updateDreamingSleepToken(boolean acquire) { + if (acquire) { + if (mDreamingSleepToken == null) { + mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); + } + } else { + if (mDreamingSleepToken != null) { + mDreamingSleepToken.release(); + } + } + } + /** {@inheritDoc} */ @Override public void enableScreenAfterBoot() { @@ -6486,7 +6518,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen); pw.print(" mShowingDream="); pw.print(mShowingDream); - pw.print(" mDreamingLockscreen="); pw.println(mDreamingLockscreen); + pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); + pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); if (mLastInputMethodWindow != null) { pw.print(prefix); pw.print("mLastInputMethodWindow="); pw.println(mLastInputMethodWindow); diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 3262cc6..5972247 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -18,8 +18,6 @@ package com.android.server.tv; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; -import static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED; -import static android.media.tv.TvInputManager.INPUT_STATE_UNKNOWN; import android.app.ActivityManager; import android.content.BroadcastReceiver; @@ -800,7 +798,7 @@ public final class TvInputManagerService extends SystemService { synchronized (mLock) { UserState userState = getUserStateLocked(resolvedUserId); TvInputState state = userState.inputMap.get(inputId); - return state == null ? INPUT_STATE_UNKNOWN : state.state; + return state == null ? INPUT_STATE_CONNECTED : state.state; } } finally { Binder.restoreCallingIdentity(identity); @@ -1908,7 +1906,7 @@ public final class TvInputManagerService extends SystemService { for (TvInputState inputState : userState.inputMap.values()) { if (inputState.info.getComponent().equals(component) - && inputState.state != INPUT_STATE_DISCONNECTED) { + && inputState.state != INPUT_STATE_CONNECTED) { notifyInputStateChangedLocked(userState, inputState.info.getId(), inputState.state, null); } @@ -1957,13 +1955,6 @@ public final class TvInputManagerService extends SystemService { serviceState.callback = null; abortPendingCreateSessionRequestsLocked(serviceState, null, mUserId); - - for (TvInputState inputState : userState.inputMap.values()) { - if (inputState.info.getComponent().equals(component)) { - notifyInputStateChangedLocked(userState, inputState.info.getId(), - INPUT_STATE_DISCONNECTED, null); - } - } } } } @@ -2508,9 +2499,6 @@ public final class TvInputManagerService extends SystemService { } private static class SessionNotFoundException extends IllegalArgumentException { - public SessionNotFoundException() { - } - public SessionNotFoundException(String name) { super(name); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java index 2661643..28ffc57 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java @@ -60,7 +60,7 @@ class DeviceOwner { private static final String ATTR_PACKAGE = "package"; private static final String ATTR_COMPONENT_NAME = "component"; private static final String ATTR_USERID = "userId"; - private static final String TAG_OTA_POLICY = "ota-policy"; + private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; private AtomicFile fileForWriting; @@ -77,8 +77,8 @@ class DeviceOwner { // Internal state for the profile owner packages. private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>(); - // Local OTA policy controllable by device owner. - private PersistableBundle mOtaPolicy; + // Local system update policy controllable by device owner. + private PersistableBundle mSystemUpdatePolicy; // Private default constructor. private DeviceOwner() { @@ -192,16 +192,16 @@ class DeviceOwner { return mProfileOwners.keySet(); } - PersistableBundle getOtaPolicy() { - return mOtaPolicy; + PersistableBundle getSystemUpdatePolicy() { + return mSystemUpdatePolicy; } - void setOtaPolicy(PersistableBundle otaPolicy) { - mOtaPolicy = otaPolicy; + void setSystemUpdatePolicy(PersistableBundle systemUpdatePolicy) { + mSystemUpdatePolicy = systemUpdatePolicy; } - void clearOtaPolicy() { - mOtaPolicy = null; + void clearSystemUpdatePolicy() { + mSystemUpdatePolicy = null; } boolean hasDeviceOwner() { @@ -290,8 +290,8 @@ class DeviceOwner { profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName); } mProfileOwners.put(userId, profileOwnerInfo); - } else if (TAG_OTA_POLICY.equals(tag)) { - mOtaPolicy = PersistableBundle.restoreFromXml(parser); + } else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) { + mSystemUpdatePolicy = PersistableBundle.restoreFromXml(parser); } else { throw new XmlPullParserException( "Unexpected tag in device owner file: " + tag); @@ -358,15 +358,15 @@ class DeviceOwner { } } - // Write OTA policy tag - if (mOtaPolicy != null) { - out.startTag(null, TAG_OTA_POLICY); + // Write system update policy tag + if (mSystemUpdatePolicy != null) { + out.startTag(null, TAG_SYSTEM_UPDATE_POLICY); try { - mOtaPolicy.saveToXml(out); + mSystemUpdatePolicy.saveToXml(out); } catch (XmlPullParserException e) { - Slog.e(TAG, "Failed to save OTA policy", e); + Slog.e(TAG, "Failed to save system update policy", e); } - out.endTag(null, TAG_OTA_POLICY); + out.endTag(null, TAG_SYSTEM_UPDATE_POLICY); } out.endDocument(); out.flush(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 8dacf6c..8486705 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -160,6 +160,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String ATTR_ENABLED = "enabled"; + private static final String DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML = + "do-not-ask-credentials-on-boot"; + private static final int REQUEST_EXPIRE_PASSWORD = 5571; private static final long MS_PER_DAY = 86400 * 1000; @@ -307,6 +310,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { String mDelegatedCertInstallerPackage; + boolean doNotAskCredentialsOnBoot = false; + public DevicePolicyData(int userHandle) { mUserHandle = userHandle; } @@ -1456,6 +1461,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.endTag(null, TAG_STATUS_BAR); } + if (policy.doNotAskCredentialsOnBoot) { + out.startTag(null, DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML); + out.endTag(null, DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML); + } + out.endTag(null, "policies"); out.endDocument(); @@ -1581,6 +1591,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { policy.mStatusBarEnabledState = Boolean.parseBoolean( parser.getAttributeValue(null, ATTR_ENABLED)); XmlUtils.skipCurrentTag(parser); + } else if (DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML.equals(tag)) { + policy.doNotAskCredentialsOnBoot = true; } else { Slog.w(LOG_TAG, "Unknown tag: " + tag); XmlUtils.skipCurrentTag(parser); @@ -2840,6 +2852,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } + boolean callerIsDeviceOwnerAdmin = isCallerDeviceOwnerOrInitializer(callingUid); + boolean doNotAskCredentialsOnBoot = + (flags & DevicePolicyManager.DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0; + if (callerIsDeviceOwnerAdmin && doNotAskCredentialsOnBoot) { + setDoNotAskCredentialsOnBoot(); + } + // Don't do this with the lock held, because it is going to call // back in to the service. long ident = Binder.clearCallingIdentity(); @@ -2868,6 +2887,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } + private void setDoNotAskCredentialsOnBoot() { + synchronized (this) { + DevicePolicyData policyData = getUserData(UserHandle.USER_OWNER); + if (!policyData.doNotAskCredentialsOnBoot) { + policyData.doNotAskCredentialsOnBoot = true; + saveSettingsLocked(UserHandle.USER_OWNER); + } + } + } + + public boolean getDoNotAskCredentialsOnBoot() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null); + synchronized (this) { + DevicePolicyData policyData = getUserData(UserHandle.USER_OWNER); + return policyData.doNotAskCredentialsOnBoot; + } + } + public void setMaximumTimeToLock(ComponentName who, long timeMs) { if (!mHasFeature) { return; @@ -6017,24 +6055,41 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public void setOtaPolicy(ComponentName who, PersistableBundle policy) { + public void setSystemUpdatePolicy(ComponentName who, PersistableBundle policy) { synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); if (policy == null) { - mDeviceOwner.clearOtaPolicy(); + mDeviceOwner.clearSystemUpdatePolicy(); } else { - mDeviceOwner.setOtaPolicy(policy); + mDeviceOwner.setSystemUpdatePolicy(policy); } mDeviceOwner.writeOwnerFile(); } - mContext.sendBroadcastAsUser(new Intent(DevicePolicyManager.ACTION_OTA_POLICY_CHANGED), + mContext.sendBroadcastAsUser( + new Intent(DevicePolicyManager.ACTION_SYSTEM_UPDATE_POLICY_CHANGED), UserHandle.OWNER); } @Override - public PersistableBundle getOtaPolicy() { + public PersistableBundle getSystemUpdatePolicy() { synchronized (this) { - return mDeviceOwner.getOtaPolicy(); + return mDeviceOwner.getSystemUpdatePolicy(); + } + } + + /** + * Checks if the caller of the method is the device owner app or device initialization app. + * + * @param callerUid UID of the caller. + * @return true if the caller is the device owner app or device initializer. + */ + private boolean isCallerDeviceOwnerOrInitializer(int callerUid) { + String[] pkgs = mContext.getPackageManager().getPackagesForUid(callerUid); + for (String pkg : pkgs) { + if (isDeviceOwner(pkg) || isDeviceInitializer(pkg)) { + return true; + } } + return false; } } diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java index e9203a4..ab56493 100644 --- a/services/net/java/android/net/dhcp/DhcpClient.java +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -92,6 +92,7 @@ public class DhcpClient extends BaseDhcpStateMachine { private static final boolean DBG = true; private static final boolean STATE_DBG = false; private static final boolean MSG_DBG = false; + private static final boolean PACKET_DBG = true; // Timers and timeouts. private static final int SECONDS = 1000; @@ -329,6 +330,9 @@ public class DhcpClient extends BaseDhcpStateMachine { if (packet != null) { maybeLog("Received packet: " + packet); sendMessage(CMD_RECEIVED_PACKET, packet); + } else if (PACKET_DBG) { + Log.d(TAG, + "Can't parse packet" + HexDump.dumpHexString(mPacket, 0, length)); } } catch (IOException|ErrnoException e) { if (!stopped) { diff --git a/services/net/java/android/net/dhcp/DhcpDeclinePacket.java b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java index 9d985ac..4a22b65 100644 --- a/services/net/java/android/net/dhcp/DhcpDeclinePacket.java +++ b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java @@ -53,6 +53,9 @@ class DhcpDeclinePacket extends DhcpPacket { * Adds optional parameters to the DECLINE packet. */ void finishPacket(ByteBuffer buffer) { - // None needed + addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_DECLINE); + addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId()); + // RFC 2131 says we MUST NOT include our common client TLVs or the parameter request list. + addTlvEnd(buffer); } } diff --git a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java index a031080..ed0fdc6 100644 --- a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java +++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java @@ -52,6 +52,7 @@ class DhcpDiscoverPacket extends DhcpPacket { */ void finishPacket(ByteBuffer buffer) { addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_DISCOVER); + addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId()); addCommonClientTlvs(buffer); addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); addTlvEnd(buffer); diff --git a/services/net/java/android/net/dhcp/DhcpInformPacket.java b/services/net/java/android/net/dhcp/DhcpInformPacket.java index 8bc7cdd..2434fc9 100644 --- a/services/net/java/android/net/dhcp/DhcpInformPacket.java +++ b/services/net/java/android/net/dhcp/DhcpInformPacket.java @@ -53,12 +53,9 @@ class DhcpInformPacket extends DhcpPacket { * Adds additional parameters to the INFORM packet. */ void finishPacket(ByteBuffer buffer) { - byte[] clientId = new byte[7]; - - clientId[0] = CLIENT_ID_ETHER; - System.arraycopy(mClientMac, 0, clientId, 1, 6); - - addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_REQUEST); + addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_INFORM); + addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId()); + addCommonClientTlvs(buffer); addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); addTlvEnd(buffer); } diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index d41629d..a64ee6f 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -285,6 +285,16 @@ abstract class DhcpPacket { } /** + * Returns the client ID. This follows RFC 2132 and is based on the hardware address. + */ + public byte[] getClientId() { + byte[] clientId = new byte[mClientMac.length + 1]; + clientId[0] = CLIENT_ID_ETHER; + System.arraycopy(mClientMac, 0, clientId, 1, mClientMac.length); + return clientId; + } + + /** * Creates a new L3 packet (including IP header) containing the * DHCP udp packet. This method relies upon the delegated method * finishPacket() to insert the per-packet contents. diff --git a/services/net/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java index 42b7b0c..5d378b8 100644 --- a/services/net/java/android/net/dhcp/DhcpRequestPacket.java +++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java @@ -56,20 +56,14 @@ class DhcpRequestPacket extends DhcpPacket { * Adds the optional parameters to the client-generated REQUEST packet. */ void finishPacket(ByteBuffer buffer) { - byte[] clientId = new byte[7]; - - // assemble client identifier - clientId[0] = CLIENT_ID_ETHER; - System.arraycopy(mClientMac, 0, clientId, 1, 6); - addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_REQUEST); + addTlv(buffer, DHCP_CLIENT_IDENTIFIER, getClientId()); if (!INADDR_ANY.equals(mRequestedIp)) { addTlv(buffer, DHCP_REQUESTED_IP, mRequestedIp); } if (!INADDR_ANY.equals(mServerIdentifier)) { addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier); } - addTlv(buffer, DHCP_CLIENT_IDENTIFIER, clientId); addCommonClientTlvs(buffer); addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); addTlvEnd(buffer); |