summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/am/AppBatteryTracker.java4
-rw-r--r--services/core/java/com/android/server/am/AppRestrictionController.java193
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java14
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,