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

Commit 77dadd93 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Global app standby flag"

parents 42c11e7a 172612c8
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -9587,9 +9587,10 @@ public final class Settings {
        /**
         * App standby (app idle) specific settings.
         * This is encoded as a key=value list, separated by commas. Ex:
         *
         * <p>
         * "idle_duration=5000,parole_interval=4500"
         *
         * <p>
         * All durations are in millis.
         * The following keys are supported:
         *
         * <pre>
@@ -9738,6 +9739,15 @@ public final class Settings {
         */
        public static final String TEXT_CLASSIFIER_CONSTANTS = "text_classifier_constants";

        /**
         * Whether or not App Standby feature is enabled. This controls throttling of apps
         * based on usage patterns and predictions.
         * Type: int (0 for false, 1 for true)
         * Default: 1
         * @hide
         */
        public static final java.lang.String APP_STANDBY_ENABLED = "app_standby_enabled";

        /**
         * Get the key that retrieves a bluetooth headset's priority.
         * @hide
+1 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ public class SettingsBackupTest {
                    Settings.Global.APN_DB_UPDATE_CONTENT_URL,
                    Settings.Global.APN_DB_UPDATE_METADATA_URL,
                    Settings.Global.APP_IDLE_CONSTANTS,
                    Settings.Global.APP_STANDBY_ENABLED,
                    Settings.Global.ASSISTED_GPS_ENABLED,
                    Settings.Global.AUDIO_SAFE_VOLUME_STATE,
                    Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
+29 −18
Original line number Diff line number Diff line
@@ -16,6 +16,15 @@

package com.android.server.usage;

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_USAGE;
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_WORKING_SET;

import android.app.usage.UsageStatsManager;
import android.os.SystemClock;
import android.util.ArrayMap;
@@ -197,14 +206,14 @@ public class AppIdleHistory {
                + (elapsedRealtime - mElapsedSnapshot);
        appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
        appUsageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
        if (appUsageHistory.currentBucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) {
            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
        if (appUsageHistory.currentBucket > STANDBY_BUCKET_ACTIVE) {
            appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
            if (DEBUG) {
                Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
                        + ", reason=" + appUsageHistory.bucketingReason);
            }
        }
        appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
        appUsageHistory.bucketingReason = REASON_USAGE;

        return appUsageHistory.currentBucket;
    }
@@ -213,15 +222,15 @@ public class AppIdleHistory {
        ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
        AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
                elapsedRealtime, true);
        if (appUsageHistory.currentBucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
        if (appUsageHistory.currentBucket > STANDBY_BUCKET_WORKING_SET) {
            appUsageHistory.currentBucket = 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 = UsageStatsManager.REASON_USAGE;
        appUsageHistory.bucketingReason = REASON_USAGE;

        return appUsageHistory.currentBucket;
    }
@@ -279,8 +288,8 @@ public class AppIdleHistory {
            appUsageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
            appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
            appUsageHistory.lastPredictedTime = getElapsedTime(0);
            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_NEVER;
            appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
            appUsageHistory.currentBucket = STANDBY_BUCKET_NEVER;
            appUsageHistory.bucketingReason = REASON_DEFAULT;
            appUsageHistory.lastInformedBucket = -1;
            userHistory.put(packageName, appUsageHistory);
        }
@@ -298,7 +307,7 @@ public class AppIdleHistory {
        if (appUsageHistory == null) {
            return false; // Default to not idle
        } else {
            return appUsageHistory.currentBucket >= UsageStatsManager.STANDBY_BUCKET_RARE;
            return appUsageHistory.currentBucket >= 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);
@@ -320,7 +329,7 @@ public class AppIdleHistory {
                getPackageHistory(userHistory, packageName, elapsedRealtime, true);
        appUsageHistory.currentBucket = bucket;
        appUsageHistory.bucketingReason = reason;
        if (reason.startsWith(UsageStatsManager.REASON_PREDICTED)) {
        if (reason.startsWith(REASON_PREDICTED)) {
            appUsageHistory.lastPredictedTime = getElapsedTime(elapsedRealtime);
        }
        if (DEBUG) {
@@ -336,12 +345,14 @@ public class AppIdleHistory {
        return appUsageHistory.currentBucket;
    }

    public Map<String, Integer> getAppStandbyBuckets(int userId, long elapsedRealtime) {
    public Map<String, Integer> getAppStandbyBuckets(int userId, long elapsedRealtime,
            boolean appIdleEnabled) {
        ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
        int size = userHistory.size();
        HashMap<String, Integer> buckets = new HashMap<>(size);
        for (int i = 0; i < size; i++) {
            buckets.put(userHistory.keyAt(i), userHistory.valueAt(i).currentBucket);
            buckets.put(userHistory.keyAt(i),
                    appIdleEnabled ? userHistory.valueAt(i).currentBucket : STANDBY_BUCKET_ACTIVE);
        }
        return buckets;
    }
@@ -363,12 +374,12 @@ public class AppIdleHistory {
        AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
                elapsedRealtime, true);
        if (idle) {
            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_RARE;
            appUsageHistory.bucketingReason = UsageStatsManager.REASON_FORCED;
            appUsageHistory.currentBucket = STANDBY_BUCKET_RARE;
            appUsageHistory.bucketingReason = REASON_FORCED;
        } else {
            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
            appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
            // This is to pretend that the app was just used, don't freeze the state anymore.
            appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
            appUsageHistory.bucketingReason = REASON_USAGE;
        }
        return appUsageHistory.currentBucket;
    }
@@ -471,12 +482,12 @@ public class AppIdleHistory {
                        String currentBucketString = parser.getAttributeValue(null,
                                ATTR_CURRENT_BUCKET);
                        appUsageHistory.currentBucket = currentBucketString == null
                                ? UsageStatsManager.STANDBY_BUCKET_ACTIVE
                                ? STANDBY_BUCKET_ACTIVE
                                : Integer.parseInt(currentBucketString);
                        appUsageHistory.bucketingReason =
                                parser.getAttributeValue(null, ATTR_BUCKETING_REASON);
                        if (appUsageHistory.bucketingReason == null) {
                            appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
                            appUsageHistory.bucketingReason = REASON_DEFAULT;
                        }
                        appUsageHistory.lastInformedBucket = -1;
                        userHistory.put(packageName, appUsageHistory);
+52 −23
Original line number Diff line number Diff line
@@ -162,12 +162,14 @@ public class AppStandbyController {
    long[] mAppStandbyScreenThresholds = SCREEN_TIME_THRESHOLDS;
    long[] mAppStandbyElapsedThresholds = ELAPSED_TIME_THRESHOLDS;

    boolean mAppIdleEnabled;
    volatile boolean mAppIdleEnabled;
    boolean mAppIdleTempParoled;
    boolean mCharging;
    private long mLastAppIdleParoledTime;
    private boolean mSystemServicesReady = false;

    private final DeviceStateReceiver mDeviceStateReceiver;

    private volatile boolean mPendingOneTimeCheckIdleStates;

    private final AppStandbyHandler mHandler;
@@ -178,7 +180,7 @@ public class AppStandbyController {
    private AppWidgetManager mAppWidgetManager;
    private PowerManager mPowerManager;
    private PackageManager mPackageManager;
    private Injector mInjector;
    Injector mInjector;


    AppStandbyController(Context context, Looper looper) {
@@ -190,14 +192,13 @@ public class AppStandbyController {
        mContext = mInjector.getContext();
        mHandler = new AppStandbyHandler(mInjector.getLooper());
        mPackageManager = mContext.getPackageManager();
        mAppIdleEnabled = mInjector.isAppIdleEnabled();
        mDeviceStateReceiver = new DeviceStateReceiver();

        if (mAppIdleEnabled) {
        IntentFilter deviceStates = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
        deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
            mContext.registerReceiver(new DeviceStateReceiver(), deviceStates);
        }
        mContext.registerReceiver(mDeviceStateReceiver, deviceStates);

        synchronized (mAppIdleLock) {
            mAppIdleHistory = new AppIdleHistory(mInjector.getDataSystemDirectory(),
                    mInjector.elapsedRealtime());
@@ -213,9 +214,14 @@ public class AppStandbyController {
                null, mHandler);
    }

    void setAppIdleEnabled(boolean enabled) {
        mAppIdleEnabled = enabled;
    }

    public void onBootPhase(int phase) {
        mInjector.onBootPhase(phase);
        if (phase == PHASE_SYSTEM_SERVICES_READY) {
            setAppIdleEnabled(mInjector.isAppIdleEnabled());
            // Observe changes to the threshold
            SettingsObserver settingsObserver = new SettingsObserver(mHandler);
            settingsObserver.registerObserver();
@@ -240,6 +246,8 @@ public class AppStandbyController {
    }

    void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
        if (!mAppIdleEnabled) return;

        // Get sync adapters for the authority
        String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser(
                authority, userId);
@@ -295,6 +303,7 @@ public class AppStandbyController {
    }

    boolean isParoledOrCharging() {
        if (!mAppIdleEnabled) return true;
        synchronized (mAppIdleLock) {
            return mAppIdleTempParoled || mCharging;
        }
@@ -520,6 +529,7 @@ public class AppStandbyController {
    }

    void reportEvent(UsageEvents.Event event, long elapsedRealtime, int userId) {
        if (!mAppIdleEnabled) return;
        synchronized (mAppIdleLock) {
            // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
            // about apps that are on some kind of whitelist anyway.
@@ -559,6 +569,8 @@ public class AppStandbyController {
     * required.
     */
    void forceIdleState(String packageName, int userId, boolean idle) {
        if (!mAppIdleEnabled) return;

        final int appId = getAppId(packageName);
        if (appId < 0) return;
        final long elapsedRealtime = mInjector.elapsedRealtime();
@@ -763,7 +775,7 @@ public class AppStandbyController {
    }

    void setAppIdleAsync(String packageName, boolean idle, int userId) {
        if (packageName == null) return;
        if (packageName == null || !mAppIdleEnabled) return;

        mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
                .sendToTarget();
@@ -771,8 +783,8 @@ public class AppStandbyController {

    @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId,
            long elapsedRealtime, boolean shouldObfuscateInstantApps) {
        if (shouldObfuscateInstantApps &&
                mInjector.isPackageEphemeral(userId, packageName)) {
        if (!mAppIdleEnabled || (shouldObfuscateInstantApps
                && mInjector.isPackageEphemeral(userId, packageName))) {
            return STANDBY_BUCKET_ACTIVE;
        }

@@ -783,7 +795,7 @@ public class AppStandbyController {

    public Map<String, Integer> getAppStandbyBuckets(int userId, long elapsedRealtime) {
        synchronized (mAppIdleLock) {
            return mAppIdleHistory.getAppStandbyBuckets(userId, elapsedRealtime);
            return mAppIdleHistory.getAppStandbyBuckets(userId, elapsedRealtime, mAppIdleEnabled);
        }
    }

@@ -1058,8 +1070,11 @@ public class AppStandbyController {
        }

        boolean isAppIdleEnabled() {
            return mContext.getResources().getBoolean(
            final boolean buildFlag = mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_enableAutoPowerModes);
            final boolean runtimeFlag = Settings.Global.getInt(mContext.getContentResolver(),
                    Settings.Global.APP_STANDBY_ENABLED, 1) == 1;
            return buildFlag && runtimeFlag;
        }

        boolean isCharging() {
@@ -1130,7 +1145,7 @@ public class AppStandbyController {
                    break;

                case MSG_CHECK_IDLE_STATES:
                    if (checkIdleStates(msg.arg1)) {
                    if (checkIdleStates(msg.arg1) && mAppIdleEnabled) {
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(
                                MSG_CHECK_IDLE_STATES, msg.arg1, 0),
                                mCheckIdleIntervalMillis);
@@ -1229,6 +1244,8 @@ public class AppStandbyController {
        void registerObserver() {
            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.APP_IDLE_CONSTANTS), false, this);
            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.APP_STANDBY_ENABLED), false, this);
        }

        @Override
@@ -1238,7 +1255,17 @@ public class AppStandbyController {
        }

        void updateSettings() {
            synchronized (mAppIdleLock) {
            if (DEBUG) {
                Slog.d(TAG,
                        "appidle=" + Settings.Global.getString(mContext.getContentResolver(),
                                Settings.Global.APP_STANDBY_ENABLED));
                Slog.d(TAG, "appidleconstants=" + Settings.Global.getString(
                        mContext.getContentResolver(),
                        Settings.Global.APP_IDLE_CONSTANTS));
            }
            // Check if app_idle_enabled has changed
            setAppIdleEnabled(mInjector.isAppIdleEnabled());

            // Look at global settings for this.
            // TODO: Maybe apply different thresholds for different users.
            try {
@@ -1248,6 +1275,8 @@ public class AppStandbyController {
                // fallthrough, mParser is empty and all defaults will be returned.
            }

            synchronized (mAppIdleLock) {

                // Default: 24 hours between paroles
                mAppIdleParoleIntervalMillis = mParser.getLong(KEY_PAROLE_INTERVAL,
                        COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE);