Loading services/core/java/com/android/server/wm/DisplayContent.java +1 −1 Original line number Diff line number Diff line Loading @@ -4589,7 +4589,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting SurfaceControl computeImeParent() { if (!ImeTargetVisibilityPolicy.isReadyToComputeImeParent(mImeLayeringTarget, if (!ImeTargetVisibilityPolicy.isValidToComputeImeParent(mImeLayeringTarget, mImeInputTarget)) { return null; } Loading services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java +31 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import android.annotation.Nullable; import android.os.IBinder; import android.view.WindowManager; Loading Loading @@ -50,10 +51,12 @@ public abstract class ImeTargetVisibilityPolicy { * Called when {@link DisplayContent#computeImeParent()} to check if it's valid to keep * computing the ime parent. * * @param imeLayeringTarget The window which IME target to layer on top of it. * @param imeInputTarget The window which start the input connection, receive input from IME. * @return {@code true} to keep computing the ime parent, {@code false} to defer this operation */ public static boolean isReadyToComputeImeParent(WindowState imeLayeringTarget, InputTarget imeInputTarget) { public static boolean isValidToComputeImeParent(@Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) { if (imeLayeringTarget == null) { return false; } Loading @@ -69,7 +72,9 @@ public abstract class ImeTargetVisibilityPolicy { boolean imeLayeringTargetMayUseIme = WindowManager.LayoutParams.mayUseInputMethod(imeLayeringTarget.mAttrs.flags) || imeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING; if (isImeTargetMismatchOnEmbedding(imeLayeringTarget, imeInputTarget)) { return true; } // Do not change parent if the window hasn't requested IME. var inputAndLayeringTargetsDisagree = (imeInputTarget == null || imeLayeringTarget.mActivityRecord != imeInputTarget.getActivityRecord()); Loading @@ -77,4 +82,27 @@ public abstract class ImeTargetVisibilityPolicy { return !inputTargetStale; } private static boolean isImeTargetMismatchOnEmbedding( @Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) { if (imeInputTarget == null || imeLayeringTarget == null) { return false; } final ActivityRecord inputTargetRecord = imeInputTarget.getActivityRecord(); final ActivityRecord layeringTargetRecord = imeLayeringTarget.getActivityRecord(); final WindowState inputTargetWindow = imeInputTarget.getWindowState(); if (inputTargetRecord == null || layeringTargetRecord == null || inputTargetWindow == null) { return false; } final boolean isImeTargetEmbedded = inputTargetRecord.isEmbedded() && layeringTargetRecord.isEmbedded(); // The IME layering target is calculated by the window hierarchy in DisplayContent. // The layering target and input target may be different when the window hasn't started // input connection, WMS hasn't received the target which reported from IMMS. We basically // won't update IME parent for better IME transition. // But in activity embedding, tapping a window won't update it to the top window so the IME // layering target may higher than input target. Update IME parent for this case. return isImeTargetEmbedded && imeLayeringTarget.compareTo(inputTargetWindow) > 0; } } services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; 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 com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; Loading Loading @@ -613,4 +614,34 @@ public class TaskFragmentTest extends WindowTestsBase { assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, tf1.getOrientation(SCREEN_ORIENTATION_UNSET)); assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, task.getOrientation(SCREEN_ORIENTATION_UNSET)); } @Test public void testUpdateImeParentForActivityEmbedding() { // Setup two activities in ActivityEmbedding. final Task task = createTask(mDisplayContent); final TaskFragment tf0 = new TaskFragmentBuilder(mAtm) .setParentTask(task) .createActivityCount(1) .setOrganizer(mOrganizer) .setFragmentToken(new Binder()) .build(); final TaskFragment tf1 = new TaskFragmentBuilder(mAtm) .setParentTask(task) .createActivityCount(1) .setOrganizer(mOrganizer) .setFragmentToken(new Binder()) .build(); final ActivityRecord activity0 = tf0.getTopMostActivity(); final ActivityRecord activity1 = tf1.getTopMostActivity(); final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, activity0, "win0"); final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity1, "win1"); doReturn(false).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeInputTarget(win0); mDisplayContent.setImeLayeringTarget(win1); // The ImeParent should be the display. assertEquals(mDisplayContent.getImeContainer().getParent().getSurfaceControl(), mDisplayContent.computeImeParent()); } } Loading
services/core/java/com/android/server/wm/DisplayContent.java +1 −1 Original line number Diff line number Diff line Loading @@ -4589,7 +4589,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting SurfaceControl computeImeParent() { if (!ImeTargetVisibilityPolicy.isReadyToComputeImeParent(mImeLayeringTarget, if (!ImeTargetVisibilityPolicy.isValidToComputeImeParent(mImeLayeringTarget, mImeInputTarget)) { return null; } Loading
services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java +31 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import android.annotation.Nullable; import android.os.IBinder; import android.view.WindowManager; Loading Loading @@ -50,10 +51,12 @@ public abstract class ImeTargetVisibilityPolicy { * Called when {@link DisplayContent#computeImeParent()} to check if it's valid to keep * computing the ime parent. * * @param imeLayeringTarget The window which IME target to layer on top of it. * @param imeInputTarget The window which start the input connection, receive input from IME. * @return {@code true} to keep computing the ime parent, {@code false} to defer this operation */ public static boolean isReadyToComputeImeParent(WindowState imeLayeringTarget, InputTarget imeInputTarget) { public static boolean isValidToComputeImeParent(@Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) { if (imeLayeringTarget == null) { return false; } Loading @@ -69,7 +72,9 @@ public abstract class ImeTargetVisibilityPolicy { boolean imeLayeringTargetMayUseIme = WindowManager.LayoutParams.mayUseInputMethod(imeLayeringTarget.mAttrs.flags) || imeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING; if (isImeTargetMismatchOnEmbedding(imeLayeringTarget, imeInputTarget)) { return true; } // Do not change parent if the window hasn't requested IME. var inputAndLayeringTargetsDisagree = (imeInputTarget == null || imeLayeringTarget.mActivityRecord != imeInputTarget.getActivityRecord()); Loading @@ -77,4 +82,27 @@ public abstract class ImeTargetVisibilityPolicy { return !inputTargetStale; } private static boolean isImeTargetMismatchOnEmbedding( @Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) { if (imeInputTarget == null || imeLayeringTarget == null) { return false; } final ActivityRecord inputTargetRecord = imeInputTarget.getActivityRecord(); final ActivityRecord layeringTargetRecord = imeLayeringTarget.getActivityRecord(); final WindowState inputTargetWindow = imeInputTarget.getWindowState(); if (inputTargetRecord == null || layeringTargetRecord == null || inputTargetWindow == null) { return false; } final boolean isImeTargetEmbedded = inputTargetRecord.isEmbedded() && layeringTargetRecord.isEmbedded(); // The IME layering target is calculated by the window hierarchy in DisplayContent. // The layering target and input target may be different when the window hasn't started // input connection, WMS hasn't received the target which reported from IMMS. We basically // won't update IME parent for better IME transition. // But in activity embedding, tapping a window won't update it to the top window so the IME // layering target may higher than input target. Update IME parent for this case. return isImeTargetEmbedded && imeLayeringTarget.compareTo(inputTargetWindow) > 0; } }
services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +31 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; 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 com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; Loading Loading @@ -613,4 +614,34 @@ public class TaskFragmentTest extends WindowTestsBase { assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, tf1.getOrientation(SCREEN_ORIENTATION_UNSET)); assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, task.getOrientation(SCREEN_ORIENTATION_UNSET)); } @Test public void testUpdateImeParentForActivityEmbedding() { // Setup two activities in ActivityEmbedding. final Task task = createTask(mDisplayContent); final TaskFragment tf0 = new TaskFragmentBuilder(mAtm) .setParentTask(task) .createActivityCount(1) .setOrganizer(mOrganizer) .setFragmentToken(new Binder()) .build(); final TaskFragment tf1 = new TaskFragmentBuilder(mAtm) .setParentTask(task) .createActivityCount(1) .setOrganizer(mOrganizer) .setFragmentToken(new Binder()) .build(); final ActivityRecord activity0 = tf0.getTopMostActivity(); final ActivityRecord activity1 = tf1.getTopMostActivity(); final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, activity0, "win0"); final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity1, "win1"); doReturn(false).when(mDisplayContent).shouldImeAttachedToApp(); mDisplayContent.setImeInputTarget(win0); mDisplayContent.setImeLayeringTarget(win1); // The ImeParent should be the display. assertEquals(mDisplayContent.getImeContainer().getParent().getSurfaceControl(), mDisplayContent.computeImeParent()); } }