diff options
3 files changed, 123 insertions, 88 deletions
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java index 655e30982091..7579d2bc78fd 100644 --- a/services/core/java/com/android/server/am/AppBatteryTracker.java +++ b/services/core/java/com/android/server/am/AppBatteryTracker.java @@ -1531,7 +1531,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> if (excessive) { if (DEBUG_BACKGROUND_BATTERY_TRACKER) { - Slog.i(TAG, "Excessive background current drain " + uid + Slog.i(TAG, "Excessive background current drain " + uid + " " + usage + " (" + usage.percentageToString() + " ) over " + TimeUtils.formatDuration(mBgCurrentDrainWindowMs)); } @@ -1542,7 +1542,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy> } } else { if (DEBUG_BACKGROUND_BATTERY_TRACKER) { - Slog.i(TAG, "Background current drain backs to normal " + uid + Slog.i(TAG, "Background current drain backs to normal " + uid + " " + usage + " (" + usage.percentageToString() + " ) over " + TimeUtils.formatDuration(mBgCurrentDrainWindowMs)); } diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java index 2ffd48739e47..4d5384c17f1f 100644 --- a/services/core/java/com/android/server/am/AppRestrictionController.java +++ b/services/core/java/com/android/server/am/AppRestrictionController.java @@ -87,7 +87,6 @@ import android.app.ActivityManager; import android.app.ActivityManager.RestrictionLevel; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal.AppBackgroundRestrictionListener; -import android.app.ActivityThread; import android.app.AppOpsManager; import android.app.IActivityManager; import android.app.IUidObserver; @@ -257,6 +256,89 @@ public final class AppRestrictionController { final ActivityManagerService mActivityManagerService; + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + switch (intent.getAction()) { + case Intent.ACTION_PACKAGE_ADDED: { + if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + if (uid >= 0) { + onUidAdded(uid); + } + } + } + // fall through. + case Intent.ACTION_PACKAGE_CHANGED: { + final String pkgName = intent.getData().getSchemeSpecificPart(); + final String[] cmpList = intent.getStringArrayExtra( + Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); + // If this is PACKAGE_ADDED (cmpList == null), or if it's a whole-package + // enable/disable event (cmpList is just the package name itself), drop + // our carrier privileged app & system-app caches and let them refresh + if (cmpList == null + || (cmpList.length == 1 && pkgName.equals(cmpList[0]))) { + clearCarrierPrivilegedApps(); + } + } break; + case Intent.ACTION_PACKAGE_FULLY_REMOVED: { + final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + final Uri data = intent.getData(); + String ssp; + if (uid >= 0 && data != null + && (ssp = data.getSchemeSpecificPart()) != null) { + onPackageRemoved(ssp, uid); + } + } break; + case Intent.ACTION_UID_REMOVED: { + if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + if (uid >= 0) { + onUidRemoved(uid); + } + } + } break; + case Intent.ACTION_USER_ADDED: { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (userId >= 0) { + onUserAdded(userId); + } + } break; + case Intent.ACTION_USER_STARTED: { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (userId >= 0) { + onUserStarted(userId); + } + } break; + case Intent.ACTION_USER_STOPPED: { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (userId >= 0) { + onUserStopped(userId); + } + } break; + case Intent.ACTION_USER_REMOVED: { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (userId >= 0) { + onUserRemoved(userId); + } + } break; + } + } + }; + + private final BroadcastReceiver mBootReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + switch (intent.getAction()) { + case Intent.ACTION_LOCKED_BOOT_COMPLETED: { + onLockedBootCompleted(); + } break; + } + } + }; + /** * The restriction levels that each package is on, the levels here are defined in * {@link android.app.ActivityManager.RESTRICTION_LEVEL_*}. @@ -804,7 +886,7 @@ public final class AppRestrictionController { void onSystemReady() { DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, - ActivityThread.currentApplication().getMainExecutor(), mConstantsObserver); + mBgExecutor, mConstantsObserver); mConstantsObserver.start(); initBgRestrictionExemptioFromSysConfig(); initRestrictionStates(); @@ -830,6 +912,13 @@ public final class AppRestrictionController { initRestrictionStates(); } + @VisibleForTesting + void tearDown() { + DeviceConfig.removeOnPropertiesChangedListener(mConstantsObserver); + unregisterForUidObservers(); + unregisterForSystemBroadcasts(); + } + private void initBgRestrictionExemptioFromSysConfig() { mBgRestrictionExemptioFromSysConfig = SystemConfig.getInstance().getBgRestrictionExemption(); @@ -912,6 +1001,14 @@ public final class AppRestrictionController { } } + private void unregisterForUidObservers() { + try { + mInjector.getIActivityManager().unregisterUidObserver(mUidObserver); + } catch (RemoteException e) { + // Intra-process call, it won't happen. + } + } + /** * Called when initializing a user. */ @@ -2147,104 +2244,28 @@ public final class AppRestrictionController { } private void registerForSystemBroadcasts() { - final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - switch (intent.getAction()) { - case Intent.ACTION_PACKAGE_ADDED: { - if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); - if (uid >= 0) { - onUidAdded(uid); - } - } - } - // fall through. - case Intent.ACTION_PACKAGE_CHANGED: { - final String pkgName = intent.getData().getSchemeSpecificPart(); - final String[] cmpList = intent.getStringArrayExtra( - Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); - // If this is PACKAGE_ADDED (cmpList == null), or if it's a whole-package - // enable/disable event (cmpList is just the package name itself), drop - // our carrier privileged app & system-app caches and let them refresh - if (cmpList == null - || (cmpList.length == 1 && pkgName.equals(cmpList[0]))) { - clearCarrierPrivilegedApps(); - } - } break; - case Intent.ACTION_PACKAGE_FULLY_REMOVED: { - final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); - final Uri data = intent.getData(); - String ssp; - if (uid >= 0 && data != null - && (ssp = data.getSchemeSpecificPart()) != null) { - onPackageRemoved(ssp, uid); - } - } break; - case Intent.ACTION_UID_REMOVED: { - if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); - if (uid >= 0) { - onUidRemoved(uid); - } - } - } break; - case Intent.ACTION_USER_ADDED: { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userId >= 0) { - onUserAdded(userId); - } - } break; - case Intent.ACTION_USER_STARTED: { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userId >= 0) { - onUserStarted(userId); - } - } break; - case Intent.ACTION_USER_STOPPED: { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userId >= 0) { - onUserStopped(userId); - } - } break; - case Intent.ACTION_USER_REMOVED: { - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userId >= 0) { - onUserRemoved(userId); - } - } break; - } - } - }; final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); packageFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED); packageFilter.addDataScheme("package"); - mContext.registerReceiverForAllUsers(broadcastReceiver, packageFilter, null, mBgHandler); + mContext.registerReceiverForAllUsers(mBroadcastReceiver, packageFilter, null, mBgHandler); final IntentFilter userFilter = new IntentFilter(); userFilter.addAction(Intent.ACTION_USER_ADDED); userFilter.addAction(Intent.ACTION_USER_REMOVED); userFilter.addAction(Intent.ACTION_UID_REMOVED); - mContext.registerReceiverForAllUsers(broadcastReceiver, userFilter, null, mBgHandler); - final BroadcastReceiver bootReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - switch (intent.getAction()) { - case Intent.ACTION_LOCKED_BOOT_COMPLETED: { - onLockedBootCompleted(); - } break; - } - } - }; + mContext.registerReceiverForAllUsers(mBroadcastReceiver, userFilter, null, mBgHandler); final IntentFilter bootFilter = new IntentFilter(); bootFilter.addAction(Intent.ACTION_LOCKED_BOOT_COMPLETED); - mContext.registerReceiverAsUser(bootReceiver, UserHandle.SYSTEM, + mContext.registerReceiverAsUser(mBootReceiver, UserHandle.SYSTEM, bootFilter, null, mBgHandler); } + private void unregisterForSystemBroadcasts() { + mContext.unregisterReceiver(mBroadcastReceiver); + mContext.unregisterReceiver(mBootReceiver); + } + void forEachTracker(Consumer<BaseAppStateTracker> sink) { for (int i = 0, size = mAppStateTrackers.size(); i < size; i++) { sink.accept(mAppStateTrackers.get(i)); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java index e6bb0ce318fe..053551309661 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java @@ -345,6 +345,7 @@ public final class BackgroundRestrictionTest { @After public void tearDown() { + mBgRestrictionController.tearDown(); mBgRestrictionController.getBackgroundHandlerThread().quitSafely(); } @@ -561,6 +562,7 @@ public final class BackgroundRestrictionTest { DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null; DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null; DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null; + DeviceConfigSession<Long> bgNotificationMinInterval = null; mBgRestrictionController.addAppBackgroundRestrictionListener(listener); @@ -615,6 +617,13 @@ public final class BackgroundRestrictionTest { R.bool.config_bg_prompt_fgs_with_noti_to_bg_restricted)); bgPromptFgsWithNotiToBgRestricted.set(true); + bgNotificationMinInterval = new DeviceConfigSession<>( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + ConstantsObserver.KEY_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL, + DeviceConfig::getLong, + ConstantsObserver.DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS); + bgNotificationMinInterval.set(windowMs); + mCurrentTimeMillis = 10_000L; doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp(); doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp(); @@ -754,6 +763,7 @@ public final class BackgroundRestrictionTest { // Sleep a while and set a higher drain Thread.sleep(windowMs); clearInvocations(mInjector.getAppStandbyInternal()); + clearInvocations(mInjector.getNotificationManager()); clearInvocations(mBgRestrictionController); // We're not going to prompt the user if the abusive app has a FGS with notification. @@ -794,6 +804,7 @@ public final class BackgroundRestrictionTest { mAppFGSTracker.onForegroundServiceNotificationUpdated( testPkgName, testUid, -notificationId); clearInvocations(mInjector.getAppStandbyInternal()); + clearInvocations(mInjector.getNotificationManager()); clearInvocations(mBgRestrictionController); runTestBgCurrentDrainMonitorOnce(listener, stats, uids, @@ -832,6 +843,7 @@ public final class BackgroundRestrictionTest { // Now we'll prompt the user even it has a FGS with notification. bgPromptFgsWithNotiToBgRestricted.set(true); clearInvocations(mInjector.getAppStandbyInternal()); + clearInvocations(mInjector.getNotificationManager()); clearInvocations(mBgRestrictionController); runTestBgCurrentDrainMonitorOnce(listener, stats, uids, @@ -899,6 +911,7 @@ public final class BackgroundRestrictionTest { closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold); closeIfNotNull(bgCurrentDrainBgRestrictedThreshold); closeIfNotNull(bgPromptFgsWithNotiToBgRestricted); + closeIfNotNull(bgNotificationMinInterval); } } @@ -1921,6 +1934,7 @@ public final class BackgroundRestrictionTest { .checkUidPermission(uid, perm); mInjector.getAppPermissionTracker().onPermissionsChanged(uid); } + waitForIdleHandler(mBgRestrictionController.getBackgroundHandler()); runExemptionTestOnce( packageName, uid, pid, serviceType, sleepMs, stopAfterSleep, perm, mediaControllers, topStateChanges, resetFGSTracker, false, |