diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 2cf23c5e6f7f4..fe661dcdb307c 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -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, diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 60a514e4d6122..c8227d9530093 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -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; } } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 1cfbe07d3f168..90a5d69e43f77 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -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