diff options
author | 2017-12-15 00:46:24 +0000 | |
---|---|---|
committer | 2017-12-15 00:46:24 +0000 | |
commit | d361a51596790be25ac7be9fd8fe80e2da8e5df0 (patch) | |
tree | 3a21efec881e2a5654726408e9483e134a25679e | |
parent | f8f9e5da97af5a2ae644c0106efd1017726767e7 (diff) | |
parent | 9388519d5e66a84485f8951242b9756e586a85ac (diff) |
Merge "Don't allow certain bucket overrides"
3 files changed, 126 insertions, 67 deletions
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java index 86ce90c03ae4..b792d821ae93 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java @@ -18,9 +18,14 @@ package com.android.server.usage; import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN; import static android.app.usage.UsageEvents.Event.USER_INTERACTION; +import static android.app.usage.UsageStatsManager.REASON_DEFAULT; +import static android.app.usage.UsageStatsManager.REASON_FORCED; import static android.app.usage.UsageStatsManager.REASON_PREDICTED; +import static android.app.usage.UsageStatsManager.REASON_TIMEOUT; +import static android.app.usage.UsageStatsManager.REASON_USAGE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT; +import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; @@ -79,6 +84,7 @@ public class AppStandbyControllerTests { private static final long RARE_THRESHOLD = 48 * HOUR_MS; private MyInjector mInjector; + private AppStandbyController mController; static class MyContextWrapper extends ContextWrapper { PackageManager mockPm = mock(PackageManager.class); @@ -237,24 +243,23 @@ public class AppStandbyControllerTests { public void setUp() throws Exception { MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext()); mInjector = new MyInjector(myContext, Looper.getMainLooper()); + mController = setupController(); } @Test public void testCharging() throws Exception { - AppStandbyController controller = setupController(); - - setChargingState(controller, true); + setChargingState(mController, true); mInjector.mElapsedRealtime = RARE_THRESHOLD + 1; - assertFalse(controller.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID, + assertFalse(mController.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime, false)); - setChargingState(controller, false); + setChargingState(mController, false); mInjector.mElapsedRealtime = 2 * RARE_THRESHOLD + 2; - controller.checkIdleStates(USER_ID); - assertTrue(controller.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID, + mController.checkIdleStates(USER_ID); + assertTrue(mController.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime, false)); - setChargingState(controller, true); - assertFalse(controller.isAppIdleFilteredOrParoled(PACKAGE_1,USER_ID, + setChargingState(mController, true); + assertFalse(mController.isAppIdleFilteredOrParoled(PACKAGE_1,USER_ID, mInjector.mElapsedRealtime, false)); } @@ -282,112 +287,142 @@ public class AppStandbyControllerTests { @Test public void testBuckets() throws Exception { - AppStandbyController controller = setupController(); - - assertTimeout(controller, 0, UsageStatsManager.STANDBY_BUCKET_NEVER); + assertTimeout(mController, 0, STANDBY_BUCKET_NEVER); - reportEvent(controller, USER_INTERACTION, 0); + reportEvent(mController, USER_INTERACTION, 0); // ACTIVE bucket - assertTimeout(controller, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE); + assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE); // WORKING_SET bucket - assertTimeout(controller, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET); + assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET); // WORKING_SET bucket - assertTimeout(controller, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET); + assertTimeout(mController, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET); // FREQUENT bucket - assertTimeout(controller, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT); + assertTimeout(mController, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT); // RARE bucket - assertTimeout(controller, RARE_THRESHOLD + 1, STANDBY_BUCKET_RARE); + assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_RARE); - reportEvent(controller, USER_INTERACTION, RARE_THRESHOLD + 1); + reportEvent(mController, USER_INTERACTION, RARE_THRESHOLD + 1); - assertTimeout(controller, RARE_THRESHOLD + 1, STANDBY_BUCKET_ACTIVE); + assertTimeout(mController, RARE_THRESHOLD + 1, STANDBY_BUCKET_ACTIVE); // RARE bucket - assertTimeout(controller, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE); + assertTimeout(mController, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE); } @Test public void testScreenTimeAndBuckets() throws Exception { - AppStandbyController controller = setupController(); mInjector.setDisplayOn(false); - assertTimeout(controller, 0, UsageStatsManager.STANDBY_BUCKET_NEVER); + assertTimeout(mController, 0, STANDBY_BUCKET_NEVER); - reportEvent(controller, USER_INTERACTION, 0); + reportEvent(mController, USER_INTERACTION, 0); // ACTIVE bucket - assertTimeout(controller, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE); + assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE); // WORKING_SET bucket - assertTimeout(controller, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET); + assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET); // RARE bucket, should fail because the screen wasn't ON. mInjector.mElapsedRealtime = RARE_THRESHOLD + 1; - controller.checkIdleStates(USER_ID); - assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller)); + mController.checkIdleStates(USER_ID); + assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); mInjector.setDisplayOn(true); - assertTimeout(controller, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE); + assertTimeout(mController, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE); } @Test public void testForcedIdle() throws Exception { - AppStandbyController controller = setupController(); - setChargingState(controller, false); + setChargingState(mController, false); - controller.forceIdleState(PACKAGE_1, USER_ID, true); - assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller)); - assertTrue(controller.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); + mController.forceIdleState(PACKAGE_1, USER_ID, true); + assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); + assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); - controller.forceIdleState(PACKAGE_1, USER_ID, false); - assertEquals(STANDBY_BUCKET_ACTIVE, controller.getAppStandbyBucket(PACKAGE_1, USER_ID, 0, + mController.forceIdleState(PACKAGE_1, USER_ID, false); + assertEquals(STANDBY_BUCKET_ACTIVE, mController.getAppStandbyBucket(PACKAGE_1, USER_ID, 0, true)); - assertFalse(controller.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); + assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0)); } @Test public void testNotificationEvent() throws Exception { - AppStandbyController controller = setupController(); - setChargingState(controller, false); + setChargingState(mController, false); - reportEvent(controller, USER_INTERACTION, 0); - assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller)); + reportEvent(mController, USER_INTERACTION, 0); + assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); mInjector.mElapsedRealtime = 1; - reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime); - assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller)); + reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime); + assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); - controller.forceIdleState(PACKAGE_1, USER_ID, true); - reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime); - assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller)); + mController.forceIdleState(PACKAGE_1, USER_ID, true); + reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime); + assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController)); } @Test public void testPredictionTimedout() throws Exception { - AppStandbyController controller = setupController(); - setChargingState(controller, false); - controller.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, - REASON_PREDICTED + "CTS", 1 * HOUR_MS); + setChargingState(mController, false); + // Set it to timeout or usage, so that prediction can override it + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, + REASON_TIMEOUT, 1 * HOUR_MS); + assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); + + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, + REASON_PREDICTED + ":CTS", 1 * HOUR_MS); + assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); // Fast forward 12 hours mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD; - controller.checkIdleStates(USER_ID); + mController.checkIdleStates(USER_ID); // Should still be in predicted bucket, since prediction timeout is 1 day since prediction - assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller)); + assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); // Fast forward two more hours mInjector.mElapsedRealtime += 2 * HOUR_MS; - controller.checkIdleStates(USER_ID); + mController.checkIdleStates(USER_ID); // Should have now applied prediction timeout - assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller)); + assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController)); // Fast forward RARE bucket mInjector.mElapsedRealtime += RARE_THRESHOLD; - controller.checkIdleStates(USER_ID); + mController.checkIdleStates(USER_ID); // Should continue to apply prediction timeout - assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller)); + assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController)); + } + + @Test + public void testOverrides() throws Exception { + setChargingState(mController, false); + // Can force to NEVER + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, + REASON_FORCED, 1 * HOUR_MS); + assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController)); + + // Prediction can't override FORCED reason + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, + REASON_FORCED, 1 * HOUR_MS); + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, + REASON_PREDICTED, 1 * HOUR_MS); + assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController)); + + // Prediction can't override NEVER + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, + REASON_DEFAULT, 2 * HOUR_MS); + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, + REASON_PREDICTED, 2 * HOUR_MS); + assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController)); + + // Prediction can't set to NEVER + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, + REASON_USAGE, 2 * HOUR_MS); + mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, + REASON_PREDICTED, 2 * HOUR_MS); + assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController)); } } diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java index 46efbd059d52..cc0259ddaa2b 100644 --- a/services/usage/java/com/android/server/usage/AppStandbyController.java +++ b/services/usage/java/com/android/server/usage/AppStandbyController.java @@ -24,6 +24,7 @@ import static android.app.usage.UsageStatsManager.REASON_USAGE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT; +import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE; import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET; @@ -133,7 +134,7 @@ public class AppStandbyController { @GuardedBy("mAppIdleLock") private AppIdleHistory mAppIdleHistory; - @GuardedBy("mAppIdleLock") + @GuardedBy("mPackageAccessListeners") private ArrayList<AppIdleStateChangeListener> mPackageAccessListeners = new ArrayList<>(); @@ -592,7 +593,7 @@ public class AppStandbyController { } void addListener(AppIdleStateChangeListener listener) { - synchronized (mAppIdleLock) { + synchronized (mPackageAccessListeners) { if (!mPackageAccessListeners.contains(listener)) { mPackageAccessListeners.add(listener); } @@ -600,7 +601,7 @@ public class AppStandbyController { } void removeListener(AppIdleStateChangeListener listener) { - synchronized (mAppIdleLock) { + synchronized (mPackageAccessListeners) { mPackageAccessListeners.remove(listener); } } @@ -789,6 +790,19 @@ public class AppStandbyController { void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, String reason, long elapsedRealtime) { synchronized (mAppIdleLock) { + AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName, + userId, elapsedRealtime); + boolean predicted = reason != null && reason.startsWith(REASON_PREDICTED); + // Don't allow changing bucket if higher than ACTIVE + if (app.currentBucket < STANDBY_BUCKET_ACTIVE) return; + // Don't allow prediction to change from or to NEVER + if ((app.currentBucket == STANDBY_BUCKET_NEVER + || newBucket == STANDBY_BUCKET_NEVER) + && predicted) { + return; + } + // If the bucket was forced, don't allow prediction to override + if (app.bucketingReason.equals(REASON_FORCED) && predicted) return; mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket, reason); } @@ -852,15 +866,19 @@ public class AppStandbyController { void informListeners(String packageName, int userId, int bucket) { final boolean idle = bucket >= STANDBY_BUCKET_RARE; - for (AppIdleStateChangeListener listener : mPackageAccessListeners) { - listener.onAppIdleStateChanged(packageName, userId, idle, bucket); + synchronized (mPackageAccessListeners) { + for (AppIdleStateChangeListener listener : mPackageAccessListeners) { + listener.onAppIdleStateChanged(packageName, userId, idle, bucket); + } } } void informParoleStateChanged() { final boolean paroled = isParoledOrCharging(); - for (AppIdleStateChangeListener listener : mPackageAccessListeners) { - listener.onParoleStateChanged(paroled); + synchronized (mPackageAccessListeners) { + for (AppIdleStateChangeListener listener : mPackageAccessListeners) { + listener.onParoleStateChanged(paroled); + } } } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 15284d5e3dec..07c860b54413 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -728,6 +728,10 @@ public class UsageStatsService extends SystemService implements } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } + final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID; + final String reason = shellCaller + ? UsageStatsManager.REASON_FORCED + : UsageStatsManager.REASON_PREDICTED + ":" + callingUid; final long token = Binder.clearCallingIdentity(); try { // Caller cannot set their own standby state @@ -735,8 +739,7 @@ public class UsageStatsService extends SystemService implements PackageManager.MATCH_ANY_USER, userId) == callingUid) { throw new IllegalArgumentException("Cannot set your own standby bucket"); } - mAppStandby.setAppStandbyBucket(packageName, userId, bucket, - UsageStatsManager.REASON_PREDICTED + ":" + callingUid, + mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason, SystemClock.elapsedRealtime()); } finally { Binder.restoreCallingIdentity(token); @@ -779,6 +782,10 @@ public class UsageStatsService extends SystemService implements } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } + final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID; + final String reason = shellCaller + ? UsageStatsManager.REASON_FORCED + : UsageStatsManager.REASON_PREDICTED + ":" + callingUid; final long token = Binder.clearCallingIdentity(); try { final long elapsedRealtime = SystemClock.elapsedRealtime(); @@ -796,8 +803,7 @@ public class UsageStatsService extends SystemService implements PackageManager.MATCH_ANY_USER, userId) == callingUid) { throw new IllegalArgumentException("Cannot set your own standby bucket"); } - mAppStandby.setAppStandbyBucket(packageName, userId, bucket, - UsageStatsManager.REASON_PREDICTED + ":" + callingUid, + mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason, elapsedRealtime); } } finally { |