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:
Chris Li
2020-04-29 23:43:52 -07:00
parent 449bd6fe45
commit c5a937ce64
5 changed files with 138 additions and 5 deletions

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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(

View File

@@ -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);
}
}

View File

@@ -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);