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

Commit b2117d15 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Implement lenient background check option.

Which really means, make background check much more
strict, with an option to revert to the more lenient
behavior.

In this strict version, an app can't have services
started or receive broadcasts at any point when it is
not foreground.  Also, it doesn't matter the importance
of a caller trying to start a service, it only depends
on the state of the app whose service is being started.

A new activity shell command allows you to control
whether to use the strict or lenient behavior.

Change-Id: I7f5a50b52881b5c8f9d8b6c8c622d3652a769fd7
parent 263e21f1
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -1532,6 +1532,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }

        case SET_LENIENT_BACKGROUND_CHECK_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            boolean enabled = data.readInt() != 0;
            setLenientBackgroundCheck(enabled);
            reply.writeNoException();
            return true;
        }

        case ENTER_SAFE_MODE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            enterSafeMode();
@@ -4855,6 +4863,17 @@ class ActivityManagerProxy implements IActivityManager
        data.recycle();
        reply.recycle();
    }
    public void setLenientBackgroundCheck(boolean enabled) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeInt(enabled ? 1 : 0);
        mRemote.transact(SET_LENIENT_BACKGROUND_CHECK_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
    public void enterSafeMode() throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
+2 −0
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ public interface IActivityManager extends IInterface {
    public void setAlwaysFinish(boolean enabled) throws RemoteException;
    public void setActivityController(IActivityController watcher)
        throws RemoteException;
    public void setLenientBackgroundCheck(boolean enabled) throws RemoteException;

    public void enterSafeMode() throws RemoteException;

@@ -978,4 +979,5 @@ public interface IActivityManager extends IInterface {
    int SUPPORTS_LOCAL_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 365;
    int NOTIFY_PINNED_STACK_ANIMATION_ENDED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 366;
    int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367;
    int SET_LENIENT_BACKGROUND_CHECK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+368;
}
+8 −1
Original line number Diff line number Diff line
@@ -7844,12 +7844,19 @@ public final class Settings {
        public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";

         /**
         * If 1, the activity manager will aggressively finish activities and
         * If not 0, the activity manager will aggressively finish activities and
         * processes as soon as they are no longer needed.  If 0, the normal
         * extended lifetime is used.
         */
        public static final String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";

        /**
         * @hide
         * If not 0, the activity manager will implement a looser version of background
         * check that is more compatible with existing apps.
         */
        public static final String LENIENT_BACKGROUND_CHECK = "lenient_background_check";

        /**
         * Use Dock audio output for media:
         *      0 = disabled
+46 −7
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
import static android.provider.Settings.Global.LENIENT_BACKGROUND_CHECK;
import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
import static android.provider.Settings.System.FONT_SCALE;
import static com.android.internal.util.XmlUtils.readBooleanAttribute;
@@ -1290,6 +1291,7 @@ public final class ActivityManagerService extends ActivityManagerNative
    String mOrigDebugApp = null;
    boolean mOrigWaitForDebugger = false;
    boolean mAlwaysFinishActivities = false;
    boolean mLenientBackgroundCheck = false;
    boolean mForceResizableActivities;
    boolean mSupportsFreeformWindowManagement;
    boolean mSupportsPictureInPicture;
@@ -7490,7 +7492,16 @@ public final class ActivityManagerService extends ActivityManagerNative
    int checkAllowBackgroundLocked(int uid, String packageName, int callingPid) {
        UidRecord uidRec = mActiveUids.get(uid);
        if (uidRec == null || uidRec.idle) {
        if (!mLenientBackgroundCheck) {
            if (uidRec == null
                    || uidRec.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                if (mAppOpsService.noteOperation(AppOpsManager.OP_RUN_IN_BACKGROUND, uid,
                        packageName) != AppOpsManager.MODE_ALLOWED) {
                    return ActivityManager.APP_START_MODE_DELAYED;
                }
            }
        } else if (uidRec == null || uidRec.idle) {
            if (callingPid >= 0) {
                ProcessRecord proc;
                synchronized (mPidsSelfLocked) {
@@ -11376,6 +11387,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        enforceCallingPermission(android.Manifest.permission.SET_ALWAYS_FINISH,
                "setAlwaysFinish()");
        long ident = Binder.clearCallingIdentity();
        try {
            Settings.Global.putInt(
                    mContext.getContentResolver(),
                    Settings.Global.ALWAYS_FINISH_ACTIVITIES, enabled ? 1 : 0);
@@ -11383,6 +11396,28 @@ public final class ActivityManagerService extends ActivityManagerNative
            synchronized (this) {
                mAlwaysFinishActivities = enabled;
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    @Override
    public void setLenientBackgroundCheck(boolean enabled) {
        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                "setLenientBackgroundCheck()");
        long ident = Binder.clearCallingIdentity();
        try {
            Settings.Global.putInt(
                    mContext.getContentResolver(),
                    Settings.Global.LENIENT_BACKGROUND_CHECK, enabled ? 1 : 0);
            synchronized (this) {
                mLenientBackgroundCheck = enabled;
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    @Override
@@ -12278,6 +12313,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0;
        final boolean alwaysFinishActivities =
                Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
        final boolean lenientBackgroundCheck =
                Settings.Global.getInt(resolver, LENIENT_BACKGROUND_CHECK, 0) != 0;
        final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
        final boolean forceResizable = Settings.Global.getInt(
                resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
@@ -12295,6 +12332,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            mDebugApp = mOrigDebugApp = debugApp;
            mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
            mAlwaysFinishActivities = alwaysFinishActivities;
            mLenientBackgroundCheck = lenientBackgroundCheck;
            mForceResizableActivities = forceResizable;
            mWindowManager.setForceResizableTasks(mForceResizableActivities);
            mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
@@ -14074,8 +14112,9 @@ public final class ActivityManagerService extends ActivityManagerNative
            }
        }
        if (dumpPackage == null) {
            if (mAlwaysFinishActivities || mController != null) {
            if (mAlwaysFinishActivities || mLenientBackgroundCheck || mController != null) {
                pw.println("  mAlwaysFinishActivities=" + mAlwaysFinishActivities
                        + " mLenientBackgroundCheck=" + mLenientBackgroundCheck
                        + " mController=" + mController);
            }
            if (dumpAll) {
+20 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ class ActivityManagerShellCommand extends ShellCommand {
                    return runUntrackAssociations(pw);
                case "is-user-stopped":
                    return runIsUserStopped(pw);
                case "lenient-background-check":
                    return runLenientBackgroundCheck(pw);
                default:
                    return handleDefaultCommands(cmd);
            }
@@ -152,6 +154,22 @@ class ActivityManagerShellCommand extends ShellCommand {
        return 0;
    }

    int runLenientBackgroundCheck(PrintWriter pw) throws RemoteException {
        String arg = getNextArg();
        if (arg != null) {
            boolean state = Boolean.valueOf(arg) || "1".equals(arg);
            mInterface.setLenientBackgroundCheck(state);
        }
        synchronized (mInternal) {
            if (mInternal.mLenientBackgroundCheck) {
                pw.println("Lenient background check enabled");
            } else {
                pw.println("Lenient background check disabled");
            }
        }
        return 0;
    }

    @Override
    public void onHelp() {
        PrintWriter pw = getOutPrintWriter();
@@ -203,6 +221,8 @@ class ActivityManagerShellCommand extends ShellCommand {
            pw.println("    Disable and clear association tracking.");
            pw.println("  is-user-stopped <USER_ID>");
            pw.println("    returns whether <USER_ID> has been stopped or not");
            pw.println("  lenient-background-check [<true|false>]");
            pw.println("    optionally controls lenient background check mode, returns current mode.");
        }
    }
}