Loading apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java +13 −2 Original line number Original line Diff line number Diff line package com.android.server.usage; package com.android.server.usage; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.usage.AppStandbyInfo; import android.app.usage.AppStandbyInfo; import android.app.usage.UsageEvents; import android.app.usage.UsageEvents; Loading Loading @@ -99,8 +100,18 @@ public interface AppStandbyInternal { List<AppStandbyInfo> getAppStandbyBuckets(int userId); 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); void addActiveDeviceAdmin(String adminPkg, int userId); Loading apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +53 −5 Original line number Original line Diff line number Diff line Loading @@ -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 static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppGlobals; Loading Loading @@ -101,7 +102,6 @@ import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.LocalServices; import com.android.server.usage.AppIdleHistory.AppUsageHistory; import com.android.server.usage.AppIdleHistory.AppUsageHistory; import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; import java.io.File; import java.io.File; import java.io.PrintWriter; import java.io.PrintWriter; Loading @@ -109,6 +109,7 @@ import java.time.Duration; import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Set; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch; Loading Loading @@ -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 @VisibleForTesting void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, int reason, long elapsedRealtime) { int reason) { setAppStandbyBucket(packageName, userId, newBucket, reason, elapsedRealtime, false); setAppStandbyBucket( packageName, userId, newBucket, reason, mInjector.elapsedRealtime(), false); } } @Override private void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, public void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, int reason, long elapsedRealtime, boolean resetTimeout) { int reason, long elapsedRealtime, boolean resetTimeout) { synchronized (mAppIdleLock) { synchronized (mAppIdleLock) { // If the package is not installed, don't allow the bucket to be set. // If the package is not installed, don't allow the bucket to be set. Loading Loading @@ -1444,6 +1488,10 @@ public class AppStandbyController implements AppStandbyInternal { mBatteryStats.noteEvent(event, packageName, uid); mBatteryStats.noteEvent(event, packageName, uid); } } PackageManagerInternal getPackageManagerInternal() { return mPackageManagerInternal; } boolean isPackageEphemeral(int userId, String packageName) { boolean isPackageEphemeral(int userId, String packageName) { return mPackageManagerInternal.isPackageEphemeral(userId, packageName); return mPackageManagerInternal.isPackageEphemeral(userId, packageName); } } Loading services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +27 −21 Original line number Original line Diff line number Diff line Loading @@ -365,8 +365,9 @@ public class AppStandbyControllerTests { public void testSetAppStandbyBucket() throws Exception { public void testSetAppStandbyBucket() throws Exception { // For a known package, standby bucket should be set properly // For a known package, standby bucket should be set properly reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); mInjector.mElapsedRealtime = HOUR_MS; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 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)); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); // For an unknown package, standby bucket should not be set, hence NEVER is returned // For an unknown package, standby bucket should not be set, hence NEVER is returned Loading @@ -374,7 +375,7 @@ public class AppStandbyControllerTests { mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID); mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID); isPackageInstalled = false; // Mock package is not installed isPackageInstalled = false; // Mock package is not installed mController.setAppStandbyBucket(PACKAGE_UNKNOWN, USER_ID, STANDBY_BUCKET_ACTIVE, 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 isPackageInstalled = true; // Reset mocked variable for other tests assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN)); assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN)); } } Loading Loading @@ -468,12 +469,13 @@ public class AppStandbyControllerTests { @Test @Test public void testPredictionTimedout() throws Exception { public void testPredictionTimedout() throws Exception { // Set it to timeout or usage, so that prediction can override it // 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, 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)); assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 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)); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); // Fast forward 12 hours // Fast forward 12 hours Loading @@ -497,29 +499,31 @@ public class AppStandbyControllerTests { @Test @Test public void testOverrides() throws Exception { public void testOverrides() throws Exception { // Can force to NEVER // Can force to NEVER mInjector.mElapsedRealtime = HOUR_MS; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 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)); assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); // Prediction can't override FORCED reason // Prediction can't override FORCED reason mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 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, 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)); assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1)); // Prediction can't override NEVER // Prediction can't override NEVER mInjector.mElapsedRealtime = 2 * HOUR_MS; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 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, 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)); assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); // Prediction can't set to NEVER // Prediction can't set to NEVER mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 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, 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)); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); } } Loading @@ -530,7 +534,7 @@ public class AppStandbyControllerTests { mInjector.mElapsedRealtime = 2000; mInjector.mElapsedRealtime = 2000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); // bucketing works after timeout // bucketing works after timeout Loading @@ -554,15 +558,17 @@ public class AppStandbyControllerTests { assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, REASON_MAIN_PREDICTED, 1000); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); mInjector.mElapsedRealtime = 2000 + mController.mStrongUsageTimeoutMillis; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, 2000 + mController.mStrongUsageTimeoutMillis); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_WORKING_SET); assertBucket(STANDBY_BUCKET_WORKING_SET); mInjector.mElapsedRealtime = 2000 + mController.mNotificationSeenTimeoutMillis; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, 2000 + mController.mNotificationSeenTimeoutMillis); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_FREQUENT); assertBucket(STANDBY_BUCKET_FREQUENT); } } Loading @@ -582,18 +588,18 @@ public class AppStandbyControllerTests { // Still in ACTIVE after first USER_INTERACTION times out // Still in ACTIVE after first USER_INTERACTION times out mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000; mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); // Both timed out, so NOTIFICATION_SEEN timeout should be effective // Both timed out, so NOTIFICATION_SEEN timeout should be effective mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000; mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_WORKING_SET); assertBucket(STANDBY_BUCKET_WORKING_SET); mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000; mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_RARE); assertBucket(STANDBY_BUCKET_RARE); } } Loading Loading @@ -625,7 +631,7 @@ public class AppStandbyControllerTests { mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100; mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100; // Make sure app is in NEVER bucket // Make sure app is in NEVER bucket mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, REASON_MAIN_FORCED, mInjector.mElapsedRealtime); REASON_MAIN_FORCED); mController.checkIdleStates(USER_ID); mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_NEVER); assertBucket(STANDBY_BUCKET_NEVER); Loading Loading @@ -670,7 +676,7 @@ public class AppStandbyControllerTests { // Predict to ACTIVE // Predict to ACTIVE mInjector.mElapsedRealtime += 1000; mInjector.mElapsedRealtime += 1000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); // CheckIdleStates should not change the prediction // CheckIdleStates should not change the prediction Loading @@ -687,7 +693,7 @@ public class AppStandbyControllerTests { // Predict to FREQUENT // Predict to FREQUENT mInjector.mElapsedRealtime = RARE_THRESHOLD; mInjector.mElapsedRealtime = RARE_THRESHOLD; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_FREQUENT); assertBucket(STANDBY_BUCKET_FREQUENT); // Add a short timeout event // Add a short timeout event Loading services/usage/java/com/android/server/usage/UsageStatsService.java +7 −61 Original line number Original line Diff line number Diff line Loading @@ -1568,44 +1568,16 @@ public class UsageStatsService extends SystemService implements } } @Override @Override public void setAppStandbyBucket(String packageName, public void setAppStandbyBucket(String packageName, int bucket, int userId) { int bucket, int userId) { getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, "No permission to change app standby 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(); final int callingUid = Binder.getCallingUid(); try { final int callingPid = Binder.getCallingPid(); 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 long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity(); try { try { final int packageUid = mPackageManagerInternal.getPackageUid(packageName, mAppStandby.setAppStandbyBucket(packageName, bucket, userId, PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DIRECT_BOOT_UNAWARE callingUid, callingPid); | 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); } finally { } finally { Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } Loading Loading @@ -1643,37 +1615,11 @@ public class UsageStatsService extends SystemService implements "No permission to change app standby state"); "No permission to change app standby state"); final int callingUid = Binder.getCallingUid(); final int callingUid = Binder.getCallingUid(); try { final int callingPid = Binder.getCallingPid(); 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 long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity(); try { try { final long elapsedRealtime = SystemClock.elapsedRealtime(); mAppStandby.setAppStandbyBuckets(appBuckets.getList(), userId, List<AppStandbyInfo> bucketList = appBuckets.getList(); callingUid, callingPid); 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); } } finally { } finally { Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } Loading Loading
apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java +13 −2 Original line number Original line Diff line number Diff line package com.android.server.usage; package com.android.server.usage; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.usage.AppStandbyInfo; import android.app.usage.AppStandbyInfo; import android.app.usage.UsageEvents; import android.app.usage.UsageEvents; Loading Loading @@ -99,8 +100,18 @@ public interface AppStandbyInternal { List<AppStandbyInfo> getAppStandbyBuckets(int userId); 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); void addActiveDeviceAdmin(String adminPkg, int userId); Loading
apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +53 −5 Original line number Original line Diff line number Diff line Loading @@ -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 static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppGlobals; Loading Loading @@ -101,7 +102,6 @@ import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.LocalServices; import com.android.server.usage.AppIdleHistory.AppUsageHistory; import com.android.server.usage.AppIdleHistory.AppUsageHistory; import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; import java.io.File; import java.io.File; import java.io.PrintWriter; import java.io.PrintWriter; Loading @@ -109,6 +109,7 @@ import java.time.Duration; import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.List; import java.util.Set; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch; Loading Loading @@ -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 @VisibleForTesting void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, int reason, long elapsedRealtime) { int reason) { setAppStandbyBucket(packageName, userId, newBucket, reason, elapsedRealtime, false); setAppStandbyBucket( packageName, userId, newBucket, reason, mInjector.elapsedRealtime(), false); } } @Override private void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, public void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket, int reason, long elapsedRealtime, boolean resetTimeout) { int reason, long elapsedRealtime, boolean resetTimeout) { synchronized (mAppIdleLock) { synchronized (mAppIdleLock) { // If the package is not installed, don't allow the bucket to be set. // If the package is not installed, don't allow the bucket to be set. Loading Loading @@ -1444,6 +1488,10 @@ public class AppStandbyController implements AppStandbyInternal { mBatteryStats.noteEvent(event, packageName, uid); mBatteryStats.noteEvent(event, packageName, uid); } } PackageManagerInternal getPackageManagerInternal() { return mPackageManagerInternal; } boolean isPackageEphemeral(int userId, String packageName) { boolean isPackageEphemeral(int userId, String packageName) { return mPackageManagerInternal.isPackageEphemeral(userId, packageName); return mPackageManagerInternal.isPackageEphemeral(userId, packageName); } } Loading
services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +27 −21 Original line number Original line Diff line number Diff line Loading @@ -365,8 +365,9 @@ public class AppStandbyControllerTests { public void testSetAppStandbyBucket() throws Exception { public void testSetAppStandbyBucket() throws Exception { // For a known package, standby bucket should be set properly // For a known package, standby bucket should be set properly reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1); mInjector.mElapsedRealtime = HOUR_MS; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 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)); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); // For an unknown package, standby bucket should not be set, hence NEVER is returned // For an unknown package, standby bucket should not be set, hence NEVER is returned Loading @@ -374,7 +375,7 @@ public class AppStandbyControllerTests { mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID); mController.clearAppIdleForPackage(PACKAGE_UNKNOWN, USER_ID); isPackageInstalled = false; // Mock package is not installed isPackageInstalled = false; // Mock package is not installed mController.setAppStandbyBucket(PACKAGE_UNKNOWN, USER_ID, STANDBY_BUCKET_ACTIVE, 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 isPackageInstalled = true; // Reset mocked variable for other tests assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN)); assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_UNKNOWN)); } } Loading Loading @@ -468,12 +469,13 @@ public class AppStandbyControllerTests { @Test @Test public void testPredictionTimedout() throws Exception { public void testPredictionTimedout() throws Exception { // Set it to timeout or usage, so that prediction can override it // 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, 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)); assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1)); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 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)); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); // Fast forward 12 hours // Fast forward 12 hours Loading @@ -497,29 +499,31 @@ public class AppStandbyControllerTests { @Test @Test public void testOverrides() throws Exception { public void testOverrides() throws Exception { // Can force to NEVER // Can force to NEVER mInjector.mElapsedRealtime = HOUR_MS; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 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)); assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); // Prediction can't override FORCED reason // Prediction can't override FORCED reason mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, 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, 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)); assertEquals(STANDBY_BUCKET_FREQUENT, getStandbyBucket(mController, PACKAGE_1)); // Prediction can't override NEVER // Prediction can't override NEVER mInjector.mElapsedRealtime = 2 * HOUR_MS; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, 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, 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)); assertEquals(STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); // Prediction can't set to NEVER // Prediction can't set to NEVER mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, 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, 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)); assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1)); } } Loading @@ -530,7 +534,7 @@ public class AppStandbyControllerTests { mInjector.mElapsedRealtime = 2000; mInjector.mElapsedRealtime = 2000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); // bucketing works after timeout // bucketing works after timeout Loading @@ -554,15 +558,17 @@ public class AppStandbyControllerTests { assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_WORKING_SET, REASON_MAIN_PREDICTED, 1000); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); mInjector.mElapsedRealtime = 2000 + mController.mStrongUsageTimeoutMillis; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, 2000 + mController.mStrongUsageTimeoutMillis); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_WORKING_SET); assertBucket(STANDBY_BUCKET_WORKING_SET); mInjector.mElapsedRealtime = 2000 + mController.mNotificationSeenTimeoutMillis; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, 2000 + mController.mNotificationSeenTimeoutMillis); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_FREQUENT); assertBucket(STANDBY_BUCKET_FREQUENT); } } Loading @@ -582,18 +588,18 @@ public class AppStandbyControllerTests { // Still in ACTIVE after first USER_INTERACTION times out // Still in ACTIVE after first USER_INTERACTION times out mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000; mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis + 1000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); // Both timed out, so NOTIFICATION_SEEN timeout should be effective // Both timed out, so NOTIFICATION_SEEN timeout should be effective mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000; mInjector.mElapsedRealtime = mController.mStrongUsageTimeoutMillis * 2 + 2000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_WORKING_SET); assertBucket(STANDBY_BUCKET_WORKING_SET); mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000; mInjector.mElapsedRealtime = mController.mNotificationSeenTimeoutMillis + 2000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_RARE); assertBucket(STANDBY_BUCKET_RARE); } } Loading Loading @@ -625,7 +631,7 @@ public class AppStandbyControllerTests { mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100; mInjector.mElapsedRealtime = 1 * RARE_THRESHOLD + 100; // Make sure app is in NEVER bucket // Make sure app is in NEVER bucket mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_NEVER, REASON_MAIN_FORCED, mInjector.mElapsedRealtime); REASON_MAIN_FORCED); mController.checkIdleStates(USER_ID); mController.checkIdleStates(USER_ID); assertBucket(STANDBY_BUCKET_NEVER); assertBucket(STANDBY_BUCKET_NEVER); Loading Loading @@ -670,7 +676,7 @@ public class AppStandbyControllerTests { // Predict to ACTIVE // Predict to ACTIVE mInjector.mElapsedRealtime += 1000; mInjector.mElapsedRealtime += 1000; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_ACTIVE); assertBucket(STANDBY_BUCKET_ACTIVE); // CheckIdleStates should not change the prediction // CheckIdleStates should not change the prediction Loading @@ -687,7 +693,7 @@ public class AppStandbyControllerTests { // Predict to FREQUENT // Predict to FREQUENT mInjector.mElapsedRealtime = RARE_THRESHOLD; mInjector.mElapsedRealtime = RARE_THRESHOLD; mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_FREQUENT, REASON_MAIN_PREDICTED, mInjector.mElapsedRealtime); REASON_MAIN_PREDICTED); assertBucket(STANDBY_BUCKET_FREQUENT); assertBucket(STANDBY_BUCKET_FREQUENT); // Add a short timeout event // Add a short timeout event Loading
services/usage/java/com/android/server/usage/UsageStatsService.java +7 −61 Original line number Original line Diff line number Diff line Loading @@ -1568,44 +1568,16 @@ public class UsageStatsService extends SystemService implements } } @Override @Override public void setAppStandbyBucket(String packageName, public void setAppStandbyBucket(String packageName, int bucket, int userId) { int bucket, int userId) { getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, "No permission to change app standby 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(); final int callingUid = Binder.getCallingUid(); try { final int callingPid = Binder.getCallingPid(); 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 long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity(); try { try { final int packageUid = mPackageManagerInternal.getPackageUid(packageName, mAppStandby.setAppStandbyBucket(packageName, bucket, userId, PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DIRECT_BOOT_UNAWARE callingUid, callingPid); | 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); } finally { } finally { Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } Loading Loading @@ -1643,37 +1615,11 @@ public class UsageStatsService extends SystemService implements "No permission to change app standby state"); "No permission to change app standby state"); final int callingUid = Binder.getCallingUid(); final int callingUid = Binder.getCallingUid(); try { final int callingPid = Binder.getCallingPid(); 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 long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity(); try { try { final long elapsedRealtime = SystemClock.elapsedRealtime(); mAppStandby.setAppStandbyBuckets(appBuckets.getList(), userId, List<AppStandbyInfo> bucketList = appBuckets.getList(); callingUid, callingPid); 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); } } finally { } finally { Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token); } } Loading