Merge "Not resume TaskFragment behind translucent others" into sc-v2-dev am: b38be99dba

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16552869

Change-Id: I3b32480d1a28a1e0d4191483f30a63ee1d1aba02
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d3d32d7..2d72c28 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5044,8 +5044,7 @@
             if (topFragment == f) {
                 return;
             }
-            if (!f.isFocusableAndVisible()) {
-                // No need to resume activity in TaskFragment that is not visible.
+            if (!f.canBeResumed(null /* starting */)) {
                 return;
             }
             resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index ec3554a..e0e2876 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -38,7 +38,6 @@
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
 import static com.android.server.wm.ActivityTaskManagerService.TAG_ROOT_TASK;
 import static com.android.server.wm.DisplayContent.alwaysCreateRootTask;
-import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -1475,9 +1474,7 @@
 
             leafTask.forAllLeafTaskFragments((taskFrag) -> {
                 final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
-                if (resumedActivity != null
-                        && (taskFrag.getVisibility(resuming) != TASK_FRAGMENT_VISIBILITY_VISIBLE
-                        || !taskFrag.isTopActivityFocusable())) {
+                if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
                     if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
                         someActivityPaused[0]++;
                     }
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 916fa5b..efd51e9 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1359,6 +1359,17 @@
         return getVisibility(starting) != TASK_FRAGMENT_VISIBILITY_INVISIBLE;
     }
 
+    /**
+     * Returns {@code true} is the activity in this TaskFragment can be resumed.
+     *
+     * @param starting The currently starting activity or {@code null} if there is none.
+     */
+    boolean canBeResumed(@Nullable ActivityRecord starting) {
+        // No need to resume activity in TaskFragment that is not visible.
+        return isTopActivityFocusable()
+                && getVisibility(starting) == TASK_FRAGMENT_VISIBILITY_VISIBLE;
+    }
+
     boolean isFocusableAndVisible() {
         return isTopActivityFocusable() && shouldBeVisible(null /* starting */);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index bfaa815..4ba3f63 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -44,6 +44,7 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.server.policy.WindowManagerPolicy.USER_ROTATION_FREE;
 import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
+import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -66,6 +67,7 @@
 import static org.mockito.Mockito.never;
 
 import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.app.TaskInfo;
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
@@ -1424,6 +1426,29 @@
         verify(task2).moveToFrontInner(anyString(), isNull());
     }
 
+    @Test
+    public void testResumeTask_doNotResumeTaskFragmentBehindTranslucent() {
+        final Task task = createTask(mDisplayContent);
+        final TaskFragment tfBehind = createTaskFragmentWithParentTask(
+                task, false /* createEmbeddedTask */);
+        final TaskFragment tfFront = createTaskFragmentWithParentTask(
+                task, false /* createEmbeddedTask */);
+        spyOn(tfFront);
+        doReturn(true).when(tfFront).isTranslucent(any());
+
+        // TaskFragment behind another translucent TaskFragment should not be resumed.
+        assertEquals(TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT,
+                tfBehind.getVisibility(null /* starting */));
+        assertTrue(tfBehind.isFocusable());
+        assertFalse(tfBehind.canBeResumed(null /* starting */));
+
+        spyOn(tfBehind);
+        task.resumeTopActivityUncheckedLocked(null /* prev */, ActivityOptions.makeBasic(),
+                false /* deferPause */);
+
+        verify(tfBehind, never()).resumeTopActivity(any(), any(), anyBoolean());
+    }
+
     private Task getTestTask() {
         final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
         return task.getBottomMostTask();