diff options
| author | 2023-02-21 05:50:10 +0000 | |
|---|---|---|
| committer | 2023-02-21 05:50:10 +0000 | |
| commit | fb499317753c716178e42738ba8ef480cb47bf91 (patch) | |
| tree | cc8de5f422817f8766b369c4c95db4dadda18d32 | |
| parent | da896af69141ccfa25a92a8e45ce012b8b01041e (diff) | |
| parent | 44cab45149892f1438e077c38a51286783a1ced6 (diff) | |
Merge "Fix wrong ime parent in embedded activity" into udc-dev
3 files changed, 63 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8cd22fe71db5..ade2fe7152c0 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -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; } diff --git a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java index 49218ad07dff..471bdf224b59 100644 --- a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java +++ b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java @@ -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; @@ -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; } @@ -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()); @@ -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; + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index dab842c4aa5a..df3af7d2f4fa 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -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; @@ -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()); + } } |