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

Commit 2639c4bf authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

New generic background restrictions.

This modifies the existing rigid background restriction to
a more moderate policy that we can (eventually) apply to all
apps:

- After N minutes no longer in the foreground, any background
  services running in the app are stopped and no more can be
  started.
- No manifest receivers for the application will be executed
  if the broadcast is not being sent explicitly to that app and
  the app is not running.  (Eventually we should tighten this so
  they won't be received if the app is past its N minute
  background window.)
- Other non-background processes may still bind to services in
  the background process, which will raise it to back to an
  executing state...  so things like syncs, jobs, live wallpapers,
  accessibility services, etc still work.

Change-Id: I08ddbfdf640ef324a27b2eb9eecd9499f3ebddd9
parent d35c13df
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -281,6 +281,7 @@ public interface MetricsConstants {
    public static final int ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
    public static final int ACTION_WIGGLE_CAMERA_GESTURE = 256;
    public static final int QS_WORKMODE = 257;
    public static final int BACKGROUND_CHECK_SUMMARY = 258;

    // These constants must match those in the analytic pipeline, do not edit.
    // Add temporary values to the top of MetricsLogger instead.
+3 −2
Original line number Diff line number Diff line
@@ -1240,8 +1240,9 @@ public final class ActiveServices {
                    try {
                        // Before going further -- if this app is not allowed to run in the
                        // background, then at this point we aren't going to let it period.
                        if (!mAm.checkAllowBackgroundLocked(sInfo.applicationInfo.uid,
                                sInfo.packageName, callingPid)) {
                        final int allowed = mAm.checkAllowBackgroundLocked(
                                sInfo.applicationInfo.uid, sInfo.packageName, callingPid);
                        if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                            Slog.w(TAG, "Background execution not allowed: service "
                                    + r.intent + " to " + name.flattenToShortString()
                                    + " from pid=" + callingPid + " uid=" + callingUid
+5 −7
Original line number Diff line number Diff line
@@ -7463,13 +7463,11 @@ public final class ActivityManagerService extends ActivityManagerNative
    public int getAppStartMode(int uid, String packageName) {
        synchronized (this) {
            boolean bg = checkAllowBackgroundLocked(uid, packageName, -1);
            return bg ? ActivityManager.APP_START_MODE_NORMAL
                    : ActivityManager.APP_START_MODE_DISABLED;
            return checkAllowBackgroundLocked(uid, packageName, -1);
        }
    }
    boolean checkAllowBackgroundLocked(int uid, String packageName, int callingPid) {
    int checkAllowBackgroundLocked(int uid, String packageName, int callingPid) {
        UidRecord uidRec = mActiveUids.get(uid);
        if (uidRec == null || uidRec.idle) {
            if (callingPid >= 0) {
@@ -7480,15 +7478,15 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (proc != null && proc.curProcState < ActivityManager.PROCESS_STATE_RECEIVER) {
                    // Whoever is instigating this is in the foreground, so we will allow it
                    // to go through.
                    return true;
                    return ActivityManager.APP_START_MODE_NORMAL;
                }
            }
            if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName)
                    != AppOpsManager.MODE_ALLOWED) {
                return false;
                return ActivityManager.APP_START_MODE_DELAYED;
            }
        }
        return true;
        return ActivityManager.APP_START_MODE_NORMAL;
    }
    private ProviderInfo getProviderInfoLocked(String authority, int userHandle) {
+25 −14
Original line number Diff line number Diff line
@@ -562,8 +562,9 @@ public final class BroadcastQueue {
            skip = true;
        }
        if (!skip) {
            if (!mService.checkAllowBackgroundLocked(filter.receiverList.uid, filter.packageName,
                    -1)) {
            final int allowed = mService.checkAllowBackgroundLocked(filter.receiverList.uid,
                    filter.packageName, -1);
            if (allowed == ActivityManager.APP_START_MODE_DISABLED) {
                Slog.w(TAG, "Background execution not allowed: receiving "
                        + r.intent
                        + " to " + filter.receiverList.app
@@ -1012,15 +1013,6 @@ public final class BroadcastQueue {
                        + " (uid " + r.callingUid + ")");
                skip = true;
            }
            if (!skip) {
                if (!mService.checkAllowBackgroundLocked(info.activityInfo.applicationInfo.uid,
                        info.activityInfo.packageName, -1)) {
                    Slog.w(TAG, "Background execution not allowed: receiving "
                            + r.intent + " to "
                            + component.flattenToShortString());
                    skip = true;
                }
            }
            if (!skip) {
                skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
                        r.callingPid, r.resolvedType, info.activityInfo.applicationInfo.uid);
@@ -1083,6 +1075,28 @@ public final class BroadcastQueue {
                }
            }

            String targetProcess = info.activityInfo.processName;
            ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                    info.activityInfo.applicationInfo.uid, false);
            if (!skip) {
                final int allowed = mService.checkAllowBackgroundLocked(
                        info.activityInfo.applicationInfo.uid, info.activityInfo.packageName, -1);
                if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                    // We won't allow this receiver to be launched if the app has been
                    // completely disabled from launches, or it is delayed and the broadcast
                    // was not explicitly sent to it and this would result in a new process
                    // for it being created.
                    if (allowed == ActivityManager.APP_START_MODE_DISABLED
                            || (r.intent.getComponent() == null
                            && r.intent.getPackage() == null && app == null)) {
                        Slog.w(TAG, "Background execution not allowed: receiving "
                                + r.intent + " to "
                                + component.flattenToShortString());
                        skip = true;
                    }
                }
            }

            if (skip) {
                if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                        "Skipping delivery of ordered [" + mQueueName + "] "
@@ -1095,7 +1109,6 @@ public final class BroadcastQueue {
            }

            r.state = BroadcastRecord.APP_RECEIVE;
            String targetProcess = info.activityInfo.processName;
            r.curComponent = component;
            final int receiverUid = info.activityInfo.applicationInfo.uid;
            // If it's a singleton, it needs to be the same app or a special app
@@ -1126,8 +1139,6 @@ public final class BroadcastQueue {
            }

            // Is this receiver's application already running?
            ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                    info.activityInfo.applicationInfo.uid, false);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(info.activityInfo.packageName,