diff options
Diffstat (limited to 'services/core/java/com/android')
33 files changed, 588 insertions, 244 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 48c89cf..8607a40 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -185,7 +185,7 @@ class AlarmManagerService extends SystemService { private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY; - private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000; + private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9*60*1000; private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000; // Minimum futurity of a new alarm @@ -1000,8 +1000,8 @@ class AlarmManagerService extends SystemService { // This is a special alarm that will put the system into idle until it goes off. // The caller has given the time they want this to happen at, however we need // to pull that earlier if there are existing alarms that have requested to - // bring us out of idle. - if (mNextWakeFromIdle != null) { + // bring us out of idle at an earlier time. + if (mNextWakeFromIdle != null && a.whenElapsed > mNextWakeFromIdle.whenElapsed) { a.when = a.whenElapsed = a.maxWhenElapsed = mNextWakeFromIdle.whenElapsed; } // Add fuzz to make the alarm go off some time before the actual desired time. @@ -1318,7 +1318,7 @@ class AlarmManagerService extends SystemService { pw.print(" Idling until: "); if (mPendingIdleUntil != null) { pw.println(mPendingIdleUntil); - mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); + mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); } else { pw.println("null"); } diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index 5d0b4f8..b5bf12c 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -44,7 +44,6 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.media.AudioAttributes; import android.os.AsyncTask; import android.os.Binder; @@ -310,12 +309,12 @@ public class AppOpsService extends IAppOpsService.Stub { Iterator<Ops> it = pkgs.values().iterator(); while (it.hasNext()) { Ops ops = it.next(); - int curUid; + int curUid = -1; try { - curUid = mContext.getPackageManager().getPackageUid(ops.packageName, + curUid = AppGlobals.getPackageManager().getPackageUidEtc(ops.packageName, + PackageManager.GET_UNINSTALLED_PACKAGES, UserHandle.getUserId(ops.uidState.uid)); - } catch (NameNotFoundException e) { - curUid = -1; + } catch (RemoteException ignored) { } if (curUid != ops.uidState.uid) { Slog.i(TAG, "Pruning old package " + ops.packageName diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index e46aff2..bc356da 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -953,13 +953,13 @@ public class ConnectivityService extends IConnectivityManager.Stub uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); } - if ((uidRules & RULE_REJECT_ALL) != 0 - || (networkCostly && (uidRules & RULE_REJECT_METERED) != 0)) { + if (uidRules == RULE_REJECT_ALL) { return true; + } else if ((uidRules == RULE_REJECT_METERED) && networkCostly) { + return true; + } else { + return false; } - - // no restrictive rules; network is visible - return false; } /** @@ -1454,10 +1454,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void enforceChangePermission() { - int uid = Binder.getCallingUid(); - Settings.checkAndNoteChangeNetworkStateOperation(mContext, uid, Settings - .getPackageNameForUid(mContext, uid), true); - + ConnectivityManager.enforceChangePermission(mContext); } private void enforceTetherAccessPermission() { @@ -3227,6 +3224,11 @@ public class ConnectivityService extends IConnectivityManager.Stub final String profileName = new String(mKeyStore.get(Credentials.LOCKDOWN_VPN)); final VpnProfile profile = VpnProfile.decode( profileName, mKeyStore.get(Credentials.VPN + profileName)); + if (profile == null) { + Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName); + setLockdownTracker(null); + return true; + } int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized(mVpns) { setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user), @@ -3373,7 +3375,7 @@ public class ConnectivityService extends IConnectivityManager.Stub .setPriority(highPriority ? Notification.PRIORITY_HIGH : Notification.PRIORITY_DEFAULT) - .setDefaults(Notification.DEFAULT_ALL) + .setDefaults(highPriority ? Notification.DEFAULT_ALL : 0) .setOnlyAlertOnce(true) .build(); @@ -3739,7 +3741,7 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized(mRulesLock) { uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); } - if ((uidRules & (RULE_REJECT_METERED | RULE_REJECT_ALL)) != 0) { + if (uidRules != RULE_ALLOW_ALL) { // we could silently fail or we can filter the available nets to only give // them those they have access to. Chose the more useful networkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 38adfbd..abe8f5c 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -242,6 +242,14 @@ public class DeviceIdleController extends SystemService if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { int plugged = intent.getIntExtra("plugged", 0); updateChargingLocked(plugged != 0); + } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { + if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + Uri data = intent.getData(); + String ssp; + if (data != null && (ssp=data.getSchemeSpecificPart()) != null) { + removePowerSaveWhitelistAppInternal(ssp); + } + } } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { synchronized (DeviceIdleController.this) { stepIdleStateLocked(); @@ -918,6 +926,10 @@ public class DeviceIdleController extends SystemService filter.addAction(Intent.ACTION_BATTERY_CHANGED); filter.addAction(ACTION_STEP_IDLE_STATE); getContext().registerReceiver(mReceiver, filter); + filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + getContext().registerReceiver(mReceiver, filter); mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray); @@ -930,7 +942,10 @@ public class DeviceIdleController extends SystemService public boolean addPowerSaveWhitelistAppInternal(String name) { synchronized (this) { try { - ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0); + ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, + PackageManager.GET_UNINSTALLED_PACKAGES + | PackageManager.GET_DISABLED_COMPONENTS + | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS); if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) { reportPowerSaveWhitelistChangedLocked(); updateWhitelistAppIdsLocked(); @@ -1271,7 +1286,6 @@ public class DeviceIdleController extends SystemService if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING."); EventLogTags.writeDeviceIdle(mState, "step"); scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT); - cancelSensingAlarmLocked(); cancelLocatingLocked(); mAnyMotionDetector.checkForAnyMotion(); mNotMoving = false; @@ -1283,7 +1297,6 @@ public class DeviceIdleController extends SystemService mState = STATE_LOCATING; if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING."); EventLogTags.writeDeviceIdle(mState, "step"); - cancelSensingAlarmLocked(); scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT); mLocating = true; mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener, @@ -1341,6 +1354,7 @@ public class DeviceIdleController extends SystemService mState = STATE_ACTIVE; mInactiveTimeout = timeout; EventLogTags.writeDeviceIdle(mState, type); + cancelSensingAlarmLocked(); becomeInactiveIfAppropriateLocked(); } } @@ -1524,7 +1538,6 @@ public class DeviceIdleController extends SystemService } catch (IOException e) { } } - } private void readConfigFileLocked(XmlPullParser parser) { @@ -1553,7 +1566,10 @@ public class DeviceIdleController extends SystemService String name = parser.getAttributeValue(null, "n"); if (name != null) { try { - ApplicationInfo ai = pm.getApplicationInfo(name, 0); + ApplicationInfo ai = pm.getApplicationInfo(name, + PackageManager.GET_UNINSTALLED_PACKAGES + | PackageManager.GET_DISABLED_COMPONENTS + | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS); mPowerSaveWhitelistUserApps.put(ai.packageName, UserHandle.getAppId(ai.uid)); } catch (PackageManager.NameNotFoundException e) { diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 8645766..6d6ca3c 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -40,6 +40,7 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.annotation.Nullable; import android.app.ActivityManagerNative; import android.app.AppGlobals; import android.app.AlertDialog; @@ -289,8 +290,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub boolean mSystemReady; /** - * Id of the currently selected input method. + * Id obtained with {@link InputMethodInfo#getId()} for the currently selected input method. + * method. This is to be synchronized with the secure settings keyed with + * {@link Settings.Secure#DEFAULT_INPUT_METHOD}. + * + * <p>This can be transiently {@code null} when the system is re-initializing input method + * settings, e.g., the system locale is just changed.</p> + * + * <p>Note that {@link #mCurId} is used to track which IME is being connected to + * {@link InputMethodManagerService}.</p> + * + * @see #mCurId */ + @Nullable String mCurMethodId; /** @@ -320,9 +332,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub EditorInfo mCurAttribute; /** - * The input method ID of the input method service that we are currently + * Id obtained with {@link InputMethodInfo#getId()} for the input method that we are currently * connected to or in the process of connecting to. + * + * <p>This can be {@code null} when no input method is connected.</p> + * + * @see #mCurMethodId */ + @Nullable String mCurId; /** @@ -978,7 +995,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub || (newLocale != null && !newLocale.equals(mLastSystemLocale))) { if (!updateOnlyWhenLocaleChanged) { hideCurrentInputLocked(0, null); - mCurMethodId = null; unbindCurrentMethodLocked(true, false); } if (DEBUG) { @@ -1532,7 +1548,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub channel.dispose(); } - void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) { + void unbindCurrentMethodLocked(boolean resetCurrentMethodAndClient, boolean savePosition) { + if (resetCurrentMethodAndClient) { + mCurMethodId = null; + } + if (mVisibleBound) { mContext.unbindService(mVisibleConnection); mVisibleBound = false; @@ -1559,9 +1579,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurId = null; clearCurMethodLocked(); - if (reportToClient && mCurClient != null) { - executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO( - MSG_UNBIND_METHOD, mCurSeq, mCurClient.client)); + if (resetCurrentMethodAndClient) { + unbindCurrentClientLocked(); } } @@ -1912,13 +1931,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id)); } catch (IllegalArgumentException e) { Slog.w(TAG, "Unknown input method from prefs: " + id, e); - mCurMethodId = null; unbindCurrentMethodLocked(true, false); } mShortcutInputMethodsAndSubtypes.clear(); } else { // There is no longer an input method set, so stop any current one. - mCurMethodId = null; unbindCurrentMethodLocked(true, false); } // code to disable the CM Phone IME switcher with config_show_cmIMESwitcher set = false diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index b135250..4847de3 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2419,8 +2419,13 @@ class MountService extends IMountService.Stub } try { - mCryptConnector.execute("cryptfs", "enablecrypto", wipe ? "wipe" : "inplace", CRYPTO_TYPES[type], - new SensitiveArg(password)); + if (type == StorageManager.CRYPT_TYPE_DEFAULT) { + mCryptConnector.execute("cryptfs", "enablecrypto", "inplace", + CRYPTO_TYPES[type]); + } else { + mCryptConnector.execute("cryptfs", "enablecrypto", "inplace", + CRYPTO_TYPES[type], new SensitiveArg(password)); + } } catch (NativeDaemonConnectorException e) { // Encryption failed return e.getCode(); diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 95c6c0e..fd42b0a 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -2055,9 +2055,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void setFirewallChainEnabled(int chain, boolean enable) { enforceSystemUid(); synchronized (mQuotaLock) { - if (mFirewallChainStates.indexOfKey(chain) >= 0 && - mFirewallChainStates.get(chain) == enable) { - // All is the same, nothing to do. + if (mFirewallChainStates.get(chain, false) == enable) { + // All is the same, nothing to do. This relies on the fact that netd has child + // chains default detached. return; } mFirewallChainStates.put(chain, enable); diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java index a0d305c..3f0664d 100644 --- a/services/core/java/com/android/server/NetworkTimeUpdateService.java +++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java @@ -30,6 +30,7 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.SystemClock; +import android.os.PowerManager; import android.provider.Settings; import android.util.Log; import android.util.NtpTrustedTime; @@ -75,6 +76,7 @@ public class NetworkTimeUpdateService { private SettingsObserver mSettingsObserver; // The last time that we successfully fetched the NTP time. private long mLastNtpFetchTime = NOT_SET; + private final PowerManager.WakeLock mWakeLock; // Normal polling frequency private final long mPollingIntervalMs; @@ -104,6 +106,9 @@ public class NetworkTimeUpdateService { com.android.internal.R.integer.config_ntpRetry); mTimeErrorThresholdMs = mContext.getResources().getInteger( com.android.internal.R.integer.config_ntpThreshold); + + mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, TAG); } /** Initialize the receivers and initiate the first NTP request */ @@ -148,7 +153,15 @@ public class NetworkTimeUpdateService { private void onPollNetworkTime(int event) { // If Automatic time is not set, don't bother. if (!isAutomaticTimeRequested()) return; + mWakeLock.acquire(); + try { + onPollNetworkTimeUnderWakeLock(event); + } finally { + mWakeLock.release(); + } + } + private void onPollNetworkTimeUnderWakeLock(int event) { final long refTime = SystemClock.elapsedRealtime(); // If NITZ time was received less than mPollingIntervalMs time ago, // no need to sync to NTP. diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index edc3685..1e0cf0a 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -3799,7 +3799,6 @@ public class AccountManagerService boolean isPermitted = isPermitted(opPackageName, callingUid, Manifest.permission.GET_ACCOUNTS, Manifest.permission.GET_ACCOUNTS_PRIVILEGED); - Log.i(TAG, String.format("getTypesVisibleToCaller: isPermitted? %s", isPermitted)); return getTypesForCaller(callingUid, userId, isPermitted); } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 9730111..542268e 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -1314,6 +1314,15 @@ public final class ActiveServices { if (!mRestartingServices.contains(r)) { return; } + if (!isServiceNeeded(r, false, false)) { + // Paranoia: is this service actually needed? In theory a service that is not + // needed should never remain on the restart list. In practice... well, there + // have been bugs where this happens, and bad things happen because the process + // ends up just being cached, so quickly killed, then restarted again and again. + // Let's not let that happen. + Slog.wtf(TAG, "Restarting service that is not needed: " + r); + return; + } try { bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); } catch (TransactionTooLargeException e) { @@ -2043,6 +2052,13 @@ public final class ActiveServices { mAm.mProcessStats); realStartServiceLocked(sr, proc, sr.createdFromFg); didSomething = true; + if (!isServiceNeeded(sr, false, false)) { + // We were waiting for this service to start, but it is actually no + // longer needed. This could happen because bringDownServiceIfNeeded + // won't bring down a service that is pending... so now the pending + // is done, so let's drop it. + bringDownServiceLocked(sr); + } } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting service " @@ -2055,7 +2071,7 @@ public final class ActiveServices { // be weird to bring up the process but arbitrarily not let the services // run at this point just because their restart time hasn't come up. if (mRestartingServices.size() > 0) { - ServiceRecord sr = null; + ServiceRecord sr; for (int i=0; i<mRestartingServices.size(); i++) { sr = mRestartingServices.get(i); if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1bf7931..b34a6ef 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -381,6 +381,10 @@ public final class ActivityManagerService extends ActivityManagerNative // we will consider it to be doing interaction for usage stats. static final int SERVICE_USAGE_INTERACTION_TIME = 30*60*1000; + // Maximum amount of time we will allow to elapse before re-reporting usage stats + // interaction with foreground processes. + static final long USAGE_STATS_INTERACTION_INTERVAL = 24*60*60*1000L; + // Maximum number of users we allow to be running at a time. static final int MAX_RUNNING_USERS = 3; @@ -18926,7 +18930,8 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now) { + private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now, + long nowElapsed) { boolean success = true; if (app.curRawAdj != app.setRawAdj) { @@ -19042,7 +19047,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.setProcState != app.curProcState) { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Proc state change of " + app.processName - + " to " + app.curProcState); + + " to " + app.curProcState); boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE; boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE; if (setImportant && !curImportant) { @@ -19053,14 +19058,14 @@ public final class ActivityManagerService extends ActivityManagerNative BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); synchronized (stats) { app.lastWakeTime = stats.getProcessWakeTime(app.info.uid, - app.pid, SystemClock.elapsedRealtime()); + app.pid, nowElapsed); } app.lastCpuTime = app.curCpuTime; } // Inform UsageStats of important process state change // Must be called before updating setProcState - maybeUpdateUsageStatsLocked(app); + maybeUpdateUsageStatsLocked(app, nowElapsed); app.setProcState = app.curProcState; if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) { @@ -19071,6 +19076,11 @@ public final class ActivityManagerService extends ActivityManagerNative } else { app.procStateChanged = true; } + } else if (app.reportedInteraction && (nowElapsed-app.interactionEventTime) + > USAGE_STATS_INTERACTION_INTERVAL) { + // For apps that sit around for a long time in the interactive state, we need + // to report this at least once a day so they don't go idle. + maybeUpdateUsageStatsLocked(app, nowElapsed); } if (changes != 0) { @@ -19171,7 +19181,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private void maybeUpdateUsageStatsLocked(ProcessRecord app) { + private void maybeUpdateUsageStatsLocked(ProcessRecord app, long nowElapsed) { if (DEBUG_USAGE_STATS) { Slog.d(TAG, "Checking proc [" + Arrays.toString(app.getPackageList()) + "] state changes: old = " + app.setProcState + ", new = " @@ -19188,19 +19198,20 @@ public final class ActivityManagerService extends ActivityManagerNative isInteraction = true; app.fgInteractionTime = 0; } else if (app.curProcState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) { - final long now = SystemClock.elapsedRealtime(); if (app.fgInteractionTime == 0) { - app.fgInteractionTime = now; + app.fgInteractionTime = nowElapsed; isInteraction = false; } else { - isInteraction = now > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME; + isInteraction = nowElapsed > app.fgInteractionTime + SERVICE_USAGE_INTERACTION_TIME; } } else { isInteraction = app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; app.fgInteractionTime = 0; } - if (isInteraction && !app.reportedInteraction) { + if (isInteraction && (!app.reportedInteraction + || (nowElapsed-app.interactionEventTime) > USAGE_STATS_INTERACTION_INTERVAL)) { + app.interactionEventTime = nowElapsed; String[] packages = app.getPackageList(); if (packages != null) { for (int i = 0; i < packages.length; i++) { @@ -19210,6 +19221,9 @@ public final class ActivityManagerService extends ActivityManagerNative } } app.reportedInteraction = isInteraction; + if (!isInteraction) { + app.interactionEventTime = 0; + } } private final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) { @@ -19232,7 +19246,7 @@ public final class ActivityManagerService extends ActivityManagerNative computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now); - return applyOomAdjLocked(app, doingAll, now); + return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime()); } final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground, @@ -19324,6 +19338,7 @@ public final class ActivityManagerService extends ActivityManagerNative final ActivityRecord TOP_ACT = resumedAppLocked(); final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null; final long now = SystemClock.uptimeMillis(); + final long nowElapsed = SystemClock.elapsedRealtime(); final long oldTime = now - ProcessList.MAX_EMPTY_TIME; final int N = mLruProcesses.size(); @@ -19481,7 +19496,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } - applyOomAdjLocked(app, true, now); + applyOomAdjLocked(app, true, now, nowElapsed); // Count the number of process types. switch (app.curProcState) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 6ccd939..be90dc8 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2496,8 +2496,13 @@ public final class ActivityStackSupervisor implements DisplayListener { final void doPendingActivityLaunchesLocked(boolean doResume) { while (!mPendingActivityLaunches.isEmpty()) { PendingActivityLaunch pal = mPendingActivityLaunches.remove(0); - startActivityUncheckedLocked(pal.r, pal.sourceRecord, null, null, pal.startFlags, - doResume && mPendingActivityLaunches.isEmpty(), null, null); + + try { + startActivityUncheckedLocked(pal.r, pal.sourceRecord, null, null, pal.startFlags, + doResume && mPendingActivityLaunches.isEmpty(), null, null); + } catch (Exception e) { + Slog.w(TAG, "Exception during pending activity launch pal=" + pal, e); + } } } @@ -3959,7 +3964,7 @@ public final class ActivityStackSupervisor implements DisplayListener { mLockTaskModeTasks.add(task); if (task.mLockTaskUid == -1) { - task.mLockTaskUid = task.mCallingUid; + task.mLockTaskUid = task.effectiveUid; } if (andResume) { diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 320d477..589a4b8 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -44,6 +44,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.util.EventLog; import android.util.Slog; +import android.util.TimeUtils; import com.android.server.DeviceIdleController; import static com.android.server.am.ActivityManagerDebugConfig.*; @@ -1297,6 +1298,7 @@ public final class BroadcastQueue { final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args, int opti, boolean dumpAll, String dumpPackage, boolean needSep) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (mParallelBroadcasts.size() > 0 || mOrderedBroadcasts.size() > 0 || mPendingBroadcast != null) { boolean printed = false; @@ -1314,7 +1316,7 @@ public final class BroadcastQueue { pw.println(" Active broadcasts [" + mQueueName + "]:"); } pw.println(" Active Broadcast " + mQueueName + " #" + i + ":"); - br.dump(pw, " "); + br.dump(pw, " ", sdf); } printed = false; needSep = true; @@ -1332,7 +1334,7 @@ public final class BroadcastQueue { pw.println(" Active ordered broadcasts [" + mQueueName + "]:"); } pw.println(" Active Ordered Broadcast " + mQueueName + " #" + i + ":"); - mOrderedBroadcasts.get(i).dump(pw, " "); + mOrderedBroadcasts.get(i).dump(pw, " ", sdf); } if (dumpPackage == null || (mPendingBroadcast != null && dumpPackage.equals(mPendingBroadcast.callerPackage))) { @@ -1341,7 +1343,7 @@ public final class BroadcastQueue { } pw.println(" Pending broadcast [" + mQueueName + "]:"); if (mPendingBroadcast != null) { - mPendingBroadcast.dump(pw, " "); + mPendingBroadcast.dump(pw, " ", sdf); } else { pw.println(" (null)"); } @@ -1379,7 +1381,7 @@ public final class BroadcastQueue { if (dumpAll) { pw.print(" Historical Broadcast " + mQueueName + " #"); pw.print(i); pw.println(":"); - r.dump(pw, " "); + r.dump(pw, " ", sdf); } else { pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r); pw.print(" "); @@ -1413,7 +1415,6 @@ public final class BroadcastQueue { } // done skipping; dump the remainder of the ring. 'i' is still the ordinal within // the overall broadcast history. - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); do { ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_SUMMARY_HISTORY); Intent intent = mBroadcastSummaryHistory[ringIndex]; @@ -1435,9 +1436,19 @@ public final class BroadcastQueue { i++; pw.print(" #"); pw.print(i); pw.print(": "); pw.println(intent.toShortString(false, true, true, false)); - pw.print(" enq="); pw.print(sdf.format(new Date(mSummaryHistoryEnqueueTime[ringIndex]))); - pw.print(" disp="); pw.print(sdf.format(new Date(mSummaryHistoryDispatchTime[ringIndex]))); - pw.print(" fin="); pw.println(sdf.format(new Date(mSummaryHistoryFinishTime[ringIndex]))); + pw.print(" "); + TimeUtils.formatDuration(mSummaryHistoryDispatchTime[ringIndex] + - mSummaryHistoryEnqueueTime[ringIndex], pw); + pw.print(" dispatch "); + TimeUtils.formatDuration(mSummaryHistoryFinishTime[ringIndex] + - mSummaryHistoryDispatchTime[ringIndex], pw); + pw.println(" finish"); + pw.print(" enq="); + pw.print(sdf.format(new Date(mSummaryHistoryEnqueueTime[ringIndex]))); + pw.print(" disp="); + pw.print(sdf.format(new Date(mSummaryHistoryDispatchTime[ringIndex]))); + pw.print(" fin="); + pw.println(sdf.format(new Date(mSummaryHistoryFinishTime[ringIndex]))); Bundle bundle = intent.getExtras(); if (bundle != null) { pw.print(" extras: "); pw.println(bundle.toString()); diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java index 1fbfd9f..b42bcff 100644 --- a/services/core/java/com/android/server/am/BroadcastRecord.java +++ b/services/core/java/com/android/server/am/BroadcastRecord.java @@ -32,6 +32,7 @@ import android.util.PrintWriterPrinter; import android.util.TimeUtils; import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -88,7 +89,7 @@ final class BroadcastRecord extends Binder { ComponentName curComponent; // the receiver class that is currently running. ActivityInfo curReceiver; // info about the receiver that is currently running. - void dump(PrintWriter pw, String prefix) { + void dump(PrintWriter pw, String prefix, SimpleDateFormat sdf) { final long now = SystemClock.uptimeMillis(); pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId); @@ -114,13 +115,19 @@ final class BroadcastRecord extends Binder { pw.print(prefix); pw.print("options="); pw.println(options.toBundle()); } pw.print(prefix); pw.print("enqueueClockTime="); - pw.print(new Date(enqueueClockTime)); + pw.print(sdf.format(new Date(enqueueClockTime))); pw.print(" dispatchClockTime="); - pw.println(new Date(dispatchClockTime)); + pw.println(sdf.format(new Date(dispatchClockTime))); pw.print(prefix); pw.print("dispatchTime="); TimeUtils.formatDuration(dispatchTime, now, pw); + pw.print(" ("); + TimeUtils.formatDuration(dispatchClockTime-enqueueClockTime, pw); + pw.print(" since enq)"); if (finishTime != 0) { pw.print(" finishTime="); TimeUtils.formatDuration(finishTime, now, pw); + pw.print(" ("); + TimeUtils.formatDuration(finishTime-dispatchTime, pw); + pw.print(" since disp)"); } else { pw.print(" receiverTime="); TimeUtils.formatDuration(receiverTime, now, pw); } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 9c4c978..9cab95b 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -114,6 +114,7 @@ final class ProcessRecord { boolean killed; // True once we know the process has been killed boolean procStateChanged; // Keep track of whether we changed 'setAdj'. boolean reportedInteraction;// Whether we have told usage stats about it being an interaction + long interactionEventTime; // The time we sent the last interaction event long fgInteractionTime; // When we became foreground for interaction purposes String waitingToKill; // Process is waiting to be killed when in the bg, and reason IBinder forcingToForeground;// Token that is forcing this process to be foreground @@ -297,6 +298,10 @@ final class ProcessRecord { if (reportedInteraction || fgInteractionTime != 0) { pw.print(prefix); pw.print("reportedInteraction="); pw.print(reportedInteraction); + if (interactionEventTime != 0) { + pw.print(" time="); + TimeUtils.formatDuration(interactionEventTime, SystemClock.elapsedRealtime(), pw); + } if (fgInteractionTime != 0) { pw.print(" fgInteractionTime="); TimeUtils.formatDuration(fgInteractionTime, SystemClock.elapsedRealtime(), pw); diff --git a/services/core/java/com/android/server/content/AppIdleMonitor.java b/services/core/java/com/android/server/content/AppIdleMonitor.java index fe5c2da..2d768d8 100644 --- a/services/core/java/com/android/server/content/AppIdleMonitor.java +++ b/services/core/java/com/android/server/content/AppIdleMonitor.java @@ -50,8 +50,8 @@ class AppIdleMonitor extends AppIdleStateChangeListener { } } - boolean isAppIdle(String packageName, int userId) { - return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, userId); + boolean isAppIdle(String packageName, int uidForAppId, int userId) { + return !mAppIdleParoleOn && mUsageStats.isAppIdle(packageName, uidForAppId, userId); } @Override diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 334bc18..3ec0bee 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -104,6 +104,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Random; import java.util.Set; @@ -2622,9 +2623,18 @@ public class SyncManager { continue; } String packageName = getPackageName(op.target); + ApplicationInfo ai = null; + if (packageName != null) { + try { + ai = mContext.getPackageManager().getApplicationInfo(packageName, + PackageManager.GET_UNINSTALLED_PACKAGES + | PackageManager.GET_DISABLED_COMPONENTS); + } catch (NameNotFoundException e) { + } + } // If app is considered idle, then skip for now and backoff - if (packageName != null - && mAppIdleMonitor.isAppIdle(packageName, op.target.userId)) { + if (ai != null + && mAppIdleMonitor.isAppIdle(packageName, ai.uid, op.target.userId)) { increaseBackoffSetting(op); op.appIdle = true; if (isLoggable) { @@ -3370,7 +3380,7 @@ public class SyncManager { if (!smaller.containsKey(key)) { return false; } - if (!bigger.get(key).equals(smaller.get(key))) { + if (!Objects.equals(bigger.get(key), smaller.get(key))) { return false; } } @@ -3378,7 +3388,6 @@ public class SyncManager { } /** - * TODO: Get rid of this when we separate sync settings extras from dev specified extras. * @return true if the provided key is used by the SyncManager in scheduling the sync. */ private static boolean isSyncSetting(String key) { diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java index bb4dbc3..835ba17 100644 --- a/services/core/java/com/android/server/display/ColorFade.java +++ b/services/core/java/com/android/server/display/ColorFade.java @@ -74,6 +74,7 @@ final class ColorFade { // Set to true when the animation context has been fully prepared. private boolean mPrepared; + private boolean mCreatedResources; private int mMode; private final DisplayManagerInternal mDisplayManagerInternal; @@ -169,6 +170,7 @@ final class ColorFade { } // Done. + mCreatedResources = true; mPrepared = true; // Dejanking optimization. @@ -313,18 +315,17 @@ final class ColorFade { } /** - * Dismisses the color fade animation surface and cleans up. + * Dismisses the color fade animation resources. * - * To prevent stray photons from leaking out after the color fade has been - * turned off, it is a good idea to defer dismissing the animation until the - * color fade has been turned back on fully. + * This function destroys the resources that are created for the color fade + * animation but does not clean up the surface. */ - public void dismiss() { + public void dismissResources() { if (DEBUG) { - Slog.d(TAG, "dismiss"); + Slog.d(TAG, "dismissResources"); } - if (mPrepared) { + if (mCreatedResources) { attachEglContext(); try { destroyScreenshotTexture(); @@ -334,8 +335,28 @@ final class ColorFade { } finally { detachEglContext(); } - destroySurface(); + // This is being called with no active context so shouldn't be + // needed but is safer to not change for now. GLES20.glFlush(); + mCreatedResources = false; + } + } + + /** + * Dismisses the color fade animation surface and cleans up. + * + * To prevent stray photons from leaking out after the color fade has been + * turned off, it is a good idea to defer dismissing the animation until the + * color fade has been turned back on fully. + */ + public void dismiss() { + if (DEBUG) { + Slog.d(TAG, "dismiss"); + } + + if (mPrepared) { + dismissResources(); + destroySurface(); mPrepared = false; } } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 45065b8..38c4180 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -859,6 +859,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mPendingScreenOff && target != Display.STATE_OFF) { setScreenState(Display.STATE_OFF); mPendingScreenOff = false; + mPowerState.dismissColorFadeResources(); } if (target == Display.STATE_ON) { @@ -932,6 +933,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // A black surface is already hiding the contents of the screen. setScreenState(Display.STATE_OFF); mPendingScreenOff = false; + mPowerState.dismissColorFadeResources(); } else if (performScreenOffTransition && mPowerState.prepareColorFade(mContext, mColorFadeFadesConfig ? diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java index 2eabd32..9862516 100644 --- a/services/core/java/com/android/server/display/DisplayPowerState.java +++ b/services/core/java/com/android/server/display/DisplayPowerState.java @@ -187,7 +187,7 @@ final class DisplayPowerState { } /** - * Dismisses the electron beam surface. + * Dismisses the color fade surface. */ public void dismissColorFade() { mColorFade.dismiss(); @@ -195,6 +195,13 @@ final class DisplayPowerState { mColorFadeReady = true; } + /** + * Dismisses the color fade resources. + */ + public void dismissColorFadeResources() { + mColorFade.dismissResources(); + } + /** * Sets the level of the electron beam steering current. * diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 67f6fe1..37326cc 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -838,8 +838,17 @@ public class InputManagerService extends IInputManager.Stub } @Override // Binder call + public int isInTabletMode() { + if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE, + "isInTabletMode()")) { + throw new SecurityException("Requires TABLET_MODE permission"); + } + return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_TABLET_MODE); + } + + @Override // Binder call public void registerTabletModeChangedListener(ITabletModeChangedListener listener) { - if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE_LISTENER, + if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE, "registerTabletModeChangedListener()")) { throw new SecurityException("Requires TABLET_MODE_LISTENER permission"); } @@ -1586,7 +1595,7 @@ public class InputManagerService extends IInputManager.Stub switchMask); } - if ((switchMask & SW_TABLET_MODE) != 0) { + if ((switchMask & SW_TABLET_MODE_BIT) != 0) { SomeArgs args = SomeArgs.obtain(); args.argi1 = (int) (whenNanos & 0xFFFFFFFF); args.argi2 = (int) (whenNanos >> 32); diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index ecda36a..3c50102 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -73,7 +73,7 @@ import com.android.server.job.controllers.TimeController; */ public class JobSchedulerService extends com.android.server.SystemService implements StateChangedListener, JobCompletedListener { - static final boolean DEBUG = false; + public static final boolean DEBUG = false; /** The number of concurrent jobs we run at one time. */ private static final int MAX_JOB_CONTEXTS_COUNT = ActivityManager.isLowRamDeviceStatic() ? 1 : 3; @@ -99,7 +99,7 @@ public class JobSchedulerService extends com.android.server.SystemService * Minimum # of connectivity jobs that must be ready in order to force the JMS to schedule * things early. */ - static final int MIN_CONNECTIVITY_COUNT = 2; + static final int MIN_CONNECTIVITY_COUNT = 1; // Run connectivity jobs as soon as ready. /** * Minimum # of jobs (with no particular constraints) for which the JMS will be happy running * some work early. @@ -443,13 +443,16 @@ public class JobSchedulerService extends com.android.server.SystemService } /** - * A job is rescheduled with exponential back-off if the client requests this from their - * execution logic. - * A caveat is for idle-mode jobs, for which the idle-mode constraint will usurp the - * timeliness of the reschedule. For an idle-mode job, no deadline is given. + * Reschedules the given job based on the job's backoff policy. It doesn't make sense to + * specify an override deadline on a failed job (the failed job will run even though it's not + * ready), so we reschedule it with {@link JobStatus#NO_LATEST_RUNTIME}, but specify that any + * ready job with {@link JobStatus#numFailures} > 0 will be executed. + * * @param failureToReschedule Provided job status that we will reschedule. * @return A newly instantiated JobStatus with the same constraints as the last job except * with adjusted timing constraints. + * + * @see JobHandler#maybeQueueReadyJobsForExecutionLockedH */ private JobStatus getRescheduleJobForFailure(JobStatus failureToReschedule) { final long elapsedNowMillis = SystemClock.elapsedRealtime(); @@ -479,8 +482,9 @@ public class JobSchedulerService extends com.android.server.SystemService } /** - * Called after a periodic has executed so we can to re-add it. We take the last execution time - * of the job to be the time of completion (i.e. the time at which this function is called). + * Called after a periodic has executed so we can reschedule it. We take the last execution + * time of the job to be the time of completion (i.e. the time at which this function is + * called). * This could be inaccurate b/c the job can run for as long as * {@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead * to underscheduling at least, rather than if we had taken the last execution time to be the @@ -491,7 +495,12 @@ public class JobSchedulerService extends com.android.server.SystemService private JobStatus getRescheduleJobForPeriodic(JobStatus periodicToReschedule) { final long elapsedNow = SystemClock.elapsedRealtime(); // Compute how much of the period is remaining. - long runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0); + long runEarly = 0L; + + // If this periodic was rescheduled it won't have a deadline. + if (periodicToReschedule.hasDeadlineConstraint()) { + runEarly = Math.max(periodicToReschedule.getLatestRunTimeElapsed() - elapsedNow, 0L); + } long newEarliestRunTimeElapsed = elapsedNow + runEarly; long period = periodicToReschedule.getJob().getIntervalMillis(); long newLatestRuntimeElapsed = newEarliestRunTimeElapsed + period; diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index bb4e388..5515393 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -62,13 +62,13 @@ import java.util.concurrent.atomic.AtomicBoolean; * */ public class JobServiceContext extends IJobCallback.Stub implements ServiceConnection { - private static final boolean DEBUG = false; + private static final boolean DEBUG = JobSchedulerService.DEBUG; private static final String TAG = "JobServiceContext"; /** Define the maximum # of jobs allowed to run on a service at once. */ private static final int defaultMaxActiveJobsPerService = ActivityManager.isLowRamDeviceStatic() ? 1 : 3; /** Amount of time a job is allowed to execute for before being considered timed-out. */ - private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; + private static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. /** Amount of time the JobScheduler will wait for a response from an app for a message. */ private static final long OP_TIMEOUT_MILLIS = 8 * 1000; @@ -108,7 +108,13 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne int mVerb; private AtomicBoolean mCancelled = new AtomicBoolean(); - /** All the information maintained about the job currently being executed. */ + /** + * All the information maintained about the job currently being executed. + * + * Any reads (dereferences) not done from the handler thread must be synchronized on + * {@link #mLock}. + * Writes can only be done from the handler thread, or {@link #executeRunnableJob(JobStatus)}. + */ private JobStatus mRunningJob; /** Binder to the client service. */ IJobService service; @@ -192,7 +198,8 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne */ JobStatus getRunningJob() { synchronized (mLock) { - return mRunningJob; + return mRunningJob == null ? + null : new JobStatus(mRunningJob); } } @@ -253,15 +260,22 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne */ @Override public void onServiceConnected(ComponentName name, IBinder service) { - if (!name.equals(mRunningJob.getServiceComponent())) { + JobStatus runningJob; + synchronized (mLock) { + // This isn't strictly necessary b/c the JobServiceHandler is running on the main + // looper and at this point we can't get any binder callbacks from the client. Better + // safe than sorry. + runningJob = mRunningJob; + } + if (runningJob == null || !name.equals(runningJob.getServiceComponent())) { mCallbackHandler.obtainMessage(MSG_SHUTDOWN_EXECUTION).sendToTarget(); return; } this.service = IJobService.Stub.asInterface(service); final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mRunningJob.getTag()); - mWakeLock.setWorkSource(new WorkSource(mRunningJob.getUid())); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, runningJob.getTag()); + mWakeLock.setWorkSource(new WorkSource(runningJob.getUid())); mWakeLock.setReferenceCounted(false); mWakeLock.acquire(); mCallbackHandler.obtainMessage(MSG_SERVICE_BOUND).sendToTarget(); @@ -279,13 +293,15 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne * @return True if the binder calling is coming from the client we expect. */ private boolean verifyCallingUid() { - if (mRunningJob == null || Binder.getCallingUid() != mRunningJob.getUid()) { - if (DEBUG) { - Slog.d(TAG, "Stale callback received, ignoring."); + synchronized (mLock) { + if (mRunningJob == null || Binder.getCallingUid() != mRunningJob.getUid()) { + if (DEBUG) { + Slog.d(TAG, "Stale callback received, ignoring."); + } + return false; } - return false; + return true; } - return true; } /** diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 24d4f15..53125c0 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -24,6 +24,7 @@ import android.os.Handler; import android.os.PersistableBundle; import android.os.SystemClock; import android.os.UserHandle; +import android.text.format.DateUtils; import android.util.AtomicFile; import android.util.ArraySet; import android.util.Pair; @@ -552,9 +553,10 @@ public class JobStore { return null; } - Pair<Long, Long> runtimes; + // Tuple of (earliest runtime, latest runtime) in elapsed realtime after disk load. + Pair<Long, Long> elapsedRuntimes; try { - runtimes = buildExecutionTimesFromXml(parser); + elapsedRuntimes = buildExecutionTimesFromXml(parser); } catch (NumberFormatException e) { if (DEBUG) { Slog.d(TAG, "Error parsing execution time parameters, skipping."); @@ -562,22 +564,45 @@ public class JobStore { return null; } + final long elapsedNow = SystemClock.elapsedRealtime(); if (XML_TAG_PERIODIC.equals(parser.getName())) { try { String val = parser.getAttributeValue(null, "period"); - jobBuilder.setPeriodic(Long.valueOf(val)); + final long periodMillis = Long.valueOf(val); + jobBuilder.setPeriodic(periodMillis); + // As a sanity check, cap the recreated run time to be no later than 2 periods + // from now. This is the latest the periodic could be pushed out. This could + // happen if the periodic ran early (at the start of its period), and then the + // device rebooted. + if (elapsedRuntimes.second > elapsedNow + 2 * periodMillis) { + final long clampedEarlyRuntimeElapsed = elapsedNow + periodMillis; + final long clampedLateRuntimeElapsed = elapsedNow + 2 * periodMillis; + Slog.w(TAG, + String.format("Periodic job for uid='%d' persisted run-time is" + + " too big [%s, %s]. Clamping to [%s,%s]", + uid, + DateUtils.formatElapsedTime(elapsedRuntimes.first / 1000), + DateUtils.formatElapsedTime(elapsedRuntimes.second / 1000), + DateUtils.formatElapsedTime( + clampedEarlyRuntimeElapsed / 1000), + DateUtils.formatElapsedTime( + clampedLateRuntimeElapsed / 1000)) + ); + elapsedRuntimes = + Pair.create(clampedEarlyRuntimeElapsed, clampedLateRuntimeElapsed); + } } catch (NumberFormatException e) { Slog.d(TAG, "Error reading periodic execution criteria, skipping."); return null; } } else if (XML_TAG_ONEOFF.equals(parser.getName())) { try { - if (runtimes.first != JobStatus.NO_EARLIEST_RUNTIME) { - jobBuilder.setMinimumLatency(runtimes.first - SystemClock.elapsedRealtime()); + if (elapsedRuntimes.first != JobStatus.NO_EARLIEST_RUNTIME) { + jobBuilder.setMinimumLatency(elapsedRuntimes.first - elapsedNow); } - if (runtimes.second != JobStatus.NO_LATEST_RUNTIME) { + if (elapsedRuntimes.second != JobStatus.NO_LATEST_RUNTIME) { jobBuilder.setOverrideDeadline( - runtimes.second - SystemClock.elapsedRealtime()); + elapsedRuntimes.second - elapsedNow); } } catch (NumberFormatException e) { Slog.d(TAG, "Error reading job execution criteria, skipping."); @@ -598,7 +623,8 @@ public class JobStore { do { eventType = parser.next(); } while (eventType == XmlPullParser.TEXT); - if (!(eventType == XmlPullParser.START_TAG && XML_TAG_EXTRAS.equals(parser.getName()))) { + if (!(eventType == XmlPullParser.START_TAG + && XML_TAG_EXTRAS.equals(parser.getName()))) { if (DEBUG) { Slog.d(TAG, "Error reading extras, skipping."); } @@ -609,7 +635,8 @@ public class JobStore { jobBuilder.setExtras(extras); parser.nextTag(); // Consume </extras> - return new JobStatus(jobBuilder.build(), uid, runtimes.first, runtimes.second); + return new JobStatus( + jobBuilder.build(), uid, elapsedRuntimes.first, elapsedRuntimes.second); } private JobInfo.Builder buildBuilderFromXml(XmlPullParser parser) throws NumberFormatException { diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java index 02d4f40..6fc02f6 100644 --- a/services/core/java/com/android/server/job/controllers/AppIdleController.java +++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java @@ -67,7 +67,7 @@ public class AppIdleController extends StateController { mTrackedTasks.add(jobStatus); String packageName = jobStatus.job.getService().getPackageName(); final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName, - jobStatus.getUserId()); + jobStatus.uId, jobStatus.getUserId()); if (DEBUG) { Slog.d(LOG_TAG, "Start tracking, setting idle state of " + packageName + " to " + appIdle); @@ -108,7 +108,7 @@ public class AppIdleController extends StateController { for (JobStatus task : mTrackedTasks) { String packageName = task.job.getService().getPackageName(); final boolean appIdle = !mAppIdleParoleOn && mUsageStatsInternal.isAppIdle(packageName, - task.getUserId()); + task.uId, task.getUserId()); if (DEBUG) { Slog.d(LOG_TAG, "Setting idle state of " + packageName + " to " + appIdle); } diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index 69c63f3..c02611f 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -82,6 +82,13 @@ public class JobStatus { this.numFailures = numFailures; } + /** Copy constructor. */ + public JobStatus(JobStatus jobStatus) { + this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.getNumFailures()); + this.earliestRunTimeElapsedMillis = jobStatus.getEarliestRunTime(); + this.latestRunTimeElapsedMillis = jobStatus.getLatestRunTimeElapsed(); + } + /** Create a newly scheduled job. */ public JobStatus(JobInfo job, int uId) { this(job, uId, 0); diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java index cda7c32..21c30c7 100644 --- a/services/core/java/com/android/server/job/controllers/StateController.java +++ b/services/core/java/com/android/server/job/controllers/StateController.java @@ -18,6 +18,7 @@ package com.android.server.job.controllers; import android.content.Context; +import com.android.server.job.JobSchedulerService; import com.android.server.job.StateChangedListener; import java.io.PrintWriter; @@ -28,7 +29,7 @@ import java.io.PrintWriter; * are ready to run, or whether they must be stopped. */ public abstract class StateController { - protected static final boolean DEBUG = false; + protected static final boolean DEBUG = JobSchedulerService.DEBUG; protected Context mContext; protected StateChangedListener mStateChangedListener; protected boolean mDeviceIdleMode; diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index f041f0d..bf7560e 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -39,17 +39,17 @@ import static android.net.NetworkPolicy.WARNING_DISABLED; import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE; import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY; -import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY; import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; +import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; +import static android.net.NetworkPolicyManager.RULE_UNKNOWN; import static android.net.NetworkPolicyManager.computeLastCycleBoundary; -import static android.net.NetworkPolicyManager.dumpPolicy; -import static android.net.NetworkPolicyManager.dumpRules; import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER; import static android.net.NetworkTemplate.MATCH_MOBILE_4G; import static android.net.NetworkTemplate.MATCH_MOBILE_ALL; @@ -108,6 +108,7 @@ import android.net.LinkProperties; import android.net.NetworkIdentity; import android.net.NetworkInfo; import android.net.NetworkPolicy; +import android.net.NetworkPolicyManager; import android.net.NetworkQuotaInfo; import android.net.NetworkState; import android.net.NetworkTemplate; @@ -138,6 +139,7 @@ import android.text.format.Time; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; +import android.util.DebugUtils; import android.util.Log; import android.util.NtpTrustedTime; import android.util.Pair; @@ -147,8 +149,6 @@ import android.util.SparseIntArray; import android.util.TrustedTime; import android.util.Xml; -import com.android.server.DeviceIdleController; -import com.android.server.EventLogTags; import libcore.io.IoUtils; import com.android.internal.R; @@ -156,6 +156,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.DeviceIdleController; +import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.google.android.collect.Lists; @@ -279,6 +281,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final SparseIntArray mUidPolicy = new SparseIntArray(); /** Currently derived rules for each UID. */ final SparseIntArray mUidRules = new SparseIntArray(); + + final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray(); + final SparseIntArray mUidFirewallDozableRules = new SparseIntArray(); + /** Set of states for the child firewall chains. True if the chain is active. */ final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); @@ -446,14 +452,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // read policy from disk readPolicyLocked(); - if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) { - updateRulesForGlobalChangeLocked(false); - updateNotificationsLocked(); - } else { - // If we are not in any special mode, we just need to make sure the current - // app idle state is updated. - updateRulesForAppIdleLocked(); - } + updateRulesForGlobalChangeLocked(false); + updateNotificationsLocked(); } updateScreenOn(); @@ -1801,7 +1801,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (mDeviceIdleMode != enabled) { mDeviceIdleMode = enabled; if (mSystemReady) { - updateRulesForDeviceIdleLocked(); + // Device idle change means we need to rebuild rules for all + // known apps, so do a global refresh. + updateRulesForGlobalChangeLocked(false); } if (enabled) { EventLogTags.writeDeviceIdleOnPhase("net"); @@ -1939,7 +1941,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.print("UID="); fout.print(uid); fout.print(" policy="); - dumpPolicy(fout, policy); + fout.print(DebugUtils.flagsToString(NetworkPolicyManager.class, "POLICY_", policy)); fout.println(); } fout.decreaseIndent(); @@ -1984,18 +1986,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.print("UID="); fout.print(uid); - int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); + final int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY); fout.print(" state="); fout.print(state); fout.print(state <= ActivityManager.PROCESS_STATE_TOP ? " (fg)" : " (bg)"); - fout.print(" rules="); - final int rulesIndex = mUidRules.indexOfKey(uid); - if (rulesIndex < 0) { - fout.print("UNKNOWN"); - } else { - dumpRules(fout, mUidRules.valueAt(rulesIndex)); - } + final int rule = mUidRules.get(uid, RULE_UNKNOWN); + fout.print(" rule="); + fout.print(DebugUtils.valueToString(NetworkPolicyManager.class, "RULE_", rule)); fout.println(); } @@ -2030,7 +2028,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { updateRulesForUidStateChangeLocked(uid, oldUidState, uidState); if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState) != isProcStateAllowedWhileIdle(uidState)) { - updateRulesForDeviceIdleLocked(); + updateRuleForDeviceIdleLocked(uid); } } } @@ -2044,7 +2042,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { updateRulesForUidStateChangeLocked(uid, oldUidState, ActivityManager.PROCESS_STATE_CACHED_EMPTY); if (mDeviceIdleMode) { - updateRulesForDeviceIdleLocked(); + updateRuleForDeviceIdleLocked(uid); } } } @@ -2091,7 +2089,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (mDeviceIdleMode) { // sync the whitelists before enable dozable chain. We don't care about the rules if // we are disabling the chain. - SparseIntArray uidRules = new SparseIntArray(); + final SparseIntArray uidRules = mUidFirewallDozableRules; + uidRules.clear(); final List<UserInfo> users = mUserManager.getUsers(); for (int ui = users.size() - 1; ui >= 0; ui--) { UserInfo user = users.get(ui); @@ -2115,6 +2114,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules); } + enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode); } @@ -2128,11 +2128,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT); } } + + updateRulesForUidLocked(uid); } void updateRulesForAppIdleLocked() { + final SparseIntArray uidRules = mUidFirewallStandbyRules; + uidRules.clear(); + // Fully update the app idle firewall chain. - SparseIntArray uidRules = new SparseIntArray(); final List<UserInfo> users = mUserManager.getUsers(); for (int ui = users.size() - 1; ui >= 0; ui--) { UserInfo user = users.get(ui); @@ -2143,6 +2147,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } } + setUidFirewallRules(FIREWALL_CHAIN_STANDBY, uidRules); } @@ -2155,11 +2160,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } else { setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT); } + + updateRulesForUidLocked(uid); } void updateRulesForAppIdleParoleLocked() { boolean enableChain = !mUsageStats.isAppIdleParoleOn(); enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain); + updateRulesForUidsLocked(mUidFirewallStandbyRules); } /** @@ -2222,13 +2230,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int userId = UserHandle.getUserId(uid); for (String packageName : packages) { - if (!mUsageStats.isAppIdle(packageName, userId)) { + if (!mUsageStats.isAppIdle(packageName, uid, userId)) { return false; } } return true; } + void updateRulesForUidsLocked(SparseIntArray uids) { + for (int i = 0; i < uids.size(); i++) { + updateRulesForUidLocked(uids.keyAt(i)); + } + } + /** * Applies network rules to bandwidth and firewall controllers based on uid policy. * @param uid The uid for which to apply the latest policy @@ -2250,8 +2264,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE); final boolean uidForeground = isUidForegroundLocked(uid); - // derive active rules based on policy and active state - + // Derive active rules based on policy and active state int appId = UserHandle.getAppId(uid); int uidRules = RULE_ALLOW_ALL; if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { @@ -2274,20 +2287,27 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - final int oldRules = mUidRules.get(uid); + // Check dozable state, which is whitelist + if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE) + && mUidFirewallDozableRules.get(uid, FIREWALL_RULE_DEFAULT) != FIREWALL_RULE_ALLOW) { + uidRules = RULE_REJECT_ALL; + } + + // Check standby state, which is blacklist + if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY) + && mUidFirewallStandbyRules.get(uid, FIREWALL_RULE_DEFAULT) == FIREWALL_RULE_DENY) { + uidRules = RULE_REJECT_ALL; + } + final int oldRules = mUidRules.get(uid); if (uidRules == RULE_ALLOW_ALL) { mUidRules.delete(uid); } else { mUidRules.put(uid, uidRules); } - // Update bandwidth rules if necessary - final boolean oldRejectMetered = (oldRules & RULE_REJECT_METERED) != 0; - final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; - if (oldRejectMetered != rejectMetered) { - setUidNetworkRules(uid, rejectMetered); - } + final boolean rejectMetered = (uidRules == RULE_REJECT_METERED); + setUidNetworkRules(uid, rejectMetered); // dispatch changed rule to existing listeners if (oldRules != uidRules) { @@ -2474,6 +2494,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Add or remove a uid to the firewall blacklist for all network ifaces. */ private void setUidFirewallRule(int chain, int uid, int rule) { + if (chain == FIREWALL_CHAIN_DOZABLE) { + mUidFirewallDozableRules.put(uid, rule); + } else if (chain == FIREWALL_CHAIN_STANDBY) { + mUidFirewallStandbyRules.put(uid, rule); + } + try { mNetworkManager.setFirewallUidRule(chain, uid, rule); } catch (IllegalStateException e) { @@ -2487,9 +2513,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Add or remove a uid to the firewall blacklist for all network ifaces. */ private void enableFirewallChainLocked(int chain, boolean enable) { - if (mFirewallChainStates.indexOfKey(chain) >= 0 && - mFirewallChainStates.get(chain) == enable) { - // All is the same, nothing to do. + if (mFirewallChainStates.get(chain, false) == enable) { + // All is the same, nothing to do. This relies on the fact that netd has child + // chains default detached. return; } mFirewallChainStates.put(chain, enable); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 91ae31d..358b773 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1798,13 +1798,16 @@ public class PackageManagerService extends IPackageManager.Stub { return; } - PermissionsState permissionsState = sb.getPermissionsState(); - - for (String permission : pkg.requestedPermissions) { - BasePermission bp = mSettings.mPermissions.get(permission); - if (bp != null && bp.isRuntime() && (grantedPermissions == null - || ArrayUtils.contains(grantedPermissions, permission))) { - permissionsState.grantRuntimePermission(bp, userId); + synchronized (mPackages) { + for (String permission : pkg.requestedPermissions) { + BasePermission bp = mSettings.mPermissions.get(permission); + if (bp != null && (bp.isRuntime() || bp.isDevelopment()) + && (grantedPermissions == null + || ArrayUtils.contains(grantedPermissions, permission)) + && (getPermissionFlags(permission, pkg.packageName, userId) + & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) == 0) { + grantRuntimePermission(pkg.packageName, permission, userId); + } } } } @@ -2389,7 +2392,7 @@ public class PackageManagerService extends IPackageManager.Stub { + mSdkVersion + "; regranting permissions for internal storage"); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } - updatePermissionsLPw(null, null, updateFlags); + updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags); ver.sdkVersion = mSdkVersion; // Remove any stale app permissions (declared permission that now are undeclared @@ -2878,26 +2881,38 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public int getPackageUid(String packageName, int userId) { + return getPackageUidEtc(packageName, 0, userId); + } + + @Override + public int getPackageUidEtc(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return -1; enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid"); // reader synchronized (mPackages) { - PackageParser.Package p = mPackages.get(packageName); - if(p != null) { + final PackageParser.Package p = mPackages.get(packageName); + if (p != null) { return UserHandle.getUid(userId, p.applicationInfo.uid); } - PackageSetting ps = mSettings.mPackages.get(packageName); - if((ps == null) || (ps.pkg == null) || (ps.pkg.applicationInfo == null)) { - return -1; + if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + return UserHandle.getUid(userId, ps.appId); + } } - p = ps.pkg; - return p != null ? UserHandle.getUid(userId, p.applicationInfo.uid) : -1; } + + return -1; } @Override - public int[] getPackageGids(String packageName, int userId) throws RemoteException { + public int[] getPackageGids(String packageName, int userId) { + return getPackageGidsEtc(packageName, 0, userId); + } + + @Override + public int[] getPackageGidsEtc(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) { return null; } @@ -2907,14 +2922,17 @@ public class PackageManagerService extends IPackageManager.Stub { // reader synchronized (mPackages) { - PackageParser.Package p = mPackages.get(packageName); - if (DEBUG_PACKAGE_INFO) { - Log.v(TAG, "getPackageGids" + packageName + ": " + p); - } + final PackageParser.Package p = mPackages.get(packageName); if (p != null) { PackageSetting ps = (PackageSetting) p.mExtras; return ps.getPermissionsState().computeGids(userId); } + if ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + return ps.getPermissionsState().computeGids(userId); + } + } } return null; @@ -3676,7 +3694,8 @@ public class PackageManagerService extends IPackageManager.Stub { killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED); } }); - } break; + } + break; } mOnPermissionChangeListeners.onPermissionsChanged(uid); @@ -4947,18 +4966,13 @@ public class PackageManagerService extends IPackageManager.Stub { // First try to add the "always" resolution(s) for the current user, if any if (alwaysList.size() > 0) { result.addAll(alwaysList); - // if there is an "always" for the parent user, add it. - } else if (xpDomainInfo != null && xpDomainInfo.bestDomainVerificationStatus - == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { - result.add(xpDomainInfo.resolveInfo); } else { // Add all undefined apps as we want them to appear in the disambiguation dialog. result.addAll(undefinedList); + // Maybe add one for the other profile. if (xpDomainInfo != null && ( xpDomainInfo.bestDomainVerificationStatus - == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED - || xpDomainInfo.bestDomainVerificationStatus - == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK)) { + != INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER)) { result.add(xpDomainInfo.resolveInfo); } includeBrowser = true; @@ -6327,41 +6341,6 @@ public class PackageManagerService extends IPackageManager.Stub { it.remove(); } } - // Give priority to system apps. - for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) { - PackageParser.Package pkg = it.next(); - if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Adding system app " + sortedPkgs.size() + ": " + pkg.packageName); - } - sortedPkgs.add(pkg); - it.remove(); - } - } - // Give priority to updated system apps. - for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) { - PackageParser.Package pkg = it.next(); - if (pkg.isUpdatedSystemApp()) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Adding updated system app " + sortedPkgs.size() + ": " + pkg.packageName); - } - sortedPkgs.add(pkg); - it.remove(); - } - } - // Give priority to apps that listen for boot complete. - intent = new Intent(Intent.ACTION_BOOT_COMPLETED); - pkgNames = getPackageNamesForIntent(intent); - for (Iterator<PackageParser.Package> it = pkgs.iterator(); it.hasNext();) { - PackageParser.Package pkg = it.next(); - if (pkgNames.contains(pkg.packageName)) { - if (DEBUG_DEXOPT) { - Log.i(TAG, "Adding boot app " + sortedPkgs.size() + ": " + pkg.packageName); - } - sortedPkgs.add(pkg); - it.remove(); - } - } // Filter out packages that aren't recently used. filterRecentlyUsedApps(pkgs); // Add all remaining apps. @@ -7926,8 +7905,8 @@ public class PackageManagerService extends IPackageManager.Stub { // We would never need to extract libs for forward-locked and external packages, // since the container service will do it for us. We shouldn't attempt to // extract libs from system app when it was not updated. - if (pkg.isForwardLocked() || isExternal(pkg) || - (isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) ) { + if (pkg.isForwardLocked() || pkg.applicationInfo.isExternalAsec() || + (isSystemApp(pkg) && !pkg.isUpdatedSystemApp())) { extractLibs = false; } @@ -8502,7 +8481,7 @@ public class PackageManagerService extends IPackageManager.Stub { final String codePath = pkg.codePath; final File codeFile = new File(codePath); final boolean bundledApp = info.isSystemApp() && !info.isUpdatedSystemApp(); - final boolean asecApp = info.isForwardLocked() || isExternal(info); + final boolean asecApp = info.isForwardLocked() || info.isExternalAsec(); info.nativeLibraryRootDir = null; info.nativeLibraryRootRequiresIsa = false; @@ -8907,8 +8886,14 @@ public class PackageManagerService extends IPackageManager.Stub { static final int UPDATE_PERMISSIONS_REPLACE_PKG = 1<<1; static final int UPDATE_PERMISSIONS_REPLACE_ALL = 1<<2; + private void updatePermissionsLPw(String changingPkg, PackageParser.Package pkgInfo, + int flags) { + final String volumeUuid = (pkgInfo != null) ? getVolumeUuidForPackage(pkgInfo) : null; + updatePermissionsLPw(changingPkg, pkgInfo, volumeUuid, flags); + } + private void updatePermissionsLPw(String changingPkg, - PackageParser.Package pkgInfo, int flags) { + PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags) { // Make sure there are no dangling permission trees. Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator(); while (it.hasNext()) { @@ -8977,14 +8962,21 @@ public class PackageManagerService extends IPackageManager.Stub { if ((flags&UPDATE_PERMISSIONS_ALL) != 0) { for (PackageParser.Package pkg : mPackages.values()) { if (pkg != pkgInfo) { - grantPermissionsLPw(pkg, (flags&UPDATE_PERMISSIONS_REPLACE_ALL) != 0, - changingPkg); + // Only replace for packages on requested volume + final String volumeUuid = getVolumeUuidForPackage(pkg); + final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0) + && Objects.equals(replaceVolumeUuid, volumeUuid); + grantPermissionsLPw(pkg, replace, changingPkg); } } } if (pkgInfo != null) { - grantPermissionsLPw(pkgInfo, (flags&UPDATE_PERMISSIONS_REPLACE_PKG) != 0, changingPkg); + // Only replace for packages on requested volume + final String volumeUuid = getVolumeUuidForPackage(pkgInfo); + final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0) + && Objects.equals(replaceVolumeUuid, volumeUuid); + grantPermissionsLPw(pkgInfo, replace, changingPkg); } } @@ -9011,6 +9003,7 @@ public class PackageManagerService extends IPackageManager.Stub { final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); + boolean runtimePermissionsRevoked = false; int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY; boolean changedInstallPermission = false; @@ -9020,6 +9013,17 @@ public class PackageManagerService extends IPackageManager.Stub { if (!ps.isSharedUser()) { origPermissions = new PermissionsState(permissionsState); permissionsState.reset(); + } else { + // We need to know only about runtime permission changes since the + // calling code always writes the install permissions state but + // the runtime ones are written only if changed. The only cases of + // changed runtime permissions here are promotion of an install to + // runtime and revocation of a runtime from a shared user. + changedRuntimePermissionUserIds = revokeUnusedSharedUserPermissionsLPw( + ps.sharedUser, UserManagerService.getInstance().getUserIds()); + if (!ArrayUtils.isEmpty(changedRuntimePermissionUserIds)) { + runtimePermissionsRevoked = true; + } } } @@ -9235,9 +9239,11 @@ public class PackageManagerService extends IPackageManager.Stub { ps.installPermissionsFixed = true; } - // Persist the runtime permissions state for users with changes. + // Persist the runtime permissions state for users with changes. If permissions + // were revoked because no app in the shared user declares them we have to + // write synchronously to avoid losing runtime permissions state. for (int userId : changedRuntimePermissionUserIds) { - mSettings.writeRuntimePermissionsForUserLPr(userId, false); + mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked); } } @@ -12762,6 +12768,66 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private int[] revokeUnusedSharedUserPermissionsLPw(SharedUserSetting su, int[] allUserIds) { + // Collect all used permissions in the UID + ArraySet<String> usedPermissions = new ArraySet<>(); + final int packageCount = su.packages.size(); + for (int i = 0; i < packageCount; i++) { + PackageSetting ps = su.packages.valueAt(i); + if (ps.pkg == null) { + continue; + } + final int requestedPermCount = ps.pkg.requestedPermissions.size(); + for (int j = 0; j < requestedPermCount; j++) { + String permission = ps.pkg.requestedPermissions.get(j); + BasePermission bp = mSettings.mPermissions.get(permission); + if (bp != null) { + usedPermissions.add(permission); + } + } + } + + PermissionsState permissionsState = su.getPermissionsState(); + // Prune install permissions + List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates(); + final int installPermCount = installPermStates.size(); + for (int i = installPermCount - 1; i >= 0; i--) { + PermissionState permissionState = installPermStates.get(i); + if (!usedPermissions.contains(permissionState.getName())) { + BasePermission bp = mSettings.mPermissions.get(permissionState.getName()); + if (bp != null) { + permissionsState.revokeInstallPermission(bp); + permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL, + PackageManager.MASK_PERMISSION_FLAGS, 0); + } + } + } + + int[] runtimePermissionChangedUserIds = EmptyArray.INT; + + // Prune runtime permissions + for (int userId : allUserIds) { + List<PermissionState> runtimePermStates = permissionsState + .getRuntimePermissionStates(userId); + final int runtimePermCount = runtimePermStates.size(); + for (int i = runtimePermCount - 1; i >= 0; i--) { + PermissionState permissionState = runtimePermStates.get(i); + if (!usedPermissions.contains(permissionState.getName())) { + BasePermission bp = mSettings.mPermissions.get(permissionState.getName()); + if (bp != null) { + permissionsState.revokeRuntimePermission(bp, userId); + permissionsState.updatePermissionFlags(bp, userId, + PackageManager.MASK_PERMISSION_FLAGS, 0); + runtimePermissionChangedUserIds = ArrayUtils.appendInt( + runtimePermissionChangedUserIds, userId); + } + } + } + } + + return runtimePermissionChangedUserIds; + } + private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName, String volumeUuid, int[] allUsers, boolean[] perUserInstalled, PackageInstalledInfo res, UserHandle user) { @@ -13259,6 +13325,18 @@ public class PackageManagerService extends IPackageManager.Stub { return installFlags; } + private String getVolumeUuidForPackage(PackageParser.Package pkg) { + if (isExternal(pkg)) { + if (TextUtils.isEmpty(pkg.volumeUuid)) { + return StorageManager.UUID_PRIMARY_PHYSICAL; + } else { + return pkg.volumeUuid; + } + } else { + return StorageManager.UUID_PRIVATE_INTERNAL; + } + } + private VersionInfo getSettingsVersionForPackage(PackageParser.Package pkg) { if (isExternal(pkg)) { if (TextUtils.isEmpty(pkg.volumeUuid)) { @@ -14301,7 +14379,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (ps != null) { libDirRoot = ps.legacyNativeLibraryPathString; } - if (p != null && (isExternal(p) || p.isForwardLocked())) { + if (p != null && (p.isForwardLocked() || p.applicationInfo.isExternalAsec())) { final long token = Binder.clearCallingIdentity(); try { String secureContainerId = cidFromCodePath(p.applicationInfo.getBaseCodePath()); @@ -16162,7 +16240,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (isMounted) { if (DEBUG_SD_INSTALL) Log.i(TAG, "Loading packages"); - loadMediaPackages(processCids, uidArr); + loadMediaPackages(processCids, uidArr, externalStorage); startCleaningPackages(); mInstallerService.onSecureContainersAvailable(); } else { @@ -16217,7 +16295,8 @@ public class PackageManagerService extends IPackageManager.Stub { * the cid is added to list of removeCids. We currently don't delete stale * containers. */ - private void loadMediaPackages(ArrayMap<AsecInstallArgs, String> processCids, int[] uidArr) { + private void loadMediaPackages(ArrayMap<AsecInstallArgs, String> processCids, int[] uidArr, + boolean externalStorage) { ArrayList<String> pkgList = new ArrayList<String>(); Set<AsecInstallArgs> keys = processCids.keySet(); @@ -16289,7 +16368,10 @@ public class PackageManagerService extends IPackageManager.Stub { // cases get permissions that the user didn't initially explicitly // allow... it would be nice to have some better way to handle // this situation. - final VersionInfo ver = mSettings.getExternalVersion(); + final VersionInfo ver = externalStorage ? mSettings.getExternalVersion() + : mSettings.getInternalVersion(); + final String volumeUuid = externalStorage ? StorageManager.UUID_PRIMARY_PHYSICAL + : StorageManager.UUID_PRIVATE_INTERNAL; int updateFlags = UPDATE_PERMISSIONS_ALL; if (ver.sdkVersion != mSdkVersion) { @@ -16297,7 +16379,7 @@ public class PackageManagerService extends IPackageManager.Stub { + mSdkVersion + "; regranting permissions for external"); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } - updatePermissionsLPw(null, null, updateFlags); + updatePermissionsLPw(null, null, volumeUuid, updateFlags); // Yay, everything is now upgraded ver.forceCurrent(); @@ -16431,7 +16513,7 @@ public class PackageManagerService extends IPackageManager.Stub { + mSdkVersion + "; regranting permissions for " + vol.fsUuid); updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; } - updatePermissionsLPw(null, null, updateFlags); + updatePermissionsLPw(null, null, vol.fsUuid, updateFlags); // Yay, everything is now upgraded ver.forceCurrent(); @@ -16605,13 +16687,18 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); final int moveId = mNextMoveId.getAndIncrement(); - try { - movePackageInternal(packageName, volumeUuid, moveId); - } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to move " + packageName, e); - mMoveCallbacks.notifyStatusChanged(moveId, - PackageManager.MOVE_FAILED_INTERNAL_ERROR); - } + mHandler.post(new Runnable() { + @Override + public void run() { + try { + movePackageInternal(packageName, volumeUuid, moveId); + } catch (PackageManagerException e) { + Slog.w(TAG, "Failed to move " + packageName, e); + mMoveCallbacks.notifyStatusChanged(moveId, + PackageManager.MOVE_FAILED_INTERNAL_ERROR); + } + } + }); return moveId; } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index e02e4da..635f46e 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -240,6 +240,7 @@ abstract class PackageSettingBase extends SettingBase { keySetData = base.keySetData; verificationInfo = base.verificationInfo; installerPackageName = base.installerPackageName; + volumeUuid = base.volumeUuid; } private PackageUserState modifyUserState(int userId) { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index da82853..7b95106 100755 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -545,7 +545,18 @@ final class Settings { ArrayList<String> removeStage = new ArrayList<String>(); for (Map.Entry<String,SharedUserSetting> entry : mSharedUsers.entrySet()) { final SharedUserSetting sus = entry.getValue(); - if (sus == null || sus.packages.size() == 0) { + if (sus == null) { + removeStage.add(entry.getKey()); + continue; + } + // remove packages that are no longer installed + for (Iterator<PackageSetting> iter = sus.packages.iterator(); iter.hasNext();) { + PackageSetting ps = iter.next(); + if (mPackages.get(ps.name) == null) { + iter.remove(); + } + } + if (sus.packages.size() == 0) { removeStage.add(entry.getKey()); } } diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c8d329c..dd4d3ab 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3567,7 +3567,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Display task switcher for ALT-TAB. if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { - if (mRecentAppsHeldModifiers == 0 && !keyguardOn) { + if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) { final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { mRecentAppsHeldModifiers = shiftlessModifiers; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 0f45e39..342a2ac 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1112,6 +1112,8 @@ class WindowStateAnimator { mAnimator.getScreenRotationAnimationLocked(displayId); final boolean screenAnimation = screenRotationAnimation != null && screenRotationAnimation.isAnimating(); + + mHasClipRect = false; if (selfTransformation || attachedTransformation != null || appTransformation != null || screenAnimation) { // cache often used attributes locally @@ -1187,7 +1189,6 @@ class WindowStateAnimator { // transforming since it is more important to have that // animation be smooth. mShownAlpha = mAlpha; - mHasClipRect = false; if (!mService.mLimitedAlphaCompositing || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format) || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy) |