summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/BackNavigationController.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java72
2 files changed, 84 insertions, 25 deletions
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index b16602e0e475..14131e693561 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -235,6 +235,7 @@ class BackNavigationController {
// We don't have an application callback, let's find the destination of the back gesture
// The search logic should align with ActivityClientController#finishActivity
prevActivity = currentTask.topRunningActivity(currentActivity.token, INVALID_TASK_ID);
+ final boolean isOccluded = isKeyguardOccluded(window);
// TODO Dialog window does not need to attach on activity, check
// window.mAttrs.type != TYPE_BASE_APPLICATION
if ((window.getParent().getChildCount() > 1
@@ -244,16 +245,24 @@ class BackNavigationController {
backType = BackNavigationInfo.TYPE_DIALOG_CLOSE;
removedWindowContainer = window;
} else if (prevActivity != null) {
- // We have another Activity in the same currentTask to go to
- backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
- removedWindowContainer = currentActivity;
- prevTask = prevActivity.getTask();
+ if (!isOccluded || prevActivity.canShowWhenLocked()) {
+ // We have another Activity in the same currentTask to go to
+ backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
+ removedWindowContainer = currentActivity;
+ prevTask = prevActivity.getTask();
+ } else {
+ backType = BackNavigationInfo.TYPE_CALLBACK;
+ }
} else if (currentTask.returnsToHomeRootTask()) {
- // Our Task should bring back to home
- removedWindowContainer = currentTask;
- prevTask = currentTask.getDisplayArea().getRootHomeTask();
- backType = BackNavigationInfo.TYPE_RETURN_TO_HOME;
- mShowWallpaper = true;
+ if (isOccluded) {
+ backType = BackNavigationInfo.TYPE_CALLBACK;
+ } else {
+ // Our Task should bring back to home
+ removedWindowContainer = currentTask;
+ prevTask = currentTask.getDisplayArea().getRootHomeTask();
+ backType = BackNavigationInfo.TYPE_RETURN_TO_HOME;
+ mShowWallpaper = true;
+ }
} else if (currentActivity.isRootOfTask()) {
// TODO(208789724): Create single source of truth for this, maybe in
// RootWindowContainer
@@ -267,7 +276,9 @@ class BackNavigationController {
backType = BackNavigationInfo.TYPE_CALLBACK;
} else {
prevActivity = prevTask.getTopNonFinishingActivity();
- if (prevTask.isActivityTypeHome()) {
+ if (prevActivity == null || (isOccluded && !prevActivity.canShowWhenLocked())) {
+ backType = BackNavigationInfo.TYPE_CALLBACK;
+ } else if (prevTask.isActivityTypeHome()) {
backType = BackNavigationInfo.TYPE_RETURN_TO_HOME;
mShowWallpaper = true;
} else {
@@ -323,6 +334,12 @@ class BackNavigationController {
return mAnimationTargets.mComposed && mAnimationTargets.mWaitTransition;
}
+ boolean isKeyguardOccluded(WindowState focusWindow) {
+ final KeyguardController kc = mWindowManagerService.mAtmService.mKeyguardController;
+ final int displayId = focusWindow.getDisplayId();
+ return kc.isKeyguardLocked(displayId) && kc.isDisplayOccluded(displayId);
+ }
+
// For legacy transition.
/**
* Once we find the transition targets match back animation targets, remove the target from
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index 3bce860b8720..1b77c95358ad 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -20,24 +20,23 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.window.BackNavigationInfo.typeToString;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.hardware.HardwareBuffer;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.WindowManager;
@@ -48,7 +47,6 @@ import android.window.IOnBackInvokedCallback;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedCallbackInfo;
import android.window.OnBackInvokedDispatcher;
-import android.window.TaskSnapshot;
import android.window.WindowOnBackInvokedDispatcher;
import com.android.server.LocalServices;
@@ -67,6 +65,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
private BackNavigationController mBackNavigationController;
private WindowManagerInternal mWindowManagerInternal;
private BackAnimationAdapter mBackAnimationAdapter;
+ private Task mRootHomeTask;
@Before
public void setUp() throws Exception {
@@ -76,6 +75,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
mBackNavigationController.setWindowManager(mWm);
mBackAnimationAdapter = mock(BackAnimationAdapter.class);
+ mRootHomeTask = initHomeActivity();
}
@Test
@@ -101,7 +101,8 @@ public class BackNavigationControllerTests extends WindowTestsBase {
ActivityRecord recordA = createActivityRecord(taskA);
Mockito.doNothing().when(recordA).reparentSurfaceControl(any(), any());
- withSystemCallback(createTopTaskWithActivity());
+ final Task topTask = createTopTaskWithActivity();
+ withSystemCallback(topTask);
BackNavigationInfo backNavigationInfo = startBackNavigation();
assertWithMessage("BackNavigationInfo").that(backNavigationInfo).isNotNull();
assertThat(typeToString(backNavigationInfo.getType()))
@@ -111,6 +112,20 @@ public class BackNavigationControllerTests extends WindowTestsBase {
verify(mBackNavigationController).scheduleAnimationLocked(
eq(BackNavigationInfo.TYPE_CROSS_TASK), any(), eq(mBackAnimationAdapter),
any());
+
+ // reset drawning status
+ topTask.forAllWindows(w -> {
+ makeWindowVisibleAndDrawn(w);
+ }, true);
+ setupKeyguardOccluded();
+ backNavigationInfo = startBackNavigation();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+
+ doReturn(true).when(recordA).canShowWhenLocked();
+ backNavigationInfo = startBackNavigation();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CROSS_TASK));
}
@Test
@@ -137,6 +152,20 @@ public class BackNavigationControllerTests extends WindowTestsBase {
assertThat(backNavigationInfo.getOnBackInvokedCallback()).isEqualTo(callback);
assertThat(typeToString(backNavigationInfo.getType()))
.isEqualTo(typeToString(BackNavigationInfo.TYPE_CROSS_ACTIVITY));
+
+ // reset drawing status
+ testCase.recordFront.forAllWindows(w -> {
+ makeWindowVisibleAndDrawn(w);
+ }, true);
+ setupKeyguardOccluded();
+ backNavigationInfo = startBackNavigation();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
+
+ doReturn(true).when(testCase.recordBack).canShowWhenLocked();
+ backNavigationInfo = startBackNavigation();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CROSS_ACTIVITY));
}
@Test
@@ -164,12 +193,17 @@ public class BackNavigationControllerTests extends WindowTestsBase {
@Test
public void preparesForBackToHome() {
- Task task = createTopTaskWithActivity();
- withSystemCallback(task);
+ final Task topTask = createTopTaskWithActivity();
+ withSystemCallback(topTask);
BackNavigationInfo backNavigationInfo = startBackNavigation();
assertThat(typeToString(backNavigationInfo.getType()))
.isEqualTo(typeToString(BackNavigationInfo.TYPE_RETURN_TO_HOME));
+
+ setupKeyguardOccluded();
+ backNavigationInfo = startBackNavigation();
+ assertThat(typeToString(backNavigationInfo.getType()))
+ .isEqualTo(typeToString(BackNavigationInfo.TYPE_CALLBACK));
}
@Test
@@ -302,14 +336,22 @@ public class BackNavigationControllerTests extends WindowTestsBase {
};
}
- @NonNull
- private TaskSnapshotController createMockTaskSnapshotController() {
- TaskSnapshotController taskSnapshotController = mock(TaskSnapshotController.class);
- TaskSnapshot taskSnapshot = mock(TaskSnapshot.class);
- when(taskSnapshot.getHardwareBuffer()).thenReturn(mock(HardwareBuffer.class));
- when(taskSnapshotController.getSnapshot(anyInt(), anyInt(), anyBoolean(), anyBoolean()))
- .thenReturn(taskSnapshot);
- return taskSnapshotController;
+ private Task initHomeActivity() {
+ final Task task = mDisplayContent.getDefaultTaskDisplayArea().getRootHomeTask();
+ task.forAllLeafTasks((t) -> {
+ if (t.getTopMostActivity() == null) {
+ final ActivityRecord r = createActivityRecord(t);
+ Mockito.doNothing().when(t).reparentSurfaceControl(any(), any());
+ Mockito.doNothing().when(r).reparentSurfaceControl(any(), any());
+ }
+ }, true);
+ return task;
+ }
+
+ private void setupKeyguardOccluded() {
+ final KeyguardController kc = mRootHomeTask.mTaskSupervisor.getKeyguardController();
+ doReturn(true).when(kc).isKeyguardLocked(anyInt());
+ doReturn(true).when(kc).isDisplayOccluded(anyInt());
}
@NonNull