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

Commit 2c27e508 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Add "Background FGS start" capability and change SHORT FGS procstate

- SHORT_SERVICE FGS now uses the FGS procstates, just like other FGS types.
  This ensures SHORT_FGS will get all "special powers" of FGS -- e.g.
  ability to hold on to wake locks during doze, ability to defeat
  Data Saver.

- However, we still shouldn't allow BFSL ("background foreground service
  lauch"), so add a new "BFSL" capability.

- Unfortunately, some of the CTS tests would break if we just add
  new capability, so the new capability is "hidden" from `am watch-uids`
  by default.

- PROCESS_CAPABILITY_ALL is also removed from @TestApi, to avoid exposing
  the new capability to CTS.

Test: atest FrameworksServicesTests:OomAdjusterTests MockingOomAdjusterTests
Test: atest CtsShortFgsTestCases \
    ActivityManagerFgsBgStartTest \
    ActivityManagerApi29Test \
    tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java \
    /android/master2/cts/tests/app/src/android/app/cts/ActivityManagerTest.java \
    ExpeditedJobTest

(ExpeditedJobTest#testTopEJUnlimited was already failing)

Bug: 257270313
Change-Id: I838da70030811ed719cba9c147c5b42d2e8601f3
parent 50fce419
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -144,8 +144,6 @@ package android.app {
    method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
    method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle();
    field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
    field public static final int PROCESS_CAPABILITY_ALL = 15; // 0xf
    field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1
    field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
    field public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
    field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
+34 −17
Original line number Diff line number Diff line
@@ -630,6 +630,8 @@ public class ActivityManager {
            PROCESS_CAPABILITY_FOREGROUND_LOCATION,
            PROCESS_CAPABILITY_FOREGROUND_CAMERA,
            PROCESS_CAPABILITY_FOREGROUND_MICROPHONE,
            PROCESS_CAPABILITY_NETWORK,
            PROCESS_CAPABILITY_BFSL,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ProcessCapability {}
@@ -654,20 +656,36 @@ public class ActivityManager {
    @TestApi
    public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;

    /** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
    @TestApi
    public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
            | PROCESS_CAPABILITY_FOREGROUND_CAMERA
            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
            | PROCESS_CAPABILITY_NETWORK;
    /**
     * All explicit capabilities. These are capabilities that need to be specified from manifest
     * file.
     * Flag used to indicate whether an app is allowed to start a foreground service from the
     * background, decided by the procstates. ("BFSL" == "background foreground service launch")
     *
     * - BFSL has a number of exemptions -- e.g. when an app is power-allowlisted, including
     *   temp-allowlist -- but this capability is *not* used to represent such exemptions.
     *   This is set only based on the procstate and the foreground service type.
     * - Basically, procstates <= BFGS (i.e. BFGS, FGS, BTOP, TOP, ...) are BFSL-allowed,
     *   and that's how things worked on Android S/T.
     *   However, Android U added a "SHORT_SERVICE" FGS type, which gets the FGS procstate
     *   *but* can't start another FGS. So now we use this flag to decide whether FGS/BFGS
     *   procstates are BFSL-allowed. (higher procstates, such as BTOP, will still always be
     *   BFSL-allowed.)
     *   We propagate this flag across via service bindings and provider references.
     *
     * @hide
     */
    @TestApi
    public static final int PROCESS_CAPABILITY_ALL_EXPLICIT =
            PROCESS_CAPABILITY_FOREGROUND_LOCATION;
    public static final int PROCESS_CAPABILITY_BFSL = 1 << 4;

    /**
     * @hide all capabilities, the ORing of all flags in {@link ProcessCapability}.
     *
     * Don't expose it as TestApi -- we may add new capabilities any time, which could
     * break CTS tests if they relied on it.
     */
    public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
            | PROCESS_CAPABILITY_FOREGROUND_CAMERA
            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
            | PROCESS_CAPABILITY_NETWORK
            | PROCESS_CAPABILITY_BFSL;

    /**
     * All implicit capabilities. There are capabilities that process automatically have.
@@ -686,6 +704,7 @@ public class ActivityManager {
        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
        pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
        pw.print((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
        pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
    }

    /** @hide */
@@ -694,6 +713,7 @@ public class ActivityManager {
        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0 ? 'C' : '-');
        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
        sb.append((caps & PROCESS_CAPABILITY_NETWORK) != 0 ? 'N' : '-');
        sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
    }

    /**
@@ -702,13 +722,10 @@ public class ActivityManager {
     */
    public static void printCapabilitiesFull(PrintWriter pw, @ProcessCapability int caps) {
        printCapabilitiesSummary(pw, caps);
        final int remain = caps & ~(PROCESS_CAPABILITY_FOREGROUND_LOCATION
                | PROCESS_CAPABILITY_FOREGROUND_CAMERA
                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
                | PROCESS_CAPABILITY_NETWORK);
        final int remain = caps & ~PROCESS_CAPABILITY_ALL;
        if (remain != 0) {
            pw.print('+');
            pw.print(remain);
            pw.print("+0x");
            pw.print(Integer.toHexString(remain));
        }
    }

+20 −2
Original line number Diff line number Diff line
@@ -20,6 +20,9 @@ import static android.Manifest.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND;
import static android.Manifest.permission.REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND;
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -7395,6 +7398,12 @@ public final class ActiveServices {
        int ret = shouldAllowFgsStartForegroundNoBindingCheckLocked(allowWhileInUse, callingPid,
                callingUid, callingPackage, r, backgroundStartPrivileges);

        // If an app (App 1) is bound by another app (App 2) that could start an FGS, then App 1
        // is also allowed to start an FGS. We check all the binding
        // in canBindingClientStartFgsLocked() to do this check.
        // (Note we won't check more than 1 level of binding.)
        // [bookmark: 61867f60-007c-408c-a2c4-e19e96056135] -- this code is referred to from
        // OomAdjuster.
        String bindFromPackage = null;
        if (ret == REASON_DENIED) {
            bindFromPackage = canBindingClientStartFgsLocked(callingUid);
@@ -7410,10 +7419,13 @@ public final class ActiveServices {
                    .getTargetSdkVersion(callingPackage);
        } catch (PackageManager.NameNotFoundException ignored) {
        }
        final boolean uidBfsl = (mAm.getUidProcessCapabilityLocked(callingUid)
                & PROCESS_CAPABILITY_BFSL) != 0;
        final String debugInfo =
                "[callingPackage: " + callingPackage
                        + "; callingUid: " + callingUid
                        + "; uidState: " + ProcessList.makeProcStateString(uidState)
                        + "; uidBFSL: " + (uidBfsl ? "[BFSL]" : "n/a")
                        + "; intent: " + intent
                        + "; code:" + reasonCodeToString(ret)
                        + "; tempAllowListReason:<"
@@ -7452,11 +7464,15 @@ public final class ActiveServices {
        }

        if (ret == REASON_DENIED) {
            final boolean uidBfsl =
                    (mAm.getUidProcessCapabilityLocked(callingUid) & PROCESS_CAPABILITY_BFSL) != 0;
            final Integer allowedType = mAm.mProcessList.searchEachLruProcessesLOSP(false, app -> {
                if (app.uid == callingUid) {
                    final ProcessStateRecord state = app.mState;
                    if (state.isAllowedStartFgs()) { // Procstate <= BFGS?
                        return getReasonCodeFromProcState(state.getCurProcState());
                    final int procstate = state.getCurProcState();
                    if ((procstate <= PROCESS_STATE_BOUND_TOP)
                            || (uidBfsl && (procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE))) {
                        return getReasonCodeFromProcState(procstate);
                    } else {
                        final ActiveInstrumentation instr = app.getActiveInstrumentation();
                        if (instr != null
@@ -7684,6 +7700,8 @@ public final class ActiveServices {
        }
        final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null
                ? r.mRecentCallerApplicationInfo.targetSdkVersion : 0;

        // TODO(short-service): Log BFSL too.
        FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                r.appInfo.uid,
                r.shortInstanceName,
+5 −0
Original line number Diff line number Diff line
@@ -5874,6 +5874,11 @@ public class ActivityManagerService extends IActivityManager.Stub
        return mProcessList.getUidProcStateLOSP(uid);
    }
    @GuardedBy("this")
    int getUidProcessCapabilityLocked(int uid) {
        return mProcessList.getUidProcessCapabilityLOSP(uid);
    }
    // =========================================================
    // PROCESS INFO
    // =========================================================
+27 −4
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.server.am;

import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
@@ -1823,16 +1827,20 @@ final class ActivityManagerShellCommand extends ShellCommand {
        final InputStream mInput;
        final int mUid;

        final int mMask;

        static final int STATE_NORMAL = 0;

        int mState;

        MyUidObserver(ActivityManagerService service, PrintWriter pw, InputStream input, int uid) {
        MyUidObserver(ActivityManagerService service, PrintWriter pw, InputStream input, int uid,
                int mask) {
            mInterface = service;
            mInternal = service;
            mPw = pw;
            mInput = input;
            mUid = uid;
            mMask = mask;
        }

        @Override
@@ -1847,7 +1855,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
                    mPw.print(" seq ");
                    mPw.print(procStateSeq);
                    mPw.print(" capability ");
                    mPw.println(capability);
                    mPw.println(capability & mMask);
                    mPw.flush();
                } finally {
                    StrictMode.setThreadPolicy(oldPolicy);
@@ -1998,9 +2006,19 @@ final class ActivityManagerShellCommand extends ShellCommand {
    int runWatchUids(PrintWriter pw) throws RemoteException {
        String opt;
        int uid = -1;

        // Because a lot of CTS won't ignore capabilities newly added, we report
        // only the following capabilities -- the ones we had on Android T -- by default.
        int mask = PROCESS_CAPABILITY_FOREGROUND_LOCATION
                | PROCESS_CAPABILITY_FOREGROUND_CAMERA
                | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
                | PROCESS_CAPABILITY_NETWORK;

        while ((opt=getNextOption()) != null) {
            if (opt.equals("--oom")) {
                uid = Integer.parseInt(getNextArgRequired());
            } else if (opt.equals("--mask")) {
                mask = Integer.parseInt(getNextArgRequired());
            } else {
                getErrPrintWriter().println("Error: Unknown option: " + opt);
                return -1;
@@ -2008,7 +2026,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
            }
        }

        MyUidObserver controller = new MyUidObserver(mInternal, pw, getRawInputStream(), uid);
        MyUidObserver controller = new MyUidObserver(mInternal, pw, getRawInputStream(), uid, mask);
        controller.run();
        return 0;
    }
@@ -4079,9 +4097,14 @@ final class ActivityManagerShellCommand extends ShellCommand {
            pw.println("      -p: only show events related to a specific process / package");
            pw.println("      -s: simple mode, only show a summary line for each event");
            pw.println("      -c: assume the input is always [c]ontinue");
            pw.println("  watch-uids [--oom <uid>]");
            pw.println("  watch-uids [--oom <uid>] [--mask <capabilities integer>]");
            pw.println("      Start watching for and reporting uid state changes.");
            pw.println("      --oom: specify a uid for which to report detailed change messages.");
            pw.println("      --mask: Specify PROCESS_CAPABILITY_XXX mask to report. ");
            pw.println("              By default, it only reports FOREGROUND_LOCATION (1)");
            pw.println("              FOREGROUND_CAMERA (2), FOREGROUND_MICROPHONE (4)");
            pw.println("              and NETWORK (8). New capabilities added on or after");
            pw.println("              Android UDC will not be reported by default.");
            pw.println("  hang [--allow-restart]");
            pw.println("      Hang the system.");
            pw.println("      --allow-restart: allow watchdog to perform normal system restart");
Loading