Merge "Add support to pre-config bg restriction exemptions in system config"
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 39f17e5..93864fa 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -237,6 +237,10 @@
     // be delivered anonymously even to apps which target O+.
     final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
 
+    // These are the packages that are exempted from the background restriction applied
+    // by the system automatically, i.e., due to high background current drain.
+    final ArraySet<String> mBgRestrictionExemption = new ArraySet<>();
+
     // These are the package names of apps which should be automatically granted domain verification
     // for all of their domains. The only way these apps can be overridden by the user is by
     // explicitly disabling overall link handling support in app info.
@@ -389,6 +393,10 @@
         return mAllowIgnoreLocationSettings;
     }
 
+    public ArraySet<String> getBgRestrictionExemption() {
+        return mBgRestrictionExemption;
+    }
+
     public ArraySet<String> getLinkedApps() {
         return mLinkedApps;
     }
@@ -1049,6 +1057,20 @@
                         }
                         XmlUtils.skipCurrentTag(parser);
                     } break;
+                    case "bg-restriction-exemption": {
+                        if (allowOverrideAppRestrictions) {
+                            String pkgname = parser.getAttributeValue(null, "package");
+                            if (pkgname == null) {
+                                Slog.w(TAG, "<" + name + "> without package in "
+                                        + permFile + " at " + parser.getPositionDescription());
+                            } else {
+                                mBgRestrictionExemption.add(pkgname);
+                            }
+                        } else {
+                            logNotAllowedInPartition(name, permFile, parser);
+                        }
+                        XmlUtils.skipCurrentTag(parser);
+                    } break;
                     case "default-enabled-vr-app": {
                         if (allowAppConfigs) {
                             String pkgname = parser.getAttributeValue(null, "package");
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 152d278..465623f 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -66,6 +66,7 @@
 import static android.os.PowerExemptionManager.REASON_PROFILE_OWNER;
 import static android.os.PowerExemptionManager.REASON_ROLE_DIALER;
 import static android.os.PowerExemptionManager.REASON_ROLE_EMERGENCY;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
 import static android.os.PowerExemptionManager.REASON_SYSTEM_MODULE;
 import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
 import static android.os.Process.SYSTEM_UID;
@@ -140,6 +141,7 @@
 import com.android.internal.util.function.TriConsumer;
 import com.android.server.AppStateTracker;
 import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
 import com.android.server.apphibernation.AppHibernationManagerInternal;
 import com.android.server.pm.UserManagerInternal;
 import com.android.server.usage.AppStandbyInternal;
@@ -232,6 +234,11 @@
     private final HashMap<String, Boolean> mSystemModulesCache = new HashMap<>();
 
     /**
+     * The pre-config packages that are exempted from the background restrictions.
+     */
+    private ArraySet<String> mBgRestrictionExemptioFromSysConfig;
+
+    /**
      * Lock specifically for bookkeeping around the carrier-privileged app set.
      * Do not acquire any other locks while holding this one. Methods that
      * require this lock to be held are named with a "CPL" suffix.
@@ -705,6 +712,7 @@
         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 ActivityThread.currentApplication().getMainExecutor(), mConstantsObserver);
         mConstantsObserver.start();
+        initBgRestrictionExemptioFromSysConfig();
         initRestrictionStates();
         initSystemModuleNames();
         registerForUidObservers();
@@ -726,6 +734,22 @@
         initRestrictionStates();
     }
 
+    private void initBgRestrictionExemptioFromSysConfig() {
+        mBgRestrictionExemptioFromSysConfig =
+                SystemConfig.getInstance().getBgRestrictionExemption();
+        if (DEBUG_BG_RESTRICTION_CONTROLLER) {
+            final ArraySet<String> exemptedPkgs = mBgRestrictionExemptioFromSysConfig;
+            for (int i = exemptedPkgs.size() - 1; i >= 0; i--) {
+                Slog.i(TAG, "bg-restriction-exemption: " + exemptedPkgs.valueAt(i));
+            }
+        }
+    }
+
+    private boolean isExemptedFromSysConfig(String packageName) {
+        return mBgRestrictionExemptioFromSysConfig != null
+                && mBgRestrictionExemptioFromSysConfig.contains(packageName);
+    }
+
     private void initRestrictionStates() {
         final int[] allUsers = mInjector.getUserManagerInternal().getUserIds();
         for (int userId : allUsers) {
@@ -1557,14 +1581,11 @@
         }
     }
 
-    boolean isOnDeviceIdleAllowlist(int uid, boolean allowExceptIdle) {
+    boolean isOnDeviceIdleAllowlist(int uid) {
         final int appId = UserHandle.getAppId(uid);
 
-        final int[] allowlist = allowExceptIdle
-                ? mDeviceIdleExceptIdleAllowlist
-                : mDeviceIdleAllowlist;
-
-        return Arrays.binarySearch(allowlist, appId) >= 0;
+        return Arrays.binarySearch(mDeviceIdleAllowlist, appId) >= 0
+                || Arrays.binarySearch(mDeviceIdleExceptIdleAllowlist, appId) >= 0;
     }
 
     void setDeviceIdleAllowlist(int[] allAppids, int[] exceptIdleAppids) {
@@ -1585,7 +1606,7 @@
         if (UserHandle.isCore(uid)) {
             return REASON_SYSTEM_UID;
         }
-        if (isOnDeviceIdleAllowlist(uid, false)) {
+        if (isOnDeviceIdleAllowlist(uid)) {
             return REASON_ALLOWLISTED_PACKAGE;
         }
         final ActivityManagerInternal am = mInjector.getActivityManagerInternal();
@@ -1621,6 +1642,8 @@
                     return REASON_SYSTEM_MODULE;
                 } else if (isCarrierApp(pkg)) {
                     return REASON_CARRIER_PRIVILEGED_APP;
+                } else if (isExemptedFromSysConfig(pkg)) {
+                    return REASON_SYSTEM_ALLOW_LISTED;
                 }
             }
         }