diff options
5 files changed, 98 insertions, 17 deletions
diff --git a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java index a9ca5cf5a26a..caf7e7f4a4ed 100644 --- a/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java +++ b/apex/jobscheduler/framework/java/com/android/server/DeviceIdleInternal.java @@ -96,4 +96,13 @@ public interface DeviceIdleInternal { * that the device is stationary or in motion. */ void unregisterStationaryListener(StationaryListener listener); + + /** + * Apply some restrictions on temp allowlist type based on the reasonCode. + * @param reasonCode temp allowlist reason code. + * @param defaultType default temp allowlist type if reasonCode can not decide a type. + * @return temp allowlist type based on the reasonCode. + */ + @TempAllowListType int getTempAllowListType(@ReasonCode int reasonCode, + @TempAllowListType int defaultType); } diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 57c8300b66f6..60f5769a46f7 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -19,6 +19,7 @@ package com.android.server; import static android.os.PowerExemptionManager.REASON_SHELL; import static android.os.PowerExemptionManager.REASON_UNKNOWN; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE; import static android.os.Process.INVALID_UID; import android.Manifest; @@ -58,6 +59,7 @@ import android.os.Handler; import android.os.IDeviceIdleController; import android.os.Looper; import android.os.Message; +import android.os.PowerExemptionManager; import android.os.PowerExemptionManager.ReasonCode; import android.os.PowerExemptionManager.TempAllowListType; import android.os.PowerManager; @@ -2015,6 +2017,12 @@ public class DeviceIdleController extends SystemService public void unregisterStationaryListener(StationaryListener listener) { DeviceIdleController.this.unregisterStationaryListener(listener); } + + @Override + public @TempAllowListType int getTempAllowListType(@ReasonCode int reasonCode, + @TempAllowListType int defaultType) { + return DeviceIdleController.this.getTempAllowListType(reasonCode, defaultType); + } } private class LocalPowerAllowlistService implements PowerAllowlistInternal { @@ -2689,6 +2697,18 @@ public class DeviceIdleController extends SystemService } } + private @TempAllowListType int getTempAllowListType(@ReasonCode int reasonCode, + @TempAllowListType int defaultType) { + switch (reasonCode) { + case PowerExemptionManager.REASON_PUSH_MESSAGING_OVER_QUOTA: + return mLocalActivityManager.getPushMessagingOverQuotaBehavior(); + case PowerExemptionManager.REASON_DENIED: + return TEMPORARY_ALLOW_LIST_TYPE_NONE; + default: + return defaultType; + } + } + void addPowerSaveTempAllowlistAppChecked(String packageName, long duration, int userId, @ReasonCode int reasonCode, @Nullable String reason) throws RemoteException { @@ -2705,9 +2725,12 @@ public class DeviceIdleController extends SystemService "addPowerSaveTempWhitelistApp", null); final long token = Binder.clearCallingIdentity(); try { - addPowerSaveTempAllowlistAppInternal(callingUid, - packageName, duration, TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, - userId, true, reasonCode, reason); + @TempAllowListType int type = getTempAllowListType(reasonCode, + TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED); + if (type != TEMPORARY_ALLOW_LIST_TYPE_NONE) { + addPowerSaveTempAllowlistAppInternal(callingUid, + packageName, duration, type, userId, true, reasonCode, reason); + } } finally { Binder.restoreCallingIdentity(token); } @@ -2741,16 +2764,6 @@ public class DeviceIdleController extends SystemService void addPowerSaveTempAllowlistAppInternal(int callingUid, String packageName, long durationMs, @TempAllowListType int tempAllowListType, int userId, boolean sync, @ReasonCode int reasonCode, @Nullable String reason) { - synchronized (this) { - int callingAppId = UserHandle.getAppId(callingUid); - if (callingAppId >= Process.FIRST_APPLICATION_UID) { - if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) { - throw new SecurityException( - "Calling app " + UserHandle.formatUid(callingUid) - + " is not on whitelist"); - } - } - } try { int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId); addPowerSaveTempWhitelistAppDirectInternal(callingUid, uid, durationMs, diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 605340061994..ab610e4e71c6 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -583,4 +583,9 @@ public abstract class ActivityManagerInternal { * Is the FGS started from an uid temporarily allowed to have while-in-use permission? */ public abstract boolean isTempAllowlistedForFgsWhileInUse(int uid); + + /** + * Return the temp allowlist type when server push messaging is over the quota. + */ + public abstract @TempAllowListType int getPushMessagingOverQuotaBehavior(); } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index bf574521b895..d8eccef8488e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -16,6 +16,9 @@ package com.android.server.am; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE; + import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK; import android.app.ActivityThread; @@ -27,6 +30,7 @@ import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.Message; +import android.os.PowerExemptionManager; import android.provider.DeviceConfig; import android.provider.DeviceConfig.OnPropertiesChangedListener; import android.provider.DeviceConfig.Properties; @@ -139,6 +143,11 @@ final class ActivityManagerConstants extends ContentObserver { private static final long DEFAULT_FG_TO_BG_FGS_GRACE_DURATION = 5 * 1000; private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000; private static final float DEFAULT_FGS_ATOM_SAMPLE_RATE = 1; // 100 % + /** + * Same as {@link TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED} + */ + private static final int + DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR = 1; // Flag stored in the DeviceConfig API. /** @@ -210,6 +219,13 @@ final class ActivityManagerConstants extends ContentObserver { private static final String KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME = "deferred_fgs_notification_exclusion_time"; + /** + * Default value for mPushMessagingOverQuotaBehavior if not explicitly set in + * Settings.Global. + */ + private static final String KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR = + "push_messaging_over_quota_behavior"; + // Maximum number of cached processes we will allow. public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES; @@ -413,6 +429,13 @@ final class ActivityManagerConstants extends ContentObserver { // before another FGS notifiction from that app can be deferred. volatile long mFgsNotificationDeferralExclusionTime = 2 * 60 * 1000L; + /** + * When server pushing message is over the quote, select one of the temp allow list type as + * defined in {@link PowerExemptionManager.TempAllowListType} + */ + volatile @PowerExemptionManager.TempAllowListType int mPushMessagingOverQuotaBehavior = + DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR; + /* * At boot time, broadcast receiver ACTION_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED and * ACTION_PRE_BOOT_COMPLETED are temp allowlisted to start FGS for a duration of time in @@ -605,6 +628,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_DEFERRED_FGS_NOTIFICATION_EXCLUSION_TIME: updateFgsNotificationDeferralExclusionTime(); break; + case KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR: + updatePushMessagingOverQuotaBehavior(); + break; case KEY_OOMADJ_UPDATE_POLICY: updateOomAdjUpdatePolicy(); break; @@ -909,6 +935,19 @@ final class ActivityManagerConstants extends ContentObserver { /*default value*/ 2 * 60 * 1000L); } + private void updatePushMessagingOverQuotaBehavior() { + mPushMessagingOverQuotaBehavior = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR, + DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR); + if (mPushMessagingOverQuotaBehavior < TEMPORARY_ALLOW_LIST_TYPE_NONE + || mPushMessagingOverQuotaBehavior + > TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED) { + mPushMessagingOverQuotaBehavior = + DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR; + } + } + private void updateOomAdjUpdatePolicy() { OOMADJ_UPDATE_QUICK = DeviceConfig.getInt( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, @@ -1166,6 +1205,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.print("="); pw.println(mFgsStartRestrictionCheckCallerTargetSdk); pw.print(" "); pw.print(KEY_FGS_ATOM_SAMPLE_RATE); pw.print("="); pw.println(mDefaultFgsAtomSampleRate); + pw.print(" "); pw.print(KEY_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR); + pw.print("="); pw.println(mPushMessagingOverQuotaBehavior); pw.println(); if (mOverrideMaxCachedProcesses >= 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 00b13b1bb6b0..9aedf1504df5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -51,7 +51,8 @@ import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL; import static android.os.IServiceManager.DUMP_FLAG_PROTO; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED; -import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE; import static android.os.Process.BLUETOOTH_UID; import static android.os.Process.FIRST_APPLICATION_UID; import static android.os.Process.INVALID_UID; @@ -14603,15 +14604,20 @@ public class ActivityManagerService extends IActivityManager.Stub */ @GuardedBy("this") void tempAllowlistUidLocked(int targetUid, long duration, @ReasonCode int reasonCode, - String reason, int type, int callingUid) { + String reason, @TempAllowListType int type, int callingUid) { synchronized (mProcLock) { + // The temp allowlist type could change according to the reasonCode. + type = mLocalDeviceIdleController.getTempAllowListType(reasonCode, type); + if (type == TEMPORARY_ALLOW_LIST_TYPE_NONE) { + return; + } mPendingTempAllowlist.put(targetUid, new PendingTempAllowlist(targetUid, duration, reasonCode, reason, type, callingUid)); setUidTempAllowlistStateLSP(targetUid, true); mUiHandler.obtainMessage(PUSH_TEMP_ALLOWLIST_UI_MSG).sendToTarget(); - if (type == TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { + if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { mFgsStartTempAllowList.add(targetUid, duration, new FgsTempAllowListItem(duration, reasonCode, reason, callingUid)); } @@ -15285,7 +15291,7 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (mProcLock) { mDeviceIdleTempAllowlist = appids; if (adding) { - if (type == TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { + if (type == TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { mFgsStartTempAllowList.add(changingUid, durationMs, new FgsTempAllowListItem(durationMs, reasonCode, reason, callingUid)); @@ -16152,6 +16158,13 @@ public class ActivityManagerService extends IActivityManager.Stub return mServices.canAllowWhileInUsePermissionInFgsLocked(pid, uid, packageName); } } + + @Override + public @TempAllowListType int getPushMessagingOverQuotaBehavior() { + synchronized (ActivityManagerService.this) { + return mConstants.mPushMessagingOverQuotaBehavior; + } + } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) { |