Tighten rules for blocking activity starts.

This means we now block various cases where we failed to before,
including where an app launches an activity shortly after the home
button has been pressed, e.g. from within onPause() - either
immediately or after some blocking call.

Details:
- We no longer use process state at all, since a process may remain
  top for a time after the user has switched away and its
  windows have ceased to be visible.
- We no longer allow a start if callerApp.hasForegroundActivities(),
  because we are checking for windows visible to the user and an
  activity may be considered foreground even when it doesn't have such
  windows.
- Windows are only considered visible if isNowVisible() is true,
  rather than isVisible().

Bug: 128688247
Test: atest BackgroundActivityLaunchTest RootWindowContainerTests \
 WmTests:ActivityStarterTests \
 CtsActivityManagerDeviceTestCases:ActivityStarterTests
Test: Manual verification with self-restarting test app
Change-Id: I9863d8637661f15828ced435ff23812a4beef78d
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 473a875..8957444 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -937,7 +937,7 @@
                 || callingUid == Process.NFC_UID) {
             return false;
         }
-        // don't abort if the callingUid is in the foreground or is a persistent system process
+        // don't abort if the callingUid has a visible window or is a persistent system process
         final int callingUidProcState = mService.getUidState(callingUid);
         final boolean callingUidHasAnyVisibleWindow =
                 mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(callingUid);
@@ -946,7 +946,7 @@
                 || callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
         final boolean isCallingUidPersistentSystemProcess = (callingUid == Process.SYSTEM_UID)
                 || callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
-        if (isCallingUidForeground || isCallingUidPersistentSystemProcess) {
+        if (callingUidHasAnyVisibleWindow || isCallingUidPersistentSystemProcess) {
             return false;
         }
         // take realCallingUid into consideration
@@ -965,8 +965,8 @@
                 : (realCallingUid == Process.SYSTEM_UID)
                         || realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
         if (realCallingUid != callingUid) {
-            // don't abort if the realCallingUid is in the foreground and callingUid isn't
-            if (isRealCallingUidForeground) {
+            // don't abort if the realCallingUid has a visible window
+            if (realCallingUidHasAnyVisibleWindow) {
                 return false;
             }
             // if the realCallingUid is a persistent system process, abort if the IntentSender
@@ -988,10 +988,6 @@
             callerApp = mService.getProcessController(realCallingPid, realCallingUid);
         }
         if (callerApp != null) {
-            // don't abort if the callerApp has any visible activity
-            if (callerApp.hasForegroundActivities()) {
-                return false;
-            }
             // don't abort if the callerApp is instrumenting with background activity starts privs
             if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
                 return false;
@@ -1061,8 +1057,7 @@
         final ArraySet<Integer> boundClientUids = callerApp.getBoundClientUids();
         for (int i = boundClientUids.size() - 1; i >= 0; --i) {
             final int uid = boundClientUids.valueAt(i);
-            if (mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid)
-                    || mService.getUidState(uid) == ActivityManager.PROCESS_STATE_TOP) {
+            if (mService.isUidForeground(uid)) {
                 return true;
             }
         }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 7d25466..48aee20 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -503,7 +503,7 @@
     public abstract ActivityManager.TaskSnapshot getTaskSnapshot(int taskId,
             boolean reducedResolution);
 
-    /** Returns true if uid has a visible window or its process is in a top state. */
+    /** Returns true if uid is considered foreground for activity start purposes. */
     public abstract boolean isUidForeground(int uid);
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b424904..22e6a35 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5872,8 +5872,8 @@
     }
 
     boolean isUidForeground(int uid) {
-        return (getUidState(uid) == ActivityManager.PROCESS_STATE_TOP)
-                || mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
+        // A uid is considered to be foreground if it has a visible non-toast window.
+        return mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
     }
 
     boolean isDeviceOwner(int uid) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1ca31f1..f9fd541 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -314,9 +314,10 @@
      * Returns true if the callingUid has any non-toast window currently visible to the user.
      */
     boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
-        return forAllWindows(w -> {
-            return w.getOwningUid() == callingUid && w.isVisible() && w.mAttrs.type != TYPE_TOAST;
-        }, true /* traverseTopToBottom */);
+        return forAllWindows(w ->
+                        w.getOwningUid() == callingUid && w.mAttrs.type != TYPE_TOAST
+                        && w.isVisibleNow(),
+                true /* traverseTopToBottom */);
     }
 
     /**