diff options
Diffstat (limited to 'services')
39 files changed, 1726 insertions, 557 deletions
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index f9f6714..b33b10b 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -61,7 +61,7 @@ import java.util.HashMap; import java.util.Map; class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; - private static final boolean DBG = true; + private static final boolean DBG = false; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; @@ -227,21 +227,23 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } else if (Intent.ACTION_USER_SWITCHED.equals(action)) { + if (DBG) Log.d(TAG, "Bluetooth user switched"); mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_USER_SWITCHED, intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); } else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) { + if (DBG) Log.d(TAG, "Bluetooth boot completed"); synchronized(mReceiver) { if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { //Enable if (DBG) Log.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); } - } - - if (!isNameAndAddressSet()) { - // Sync the Bluetooth name and address from the Bluetooth Adapter - if (DBG) Log.d(TAG,"Retrieving Bluetooth Adapter name and address..."); - getNameAndAddress(); + if (!isNameAndAddressSet()) { + // Sync the Bluetooth name and address from the + // Bluetooth Adapter + if (DBG) Log.d(TAG, "Retrieving Bluetooth Adapter name and address..."); + getNameAndAddress(); + } } } } @@ -1099,7 +1101,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { boolean unbind = false; if (DBG) Log.d(TAG,"MESSAGE_SAVE_NAME_AND_ADDRESS"); synchronized(mConnection) { - if (!mEnable && mBluetooth != null) { + if (!mEnable && mBluetooth != null && !mConnection.isGetNameAddressOnly()) { try { mBluetooth.enable(); } catch (RemoteException e) { @@ -1107,7 +1109,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } - if (mBluetooth != null) waitForOnOff(true, false); + if (mBluetooth != null && !mConnection.isGetNameAddressOnly()) waitForOnOff(true, false); synchronized(mConnection) { if (mBluetooth != null) { String name = null; @@ -1137,7 +1139,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } - if (!mEnable) { + if (!mEnable && !mConnection.isGetNameAddressOnly()) { try { mBluetooth.disable(); } catch (RemoteException e) { @@ -1152,7 +1154,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mHandler.sendMessage(getMsg); } } - if (!mEnable && mBluetooth != null) waitForOnOff(false, true); + if (!mEnable && mBluetooth != null && !mConnection.isGetNameAddressOnly()) { + waitForOnOff(false, true); + } if (unbind) { unbindAndFinish(); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 98f0b45..25d4d5e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -326,7 +326,7 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * used to add a network request with a pending intent - * includes a NetworkRequestInfo + * obj = NetworkRequestInfo */ private static final int EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT = 26; @@ -356,6 +356,12 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30; + /** + * used to add a network listener with a pending intent + * obj = NetworkRequestInfo + */ + private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31; + /** Handler used for internal events. */ final private InternalHandler mHandler; /** Handler used for incoming {@link NetworkStateTracker} events. */ @@ -2068,15 +2074,6 @@ public class ConnectivityService extends IConnectivityManager.Stub log(nai.name() + " got DISCONNECTED, was satisfying " + nai.networkRequests.size()); } // A network agent has disconnected. - if (nai.created) { - // Tell netd to clean up the configuration for this network - // (routing rules, DNS, etc). - try { - mNetd.removeNetwork(nai.network.netId); - } catch (Exception e) { - loge("Exception removing network: " + e); - } - } // TODO - if we move the logic to the network agent (have them disconnect // because they lost all their requests or because their score isn't good) // then they would disconnect organically, report their new state and then @@ -2095,8 +2092,9 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkAgentInfos.remove(msg.replyTo); updateClat(null, nai.linkProperties, nai); synchronized (mNetworkForNetId) { + // Remove the NetworkAgent, but don't mark the netId as + // available until we've told netd to delete it below. mNetworkForNetId.remove(nai.network.netId); - mNetIdInUse.delete(nai.network.netId); } // Since we've lost the network, go through all the requests that // it was satisfying and see if any other factory can satisfy them. @@ -2138,9 +2136,28 @@ public class ConnectivityService extends IConnectivityManager.Stub rematchNetworkAndRequests(networkToActivate, NascentState.NOT_JUST_VALIDATED, ReapUnvalidatedNetworks.DONT_REAP); } + if (nai.created) { + // Tell netd to clean up the configuration for this network + // (routing rules, DNS, etc). + // This may be slow as it requires a lot of netd shelling out to ip and + // ip[6]tables to flush routes and remove the incoming packet mark rule, so do it + // after we've rematched networks with requests which should make a potential + // fallback network the default or requested a new network from the + // NetworkFactories, so network traffic isn't interrupted for an unnecessarily + // long time. + try { + mNetd.removeNetwork(nai.network.netId); + } catch (Exception e) { + loge("Exception removing network: " + e); + } + } + synchronized (mNetworkForNetId) { + mNetIdInUse.delete(nai.network.netId); + } + } else { + NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo); + if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name); } - NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(msg.replyTo); - if (DBG && nfi != null) log("unregisterNetworkFactory for " + nfi.name); } // If this method proves to be too slow then we can maintain a separate @@ -2185,7 +2202,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // Not setting bestNetwork here as a listening NetworkRequest may be // satisfied by multiple Networks. Instead the request is added to // each satisfying Network and notified about each. - network.addRequest(nri.request); + if (!network.addRequest(nri.request)) { + Slog.wtf(TAG, "BUG: " + network.name() + " already has " + nri.request); + } notifyNetworkCallback(network, nri); } else if (bestNetwork == null || bestNetwork.getCurrentScore() < network.getCurrentScore()) { @@ -2196,7 +2215,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (bestNetwork != null) { if (DBG) log("using " + bestNetwork.name()); unlinger(bestNetwork); - bestNetwork.addRequest(nri.request); + if (!bestNetwork.addRequest(nri.request)) { + Slog.wtf(TAG, "BUG: " + bestNetwork.name() + " already has " + nri.request); + } mNetworkForRequestId.put(nri.request.requestId, bestNetwork); notifyNetworkCallback(bestNetwork, nri); if (nri.request.legacyType != TYPE_NONE) { @@ -2480,7 +2501,8 @@ public class ConnectivityService extends IConnectivityManager.Stub handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj); break; } - case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: { + case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: + case EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT: { handleRegisterNetworkRequestWithIntent(msg); break; } @@ -3689,6 +3711,18 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation) { + checkNotNull(operation, "PendingIntent cannot be null."); + if (!hasWifiNetworkListenPermission(networkCapabilities)) { + enforceAccessPermission(); + } + + NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities( + networkCapabilities), TYPE_NONE, nextNetworkRequestId()); + if (DBG) log("pendingListenForNetwork for " + networkRequest + " to trigger " + operation); + NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation, + NetworkRequestInfo.LISTEN); + + mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri)); } @Override @@ -4197,6 +4231,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Find and migrate to this Network any NetworkRequests for // which this network is now the best. ArrayList<NetworkAgentInfo> affectedNetworks = new ArrayList<NetworkAgentInfo>(); + ArrayList<NetworkRequestInfo> addedRequests = new ArrayList<NetworkRequestInfo>(); if (VDBG) log(" network has: " + newNetwork.networkCapabilities); for (NetworkRequestInfo nri : mNetworkRequests.values()) { NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId); @@ -4215,7 +4250,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!nri.isRequest) { // This is not a request, it's a callback listener. // Add it to newNetwork regardless of score. - newNetwork.addRequest(nri.request); + if (newNetwork.addRequest(nri.request)) addedRequests.add(nri); continue; } @@ -4238,7 +4273,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } unlinger(newNetwork); mNetworkForRequestId.put(nri.request.requestId, newNetwork); - newNetwork.addRequest(nri.request); + if (!newNetwork.addRequest(nri.request)) { + Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request); + } + addedRequests.add(nri); keep = true; // Tell NetworkFactories about the new score, so they can stop // trying to connect if they know they cannot match it. @@ -4281,7 +4319,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // do this after the default net is switched, but // before LegacyTypeTracker sends legacy broadcasts - notifyNetworkCallbacks(newNetwork, ConnectivityManager.CALLBACK_AVAILABLE); + for (NetworkRequestInfo nri : addedRequests) notifyNetworkCallback(newNetwork, nri); if (isNewDefault) { // Maintain the illusion: since the legacy API only diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 8dd087a..dc203ff 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -45,6 +45,7 @@ import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.PowerManagerInternal; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -96,9 +97,6 @@ public class DeviceIdleController extends SystemService private static final String ACTION_STEP_IDLE_STATE = "com.android.server.device_idle.STEP_IDLE_STATE"; - private static final String ACTION_ENTER_INACTIVE_STATE = - "com.android.server.device_idle.ENTER_INACTIVE_STATE"; - private AlarmManager mAlarmManager; private IBatteryStats mBatteryStats; private PowerManagerInternal mLocalPowerManager; @@ -111,7 +109,7 @@ public class DeviceIdleController extends SystemService private Intent mIdleIntent; private Display mCurDisplay; private AnyMotionDetector mAnyMotionDetector; - private boolean mIdleDisabled; + private boolean mEnabled; private boolean mScreenOn; private boolean mCharging; private boolean mSigMotionActive; @@ -190,10 +188,6 @@ public class DeviceIdleController extends SystemService synchronized (DeviceIdleController.this) { stepIdleStateLocked(); } - } else if (ACTION_ENTER_INACTIVE_STATE.equals(intent.getAction())) { - synchronized (DeviceIdleController.this) { - enterInactiveStateLocked(); - } } } }; @@ -487,7 +481,7 @@ public class DeviceIdleController extends SystemService mLocalPowerManager.setDeviceIdleMode(true); try { mNetworkPolicyManager.setDeviceIdleMode(true); - mBatteryStats.noteDeviceIdleMode(true, false, false); + mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid()); } catch (RemoteException e) { } getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); @@ -496,18 +490,19 @@ public class DeviceIdleController extends SystemService mLocalPowerManager.setDeviceIdleMode(false); try { mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, false, false); + mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid()); } catch (RemoteException e) { } getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); } break; case MSG_REPORT_ACTIVE: { - boolean fromMotion = msg.arg1 != 0; + String activeReason = (String)msg.obj; + int activeUid = msg.arg1; boolean needBroadcast = msg.arg2 != 0; mLocalPowerManager.setDeviceIdleMode(false); try { mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, !fromMotion, fromMotion); + mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid); } catch (RemoteException e) { } if (needBroadcast) { @@ -578,6 +573,12 @@ public class DeviceIdleController extends SystemService } } + @Override public void exitIdle(String reason) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + exitIdleInternal(reason); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { DeviceIdleController.this.dump(fd, pw, args); } @@ -604,6 +605,8 @@ public class DeviceIdleController extends SystemService final PackageManager pm = getContext().getPackageManager(); synchronized (this) { + mEnabled = getContext().getResources().getBoolean( + com.android.internal.R.bool.config_enableAutoPowerModes); SystemConfig sysConfig = SystemConfig.getInstance(); ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); for (int i=0; i<allowPower.size(); i++) { @@ -818,6 +821,12 @@ public class DeviceIdleController extends SystemService } } + public void exitIdleInternal(String reason) { + synchronized (this) { + becomeActiveLocked(reason, Binder.getCallingUid()); + } + } + void updateDisplayLocked() { mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); // We consider any situation where the display is showing something to be it on, @@ -830,7 +839,7 @@ public class DeviceIdleController extends SystemService becomeInactiveIfAppropriateLocked(); } else if (screenOn) { mScreenOn = true; - becomeActiveLocked("screen"); + becomeActiveLocked("screen", Process.myUid()); } } @@ -841,21 +850,21 @@ public class DeviceIdleController extends SystemService becomeInactiveIfAppropriateLocked(); } else if (charging) { mCharging = charging; - becomeActiveLocked("charging"); + becomeActiveLocked("charging", Process.myUid()); } } - void scheduleReportActiveLocked(boolean fromMotion) { - Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, fromMotion ? 1 : 0, - mState == STATE_IDLE ? 1 : 0); + void scheduleReportActiveLocked(String activeReason, int activeUid) { + Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, + mState == STATE_IDLE ? 1 : 0, activeReason); mHandler.sendMessage(msg); } - void becomeActiveLocked(String reason) { - if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + reason); + void becomeActiveLocked(String activeReason, int activeUid) { + if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason); if (mState != STATE_ACTIVE) { - EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason); - scheduleReportActiveLocked(false); + EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason); + scheduleReportActiveLocked(activeReason, activeUid); mState = STATE_ACTIVE; mInactiveTimeout = mConstants.INACTIVE_TIMEOUT; mNextIdlePendingDelay = 0; @@ -867,7 +876,7 @@ public class DeviceIdleController extends SystemService void becomeInactiveIfAppropriateLocked() { if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()"); - if (!mScreenOn && !mCharging && !mIdleDisabled && mState == STATE_ACTIVE) { + if (!mScreenOn && !mCharging && mEnabled && mState == STATE_ACTIVE) { // Screen has turned off; we are now going to become inactive and start // waiting to see if we will ultimately go idle. mState = STATE_INACTIVE; @@ -896,7 +905,7 @@ public class DeviceIdleController extends SystemService if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { // Whoops, there is an upcoming alarm. We don't actually want to go idle. if (mState != STATE_ACTIVE) { - becomeActiveLocked("alarm"); + becomeActiveLocked("alarm", Process.myUid()); } return; } @@ -954,7 +963,7 @@ public class DeviceIdleController extends SystemService // state to wait again for no motion. Note that we only monitor for significant // motion after moving out of the inactive state, so no need to worry about that. if (mState != STATE_ACTIVE) { - scheduleReportActiveLocked(true); + scheduleReportActiveLocked("motion", Process.myUid()); mState = STATE_ACTIVE; mInactiveTimeout = mConstants.MOTION_INACTIVE_TIMEOUT; EventLogTags.writeDeviceIdle(mState, "motion"); @@ -1202,8 +1211,12 @@ public class DeviceIdleController extends SystemService pw.println(" Completely disable device idle mode."); pw.println(" enable"); pw.println(" Re-enable device idle mode after it had previously been disabled."); - pw.println(" whitelist"); + pw.println(" enabled"); + pw.println(" Print 1 if device idle mode is currently enabled, else 0."); + pw.println(" whitelist [package ...]"); pw.println(" Add (prefix with +) or remove (prefix with -) packages."); + pw.println(" tempwhitelist [package ..]"); + pw.println(" Temporarily place packages in whitelist for 10 seconds."); } void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -1238,22 +1251,27 @@ public class DeviceIdleController extends SystemService return; } else if ("disable".equals(arg)) { synchronized (this) { - if (!mIdleDisabled) { - mIdleDisabled = true; - becomeActiveLocked("disabled"); + if (mEnabled) { + mEnabled = false; + becomeActiveLocked("disabled", Process.myUid()); pw.println("Idle mode disabled"); } } return; } else if ("enable".equals(arg)) { synchronized (this) { - if (mIdleDisabled) { - mIdleDisabled = false; + if (!mEnabled) { + mEnabled = true; becomeInactiveIfAppropriateLocked(); pw.println("Idle mode enabled"); } } return; + } else if ("enabled".equals(arg)) { + synchronized (this) { + pw.println(mEnabled ? "1" : " 0"); + } + return; } else if ("whitelist".equals(arg)) { i++; while (i < args.length) { @@ -1350,9 +1368,9 @@ public class DeviceIdleController extends SystemService } } + pw.print(" mEnabled="); pw.println(mEnabled); pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); pw.print(" mCurDisplay="); pw.println(mCurDisplay); - pw.print(" mIdleDisabled="); pw.println(mIdleDisabled); pw.print(" mScreenOn="); pw.println(mScreenOn); pw.print(" mCharging="); pw.println(mCharging); pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 2f153a0..dbe8781 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -16,6 +16,7 @@ package com.android.server; import android.annotation.NonNull; +import android.content.pm.PackageManagerInternal; import com.android.internal.content.PackageMonitor; import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController; import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem; @@ -31,6 +32,7 @@ import com.android.internal.view.IInputMethodClient; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.InputBindResult; +import com.android.server.pm.UserManagerService; import com.android.server.statusbar.StatusBarManagerService; import com.android.server.wm.WindowManagerService; @@ -859,6 +861,38 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // mSettings should be created before buildInputMethodListLocked mSettings = new InputMethodSettings( mRes, context.getContentResolver(), mMethodMap, mMethodList, userId); + + // Let the package manager query which are the default imes + // as they get certain permissions granted by default. + PackageManagerInternal packageManagerInternal = LocalServices.getService( + PackageManagerInternal.class); + packageManagerInternal.setImePackagesProvider( + new PackageManagerInternal.PackagesProvider() { + @Override + public String[] getPackages(int userId) { + synchronized (mMethodMap) { + final int currentUserId = mSettings.getCurrentUserId(); + // TODO: We are switching the current user id in the settings + // object to query it and then revert the user id. Ideally, we + // should call a API in settings with the user id as an argument. + mSettings.setCurrentUserId(userId); + List<InputMethodInfo> imes = mSettings + .getEnabledInputMethodListLocked(); + String[] packageNames = null; + if (imes != null) { + final int imeCount = imes.size(); + packageNames = new String[imeCount]; + for (int i = 0; i < imeCount; i++) { + InputMethodInfo ime = imes.get(i); + packageNames[i] = ime.getPackageName(); + } + } + mSettings.setCurrentUserId(currentUserId); + return packageNames; + } + } + }); + updateCurrentProfileIds(); mFileManager = new InputMethodFileManager(mMethodMap, userId); synchronized (mMethodMap) { @@ -1009,8 +1043,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub resetAllInternalStateLocked(false /* updateOnlyWhenLocaleChanged */, initialUserSwitch /* needsToResetDefaultIme */); if (initialUserSwitch) { - InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(), - mSettings.getEnabledInputMethodListLocked()); + InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager, + mSettings.getEnabledInputMethodListLocked(), newUserId, + mContext.getBasePackageName()); } if (DEBUG) Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId @@ -1067,9 +1102,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (!mImeSelectedOnBoot) { Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here."); resetStateIfCurrentLocaleChangedLocked(); - InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed( - mContext.getPackageManager(), - mSettings.getEnabledInputMethodListLocked()); + InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager, + mSettings.getEnabledInputMethodListLocked(), + mSettings.getCurrentUserId(), mContext.getBasePackageName()); } mLastSystemLocale = mRes.getConfiguration().locale; try { diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 743aafb..61bedf5 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -16,6 +16,7 @@ package com.android.server; +import android.content.pm.PackageManagerInternal; import com.android.internal.content.PackageMonitor; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ProviderRequest; @@ -218,6 +219,19 @@ public class LocationManagerService extends ILocationManager.Stub { mContext = context; mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); + // Let the package manager query which are the default location + // providers as they get certain permissions granted by default. + PackageManagerInternal packageManagerInternal = LocalServices.getService( + PackageManagerInternal.class); + packageManagerInternal.setLocationPackagesProvider( + new PackageManagerInternal.PackagesProvider() { + @Override + public String[] getPackages(int userId) { + return mContext.getResources().getStringArray( + com.android.internal.R.array.config_locationProviderPackageNames); + } + }); + if (D) Log.d(TAG, "Constructed"); // most startup is deferred until systemReady() diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c4f460e..0301638 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -676,9 +676,9 @@ public final class ActivityManagerService extends ActivityManagerNative final SparseArray<UidRecord> mActiveUids = new SparseArray<>(); /** - * Which uses have been started, so are allowed to run code. + * Which users have been started, so are allowed to run code. */ - final SparseArray<UserStartedState> mStartedUsers = new SparseArray<>(); + final SparseArray<UserState> mStartedUsers = new SparseArray<>(); /** * LRU list of history of current users. Most recently current is at the end. @@ -1781,15 +1781,15 @@ public final class ActivityManagerService extends ActivityManagerNative break; } case REPORT_USER_SWITCH_MSG: { - dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); + dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); break; } case CONTINUE_USER_SWITCH_MSG: { - continueUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); + continueUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); break; } case USER_SWITCH_TIMEOUT_MSG: { - timeoutUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2); + timeoutUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2); break; } case IMMERSIVE_MODE_LOCK_MSG: { @@ -2309,7 +2309,7 @@ public final class ActivityManagerService extends ActivityManagerNative mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml")); // User 0 is the first and only user that runs at boot. - mStartedUsers.put(UserHandle.USER_OWNER, new UserStartedState(UserHandle.OWNER, true)); + mStartedUsers.put(UserHandle.USER_OWNER, new UserState(UserHandle.OWNER, true)); mUserLru.add(UserHandle.USER_OWNER); updateStartedUserArrayLocked(); @@ -2488,10 +2488,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized(bstats) { synchronized(mPidsSelfLocked) { if (haveNewCpuStats) { - final int perc = bstats.startAddingCpuLocked(); - if (perc >= 0) { - int remainUTime = 0; - int remainSTime = 0; + if (bstats.startAddingCpuLocked()) { int totalUTime = 0; int totalSTime = 0; final int N = mProcessCpuTracker.countStats(); @@ -2501,10 +2498,6 @@ public final class ActivityManagerService extends ActivityManagerNative continue; } ProcessRecord pr = mPidsSelfLocked.get(st.pid); - int otherUTime = (st.rel_utime*perc)/100; - int otherSTime = (st.rel_stime*perc)/100; - remainUTime += otherUTime; - remainSTime += otherSTime; totalUTime += st.rel_utime; totalSTime += st.rel_stime; if (pr != null) { @@ -2513,8 +2506,7 @@ public final class ActivityManagerService extends ActivityManagerNative pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked( pr.info.uid, pr.processName); } - ps.addCpuTimeLocked(st.rel_utime - otherUTime, - st.rel_stime - otherSTime); + ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); pr.curCpuTime += st.rel_utime + st.rel_stime; } else { BatteryStatsImpl.Uid.Proc ps = st.batteryStats; @@ -2522,8 +2514,7 @@ public final class ActivityManagerService extends ActivityManagerNative st.batteryStats = ps = bstats.getProcessStatsLocked( bstats.mapUid(st.uid), st.name); } - ps.addCpuTimeLocked(st.rel_utime - otherUTime, - st.rel_stime - otherSTime); + ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); } } final int userTime = mProcessCpuTracker.getLastUserTime(); @@ -2532,9 +2523,8 @@ public final class ActivityManagerService extends ActivityManagerNative final int irqTime = mProcessCpuTracker.getLastIrqTime(); final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); final int idleTime = mProcessCpuTracker.getLastIdleTime(); - bstats.finishAddingCpuLocked(perc, remainUTime, - remainSTime, totalUTime, totalSTime, userTime, systemTime, - iowaitTime, irqTime, softIrqTime, idleTime); + bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime, + systemTime, iowaitTime, irqTime, softIrqTime, idleTime); } } } @@ -2754,13 +2744,19 @@ public final class ActivityManagerService extends ActivityManagerNative return index; } + private static void killProcessGroup(int uid, int pid) { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "killProcessGroup"); + Process.killProcessGroup(uid, pid); + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + } + final void removeLruProcessLocked(ProcessRecord app) { int lrui = mLruProcesses.lastIndexOf(app); if (lrui >= 0) { if (!app.killed) { Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app); Process.killProcessQuiet(app.pid); - Process.killProcessGroup(app.info.uid, app.pid); + killProcessGroup(app.info.uid, app.pid); } if (lrui <= mLruProcessActivityStart) { mLruProcessActivityStart--; @@ -3125,7 +3121,7 @@ public final class ActivityManagerService extends ActivityManagerNative // clean it up now. if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app); checkTime(startTime, "startProcess: bad proc running, killing"); - Process.killProcessGroup(app.info.uid, app.pid); + killProcessGroup(app.info.uid, app.pid); handleAppDiedLocked(app, true, true); checkTime(startTime, "startProcess: done killing old proc"); } @@ -3274,9 +3270,9 @@ public final class ActivityManagerService extends ActivityManagerNative debugFlags |= Zygote.DEBUG_ENABLE_JIT; } } - String genCFIDebugProperty = SystemProperties.get("debug.gencfi"); - if ("true".equals(genCFIDebugProperty)) { - debugFlags |= Zygote.DEBUG_GENERATE_CFI; + String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info"); + if ("true".equals(genDebugInfoProperty)) { + debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; } if ("1".equals(SystemProperties.get("debug.jni.logging"))) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; @@ -3589,6 +3585,8 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public int getPackageProcessState(String packageName) { + enforceCallingPermission(android.Manifest.permission.GET_PACKAGE_IMPORTANCE, + "getPackageProcessState"); int procState = ActivityManager.PROCESS_STATE_NONEXISTENT; synchronized (this) { for (int i=mLruProcesses.size()-1; i>=0; i--) { @@ -4611,7 +4609,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (!fromBinderDied) { Process.killProcessQuiet(pid); } - Process.killProcessGroup(app.info.uid, pid); + killProcessGroup(app.info.uid, pid); app.killed = true; } @@ -5932,7 +5930,7 @@ public final class ActivityManagerService extends ActivityManagerNative EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid); if (pid > 0 && pid != MY_PID) { Process.killProcessQuiet(pid); - //TODO: Process.killProcessGroup(app.info.uid, pid); + //TODO: killProcessGroup(app.info.uid, pid); } else { try { thread.scheduleExit(); @@ -6313,9 +6311,9 @@ public final class ActivityManagerService extends ActivityManagerNative SystemProperties.set("dev.bootcomplete", "1"); } for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); - if (uss.mState == UserStartedState.STATE_BOOTING) { - uss.mState = UserStartedState.STATE_RUNNING; + UserState uss = mStartedUsers.valueAt(i); + if (uss.mState == UserState.STATE_BOOTING) { + uss.mState = UserState.STATE_RUNNING; final int userId = mStartedUsers.keyAt(i); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); @@ -8278,7 +8276,7 @@ public final class ActivityManagerService extends ActivityManagerNative try { if (AppGlobals.getPackageManager().isUidPrivileged(callingUid)) { allowed = true; - Slog.w(TAG, caller + ": caller " + callingUid + if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid + " is using old GET_TASKS but privileged; allowing"); } } catch (RemoteException e) { @@ -8286,7 +8284,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (!allowed) { - Slog.w(TAG, caller + ": caller " + callingUid + if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid + " does not hold REAL_GET_TASKS; limiting output"); } return allowed; @@ -9442,6 +9440,7 @@ public final class ActivityManagerService extends ActivityManagerNative } checkTime(startTime, "getContentProviderImpl: before updateOomAdj"); boolean success = updateOomAdjLocked(cpr.proc); + maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name); checkTime(startTime, "getContentProviderImpl: after updateOomAdj"); if (DEBUG_PROVIDER) Slog.i(TAG_PROVIDER, "Adjust success: " + success); // NOTE: there is still a race here where a signal could be @@ -9831,6 +9830,8 @@ public final class ActivityManagerService extends ActivityManagerNative dst.notifyAll(); } updateOomAdjLocked(r); + maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, + src.info.authority); } } @@ -12397,7 +12398,7 @@ public final class ActivityManagerService extends ActivityManagerNative } else { // Huh. Process.killProcess(pid); - Process.killProcessGroup(uid, pid); + killProcessGroup(uid, pid); } } return; @@ -13343,7 +13344,7 @@ public final class ActivityManagerService extends ActivityManagerNative needSep = false; pw.println(" mStartedUsers:"); for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); + UserState uss = mStartedUsers.valueAt(i); pw.print(" User #"); pw.print(uss.mHandle.getIdentifier()); pw.print(": "); uss.dump("", pw); } @@ -18615,6 +18616,22 @@ public final class ActivityManagerService extends ActivityManagerNative uidRec.pendingChange.processState = uidRec.setProcState; } + private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName, + String authority) { + if (app == null) return; + if (app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { + UserState userState = mStartedUsers.get(app.userId); + if (userState == null) return; + final long now = SystemClock.elapsedRealtime(); + Long lastReported = userState.mProviderLastReportedFg.get(authority); + if (lastReported == null || lastReported < now - 60 * 1000L) { + mUsageStatsService.reportContentProviderUsage( + authority, providerPkgName, app.userId); + userState.mProviderLastReportedFg.put(authority, now); + } + } + } + private void maybeUpdateUsageStatsLocked(ProcessRecord app) { if (DEBUG_USAGE_STATS) { Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList()) @@ -19602,7 +19619,7 @@ public final class ActivityManagerService extends ActivityManagerNative // If the user we are switching to is not currently started, then // we need to start it now. if (mStartedUsers.get(userId) == null) { - mStartedUsers.put(userId, new UserStartedState(new UserHandle(userId), false)); + mStartedUsers.put(userId, new UserState(new UserHandle(userId), false)); updateStartedUserArrayLocked(); needStart = true; } @@ -19627,26 +19644,26 @@ public final class ActivityManagerService extends ActivityManagerNative mUserLru.add(currentUserIdInt); } - final UserStartedState uss = mStartedUsers.get(userId); + final UserState uss = mStartedUsers.get(userId); // Make sure user is in the started state. If it is currently // stopping, we need to knock that off. - if (uss.mState == UserStartedState.STATE_STOPPING) { + if (uss.mState == UserState.STATE_STOPPING) { // If we are stopping, we haven't sent ACTION_SHUTDOWN, // so we can just fairly silently bring the user back from // the almost-dead. - uss.mState = UserStartedState.STATE_RUNNING; + uss.mState = UserState.STATE_RUNNING; updateStartedUserArrayLocked(); needStart = true; - } else if (uss.mState == UserStartedState.STATE_SHUTDOWN) { + } else if (uss.mState == UserState.STATE_SHUTDOWN) { // This means ACTION_SHUTDOWN has been sent, so we will // need to treat this as a new boot of the user. - uss.mState = UserStartedState.STATE_BOOTING; + uss.mState = UserState.STATE_BOOTING; updateStartedUserArrayLocked(); needStart = true; } - if (uss.mState == UserStartedState.STATE_BOOTING) { + if (uss.mState == UserState.STATE_BOOTING) { // Booting up a new user, need to tell system services about it. // Note that this is on the same handler as scheduling of broadcasts, // which is important because it needs to go first. @@ -19784,7 +19801,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void dispatchUserSwitch(final UserStartedState uss, final int oldUserId, + void dispatchUserSwitch(final UserState uss, final int oldUserId, final int newUserId) { final int N = mUserSwitchObservers.beginBroadcast(); if (N > 0) { @@ -19821,21 +19838,21 @@ public final class ActivityManagerService extends ActivityManagerNative mUserSwitchObservers.finishBroadcast(); } - void timeoutUserSwitch(UserStartedState uss, int oldUserId, int newUserId) { + void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) { synchronized (this) { Slog.w(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId); sendContinueUserSwitchLocked(uss, oldUserId, newUserId); } } - void sendContinueUserSwitchLocked(UserStartedState uss, int oldUserId, int newUserId) { + void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) { mCurUserSwitchCallback = null; mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG); mHandler.sendMessage(mHandler.obtainMessage(CONTINUE_USER_SWITCH_MSG, oldUserId, newUserId, uss)); } - void onUserInitialized(UserStartedState uss, boolean foreground, int oldUserId, int newUserId) { + void onUserInitialized(UserState uss, boolean foreground, int oldUserId, int newUserId) { synchronized (this) { if (foreground) { moveUserToForeground(uss, oldUserId, newUserId); @@ -19845,7 +19862,7 @@ public final class ActivityManagerService extends ActivityManagerNative completeSwitchAndInitalize(uss, newUserId, true, false); } - void moveUserToForeground(UserStartedState uss, int oldUserId, int newUserId) { + void moveUserToForeground(UserState uss, int oldUserId, int newUserId) { boolean homeInFront = mStackSupervisor.switchUserLocked(newUserId, uss); if (homeInFront) { startHomeActivityLocked(newUserId, "moveUserToFroreground"); @@ -19857,11 +19874,11 @@ public final class ActivityManagerService extends ActivityManagerNative sendUserSwitchBroadcastsLocked(oldUserId, newUserId); } - void continueUserSwitch(UserStartedState uss, int oldUserId, int newUserId) { + void continueUserSwitch(UserState uss, int oldUserId, int newUserId) { completeSwitchAndInitalize(uss, newUserId, false, true); } - void completeSwitchAndInitalize(UserStartedState uss, int newUserId, + void completeSwitchAndInitalize(UserState uss, int newUserId, boolean clearInitializing, boolean clearSwitching) { boolean unfrozen = false; synchronized (this) { @@ -19898,10 +19915,10 @@ public final class ActivityManagerService extends ActivityManagerNative final int num = mUserLru.size(); for (int i = 0; i < num; i++) { Integer oldUserId = mUserLru.get(i); - UserStartedState oldUss = mStartedUsers.get(oldUserId); + UserState oldUss = mStartedUsers.get(oldUserId); if (oldUserId == UserHandle.USER_OWNER || oldUserId == mCurrentUserId - || oldUss.mState == UserStartedState.STATE_STOPPING - || oldUss.mState == UserStartedState.STATE_SHUTDOWN) { + || oldUss.mState == UserState.STATE_STOPPING + || oldUss.mState == UserState.STATE_SHUTDOWN) { continue; } UserInfo userInfo = mUserManager.getUserInfo(oldUserId); @@ -19942,11 +19959,11 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void finishUserBoot(UserStartedState uss) { + void finishUserBoot(UserState uss) { synchronized (this) { - if (uss.mState == UserStartedState.STATE_BOOTING + if (uss.mState == UserState.STATE_BOOTING && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) { - uss.mState = UserStartedState.STATE_RUNNING; + uss.mState = UserState.STATE_RUNNING; final int userId = uss.mHandle.getIdentifier(); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); @@ -19959,7 +19976,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - void finishUserSwitch(UserStartedState uss) { + void finishUserSwitch(UserState uss) { synchronized (this) { finishUserBoot(uss); @@ -19969,15 +19986,15 @@ public final class ActivityManagerService extends ActivityManagerNative int i = 0; while (num > MAX_RUNNING_USERS && i < mUserLru.size()) { Integer oldUserId = mUserLru.get(i); - UserStartedState oldUss = mStartedUsers.get(oldUserId); + UserState oldUss = mStartedUsers.get(oldUserId); if (oldUss == null) { // Shouldn't happen, but be sane if it does. mUserLru.remove(i); num--; continue; } - if (oldUss.mState == UserStartedState.STATE_STOPPING - || oldUss.mState == UserStartedState.STATE_SHUTDOWN) { + if (oldUss.mState == UserState.STATE_STOPPING + || oldUss.mState == UserState.STATE_SHUTDOWN) { // This user is already stopping, doesn't count. num--; i++; @@ -20022,7 +20039,7 @@ public final class ActivityManagerService extends ActivityManagerNative return ActivityManager.USER_OP_IS_CURRENT; } - final UserStartedState uss = mStartedUsers.get(userId); + final UserState uss = mStartedUsers.get(userId); if (uss == null) { // User is not started, nothing to do... but we do need to // callback if requested. @@ -20044,9 +20061,9 @@ public final class ActivityManagerService extends ActivityManagerNative uss.mStopCallbacks.add(callback); } - if (uss.mState != UserStartedState.STATE_STOPPING - && uss.mState != UserStartedState.STATE_SHUTDOWN) { - uss.mState = UserStartedState.STATE_STOPPING; + if (uss.mState != UserState.STATE_STOPPING + && uss.mState != UserState.STATE_SHUTDOWN) { + uss.mState = UserState.STATE_STOPPING; updateStartedUserArrayLocked(); long ident = Binder.clearCallingIdentity(); @@ -20074,11 +20091,11 @@ public final class ActivityManagerService extends ActivityManagerNative Bundle extras, boolean ordered, boolean sticky, int sendingUser) { // On to the next. synchronized (ActivityManagerService.this) { - if (uss.mState != UserStartedState.STATE_STOPPING) { + if (uss.mState != UserState.STATE_STOPPING) { // Whoops, we are being started back up. Abort, abort! return; } - uss.mState = UserStartedState.STATE_SHUTDOWN; + uss.mState = UserState.STATE_SHUTDOWN; } mBatteryStatsService.noteEvent( BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH, @@ -20102,7 +20119,7 @@ public final class ActivityManagerService extends ActivityManagerNative return ActivityManager.USER_OP_SUCCESS; } - void finishUserStop(UserStartedState uss) { + void finishUserStop(UserState uss) { final int userId = uss.mHandle.getIdentifier(); boolean stopped; ArrayList<IStopUserCallback> callbacks; @@ -20110,7 +20127,7 @@ public final class ActivityManagerService extends ActivityManagerNative callbacks = new ArrayList<IStopUserCallback>(uss.mStopCallbacks); if (mStartedUsers.get(userId) != uss) { stopped = false; - } else if (uss.mState != UserStartedState.STATE_SHUTDOWN) { + } else if (uss.mState != UserState.STATE_SHUTDOWN) { stopped = false; } else { stopped = true; @@ -20184,15 +20201,15 @@ public final class ActivityManagerService extends ActivityManagerNative } boolean isUserRunningLocked(int userId, boolean orStopped) { - UserStartedState state = mStartedUsers.get(userId); + UserState state = mStartedUsers.get(userId); if (state == null) { return false; } if (orStopped) { return true; } - return state.mState != UserStartedState.STATE_STOPPING - && state.mState != UserStartedState.STATE_SHUTDOWN; + return state.mState != UserState.STATE_STOPPING + && state.mState != UserState.STATE_SHUTDOWN; } @Override @@ -20214,19 +20231,19 @@ public final class ActivityManagerService extends ActivityManagerNative private void updateStartedUserArrayLocked() { int num = 0; for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); + UserState uss = mStartedUsers.valueAt(i); // This list does not include stopping users. - if (uss.mState != UserStartedState.STATE_STOPPING - && uss.mState != UserStartedState.STATE_SHUTDOWN) { + if (uss.mState != UserState.STATE_STOPPING + && uss.mState != UserState.STATE_SHUTDOWN) { num++; } } mStartedUserArray = new int[num]; num = 0; for (int i=0; i<mStartedUsers.size(); i++) { - UserStartedState uss = mStartedUsers.valueAt(i); - if (uss.mState != UserStartedState.STATE_STOPPING - && uss.mState != UserStartedState.STATE_SHUTDOWN) { + UserState uss = mStartedUsers.valueAt(i); + if (uss.mState != UserState.STATE_STOPPING + && uss.mState != UserState.STATE_SHUTDOWN) { mStartedUserArray[num] = mStartedUsers.keyAt(i); num++; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 9e33f2a..f967aef 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -233,10 +233,10 @@ public final class ActivityStackSupervisor implements DisplayListener { final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<>(); /** Used on user changes */ - final ArrayList<UserStartedState> mStartingUsers = new ArrayList<>(); + final ArrayList<UserState> mStartingUsers = new ArrayList<>(); /** Used to queue up any background users being started */ - final ArrayList<UserStartedState> mStartingBackgroundUsers = new ArrayList<>(); + final ArrayList<UserState> mStartingBackgroundUsers = new ArrayList<>(); /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity * is being brought in front of us. */ @@ -883,8 +883,18 @@ public final class ActivityStackSupervisor implements DisplayListener { void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) { moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason); - startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, - 0, 0, 0, null, false, null, null, null); + startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo, + null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */, + null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */, + null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */, + 0 /* startFlags */, null /* options */, false /* componentSpecified */, + null /* outActivity */, null /* container */, null /* inTask */); + if (inResumeTopActivity) { + // If we are in resume section already, home activity will be initialized, but not + // resumed (to avoid recursive resume) and will stay that way until something pokes it + // again. We need to schedule another resume. + scheduleResumeTopActivities(); + } } final int startActivityMayWait(IApplicationThread caller, int callingUid, @@ -1915,7 +1925,12 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityRecord intentActivity = !launchSingleInstance ? findTaskLocked(r) : findActivityLocked(intent, r.info); if (intentActivity != null) { - if (isLockTaskModeViolation(intentActivity.task)) { + // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused + // but still needs to be a lock task mode violation since the task gets + // cleared out and the device would otherwise leave the locked task. + if (isLockTaskModeViolation(intentActivity.task, + (launchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) + == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { showLockTaskToast(); Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION; @@ -2371,7 +2386,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ArrayList<ActivityRecord> stops = null; ArrayList<ActivityRecord> finishes = null; - ArrayList<UserStartedState> startingUsers = null; + ArrayList<UserState> startingUsers = null; int NS = 0; int NF = 0; boolean booting = false; @@ -2468,7 +2483,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } // Complete starting up of background users if (mStartingBackgroundUsers.size() > 0) { - startingUsers = new ArrayList<UserStartedState>(mStartingBackgroundUsers); + startingUsers = new ArrayList<UserState>(mStartingBackgroundUsers); mStartingBackgroundUsers.clear(); for (int i = 0; i < startingUsers.size(); i++) { mService.finishUserBoot(startingUsers.get(i)); @@ -3230,7 +3245,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - boolean switchUserLocked(int userId, UserStartedState uss) { + boolean switchUserLocked(int userId, UserState uss) { mUserStackInFront.put(mCurrentUser, mFocusedStack.getStackId()); final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID); mCurrentUser = userId; @@ -3271,7 +3286,7 @@ public final class ActivityStackSupervisor implements DisplayListener { * @param userId The user being started in the background * @param uss The state object for the user. */ - public void startBackgroundUserLocked(int userId, UserStartedState uss) { + public void startBackgroundUserLocked(int userId, UserState uss) { mStartingBackgroundUsers.add(uss); } @@ -3780,7 +3795,11 @@ public final class ActivityStackSupervisor implements DisplayListener { } boolean isLockTaskModeViolation(TaskRecord task) { - if (getLockedTaskLocked() == task) { + return isLockTaskModeViolation(task, false); + } + + boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) { + if (getLockedTaskLocked() == task && !isNewClearTask) { return false; } final int lockTaskAuth = task.mLockTaskAuth; diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index c973386..3854e51 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -42,6 +42,7 @@ import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.util.Slog; +import android.util.TimeUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; @@ -64,16 +65,22 @@ public final class BatteryStatsService extends IBatteryStats.Stub implements PowerManagerInternal.LowPowerModeListener { static final String TAG = "BatteryStatsService"; - private boolean mFirstExternalStatsUpdate = true; static IBatteryStats sService; final BatteryStatsImpl mStats; final BatteryStatsHandler mHandler; Context mContext; PowerManagerInternal mPowerManagerInternal; + final int UPDATE_CPU = 0x01; + final int UPDATE_WIFI = 0x02; + final int UPDATE_RADIO = 0x04; + final int UPDATE_BT = 0x08; + final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT; + class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync { public static final int MSG_SYNC_EXTERNAL_STATS = 1; public static final int MSG_WRITE_TO_DISK = 2; + private int mUpdateFlags = 0; public BatteryStatsHandler(Looper looper) { super(looper); @@ -83,11 +90,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void handleMessage(Message msg) { switch (msg.what) { case MSG_SYNC_EXTERNAL_STATS: - updateExternalStats((String)msg.obj, false); + final int updateFlags; + synchronized (this) { + removeMessages(MSG_SYNC_EXTERNAL_STATS); + updateFlags = mUpdateFlags; + mUpdateFlags = 0; + } + updateExternalStats((String)msg.obj, updateFlags); break; case MSG_WRITE_TO_DISK: - updateExternalStats("write", true); + updateExternalStats("write", UPDATE_ALL); synchronized (mStats) { mStats.writeAsyncLocked(); } @@ -97,9 +110,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void scheduleSync(String reason) { - if (!hasMessages(MSG_SYNC_EXTERNAL_STATS)) { - Message msg = Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason); - sendMessage(msg); + scheduleSyncImpl(reason, UPDATE_ALL); + } + + @Override + public void scheduleWifiSync(String reason) { + scheduleSyncImpl(reason, UPDATE_WIFI); + } + + private void scheduleSyncImpl(String reason, int updateFlags) { + synchronized (this) { + if (mUpdateFlags == 0) { + sendMessage(Message.obtain(this, MSG_SYNC_EXTERNAL_STATS, reason)); + } + mUpdateFlags |= updateFlags; } } } @@ -137,7 +161,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void shutdown() { Slog.w("BatteryStats", "Writing battery stats before shutdown..."); - updateExternalStats("shutdown", true); + updateExternalStats("shutdown", UPDATE_ALL); synchronized (mStats) { mStats.shutdownLocked(); } @@ -237,7 +261,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub //Slog.i("foo", "SENDING BATTERY INFO:"); //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); Parcel out = Parcel.obtain(); - updateExternalStats("get-stats", true); + updateExternalStats("get-stats", UPDATE_ALL); synchronized (mStats) { mStats.writeToParcel(out, 0); } @@ -252,7 +276,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub //Slog.i("foo", "SENDING BATTERY INFO:"); //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); Parcel out = Parcel.obtain(); - updateExternalStats("get-stats", true); + updateExternalStats("get-stats", UPDATE_ALL); synchronized (mStats) { mStats.writeToParcel(out, 0); } @@ -603,8 +627,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub // There was a change in WiFi power state. // Collect data now for the past activity. - mHandler.scheduleSync("wifi-data"); synchronized (mStats) { + if (mStats.isOnBattery()) { + mHandler.scheduleWifiSync("wifi-data"); + } mStats.noteWifiRadioPowerState(powerState, tsNanos); } } @@ -767,10 +793,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub } @Override - public void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion) { + public void noteDeviceIdleMode(boolean enabled, String activeReason, int activeUid) { enforceCallingPermission(); synchronized (mStats) { - mStats.noteDeviceIdleModeLocked(enabled, fromActive, fromMotion); + mStats.noteDeviceIdleModeLocked(enabled, activeReason, activeUid); } } @@ -807,7 +833,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub // Sync external stats first as the battery has changed states. If we don't sync // immediately here, we may not collect the relevant data later. - updateExternalStats("battery-state", false); + updateExternalStats("battery-state", UPDATE_ALL); synchronized (mStats) { mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt); } @@ -961,9 +987,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub pw.println("Battery stats reset."); noOutput = true; } - updateExternalStats("dump", true); + updateExternalStats("dump", UPDATE_ALL); } else if ("--write".equals(arg)) { - updateExternalStats("dump", true); + updateExternalStats("dump", UPDATE_ALL); synchronized (mStats) { mStats.writeSyncLocked(); pw.println("Battery stats written."); @@ -1027,7 +1053,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY; } // Fetch data from external sources and update the BatteryStatsImpl object with them. - updateExternalStats("dump", true); + updateExternalStats("dump", UPDATE_ALL); } finally { Binder.restoreCallingIdentity(ident); } @@ -1119,6 +1145,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub return null; } + final long timePeriodMs = info.mTimestamp - mLastInfo.mTimestamp; + final long lastIdleMs = mLastInfo.mControllerIdleTimeMs; + final long lastTxMs = mLastInfo.mControllerTxTimeMs; + final long lastRxMs = mLastInfo.mControllerRxTimeMs; + final long lastEnergy = mLastInfo.mControllerEnergyUsed; + // We will modify the last info object to be the delta, and store the new // WifiActivityEnergyInfo object as our last one. final WifiActivityEnergyInfo result = mLastInfo; @@ -1126,19 +1158,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub result.mStackState = info.getStackState(); // These times seem to be the most reliable. - result.mControllerTxTimeMs = - info.mControllerTxTimeMs - mLastInfo.mControllerTxTimeMs; - result.mControllerRxTimeMs = - info.mControllerRxTimeMs - mLastInfo.mControllerRxTimeMs; + result.mControllerTxTimeMs = info.mControllerTxTimeMs - lastTxMs; + result.mControllerRxTimeMs = info.mControllerRxTimeMs - lastRxMs; // WiFi calculates the idle time as a difference from the on time and the various // Rx + Tx times. There seems to be some missing time there because this sometimes // becomes negative. Just cap it at 0 and move on. // b/21613534 - result.mControllerIdleTimeMs = - Math.max(0, info.mControllerIdleTimeMs - mLastInfo.mControllerIdleTimeMs); + result.mControllerIdleTimeMs = Math.max(0, info.mControllerIdleTimeMs - lastIdleMs); result.mControllerEnergyUsed = - Math.max(0, info.mControllerEnergyUsed - mLastInfo.mControllerEnergyUsed); + Math.max(0, info.mControllerEnergyUsed - lastEnergy); if (result.mControllerTxTimeMs < 0 || result.mControllerRxTimeMs < 0) { @@ -1151,6 +1180,34 @@ public final class BatteryStatsService extends IBatteryStats.Stub Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result); } + + final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs + + result.mControllerTxTimeMs; + if (totalTimeMs > timePeriodMs) { + StringBuilder sb = new StringBuilder(); + sb.append("Total time "); + TimeUtils.formatDuration(totalTimeMs, sb); + sb.append(" is longer than sample period "); + TimeUtils.formatDuration(timePeriodMs, sb); + sb.append(".\n"); + sb.append("Previous WiFi snapshot: ").append("idle="); + TimeUtils.formatDuration(lastIdleMs, sb); + sb.append(" rx="); + TimeUtils.formatDuration(lastRxMs, sb); + sb.append(" tx="); + TimeUtils.formatDuration(lastTxMs, sb); + sb.append(" e=").append(lastEnergy); + sb.append("\n"); + sb.append("Current WiFi snapshot: ").append("idle="); + TimeUtils.formatDuration(info.mControllerIdleTimeMs, sb); + sb.append(" rx="); + TimeUtils.formatDuration(info.mControllerRxTimeMs, sb); + sb.append(" tx="); + TimeUtils.formatDuration(info.mControllerTxTimeMs, sb); + sb.append(" e=").append(info.mControllerEnergyUsed); + Slog.wtf(TAG, sb.toString()); + } + mLastInfo = info; return result; } @@ -1184,15 +1241,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub * We first grab a lock specific to this method, then once all the data has been collected, * we grab the mStats lock and update the data. * - * TODO(adamlesinski): When we start distributing bluetooth data to apps, we'll want to - * separate these external stats so that they can be collected individually and on different - * intervals. - * * @param reason The reason why this collection was requested. Useful for debugging. - * @param force If false, some stats may decide not to be collected for efficiency as their - * results aren't needed immediately. When true, collect all stats unconditionally. + * @param updateFlags Which external stats to update. Can be a combination of + * {@link #UPDATE_CPU}, {@link #UPDATE_RADIO}, {@link #UPDATE_WIFI}, + * and {@link #UPDATE_BT}. */ - void updateExternalStats(String reason, boolean force) { + void updateExternalStats(final String reason, final int updateFlags) { synchronized (mExternalStatsLock) { if (mContext == null) { // We haven't started yet (which means the BatteryStatsImpl object has @@ -1200,34 +1254,46 @@ public final class BatteryStatsService extends IBatteryStats.Stub return; } - final WifiActivityEnergyInfo wifiEnergyInfo = pullWifiEnergyInfoLocked(); - final BluetoothActivityEnergyInfo bluetoothEnergyInfo; - if (force) { + if (BatteryStatsImpl.DEBUG_ENERGY) { + Slog.d(TAG, "Updating external stats: reason=" + reason); + } + + WifiActivityEnergyInfo wifiEnergyInfo = null; + if ((updateFlags & UPDATE_WIFI) != 0) { + wifiEnergyInfo = pullWifiEnergyInfoLocked(); + } + + BluetoothActivityEnergyInfo bluetoothEnergyInfo = null; + if ((updateFlags & UPDATE_BT) != 0) { // We only pull bluetooth stats when we have to, as we are not distributing its // use amongst apps and the sampling frequency does not matter. bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked(); - } else { - bluetoothEnergyInfo = null; } synchronized (mStats) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); if (mStats.mRecordAllHistory) { - final long elapsedRealtime = SystemClock.elapsedRealtime(); - final long uptime = SystemClock.uptimeMillis(); mStats.addHistoryEventLocked(elapsedRealtime, uptime, BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0); } - mStats.updateCpuTimeLocked(mFirstExternalStatsUpdate); - mStats.updateKernelWakelocksLocked(); - mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime()); - mStats.updateWifiStateLocked(wifiEnergyInfo); - mStats.updateBluetoothStateLocked(bluetoothEnergyInfo); - } - if (mFirstExternalStatsUpdate) { - // We have read the stats for the first time, which means we have a baseline - // from which to calculate delta. - mFirstExternalStatsUpdate = false; + if ((updateFlags & UPDATE_CPU) != 0) { + mStats.updateCpuTimeLocked(); + mStats.updateKernelWakelocksLocked(); + } + + if ((updateFlags & UPDATE_RADIO) != 0) { + mStats.updateMobileRadioStateLocked(elapsedRealtime); + } + + if ((updateFlags & UPDATE_WIFI) != 0) { + mStats.updateWifiStateLocked(wifiEnergyInfo); + } + + if ((updateFlags & UPDATE_BT) != 0) { + mStats.updateBluetoothStateLocked(bluetoothEnergyInfo); + } } } } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 3acd3a3..bd31a21 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -40,6 +40,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Process; import android.os.SystemClock; +import android.os.Trace; import android.os.UserHandle; import android.util.ArrayMap; import android.util.PrintWriterPrinter; @@ -536,6 +537,7 @@ final class ProcessRecord { void kill(String reason, boolean noisy) { if (!killedByAm) { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill"); if (noisy) { Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason); } @@ -546,6 +548,7 @@ final class ProcessRecord { killed = true; killedByAm = true; } + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } } diff --git a/services/core/java/com/android/server/am/UserStartedState.java b/services/core/java/com/android/server/am/UserState.java index d3e73d5..b3d82bc 100644 --- a/services/core/java/com/android/server/am/UserStartedState.java +++ b/services/core/java/com/android/server/am/UserState.java @@ -21,8 +21,9 @@ import java.util.ArrayList; import android.app.IStopUserCallback; import android.os.UserHandle; +import android.util.ArrayMap; -public final class UserStartedState { +public final class UserState { // User is first coming up. public final static int STATE_BOOTING = 0; // User is in the normal running state. @@ -40,7 +41,13 @@ public final class UserStartedState { public boolean switching; public boolean initializing; - public UserStartedState(UserHandle handle, boolean initial) { + /** + * The last time that a provider was reported to usage stats as being brought to important + * foreground procstate. + */ + public final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>(); + + public UserState(UserHandle handle, boolean initial) { mHandle = handle; } diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index 4ccb5ad..f72b598 100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -46,10 +46,12 @@ import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; import android.speech.RecognizerIntent; @@ -1086,6 +1088,14 @@ public class MediaFocusControl implements OnFinished { voiceIntent = new Intent(android.speech.RecognizerIntent.ACTION_WEB_SEARCH); Log.i(TAG, "voice-based interactions: about to use ACTION_WEB_SEARCH"); } else { + IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); + if (dic != null) { + try { + dic.exitIdle("voice-search"); + } catch (RemoteException e) { + } + } voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, isLocked && mKeyguardManager.isKeyguardSecure()); diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index eac748f..3bf1183 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -106,8 +106,16 @@ public class NetworkAgentInfo { networkMisc = misc; } - public void addRequest(NetworkRequest networkRequest) { + /** + * Add {@code networkRequest} to this network as it's satisfied by this network. + * NOTE: This function must only be called on ConnectivityService's main thread. + * @return true if {@code networkRequest} was added or false if {@code networkRequest} was + * already present. + */ + public boolean addRequest(NetworkRequest networkRequest) { + if (networkRequests.get(networkRequest.requestId) == networkRequest) return false; networkRequests.put(networkRequest.requestId, networkRequest); + return true; } // Does this network satisfy request? diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index fc50e2c..99a0567 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -178,6 +178,13 @@ public class NetworkMonitor extends StateMachine { */ private static final int CMD_LAUNCH_CAPTIVE_PORTAL_APP = BASE + 11; + /** + * Retest network to see if captive portal is still in place. + * arg1 = UID responsible for requesting this reeval. Will be billed for data. + * 0 indicates self-initiated, so nobody to blame. + */ + private static final int CMD_CAPTIVE_PORTAL_RECHECK = BASE + 12; + private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger"; // Default to 30s linger time-out. Modifyable only for testing. private static int DEFAULT_LINGER_DELAY_MS = 30000; @@ -194,6 +201,8 @@ public class NetworkMonitor extends StateMachine { private int mUidResponsibleForReeval = INVALID_UID; // Stop blaming UID that requested re-evaluation after this many attempts. private static final int BLAME_FOR_EVALUATION_ATTEMPTS = 5; + // Delay between reevaluations once a captive portal has been found. + private static final int CAPTIVE_PORTAL_REEVALUATE_DELAY_MS = 10*60*1000; private final Context mContext; private final Handler mConnectivityServiceHandler; @@ -287,6 +296,7 @@ public class NetworkMonitor extends StateMachine { quit(); return HANDLED; case CMD_FORCE_REEVALUATION: + case CMD_CAPTIVE_PORTAL_RECHECK: if (DBG) log("Forcing reevaluation"); mUidResponsibleForReeval = message.arg1; transitionTo(mEvaluatingState); @@ -517,6 +527,9 @@ public class NetworkMonitor extends StateMachine { mNetworkAgentInfo.network.netId, mLaunchCaptivePortalAppBroadcastReceiver.getPendingIntent()); mConnectivityServiceHandler.sendMessage(message); + // Retest for captive portal occasionally. + sendMessageDelayed(CMD_CAPTIVE_PORTAL_RECHECK, 0 /* no UID */, + CAPTIVE_PORTAL_REEVALUATE_DELAY_MS); } @Override @@ -524,6 +537,11 @@ public class NetworkMonitor extends StateMachine { if (DBG) log(getName() + message.toString()); return NOT_HANDLED; } + + @Override + public void exit() { + removeMessages(CMD_CAPTIVE_PORTAL_RECHECK); + } } // Being in the LingeringState State indicates a Network's validated bit is true and it once diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index ea461e5..93ed2ee 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -506,6 +506,21 @@ public final class ContentService extends IContentService.Stub { } @Override + public String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId) { + enforceCrossUserPermission(userId, + "no permission to read sync settings for user " + userId); + // This makes it so that future permission checks will be in the context of this + // process rather than the caller's process. We will restore this before returning. + final long identityToken = clearCallingIdentity(); + try { + SyncManager syncManager = getSyncManager(); + return syncManager.getSyncAdapterPackagesForAuthorityAsUser(authority, userId); + } finally { + restoreCallingIdentity(identityToken); + } + } + + @Override public boolean getSyncAutomatically(Account account, String providerName) { return getSyncAutomaticallyAsUser(account, providerName, UserHandle.getCallingUserId()); } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 2eb8797..cd9c7fe 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -908,6 +908,10 @@ public class SyncManager { return types; } + public String[] getSyncAdapterPackagesForAuthorityAsUser(String authority, int userId) { + return mSyncAdapters.getSyncAdapterPackagesForAuthority(authority, userId); + } + private void sendSyncAlarmMessage() { if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "sending MESSAGE_SYNC_ALARM"); mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_SYNC_ALARM); diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java index 259ff1d..d4f3c4d 100644 --- a/services/core/java/com/android/server/location/FlpHardwareProvider.java +++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java @@ -136,6 +136,10 @@ public class FlpHardwareProvider { } maybeSendCapabilities(); + + if (mGeofenceHardwareSink != null) { + mGeofenceHardwareSink.setVersion(getVersion()); + } } private void onBatchingStatus(int status) { @@ -152,10 +156,23 @@ public class FlpHardwareProvider { } } + // Returns the current version of the FLP HAL. This depends both on the version of the + // structure returned by the hardware layer, and whether or not we've received the + // capabilities callback on initialization. Assume original version until we get + // the new initialization callback. + private int getVersion() { + synchronized (mLocationSinkLock) { + if (mHaveBatchingCapabilities) { + return mVersion; + } + } + return 1; + } + private void setVersion(int version) { mVersion = version; if (mGeofenceHardwareSink != null) { - mGeofenceHardwareSink.setVersion(version); + mGeofenceHardwareSink.setVersion(getVersion()); } } @@ -375,7 +392,7 @@ public class FlpHardwareProvider { @Override public void flushBatchedLocations() { - if (mVersion >= FIRST_VERSION_WITH_FLUSH_LOCATIONS) { + if (getVersion() >= FIRST_VERSION_WITH_FLUSH_LOCATIONS) { nativeFlushBatchedLocations(); } else { Log.wtf(TAG, @@ -405,7 +422,7 @@ public class FlpHardwareProvider { @Override public int getVersion() { - return mVersion; + return FlpHardwareProvider.this.getVersion(); } }; @@ -482,7 +499,7 @@ public class FlpHardwareProvider { private GeofenceHardwareImpl getGeofenceHardwareSink() { if (mGeofenceHardwareSink == null) { mGeofenceHardwareSink = GeofenceHardwareImpl.getInstance(mContext); - mGeofenceHardwareSink.setVersion(mVersion); + mGeofenceHardwareSink.setVersion(getVersion()); } return mGeofenceHardwareSink; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 9c288be..0dcad82 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1969,6 +1969,9 @@ public class NotificationManagerService extends SystemService { for (int i=0; i<N; i++) { final NotificationRecord r = mNotificationList.get(i); if (r.sbn.getPackageName().equals(pkg) && r.sbn.getUserId() == userId) { + if (r.sbn.getId() == id && TextUtils.equals(r.sbn.getTag(), tag)) { + break; // Allow updating existing notification + } count++; if (count >= MAX_PACKAGE_NOTIFICATIONS) { Slog.e(TAG, "Package has already posted " + count @@ -2999,19 +3002,8 @@ public class NotificationManagerService extends SystemService { final int len = list.size(); for (int i=0; i<len; i++) { NotificationRecord r = list.get(i); - if (!notificationMatchesUserId(r, userId) || r.sbn.getId() != id) { - continue; - } - if (tag == null) { - if (r.sbn.getTag() != null) { - continue; - } - } else { - if (!tag.equals(r.sbn.getTag())) { - continue; - } - } - if (r.sbn.getPackageName().equals(pkg)) { + if (notificationMatchesUserId(r, userId) && r.sbn.getId() == id && + TextUtils.equals(r.sbn.getTag(), tag) && r.sbn.getPackageName().equals(pkg)) { return i; } } diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java new file mode 100644 index 0000000..fe3103b --- /dev/null +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal.PackagesProvider; +import android.content.pm.PackageParser; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.os.Build; +import android.os.UserHandle; +import android.provider.MediaStore; +import android.util.ArraySet; +import android.util.Log; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static android.os.Process.FIRST_APPLICATION_UID; + +/** + * This class is the policy for granting runtime permissions to + * platform components and default handlers in the system such + * that the device is usable out-of-the-box. For example, the + * shell UID is a part of the system and the Phone app should + * have phone related permission by default. + */ +final class DefaultPermissionGrantPolicy { + private static final String TAG = "DefaultPermissionGrantPolicy"; + private static final boolean DEBUG = false; + + private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive"; + + private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>(); + static { + PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE); + PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE); + PHONE_PERMISSIONS.add( Manifest.permission.READ_CALL_LOG); + PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG); + PHONE_PERMISSIONS.add(Manifest.permission.ADD_VOICEMAIL); + PHONE_PERMISSIONS.add(Manifest.permission.USE_SIP); + PHONE_PERMISSIONS.add(Manifest.permission.PROCESS_OUTGOING_CALLS); + } + + private static final Set<String> CONTACTS_PERMISSIONS = new ArraySet<>(); + static { + CONTACTS_PERMISSIONS.add(Manifest.permission.READ_CONTACTS); + CONTACTS_PERMISSIONS.add(Manifest.permission.WRITE_CONTACTS); + } + + private static final Set<String> LOCATION_PERMISSIONS = new ArraySet<>(); + static { + LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION); + LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION); + } + + private static final Set<String> CALENDAR_PERMISSIONS = new ArraySet<>(); + static { + CALENDAR_PERMISSIONS.add(Manifest.permission.READ_CALENDAR); + CALENDAR_PERMISSIONS.add(Manifest.permission.WRITE_CALENDAR); + } + + private static final Set<String> SMS_PERMISSIONS = new ArraySet<>(); + static { + SMS_PERMISSIONS.add(Manifest.permission.SEND_SMS); + SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_SMS); + SMS_PERMISSIONS.add(Manifest.permission.READ_SMS); + SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_WAP_PUSH); + SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_MMS); + SMS_PERMISSIONS.add(Manifest.permission.READ_CELL_BROADCASTS); + } + + private static final Set<String> MICROPHONE_PERMISSIONS = new ArraySet<>(); + static { + MICROPHONE_PERMISSIONS.add(Manifest.permission.RECORD_AUDIO); + } + + private static final Set<String> CAMERA_PERMISSIONS = new ArraySet<>(); + static { + CAMERA_PERMISSIONS.add(Manifest.permission.CAMERA); + } + + private static final Set<String> SENSORS_PERMISSIONS = new ArraySet<>(); + static { + SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS); + } + + private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>(); + static { +// STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE); + STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + } + + private static final Set<String> SETTINGS_PERMISSIONS = new ArraySet<>(); + static { + SETTINGS_PERMISSIONS.add(Manifest.permission.WRITE_SETTINGS); + } + + private static final Set<String> INSTALLER_PERMISSIONS = new ArraySet<>(); + static { + INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS); + INSTALLER_PERMISSIONS.add(Manifest.permission.INTERACT_ACROSS_USERS_FULL); + INSTALLER_PERMISSIONS.add(Manifest.permission.CLEAR_APP_USER_DATA); + INSTALLER_PERMISSIONS.add(Manifest.permission.KILL_UID); + } + + private static final Set<String> VERIFIER_PERMISSIONS = new ArraySet<>(); + static { + INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS); + } + + private final PackageManagerService mService; + + private PackagesProvider mImePackagesProvider; + private PackagesProvider mLocationPackagesProvider; + private PackagesProvider mVoiceInteractionPackagesProvider; + + public DefaultPermissionGrantPolicy(PackageManagerService service) { + mService = service; + } + + public void setImePackagesProviderLPr(PackagesProvider provider) { + mImePackagesProvider = provider; + } + + public void setLocationPackagesProviderLPw(PackagesProvider provider) { + mLocationPackagesProvider = provider; + } + + public void setVoiceInteractionPackagesProviderLPw(PackagesProvider provider) { + mVoiceInteractionPackagesProvider = provider; + } + + public void grantDefaultPermissions(int userId) { + grantPermissionsToSysComponentsAndPrivApps(userId); + grantDefaultSystemHandlerPermissions(userId); + } + + private void grantPermissionsToSysComponentsAndPrivApps(int userId) { + Log.i(TAG, "Granting permissions to platform components"); + + synchronized (mService.mPackages) { + for (PackageParser.Package pkg : mService.mPackages.values()) { + if (!isSysComponentOrPersistentPrivApp(pkg) + || !doesPackageSupportRuntimePermissions(pkg)) { + continue; + } + final int permissionCount = pkg.requestedPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + String permission = pkg.requestedPermissions.get(i); + BasePermission bp = mService.mSettings.mPermissions.get(permission); + if (bp != null && bp.isRuntime()) { + final int flags = mService.getPermissionFlags(permission, + pkg.packageName, userId); + if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) == 0) { + mService.grantRuntimePermission(pkg.packageName, permission, userId); + mService.updatePermissionFlags(permission, pkg.packageName, + PackageManager.MASK_PERMISSION_FLAGS, + PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, userId); + if (DEBUG) { + Log.i(TAG, "Granted " + permission + " to system component " + + pkg.packageName); + } + } + } + } + } + } + } + + private void grantDefaultSystemHandlerPermissions(int userId) { + Log.i(TAG, "Granting permissions to default platform handlers"); + + final PackagesProvider imePackagesProvider; + final PackagesProvider locationPackagesProvider; + final PackagesProvider voiceInteractionPackagesProvider; + + synchronized (mService.mPackages) { + imePackagesProvider = mImePackagesProvider; + locationPackagesProvider = mLocationPackagesProvider; + voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider; + } + + String[] imePackageNames = (imePackagesProvider != null) + ? imePackagesProvider.getPackages(userId) : null; + String[] voiceInteractPackageNames = (voiceInteractionPackagesProvider != null) + ? voiceInteractionPackagesProvider.getPackages(userId) : null; + String[] locationPackageNames = (locationPackagesProvider != null) + ? locationPackagesProvider.getPackages(userId) : null; + + synchronized (mService.mPackages) { + // Installers + Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE); + installerIntent.addCategory(Intent.CATEGORY_DEFAULT); + installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")), + PACKAGE_MIME_TYPE); + List<PackageParser.Package> installerPackages = + getPrivilegedHandlerActivityPackagesLPr(installerIntent, userId); + final int installerCount = installerPackages.size(); + for (int i = 0; i < installerCount; i++) { + PackageParser.Package installPackage = installerPackages.get(i); + grantInstallPermissionsLPw(installPackage, INSTALLER_PERMISSIONS, userId); + } + + // Verifiers + Intent verifierIntent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION); + verifierIntent.setType(PACKAGE_MIME_TYPE); + List<PackageParser.Package> verifierPackages = + getPrivilegedHandlerReceiverPackagesLPr(verifierIntent, userId); + final int verifierCount = verifierPackages.size(); + for (int i = 0; i < verifierCount; i++) { + PackageParser.Package verifierPackage = verifierPackages.get(i); + grantInstallPermissionsLPw(verifierPackage, VERIFIER_PERMISSIONS, userId); + } + + // SetupWizard + Intent setupIntent = new Intent(Intent.ACTION_MAIN); + setupIntent.addCategory(Intent.CATEGORY_HOME); + PackageParser.Package setupPackage = getDefaultSystemHandlerActvityPackageLPr( + setupIntent, userId); + if (setupPackage != null + && doesPackageSupportRuntimePermissions(setupPackage)) { + grantRuntimePermissionsLPw(setupPackage, PHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(setupPackage, CONTACTS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(setupPackage, SETTINGS_PERMISSIONS, userId); + } + + // Phone + Intent dialerIntent = new Intent(Intent.ACTION_DIAL); + PackageParser.Package dialerPackage = getDefaultSystemHandlerActvityPackageLPr( + dialerIntent, userId); + if (dialerPackage != null + && doesPackageSupportRuntimePermissions(dialerPackage)) { + grantRuntimePermissionsLPw(dialerPackage, PHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId); + } + + // Camera + Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + PackageParser.Package cameraPackage = getDefaultSystemHandlerActvityPackageLPr( + cameraIntent, userId); + if (cameraPackage != null + && doesPackageSupportRuntimePermissions(cameraPackage)) { + grantRuntimePermissionsLPw(cameraPackage, CAMERA_PERMISSIONS, userId); + grantRuntimePermissionsLPw(cameraPackage, MICROPHONE_PERMISSIONS, userId); + } + + // Messaging + Intent messagingIntent = new Intent(Intent.ACTION_MAIN); + messagingIntent.addCategory(Intent.CATEGORY_APP_MESSAGING); + PackageParser.Package messagingPackage = getDefaultSystemHandlerActvityPackageLPr( + messagingIntent, userId); + if (messagingPackage != null + && doesPackageSupportRuntimePermissions(messagingPackage)) { + grantRuntimePermissionsLPw(messagingPackage, PHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(messagingPackage, CONTACTS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(messagingPackage, SMS_PERMISSIONS, userId); + } + + // Calendar + Intent calendarIntent = new Intent(Intent.ACTION_MAIN); + calendarIntent.addCategory(Intent.CATEGORY_APP_CALENDAR); + PackageParser.Package calendarPackage = getDefaultSystemHandlerActvityPackageLPr( + calendarIntent, userId); + if (calendarPackage != null + && doesPackageSupportRuntimePermissions(calendarPackage)) { + grantRuntimePermissionsLPw(calendarPackage, CALENDAR_PERMISSIONS, userId); + grantRuntimePermissionsLPw(calendarPackage, CONTACTS_PERMISSIONS, userId); + } + + // Contacts + Intent contactsIntent = new Intent(Intent.ACTION_MAIN); + contactsIntent.addCategory(Intent.CATEGORY_APP_CONTACTS); + PackageParser.Package contactsPackage = getDefaultSystemHandlerActvityPackageLPr( + contactsIntent, userId); + if (contactsPackage != null + && doesPackageSupportRuntimePermissions(contactsPackage)) { + grantRuntimePermissionsLPw(contactsPackage, CONTACTS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(contactsPackage, PHONE_PERMISSIONS, userId); + } + + // Maps + Intent mapsIntent = new Intent(Intent.ACTION_MAIN); + mapsIntent.addCategory(Intent.CATEGORY_APP_MAPS); + PackageParser.Package mapsPackage = getDefaultSystemHandlerActvityPackageLPr( + mapsIntent, userId); + if (mapsPackage != null + && doesPackageSupportRuntimePermissions(mapsPackage)) { + grantRuntimePermissionsLPw(mapsPackage, LOCATION_PERMISSIONS, userId); + } + + // Email + Intent emailIntent = new Intent(Intent.ACTION_MAIN); + emailIntent.addCategory(Intent.CATEGORY_APP_EMAIL); + PackageParser.Package emailPackage = getDefaultSystemHandlerActvityPackageLPr( + emailIntent, userId); + if (emailPackage != null + && doesPackageSupportRuntimePermissions(emailPackage)) { + grantRuntimePermissionsLPw(emailPackage, CONTACTS_PERMISSIONS, userId); + } + + // Browser + Intent browserIntent = new Intent(Intent.ACTION_MAIN); + browserIntent.addCategory(Intent.CATEGORY_APP_BROWSER); + PackageParser.Package browserPackage = getDefaultSystemHandlerActvityPackageLPr( + browserIntent, userId); + if (browserPackage != null + && doesPackageSupportRuntimePermissions(browserPackage)) { + grantRuntimePermissionsLPw(browserPackage, LOCATION_PERMISSIONS, userId); + } + + // IME + if (imePackageNames != null) { + for (String imePackageName : imePackageNames) { + PackageParser.Package imePackage = getSystemPackageLPr(imePackageName); + if (imePackage != null + && doesPackageSupportRuntimePermissions(imePackage)) { + grantRuntimePermissionsLPw(imePackage, CONTACTS_PERMISSIONS, userId); + } + } + } + + // Voice interaction + if (voiceInteractPackageNames != null) { + for (String voiceInteractPackageName : voiceInteractPackageNames) { + PackageParser.Package voiceInteractPackage = getSystemPackageLPr( + voiceInteractPackageName); + if (voiceInteractPackage != null + && doesPackageSupportRuntimePermissions(voiceInteractPackage)) { + grantRuntimePermissionsLPw(voiceInteractPackage, + CONTACTS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(voiceInteractPackage, + CALENDAR_PERMISSIONS, userId); + grantRuntimePermissionsLPw(voiceInteractPackage, + MICROPHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(voiceInteractPackage, + PHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(voiceInteractPackage, + SMS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(voiceInteractPackage, + LOCATION_PERMISSIONS, userId); + } + } + } + + // Location + if (locationPackageNames != null) { + for (String packageName : locationPackageNames) { + PackageParser.Package locationPackage = getSystemPackageLPr(packageName); + if (locationPackage != null + && doesPackageSupportRuntimePermissions(locationPackage)) { + grantRuntimePermissionsLPw(locationPackage, CONTACTS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, CALENDAR_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, MICROPHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, PHONE_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, SMS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, LOCATION_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, CAMERA_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, SENSORS_PERMISSIONS, userId); + grantRuntimePermissionsLPw(locationPackage, STORAGE_PERMISSIONS, userId); + } + } + } + } + } + + private List<PackageParser.Package> getPrivilegedHandlerReceiverPackagesLPr( + Intent intent, int userId) { + List<ResolveInfo> handlers = mService.queryIntentReceivers( + intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()), + 0, userId); + return getPrivilegedPackages(handlers); + } + + private List<PackageParser.Package> getPrivilegedHandlerActivityPackagesLPr( + Intent intent, int userId) { + List<ResolveInfo> handlers = mService.queryIntentActivities( + intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()), + 0, userId); + return getPrivilegedPackages(handlers); + } + + private List<PackageParser.Package> getPrivilegedPackages(List<ResolveInfo> resolveInfos) { + List<PackageParser.Package> handlerPackages = new ArrayList<>(); + final int handlerCount = resolveInfos.size(); + for (int i = 0; i < handlerCount; i++) { + ResolveInfo handler = resolveInfos.get(i); + PackageParser.Package handlerPackage = getPrivilegedPackageLPr( + handler.activityInfo.packageName); + if (handlerPackage != null) { + handlerPackages.add(handlerPackage); + } + } + return handlerPackages; + } + + private PackageParser.Package getDefaultSystemHandlerActvityPackageLPr( + Intent intent, int userId) { + List<ResolveInfo> handlers = mService.queryIntentActivities(intent, null, 0, userId); + final int handlerCount = handlers.size(); + for (int i = 0; i < handlerCount; i++) { + ResolveInfo handler = handlers.get(i); + // TODO: This is a temporary hack to figure out the setup app. + PackageParser.Package handlerPackage = getSystemPackageLPr( + handler.activityInfo.packageName); + if (handlerPackage != null) { + return handlerPackage; + } + } + return null; + } + + private PackageParser.Package getSystemPackageLPr(String packageName) { + PackageParser.Package pkg = mService.mPackages.get(packageName); + if (pkg != null && pkg.isSystemApp()) { + return !isSysComponentOrPersistentPrivApp(pkg) ? pkg : null; + } + return null; + } + + private PackageParser.Package getPrivilegedPackageLPr(String packageName) { + PackageParser.Package pkg = mService.mPackages.get(packageName); + if (pkg != null && pkg.applicationInfo.isPrivilegedApp()) { + return !isSysComponentOrPersistentPrivApp(pkg) ? pkg : null; + } + return null; + } + + private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions, + int userId) { + List<String> requestedPermissions = pkg.requestedPermissions; + + if (pkg.isUpdatedSystemApp()) { + PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName); + if (sysPs != null) { + requestedPermissions = sysPs.pkg.requestedPermissions; + } + } + + final int permissionCount = requestedPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + String permission = requestedPermissions.get(i); + if (permissions.contains(permission)) { + final int flags = mService.getPermissionFlags(permission, pkg.packageName, userId); + + // If any flags are set to the permission, then it is either set in + // its current state by the system or device/profile owner or the user. + // In all these cases we do not want to clobber the current state. + if (flags == 0) { + mService.grantRuntimePermission(pkg.packageName, permission, userId); + if (DEBUG) { + Log.i(TAG, "Granted " + permission + " to default handler " + + pkg.packageName); + } + } + } + } + } + + private void grantInstallPermissionsLPw(PackageParser.Package pkg, Set<String> permissions, + int userId) { + List<String> requestedPermissions = pkg.requestedPermissions; + + if (pkg.isUpdatedSystemApp()) { + PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName); + if (sysPs != null) { + requestedPermissions = sysPs.pkg.requestedPermissions; + } + } + + final int permissionCount = requestedPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + String permission = requestedPermissions.get(i); + if (permissions.contains(permission)) { + final int flags = mService.getPermissionFlags(permission, pkg.packageName, userId); + + // If any flags are set to the permission, then it is either set in + // its current state by the system or device/profile owner or the user. + // In all these cases we do not want to clobber the current state. + if (flags == 0) { + mService.grantInstallPermissionLPw(permission, pkg); + if (DEBUG) { + Log.i(TAG, "Granted install " + permission + " to " + pkg.packageName); + } + } + } + } + } + + private static boolean isSysComponentOrPersistentPrivApp(PackageParser.Package pkg) { + return UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID + || ((pkg.applicationInfo.privateFlags + & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 + && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0); + } + + private static boolean doesPackageSupportRuntimePermissions(PackageParser.Package pkg) { + return pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1; + } +} diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ef833cb..b593906 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -55,7 +55,6 @@ import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING; import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE; import static android.content.pm.PackageParser.isApkFile; -import static android.os.Process.FIRST_APPLICATION_UID; import static android.os.Process.PACKAGE_INFO_GID; import static android.os.Process.SYSTEM_UID; import static android.system.OsConstants.O_CREAT; @@ -111,6 +110,7 @@ import android.content.pm.PackageInfoLite; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageManager.LegacyPackageDeleteObserver; +import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; import android.content.pm.PackageParser.ActivityIntentInfo; import android.content.pm.PackageParser.PackageLite; @@ -281,6 +281,8 @@ public class PackageManagerService extends IPackageManager.Stub { private static final boolean DEBUG_DEXOPT = false; private static final boolean DEBUG_ABI_SELECTION = false; + static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = Build.IS_DEBUGGABLE; + private static final int RADIO_UID = Process.PHONE_UID; private static final int LOG_UID = Process.LOG_UID; private static final int NFC_UID = Process.NFC_UID; @@ -551,6 +553,9 @@ public class PackageManagerService extends IPackageManager.Stub { final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates = new SparseArray<IntentFilterVerificationState>(); + final DefaultPermissionGrantPolicy mDefaultPermissionPolicy = + new DefaultPermissionGrantPolicy(this); + private interface IntentFilterVerifier<T extends IntentFilter> { boolean addOneIntentFilterVerification(int verifierId, int userId, int verificationId, T filter, String packageName); @@ -1592,6 +1597,11 @@ public class PackageManagerService extends IPackageManager.Stub { grantRequestedRuntimePermissionsForUser(pkg, someUserId); } } + + // We could have touched GID membership, so flush out packages.list + synchronized (mPackages) { + mSettings.writePackageListLPr(); + } } private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId) { @@ -2200,6 +2210,9 @@ public class PackageManagerService extends IPackageManager.Stub { // are all flushed. Not really needed, but keeps things nice and // tidy. Runtime.getRuntime().gc(); + + // Expose private service for system components to use. + LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl()); } @Override @@ -3156,7 +3169,7 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public void grantRuntimePermission(String packageName, String name, int userId) { + public void grantRuntimePermission(String packageName, String name, final int userId) { if (!sUserManager.exists(userId)) { Log.e(TAG, "No such user:" + userId); return; @@ -3169,7 +3182,6 @@ public class PackageManagerService extends IPackageManager.Stub { enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "grantRuntimePermission"); - boolean gidsChanged = false; final SettingBase sb; synchronized (mPackages) { @@ -3205,7 +3217,12 @@ public class PackageManagerService extends IPackageManager.Stub { } case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: { - gidsChanged = true; + mHandler.post(new Runnable() { + @Override + public void run() { + killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED); + } + }); } break; } @@ -3214,10 +3231,6 @@ public class PackageManagerService extends IPackageManager.Stub { // Not critical if that is lost - app has to request again. mSettings.writeRuntimePermissionsForUserLPr(userId, false); } - - if (gidsChanged) { - killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED); - } } @Override @@ -3324,15 +3337,14 @@ public class PackageManagerService extends IPackageManager.Stub { enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "updatePermissionFlags"); - // Only the system can change policy flags. + // Only the system can change policy and system fixed flags. if (getCallingUid() != Process.SYSTEM_UID) { flagMask &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED; flagValues &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED; - } - // Only the package manager can change system flags. - flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; - flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; + flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; + flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; + } synchronized (mPackages) { final PackageParser.Package pkg = mPackages.get(packageName); @@ -3410,6 +3422,21 @@ public class PackageManagerService extends IPackageManager.Stub { return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0; } + void grantInstallPermissionLPw(String permission, PackageParser.Package pkg) { + BasePermission bp = mSettings.mPermissions.get(permission); + if (bp == null) { + throw new SecurityException("Missing " + permission + " permission"); + } + + SettingBase sb = (SettingBase) pkg.mExtras; + PermissionsState permissionsState = sb.getPermissionsState(); + + if (permissionsState.grantInstallPermission(bp) != + PermissionsState.PERMISSION_OPERATION_FAILURE) { + scheduleWriteSettingsLocked(); + } + } + @Override public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) { mContext.enforceCallingOrSelfPermission( @@ -7725,7 +7752,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } } - + if (pkgInfo != null) { grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0, changingPkg); } @@ -7754,7 +7781,6 @@ public class PackageManagerService extends IPackageManager.Stub { final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); - int[] upgradeUserIds = EMPTY_INT_ARRAY; int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY; boolean changedInstallPermission = false; @@ -7811,32 +7837,11 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) { // For legacy apps dangerous permissions are install time ones. grant = GRANT_INSTALL_LEGACY; - } else if (ps.isSystem()) { - final int[] updatedUserIds = ps.getPermissionsUpdatedForUserIds(); - if (origPermissions.hasInstallPermission(bp.name)) { - // If a system app had an install permission, then the app was - // upgraded and we grant the permissions as runtime to all users. - grant = GRANT_UPGRADE; - upgradeUserIds = currentUserIds; - } else if (!Arrays.equals(updatedUserIds, currentUserIds)) { - // If users changed since the last permissions update for a - // system app, we grant the permission as runtime to the new users. - grant = GRANT_UPGRADE; - upgradeUserIds = currentUserIds; - for (int userId : updatedUserIds) { - upgradeUserIds = ArrayUtils.removeInt(upgradeUserIds, userId); - } - } else { - // Otherwise, we grant the permission as runtime if the app - // already had it, i.e. we preserve runtime permissions. - grant = GRANT_RUNTIME; - } } else if (origPermissions.hasInstallPermission(bp.name)) { // For legacy apps that became modern, install becomes runtime. grant = GRANT_UPGRADE; - upgradeUserIds = currentUserIds; - } else if (replace) { - // For upgraded modern apps keep runtime permissions unchanged. + } else { + // For modern apps keep runtime permissions unchanged. grant = GRANT_RUNTIME; } } break; @@ -7871,7 +7876,7 @@ public class PackageManagerService extends IPackageManager.Stub { switch (grant) { case GRANT_INSTALL: { // Revoke this as runtime permission to handle the case of - // a runtime permssion being downgraded to an install one. + // a runtime permission being downgraded to an install one. for (int userId : UserManagerService.getInstance().getUserIds()) { if (origPermissions.getRuntimePermissionState( bp.name, userId) != null) { @@ -7902,26 +7907,20 @@ public class PackageManagerService extends IPackageManager.Stub { case GRANT_RUNTIME: { // Grant previously granted runtime permissions. for (int userId : UserManagerService.getInstance().getUserIds()) { + PermissionState permissionState = origPermissions + .getRuntimePermissionState(bp.name, userId); + final int flags = permissionState != null + ? permissionState.getFlags() : 0; if (origPermissions.hasRuntimePermission(bp.name, userId)) { - PermissionState permissionState = origPermissions - .getRuntimePermissionState(bp.name, userId); - final int flags = permissionState.getFlags(); if (permissionsState.grantRuntimePermission(bp, userId) == PermissionsState.PERMISSION_OPERATION_FAILURE) { // If we cannot put the permission as it was, we have to write. changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); - } else { - // System components not only get the permissions but - // they are also fixed, so nothing can change that. - final int newFlags = !isSystemComponentOrPersistentPrivApp(pkg) - ? flags - : flags | PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; - // Propagate the permission flags. - permissionsState.updatePermissionFlags(bp, userId, - newFlags, newFlags); } } + // Propagate the permission flags. + permissionsState.updatePermissionFlags(bp, userId, flags, flags); } } break; @@ -7931,25 +7930,23 @@ public class PackageManagerService extends IPackageManager.Stub { .getInstallPermissionState(bp.name); final int flags = permissionState != null ? permissionState.getFlags() : 0; - origPermissions.revokeInstallPermission(bp); - // We will be transferring the permission flags, so clear them. - origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL, - PackageManager.MASK_PERMISSION_FLAGS, 0); + if (origPermissions.revokeInstallPermission(bp) + != PermissionsState.PERMISSION_OPERATION_FAILURE) { + // We will be transferring the permission flags, so clear them. + origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL, + PackageManager.MASK_PERMISSION_FLAGS, 0); + changedInstallPermission = true; + } // If the permission is not to be promoted to runtime we ignore it and // also its other flags as they are not applicable to install permissions. if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) { - for (int userId : upgradeUserIds) { + for (int userId : currentUserIds) { if (permissionsState.grantRuntimePermission(bp, userId) != PermissionsState.PERMISSION_OPERATION_FAILURE) { - // System components not only get the permissions but - // they are also fixed so nothing can change that. - final int newFlags = !isSystemComponentOrPersistentPrivApp(pkg) - ? flags - : flags | PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; // Transfer the permission flags. permissionsState.updatePermissionFlags(bp, userId, - newFlags, newFlags); + flags, flags); // If we granted the permission, we have to write. changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); @@ -8001,11 +7998,9 @@ public class PackageManagerService extends IPackageManager.Stub { ps.installPermissionsFixed = true; } - ps.setPermissionsUpdatedForUserIds(currentUserIds); - // Persist the runtime permissions state for users with changes. for (int userId : changedRuntimePermissionUserIds) { - mSettings.writeRuntimePermissionsForUserLPr(userId, true); + mSettings.writeRuntimePermissionsForUserLPr(userId, false); } } @@ -8254,6 +8249,7 @@ public class PackageManagerService extends IPackageManager.Stub { } else { res.icon = info.icon; } + res.iconResourceId = info.icon; res.system = res.activityInfo.applicationInfo.isSystemApp(); return res; } @@ -11881,13 +11877,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - private boolean isSystemComponentOrPersistentPrivApp(PackageParser.Package pkg) { - return UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID - || ((pkg.applicationInfo.privateFlags - & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0 - && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0); - } - private static boolean isMultiArch(PackageSetting ps) { return (ps.pkgFlags & ApplicationInfo.FLAG_MULTIARCH) != 0; } @@ -12500,6 +12489,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (clearPackagePreferredActivitiesLPw(packageName, removeUser)) { scheduleWritePackageRestrictionsLocked(removeUser); } + revokeRuntimePermissionsAndClearAllFlagsLocked(ps.getPermissionsState(), + removeUser); } return true; } @@ -12706,17 +12697,44 @@ public class PackageManagerService extends IPackageManager.Stub { | PackageManager.FLAG_PERMISSION_USER_FIXED | PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE; + revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId, userSetFlags); + } + + /** + * Revokes granted runtime permissions and clears all flags. + * + * @param permissionsState The permission state to reset. + * @param userId The device user for which to do a reset. + */ + private void revokeRuntimePermissionsAndClearAllFlagsLocked( + PermissionsState permissionsState, int userId) { + revokeRuntimePermissionsAndClearFlagsLocked(permissionsState, userId, + PackageManager.MASK_PERMISSION_FLAGS); + } + + /** + * Revokes granted runtime permissions and clears certain flags. + * + * @param permissionsState The permission state to reset. + * @param userId The device user for which to do a reset. + * @param flags The flags that is going to be reset. + */ + private void revokeRuntimePermissionsAndClearFlagsLocked( + PermissionsState permissionsState, int userId, int flags) { boolean needsWrite = false; for (PermissionState state : permissionsState.getRuntimePermissionStates(userId)) { BasePermission bp = mSettings.mPermissions.get(state.getName()); if (bp != null) { permissionsState.revokeRuntimePermission(bp, userId); - permissionsState.updatePermissionFlags(bp, userId, userSetFlags, 0); + permissionsState.updatePermissionFlags(bp, userId, flags, 0); needsWrite = true; } } + // Ensure default permissions are never cleared. + mDefaultPermissionPolicy.grantDefaultPermissions(userId); + if (needsWrite) { mSettings.writeRuntimePermissionsForUserLPr(userId, true); } @@ -13680,6 +13698,14 @@ public class PackageManagerService extends IPackageManager.Stub { } sUserManager.systemReady(); + // If we upgraded grant all default permissions before kicking off. + if (isFirstBoot() || (CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE && mIsUpgrade)) { + updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL); + for (int userId : UserManagerService.getInstance().getUserIds()) { + mDefaultPermissionPolicy.grantDefaultPermissions(userId); + } + } + // Kick off any messages waiting for system ready if (mPostSystemReadyMessages != null) { for (Message msg : mPostSystemReadyMessages) { @@ -14091,7 +14117,9 @@ public class PackageManagerService extends IPackageManager.Stub { } } - if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) { + if (!checkin + && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED) + && packageName == null) { pw.println(); int count = mSettings.mPackages.size(); if (count == 0) { @@ -15067,9 +15095,16 @@ public class PackageManagerService extends IPackageManager.Stub { } } - void newUserCreatedLILPw(int userHandle) { - // Adding a user requires updating runtime permissions for system apps. - updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL); + void newUserCreatedLILPw(final int userHandle) { + // We cannot grant the default permissions with a lock held as + // we query providers from other components for default handlers + // such as enabled IMEs, etc. + mHandler.post(new Runnable() { + @Override + public void run() { + mDefaultPermissionPolicy.grantDefaultPermissions(userHandle); + } + }); } @Override @@ -15421,4 +15456,27 @@ public class PackageManagerService extends IPackageManager.Stub { } } } + + private class PackageManagerInternalImpl extends PackageManagerInternal { + @Override + public void setLocationPackagesProvider(PackagesProvider provider) { + synchronized (mPackages) { + mDefaultPermissionPolicy.setLocationPackagesProviderLPw(provider); + } + } + + @Override + public void setImePackagesProvider(PackagesProvider provider) { + synchronized (mPackages) { + mDefaultPermissionPolicy.setImePackagesProviderLPr(provider); + } + } + + @Override + public void setVoiceInteractionPackagesProvider(PackagesProvider provider) { + synchronized (mPackages) { + mDefaultPermissionPolicy.setVoiceInteractionPackagesProviderLPw(provider); + } + } + } } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index f62c00c..6f46f69 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -24,7 +24,6 @@ import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageUserState; import android.os.storage.VolumeInfo; -import android.text.TextUtils; import android.util.ArraySet; import android.util.SparseArray; @@ -223,7 +222,6 @@ abstract class PackageSettingBase extends SettingBase { * Make a shallow copy of this package settings. */ public void copyFrom(PackageSettingBase base) { - setPermissionsUpdatedForUserIds(base.getPermissionsUpdatedForUserIds()); mPermissionsState.copyFrom(base.mPermissionsState); primaryCpuAbiString = base.primaryCpuAbiString; secondaryCpuAbiString = base.secondaryCpuAbiString; diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java index c35258a..5cf92a9 100644 --- a/services/core/java/com/android/server/pm/SettingBase.java +++ b/services/core/java/com/android/server/pm/SettingBase.java @@ -18,16 +18,11 @@ package com.android.server.pm; import android.content.pm.ApplicationInfo; -import java.util.Arrays; - abstract class SettingBase { - private static final int[] USERS_NONE = new int[0]; - int pkgFlags; int pkgPrivateFlags; protected final PermissionsState mPermissionsState; - private int[] mPermissionsUpdatedForUserIds = USERS_NONE; SettingBase(int pkgFlags, int pkgPrivateFlags) { setFlags(pkgFlags); @@ -39,29 +34,12 @@ abstract class SettingBase { pkgFlags = base.pkgFlags; pkgPrivateFlags = base.pkgPrivateFlags; mPermissionsState = new PermissionsState(base.mPermissionsState); - setPermissionsUpdatedForUserIds(base.mPermissionsUpdatedForUserIds); } public PermissionsState getPermissionsState() { return mPermissionsState; } - public int[] getPermissionsUpdatedForUserIds() { - return mPermissionsUpdatedForUserIds; - } - - public void setPermissionsUpdatedForUserIds(int[] userIds) { - if (Arrays.equals(mPermissionsUpdatedForUserIds, userIds)) { - return; - } - - if (userIds == USERS_NONE) { - mPermissionsUpdatedForUserIds = userIds; - } else { - mPermissionsUpdatedForUserIds = Arrays.copyOf(userIds, userIds.length); - } - } - void setFlags(int pkgFlags) { this.pkgFlags = pkgFlags & (ApplicationInfo.FLAG_SYSTEM diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index cd50946..6415343 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -1139,17 +1139,6 @@ final class Settings { return new File(userDir, RUNTIME_PERMISSIONS_FILE_NAME); } - boolean isFirstRuntimePermissionsBoot() { - return !getUserRuntimePermissionsFile(UserHandle.USER_OWNER).exists(); - } - - void deleteRuntimePermissionsFiles() { - for (int userId : UserManagerService.getInstance().getUserIds()) { - File file = getUserRuntimePermissionsFile(userId); - file.delete(); - } - } - private File getUserPackagesStateBackupFile(int userId) { return new File(Environment.getUserSystemDirectory(userId), "package-restrictions-backup.xml"); @@ -2098,7 +2087,7 @@ final class Settings { } final ApplicationInfo ai = pkg.pkg.applicationInfo; - final String dataPath = ai.dataDir; + final String dataPath = new File(ai.dataDir).getCanonicalPath(); final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; final int[] gids = pkg.getPermissionsState().computeGids(userIds); @@ -2466,6 +2455,22 @@ final class Settings { } catch (NumberFormatException e) { } mFingerprint = parser.getAttributeValue(null, "fingerprint"); + + // If the build is setup to drop runtime permissions + // on update drop the files before loading them. + if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) { + if (!Build.FINGERPRINT.equals(mFingerprint)) { + if (users == null) { + mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( + UserHandle.USER_OWNER); + } else { + for (UserInfo user : users) { + mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile( + user.id); + } + } + } + } } else if (tagName.equals("database-version")) { mInternalDatabaseVersion = mExternalDatabaseVersion = 0; try { @@ -2554,15 +2559,21 @@ final class Settings { } else { if (users == null) { readPackageRestrictionsLPr(0); - mRuntimePermissionsPersistence.readStateForUserSyncLPr(UserHandle.USER_OWNER); } else { for (UserInfo user : users) { readPackageRestrictionsLPr(user.id); - mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id); } } } + if (users == null) { + mRuntimePermissionsPersistence.readStateForUserSyncLPr(UserHandle.USER_OWNER); + } else { + for (UserInfo user : users) { + mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id); + } + } + /* * Make sure all the updated system packages have their shared users * associated with them. @@ -3056,18 +3067,6 @@ final class Settings { } } - // We keep track for which users we granted permissions to be able - // to grant runtime permissions to system apps for newly appeared - // users or newly appeared system apps. If we supported runtime - // permissions during the previous boot, then we already granted - // permissions for all device users. In such a case we set the users - // for which we granted permissions to avoid clobbering of runtime - // permissions we granted to system apps but the user revoked later. - if (!isFirstRuntimePermissionsBoot()) { - final int[] userIds = UserManagerService.getInstance().getUserIds(); - ps.setPermissionsUpdatedForUserIds(userIds); - } - mDisabledSysPackages.put(name, ps); } @@ -3364,18 +3363,6 @@ final class Settings { XmlUtils.skipCurrentTag(parser); } } - - // We keep track for which users we granted permissions to be able - // to grant runtime permissions to system apps for newly appeared - // users or newly appeared system apps. If we supported runtime - // permissions during the previous boot, then we already granted - // permissions for all device users. In such a case we set the users - // for which we granted permissions to avoid clobbering of runtime - // permissions we granted to system apps but the user revoked later. - if (!isFirstRuntimePermissionsBoot()) { - final int[] userIds = UserManagerService.getInstance().getUserIds(); - packageSetting.setPermissionsUpdatedForUserIds(userIds); - } } else { XmlUtils.skipCurrentTag(parser); } @@ -3493,18 +3480,6 @@ final class Settings { XmlUtils.skipCurrentTag(parser); } } - - // We keep track for which users we granted permissions to be able - // to grant runtime permissions to system apps for newly appeared - // users or newly appeared system apps. If we supported runtime - // permissions during the previous boot, then we already granted - // permissions for all device users. In such a case we set the users - // for which we granted permissions to avoid clobbering of runtime - // permissions we granted to system apps but the user revoked later. - if (!isFirstRuntimePermissionsBoot()) { - final int[] userIds = UserManagerService.getInstance().getUserIds(); - su.setPermissionsUpdatedForUserIds(userIds); - } } else { XmlUtils.skipCurrentTag(parser); } @@ -4364,8 +4339,6 @@ final class Settings { Slog.wtf(PackageManagerService.TAG, "Failed to write settings, restoring backup", t); destination.failWrite(out); - throw new IllegalStateException("Failed to write runtime permissions," - + " restoring backup", t); } finally { IoUtils.closeQuietly(out); } @@ -4397,6 +4370,10 @@ final class Settings { } } + public void deleteUserRuntimePermissionsFile(int userId) { + getUserRuntimePermissionsFile(userId).delete(); + } + public void readStateForUserSyncLPr(int userId) { File permissionsFile = getUserRuntimePermissionsFile(userId); if (!permissionsFile.exists()) { @@ -4489,22 +4466,12 @@ final class Settings { ? Integer.parseInt(flagsStr, 16) : 0; if (granted) { - if (permissionsState.grantRuntimePermission(bp, userId) == - PermissionsState.PERMISSION_OPERATION_FAILURE) { - Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name); - } else { - permissionsState.updatePermissionFlags(bp, userId, + permissionsState.grantRuntimePermission(bp, userId); + permissionsState.updatePermissionFlags(bp, userId, PackageManager.MASK_PERMISSION_FLAGS, flags); - - } } else { - if (permissionsState.revokeRuntimePermission(bp, userId) == - PermissionsState.PERMISSION_OPERATION_FAILURE) { - Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name); - } else { - permissionsState.updatePermissionFlags(bp, userId, - PackageManager.MASK_PERMISSION_FLAGS, flags); - } + permissionsState.updatePermissionFlags(bp, userId, + PackageManager.MASK_PERMISSION_FLAGS, flags); } } break; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 6fb9a5c..bd545df 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -56,6 +56,7 @@ import android.os.Debug; import android.os.FactoryTest; import android.os.Handler; import android.os.IBinder; +import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; import android.os.Messenger; @@ -2734,6 +2735,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!keyguardOn) { voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); } else { + IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); + if (dic != null) { + try { + dic.exitIdle("voice-search"); + } catch (RemoteException e) { + } + } voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true); } @@ -5192,6 +5201,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { } void launchVoiceAssistWithWakeLock(boolean keyguardActive) { + IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( + ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); + if (dic != null) { + try { + dic.exitIdle("voice-search"); + } catch (RemoteException e) { + } + } Intent voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 5a391f4..d21c6d2 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -95,6 +95,9 @@ final class Notifier { private final Intent mScreenOffIntent; private final Intent mScreenBrightnessBoostIntent; + // True if the device should suspend when the screen is off due to proximity. + private final boolean mSuspendWhenScreenOffDueToProximityConfig; + // The current interactive state. This is set as soon as an interactive state // transition begins so as to capture the reason that it happened. At some point // this state will propagate to the pending state then eventually to the @@ -143,6 +146,9 @@ final class Notifier { mScreenBrightnessBoostIntent.addFlags( Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); + mSuspendWhenScreenOffDueToProximityConfig = context.getResources().getBoolean( + com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity); + // Initialize interactive state for battery stats. try { mBatteryStats.noteInteractive(true); @@ -161,22 +167,24 @@ final class Notifier { + ", workSource=" + workSource); } - try { - final int monitorType = getBatteryStatsWakeLockMonitorType(flags); - boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0 - && ownerUid == Process.SYSTEM_UID; - if (workSource != null) { - mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, historyTag, - monitorType, unimportantForLogging); - } else { - mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag, - monitorType, unimportantForLogging); - // XXX need to deal with disabled operations. - mAppOps.startOperation(AppOpsManager.getToken(mAppOps), - AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); + final int monitorType = getBatteryStatsWakeLockMonitorType(flags); + if (monitorType >= 0) { + try { + final boolean unimportantForLogging = ownerUid == Process.SYSTEM_UID + && (flags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0; + if (workSource != null) { + mBatteryStats.noteStartWakelockFromSource(workSource, ownerPid, tag, + historyTag, monitorType, unimportantForLogging); + } else { + mBatteryStats.noteStartWakelock(ownerUid, ownerPid, tag, historyTag, + monitorType, unimportantForLogging); + // XXX need to deal with disabled operations. + mAppOps.startOperation(AppOpsManager.getToken(mAppOps), + AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); + } + } catch (RemoteException ex) { + // Ignore } - } catch (RemoteException ex) { - // Ignore } } @@ -188,17 +196,19 @@ final class Notifier { int newFlags, String newTag, String newPackageName, int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) { - if (workSource != null && newWorkSource != null) { - final int monitorType = getBatteryStatsWakeLockMonitorType(flags); - final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags); - boolean unimportantForLogging = (newFlags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0 - && newOwnerUid == Process.SYSTEM_UID; + final int monitorType = getBatteryStatsWakeLockMonitorType(flags); + final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags); + if (workSource != null && newWorkSource != null + && monitorType >= 0 && newMonitorType >= 0) { if (DEBUG) { Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag + "\", packageName=" + newPackageName + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid + ", workSource=" + newWorkSource); } + + final boolean unimportantForLogging = newOwnerUid == Process.SYSTEM_UID + && (newFlags & PowerManager.UNIMPORTANT_FOR_LOGGING) != 0; try { mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, historyTag, monitorType, newWorkSource, newOwnerPid, newTag, newHistoryTag, @@ -225,28 +235,50 @@ final class Notifier { + ", workSource=" + workSource); } - try { - final int monitorType = getBatteryStatsWakeLockMonitorType(flags); - if (workSource != null) { - mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, historyTag, - monitorType); - } else { - mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, historyTag, monitorType); - mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), - AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); + final int monitorType = getBatteryStatsWakeLockMonitorType(flags); + if (monitorType >= 0) { + try { + if (workSource != null) { + mBatteryStats.noteStopWakelockFromSource(workSource, ownerPid, tag, + historyTag, monitorType); + } else { + mBatteryStats.noteStopWakelock(ownerUid, ownerPid, tag, + historyTag, monitorType); + mAppOps.finishOperation(AppOpsManager.getToken(mAppOps), + AppOpsManager.OP_WAKE_LOCK, ownerUid, packageName); + } + } catch (RemoteException ex) { + // Ignore } - } catch (RemoteException ex) { - // Ignore } } - private static int getBatteryStatsWakeLockMonitorType(int flags) { + private int getBatteryStatsWakeLockMonitorType(int flags) { switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) { case PowerManager.PARTIAL_WAKE_LOCK: + return BatteryStats.WAKE_TYPE_PARTIAL; + + case PowerManager.SCREEN_DIM_WAKE_LOCK: + case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: + return BatteryStats.WAKE_TYPE_FULL; + case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: + if (mSuspendWhenScreenOffDueToProximityConfig) { + return -1; + } return BatteryStats.WAKE_TYPE_PARTIAL; + + case PowerManager.DRAW_WAKE_LOCK: + return BatteryStats.WAKE_TYPE_DRAW; + + case PowerManager.DOZE_WAKE_LOCK: + // Doze wake locks are an internal implementation detail of the + // communication between dream manager service and power manager + // service. They have no additive battery impact. + return -1; + default: - return BatteryStats.WAKE_TYPE_FULL; + return -1; } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 3af97db..51bb36f 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -970,6 +970,7 @@ public final class PowerManagerService extends SystemService case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: case PowerManager.FULL_WAKE_LOCK: case PowerManager.DOZE_WAKE_LOCK: + case PowerManager.DRAW_WAKE_LOCK: return true; case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 58c3ea1..4692403 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -24,4 +24,5 @@ public interface StatusBarManagerInternal { void notificationLightPulse(int argb, int onMillis, int offMillis); void notificationLightOff(); void showScreenPinningRequest(); + void showAssistDisclosure(); } diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 5669f30..a754379 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -154,6 +154,16 @@ public class StatusBarManagerService extends IStatusBarService.Stub { } } } + + @Override + public void showAssistDisclosure() { + if (mBar != null) { + try { + mBar.showAssistDisclosure(); + } catch (RemoteException e) { + } + } + } }; // ================================================================================ diff --git a/services/core/java/com/android/server/tv/PersistentDataStore.java b/services/core/java/com/android/server/tv/PersistentDataStore.java index f9b5b9a..f6b1705 100644 --- a/services/core/java/com/android/server/tv/PersistentDataStore.java +++ b/services/core/java/com/android/server/tv/PersistentDataStore.java @@ -111,8 +111,8 @@ final class PersistentDataStore { public boolean isRatingBlocked(TvContentRating rating) { loadIfNeeded(); synchronized (mBlockedRatings) { - for (TvContentRating blcokedRating : mBlockedRatings) { - if (rating.contains(blcokedRating)) { + for (TvContentRating blockedRating : mBlockedRatings) { + if (rating.contains(blockedRating)) { return true; } } diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java index de271b8..a035826 100644 --- a/services/core/java/com/android/server/tv/TvInputHal.java +++ b/services/core/java/com/android/server/tv/TvInputHal.java @@ -47,11 +47,10 @@ final class TvInputHal implements Handler.Callback { public static final int EVENT_FIRST_FRAME_CAPTURED = 4; public interface Callback { - public void onDeviceAvailable( - TvInputHardwareInfo info, TvStreamConfig[] configs); - public void onDeviceUnavailable(int deviceId); - public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs); - public void onFirstFrameCaptured(int deviceId, int streamId); + void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs); + void onDeviceUnavailable(int deviceId); + void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs); + void onFirstFrameCaptured(int deviceId, int streamId); } private native long nativeOpen(MessageQueue queue); @@ -152,7 +151,7 @@ final class TvInputHal implements Handler.Callback { // Handler.Callback implementation - private final Queue<Message> mPendingMessageQueue = new LinkedList<Message>(); + private final Queue<Message> mPendingMessageQueue = new LinkedList<>(); @Override public boolean handleMessage(Message msg) { diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index 444969f..7f4c42b 100644 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -252,13 +252,8 @@ class TvInputHardwareManager implements TvInputHal.Callback { Connection connection, int callingUid, int resolvedUserId) { Integer connectionCallingUid = connection.getCallingUidLocked(); Integer connectionResolvedUserId = connection.getResolvedUserIdLocked(); - if (connectionCallingUid == null || connectionResolvedUserId == null) { - return true; - } - if (connectionCallingUid != callingUid || connectionResolvedUserId != resolvedUserId) { - return true; - } - return false; + return connectionCallingUid == null || connectionResolvedUserId == null + || connectionCallingUid != callingUid || connectionResolvedUserId != resolvedUserId; } private int convertConnectedToState(boolean connected) { @@ -303,7 +298,6 @@ class TvInputHardwareManager implements TvInputHal.Callback { mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, convertConnectedToState(connection.getConfigsLocked().length > 0), 0, info.getId()).sendToTarget(); - return; } } } @@ -435,7 +429,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { */ public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int callingUid, int resolvedUserId) { - List<TvStreamConfig> configsList = new ArrayList<TvStreamConfig>(); + List<TvStreamConfig> configsList = new ArrayList<>(); synchronized (mLock) { int deviceId = findDeviceIdForInputIdLocked(inputId); if (deviceId < 0) { @@ -508,25 +502,31 @@ class TvInputHardwareManager implements TvInputHal.Callback { private void handleVolumeChange(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) { - int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); - if (streamType != AudioManager.STREAM_MUSIC) { - return; + switch (action) { + case AudioManager.VOLUME_CHANGED_ACTION: { + int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); + if (streamType != AudioManager.STREAM_MUSIC) { + return; + } + int index = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); + if (index == mCurrentIndex) { + return; + } + mCurrentIndex = index; + break; } - int index = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); - if (index == mCurrentIndex) { - return; + case AudioManager.STREAM_MUTE_CHANGED_ACTION: { + int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); + if (streamType != AudioManager.STREAM_MUSIC) { + return; + } + // volume index will be updated at onMediaStreamVolumeChanged() through + // updateVolume(). + break; } - mCurrentIndex = index; - } else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) { - int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); - if (streamType != AudioManager.STREAM_MUSIC) { + default: + Slog.w(TAG, "Unrecognized intent: " + intent); return; - } - // volume index will be updated at onMediaStreamVolumeChanged() through updateVolume(). - } else { - Slog.w(TAG, "Unrecognized intent: " + intent); - return; } synchronized (mLock) { for (int i = 0; i < mConnections.size(); ++i) { @@ -691,7 +691,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { private void findAudioSinkFromAudioPolicy(List<AudioDevicePort> sinks) { sinks.clear(); - ArrayList<AudioDevicePort> devicePorts = new ArrayList<AudioDevicePort>(); + ArrayList<AudioDevicePort> devicePorts = new ArrayList<>(); if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) { return; } @@ -707,7 +707,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { if (type == AudioManager.DEVICE_NONE) { return null; } - ArrayList<AudioDevicePort> devicePorts = new ArrayList<AudioDevicePort>(); + ArrayList<AudioDevicePort> devicePorts = new ArrayList<>(); if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) { return null; } @@ -900,7 +900,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { mAudioManager.createAudioPatch( audioPatchArray, new AudioPortConfig[] { sourceConfig }, - sinkConfigs.toArray(new AudioPortConfig[0])); + sinkConfigs.toArray(new AudioPortConfig[sinkConfigs.size()])); mAudioPatch = audioPatchArray[0]; if (sourceGainConfig != null) { mAudioManager.setAudioPortGain(mAudioSource, sourceGainConfig); @@ -1027,12 +1027,12 @@ class TvInputHardwareManager implements TvInputHal.Callback { } interface Listener { - public void onStateChanged(String inputId, int state); - public void onHardwareDeviceAdded(TvInputHardwareInfo info); - public void onHardwareDeviceRemoved(TvInputHardwareInfo info); - public void onHdmiDeviceAdded(HdmiDeviceInfo device); - public void onHdmiDeviceRemoved(HdmiDeviceInfo device); - public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo device); + void onStateChanged(String inputId, int state); + void onHardwareDeviceAdded(TvInputHardwareInfo info); + void onHardwareDeviceRemoved(TvInputHardwareInfo info); + void onHdmiDeviceAdded(HdmiDeviceInfo device); + void onHdmiDeviceRemoved(HdmiDeviceInfo device); + void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo device); } private class ListenerHandler extends Handler { @@ -1074,7 +1074,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { } case HDMI_DEVICE_UPDATED: { HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj; - String inputId = null; + String inputId; synchronized (mLock) { inputId = mHdmiInputIdMap.get(info.getId()); } diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 4895d12..f5c5861 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -121,7 +121,7 @@ public final class TvInputManagerService extends SystemService { private int mCurrentUserId = UserHandle.USER_OWNER; // A map from user id to UserState. - private final SparseArray<UserState> mUserStates = new SparseArray<UserState>(); + private final SparseArray<UserState> mUserStates = new SparseArray<>(); private final WatchLogHandler mWatchLogHandler; @@ -231,8 +231,7 @@ public final class TvInputManagerService extends SystemService { } } - ArrayList<ContentProviderOperation> operations = - new ArrayList<ContentProviderOperation>(); + ArrayList<ContentProviderOperation> operations = new ArrayList<>(); String selection = TvContract.BaseTvColumns.COLUMN_PACKAGE_NAME + "=?"; String[] selectionArgs = { packageName }; @@ -292,7 +291,7 @@ public final class TvInputManagerService extends SystemService { new Intent(TvInputService.SERVICE_INTERFACE), PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, userId); - List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); + List<TvInputInfo> inputList = new ArrayList<>(); for (ResolveInfo ri : services) { ServiceInfo si = ri.serviceInfo; if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) { @@ -325,7 +324,7 @@ public final class TvInputManagerService extends SystemService { userState.packageSet.add(si.packageName); } - Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); + Map<String, TvInputState> inputMap = new HashMap<>(); for (TvInputInfo info : inputList) { if (DEBUG) { Slog.d(TAG, "add " + info.getId()); @@ -777,7 +776,7 @@ public final class TvInputManagerService extends SystemService { try { synchronized (mLock) { UserState userState = getUserStateLocked(resolvedUserId); - List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); + List<TvInputInfo> inputList = new ArrayList<>(); for (TvInputState state : userState.inputMap.values()) { inputList.add(state.info); } @@ -934,7 +933,7 @@ public final class TvInputManagerService extends SystemService { try { synchronized (mLock) { UserState userState = getUserStateLocked(resolvedUserId); - List<String> ratings = new ArrayList<String>(); + List<String> ratings = new ArrayList<>(); for (TvContentRating rating : userState.persistentDataStore.getBlockedRatings()) { ratings.add(rating.flattenToString()); @@ -1012,7 +1011,7 @@ public final class TvInputManagerService extends SystemService { userState.serviceStateMap.put(info.getComponent(), serviceState); } // Send a null token immediately while reconnecting. - if (serviceState.reconnecting == true) { + if (serviceState.reconnecting) { sendSessionTokenToClientLocked(client, inputId, null, null, seq); return; } @@ -1210,7 +1209,6 @@ public final class TvInputManagerService extends SystemService { .sendToTarget(); } catch (RemoteException | SessionNotFoundException e) { Slog.e(TAG, "error in tune", e); - return; } } } finally { @@ -1658,10 +1656,9 @@ public final class TvInputManagerService extends SystemService { UserState userState = getUserStateLocked(resolvedUserId); if (userState.sessionStateMap.size() == 1) { return true; - } - else if (userState.sessionStateMap.size() == 2) { + } else if (userState.sessionStateMap.size() == 2) { SessionState[] sessionStates = userState.sessionStateMap.values().toArray( - new SessionState[0]); + new SessionState[2]); // Check if there is a wrapper input. if (sessionStates[0].hardwareSessionToken != null || sessionStates[1].hardwareSessionToken != null) { @@ -1800,30 +1797,26 @@ public final class TvInputManagerService extends SystemService { private static final class UserState { // A mapping from the TV input id to its TvInputState. - private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>(); + private Map<String, TvInputState> inputMap = new HashMap<>(); // A set of all TV input packages. - private final Set<String> packageSet = new HashSet<String>(); + private final Set<String> packageSet = new HashSet<>(); // A list of all TV content rating systems defined. private final List<TvContentRatingSystemInfo> - contentRatingSystemList = new ArrayList<TvContentRatingSystemInfo>(); + contentRatingSystemList = new ArrayList<>(); // A mapping from the token of a client to its state. - private final Map<IBinder, ClientState> clientStateMap = - new HashMap<IBinder, ClientState>(); + private final Map<IBinder, ClientState> clientStateMap = new HashMap<>(); // A mapping from the name of a TV input service to its state. - private final Map<ComponentName, ServiceState> serviceStateMap = - new HashMap<ComponentName, ServiceState>(); + private final Map<ComponentName, ServiceState> serviceStateMap = new HashMap<>(); // A mapping from the token of a TV input session to its state. - private final Map<IBinder, SessionState> sessionStateMap = - new HashMap<IBinder, SessionState>(); + private final Map<IBinder, SessionState> sessionStateMap = new HashMap<>(); // A set of callbacks. - private final Set<ITvInputManagerCallback> callbackSet = - new HashSet<ITvInputManagerCallback>(); + private final Set<ITvInputManagerCallback> callbackSet = new HashSet<>(); // The token of a "main" TV input session. private IBinder mainSessionToken = null; @@ -1838,7 +1831,7 @@ public final class TvInputManagerService extends SystemService { } private final class ClientState implements IBinder.DeathRecipient { - private final List<IBinder> sessionTokens = new ArrayList<IBinder>(); + private final List<IBinder> sessionTokens = new ArrayList<>(); private IBinder clientToken; private final int userId; @@ -1871,11 +1864,11 @@ public final class TvInputManagerService extends SystemService { } private final class ServiceState { - private final List<IBinder> sessionTokens = new ArrayList<IBinder>(); + private final List<IBinder> sessionTokens = new ArrayList<>(); private final ServiceConnection connection; private final ComponentName component; private final boolean isHardware; - private final List<TvInputInfo> inputList = new ArrayList<TvInputInfo>(); + private final List<TvInputInfo> inputList = new ArrayList<>(); private ITvInputService service; private ServiceCallback callback; @@ -2125,13 +2118,13 @@ public final class TvInputManagerService extends SystemService { } @Override - public void onSessionCreated(ITvInputSession session, IBinder harewareSessionToken) { + public void onSessionCreated(ITvInputSession session, IBinder hardwareSessionToken) { if (DEBUG) { Slog.d(TAG, "onSessionCreated(inputId=" + mSessionState.info.getId() + ")"); } synchronized (mLock) { mSessionState.session = session; - mSessionState.hardwareSessionToken = harewareSessionToken; + mSessionState.hardwareSessionToken = hardwareSessionToken; if (session != null && addSessionTokenToClientStateLocked(session)) { sendSessionTokenToClientLocked(mSessionState.client, mSessionState.info.getId(), mSessionState.sessionToken, mChannels[0], @@ -2559,7 +2552,7 @@ public final class TvInputManagerService extends SystemService { @Override public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo deviceInfo) { synchronized (mLock) { - Integer state = null; + Integer state; switch (deviceInfo.getDevicePowerStatus()) { case HdmiControlManager.POWER_STATUS_ON: state = INPUT_STATE_CONNECTED; @@ -2575,7 +2568,7 @@ public final class TvInputManagerService extends SystemService { break; } if (state != null) { - setStateLocked(inputId, state.intValue(), mCurrentUserId); + setStateLocked(inputId, state, mCurrentUserId); } } } diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java index ac79b36..d4c5f87 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java @@ -40,8 +40,6 @@ public class WebViewUpdateService extends SystemService { private boolean mRelroReady32Bit = false; private boolean mRelroReady64Bit = false; - private String oldWebViewPackageName = null; - private BroadcastReceiver mWebViewUpdatedReceiver; public WebViewUpdateService(Context context) { @@ -53,22 +51,9 @@ public class WebViewUpdateService extends SystemService { mWebViewUpdatedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - - for (String packageName : WebViewFactory.getWebViewPackageNames()) { - String webviewPackage = "package:" + packageName; - - if (webviewPackage.equals(intent.getDataString())) { - String usedPackageName = - WebViewFactory.findPreferredWebViewPackage().packageName; - // Only trigger update actions if the updated package is the one that - // will be used, or the one that was in use before the update. - if (packageName.equals(usedPackageName) || - packageName.equals(oldWebViewPackageName)) { - onWebViewUpdateInstalled(); - oldWebViewPackageName = usedPackageName; - } - return; - } + String webviewPackage = "package:" + WebViewFactory.getWebViewPackageName(); + if (webviewPackage.equals(intent.getDataString())) { + onWebViewUpdateInstalled(); } } }; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 5064d8f..f1331e9 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1383,10 +1383,21 @@ class WindowStateAnimator { // Adjust for surface insets. final LayoutParams attrs = w.getAttrs(); - width += attrs.surfaceInsets.left + attrs.surfaceInsets.right; - height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom; - left -= attrs.surfaceInsets.left; - top -= attrs.surfaceInsets.top; + final int displayId = w.getDisplayId(); + float scale = 1.0f; + // Magnification is supported only for the default display. + if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) { + MagnificationSpec spec = + mService.mAccessibilityController.getMagnificationSpecForWindowLocked(w); + if (spec != null && !spec.isNop()) { + scale = spec.scale; + } + } + + width += scale * (attrs.surfaceInsets.left + attrs.surfaceInsets.right); + height += scale * (attrs.surfaceInsets.top + attrs.surfaceInsets.bottom); + left -= scale * attrs.surfaceInsets.left; + top -= scale * attrs.surfaceInsets.top; final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top; if (surfaceMoved) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 29c65db..76226b4 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -292,7 +292,7 @@ public final class SystemServer { private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); - mSystemContext.setTheme(android.R.style.Theme_Material_DayNight_DarkActionBar); + mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); } /** diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index b58c2e2..712db09 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -134,6 +134,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { private final NetworkInfo mNetworkInfo; private final NetworkCapabilities mNetworkCapabilities; private final Thread mThread; + private int mScore; private NetworkAgent mNetworkAgent; MockNetworkAgent(int transport) { @@ -142,13 +143,12 @@ public class ConnectivityServiceTest extends AndroidTestCase { mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); mNetworkCapabilities = new NetworkCapabilities(); mNetworkCapabilities.addTransportType(transport); - final int score; switch (transport) { case TRANSPORT_WIFI: - score = 60; + mScore = 60; break; case TRANSPORT_CELLULAR: - score = 50; + mScore = 50; break; default: throw new UnsupportedOperationException("unimplemented network type"); @@ -159,7 +159,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { Looper.prepare(); mNetworkAgent = new NetworkAgent(Looper.myLooper(), mServiceContext, "Mock" + typeName, mNetworkInfo, mNetworkCapabilities, - new LinkProperties(), score, new NetworkMisc()) { + new LinkProperties(), mScore, new NetworkMisc()) { public void unwanted() {} }; initComplete.open(); @@ -167,7 +167,12 @@ public class ConnectivityServiceTest extends AndroidTestCase { } }; mThread.start(); - initComplete.block(); + waitFor(initComplete); + } + + public void adjustScore(int change) { + mScore += change; + mNetworkAgent.sendNetworkScore(mScore); } /** @@ -209,7 +214,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { if (validated) { // Wait for network to validate. - validatedCv.block(); + waitFor(validatedCv); mNetworkCapabilities.addCapability(NET_CAPABILITY_INTERNET); mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); } @@ -330,6 +335,10 @@ public class ConnectivityServiceTest extends AndroidTestCase { public boolean get(); } + /** + * Wait up to 500ms for {@code criteria.get()} to become true, polling. + * Fails if 500ms goes by before {@code criteria.get()} to become true. + */ static private void waitFor(Criteria criteria) { int delays = 0; while (!criteria.get()) { @@ -341,6 +350,26 @@ public class ConnectivityServiceTest extends AndroidTestCase { } } + /** + * Wait up to 500ms for {@code conditonVariable} to open. + * Fails if 500ms goes by before {@code conditionVariable} opens. + */ + static private void waitFor(ConditionVariable conditionVariable) { + assertTrue(conditionVariable.block(500)); + } + + /** + * This should only be used to verify that nothing happens, in other words that no unexpected + * changes occur. It should never be used to wait for a specific positive signal to occur. + */ + private void shortSleep() { + // TODO: Instead of sleeping, instead wait for all message loops to idle. + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + } + @Override public void setUp() throws Exception { super.setUp(); @@ -431,7 +460,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // Test bringing up validated cellular. ConditionVariable cv = waitForConnectivityBroadcasts(1); mCellNetworkAgent.connect(true); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); assertEquals(2, mCm.getAllNetworks().length); assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || @@ -441,7 +470,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // Test bringing up validated WiFi. cv = waitForConnectivityBroadcasts(2); mWiFiNetworkAgent.connect(true); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); assertEquals(2, mCm.getAllNetworks().length); assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) || @@ -459,7 +488,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // Test WiFi disconnect. cv = waitForConnectivityBroadcasts(1); mWiFiNetworkAgent.disconnect(); - cv.block(); + waitFor(cv); verifyNoNetwork(); } @@ -469,38 +498,32 @@ public class ConnectivityServiceTest extends AndroidTestCase { mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); ConditionVariable cv = waitForConnectivityBroadcasts(1); mWiFiNetworkAgent.connect(false); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Test bringing up unvalidated cellular mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); mCellNetworkAgent.connect(false); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } + shortSleep(); verifyActiveNetwork(TRANSPORT_WIFI); // Test cellular disconnect. mCellNetworkAgent.disconnect(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } + shortSleep(); verifyActiveNetwork(TRANSPORT_WIFI); // Test bringing up validated cellular mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); cv = waitForConnectivityBroadcasts(2); mCellNetworkAgent.connect(true); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test cellular disconnect. cv = waitForConnectivityBroadcasts(2); mCellNetworkAgent.disconnect(); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Test WiFi disconnect. cv = waitForConnectivityBroadcasts(1); mWiFiNetworkAgent.disconnect(); - cv.block(); + waitFor(cv); verifyNoNetwork(); } @@ -510,27 +533,209 @@ public class ConnectivityServiceTest extends AndroidTestCase { mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); ConditionVariable cv = waitForConnectivityBroadcasts(1); mCellNetworkAgent.connect(false); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test bringing up unvalidated WiFi. mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); cv = waitForConnectivityBroadcasts(2); mWiFiNetworkAgent.connect(false); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_WIFI); // Test WiFi disconnect. cv = waitForConnectivityBroadcasts(2); mWiFiNetworkAgent.disconnect(); - cv.block(); + waitFor(cv); verifyActiveNetwork(TRANSPORT_CELLULAR); // Test cellular disconnect. cv = waitForConnectivityBroadcasts(1); mCellNetworkAgent.disconnect(); - cv.block(); + waitFor(cv); verifyNoNetwork(); } @LargeTest + public void testCellularOutscoresWeakWifi() throws Exception { + // Test bringing up validated cellular. + mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); + ConditionVariable cv = waitForConnectivityBroadcasts(1); + mCellNetworkAgent.connect(true); + waitFor(cv); + verifyActiveNetwork(TRANSPORT_CELLULAR); + // Test bringing up validated WiFi. + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + cv = waitForConnectivityBroadcasts(2); + mWiFiNetworkAgent.connect(true); + waitFor(cv); + verifyActiveNetwork(TRANSPORT_WIFI); + // Test WiFi getting really weak. + cv = waitForConnectivityBroadcasts(2); + mWiFiNetworkAgent.adjustScore(-11); + waitFor(cv); + verifyActiveNetwork(TRANSPORT_CELLULAR); + // Test WiFi restoring signal strength. + cv = waitForConnectivityBroadcasts(2); + mWiFiNetworkAgent.adjustScore(11); + waitFor(cv); + verifyActiveNetwork(TRANSPORT_WIFI); + mCellNetworkAgent.disconnect(); + mWiFiNetworkAgent.disconnect(); + } + + enum CallbackState { + NONE, + AVAILABLE, + LOSING, + LOST + } + + private class TestNetworkCallback extends NetworkCallback { + private final ConditionVariable mConditionVariable = new ConditionVariable(); + private CallbackState mLastCallback = CallbackState.NONE; + + public void onAvailable(Network network) { + assertEquals(CallbackState.NONE, mLastCallback); + mLastCallback = CallbackState.AVAILABLE; + mConditionVariable.open(); + } + + public void onLosing(Network network, int maxMsToLive) { + assertEquals(CallbackState.NONE, mLastCallback); + mLastCallback = CallbackState.LOSING; + mConditionVariable.open(); + } + + public void onLost(Network network) { + assertEquals(CallbackState.NONE, mLastCallback); + mLastCallback = CallbackState.LOST; + mConditionVariable.open(); + } + + ConditionVariable getConditionVariable() { + mLastCallback = CallbackState.NONE; + mConditionVariable.close(); + return mConditionVariable; + } + + CallbackState getLastCallback() { + return mLastCallback; + } + } + + @LargeTest + public void testStateChangeNetworkCallbacks() throws Exception { + final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); + final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback(); + final NetworkRequest wifiRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_WIFI).build(); + final NetworkRequest cellRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_CELLULAR).build(); + mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); + mCm.registerNetworkCallback(cellRequest, cellNetworkCallback); + + // Test unvalidated networks + ConditionVariable cellCv = cellNetworkCallback.getConditionVariable(); + ConditionVariable wifiCv = wifiNetworkCallback.getConditionVariable(); + ConditionVariable cv = waitForConnectivityBroadcasts(1); + mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(false); + waitFor(cellCv); + assertEquals(CallbackState.AVAILABLE, cellNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback()); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + waitFor(cv); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + // This should not trigger spurious onAvailable() callbacks, b/21762680. + mCellNetworkAgent.adjustScore(-1); + shortSleep(); + assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback()); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + cv = waitForConnectivityBroadcasts(2); + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(false); + waitFor(wifiCv); + assertEquals(CallbackState.AVAILABLE, wifiNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback()); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + waitFor(cv); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + cv = waitForConnectivityBroadcasts(2); + mWiFiNetworkAgent.disconnect(); + waitFor(wifiCv); + assertEquals(CallbackState.LOST, wifiNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback()); + waitFor(cv); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + cv = waitForConnectivityBroadcasts(1); + mCellNetworkAgent.disconnect(); + waitFor(cellCv); + assertEquals(CallbackState.LOST, cellNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback()); + waitFor(cv); + + // Test validated networks + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + // Our method for faking successful validation generates an additional callback, so wait + // for broadcast instead. + cv = waitForConnectivityBroadcasts(1); + mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + waitFor(cv); + waitFor(cellCv); + assertEquals(CallbackState.AVAILABLE, cellNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback()); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + // This should not trigger spurious onAvailable() callbacks, b/21762680. + mCellNetworkAgent.adjustScore(-1); + shortSleep(); + assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback()); + assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + // Our method for faking successful validation generates an additional callback, so wait + // for broadcast instead. + cv = waitForConnectivityBroadcasts(1); + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(true); + waitFor(cv); + waitFor(wifiCv); + assertEquals(CallbackState.AVAILABLE, wifiNetworkCallback.getLastCallback()); + waitFor(cellCv); + assertEquals(CallbackState.LOSING, cellNetworkCallback.getLastCallback()); + assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + mWiFiNetworkAgent.disconnect(); + waitFor(wifiCv); + assertEquals(CallbackState.LOST, wifiNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, cellNetworkCallback.getLastCallback()); + + cellCv = cellNetworkCallback.getConditionVariable(); + wifiCv = wifiNetworkCallback.getConditionVariable(); + mCellNetworkAgent.disconnect(); + waitFor(cellCv); + assertEquals(CallbackState.LOST, cellNetworkCallback.getLastCallback()); + assertEquals(CallbackState.NONE, wifiNetworkCallback.getLastCallback()); + } + + @LargeTest public void testNetworkFactoryRequests() throws Exception { NetworkCapabilities filter = new NetworkCapabilities(); filter.addCapability(NET_CAPABILITY_INTERNET); @@ -541,7 +746,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { testFactory.setScoreFilter(40); ConditionVariable cv = testFactory.getNetworkStartedCV(); testFactory.register(); - cv.block(); + waitFor(cv); assertEquals(1, testFactory.getMyRequestCount()); assertEquals(true, testFactory.getMyStartRequested()); @@ -550,10 +755,10 @@ public class ConnectivityServiceTest extends AndroidTestCase { cv = waitForConnectivityBroadcasts(1); ConditionVariable cvRelease = testFactory.getNetworkStoppedCV(); testAgent.connect(true); - cv.block(); + waitFor(cv); // part of the bringup makes another network request and then releases it // wait for the release - cvRelease.block(); + waitFor(cvRelease); assertEquals(false, testFactory.getMyStartRequested()); testFactory.waitForNetworkRequests(1); @@ -579,7 +784,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // drop the higher scored network cv = waitForConnectivityBroadcasts(1); testAgent.disconnect(); - cv.block(); + waitFor(cv); assertEquals(1, testFactory.getMyRequestCount()); assertEquals(true, testFactory.getMyStartRequested()); @@ -605,7 +810,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // // cv = waitForConnectivityBroadcasts(1); // mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget(); -// cv.block(); +// waitFor(cv); // // // verify that both routes were added // int mobileNetId = mMobile.tracker.getNetwork().netId; @@ -625,7 +830,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // // cv = waitForConnectivityBroadcasts(1); // mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget(); -// cv.block(); +// waitFor(cv); // // reset(mNetManager); // @@ -641,7 +846,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // // cv = waitForConnectivityBroadcasts(1); // mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mWifi.info).sendToTarget(); -// cv.block(); +// waitFor(cv); // // // verify that wifi routes added, and teardown requested // int wifiNetId = mWifi.tracker.getNetwork().netId; @@ -660,7 +865,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { // // cv = waitForConnectivityBroadcasts(1); // mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget(); -// cv.block(); +// waitFor(cv); // // verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V4)); // verify(mNetManager).removeRoute(eq(mobileNetId), eq(MOBILE_ROUTE_V6)); diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 3767fce..490236e 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -31,6 +31,7 @@ import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; import android.appwidget.AppWidgetManager; import android.content.BroadcastReceiver; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -69,8 +70,8 @@ import android.view.Display; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; +import com.android.internal.os.SomeArgs; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.DeviceIdleController; import com.android.server.SystemService; import java.io.BufferedReader; @@ -117,6 +118,7 @@ public class UsageStatsService extends SystemService implements static final int MSG_CHECK_IDLE_STATES = 5; static final int MSG_CHECK_PAROLE_TIMEOUT = 6; static final int MSG_PAROLE_END_TIMEOUT = 7; + static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8; private final Object mLock = new Object(); Handler mHandler; @@ -133,6 +135,7 @@ public class UsageStatsService extends SystemService implements long mRealTimeSnapshot; long mSystemTimeSnapshot; + boolean mAppIdleEnabled; boolean mAppIdleParoled; private boolean mScreenOn; private long mLastAppIdleParoledTime; @@ -170,10 +173,15 @@ public class UsageStatsService extends SystemService implements getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions, null, null); - IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); - deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); - deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - getContext().registerReceiver(new DeviceStateReceiver(), deviceStates); + mAppIdleEnabled = getContext().getResources().getBoolean( + com.android.internal.R.bool.config_enableAutoPowerModes); + if (mAppIdleEnabled) { + IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); + deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); + deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); + getContext().registerReceiver(new DeviceStateReceiver(), deviceStates); + } + synchronized (mLock) { cleanUpRemovedUsersLocked(); } @@ -181,7 +189,6 @@ public class UsageStatsService extends SystemService implements mRealTimeSnapshot = SystemClock.elapsedRealtime(); mSystemTimeSnapshot = System.currentTimeMillis(); - publishLocalService(UsageStatsManagerInternal.class, new LocalService()); publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); } @@ -337,6 +344,10 @@ public class UsageStatsService extends SystemService implements /** Check all running users' or specified user's apps to see if they enter an idle state. */ void checkIdleStates(int checkUserId) { + if (!mAppIdleEnabled) { + return; + } + final int[] userIds; try { if (checkUserId == UserHandle.USER_ALL) { @@ -583,6 +594,29 @@ public class UsageStatsService extends SystemService implements } } + void reportContentProviderUsage(String authority, String providerPkgName, int userId) { + // Get sync adapters for the authority + String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser( + authority, userId); + for (String packageName: packages) { + // Only force the sync adapters to active if the provider is not in the same package and + // the sync adapter is a system package. + try { + PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo( + packageName, 0, userId); + if (pi == null || pi.applicationInfo == null + || !pi.applicationInfo.isSystemApp()) { + continue; + } + if (!packageName.equals(providerPkgName)) { + forceIdleState(packageName, userId, false); + } + } catch (RemoteException re) { + // Shouldn't happen + } + } + } + /** * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle, * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind @@ -605,7 +639,7 @@ public class UsageStatsService extends SystemService implements timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000); // Inform listeners if necessary if (previouslyIdle != idle) { - // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); + // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName); mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, /* idle = */ idle ? 1 : 0, packageName)); if (!idle) { @@ -744,6 +778,10 @@ public class UsageStatsService extends SystemService implements private boolean isAppIdleFiltered(String packageName, int userId, UserUsageStatsService userService, long timeNow, long screenOnTime) { if (packageName == null) return false; + // If not enabled at all, of course nobody is ever idle. + if (!mAppIdleEnabled) { + return false; + } synchronized (mLock) { // Temporary exemption, probably due to device charging or occasional allowance to // be allowed to sync, etc. @@ -872,6 +910,19 @@ public class UsageStatsService extends SystemService implements pw.print(" mAppIdleParoleDurationMillis="); TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw); pw.println(); + + pw.println(); + pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled); + pw.print(" mAppIdleParoled="); pw.print(mAppIdleParoled); + pw.print(" mScreenOn="); pw.println(mScreenOn); + pw.print("mLastAppIdleParoledTime="); + TimeUtils.formatDuration(mLastAppIdleParoledTime, pw); + pw.println(); + pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw); + pw.println(); + pw.print("mScreenOnSystemTimeSnapshot="); + TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw); + pw.println(); } } @@ -916,6 +967,14 @@ public class UsageStatsService extends SystemService implements setAppIdleParoled(false); break; + case MSG_REPORT_CONTENT_PROVIDER_USAGE: + SomeArgs args = (SomeArgs) msg.obj; + reportContentProviderUsage((String) args.arg1, // authority name + (String) args.arg2, // package name + (int) args.arg3); // userId + args.recycle(); + break; + default: super.handleMessage(msg); break; @@ -1177,6 +1236,16 @@ public class UsageStatsService extends SystemService implements } @Override + public void reportContentProviderUsage(String name, String packageName, int userId) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = name; + args.arg2 = packageName; + args.arg3 = userId; + mHandler.obtainMessage(MSG_REPORT_CONTENT_PROVIDER_USAGE, args) + .sendToTarget(); + } + + @Override public boolean isAppIdle(String packageName, int userId) { return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index fafe44a..b68abab 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.res.Resources; @@ -57,6 +58,7 @@ import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; +import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.UiThread; @@ -83,6 +85,21 @@ public class VoiceInteractionManagerService extends SystemService { mDbHelper = new DatabaseHelper(context); mSoundTriggerHelper = new SoundTriggerHelper(context); mServiceStub = new VoiceInteractionManagerServiceStub(); + + PackageManagerInternal packageManagerInternal = LocalServices.getService( + PackageManagerInternal.class); + packageManagerInternal.setVoiceInteractionPackagesProvider( + new PackageManagerInternal.PackagesProvider() { + @Override + public String[] getPackages(int userId) { + mServiceStub.initForUser(userId); + ComponentName interactor = mServiceStub.getCurInteractor(userId); + if (interactor != null) { + return new String[] {interactor.getPackageName()}; + } + return null; + } + }); } @Override diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index acd484d..af0ddbe 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -139,7 +139,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne IVoiceInteractionSessionShowCallback showCallback) { if (mActiveSession == null) { mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName, - mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid); + mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler); } return mActiveSession.showLocked(args, flags, showCallback); } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index 47a230a..cc6a9c5 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -32,6 +32,7 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -48,6 +49,8 @@ import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.os.IResultReceiver; +import com.android.server.LocalServices; +import com.android.server.statusbar.StatusBarManagerInternal; import java.io.PrintWriter; import java.util.ArrayList; @@ -63,6 +66,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { final Context mContext; final Callback mCallback; final int mCallingUid; + final Handler mHandler; final IActivityManager mAm; final IWindowManager mIWindowManager; final AppOpsManager mAppOps; @@ -141,13 +145,14 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { }; public VoiceInteractionSessionConnection(Object lock, ComponentName component, int user, - Context context, Callback callback, int callingUid) { + Context context, Callback callback, int callingUid, Handler handler) { mLock = lock; mSessionComponentName = component; mUser = user; mContext = context; mCallback = callback; mCallingUid = callingUid; + mHandler = handler; mAm = ActivityManagerNative.getDefault(); mIWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); @@ -193,11 +198,13 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mShowArgs = args; mShowFlags = flags; mHaveAssistData = false; + boolean needDisclosure = false; if ((flags& VoiceInteractionSession.SHOW_WITH_ASSIST) != 0) { if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ASSIST_STRUCTURE, mCallingUid, mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED && allDataEnabled) { try { + needDisclosure = true; mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL, mAssistReceiver); } catch (RemoteException e) { @@ -215,6 +222,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED && allDataEnabled) { try { + needDisclosure = true; mIWindowManager.requestAssistScreenshot(mScreenshotReceiver); } catch (RemoteException e) { } @@ -225,6 +233,9 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { } else { mScreenshot = null; } + if (needDisclosure) { + mHandler.post(mShowAssistDisclosureRunnable); + } if (mSession != null) { try { mSession.show(mShowArgs, mShowFlags, showCallback); @@ -483,4 +494,15 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { pw.print(prefix); pw.print("mAssistData="); pw.println(mAssistData); } } + + private Runnable mShowAssistDisclosureRunnable = new Runnable() { + @Override + public void run() { + StatusBarManagerInternal statusBarInternal = LocalServices.getService( + StatusBarManagerInternal.class); + if (statusBarInternal != null) { + statusBarInternal.showAssistDisclosure(); + } + } + }; }; |