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

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

Merge "Migrate AlarmManager to DeviceConfig."

parents 189d6050 1e7a69c6
Loading
Loading
Loading
Loading
+127 −78
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.app.AlarmManager.RTC_WAKEUP;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.os.UserHandle.USER_SYSTEM;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManagerInternal;
@@ -39,12 +40,10 @@ import android.app.PendingIntent;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
@@ -68,6 +67,7 @@ import android.os.ThreadLocalWorkSource;
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.system.Os;
import android.text.TextUtils;
@@ -76,7 +76,6 @@ import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.KeyValueListParser;
import android.util.Log;
import android.util.LongArrayQueue;
import android.util.MutableBoolean;
@@ -102,6 +101,7 @@ import com.android.server.AppStateTrackerImpl;
import com.android.server.AppStateTrackerImpl.Listener;
import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
@@ -374,7 +374,7 @@ public class AlarmManagerService extends SystemService {
     * holding the AlarmManagerService.mLock lock.
     */
    @VisibleForTesting
    final class Constants extends ContentObserver {
    final class Constants implements DeviceConfig.OnPropertiesChangedListener {
        // Key names stored in the settings value.
        @VisibleForTesting
        static final String KEY_MIN_FUTURITY = "min_futurity";
@@ -394,17 +394,19 @@ public class AlarmManagerService extends SystemService {
        @VisibleForTesting
        static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid";
        private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window";
        private static final String KEY_PREFIX_STANDBY_QUOTA = "standby_quota_";
        @VisibleForTesting
        final String[] KEYS_APP_STANDBY_QUOTAS = {
                "standby_active_quota",
                "standby_working_quota",
                "standby_frequent_quota",
                "standby_rare_quota",
                "standby_never_quota",
                KEY_PREFIX_STANDBY_QUOTA + "active",
                KEY_PREFIX_STANDBY_QUOTA + "working",
                KEY_PREFIX_STANDBY_QUOTA + "frequent",
                KEY_PREFIX_STANDBY_QUOTA + "rare",
                KEY_PREFIX_STANDBY_QUOTA + "never",
        };
        // Not putting this in the KEYS_APP_STANDBY_QUOTAS array because this uses a different
        // window size.
        private static final String KEY_APP_STANDBY_RESTRICTED_QUOTA = "standby_restricted_quota";
        private static final String KEY_APP_STANDBY_RESTRICTED_QUOTA =
                KEY_PREFIX_STANDBY_QUOTA + "restricted";
        private static final String KEY_APP_STANDBY_RESTRICTED_WINDOW =
                "app_standby_restricted_window";

@@ -458,20 +460,18 @@ public class AlarmManagerService extends SystemService {
        public int APP_STANDBY_RESTRICTED_QUOTA = DEFAULT_APP_STANDBY_RESTRICTED_QUOTA;
        public long APP_STANDBY_RESTRICTED_WINDOW = DEFAULT_APP_STANDBY_RESTRICTED_WINDOW;

        private ContentResolver mResolver;
        private final KeyValueListParser mParser = new KeyValueListParser(',');
        private long mLastAllowWhileIdleWhitelistDuration = -1;

        public Constants(Handler handler) {
            super(handler);
        Constants() {
            updateAllowWhileIdleWhitelistDurationLocked();
            for (int i = 0; i < APP_STANDBY_QUOTAS.length; i++) {
                APP_STANDBY_QUOTAS[i] = DEFAULT_APP_STANDBY_QUOTAS[i];
            }
        }

        public void start(ContentResolver resolver) {
            mResolver = resolver;
            mResolver.registerContentObserver(Settings.Global.getUriFor(
                    Settings.Global.ALARM_MANAGER_CONSTANTS), false, this);
            updateConstants();
        public void start() {
            mInjector.registerDeviceConfigListener(this);
            onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ALARM_MANAGER));
        }

        public void updateAllowWhileIdleWhitelistDurationLocked() {
@@ -484,71 +484,115 @@ public class AlarmManagerService extends SystemService {
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            updateConstants();
        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
            boolean standbyQuotaUpdated = false;
            synchronized (mLock) {
                for (String name : properties.getKeyset()) {
                    if (name == null) {
                        continue;
                    }

        private void updateConstants() {
            synchronized (mLock) {
                try {
                    mParser.setString(Settings.Global.getString(mResolver,
                            Settings.Global.ALARM_MANAGER_CONSTANTS));
                } catch (IllegalArgumentException e) {
                    // Failed to parse the settings string, log this and move on
                    // with defaults.
                    Slog.e(TAG, "Bad alarm manager settings", e);
                }

                MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
                MIN_INTERVAL = mParser.getLong(KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
                MAX_INTERVAL = mParser.getLong(KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
                ALLOW_WHILE_IDLE_SHORT_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
                    switch (name) {
                        case KEY_MIN_FUTURITY:
                            MIN_FUTURITY = properties.getLong(
                                    KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
                            break;
                        case KEY_MIN_INTERVAL:
                            MIN_INTERVAL = properties.getLong(
                                    KEY_MIN_INTERVAL, DEFAULT_MIN_INTERVAL);
                            break;
                        case KEY_MAX_INTERVAL:
                            MAX_INTERVAL = properties.getLong(
                                    KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
                            break;
                        case KEY_ALLOW_WHILE_IDLE_SHORT_TIME:
                            ALLOW_WHILE_IDLE_SHORT_TIME = properties.getLong(
                                    KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
                                    DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
                ALLOW_WHILE_IDLE_LONG_TIME = mParser.getLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME,
                            break;
                        case KEY_ALLOW_WHILE_IDLE_LONG_TIME:
                            ALLOW_WHILE_IDLE_LONG_TIME = properties.getLong(
                                    KEY_ALLOW_WHILE_IDLE_LONG_TIME,
                                    DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
                ALLOW_WHILE_IDLE_WHITELIST_DURATION = mParser.getLong(
                            break;
                        case KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION:
                            ALLOW_WHILE_IDLE_WHITELIST_DURATION = properties.getLong(
                                    KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION,
                                    DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
                LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
                        DEFAULT_LISTENER_TIMEOUT);

                APP_STANDBY_WINDOW = mParser.getLong(KEY_APP_STANDBY_WINDOW,
                        DEFAULT_APP_STANDBY_WINDOW);
                if (APP_STANDBY_WINDOW > DEFAULT_APP_STANDBY_WINDOW) {
                    Slog.w(TAG, "Cannot exceed the app_standby_window size of "
                            + DEFAULT_APP_STANDBY_WINDOW);
                    APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
                } else if (APP_STANDBY_WINDOW < DEFAULT_APP_STANDBY_WINDOW) {
                    // Not recommended outside of testing.
                    Slog.w(TAG, "Using a non-default app_standby_window of " + APP_STANDBY_WINDOW);
                            updateAllowWhileIdleWhitelistDurationLocked();
                            break;
                        case KEY_LISTENER_TIMEOUT:
                            LISTENER_TIMEOUT = properties.getLong(
                                    KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT);
                            break;
                        case KEY_MAX_ALARMS_PER_UID:
                            MAX_ALARMS_PER_UID = properties.getInt(
                                    KEY_MAX_ALARMS_PER_UID, DEFAULT_MAX_ALARMS_PER_UID);
                            if (MAX_ALARMS_PER_UID < DEFAULT_MAX_ALARMS_PER_UID) {
                                Slog.w(TAG, "Cannot set " + KEY_MAX_ALARMS_PER_UID + " lower than "
                                        + DEFAULT_MAX_ALARMS_PER_UID);
                                MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
                            }
                            break;
                        case KEY_APP_STANDBY_WINDOW:
                        case KEY_APP_STANDBY_RESTRICTED_WINDOW:
                            updateStandbyWindowsLocked();
                            break;
                        default:
                            if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
                                // The quotas need to be updated in order, so we can't just rely
                                // on the property iteration order.
                                updateStandbyQuotasLocked();
                                standbyQuotaUpdated = true;
                            }
                            break;
                    }
                }
            }
        }

        private void updateStandbyQuotasLocked() {
            // The bucket quotas need to be read as an atomic unit but the properties passed to
            // onPropertiesChanged may only have one key populated at a time.
            final DeviceConfig.Properties properties = DeviceConfig.getProperties(
                    DeviceConfig.NAMESPACE_ALARM_MANAGER, KEYS_APP_STANDBY_QUOTAS);

                APP_STANDBY_QUOTAS[ACTIVE_INDEX] = mParser.getInt(
            APP_STANDBY_QUOTAS[ACTIVE_INDEX] = properties.getInt(
                    KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX],
                    DEFAULT_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
            for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
                    APP_STANDBY_QUOTAS[i] = mParser.getInt(KEYS_APP_STANDBY_QUOTAS[i],
                APP_STANDBY_QUOTAS[i] = properties.getInt(
                        KEYS_APP_STANDBY_QUOTAS[i],
                        Math.min(APP_STANDBY_QUOTAS[i - 1], DEFAULT_APP_STANDBY_QUOTAS[i]));
            }

            APP_STANDBY_RESTRICTED_QUOTA = Math.max(1,
                        mParser.getInt(KEY_APP_STANDBY_RESTRICTED_QUOTA,
                    DeviceConfig.getInt(DeviceConfig.NAMESPACE_ALARM_MANAGER,
                            KEY_APP_STANDBY_RESTRICTED_QUOTA,
                            DEFAULT_APP_STANDBY_RESTRICTED_QUOTA));

                APP_STANDBY_RESTRICTED_WINDOW = Math.max(APP_STANDBY_WINDOW,
                        mParser.getLong(KEY_APP_STANDBY_RESTRICTED_WINDOW,
                                DEFAULT_APP_STANDBY_RESTRICTED_WINDOW));

                MAX_ALARMS_PER_UID = mParser.getInt(KEY_MAX_ALARMS_PER_UID,
                        DEFAULT_MAX_ALARMS_PER_UID);
                if (MAX_ALARMS_PER_UID < DEFAULT_MAX_ALARMS_PER_UID) {
                    Slog.w(TAG, "Cannot set " + KEY_MAX_ALARMS_PER_UID + " lower than "
                            + DEFAULT_MAX_ALARMS_PER_UID);
                    MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
        }

                updateAllowWhileIdleWhitelistDurationLocked();
        private void updateStandbyWindowsLocked() {
            // The bucket windows need to be read as an atomic unit but the properties passed to
            // onPropertiesChanged may only have one key populated at a time.
            final DeviceConfig.Properties properties = DeviceConfig.getProperties(
                    DeviceConfig.NAMESPACE_ALARM_MANAGER,
                    KEY_APP_STANDBY_WINDOW, KEY_APP_STANDBY_RESTRICTED_WINDOW);
            APP_STANDBY_WINDOW = properties.getLong(
                    KEY_APP_STANDBY_WINDOW, DEFAULT_APP_STANDBY_WINDOW);
            if (APP_STANDBY_WINDOW > DEFAULT_APP_STANDBY_WINDOW) {
                Slog.w(TAG, "Cannot exceed the app_standby_window size of "
                        + DEFAULT_APP_STANDBY_WINDOW);
                APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
            } else if (APP_STANDBY_WINDOW < DEFAULT_APP_STANDBY_WINDOW) {
                // Not recommended outside of testing.
                Slog.w(TAG, "Using a non-default app_standby_window of " + APP_STANDBY_WINDOW);
            }

            APP_STANDBY_RESTRICTED_WINDOW = Math.max(APP_STANDBY_WINDOW,
                    properties.getLong(
                            KEY_APP_STANDBY_RESTRICTED_WINDOW,
                            DEFAULT_APP_STANDBY_RESTRICTED_WINDOW));
        }

        void dump(PrintWriter pw, String prefix) {
@@ -1199,7 +1243,7 @@ public class AlarmManagerService extends SystemService {

        synchronized (mLock) {
            mHandler = new AlarmHandler();
            mConstants = new Constants(mHandler);
            mConstants = new Constants();
            mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);

            mNextWakeup = mNextNonWakeup = 0;
@@ -1284,7 +1328,7 @@ public class AlarmManagerService extends SystemService {
    public void onBootPhase(int phase) {
        if (phase == PHASE_SYSTEM_SERVICES_READY) {
            synchronized (mLock) {
                mConstants.start(getContext().getContentResolver());
                mConstants.start();
                mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
                mLocalDeviceIdleController =
                        LocalServices.getService(DeviceIdleInternal.class);
@@ -3382,6 +3426,11 @@ public class AlarmManagerService extends SystemService {
        ClockReceiver getClockReceiver(AlarmManagerService service) {
            return service.new ClockReceiver();
        }

        void registerDeviceConfigListener(DeviceConfig.OnPropertiesChangedListener listener) {
            DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ALARM_MANAGER,
                    JobSchedulerBackgroundThread.getExecutor(), listener);
        }
    }

    private class AlarmThread extends Thread {
+1 −0
Original line number Diff line number Diff line
@@ -153,6 +153,7 @@ package android.os {
package android.provider {

  public final class DeviceConfig {
    field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
    field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
  }

+1 −0
Original line number Diff line number Diff line
@@ -3294,6 +3294,7 @@ package android.provider {
    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String);
    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperties(@NonNull android.provider.DeviceConfig.Properties) throws android.provider.DeviceConfig.BadConfigException;
    method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setProperty(@NonNull String, @NonNull String, @Nullable String, boolean);
    field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
    field public static final String NAMESPACE_ANDROID = "android";
    field public static final String NAMESPACE_AUTOFILL = "autofill";
    field public static final String NAMESPACE_BIOMETRICS = "biometrics";
+9 −0
Original line number Diff line number Diff line
@@ -83,6 +83,15 @@ public final class DeviceConfig {
    public static final String NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT =
            "activity_manager_native_boot";

    /**
     * Namespace for AlarmManager configurations.
     *
     * @hide
     */
    @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
    @TestApi
    public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";

    /**
     * Namespace for all app compat related features.  These features will be applied
     * immediately upon change.
+0 −23
Original line number Diff line number Diff line
@@ -11807,29 +11807,6 @@ public final class Settings {
         */
        public static final String POWER_MANAGER_CONSTANTS = "power_manager_constants";
        /**
         * Alarm manager specific settings.
         * This is encoded as a key=value list, separated by commas. Ex:
         *
         * "min_futurity=5000,allow_while_idle_short_time=4500"
         *
         * The following keys are supported:
         *
         * <pre>
         * min_futurity                         (long)
         * min_interval                         (long)
         * allow_while_idle_short_time          (long)
         * allow_while_idle_long_time           (long)
         * allow_while_idle_whitelist_duration  (long)
         * </pre>
         *
         * <p>
         * Type: string
         * @hide
         * @see com.android.server.AlarmManagerService.Constants
         */
        public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants";
        /**
         * Job scheduler QuotaController specific settings.
         * This is encoded as a key=value list, separated by commas. Ex:
Loading