summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKweku Adams <kwekua@google.com>2020-01-08 11:14:39 -0800
committerKweku Adams <kwekua@google.com>2020-01-09 12:33:44 -0800
commitc4ee998be8a13b4e808072a0ea0780dd1b2ecd9c (patch)
tree938f8379e50bc97025ede573d514123b52e63241
parent2a4b15a30f8b8ac70fb67b499249d49c1d5ea311 (diff)
Move setAppStandby logic inside AppStandbyController.
Since we've moved AppStandbyController inside the JobScheduler mainline module boundary, we need to move the logic of setAppStandby over so that it's consistent for callers and easy to do the right thing. Bug: 137763703 Bug: 145551233 Test: atest AppIdleHistoryTests Test: atest AppStandbyControllerTests Test: atest UsageStatsTest Change-Id: Ie2ccb0508c3a3887ab3debc47e78427477d2d77b
-rw-r--r--apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java15
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java58
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java48
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java68
4 files changed, 100 insertions, 89 deletions
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index 041825c235d0..6109b713de24 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -1,5 +1,6 @@
package com.android.server.usage;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.usage.AppStandbyInfo;
import android.app.usage.UsageEvents;
@@ -99,8 +100,18 @@ public interface AppStandbyInternal {
List<AppStandbyInfo> getAppStandbyBuckets(int userId);
- void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
- int reason, long elapsedRealtime, boolean resetTimeout);
+ /**
+ * Changes an app's standby bucket to the provided value. The caller can only set the standby
+ * bucket for a different app than itself.
+ */
+ void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId, int callingUid,
+ int callingPid);
+
+ /**
+ * Changes the app standby bucket for multiple apps at once.
+ */
+ void setAppStandbyBuckets(@NonNull List<AppStandbyInfo> appBuckets, int userId, int callingUid,
+ int callingPid);
void addActiveDeviceAdmin(String adminPkg, int userId);
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 2f8b5130edb0..58eb58961ac4 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -47,6 +47,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppGlobals;
@@ -101,7 +102,6 @@ import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.usage.AppIdleHistory.AppUsageHistory;
-import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
import java.io.File;
import java.io.PrintWriter;
@@ -109,6 +109,7 @@ import java.time.Duration;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -1014,14 +1015,57 @@ public class AppStandbyController implements AppStandbyInternal {
}
}
+ @Override
+ public void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId,
+ int callingUid, int callingPid) {
+ setAppStandbyBuckets(
+ Collections.singletonList(new AppStandbyInfo(packageName, bucket)),
+ userId, callingUid, callingPid);
+ }
+
+ @Override
+ public void setAppStandbyBuckets(@NonNull List<AppStandbyInfo> appBuckets, int userId,
+ int callingUid, int callingPid) {
+ userId = ActivityManager.handleIncomingUser(
+ callingPid, callingUid, userId, false, true, "setAppStandbyBucket", null);
+ final boolean shellCaller = callingUid == Process.ROOT_UID
+ || callingUid == Process.SHELL_UID;
+ final boolean systemCaller = UserHandle.isCore(callingUid);
+ final int reason = systemCaller ? REASON_MAIN_FORCED : REASON_MAIN_PREDICTED;
+ final int packageFlags = PackageManager.MATCH_ANY_USER
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE;
+ final int numApps = appBuckets.size();
+ final long elapsedRealtime = mInjector.elapsedRealtime();
+ for (int i = 0; i < numApps; ++i) {
+ final AppStandbyInfo bucketInfo = appBuckets.get(i);
+ final String packageName = bucketInfo.mPackageName;
+ final int bucket = bucketInfo.mStandbyBucket;
+ if (bucket < STANDBY_BUCKET_ACTIVE || bucket > STANDBY_BUCKET_NEVER) {
+ throw new IllegalArgumentException("Cannot set the standby bucket to " + bucket);
+ }
+ final int packageUid = mInjector.getPackageManagerInternal()
+ .getPackageUid(packageName, packageFlags, userId);
+ // Caller cannot set their own standby state
+ if (packageUid == callingUid) {
+ throw new IllegalArgumentException("Cannot set your own standby bucket");
+ }
+ if (packageUid < 0) {
+ throw new IllegalArgumentException(
+ "Cannot set standby bucket for non existent package (" + packageName + ")");
+ }
+ setAppStandbyBucket(packageName, userId, bucket, reason, elapsedRealtime, shellCaller);
+ }
+ }
+
@VisibleForTesting
void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
- int reason, long elapsedRealtime) {
- setAppStandbyBucket(packageName, userId, newBucket, reason, elapsedRealtime, false);
+ int reason) {
+ setAppStandbyBucket(
+ packageName, userId, newBucket, reason, mInjector.elapsedRealtime(), false);
}
- @Override
- public void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
+ private void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
int reason, long elapsedRealtime, boolean resetTimeout) {
synchronized (mAppIdleLock) {
// If the package is not installed, don't allow the bucket to be set.
@@ -1444,6 +1488,10 @@ public class AppStandbyController implements AppStandbyInternal {
mBatteryStats.noteEvent(event, packageName, uid);
}
+ PackageManagerInternal getPackageManagerInternal() {
+ return mPackageManagerInternal;
+ }
+
boolean isPackageEphemeral(int userId, String packageName) {
return mPackageManagerInternal.isPackageEphemeral(userId, packageName);
}
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 12ba219d0365..1dd7e64690c7 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -365,8 +365,9 @@ public class AppStandbyControllerTests {
public void testSetAppStandbyBucket() throws Exception {
// For a known package, standby bucket should be set properly
reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
+ mInjector.mElapsedRealtime = HOUR_MS;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
- REASON_MAIN_TIMEOUT, HOUR_MS);
+ REASON_MAIN_TIMEOUT);
assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
// For an unknown package, standby bucket should not be set, hence NEVER is returned
@@ -374,7 +375,7 @@ public class AppStandbyControllerTests {
mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID);
isPackageInstalled = false; // Mock package is not installed
mController.setAppStandbyBucket(PACKAGE_UNKNOWN, USER_ID, STANDBY_BUCKET_ACTIVE,
- REASON_MAIN_TIMEOUT, HOUR_MS);
+ REASON_MAIN_TIMEOUT);
isPackageInstalled = true; // Reset mocked variable for other tests
assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN));
}
@@ -468,12 +469,13 @@ public class AppStandbyControllerTests {
@Test
public void testPredictionTimedout() throws Exception {
// Set it to timeout or usage, so that prediction can override it
+ mInjector.mElapsedRealtime = HOUR_MS;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
- REASON_MAIN_TIMEOUT, HOUR_MS);
+ REASON_MAIN_TIMEOUT);
assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
- REASON_MAIN_PREDICTED, HOUR_MS);
+ REASON_MAIN_PREDICTED);
assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
// Fast forward 12 hours
@@ -497,29 +499,31 @@ public class AppStandbyControllerTests {
@Test
public void testOverrides() throws Exception {
// Can force to NEVER
+ mInjector.mElapsedRealtime = HOUR_MS;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_FORCED, 1 * HOUR_MS);
+ REASON_MAIN_FORCED);
assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
// Prediction can't override FORCED reason
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_FORCED, 1 * HOUR_MS);
+ REASON_MAIN_FORCED);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
- REASON_MAIN_PREDICTED, 1 * HOUR_MS);
+ REASON_MAIN_PREDICTED);
assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1));
// Prediction can't override NEVER
+ mInjector.mElapsedRealtime = 2 * HOUR_MS;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_DEFAULT, 2 * HOUR_MS);
+ REASON_MAIN_DEFAULT);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
- REASON_MAIN_PREDICTED, 2 * HOUR_MS);
+ REASON_MAIN_PREDICTED);
assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1));
// Prediction can't set to NEVER
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
- REASON_MAIN_USAGE, 2 * HOUR_MS);
+ REASON_MAIN_USAGE);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_PREDICTED, 2 * HOUR_MS);
+ REASON_MAIN_PREDICTED);
assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
}
@@ -530,7 +534,7 @@ public class AppStandbyControllerTests {
mInjector.mElapsedRealtime = 2000;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_ACTIVE);
// bucketing works after timeout
@@ -554,15 +558,17 @@ public class AppStandbyControllerTests {
assertBucket(STANDBY_BUCKET_ACTIVE);
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET,
- REASON_MAIN_PREDICTED, 1000);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_ACTIVE);
+ mInjector.mElapsedRealtime = 2000 + mController.mStrongUsageTimeoutMillis;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_PREDICTED, 2000 + mController.mStrongUsageTimeoutMillis);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_WORKING_SET);
+ mInjector.mElapsedRealtime = 2000 + mController.mNotificationSeenTimeoutMillis;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_PREDICTED, 2000 + mController.mNotificationSeenTimeoutMillis);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_FREQUENT);
}
@@ -582,18 +588,18 @@ public class AppStandbyControllerTests {
// Still in ACTIVE after first USER_INTERACTION times out
mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_ACTIVE);
// Both timed out, so NOTIFICATION_SEEN timeout should be effective
mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_WORKING_SET);
mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
- REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_RARE);
}
@@ -625,7 +631,7 @@ public class AppStandbyControllerTests {
mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100;
// Make sure app is in NEVER bucket
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER,
- REASON_MAIN_FORCED, mInjector.mElapsedRealtime);
+ REASON_MAIN_FORCED);
mController.checkIdleStates(USER_ID);
assertBucket(STANDBY_BUCKET_NEVER);
@@ -670,7 +676,7 @@ public class AppStandbyControllerTests {
// Predict to ACTIVE
mInjector.mElapsedRealtime += 1000;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
- REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_ACTIVE);
// CheckIdleStates should not change the prediction
@@ -687,7 +693,7 @@ public class AppStandbyControllerTests {
// Predict to FREQUENT
mInjector.mElapsedRealtime = RARE_THRESHOLD;
mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT,
- REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime);
+ REASON_MAIN_PREDICTED);
assertBucket(STANDBY_BUCKET_FREQUENT);
// Add a short timeout event
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index c900f386b438..8397aa485595 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1568,44 +1568,16 @@ public class UsageStatsService extends SystemService implements
}
@Override
- public void setAppStandbyBucket(String packageName,
- int bucket, int userId) {
+ public void setAppStandbyBucket(String packageName, int bucket, int userId) {
getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
"No permission to change app standby state");
- if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
- || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
- throw new IllegalArgumentException("Cannot set the standby bucket to " + bucket);
- }
final int callingUid = Binder.getCallingUid();
- try {
- userId = ActivityManager.getService().handleIncomingUser(
- Binder.getCallingPid(), callingUid, userId, false, true,
- "setAppStandbyBucket", null);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
- final boolean systemCaller = UserHandle.isCore(callingUid);
- final int reason = systemCaller
- ? UsageStatsManager.REASON_MAIN_FORCED
- : UsageStatsManager.REASON_MAIN_PREDICTED;
+ final int callingPid = Binder.getCallingPid();
final long token = Binder.clearCallingIdentity();
try {
- final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
- PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
- | PackageManager.MATCH_DIRECT_BOOT_AWARE, userId);
- // Caller cannot set their own standby state
- if (packageUid == callingUid) {
- throw new IllegalArgumentException("Cannot set your own standby bucket");
- }
- if (packageUid < 0) {
- throw new IllegalArgumentException(
- "Cannot set standby bucket for non existent package (" + packageName
- + ")");
- }
- mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
- SystemClock.elapsedRealtime(), shellCaller);
+ mAppStandby.setAppStandbyBucket(packageName, bucket, userId,
+ callingUid, callingPid);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1643,37 +1615,11 @@ public class UsageStatsService extends SystemService implements
"No permission to change app standby state");
final int callingUid = Binder.getCallingUid();
- try {
- userId = ActivityManager.getService().handleIncomingUser(
- Binder.getCallingPid(), callingUid, userId, false, true,
- "setAppStandbyBucket", null);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
- final int reason = shellCaller
- ? UsageStatsManager.REASON_MAIN_FORCED
- : UsageStatsManager.REASON_MAIN_PREDICTED;
+ final int callingPid = Binder.getCallingPid();
final long token = Binder.clearCallingIdentity();
try {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- List<AppStandbyInfo> bucketList = appBuckets.getList();
- for (AppStandbyInfo bucketInfo : bucketList) {
- final String packageName = bucketInfo.mPackageName;
- final int bucket = bucketInfo.mStandbyBucket;
- if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
- || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
- throw new IllegalArgumentException(
- "Cannot set the standby bucket to " + bucket);
- }
- // Caller cannot set their own standby state
- if (mPackageManagerInternal.getPackageUid(packageName,
- PackageManager.MATCH_ANY_USER, userId) == callingUid) {
- throw new IllegalArgumentException("Cannot set your own standby bucket");
- }
- mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
- elapsedRealtime, shellCaller);
- }
+ mAppStandby.setAppStandbyBuckets(appBuckets.getList(), userId,
+ callingUid, callingPid);
} finally {
Binder.restoreCallingIdentity(token);
}