Loading core/api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -607,7 +607,10 @@ package android.app { method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean); method public void setDontSendToRestrictedApps(boolean); method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long); method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(int, long); method public android.os.Bundle toBundle(); field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0 field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1 } public class DownloadManager { Loading core/java/android/app/BroadcastOptions.java +57 −0 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package android.app; import android.annotation.IntDef; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.os.Build; import android.os.Bundle; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Helper class for building an options Bundle that can be used with * {@link android.content.Context#sendBroadcast(android.content.Intent) Loading @@ -30,6 +34,7 @@ import android.os.Bundle; @SystemApi public class BroadcastOptions { private long mTemporaryAppWhitelistDuration; private @TempAllowListType int mTemporaryAppWhitelistType; private int mMinManifestReceiverApiLevel = 0; private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT; private boolean mDontSendToRestrictedApps = false; Loading @@ -42,6 +47,9 @@ public class BroadcastOptions { static final String KEY_TEMPORARY_APP_WHITELIST_DURATION = "android:broadcast.temporaryAppWhitelistDuration"; static final String KEY_TEMPORARY_APP_WHITELIST_TYPE = "android:broadcast.temporaryAppWhitelistType"; /** * Corresponds to {@link #setMinManifestReceiverApiLevel}. */ Loading @@ -66,6 +74,27 @@ public class BroadcastOptions { static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS = "android:broadcast.allowBackgroundActivityStarts"; /** * Allow the temp allowlist behavior, plus allow foreground service start from background. */ public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; /** * Only allow the temp allowlist behavior, not allow foreground service start from * background. */ public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; /** * The list of temp allowlist types. * @hide */ @IntDef(flag = true, prefix = { "TEMPORARY_WHITELIST_TYPE_" }, value = { TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED, TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, }) @Retention(RetentionPolicy.SOURCE) public @interface TempAllowListType {} public static BroadcastOptions makeBasic() { BroadcastOptions opts = new BroadcastOptions(); return opts; Loading @@ -77,6 +106,7 @@ public class BroadcastOptions { /** @hide */ public BroadcastOptions(Bundle opts) { mTemporaryAppWhitelistDuration = opts.getLong(KEY_TEMPORARY_APP_WHITELIST_DURATION); mTemporaryAppWhitelistType = opts.getInt(KEY_TEMPORARY_APP_WHITELIST_TYPE); mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0); mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, Build.VERSION_CODES.CUR_DEVELOPMENT); Loading @@ -95,6 +125,22 @@ public class BroadcastOptions { android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long duration) { mTemporaryAppWhitelistDuration = duration; mTemporaryAppWhitelistType = TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED; } /** * Set a duration for which the system should temporary place an application on the * power allowlist when this broadcast is being delivered to it, specify the temp allowlist * type. * @param type one of {@link TempAllowListType} * @param duration the duration in milliseconds; 0 means to not place on allowlist. */ @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(@TempAllowListType int type, long duration) { mTemporaryAppWhitelistDuration = duration; mTemporaryAppWhitelistType = type; } /** Loading @@ -105,6 +151,14 @@ public class BroadcastOptions { return mTemporaryAppWhitelistDuration; } /** * Return {@link #mTemporaryAppWhitelistType}. * @hide */ public @TempAllowListType int getTemporaryAppWhitelistType() { return mTemporaryAppWhitelistType; } /** * Set the minimum target API level of receivers of the broadcast. If an application * is targeting an API level less than this, the broadcast will not be delivered to Loading Loading @@ -190,6 +244,9 @@ public class BroadcastOptions { if (mTemporaryAppWhitelistDuration > 0) { b.putLong(KEY_TEMPORARY_APP_WHITELIST_DURATION, mTemporaryAppWhitelistDuration); } if (mTemporaryAppWhitelistType != 0) { b.putInt(KEY_TEMPORARY_APP_WHITELIST_TYPE, mTemporaryAppWhitelistType); } if (mMinManifestReceiverApiLevel != 0) { b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel); } Loading services/core/java/com/android/server/am/ActiveServices.java +6 −3 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.ApplicationExitInfo; import android.app.BroadcastOptions; import android.app.IApplicationThread; import android.app.IServiceConnection; import android.app.Notification; Loading Loading @@ -3201,7 +3202,8 @@ public final class ActiveServices { + " for fg-service launch"); } mAm.tempWhitelistUidLocked(r.appInfo.uid, SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch"); SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch", BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED); } if (!mPendingServices.contains(r)) { Loading Loading @@ -5284,8 +5286,9 @@ public final class ActiveServices { if (ret == FGS_FEATURE_DENIED) { if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { // uid is on DeviceIdleController's allowlist. && mAm.isWhitelistedForFgsStartLocked(r.appInfo.uid)) { // uid is on DeviceIdleController's user/system allowlist // or AMS's FgsStartTempAllowList. ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST; } } Loading services/core/java/com/android/server/am/ActivityManagerService.java +18 −2 Original line number Diff line number Diff line Loading @@ -1093,6 +1093,11 @@ public class ActivityManagerService extends IActivityManager.Stub final PendingTempWhitelists mPendingTempWhitelist = new PendingTempWhitelists(this); /** * The temp-allowlist that is allowed to start FGS from background. */ final FgsStartTempAllowList mFgsStartTempAllowList = new FgsStartTempAllowList(); /** * Information about and control over application operations */ Loading Loading @@ -5510,6 +5515,12 @@ public class ActivityManagerService extends IActivityManager.Stub || mPendingTempWhitelist.indexOfKey(uid) >= 0; } boolean isWhitelistedForFgsStartLocked(int uid) { final int appId = UserHandle.getAppId(uid); return Arrays.binarySearch(mDeviceIdleExceptIdleWhitelist, appId) >= 0 || mFgsStartTempAllowList.isAllowed(uid); } /** * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on * the whitelist Loading Loading @@ -15324,17 +15335,22 @@ public class ActivityManagerService extends IActivityManager.Stub } } tempWhitelistUidLocked(targetUid, duration, tag); tempWhitelistUidLocked(targetUid, duration, tag, BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED); } /** * Whitelists {@code targetUid} to temporarily bypass Power Save mode. */ @GuardedBy("this") void tempWhitelistUidLocked(int targetUid, long duration, String tag) { void tempWhitelistUidLocked(int targetUid, long duration, String tag, int type) { mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag)); setUidTempWhitelistStateLocked(targetUid, true); mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget(); if (type == BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { mFgsStartTempAllowList.add(targetUid, duration); } } void pushTempWhitelist() { services/core/java/com/android/server/am/BroadcastQueue.java +8 −5 Original line number Diff line number Diff line Loading @@ -896,7 +896,8 @@ public final class BroadcastQueue { return false; } final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r) { final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r, @BroadcastOptions.TempAllowListType int type) { if (duration > Integer.MAX_VALUE) { duration = Integer.MAX_VALUE; } Loading @@ -919,9 +920,9 @@ public final class BroadcastQueue { } if (DEBUG_BROADCAST) { Slog.v(TAG, "Broadcast temp whitelist uid=" + uid + " duration=" + duration + " : " + b.toString()); + " type=" + type + " : " + b.toString()); } mService.tempWhitelistUidLocked(uid, duration, b.toString()); mService.tempWhitelistUidLocked(uid, duration, b.toString(), type); } /** Loading Loading @@ -1318,7 +1319,8 @@ public final class BroadcastQueue { } if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { scheduleTempWhitelistLocked(filter.owningUid, brOptions.getTemporaryAppWhitelistDuration(), r); brOptions.getTemporaryAppWhitelistDuration(), r, brOptions.getTemporaryAppWhitelistType()); } } return; Loading Loading @@ -1610,7 +1612,8 @@ public final class BroadcastQueue { (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0); if (isActivityCapable) { scheduleTempWhitelistLocked(receiverUid, brOptions.getTemporaryAppWhitelistDuration(), r); brOptions.getTemporaryAppWhitelistDuration(), r, brOptions.getTemporaryAppWhitelistType()); } // Broadcast is being executed, its package can't be stopped. Loading Loading
core/api/system-current.txt +3 −0 Original line number Diff line number Diff line Loading @@ -607,7 +607,10 @@ package android.app { method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean); method public void setDontSendToRestrictedApps(boolean); method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long); method @RequiresPermission(anyOf={android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(int, long); method public android.os.Bundle toBundle(); field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; // 0x0 field public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; // 0x1 } public class DownloadManager { Loading
core/java/android/app/BroadcastOptions.java +57 −0 Original line number Diff line number Diff line Loading @@ -16,11 +16,15 @@ package android.app; import android.annotation.IntDef; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.os.Build; import android.os.Bundle; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Helper class for building an options Bundle that can be used with * {@link android.content.Context#sendBroadcast(android.content.Intent) Loading @@ -30,6 +34,7 @@ import android.os.Bundle; @SystemApi public class BroadcastOptions { private long mTemporaryAppWhitelistDuration; private @TempAllowListType int mTemporaryAppWhitelistType; private int mMinManifestReceiverApiLevel = 0; private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT; private boolean mDontSendToRestrictedApps = false; Loading @@ -42,6 +47,9 @@ public class BroadcastOptions { static final String KEY_TEMPORARY_APP_WHITELIST_DURATION = "android:broadcast.temporaryAppWhitelistDuration"; static final String KEY_TEMPORARY_APP_WHITELIST_TYPE = "android:broadcast.temporaryAppWhitelistType"; /** * Corresponds to {@link #setMinManifestReceiverApiLevel}. */ Loading @@ -66,6 +74,27 @@ public class BroadcastOptions { static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS = "android:broadcast.allowBackgroundActivityStarts"; /** * Allow the temp allowlist behavior, plus allow foreground service start from background. */ public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED = 0; /** * Only allow the temp allowlist behavior, not allow foreground service start from * background. */ public static final int TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED = 1; /** * The list of temp allowlist types. * @hide */ @IntDef(flag = true, prefix = { "TEMPORARY_WHITELIST_TYPE_" }, value = { TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED, TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED, }) @Retention(RetentionPolicy.SOURCE) public @interface TempAllowListType {} public static BroadcastOptions makeBasic() { BroadcastOptions opts = new BroadcastOptions(); return opts; Loading @@ -77,6 +106,7 @@ public class BroadcastOptions { /** @hide */ public BroadcastOptions(Bundle opts) { mTemporaryAppWhitelistDuration = opts.getLong(KEY_TEMPORARY_APP_WHITELIST_DURATION); mTemporaryAppWhitelistType = opts.getInt(KEY_TEMPORARY_APP_WHITELIST_TYPE); mMinManifestReceiverApiLevel = opts.getInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, 0); mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL, Build.VERSION_CODES.CUR_DEVELOPMENT); Loading @@ -95,6 +125,22 @@ public class BroadcastOptions { android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(long duration) { mTemporaryAppWhitelistDuration = duration; mTemporaryAppWhitelistType = TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED; } /** * Set a duration for which the system should temporary place an application on the * power allowlist when this broadcast is being delivered to it, specify the temp allowlist * type. * @param type one of {@link TempAllowListType} * @param duration the duration in milliseconds; 0 means to not place on allowlist. */ @RequiresPermission(anyOf = {android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST, android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND}) public void setTemporaryAppWhitelistDuration(@TempAllowListType int type, long duration) { mTemporaryAppWhitelistDuration = duration; mTemporaryAppWhitelistType = type; } /** Loading @@ -105,6 +151,14 @@ public class BroadcastOptions { return mTemporaryAppWhitelistDuration; } /** * Return {@link #mTemporaryAppWhitelistType}. * @hide */ public @TempAllowListType int getTemporaryAppWhitelistType() { return mTemporaryAppWhitelistType; } /** * Set the minimum target API level of receivers of the broadcast. If an application * is targeting an API level less than this, the broadcast will not be delivered to Loading Loading @@ -190,6 +244,9 @@ public class BroadcastOptions { if (mTemporaryAppWhitelistDuration > 0) { b.putLong(KEY_TEMPORARY_APP_WHITELIST_DURATION, mTemporaryAppWhitelistDuration); } if (mTemporaryAppWhitelistType != 0) { b.putInt(KEY_TEMPORARY_APP_WHITELIST_TYPE, mTemporaryAppWhitelistType); } if (mMinManifestReceiverApiLevel != 0) { b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel); } Loading
services/core/java/com/android/server/am/ActiveServices.java +6 −3 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.ApplicationExitInfo; import android.app.BroadcastOptions; import android.app.IApplicationThread; import android.app.IServiceConnection; import android.app.Notification; Loading Loading @@ -3201,7 +3202,8 @@ public final class ActiveServices { + " for fg-service launch"); } mAm.tempWhitelistUidLocked(r.appInfo.uid, SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch"); SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch", BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED); } if (!mPendingServices.contains(r)) { Loading Loading @@ -5284,8 +5286,9 @@ public final class ActiveServices { if (ret == FGS_FEATURE_DENIED) { if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { // uid is on DeviceIdleController's allowlist. && mAm.isWhitelistedForFgsStartLocked(r.appInfo.uid)) { // uid is on DeviceIdleController's user/system allowlist // or AMS's FgsStartTempAllowList. ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST; } } Loading
services/core/java/com/android/server/am/ActivityManagerService.java +18 −2 Original line number Diff line number Diff line Loading @@ -1093,6 +1093,11 @@ public class ActivityManagerService extends IActivityManager.Stub final PendingTempWhitelists mPendingTempWhitelist = new PendingTempWhitelists(this); /** * The temp-allowlist that is allowed to start FGS from background. */ final FgsStartTempAllowList mFgsStartTempAllowList = new FgsStartTempAllowList(); /** * Information about and control over application operations */ Loading Loading @@ -5510,6 +5515,12 @@ public class ActivityManagerService extends IActivityManager.Stub || mPendingTempWhitelist.indexOfKey(uid) >= 0; } boolean isWhitelistedForFgsStartLocked(int uid) { final int appId = UserHandle.getAppId(uid); return Arrays.binarySearch(mDeviceIdleExceptIdleWhitelist, appId) >= 0 || mFgsStartTempAllowList.isAllowed(uid); } /** * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on * the whitelist Loading Loading @@ -15324,17 +15335,22 @@ public class ActivityManagerService extends IActivityManager.Stub } } tempWhitelistUidLocked(targetUid, duration, tag); tempWhitelistUidLocked(targetUid, duration, tag, BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED); } /** * Whitelists {@code targetUid} to temporarily bypass Power Save mode. */ @GuardedBy("this") void tempWhitelistUidLocked(int targetUid, long duration, String tag) { void tempWhitelistUidLocked(int targetUid, long duration, String tag, int type) { mPendingTempWhitelist.put(targetUid, new PendingTempWhitelist(targetUid, duration, tag)); setUidTempWhitelistStateLocked(targetUid, true); mUiHandler.obtainMessage(PUSH_TEMP_WHITELIST_UI_MSG).sendToTarget(); if (type == BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED) { mFgsStartTempAllowList.add(targetUid, duration); } } void pushTempWhitelist() {
services/core/java/com/android/server/am/BroadcastQueue.java +8 −5 Original line number Diff line number Diff line Loading @@ -896,7 +896,8 @@ public final class BroadcastQueue { return false; } final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r) { final void scheduleTempWhitelistLocked(int uid, long duration, BroadcastRecord r, @BroadcastOptions.TempAllowListType int type) { if (duration > Integer.MAX_VALUE) { duration = Integer.MAX_VALUE; } Loading @@ -919,9 +920,9 @@ public final class BroadcastQueue { } if (DEBUG_BROADCAST) { Slog.v(TAG, "Broadcast temp whitelist uid=" + uid + " duration=" + duration + " : " + b.toString()); + " type=" + type + " : " + b.toString()); } mService.tempWhitelistUidLocked(uid, duration, b.toString()); mService.tempWhitelistUidLocked(uid, duration, b.toString(), type); } /** Loading Loading @@ -1318,7 +1319,8 @@ public final class BroadcastQueue { } if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { scheduleTempWhitelistLocked(filter.owningUid, brOptions.getTemporaryAppWhitelistDuration(), r); brOptions.getTemporaryAppWhitelistDuration(), r, brOptions.getTemporaryAppWhitelistType()); } } return; Loading Loading @@ -1610,7 +1612,8 @@ public final class BroadcastQueue { (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0); if (isActivityCapable) { scheduleTempWhitelistLocked(receiverUid, brOptions.getTemporaryAppWhitelistDuration(), r); brOptions.getTemporaryAppWhitelistDuration(), r, brOptions.getTemporaryAppWhitelistType()); } // Broadcast is being executed, its package can't be stopped. Loading