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

Commit 881254f4 authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Creating new RESTRICTED bucket."

parents ba5a5356 c6a9b341
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -103,6 +103,8 @@ public interface AppStandbyInternal {
    /**
     * Changes an app's standby bucket to the provided value. The caller can only set the standby
     * bucket for a different app than itself.
     * If attempting to automatically place an app in the RESTRICTED bucket, use
     * {@link #restrictApp(String, int, int)} instead.
     */
    void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId, int callingUid,
            int callingPid);
@@ -113,6 +115,17 @@ public interface AppStandbyInternal {
    void setAppStandbyBuckets(@NonNull List<AppStandbyInfo> appBuckets, int userId, int callingUid,
            int callingPid);

    /**
     * Put the specified app in the
     * {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
     * bucket. If it has been used by the user recently, the restriction will delayed until an
     * appropriate time.
     *
     * @param restrictReason The restrictReason for restricting the app. Should be one of the
     *                       UsageStatsManager.REASON_SUB_RESTRICT_* reasons.
     */
    void restrictApp(@NonNull String packageName, int userId, int restrictReason);

    void addActiveDeviceAdmin(String adminPkg, int userId);

    void setActiveAdminApps(Set<String> adminPkgs, int userId);
+5 −3
Original line number Diff line number Diff line
@@ -277,6 +277,7 @@ public class JobSchedulerService extends com.android.server.SystemService
    DeviceIdleInternal mLocalDeviceIdleController;
    AppStateTracker mAppStateTracker;
    final UsageStatsManagerInternal mUsageStats;
    private final AppStandbyInternal mAppStandbyInternal;

    /**
     * Set to true once we are allowed to run third party apps.
@@ -1062,7 +1063,8 @@ public class JobSchedulerService extends com.android.server.SystemService
                    packageName == null ? job.getService().getPackageName() : packageName;
            if (!mQuotaTracker.isWithinQuota(userId, pkg, QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG)) {
                Slog.e(TAG, userId + "-" + pkg + " has called schedule() too many times");
                // TODO(b/145551233): attempt to restrict app
                mAppStandbyInternal.restrictApp(
                        pkg, userId, UsageStatsManager.REASON_SUB_RESTRICT_BUGGY);
                if (mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION
                        && mPlatformCompat.isChangeEnabledByPackageName(
                                CRASH_ON_EXCEEDED_LIMIT, pkg, userId)) {
@@ -1430,8 +1432,8 @@ public class JobSchedulerService extends com.android.server.SystemService
                mConstants.API_QUOTA_SCHEDULE_COUNT,
                mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);

        AppStandbyInternal appStandby = LocalServices.getService(AppStandbyInternal.class);
        appStandby.addListener(mStandbyTracker);
        mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
        mAppStandbyInternal.addListener(mStandbyTracker);

        // The job store needs to call back
        publishLocalService(JobSchedulerInternal.class, new LocalService());
+96 −15
Original line number Diff line number Diff line
@@ -25,8 +25,11 @@ import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACT
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
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_RESTRICTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;

import static com.android.server.usage.AppStandbyController.isUserUsage;

import android.app.usage.AppStandbyInfo;
import android.app.usage.UsageStatsManager;
import android.os.SystemClock;
@@ -81,6 +84,8 @@ public class AppIdleHistory {
    private static final String ATTR_SCREEN_IDLE = "screenIdleTime";
    // Elapsed timebase time when app was last used
    private static final String ATTR_ELAPSED_IDLE = "elapsedIdleTime";
    // Elapsed timebase time when app was last used by the user
    private static final String ATTR_LAST_USED_BY_USER_ELAPSED = "lastUsedByUserElapsedTime";
    // Elapsed timebase time when the app bucket was last predicted externally
    private static final String ATTR_LAST_PREDICTED_TIME = "lastPredictedTime";
    // The standby bucket for the app
@@ -93,6 +98,12 @@ public class AppIdleHistory {
    private static final String ATTR_BUCKET_ACTIVE_TIMEOUT_TIME = "activeTimeoutTime";
    // The time when the forced working_set state can be overridden.
    private static final String ATTR_BUCKET_WORKING_SET_TIMEOUT_TIME = "workingSetTimeoutTime";
    // Elapsed timebase time when the app was last marked for restriction.
    private static final String ATTR_LAST_RESTRICTION_ATTEMPT_ELAPSED =
            "lastRestrictionAttemptElapsedTime";
    // Reason why the app was last marked for restriction.
    private static final String ATTR_LAST_RESTRICTION_ATTEMPT_REASON =
            "lastRestrictionAttemptReason";

    // device on time = mElapsedDuration + (timeNow - mElapsedSnapshot)
    private long mElapsedSnapshot; // Elapsed time snapshot when last write of mDeviceOnDuration
@@ -107,8 +118,10 @@ public class AppIdleHistory {
    private boolean mScreenOn;

    static class AppUsageHistory {
        // Last used time using elapsed timebase
        // Last used time (including system usage), using elapsed timebase
        long lastUsedElapsedTime;
        // Last time the user used the app, using elapsed timebase
        long lastUsedByUserElapsedTime;
        // Last used time using screen_on timebase
        long lastUsedScreenTime;
        // Last predicted time using elapsed timebase
@@ -136,6 +149,10 @@ public class AppIdleHistory {
        // under any active state timeout, so that it becomes applicable after the active state
        // timeout expires.
        long bucketWorkingSetTimeoutTime;
        // The last time an agent attempted to put the app into the RESTRICTED bucket.
        long lastRestrictAttemptElapsedTime;
        // The last reason the app was marked to be put into the RESTRICTED bucket.
        int lastRestrictReason;
    }

    AppIdleHistory(File storageDir, long elapsedRealtime) {
@@ -229,6 +246,14 @@ public class AppIdleHistory {
     */
    public AppUsageHistory reportUsage(AppUsageHistory appUsageHistory, String packageName,
            int newBucket, int usageReason, long elapsedRealtime, long timeout) {
        int bucketingReason = REASON_MAIN_USAGE | usageReason;
        final boolean isUserUsage = isUserUsage(bucketingReason);

        if (appUsageHistory.currentBucket == STANDBY_BUCKET_RESTRICTED && !isUserUsage) {
            // Only user usage should bring an app out of the RESTRICTED bucket.
            newBucket = STANDBY_BUCKET_RESTRICTED;
            bucketingReason = appUsageHistory.bucketingReason;
        } else {
            // Set the timeout if applicable
            if (timeout > elapsedRealtime) {
                // Convert to elapsed timebase
@@ -240,14 +265,18 @@ public class AppIdleHistory {
                    appUsageHistory.bucketWorkingSetTimeoutTime = Math.max(timeoutTime,
                            appUsageHistory.bucketWorkingSetTimeoutTime);
                } else {
                throw new IllegalArgumentException("Cannot set a timeout on bucket=" +
                        newBucket);
                    throw new IllegalArgumentException("Cannot set a timeout on bucket="
                            + newBucket);
                }
            }
        }

        if (elapsedRealtime != 0) {
            appUsageHistory.lastUsedElapsedTime = mElapsedDuration
                    + (elapsedRealtime - mElapsedSnapshot);
            if (isUserUsage) {
                appUsageHistory.lastUsedByUserElapsedTime = appUsageHistory.lastUsedElapsedTime;
            }
            appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
        }

@@ -259,7 +288,7 @@ public class AppIdleHistory {
                        + ", reason=0x0" + Integer.toHexString(appUsageHistory.bucketingReason));
            }
        }
        appUsageHistory.bucketingReason = REASON_MAIN_USAGE | usageReason;
        appUsageHistory.bucketingReason = bucketingReason;

        return appUsageHistory;
    }
@@ -385,6 +414,24 @@ public class AppIdleHistory {
        appUsageHistory.lastJobRunTime = getElapsedTime(elapsedRealtime);
    }

    /**
     * Notes an attempt to put the app in the {@link UsageStatsManager#STANDBY_BUCKET_RESTRICTED}
     * bucket.
     *
     * @param packageName     The package name of the app that is being restricted
     * @param userId          The ID of the user in which the app is being restricted
     * @param elapsedRealtime The time the attempt was made, in the (unadjusted) elapsed realtime
     *                        timebase
     * @param reason          The reason for the restriction attempt
     */
    void noteRestrictionAttempt(String packageName, int userId, long elapsedRealtime, int reason) {
        ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
        AppUsageHistory appUsageHistory =
                getPackageHistory(userHistory, packageName, elapsedRealtime, true);
        appUsageHistory.lastRestrictAttemptElapsedTime = getElapsedTime(elapsedRealtime);
        appUsageHistory.lastRestrictReason = reason;
    }

    /**
     * Returns the time since the last job was run for this app. This can be larger than the
     * current elapsedRealtime, in case it happened before boot or a really large value if no jobs
@@ -547,6 +594,9 @@ public class AppIdleHistory {
                        AppUsageHistory appUsageHistory = new AppUsageHistory();
                        appUsageHistory.lastUsedElapsedTime =
                                Long.parseLong(parser.getAttributeValue(null, ATTR_ELAPSED_IDLE));
                        appUsageHistory.lastUsedByUserElapsedTime = getLongValue(parser,
                                ATTR_LAST_USED_BY_USER_ELAPSED,
                                appUsageHistory.lastUsedElapsedTime);
                        appUsageHistory.lastUsedScreenTime =
                                Long.parseLong(parser.getAttributeValue(null, ATTR_SCREEN_IDLE));
                        appUsageHistory.lastPredictedTime = getLongValue(parser,
@@ -570,6 +620,19 @@ public class AppIdleHistory {
                                appUsageHistory.bucketingReason =
                                        Integer.parseInt(bucketingReason, 16);
                            } catch (NumberFormatException nfe) {
                                Slog.wtf(TAG, "Unable to read bucketing reason", nfe);
                            }
                        }
                        appUsageHistory.lastRestrictAttemptElapsedTime =
                                getLongValue(parser, ATTR_LAST_RESTRICTION_ATTEMPT_ELAPSED, 0);
                        String lastRestrictReason = parser.getAttributeValue(
                                null, ATTR_LAST_RESTRICTION_ATTEMPT_REASON);
                        if (lastRestrictReason != null) {
                            try {
                                appUsageHistory.lastRestrictReason =
                                        Integer.parseInt(lastRestrictReason, 16);
                            } catch (NumberFormatException nfe) {
                                Slog.wtf(TAG, "Unable to read last restrict reason", nfe);
                            }
                        }
                        appUsageHistory.lastInformedBucket = -1;
@@ -618,6 +681,8 @@ public class AppIdleHistory {
                xml.attribute(null, ATTR_NAME, packageName);
                xml.attribute(null, ATTR_ELAPSED_IDLE,
                        Long.toString(history.lastUsedElapsedTime));
                xml.attribute(null, ATTR_LAST_USED_BY_USER_ELAPSED,
                        Long.toString(history.lastUsedByUserElapsedTime));
                xml.attribute(null, ATTR_SCREEN_IDLE,
                        Long.toString(history.lastUsedScreenTime));
                xml.attribute(null, ATTR_LAST_PREDICTED_TIME,
@@ -638,6 +703,12 @@ public class AppIdleHistory {
                    xml.attribute(null, ATTR_LAST_RUN_JOB_TIME, Long.toString(history
                            .lastJobRunTime));
                }
                if (history.lastRestrictAttemptElapsedTime > 0) {
                    xml.attribute(null, ATTR_LAST_RESTRICTION_ATTEMPT_ELAPSED,
                            Long.toString(history.lastRestrictAttemptElapsedTime));
                }
                xml.attribute(null, ATTR_LAST_RESTRICTION_ATTEMPT_REASON,
                        Integer.toHexString(history.lastRestrictReason));
                xml.endTag(null, TAG_PACKAGE);
            }

@@ -672,6 +743,9 @@ public class AppIdleHistory {
                    + UsageStatsManager.reasonToString(appUsageHistory.bucketingReason));
            idpw.print(" used=");
            TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedElapsedTime, idpw);
            idpw.print(" usedByUser=");
            TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastUsedByUserElapsedTime,
                    idpw);
            idpw.print(" usedScr=");
            TimeUtils.formatDuration(screenOnTime - appUsageHistory.lastUsedScreenTime, idpw);
            idpw.print(" lastPred=");
@@ -684,6 +758,13 @@ public class AppIdleHistory {
                    idpw);
            idpw.print(" lastJob=");
            TimeUtils.formatDuration(totalElapsedTime - appUsageHistory.lastJobRunTime, idpw);
            if (appUsageHistory.lastRestrictAttemptElapsedTime > 0) {
                idpw.print(" lastRestrictAttempt=");
                TimeUtils.formatDuration(
                        totalElapsedTime - appUsageHistory.lastRestrictAttemptElapsedTime, idpw);
                idpw.print(" lastRestrictReason="
                        + UsageStatsManager.reasonToString(appUsageHistory.lastRestrictReason));
            }
            idpw.print(" idle=" + (isIdle(packageName, userId, elapsedRealtime) ? "y" : "n"));
            idpw.println();
        }
+112 −11
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.app.usage.UsageStatsManager.REASON_MAIN_MASK;
import static android.app.usage.UsageStatsManager.REASON_MAIN_PREDICTED;
import static android.app.usage.UsageStatsManager.REASON_MAIN_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
import static android.app.usage.UsageStatsManager.REASON_SUB_MASK;
import static android.app.usage.UsageStatsManager.REASON_SUB_PREDICTED_RESTORED;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_ACTIVE_TIMEOUT;
import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
@@ -44,6 +45,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RESTRICTED;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;

import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
@@ -73,6 +75,7 @@ import android.net.Network;
import android.net.NetworkRequest;
import android.net.NetworkScoreManager;
import android.os.BatteryStats;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.IDeviceIdleController;
@@ -93,7 +96,9 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.view.Display;
import android.widget.Toast;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
@@ -124,7 +129,7 @@ import java.util.concurrent.CountDownLatch;
public class AppStandbyController implements AppStandbyInternal {

    private static final String TAG = "AppStandbyController";
    static final boolean DEBUG = false;
    static final boolean DEBUG = true;

    static final boolean COMPRESS_TIME = false;
    private static final long ONE_MINUTE = 60 * 1000;
@@ -615,6 +620,16 @@ public class AppStandbyController implements AppStandbyInternal {
                        Slog.d(TAG, "    Keeping at WORKING_SET due to min timeout");
                    }
                }

                if (app.lastRestrictAttemptElapsedTime > app.lastUsedByUserElapsedTime
                        && elapsedTimeAdjusted - app.lastUsedByUserElapsedTime
                        >= mInjector.getRestrictedBucketDelayMs()) {
                    newBucket = STANDBY_BUCKET_RESTRICTED;
                    reason = app.lastRestrictReason;
                    if (DEBUG) {
                        Slog.d(TAG, "Bringing down to RESTRICTED due to timeout");
                    }
                }
                if (DEBUG) {
                    Slog.d(TAG, "     Old bucket=" + oldBucket
                            + ", newBucket=" + newBucket);
@@ -733,15 +748,16 @@ public class AppStandbyController implements AppStandbyInternal {
                            elapsedRealtime, elapsedRealtime + mStrongUsageTimeoutMillis);
                    nextCheckTime = mStrongUsageTimeoutMillis;
                }
                mHandler.sendMessageDelayed(mHandler.obtainMessage
                        (MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, pkg),
                if (appHistory.currentBucket != prevBucket) {
                    mHandler.sendMessageDelayed(
                            mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, pkg),
                            nextCheckTime);
                    final boolean userStartedInteracting =
                        appHistory.currentBucket == STANDBY_BUCKET_ACTIVE &&
                        prevBucket != appHistory.currentBucket &&
                        (prevBucketReason & REASON_MAIN_MASK) != REASON_MAIN_USAGE;
                            appHistory.currentBucket == STANDBY_BUCKET_ACTIVE
                                    && (prevBucketReason & REASON_MAIN_MASK) != REASON_MAIN_USAGE;
                    maybeInformListeners(pkg, userId, elapsedRealtime,
                            appHistory.currentBucket, reason, userStartedInteracting);
                }

                if (previouslyIdle) {
                    notifyBatteryStats(pkg, userId, false);
@@ -923,6 +939,15 @@ public class AppStandbyController implements AppStandbyInternal {
        }
    }

    static boolean isUserUsage(int reason) {
        if ((reason & REASON_MAIN_MASK) == REASON_MAIN_USAGE) {
            final int subReason = reason & REASON_SUB_MASK;
            return subReason == REASON_SUB_USAGE_USER_INTERACTION
                    || subReason == REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
        }
        return false;
    }

    @Override
    public int[] getIdleUidsForUser(int userId) {
        if (!mAppIdleEnabled) {
@@ -1016,6 +1041,20 @@ public class AppStandbyController implements AppStandbyInternal {
        }
    }

    @Override
    public void restrictApp(@NonNull String packageName, int userId, int restrictReason) {
        // If the package is not installed, don't allow the bucket to be set.
        if (!mInjector.isPackageInstalled(packageName, 0, userId)) {
            Slog.e(TAG, "Tried to restrict uninstalled app: " + packageName);
            return;
        }

        final int reason = REASON_MAIN_FORCED_BY_SYSTEM | (REASON_SUB_MASK & restrictReason);
        final long nowElapsed = mInjector.elapsedRealtime();
        setAppStandbyBucket(packageName, userId, STANDBY_BUCKET_RESTRICTED, reason,
                nowElapsed, false);
    }

    @Override
    public void setAppStandbyBucket(@NonNull String packageName, int bucket, int userId,
            int callingUid, int callingPid) {
@@ -1080,6 +1119,7 @@ public class AppStandbyController implements AppStandbyInternal {
        synchronized (mAppIdleLock) {
            // If the package is not installed, don't allow the bucket to be set.
            if (!mInjector.isPackageInstalled(packageName, 0, userId)) {
                Slog.e(TAG, "Tried to set bucket of uninstalled app: " + packageName);
                return;
            }
            AppIdleHistory.AppUsageHistory app = mAppIdleHistory.getAppUsageHistory(packageName,
@@ -1089,8 +1129,9 @@ public class AppStandbyController implements AppStandbyInternal {
            // Don't allow changing bucket if higher than ACTIVE
            if (app.currentBucket < STANDBY_BUCKET_ACTIVE) return;

            // Don't allow prediction to change from/to NEVER
            // Don't allow prediction to change from/to NEVER or from RESTRICTED.
            if ((app.currentBucket == STANDBY_BUCKET_NEVER
                    || app.currentBucket == STANDBY_BUCKET_RESTRICTED
                    || newBucket == STANDBY_BUCKET_NEVER)
                    && predicted) {
                return;
@@ -1103,6 +1144,50 @@ public class AppStandbyController implements AppStandbyInternal {
                return;
            }

            final boolean isForcedByUser =
                    (reason & REASON_MAIN_MASK) == REASON_MAIN_FORCED_BY_USER;

            // If the current bucket is RESTRICTED, only user force or usage should bring it out.
            if (app.currentBucket == STANDBY_BUCKET_RESTRICTED && !isUserUsage(reason)
                    && !isForcedByUser) {
                return;
            }

            if (newBucket == STANDBY_BUCKET_RESTRICTED) {
                mAppIdleHistory
                        .noteRestrictionAttempt(packageName, userId, elapsedRealtime, reason);

                if (isForcedByUser) {
                    // Only user force can bypass the delay restriction. If the user forced the
                    // app into the RESTRICTED bucket, then a toast confirming the action
                    // shouldn't be surprising.
                    if (Build.IS_DEBUGGABLE) {
                        Toast.makeText(mContext,
                                // Since AppStandbyController sits low in the lock hierarchy,
                                // make sure not to call out with the lock held.
                                mHandler.getLooper(),
                                mContext.getResources().getString(
                                        R.string.as_app_forced_to_restricted_bucket, packageName),
                                Toast.LENGTH_SHORT)
                                .show();
                    } else {
                        Slog.i(TAG, packageName + " restricted by user");
                    }
                } else {
                    final long timeUntilRestrictPossibleMs = app.lastUsedByUserElapsedTime
                            + mInjector.getRestrictedBucketDelayMs() - elapsedRealtime;
                    if (timeUntilRestrictPossibleMs > 0) {
                        Slog.w(TAG, "Tried to restrict recently used app: " + packageName
                                + " due to " + reason);
                        mHandler.sendMessageDelayed(
                                mHandler.obtainMessage(
                                        MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, packageName),
                                timeUntilRestrictPossibleMs);
                        return;
                    }
                }
            }

            // If the bucket is required to stay in a higher state for a specified duration, don't
            // override unless the duration has passed
            if (predicted) {
@@ -1435,6 +1520,12 @@ public class AppStandbyController implements AppStandbyInternal {
        private DisplayManager mDisplayManager;
        private PowerManager mPowerManager;
        int mBootPhase;
        /**
         * The minimum amount of time required since the last user interaction before an app can be
         * placed in the RESTRICTED bucket.
         */
        // TODO: make configurable via DeviceConfig
        private long mRestrictedBucketDelayMs = ONE_DAY;

        Injector(Context context, Looper looper) {
            mContext = context;
@@ -1459,6 +1550,12 @@ public class AppStandbyController implements AppStandbyInternal {
                mDisplayManager = (DisplayManager) mContext.getSystemService(
                        Context.DISPLAY_SERVICE);
                mPowerManager = mContext.getSystemService(PowerManager.class);

                final ActivityManager activityManager =
                        (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
                if (activityManager.isLowRamDevice() || ActivityManager.isSmallBatteryDevice()) {
                    mRestrictedBucketDelayMs = 12 * ONE_HOUR;
                }
            }
            mBootPhase = phase;
        }
@@ -1498,6 +1595,10 @@ public class AppStandbyController implements AppStandbyInternal {
            return Environment.getDataSystemDirectory();
        }

        long getRestrictedBucketDelayMs() {
            return mRestrictedBucketDelayMs;
        }

        void noteEvent(int event, String packageName, int uid) throws RemoteException {
            mBatteryStats.noteEvent(event, packageName, uid);
        }
+1 −0
Original line number Diff line number Diff line
@@ -8030,6 +8030,7 @@ package android.app.usage {
    field public static final int STANDBY_BUCKET_ACTIVE = 10; // 0xa
    field public static final int STANDBY_BUCKET_FREQUENT = 30; // 0x1e
    field public static final int STANDBY_BUCKET_RARE = 40; // 0x28
    field public static final int STANDBY_BUCKET_RESTRICTED = 45; // 0x2d
    field public static final int STANDBY_BUCKET_WORKING_SET = 20; // 0x14
  }
Loading