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

Commit cc8af26b authored by Hui Yu's avatar Hui Yu
Browse files

Create multiple temp allowlist types.

1. In BroadcastOptions, create multiple temp allowlist types,
TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED is the default which
allows both DeviceIdleController temp allowlist behavior and FGS start
 from background.
TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED
 only allows DeviceIdleController temp allowlist behavior.
2. Create FgsStartTempAllowList class to contain the UIDs that is
temporarily allowed to start FGS from background.

Bug: 171305836
Test: atest cts/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java#testTempAllowListType
Change-Id: I32a14d675550cd262976bb8e16a48a070387d318
parent 29bca688
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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 {
+57 −0
Original line number Diff line number Diff line
@@ -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)
@@ -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;
@@ -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}.
     */
@@ -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;
@@ -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);
@@ -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;
    }

    /**
@@ -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
@@ -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);
        }
+6 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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)) {
@@ -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;
            }
        }
+18 −2
Original line number Diff line number Diff line
@@ -1096,6 +1096,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
     */
@@ -5513,6 +5518,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
@@ -15327,17 +15338,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() {
+8 −5
Original line number Diff line number Diff line
@@ -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;
        }
@@ -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);
    }

    /**
@@ -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;
@@ -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