Allow background activity starts to be controlled by DeviceConfig.

If the global setting has been explicitly set to 1 or 0 (e.g. via
developer settings) then that takes precedence - so we don't interfere
with what the user has set. Otherwise the default value from
DeviceConfig is used.

Also migrate the associated (not yet used) package whitelist to
DeviceConfig, so we can set both at the same time. The whitelist is
ignored if the user has explicitly enabled or disabled background
starts.

Bug: 129533810
Test: atest WmTests:ActivityStarterTests

Change-Id: I2856edb5cb8c99a8cfef4712732d9dc9c5d7cdb7
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5c2eacc..bf69728 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11521,15 +11521,6 @@
                 "background_activity_starts_enabled";
 
         /**
-         * The packages temporarily whitelisted to be able so start activities from background.
-         * The list of packages is {@code ":"} colon delimited.
-         *
-         * @hide
-         */
-        public static final String BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST =
-                "background_activity_starts_package_names_whitelist";
-
-        /**
          * @hide
          * @see com.android.server.appbinding.AppBindingConstants
          */
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 80250db..8516ad0 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -131,7 +131,6 @@
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
                     Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
                     Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED,
-                    Settings.Global.BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST,
                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
                     Settings.Global.BROADCAST_BG_CONSTANTS,
                     Settings.Global.BROADCAST_FG_CONSTANTS,
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index b759dd4..d7decb4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -116,6 +116,22 @@
      */
     private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";
 
+    /**
+     * Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
+     * Settings.Global. This allows it to be set experimentally unless it has been
+     * enabled/disabled in developer options. Defaults to true.
+     */
+    private static final String KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED =
+            "default_background_activity_starts_enabled";
+
+    /**
+     * The packages temporarily whitelisted to be able to start activities from background.
+     * The list of packages is {@code ":"} colon delimited.
+     */
+    private static final String KEY_BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST =
+            "background_activity_starts_package_names_whitelist";
+
+
     // Maximum number of cached processes we will allow.
     public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
 
@@ -242,7 +258,8 @@
     volatile boolean mFlagActivityStartsLoggingEnabled;
 
     // Indicates whether the background activity starts is enabled.
-    // Controlled by Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED
+    // Controlled by Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED.
+    // If not set explicitly the default is controlled by DeviceConfig.
     volatile boolean mFlagBackgroundActivityStartsEnabled;
 
     volatile ArraySet<String> mPackageNamesWhitelistedForBgActivityStarts = new ArraySet<>();
@@ -295,10 +312,6 @@
                 Settings.Global.getUriFor(
                         Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED);
 
-    private static final Uri BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI =
-                Settings.Global.getUriFor(
-                        Settings.Global.BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST);
-
     private static final Uri ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI =
             Settings.Global.getUriFor(Settings.Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS);
 
@@ -306,8 +319,19 @@
             new OnPropertyChangedListener() {
                 @Override
                 public void onPropertyChanged(String namespace, String name, String value) {
-                    if (KEY_MAX_CACHED_PROCESSES.equals(name)) {
-                        updateMaxCachedProcesses();
+                    if (name == null) {
+                        return;
+                    }
+                    switch (name) {
+                        case KEY_MAX_CACHED_PROCESSES:
+                            updateMaxCachedProcesses();
+                            break;
+                        case KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED:
+                        case KEY_BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST:
+                            updateBackgroundActivityStarts();
+                            break;
+                        default:
+                            break;
                     }
                 }
             };
@@ -330,16 +354,11 @@
         mResolver.registerContentObserver(ACTIVITY_MANAGER_CONSTANTS_URI, false, this);
         mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this);
         mResolver.registerContentObserver(BACKGROUND_ACTIVITY_STARTS_ENABLED_URI, false, this);
-        mResolver.registerContentObserver(BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI,
-                false, this);
         if (mSystemServerAutomaticHeapDumpEnabled) {
             mResolver.registerContentObserver(ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI,
                     false, this);
         }
         updateConstants();
-        updateActivityStartsLoggingEnabled();
-        updateBackgroundActivityStartsEnabled();
-        updateBackgroundActivityStartsPackageNamesWhitelist();
         if (mSystemServerAutomaticHeapDumpEnabled) {
             updateEnableAutomaticSystemServerHeapDumps();
         }
@@ -347,7 +366,8 @@
                 ActivityThread.currentApplication().getMainExecutor(),
                 mOnDeviceConfigChangedListener);
         updateMaxCachedProcesses();
-
+        updateActivityStartsLoggingEnabled();
+        updateBackgroundActivityStarts();
     }
 
     public void setOverrideMaxCachedProcesses(int value) {
@@ -371,9 +391,7 @@
         } else if (ACTIVITY_STARTS_LOGGING_ENABLED_URI.equals(uri)) {
             updateActivityStartsLoggingEnabled();
         } else if (BACKGROUND_ACTIVITY_STARTS_ENABLED_URI.equals(uri)) {
-            updateBackgroundActivityStartsEnabled();
-        } else if (BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST_URI.equals(uri)) {
-            updateBackgroundActivityStartsPackageNamesWhitelist();
+            updateBackgroundActivityStarts();
         } else if (ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI.equals(uri)) {
             updateEnableAutomaticSystemServerHeapDumps();
         }
@@ -463,24 +481,40 @@
                 Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED, 1) == 1;
     }
 
-    private void updateBackgroundActivityStartsEnabled() {
-        mFlagBackgroundActivityStartsEnabled = Settings.Global.getInt(mResolver,
-                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, 1) == 1;
-    }
+    private void updateBackgroundActivityStarts() {
+        String whitelistedPackageNames = null;
+        int settingsValue = Settings.Global.getInt(mResolver,
+                Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, -1);
 
-    private void updateBackgroundActivityStartsPackageNamesWhitelist() {
-        final String setting = Settings.Global.getString(mResolver,
-                Settings.Global.BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST);
-        if (TextUtils.isEmpty(setting)) {
-            return;
+        // If the user has explicitly enabled or disabled, that affects all apps.
+        // Otherwise we take the default state and whitelist from DeviceConfig.
+        if (settingsValue >= 0) {
+            mFlagBackgroundActivityStartsEnabled = settingsValue != 0;
+        } else {
+            boolean enabledInDeviceConfig = DeviceConfig.getBoolean(
+                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                    KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED,
+                    /*defaultValue*/ true);
+            mFlagBackgroundActivityStartsEnabled = enabledInDeviceConfig;
+            if (!enabledInDeviceConfig) {
+                whitelistedPackageNames = DeviceConfig.getProperty(
+                        DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                        KEY_BACKGROUND_ACTIVITY_STARTS_PACKAGE_NAMES_WHITELIST);
+            }
         }
-        ArraySet<String> newSet = new ArraySet<>();
-        SimpleStringSplitter splitter = new SimpleStringSplitter(':');
-        splitter.setString(setting);
-        while (splitter.hasNext()) {
-            newSet.add(splitter.next());
+        if (TextUtils.isEmpty(whitelistedPackageNames)) {
+            if (!mPackageNamesWhitelistedForBgActivityStarts.isEmpty()) {
+                mPackageNamesWhitelistedForBgActivityStarts = new ArraySet<>();
+            }
+        } else {
+            ArraySet<String> newSet = new ArraySet<>();
+            SimpleStringSplitter splitter = new SimpleStringSplitter(':');
+            splitter.setString(whitelistedPackageNames);
+            while (splitter.hasNext()) {
+                newSet.add(splitter.next());
+            }
+            mPackageNamesWhitelistedForBgActivityStarts = newSet;
         }
-        mPackageNamesWhitelistedForBgActivityStarts = newSet;
     }
 
     private void updateEnableAutomaticSystemServerHeapDumps() {