Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9388519d authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Don't allow certain bucket overrides

Don't allow EXEMPT to be overridden
Differentiate between shell and other callers who set
buckets.
Don't allow forced to be modified by bucketeer.
Don't allow bucketeer to modify NEVER bucket.

Fix a locking issue in listeners list. Don't use
the primary lock when calling out to listeners.

Fixes: 70622791
Fixes: 70622338

Test: atest FrameworksServicesTests:AppIdleHistoryTests
      atest FrameworksServicesTests:AppStandbyControllerTests
      atest CtsAppUsageHostTestCases
Change-Id: I22309478b947d6461235f5a77e08c7be86309e4b
parent ff38f236
Loading
Loading
Loading
Loading
+91 −56
Original line number Original line Diff line number Diff line
@@ -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.NOTIFICATION_SEEN;
import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
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_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_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
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_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
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 static final long RARE_THRESHOLD = 48 * HOUR_MS;


    private MyInjector mInjector;
    private MyInjector mInjector;
    private AppStandbyController mController;


    static class MyContextWrapper extends ContextWrapper {
    static class MyContextWrapper extends ContextWrapper {
        PackageManager mockPm = mock(PackageManager.class);
        PackageManager mockPm = mock(PackageManager.class);
@@ -237,24 +243,23 @@ public class AppStandbyControllerTests {
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext());
        MyContextWrapper myContext = new MyContextWrapper(InstrumentationRegistry.getContext());
        mInjector = new MyInjector(myContext, Looper.getMainLooper());
        mInjector = new MyInjector(myContext, Looper.getMainLooper());
        mController = setupController();
    }
    }


    @Test
    @Test
    public void testCharging() throws Exception {
    public void testCharging() throws Exception {
        AppStandbyController controller = setupController();
        setChargingState(mController, true);

        setChargingState(controller, true);
        mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
        mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
        assertFalse(controller.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID,
        assertFalse(mController.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID,
                mInjector.mElapsedRealtime, false));
                mInjector.mElapsedRealtime, false));


        setChargingState(controller, false);
        setChargingState(mController, false);
        mInjector.mElapsedRealtime = 2 * RARE_THRESHOLD + 2;
        mInjector.mElapsedRealtime = 2 * RARE_THRESHOLD + 2;
        controller.checkIdleStates(USER_ID);
        mController.checkIdleStates(USER_ID);
        assertTrue(controller.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID,
        assertTrue(mController.isAppIdleFilteredOrParoled(PACKAGE_1, USER_ID,
                mInjector.mElapsedRealtime, false));
                mInjector.mElapsedRealtime, false));
        setChargingState(controller, true);
        setChargingState(mController, true);
        assertFalse(controller.isAppIdleFilteredOrParoled(PACKAGE_1,USER_ID,
        assertFalse(mController.isAppIdleFilteredOrParoled(PACKAGE_1,USER_ID,
                mInjector.mElapsedRealtime, false));
                mInjector.mElapsedRealtime, false));
    }
    }


@@ -282,112 +287,142 @@ public class AppStandbyControllerTests {


    @Test
    @Test
    public void testBuckets() throws Exception {
    public void testBuckets() throws Exception {
        AppStandbyController controller = setupController();
        assertTimeout(mController, 0, STANDBY_BUCKET_NEVER);

        assertTimeout(controller, 0, UsageStatsManager.STANDBY_BUCKET_NEVER);


        reportEvent(controller, USER_INTERACTION, 0);
        reportEvent(mController, USER_INTERACTION, 0);


        // ACTIVE bucket
        // ACTIVE bucket
        assertTimeout(controller, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
        assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);


        // WORKING_SET bucket
        // 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
        // WORKING_SET bucket
        assertTimeout(controller, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET);
        assertTimeout(mController, FREQUENT_THRESHOLD - 1, STANDBY_BUCKET_WORKING_SET);


        // FREQUENT bucket
        // FREQUENT bucket
        assertTimeout(controller, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT);
        assertTimeout(mController, FREQUENT_THRESHOLD + 1, STANDBY_BUCKET_FREQUENT);


        // RARE bucket
        // 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
        // RARE bucket
        assertTimeout(controller, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE);
        assertTimeout(mController, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE);
    }
    }


    @Test
    @Test
    public void testScreenTimeAndBuckets() throws Exception {
    public void testScreenTimeAndBuckets() throws Exception {
        AppStandbyController controller = setupController();
        mInjector.setDisplayOn(false);
        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
        // ACTIVE bucket
        assertTimeout(controller, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);
        assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE);


        // WORKING_SET bucket
        // 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.
        // RARE bucket, should fail because the screen wasn't ON.
        mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
        mInjector.mElapsedRealtime = RARE_THRESHOLD + 1;
        controller.checkIdleStates(USER_ID);
        mController.checkIdleStates(USER_ID);
        assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller));
        assertNotEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));


        mInjector.setDisplayOn(true);
        mInjector.setDisplayOn(true);
        assertTimeout(controller, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE);
        assertTimeout(mController, RARE_THRESHOLD * 2 + 2, STANDBY_BUCKET_RARE);
    }
    }


    @Test
    @Test
    public void testForcedIdle() throws Exception {
    public void testForcedIdle() throws Exception {
        AppStandbyController controller = setupController();
        setChargingState(mController, false);
        setChargingState(controller, false);


        controller.forceIdleState(PACKAGE_1, USER_ID, true);
        mController.forceIdleState(PACKAGE_1, USER_ID, true);
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(controller));
        assertEquals(STANDBY_BUCKET_RARE, getStandbyBucket(mController));
        assertTrue(controller.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertTrue(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));


        controller.forceIdleState(PACKAGE_1, USER_ID, false);
        mController.forceIdleState(PACKAGE_1, USER_ID, false);
        assertEquals(STANDBY_BUCKET_ACTIVE, controller.getAppStandbyBucket(PACKAGE_1, USER_ID, 0,
        assertEquals(STANDBY_BUCKET_ACTIVE, mController.getAppStandbyBucket(PACKAGE_1, USER_ID, 0,
                true));
                true));
        assertFalse(controller.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
        assertFalse(mController.isAppIdleFiltered(PACKAGE_1, UID_1, USER_ID, 0));
    }
    }


    @Test
    @Test
    public void testNotificationEvent() throws Exception {
    public void testNotificationEvent() throws Exception {
        AppStandbyController controller = setupController();
        setChargingState(mController, false);
        setChargingState(controller, false);


        reportEvent(controller, USER_INTERACTION, 0);
        reportEvent(mController, USER_INTERACTION, 0);
        assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller));
        assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));
        mInjector.mElapsedRealtime = 1;
        mInjector.mElapsedRealtime = 1;
        reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
        reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
        assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(controller));
        assertEquals(STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController));


        controller.forceIdleState(PACKAGE_1, USER_ID, true);
        mController.forceIdleState(PACKAGE_1, USER_ID, true);
        reportEvent(controller, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
        reportEvent(mController, NOTIFICATION_SEEN, mInjector.mElapsedRealtime);
        assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller));
        assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));
    }
    }


    @Test
    @Test
    public void testPredictionTimedout() throws Exception {
    public void testPredictionTimedout() throws Exception {
        AppStandbyController controller = setupController();
        setChargingState(mController, false);
        setChargingState(controller, false);
        // Set it to timeout or usage, so that prediction can override it
        controller.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_ACTIVE,
        mController.setAppStandbyBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE,
                REASON_PREDICTED + "CTS", 1 * HOUR_MS);
                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
        // Fast forward 12 hours
        mInjector.mElapsedRealtime += WORKING_SET_THRESHOLD;
        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
        // 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
        // Fast forward two more hours
        mInjector.mElapsedRealtime += 2 * HOUR_MS;
        mInjector.mElapsedRealtime += 2 * HOUR_MS;
        controller.checkIdleStates(USER_ID);
        mController.checkIdleStates(USER_ID);
        // Should have now applied prediction timeout
        // Should have now applied prediction timeout
        assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(controller));
        assertEquals(STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController));


        // Fast forward RARE bucket
        // Fast forward RARE bucket
        mInjector.mElapsedRealtime += RARE_THRESHOLD;
        mInjector.mElapsedRealtime += RARE_THRESHOLD;
        controller.checkIdleStates(USER_ID);
        mController.checkIdleStates(USER_ID);
        // Should continue to apply prediction timeout
        // 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));
    }
    }
}
}
+25 −7
Original line number Original line Diff line number Diff line
@@ -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_ACTIVE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
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_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_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;


@@ -133,7 +134,7 @@ public class AppStandbyController {
    @GuardedBy("mAppIdleLock")
    @GuardedBy("mAppIdleLock")
    private AppIdleHistory mAppIdleHistory;
    private AppIdleHistory mAppIdleHistory;


    @GuardedBy("mAppIdleLock")
    @GuardedBy("mPackageAccessListeners")
    private ArrayList<AppIdleStateChangeListener>
    private ArrayList<AppIdleStateChangeListener>
            mPackageAccessListeners = new ArrayList<>();
            mPackageAccessListeners = new ArrayList<>();


@@ -592,7 +593,7 @@ public class AppStandbyController {
    }
    }


    void addListener(AppIdleStateChangeListener listener) {
    void addListener(AppIdleStateChangeListener listener) {
        synchronized (mAppIdleLock) {
        synchronized (mPackageAccessListeners) {
            if (!mPackageAccessListeners.contains(listener)) {
            if (!mPackageAccessListeners.contains(listener)) {
                mPackageAccessListeners.add(listener);
                mPackageAccessListeners.add(listener);
            }
            }
@@ -600,7 +601,7 @@ public class AppStandbyController {
    }
    }


    void removeListener(AppIdleStateChangeListener listener) {
    void removeListener(AppIdleStateChangeListener listener) {
        synchronized (mAppIdleLock) {
        synchronized (mPackageAccessListeners) {
            mPackageAccessListeners.remove(listener);
            mPackageAccessListeners.remove(listener);
        }
        }
    }
    }
@@ -789,6 +790,19 @@ public class AppStandbyController {
    void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
    void setAppStandbyBucket(String packageName, int userId, @StandbyBuckets int newBucket,
            String reason, long elapsedRealtime) {
            String reason, long elapsedRealtime) {
        synchronized (mAppIdleLock) {
        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,
            mAppIdleHistory.setAppStandbyBucket(packageName, userId, elapsedRealtime, newBucket,
                    reason);
                    reason);
        }
        }
@@ -852,17 +866,21 @@ public class AppStandbyController {


    void informListeners(String packageName, int userId, int bucket) {
    void informListeners(String packageName, int userId, int bucket) {
        final boolean idle = bucket >= STANDBY_BUCKET_RARE;
        final boolean idle = bucket >= STANDBY_BUCKET_RARE;
        synchronized (mPackageAccessListeners) {
            for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
            for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
                listener.onAppIdleStateChanged(packageName, userId, idle, bucket);
                listener.onAppIdleStateChanged(packageName, userId, idle, bucket);
            }
            }
        }
        }
    }


    void informParoleStateChanged() {
    void informParoleStateChanged() {
        final boolean paroled = isParoledOrCharging();
        final boolean paroled = isParoledOrCharging();
        synchronized (mPackageAccessListeners) {
            for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
            for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
                listener.onParoleStateChanged(paroled);
                listener.onParoleStateChanged(paroled);
            }
            }
        }
        }
    }


    void flushToDisk(int userId) {
    void flushToDisk(int userId) {
        synchronized (mAppIdleLock) {
        synchronized (mAppIdleLock) {
+10 −4
Original line number Original line Diff line number Diff line
@@ -728,6 +728,10 @@ public class UsageStatsService extends SystemService implements
            } catch (RemoteException re) {
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
                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();
            final long token = Binder.clearCallingIdentity();
            try {
            try {
                // Caller cannot set their own standby state
                // Caller cannot set their own standby state
@@ -735,8 +739,7 @@ public class UsageStatsService extends SystemService implements
                        PackageManager.MATCH_ANY_USER, userId) == callingUid) {
                        PackageManager.MATCH_ANY_USER, userId) == callingUid) {
                    throw new IllegalArgumentException("Cannot set your own standby bucket");
                    throw new IllegalArgumentException("Cannot set your own standby bucket");
                }
                }
                mAppStandby.setAppStandbyBucket(packageName, userId, bucket,
                mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
                        UsageStatsManager.REASON_PREDICTED + ":" + callingUid,
                        SystemClock.elapsedRealtime());
                        SystemClock.elapsedRealtime());
            } finally {
            } finally {
                Binder.restoreCallingIdentity(token);
                Binder.restoreCallingIdentity(token);
@@ -779,6 +782,10 @@ public class UsageStatsService extends SystemService implements
            } catch (RemoteException re) {
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
                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();
            final long token = Binder.clearCallingIdentity();
            try {
            try {
                final long elapsedRealtime = SystemClock.elapsedRealtime();
                final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -796,8 +803,7 @@ public class UsageStatsService extends SystemService implements
                            PackageManager.MATCH_ANY_USER, userId) == callingUid) {
                            PackageManager.MATCH_ANY_USER, userId) == callingUid) {
                        throw new IllegalArgumentException("Cannot set your own standby bucket");
                        throw new IllegalArgumentException("Cannot set your own standby bucket");
                    }
                    }
                    mAppStandby.setAppStandbyBucket(packageName, userId, bucket,
                    mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
                            UsageStatsManager.REASON_PREDICTED + ":" + callingUid,
                            elapsedRealtime);
                            elapsedRealtime);
                }
                }
            } finally {
            } finally {