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

Commit 9d8d5214 authored by Louis Chang's avatar Louis Chang
Browse files

Auto resuming app switch for visible apps

Or unable to launch activities from apps, even the app
has visible windows, like bubbles.

Bug: 208198575
Test: start activity from bubble
Test: atest BackgroundActivityLaunchTest
Change-Id: I0d9b0b16a437ddda1e0da9be930f3418d5751ce5
parent 3f7eca56
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
@@ -1275,7 +1277,10 @@ class ActivityStarter {

        // This is used to block background activity launch even if the app is still
        // visible to user after user clicking home button.
        final boolean appSwitchAllowed = mService.getBalAppSwitchesAllowed();
        final int appSwitchState = mService.getBalAppSwitchesState();
        final boolean appSwitchAllowed = appSwitchState == APP_SWITCH_ALLOW;
        final boolean appSwitchAllowedOrFg =
                appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;

        // don't abort if the callingUid has a visible window or is a persistent system process
        final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
@@ -1288,7 +1293,7 @@ class ActivityStarter {

        // Normal apps with visible app window will be allowed to start activity if app switching
        // is allowed, or apps like live wallpaper with non app visible window will be allowed.
        if (((appSwitchAllowed || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
        if (((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
                && callingUidHasAnyVisibleWindow)
                || isCallingUidPersistentSystemProcess) {
            if (DEBUG_ACTIVITY_STARTS) {
@@ -1426,7 +1431,7 @@ class ActivityStarter {
        // anything that has fallen through would currently be aborted
        Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                + "; callingUid: " + callingUid
                + "; appSwitchAllowed: " + appSwitchAllowed
                + "; appSwitchState: " + appSwitchState
                + "; isCallingUidForeground: " + isCallingUidForeground
                + "; callingUidHasAnyVisibleWindow: " + callingUidHasAnyVisibleWindow
                + "; callingUidProcState: " + DebugUtils.valueToString(ActivityManager.class,
+38 −6
Original line number Diff line number Diff line
@@ -504,7 +504,27 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
     * Whether normal application switches are allowed; a call to {@link #stopAppSwitches()
     * disables this.
     */
    private volatile boolean mAppSwitchesAllowed = true;
    private volatile int mAppSwitchesState = APP_SWITCH_ALLOW;

    // The duration of resuming foreground app switch from disallow.
    private static final long RESUME_FG_APP_SWITCH_MS = 500;

    /** App switch is not allowed. */
    static final int APP_SWITCH_DISALLOW = 0;

    /** App switch is allowed only if the activity launch was requested by a foreground app. */
    static final int APP_SWITCH_FG_ONLY = 1;

    /** App switch is allowed. */
    static final int APP_SWITCH_ALLOW = 2;

    @IntDef({
            APP_SWITCH_DISALLOW,
            APP_SWITCH_FG_ONLY,
            APP_SWITCH_ALLOW,
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface AppSwitchState {}

    /**
     * Last stop app switches time, apps finished before this time cannot start background activity
@@ -1247,7 +1267,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            if (topFocusedRootTask != null && topFocusedRootTask.getTopResumedActivity() != null
                    && topFocusedRootTask.getTopResumedActivity().info.applicationInfo.uid
                    == Binder.getCallingUid()) {
                mAppSwitchesAllowed = true;
                mAppSwitchesState = APP_SWITCH_ALLOW;
            }
        }
        return pir.sendInner(0, fillInIntent, resolvedType, allowlistToken, null, null,
@@ -2158,8 +2178,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    /**
     * Return true if app switching is allowed.
     */
    boolean getBalAppSwitchesAllowed() {
        return mAppSwitchesAllowed;
    @AppSwitchState int getBalAppSwitchesState() {
        return mAppSwitchesState;
    }

    /** Register an {@link AnrController} to control the ANR dialog behavior */
@@ -3680,8 +3700,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    public void stopAppSwitches() {
        mAmInternal.enforceCallingPermission(STOP_APP_SWITCHES, "stopAppSwitches");
        synchronized (mGlobalLock) {
            mAppSwitchesAllowed = false;
            mAppSwitchesState = APP_SWITCH_DISALLOW;
            mLastStopAppSwitchesTime = SystemClock.uptimeMillis();
            mH.removeMessages(H.RESUME_FG_APP_SWITCH_MSG);
            mH.sendEmptyMessageDelayed(H.RESUME_FG_APP_SWITCH_MSG, RESUME_FG_APP_SWITCH_MS);
        }
    }

@@ -3689,7 +3711,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    public void resumeAppSwitches() {
        mAmInternal.enforceCallingPermission(STOP_APP_SWITCHES, "resumeAppSwitches");
        synchronized (mGlobalLock) {
            mAppSwitchesAllowed = true;
            mAppSwitchesState = APP_SWITCH_ALLOW;
            mH.removeMessages(H.RESUME_FG_APP_SWITCH_MSG);
        }
    }

@@ -5170,6 +5193,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        static final int REPORT_TIME_TRACKER_MSG = 1;
        static final int UPDATE_PROCESS_ANIMATING_STATE = 2;
        static final int END_POWER_MODE_UNKNOWN_VISIBILITY_MSG = 3;
        static final int RESUME_FG_APP_SWITCH_MSG = 4;

        static final int FIRST_ACTIVITY_TASK_MSG = 100;
        static final int FIRST_SUPERVISOR_TASK_MSG = 200;
@@ -5207,6 +5231,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                    }
                }
                break;
                case RESUME_FG_APP_SWITCH_MSG: {
                    synchronized (mGlobalLock) {
                        if (mAppSwitchesState == APP_SWITCH_DISALLOW) {
                            mAppSwitchesState = APP_SWITCH_FG_ONLY;
                        }
                    }
                }
                break;
            }
        }
    }
+2 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFI
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;

@@ -512,7 +513,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
     */
    @HotPath(caller = HotPath.START_SERVICE)
    public boolean areBackgroundFgsStartsAllowed() {
        return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesAllowed(),
        return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesState() == APP_SWITCH_ALLOW,
                true /* isCheckingForFgsStart */);
    }