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

Commit df0a9c7f authored by Kweku Adams's avatar Kweku Adams
Browse files

Allow UI jobs to run during data saver.

Since user-initiated jobs are initiated by the user and visible to the
user, similar to FGS, we allow them to run during data saver. We also
make sure not to run non-UI jobs if they would otherwise not run due to
Data Saver.

Bug: 261999509
Test: atest CtsAppTestCases:ActivityManagerFgsBgStartTest
Test: atest CtsAppTestCases:ActivityManagerProcessStateTest
Test: atest CtsAppTestCases:ActivityManagerTest
Test: atest CtsJobSchedulerTestCases:ConnectivityConstraintTest
Test: atest CtsJobSchedulerTestCases:ExpeditedJobTest
Test: atest CtsJobSchedulerTestCases:JobThrottlingTest
Test: atest CtsJobSchedulerTestCases:UserInitiatedJobTest
Test: atest FrameworksMockingServicesTests:ConnectivityControllerTest
Test: atest FrameworksServicesTests:ActivityManagerServiceTest
Change-Id: I80d5e5377a581c25220c06b7f762e9858da7769b
parent 1dfa76c9
Loading
Loading
Loading
Loading
+102 −6
Original line number Diff line number Diff line
@@ -365,6 +365,16 @@ public class JobSchedulerService extends com.android.server.SystemService
     * A mapping of which uids are currently in the foreground to their effective bias.
     */
    final SparseIntArray mUidBiasOverride = new SparseIntArray();
    /**
     * A cached mapping of uids to their current capabilities.
     */
    @GuardedBy("mLock")
    private final SparseIntArray mUidCapabilities = new SparseIntArray();
    /**
     * A cached mapping of uids to their proc states.
     */
    @GuardedBy("mLock")
    private final SparseIntArray mUidProcStates = new SparseIntArray();

    /**
     * Which uids are currently performing backups, so we shouldn't allow their jobs to run.
@@ -1135,6 +1145,14 @@ public class JobSchedulerService extends com.android.server.SystemService
                    mDebuggableApps.remove(pkgName);
                    mConcurrencyManager.onAppRemovedLocked(pkgName, pkgUid);
                }
            } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                    synchronized (mLock) {
                        mUidBiasOverride.delete(pkgUid);
                        mUidCapabilities.delete(pkgUid);
                        mUidProcStates.delete(pkgUid);
                    }
                }
            } else if (Intent.ACTION_USER_ADDED.equals(action)) {
                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                synchronized (mLock) {
@@ -1205,7 +1223,11 @@ public class JobSchedulerService extends com.android.server.SystemService
    final private IUidObserver mUidObserver = new IUidObserver.Stub() {
        @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
                int capability) {
            mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
            final SomeArgs args = SomeArgs.obtain();
            args.argi1 = uid;
            args.argi2 = procState;
            args.argi3 = capability;
            mHandler.obtainMessage(MSG_UID_STATE_CHANGED, args).sendToTarget();
        }

        @Override public void onUidGone(int uid, boolean disabled) {
@@ -1947,8 +1969,14 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    }

    void updateUidState(int uid, int procState) {
    void updateUidState(int uid, int procState, int capabilities) {
        if (DEBUG) {
            Slog.d(TAG, "UID " + uid + " proc state changed to "
                    + ActivityManager.procStateToString(procState)
                    + " with capabilities=" + ActivityManager.getCapabilitiesSummary(capabilities));
        }
        synchronized (mLock) {
            mUidProcStates.put(uid, procState);
            final int prevBias = mUidBiasOverride.get(uid, JobInfo.BIAS_DEFAULT);
            if (procState == ActivityManager.PROCESS_STATE_TOP) {
                // Only use this if we are exactly the top app.  All others can live
@@ -1962,6 +1990,12 @@ public class JobSchedulerService extends com.android.server.SystemService
            } else {
                mUidBiasOverride.delete(uid);
            }
            if (capabilities == ActivityManager.PROCESS_CAPABILITY_NONE
                    || procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
                mUidCapabilities.delete(uid);
            } else {
                mUidCapabilities.put(uid, capabilities);
            }
            final int newBias = mUidBiasOverride.get(uid, JobInfo.BIAS_DEFAULT);
            if (prevBias != newBias) {
                if (DEBUG) {
@@ -1982,6 +2016,23 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    }

    /**
     * Return the current {@link ActivityManager#PROCESS_CAPABILITY_ALL capabilities}
     * of the given UID.
     */
    public int getUidCapabilities(int uid) {
        synchronized (mLock) {
            return mUidCapabilities.get(uid, ActivityManager.PROCESS_CAPABILITY_NONE);
        }
    }

    /** Return the current proc state of the given UID. */
    public int getUidProcState(int uid) {
        synchronized (mLock) {
            return mUidProcStates.get(uid, ActivityManager.PROCESS_STATE_UNKNOWN);
        }
    }

    @Override
    public void onDeviceIdleStateChanged(boolean deviceIdle) {
        synchronized (mLock) {
@@ -2245,6 +2296,9 @@ public class JobSchedulerService extends com.android.server.SystemService
            filter.addDataScheme("package");
            getContext().registerReceiverAsUser(
                    mBroadcastReceiver, UserHandle.ALL, filter, null, null);
            final IntentFilter uidFilter = new IntentFilter(Intent.ACTION_UID_REMOVED);
            getContext().registerReceiverAsUser(
                    mBroadcastReceiver, UserHandle.ALL, uidFilter, null, null);
            final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
            userFilter.addAction(Intent.ACTION_USER_ADDED);
            getContext().registerReceiverAsUser(
@@ -2776,15 +2830,19 @@ public class JobSchedulerService extends com.android.server.SystemService
                        break;

                    case MSG_UID_STATE_CHANGED: {
                        final int uid = message.arg1;
                        final int procState = message.arg2;
                        updateUidState(uid, procState);
                        final SomeArgs args = (SomeArgs) message.obj;
                        final int uid = args.argi1;
                        final int procState = args.argi2;
                        final int capabilities = args.argi3;
                        updateUidState(uid, procState, capabilities);
                        args.recycle();
                        break;
                    }
                    case MSG_UID_GONE: {
                        final int uid = message.arg1;
                        final boolean disabled = message.arg2 != 0;
                        updateUidState(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
                        updateUidState(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                                ActivityManager.PROCESS_CAPABILITY_NONE);
                        if (disabled) {
                            cancelJobsForUid(uid,
                                    /* includeSourceApp */ true,
@@ -4836,6 +4894,25 @@ public class JobSchedulerService extends com.android.server.SystemService
                pw.decreaseIndent();
            }

            boolean procStatePrinted = false;
            for (int i = 0; i < mUidProcStates.size(); i++) {
                int uid = mUidProcStates.keyAt(i);
                if (filterAppId == -1 || filterAppId == UserHandle.getAppId(uid)) {
                    if (!procStatePrinted) {
                        procStatePrinted = true;
                        pw.println();
                        pw.println("Uid proc states:");
                        pw.increaseIndent();
                    }
                    pw.print(UserHandle.formatUid(uid));
                    pw.print(": ");
                    pw.println(ActivityManager.procStateToString(mUidProcStates.valueAt(i)));
                }
            }
            if (procStatePrinted) {
                pw.decreaseIndent();
            }

            boolean overridePrinted = false;
            for (int i = 0; i < mUidBiasOverride.size(); i++) {
                int uid = mUidBiasOverride.keyAt(i);
@@ -4854,6 +4931,25 @@ public class JobSchedulerService extends com.android.server.SystemService
                pw.decreaseIndent();
            }

            boolean capabilitiesPrinted = false;
            for (int i = 0; i < mUidCapabilities.size(); i++) {
                int uid = mUidCapabilities.keyAt(i);
                if (filterAppId == -1 || filterAppId == UserHandle.getAppId(uid)) {
                    if (!capabilitiesPrinted) {
                        capabilitiesPrinted = true;
                        pw.println();
                        pw.println("Uid capabilities:");
                        pw.increaseIndent();
                    }
                    pw.print(UserHandle.formatUid(uid));
                    pw.print(": ");
                    pw.println(ActivityManager.getCapabilitiesSummary(mUidCapabilities.valueAt(i)));
                }
            }
            if (capabilitiesPrinted) {
                pw.decreaseIndent();
            }

            boolean uidMapPrinted = false;
            for (int i = 0; i < mUidToPackageCache.size(); ++i) {
                final int uid = mUidToPackageCache.keyAt(i);
+18 −14
Original line number Diff line number Diff line
@@ -390,23 +390,27 @@ public final class JobServiceContext implements ServiceConnection {
                    .setFlags(Intent.FLAG_FROM_BACKGROUND);
            boolean binding = false;
            try {
                final int bindFlags;
                final Context.BindServiceFlags bindFlags;
                if (job.shouldTreatAsUserInitiatedJob()) {
                    // TODO (191785864, 261999509): add an appropriate flag so user-initiated jobs
                    //    can bypass data saver
                    bindFlags = Context.BIND_AUTO_CREATE
                    bindFlags = Context.BindServiceFlags.of(
                            Context.BIND_AUTO_CREATE
                                    | Context.BIND_ALMOST_PERCEPTIBLE
                                    | Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS
                            | Context.BIND_NOT_APP_COMPONENT_USAGE;
                                    | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS
                                    | Context.BIND_NOT_APP_COMPONENT_USAGE);
                } else if (job.shouldTreatAsExpeditedJob()) {
                    bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
                    bindFlags = Context.BindServiceFlags.of(
                            Context.BIND_AUTO_CREATE
                                    | Context.BIND_NOT_FOREGROUND
                                    | Context.BIND_ALMOST_PERCEPTIBLE
                                    | Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS
                            | Context.BIND_NOT_APP_COMPONENT_USAGE;
                                    | Context.BIND_NOT_APP_COMPONENT_USAGE);
                } else {
                    bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
                    bindFlags = Context.BindServiceFlags.of(
                            Context.BIND_AUTO_CREATE
                                    | Context.BIND_NOT_FOREGROUND
                                    | Context.BIND_NOT_PERCEPTIBLE
                            | Context.BIND_NOT_APP_COMPONENT_USAGE;
                                    | Context.BIND_NOT_APP_COMPONENT_USAGE);
                }
                binding = mContext.bindServiceAsUser(intent, this, bindFlags,
                        UserHandle.of(job.getUserId()));
+154 −6
Original line number Diff line number Diff line
@@ -18,15 +18,18 @@ package com.android.server.job.controllers;

import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;

import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.job.JobInfo;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.INetworkPolicyListener;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
@@ -47,6 +50,7 @@ import android.util.Log;
import android.util.Pools;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

@@ -98,13 +102,12 @@ public final class ConnectivityController extends RestrictingController implemen
            ~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY
                    | ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER
                    | ConnectivityManager.BLOCKED_REASON_DOZE);
    // TODO(261999509): allow bypassing data saver & user-restricted. However, when we allow a UI
    //     job to run while data saver restricts the app, we must ensure that we don't run regular
    //     jobs when we put a hole in the data saver wall for the UI job
    private static final int UNBYPASSABLE_UI_BLOCKED_REASONS =
            ~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY
                    | ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER
                    | ConnectivityManager.BLOCKED_REASON_DOZE);
                    | ConnectivityManager.BLOCKED_REASON_DOZE
                    | ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER
                    | ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED);
    private static final int UNBYPASSABLE_FOREGROUND_BLOCKED_REASONS =
            ~(ConnectivityManager.BLOCKED_REASON_APP_STANDBY
                    | ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER
@@ -113,6 +116,7 @@ public final class ConnectivityController extends RestrictingController implemen
                    | ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED);

    private final ConnectivityManager mConnManager;
    private final NetworkPolicyManager mNetPolicyManager;
    private final NetworkPolicyManagerInternal mNetPolicyManagerInternal;
    private final FlexibilityController mFlexibilityController;

@@ -241,6 +245,8 @@ public final class ConnectivityController extends RestrictingController implemen
     */
    private final List<UidStats> mSortedStats = new ArrayList<>();
    @GuardedBy("mLock")
    private final SparseBooleanArray mBackgroundMeteredAllowed = new SparseBooleanArray();
    @GuardedBy("mLock")
    private long mLastCallbackAdjustmentTimeElapsed;
    @GuardedBy("mLock")
    private final SparseArray<CellSignalStrengthCallback> mSignalStrengths = new SparseArray<>();
@@ -250,6 +256,8 @@ public final class ConnectivityController extends RestrictingController implemen

    private static final int MSG_ADJUST_CALLBACKS = 0;
    private static final int MSG_UPDATE_ALL_TRACKED_JOBS = 1;
    private static final int MSG_DATA_SAVER_TOGGLED = 2;
    private static final int MSG_UID_POLICIES_CHANGED = 3;

    private final Handler mHandler;

@@ -259,6 +267,7 @@ public final class ConnectivityController extends RestrictingController implemen
        mHandler = new CcHandler(AppSchedulingModuleThread.get().getLooper());

        mConnManager = mContext.getSystemService(ConnectivityManager.class);
        mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
        mNetPolicyManagerInternal = LocalServices.getService(NetworkPolicyManagerInternal.class);
        mFlexibilityController = flexibilityController;

@@ -266,6 +275,8 @@ public final class ConnectivityController extends RestrictingController implemen
        // network changes against the active network for each UID with jobs.
        final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
        mConnManager.registerNetworkCallback(request, mNetworkCallback);

        mNetPolicyManager.registerListener(mNetPolicyListener);
    }

    @GuardedBy("mLock")
@@ -530,6 +541,7 @@ public final class ConnectivityController extends RestrictingController implemen
            // All packages in the UID have been removed. It's safe to remove things based on
            // UID alone.
            mTrackedJobs.delete(uid);
            mBackgroundMeteredAllowed.delete(uid);
            UidStats uidStats = mUidStats.removeReturnOld(uid);
            unregisterDefaultNetworkCallbackLocked(uid, sElapsedRealtimeClock.millis());
            mSortedStats.remove(uidStats);
@@ -549,6 +561,12 @@ public final class ConnectivityController extends RestrictingController implemen
                mUidStats.removeAt(u);
            }
        }
        for (int u = mBackgroundMeteredAllowed.size() - 1; u >= 0; --u) {
            final int uid = mBackgroundMeteredAllowed.keyAt(u);
            if (UserHandle.getUserId(uid) == userId) {
                mBackgroundMeteredAllowed.removeAt(u);
            }
        }
        postAdjustCallbacks();
    }

@@ -666,6 +684,88 @@ public final class ConnectivityController extends RestrictingController implemen
        return false;
    }

    private boolean isMeteredAllowed(@NonNull JobStatus jobStatus,
            @NonNull NetworkCapabilities networkCapabilities) {
        // Network isn't metered. Usage is allowed. The rest of this method doesn't apply.
        if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)
                || networkCapabilities.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)) {
            return true;
        }

        final int uid = jobStatus.getSourceUid();
        final int procState = mService.getUidProcState(uid);
        final int capabilities = mService.getUidCapabilities(uid);
        // Jobs don't raise the proc state to anything better than IMPORTANT_FOREGROUND.
        // If the app is in a better state, see if it has the capability to use the metered network.
        final boolean currentStateAllows = procState != ActivityManager.PROCESS_STATE_UNKNOWN
                && procState < ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
                && NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground(
                        procState, capabilities);
        if (DEBUG) {
            Slog.d(TAG, "UID " + uid
                    + " current state allows metered network=" + currentStateAllows
                    + " procState=" + ActivityManager.procStateToString(procState)
                    + " capabilities=" + ActivityManager.getCapabilitiesSummary(capabilities));
        }
        if (currentStateAllows) {
            return true;
        }

        if ((jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) {
            final int expectedProcState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
            final int mergedCapabilities = capabilities
                    | NetworkPolicyManager.getDefaultProcessNetworkCapabilities(expectedProcState);
            final boolean wouldBeAllowed =
                    NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground(
                            expectedProcState, mergedCapabilities);
            if (DEBUG) {
                Slog.d(TAG, "UID " + uid
                        + " willBeForeground flag allows metered network=" + wouldBeAllowed
                        + " capabilities="
                        + ActivityManager.getCapabilitiesSummary(mergedCapabilities));
            }
            if (wouldBeAllowed) {
                return true;
            }
        }

        if (jobStatus.shouldTreatAsUserInitiatedJob()) {
            // Since the job is initiated by the user and will be visible to the user, it
            // should be able to run on metered networks, similar to FGS.
            // With user-initiated jobs, JobScheduler will request that the process
            // run at IMPORTANT_FOREGROUND process state
            // and get the USER_RESTRICTED_NETWORK process capability.
            final int expectedProcState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
            final int mergedCapabilities = capabilities
                    | ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK
                    | NetworkPolicyManager.getDefaultProcessNetworkCapabilities(expectedProcState);
            final boolean wouldBeAllowed =
                    NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground(
                            expectedProcState, mergedCapabilities);
            if (DEBUG) {
                Slog.d(TAG, "UID " + uid
                        + " UI job state allows metered network=" + wouldBeAllowed
                        + " capabilities=" + mergedCapabilities);
            }
            if (wouldBeAllowed) {
                return true;
            }
        }

        if (mBackgroundMeteredAllowed.indexOfKey(uid) >= 0) {
            return mBackgroundMeteredAllowed.get(uid);
        }

        final boolean allowed =
                mNetPolicyManager.getRestrictBackgroundStatus(uid)
                        != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
        if (DEBUG) {
            Slog.d(TAG, "UID " + uid + " allowed in data saver=" + allowed);
        }
        mBackgroundMeteredAllowed.put(uid, allowed);
        return allowed;
    }

    /**
     * Return the estimated amount of time this job will be transferring data,
     * based on the current network speed.
@@ -859,6 +959,12 @@ public final class ConnectivityController extends RestrictingController implemen
        // First, are we insane?
        if (isInsane(jobStatus, network, capabilities, constants)) return false;

        // User-initiated jobs might make NetworkPolicyManager open up network access for
        // the whole UID. If network access is opened up just because of UI jobs, we want
        // to make sure that non-UI jobs don't run during that time,
        // so make sure the job can make use of the metered network at this time.
        if (!isMeteredAllowed(jobStatus, capabilities)) return false;

        // Second, is the network congested?
        if (isCongestionDelayed(jobStatus, network, capabilities, constants)) return false;

@@ -1138,9 +1244,10 @@ public final class ConnectivityController extends RestrictingController implemen
            // but it doesn't yet satisfy the requested constraints and the old network
            // is still available and satisfies the constraints. Don't change the network
            // given to the job for now and let it keep running. We will re-evaluate when
            // the capabilities or connection state of the either network change.
            // the capabilities or connection state of either network change.
            if (DEBUG) {
                Slog.i(TAG, "Not reassigning network for running job " + jobStatus);
                Slog.i(TAG, "Not reassigning network from " + jobStatus.network
                        + " to " + network + " for running job " + jobStatus);
            }
            return false;
        }
@@ -1389,6 +1496,26 @@ public final class ConnectivityController extends RestrictingController implemen
        }
    };

    private final INetworkPolicyListener mNetPolicyListener = new NetworkPolicyManager.Listener() {
        @Override
        public void onRestrictBackgroundChanged(boolean restrictBackground) {
            if (DEBUG) {
                Slog.v(TAG, "onRestrictBackgroundChanged: " + restrictBackground);
            }
            mHandler.obtainMessage(MSG_DATA_SAVER_TOGGLED).sendToTarget();
        }

        @Override
        public void onUidPoliciesChanged(int uid, int uidPolicies) {
            if (DEBUG) {
                Slog.v(TAG, "onUidPoliciesChanged: " + uid);
            }
            mHandler.obtainMessage(MSG_UID_POLICIES_CHANGED,
                    uid, mNetPolicyManager.getRestrictBackgroundStatus(uid))
                    .sendToTarget();
        }
    };

    private class CcHandler extends Handler {
        CcHandler(Looper looper) {
            super(looper);
@@ -1410,6 +1537,27 @@ public final class ConnectivityController extends RestrictingController implemen
                            updateAllTrackedJobsLocked(allowThrottle);
                        }
                        break;

                    case MSG_DATA_SAVER_TOGGLED:
                        removeMessages(MSG_DATA_SAVER_TOGGLED);
                        synchronized (mLock) {
                            mBackgroundMeteredAllowed.clear();
                            updateTrackedJobsLocked(-1, null);
                        }
                        break;

                    case MSG_UID_POLICIES_CHANGED:
                        final int uid = msg.arg1;
                        final boolean newAllowed =
                                msg.arg2 != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
                        synchronized (mLock) {
                            final boolean oldAllowed = mBackgroundMeteredAllowed.get(uid);
                            if (oldAllowed != newAllowed) {
                                mBackgroundMeteredAllowed.put(uid, newAllowed);
                                updateTrackedJobsLocked(uid, null);
                            }
                        }
                        break;
                }
            }
        }
+1 −0
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ package android.app {
    field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6
    field @Deprecated public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
    field public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 8; // 0x8
    field public static final int PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK = 32; // 0x20
    field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
    field public static final int PROCESS_STATE_TOP = 2; // 0x2
    field public static final int STOP_USER_ON_SWITCH_DEFAULT = -1; // 0xffffffff
+12 −1
Original line number Diff line number Diff line
@@ -764,6 +764,7 @@ public class ActivityManager {
            PROCESS_CAPABILITY_FOREGROUND_MICROPHONE,
            PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
            PROCESS_CAPABILITY_BFSL,
            PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ProcessCapability {}
@@ -913,6 +914,13 @@ public class ActivityManager {
     */
    public static final int PROCESS_CAPABILITY_BFSL = 1 << 4;

    /**
     * @hide
     * Process can access network at a high enough proc state despite any user restrictions.
     */
    @TestApi
    public static final int PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK = 1 << 5;

    /**
     * @hide all capabilities, the ORing of all flags in {@link ProcessCapability}.
     *
@@ -923,7 +931,8 @@ public class ActivityManager {
            | PROCESS_CAPABILITY_FOREGROUND_CAMERA
            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
            | PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
            | PROCESS_CAPABILITY_BFSL;
            | PROCESS_CAPABILITY_BFSL
            | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;

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

    /** @hide */
@@ -952,6 +962,7 @@ public class ActivityManager {
        sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0 ? 'M' : '-');
        sb.append((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
        sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
        sb.append((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
    }

    /**
Loading