Do not ignore home activity focus change on multi TaskDisplayArea device
Before, tapping home search didn't bring up IME because of no focus. Now, it will focus home if it is on a different TDA. Fix: 155000370 Test: manual: verify on a dual TDA device Test: atest WmTests:WindowContainerTests Test: atest WmTests:WindowManagerServiceTests Change-Id: I9c6e815e62ad6f82d6d6b5fbbd361437b40d5e89
This commit is contained in:
@@ -280,7 +280,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
private final DisplayArea.Root mRootDisplayArea = new DisplayArea.Root(mWmService);
|
||||
|
||||
private final DisplayAreaPolicy mDisplayAreaPolicy;
|
||||
@VisibleForTesting
|
||||
final DisplayAreaPolicy mDisplayAreaPolicy;
|
||||
|
||||
private WindowState mTmpWindow;
|
||||
private WindowState mTmpWindow2;
|
||||
|
||||
@@ -7970,17 +7970,24 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
handleTaskFocusChange(touchedWindow.getTask());
|
||||
}
|
||||
|
||||
private void handleTaskFocusChange(Task task) {
|
||||
@VisibleForTesting
|
||||
void handleTaskFocusChange(Task task) {
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ActivityStack stack = task.getStack();
|
||||
// We ignore home stack since we don't want home stack to move to front when touched.
|
||||
// Specifically, in freeform we don't want tapping on home to cause the freeform apps to go
|
||||
// behind home. See b/117376413
|
||||
if (stack.isActivityTypeHome()) {
|
||||
return;
|
||||
if (task.isActivityTypeHome()) {
|
||||
// Only ignore home stack if the requested focus home Task is in the same
|
||||
// TaskDisplayArea as the current focus Task.
|
||||
TaskDisplayArea homeTda = task.getDisplayArea();
|
||||
WindowState curFocusedWindow = getFocusedWindow();
|
||||
if (curFocusedWindow != null && homeTda != null
|
||||
&& curFocusedWindow.isDescendantOf(homeTda)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
|
||||
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
|
||||
@@ -35,6 +36,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||
import static com.android.server.wm.DisplayArea.Type.ANY;
|
||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
|
||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
|
||||
@@ -839,6 +841,36 @@ public class WindowContainerTests extends WindowTestsBase {
|
||||
verifyWindowContainerApplyAnimation(stack, activity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDisplayArea() {
|
||||
// WindowContainer
|
||||
final WindowContainer windowContainer = new WindowContainer(mWm);
|
||||
|
||||
assertNull(windowContainer.getDisplayArea());
|
||||
|
||||
// ActivityStack > WindowContainer
|
||||
final ActivityStack activityStack = createTaskStackOnDisplay(mDisplayContent);
|
||||
activityStack.addChild(windowContainer, 0);
|
||||
activityStack.setParent(null);
|
||||
|
||||
assertNull(windowContainer.getDisplayArea());
|
||||
assertNull(activityStack.getDisplayArea());
|
||||
|
||||
// TaskDisplayArea > ActivityStack > WindowContainer
|
||||
final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(
|
||||
mDisplayContent, mWm, "TaskDisplayArea", FEATURE_DEFAULT_TASK_CONTAINER);
|
||||
taskDisplayArea.addChild(activityStack, 0);
|
||||
|
||||
assertEquals(taskDisplayArea, windowContainer.getDisplayArea());
|
||||
assertEquals(taskDisplayArea, activityStack.getDisplayArea());
|
||||
assertEquals(taskDisplayArea, taskDisplayArea.getDisplayArea());
|
||||
|
||||
// DisplayArea
|
||||
final DisplayArea displayArea = new DisplayArea(mWm, ANY, "DisplayArea");
|
||||
|
||||
assertEquals(displayArea, displayArea.getDisplayArea());
|
||||
}
|
||||
|
||||
private void verifyWindowContainerApplyAnimation(WindowContainer wc, ActivityRecord act) {
|
||||
// Initial remote animation for app transition.
|
||||
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
||||
|
||||
@@ -16,21 +16,30 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.os.Process.INVALID_UID;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -40,6 +49,10 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Build/Install/Run:
|
||||
* atest WmTests:WindowManagerServiceTests
|
||||
*/
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(WindowTestRunner.class)
|
||||
@@ -105,4 +118,70 @@ public class WindowManagerServiceTests extends WindowTestsBase {
|
||||
|
||||
mWm.removeWindowToken(token, mDisplayContent.getDisplayId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTaskFocusChange_stackNotHomeType_focusChanges() throws RemoteException {
|
||||
DisplayContent display = createNewDisplay();
|
||||
// Current focused window
|
||||
ActivityStack focusedStack = createTaskStackOnDisplay(
|
||||
WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, display);
|
||||
Task focusedTask = createTaskInStack(focusedStack, 0 /* userId */);
|
||||
WindowState focusedWindow = createAppWindow(focusedTask, TYPE_APPLICATION, "App Window");
|
||||
mDisplayContent.mCurrentFocus = focusedWindow;
|
||||
// Tapped task
|
||||
ActivityStack tappedStack = createTaskStackOnDisplay(
|
||||
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, display);
|
||||
Task tappedTask = createTaskInStack(tappedStack, 0 /* userId */);
|
||||
spyOn(mWm.mActivityTaskManager);
|
||||
|
||||
mWm.handleTaskFocusChange(tappedTask);
|
||||
|
||||
verify(mWm.mActivityTaskManager).setFocusedTask(tappedTask.mTaskId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTaskFocusChange_stackHomeTypeWithSameTaskDisplayArea_focusDoesNotChange()
|
||||
throws RemoteException {
|
||||
DisplayContent display = createNewDisplay();
|
||||
// Current focused window
|
||||
ActivityStack focusedStack = createTaskStackOnDisplay(
|
||||
WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, display);
|
||||
Task focusedTask = createTaskInStack(focusedStack, 0 /* userId */);
|
||||
WindowState focusedWindow = createAppWindow(focusedTask, TYPE_APPLICATION, "App Window");
|
||||
mDisplayContent.mCurrentFocus = focusedWindow;
|
||||
// Tapped home task
|
||||
ActivityStack tappedStack = createTaskStackOnDisplay(
|
||||
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, display);
|
||||
Task tappedTask = createTaskInStack(tappedStack, 0 /* userId */);
|
||||
spyOn(mWm.mActivityTaskManager);
|
||||
|
||||
mWm.handleTaskFocusChange(tappedTask);
|
||||
|
||||
verify(mWm.mActivityTaskManager, never()).setFocusedTask(tappedTask.mTaskId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTaskFocusChange_stackHomeTypeWithDifferentTaskDisplayArea_focusChanges()
|
||||
throws RemoteException {
|
||||
DisplayContent display = createNewDisplay();
|
||||
TaskDisplayArea secondTda =
|
||||
new TaskDisplayArea(display, mWm, "Tapped TDA", FEATURE_VENDOR_FIRST);
|
||||
display.mDisplayAreaPolicy.mRoot.addChild(secondTda, 1);
|
||||
display.mDisplayAreaPolicy.mTaskDisplayAreas.add(secondTda);
|
||||
// Current focused window
|
||||
ActivityStack focusedStack = createTaskStackOnDisplay(
|
||||
WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, display);
|
||||
Task focusedTask = createTaskInStack(focusedStack, 0 /* userId */);
|
||||
WindowState focusedWindow = createAppWindow(focusedTask, TYPE_APPLICATION, "App Window");
|
||||
mDisplayContent.mCurrentFocus = focusedWindow;
|
||||
// Tapped home task on another task display area
|
||||
ActivityStack tappedStack = createTaskStackOnTaskDisplayArea(
|
||||
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, secondTda);
|
||||
Task tappedTask = createTaskInStack(tappedStack, 0 /* userId */);
|
||||
spyOn(mWm.mActivityTaskManager);
|
||||
|
||||
mWm.handleTaskFocusChange(tappedTask);
|
||||
|
||||
verify(mWm.mActivityTaskManager).setFocusedTask(tappedTask.mTaskId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,6 +304,20 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
}
|
||||
}
|
||||
|
||||
ActivityStack createTaskStackOnTaskDisplayArea(
|
||||
int windowingMode, int activityType, TaskDisplayArea tda) {
|
||||
synchronized (mWm.mGlobalLock) {
|
||||
return new ActivityTestsBase.StackBuilder(
|
||||
tda.mDisplayContent.mWmService.mAtmService.mRootWindowContainer)
|
||||
.setTaskDisplayArea(tda)
|
||||
.setWindowingMode(windowingMode)
|
||||
.setActivityType(activityType)
|
||||
.setCreateActivity(false)
|
||||
.setIntent(new Intent())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a {@link Task} and adds it to the specified {@link ActivityStack}. */
|
||||
Task createTaskInStack(ActivityStack stack, int userId) {
|
||||
return WindowTestUtils.createTaskInStack(mWm, stack, userId);
|
||||
|
||||
Reference in New Issue
Block a user