Expose App Standby APIs for apps and system

Allow apps to query their own standby bucket.
Allow privileged apps with PACKAGE_USAGE_STATS permission to
query apps.
Allow privileged apps with CHANGE_APP_IDLE_STATE to set the
standby state for apps, but not for themselves.
Removed AppStandby class and moved constants into UsageStatsManager.

Bug: 63527785
Test: cts-tradefed run cts-dev -m CtsAppUsageHostTestCases
Change-Id: I3c1c20f6ecb6d54e248233696039286b243d663c
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 7eb922c..979323f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -224,6 +224,8 @@
                     return runGetInactive(pw);
                 case "set-standby-bucket":
                     return runSetStandbyBucket(pw);
+                case "get-standby-bucket":
+                    return runGetStandbyBucket(pw);
                 case "send-trim-memory":
                     return runSendTrimMemory(pw);
                 case "display":
@@ -1826,6 +1828,29 @@
         return 0;
     }
 
+    private int bucketNameToBucketValue(String name) {
+        String lower = name.toLowerCase();
+        if (lower.startsWith("ac")) {
+            return UsageStatsManager.STANDBY_BUCKET_ACTIVE;
+        } else if (lower.startsWith("wo")) {
+            return UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+        } else if (lower.startsWith("fr")) {
+            return UsageStatsManager.STANDBY_BUCKET_FREQUENT;
+        } else if (lower.startsWith("ra")) {
+            return UsageStatsManager.STANDBY_BUCKET_RARE;
+        } else if (lower.startsWith("ne")) {
+            return UsageStatsManager.STANDBY_BUCKET_NEVER;
+        } else {
+            try {
+                int bucket = Integer.parseInt(lower);
+                return bucket;
+            } catch (NumberFormatException nfe) {
+                getErrPrintWriter().println("Error: Unknown bucket: " + name);
+            }
+        }
+        return -1;
+    }
+
     int runSetStandbyBucket(PrintWriter pw) throws RemoteException {
         int userId = UserHandle.USER_CURRENT;
 
@@ -1840,10 +1865,33 @@
         }
         String packageName = getNextArgRequired();
         String value = getNextArgRequired();
+        int bucket = bucketNameToBucketValue(value);
+        if (bucket < 0) return -1;
 
         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
                 Context.USAGE_STATS_SERVICE));
-        usm.setAppStandbyBucket(packageName, Integer.parseInt(value), userId);
+        usm.setAppStandbyBucket(packageName, bucketNameToBucketValue(value), userId);
+        return 0;
+    }
+
+    int runGetStandbyBucket(PrintWriter pw) throws RemoteException {
+        int userId = UserHandle.USER_CURRENT;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        String packageName = getNextArgRequired();
+
+        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
+                Context.USAGE_STATS_SERVICE));
+        int bucket = usm.getAppStandbyBucket(packageName, null, userId);
+        pw.println(bucket);
         return 0;
     }
 
@@ -2597,8 +2645,10 @@
             pw.println("      Sets the inactive state of an app.");
             pw.println("  get-inactive [--user <USER_ID>] <PACKAGE>");
             pw.println("      Returns the inactive state of an app.");
-            pw.println("  set-standby-bucket [--user <USER_ID>] <PACKAGE> <BUCKET>");
+            pw.println("  set-standby-bucket [--user <USER_ID>] <PACKAGE> active|working_set|frequent|rare");
             pw.println("      Puts an app in the standby bucket.");
+            pw.println("  get-standby-bucket [--user <USER_ID>] <PACKAGE>");
+            pw.println("      Returns the standby bucket of an app.");
             pw.println("  send-trim-memory [--user <USER_ID>] <PROCESS>");
             pw.println("          [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]");
             pw.println("      Send a memory trim event to a <PROCESS>.  May also supply a raw trim int level.");
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 4af86a0..3f014b5 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -29,7 +29,7 @@
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
 import android.app.job.JobWorkItem;
-import android.app.usage.AppStandby;
+import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
@@ -2074,10 +2074,10 @@
 
     public static int standbyBucketToBucketIndex(int bucket) {
         // Normalize AppStandby constants to indices into our bookkeeping
-        if (bucket == AppStandby.STANDBY_BUCKET_NEVER) return 4;
-        else if (bucket >= AppStandby.STANDBY_BUCKET_RARE) return 3;
-        else if (bucket >= AppStandby.STANDBY_BUCKET_FREQUENT) return 2;
-        else if (bucket >= AppStandby.STANDBY_BUCKET_WORKING_SET) return 1;
+        if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) return 4;
+        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_RARE) return 3;
+        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_FREQUENT) return 2;
+        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) return 1;
         else return 0;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index 39d256a..b62d724 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -16,14 +16,17 @@
 
 package com.android.server.usage;
 
-import android.app.usage.AppStandby;
+import static android.app.usage.UsageStatsManager.REASON_TIMEOUT;
+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_RARE;
+
+import android.app.usage.UsageStatsManager;
 import android.os.FileUtils;
 import android.test.AndroidTestCase;
 
 import java.io.File;
 
-import static android.app.usage.AppStandby.*;
-
 public class AppIdleHistoryTests extends AndroidTestCase {
 
     File mStorageDir;
@@ -85,12 +88,12 @@
         AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
 
         aih.setAppStandbyBucket(PACKAGE_1, USER_ID, 1000, STANDBY_BUCKET_ACTIVE,
-                AppStandby.REASON_USAGE);
+                UsageStatsManager.REASON_USAGE);
         // ACTIVE means not idle
         assertFalse(aih.isIdle(PACKAGE_1, USER_ID, 2000));
 
         aih.setAppStandbyBucket(PACKAGE_2, USER_ID, 2000, STANDBY_BUCKET_ACTIVE,
-                AppStandby.REASON_USAGE);
+                UsageStatsManager.REASON_USAGE);
         aih.setAppStandbyBucket(PACKAGE_1, USER_ID, 3000, STANDBY_BUCKET_RARE,
                 REASON_TIMEOUT);
 
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 40edfd2..87b34ab 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -16,9 +16,12 @@
 
 package com.android.server.usage;
 
-import static android.app.usage.AppStandby.*;
 import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
 import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
+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_RARE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -30,8 +33,8 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
-import android.app.usage.AppStandby;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager;
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -280,7 +283,7 @@
     public void testBuckets() throws Exception {
         AppStandbyController controller = setupController();
 
-        assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
+        assertTimeout(controller, 0, UsageStatsManager.STANDBY_BUCKET_NEVER);
 
         reportEvent(controller, USER_INTERACTION, 0);
 
@@ -312,7 +315,7 @@
         AppStandbyController controller = setupController();
         mInjector.setDisplayOn(false);
 
-        assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
+        assertTimeout(controller, 0, UsageStatsManager.STANDBY_BUCKET_NEVER);
 
         reportEvent(controller, USER_INTERACTION, 0);
 
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index ee11241..5aef55b 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -16,10 +16,7 @@
 
 package com.android.server.usage;
 
-import static android.app.usage.AppStandby.*;
-
-import android.app.usage.AppStandby;
-import android.os.Environment;
+import android.app.usage.UsageStatsManager;
 import android.os.SystemClock;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
@@ -99,7 +96,8 @@
         final byte[] recent = new byte[HISTORY_SIZE];
         long lastUsedElapsedTime;
         long lastUsedScreenTime;
-        @StandbyBuckets int currentBucket;
+        @UsageStatsManager.StandbyBuckets
+        int currentBucket;
         String bucketingReason;
         int lastInformedBucket;
     }
@@ -190,14 +188,14 @@
                 + (elapsedRealtime - mElapsedSnapshot);
         appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
         appUsageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
-        if (appUsageHistory.currentBucket > STANDBY_BUCKET_ACTIVE) {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
+        if (appUsageHistory.currentBucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) {
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
             if (DEBUG) {
                 Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
                         + ", reason=" + appUsageHistory.bucketingReason);
             }
         }
-        appUsageHistory.bucketingReason = AppStandby.REASON_USAGE;
+        appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
 
         return appUsageHistory.currentBucket;
     }
@@ -206,15 +204,15 @@
         ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
         AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
                 elapsedRealtime, true);
-        if (appUsageHistory.currentBucket > STANDBY_BUCKET_WORKING_SET) {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_WORKING_SET;
+        if (appUsageHistory.currentBucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
             if (DEBUG) {
                 Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
                         + ", reason=" + appUsageHistory.bucketingReason);
             }
         }
         // TODO: Should this be a different reason for partial usage?
-        appUsageHistory.bucketingReason = AppStandby.REASON_USAGE;
+        appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
 
         return appUsageHistory.currentBucket;
     }
@@ -271,8 +269,9 @@
             appUsageHistory = new AppUsageHistory();
             appUsageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
             appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
-            appUsageHistory.currentBucket = AppStandby.STANDBY_BUCKET_NEVER;
-            appUsageHistory.bucketingReason = REASON_DEFAULT;
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_NEVER;
+            appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
+            appUsageHistory.lastInformedBucket = -1;
             userHistory.put(packageName, appUsageHistory);
         }
         return appUsageHistory;
@@ -289,7 +288,7 @@
         if (appUsageHistory == null) {
             return false; // Default to not idle
         } else {
-            return appUsageHistory.currentBucket >= AppStandby.STANDBY_BUCKET_RARE;
+            return appUsageHistory.currentBucket >= UsageStatsManager.STANDBY_BUCKET_RARE;
             // Whether or not it's passed will now be externally calculated and the
             // bucket will be pushed to the history using setAppStandbyBucket()
             //return hasPassedThresholds(appUsageHistory, elapsedRealtime);
@@ -333,12 +332,12 @@
         AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
                 elapsedRealtime, true);
         if (idle) {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_RARE;
-            appUsageHistory.bucketingReason = REASON_FORCED;
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_RARE;
+            appUsageHistory.bucketingReason = UsageStatsManager.REASON_FORCED;
         } else {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
             // This is to pretend that the app was just used, don't freeze the state anymore.
-            appUsageHistory.bucketingReason = REASON_USAGE;
+            appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
         }
         return appUsageHistory.currentBucket;
     }
@@ -435,12 +434,12 @@
                         String currentBucketString = parser.getAttributeValue(null,
                                 ATTR_CURRENT_BUCKET);
                         appUsageHistory.currentBucket = currentBucketString == null
-                                ? AppStandby.STANDBY_BUCKET_ACTIVE
+                                ? UsageStatsManager.STANDBY_BUCKET_ACTIVE
                                 : Integer.parseInt(currentBucketString);
                         appUsageHistory.bucketingReason =
                                 parser.getAttributeValue(null, ATTR_BUCKETING_REASON);
                         if (appUsageHistory.bucketingReason == null) {
-                            appUsageHistory.bucketingReason = REASON_DEFAULT;
+                            appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
                         }
                         userHistory.put(packageName, appUsageHistory);
                     }
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 3c099c2..4527879 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -16,15 +16,23 @@
 
 package com.android.server.usage;
 
+import static android.app.usage.UsageStatsManager.REASON_FORCED;
+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_RARE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+
 import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.admin.DevicePolicyManager;
-import android.app.usage.AppStandby;
-import android.app.usage.AppStandby.StandbyBuckets;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.appwidget.AppWidgetManager;
 import android.content.BroadcastReceiver;
@@ -102,10 +110,10 @@
     };
 
     static final int[] THRESHOLD_BUCKETS = {
-            AppStandby.STANDBY_BUCKET_ACTIVE,
-            AppStandby.STANDBY_BUCKET_WORKING_SET,
-            AppStandby.STANDBY_BUCKET_FREQUENT,
-            AppStandby.STANDBY_BUCKET_RARE
+            STANDBY_BUCKET_ACTIVE,
+            STANDBY_BUCKET_WORKING_SET,
+            STANDBY_BUCKET_FREQUENT,
+            STANDBY_BUCKET_RARE
     };
 
     // To name the lock for stack traces
@@ -371,18 +379,18 @@
                 }
                 if (isSpecial) {
                     maybeInformListeners(packageName, userId, elapsedRealtime,
-                            AppStandby.STANDBY_BUCKET_ACTIVE);
+                            STANDBY_BUCKET_ACTIVE);
                 } else {
                     synchronized (mAppIdleLock) {
                         String bucketingReason = mAppIdleHistory.getAppStandbyReason(packageName,
                                 userId, elapsedRealtime);
                         // If the bucket was forced by the developer, leave it alone
-                        if (AppStandby.REASON_FORCED.equals(bucketingReason)) {
+                        if (REASON_FORCED.equals(bucketingReason)) {
                             continue;
                         }
                         // If the bucket was moved up due to usage, let the timeouts apply.
-                        if (AppStandby.REASON_USAGE.equals(bucketingReason)
-                                || AppStandby.REASON_TIMEOUT.equals(bucketingReason)) {
+                        if (REASON_USAGE.equals(bucketingReason)
+                                || REASON_TIMEOUT.equals(bucketingReason)) {
                             int oldBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId,
                                     elapsedRealtime);
                             int newBucket = getBucketForLocked(packageName, userId,
@@ -393,7 +401,7 @@
                             }
                             if (oldBucket < newBucket) {
                                 mAppIdleHistory.setAppStandbyBucket(packageName, userId,
-                                        elapsedRealtime, newBucket, AppStandby.REASON_TIMEOUT);
+                                        elapsedRealtime, newBucket, REASON_TIMEOUT);
                                 maybeInformListeners(packageName, userId, elapsedRealtime,
                                         newBucket);
                             }
@@ -742,7 +750,7 @@
             long elapsedRealtime, boolean shouldObfuscateInstantApps) {
         if (shouldObfuscateInstantApps &&
                 mInjector.isPackageEphemeral(userId, packageName)) {
-            return AppStandby.STANDBY_BUCKET_ACTIVE;
+            return STANDBY_BUCKET_ACTIVE;
         }
 
         return mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime);
@@ -811,7 +819,7 @@
     }
 
     void informListeners(String packageName, int userId, int bucket) {
-        final boolean idle = bucket >= AppStandby.STANDBY_BUCKET_RARE;
+        final boolean idle = bucket >= STANDBY_BUCKET_RARE;
         for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
             listener.onAppIdleStateChanged(packageName, userId, idle, bucket);
         }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 65c1cef..878fbed 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -20,11 +20,11 @@
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.IUidObserver;
-import android.app.usage.AppStandby;
 import android.app.usage.ConfigurationStats;
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
-import android.app.usage.AppStandby.StandbyBuckets;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManagerInternal;
@@ -149,6 +149,8 @@
 
         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
+        // Make sure we initialize the data, in case job scheduler needs it early.
+        getUserDataAndInitializeIfNeededLocked(UserHandle.USER_SYSTEM, mSystemTimeSnapshot);
     }
 
     @Override
@@ -678,10 +680,6 @@
 
         @Override
         public int getAppStandbyBucket(String packageName, String callingPackage, int userId) {
-            if (!hasPermission(callingPackage)) {
-                throw new SecurityException("Don't have permission to query app standby bucket");
-            }
-
             final int callingUid = Binder.getCallingUid();
             try {
                 userId = ActivityManager.getService().handleIncomingUser(
@@ -690,6 +688,14 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
+            // If the calling app is asking about itself, continue, else check for permission.
+            if (mPackageManagerInternal.getPackageUid(packageName, PackageManager.MATCH_ANY_USER,
+                    userId) != callingUid) {
+                if (!hasPermission(callingPackage)) {
+                    throw new SecurityException(
+                            "Don't have permission to query app standby bucket");
+                }
+            }
             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid,
                     userId);
             final long token = Binder.clearCallingIdentity();
@@ -707,6 +713,10 @@
             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(
@@ -717,8 +727,13 @@
             }
             final long token = Binder.clearCallingIdentity();
             try {
+                // 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,
-                        AppStandby.REASON_PREDICTED + ":" + callingUid,
+                        UsageStatsManager.REASON_PREDICTED + ":" + callingUid,
                         SystemClock.elapsedRealtime());
             } finally {
                 Binder.restoreCallingIdentity(token);