summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java3
-rw-r--r--services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java53
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java31
3 files changed, 82 insertions, 5 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index de7c867bb9e1..dfa1a62ff506 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4589,8 +4589,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
@VisibleForTesting
SurfaceControl computeImeParent() {
- if (!ImeTargetVisibilityPolicy.isReadyToComputeImeParent(mImeLayeringTarget,
- mImeInputTarget)) {
+ if (!ImeTargetVisibilityPolicy.canComputeImeParent(mImeLayeringTarget, mImeInputTarget)) {
return null;
}
// Attach it to app if the target is part of an app and such app is covering the entire
diff --git a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
index 49218ad07dff..71dd91785384 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,13 +51,18 @@ 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 canComputeImeParent(@Nullable WindowState imeLayeringTarget,
+ @Nullable InputTarget imeInputTarget) {
if (imeLayeringTarget == null) {
return false;
}
+ if (shouldComputeImeParentForEmbeddedActivity(imeLayeringTarget, imeInputTarget)) {
+ return true;
+ }
// Ensure changing the IME parent when the layering target that may use IME has
// became to the input target for preventing IME flickers.
// Note that:
@@ -69,7 +75,6 @@ public abstract class ImeTargetVisibilityPolicy {
boolean imeLayeringTargetMayUseIme =
WindowManager.LayoutParams.mayUseInputMethod(imeLayeringTarget.mAttrs.flags)
|| imeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING;
-
// Do not change parent if the window hasn't requested IME.
var inputAndLayeringTargetsDisagree = (imeInputTarget == null
|| imeLayeringTarget.mActivityRecord != imeInputTarget.getActivityRecord());
@@ -77,4 +82,46 @@ public abstract class ImeTargetVisibilityPolicy {
return !inputTargetStale;
}
+
+
+ /**
+ * Called from {@link DisplayContent#computeImeParent()} to check the given IME targets if the
+ * IME surface parent should be updated in ActivityEmbeddings.
+ *
+ * As the IME layering target is calculated according to the window hierarchy by
+ * {@link DisplayContent#computeImeTarget}, the layering target and input target may be
+ * different when the window hasn't started input connection, WindowManagerService hasn't yet
+ * received the input target which reported from InputMethodManagerService. To make the IME
+ * surface will be shown on the best fit IME layering target, we basically won't update IME
+ * parent until both IME input and layering target updated for better IME transition.
+ *
+ * However, in activity embedding, tapping a window won't update it to the top window so the
+ * calculated IME layering target may higher than input target. Update IME parent for this case.
+ *
+ * @return {@code true} means the layer of IME layering target is higher than the input target
+ * and {@link DisplayContent#computeImeParent()} should keep progressing to update the IME
+ * surface parent on the display in case the IME surface left behind.
+ */
+ private static boolean shouldComputeImeParentForEmbeddedActivity(
+ @Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) {
+ if (imeInputTarget == null || imeLayeringTarget == null) {
+ return false;
+ }
+ final WindowState inputTargetWindow = imeInputTarget.getWindowState();
+ if (inputTargetWindow == null || !imeLayeringTarget.isAttached()
+ || !inputTargetWindow.isAttached()) {
+ return false;
+ }
+
+ final ActivityRecord inputTargetRecord = imeInputTarget.getActivityRecord();
+ final ActivityRecord layeringTargetRecord = imeLayeringTarget.getActivityRecord();
+ if (inputTargetRecord == null || layeringTargetRecord == null
+ || inputTargetRecord == layeringTargetRecord
+ || (inputTargetRecord.getTask() != layeringTargetRecord.getTask())
+ || !inputTargetRecord.isEmbedded() || !layeringTargetRecord.isEmbedded()) {
+ // Check whether the input target and layering target are embedded in the same Task.
+ return false;
+ }
+ return 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());
+ }
}