From b83940c9e77e48c11423953dc8dcda40c9b2c7c3 Mon Sep 17 00:00:00 2001 From: Yunfan Chen Date: Mon, 6 Apr 2020 16:43:09 +0900 Subject: [PATCH] Add the IME insets to virtual display for bubble This patch will add a fake IME window to virtual display when IME is showing and covering a bubble window. Without the fake window, the bubble will not receive the correct IME insets. To do that, this patch: 1. Added an interface in ActivityView to get VirtualDisplay when needed, in order to create the display context. 2. Modify the visibility update. When the target is not a client controlled target, we ignore the client visibility. We also call visibility update when the control target updated. 3. With the modified infra, add the window with correct param and context. Bug: 150780413 Test: atest WmTests:DisplayPolicyLayoutTests Test: atest InsetsStateTest Test: atest InsetsPolicyTest Test: go/wm-smoke Test: See reproduce steps in the bug Change-Id: I52691b5c7f81261de580bb4fc762e88486e78141 --- core/java/android/app/ActivityView.java | 9 +++ core/java/android/window/TaskEmbedder.java | 8 +- .../window/VirtualDisplayTaskEmbedder.java | 8 ++ .../systemui/bubbles/BubbleExpandedView.java | 78 ++++++++++++++++--- .../com/android/server/wm/DisplayContent.java | 5 ++ .../server/wm/InsetsControlTarget.java | 8 ++ .../server/wm/InsetsSourceProvider.java | 11 ++- .../android/server/wm/InsetsPolicyTest.java | 2 +- 8 files changed, 113 insertions(+), 16 deletions(-) diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 1098fa1753361..635ed138cc65e 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -29,6 +29,7 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; +import android.hardware.display.VirtualDisplay; import android.os.Bundle; import android.os.UserHandle; import android.util.AttributeSet; @@ -443,6 +444,14 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd return mTaskEmbedder.getDisplayId(); } + /** + * @hide + * @return virtual display. + */ + public VirtualDisplay getVirtualDisplay() { + return mTaskEmbedder.getVirtualDisplay(); + } + /** * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the * virtual display. diff --git a/core/java/android/window/TaskEmbedder.java b/core/java/android/window/TaskEmbedder.java index 2ead37a9397dc..4257ce0848290 100644 --- a/core/java/android/window/TaskEmbedder.java +++ b/core/java/android/window/TaskEmbedder.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityOptions; import android.app.ActivityTaskManager; -import android.app.ActivityView; import android.app.IActivityTaskManager; import android.app.PendingIntent; import android.content.ComponentName; @@ -36,9 +35,8 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; -import android.os.RemoteException; +import android.hardware.display.VirtualDisplay; import android.os.UserHandle; -import android.util.Log; import android.view.IWindow; import android.view.IWindowManager; import android.view.KeyEvent; @@ -256,6 +254,10 @@ public abstract class TaskEmbedder { return INVALID_DISPLAY; } + public VirtualDisplay getVirtualDisplay() { + return null; + } + /** * Set forwarded insets on the task content. * diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java index 1c0598b1d2164..6f85dc263a4d1 100644 --- a/core/java/android/window/VirtualDisplayTaskEmbedder.java +++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java @@ -251,6 +251,14 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { return INVALID_DISPLAY; } + @Override + public VirtualDisplay getVirtualDisplay() { + if (isInitialized()) { + return mVirtualDisplay; + } + return null; + } + /** * Check if container is ready to launch and create {@link ActivityOptions} to target the * virtual display. diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index bb2365559f74a..07db3bef3dc19 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -19,9 +19,15 @@ package com.android.systemui.bubbles; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; +import static android.graphics.PixelFormat.TRANSPARENT; import static android.view.Display.INVALID_DISPLAY; +import static android.view.InsetsState.ITYPE_IME; import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL; import static android.view.ViewRootImpl.sNewInsetsMode; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; +import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; +import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_EXPANDED_VIEW; import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES; @@ -42,9 +48,12 @@ import android.graphics.Insets; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.ShapeDrawable; +import android.hardware.display.VirtualDisplay; +import android.os.Binder; import android.os.RemoteException; import android.util.AttributeSet; import android.util.Log; +import android.view.Gravity; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; @@ -62,6 +71,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; */ public class BubbleExpandedView extends LinearLayout { private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleExpandedView" : TAG_BUBBLES; + private static final String WINDOW_TITLE = "ImeInsetsWindowWithoutContent"; private enum ActivityViewStatus { // ActivityView is being initialized, cannot start an activity yet. @@ -107,6 +117,9 @@ public class BubbleExpandedView extends LinearLayout { private WindowManager mWindowManager; private BubbleStackView mStackView; + private View mVirtualImeView; + private WindowManager mVirtualDisplayWindowManager; + private boolean mImeShowing = false; private ActivityView.StateCallback mStateCallback = new ActivityView.StateCallback() { @Override @@ -316,11 +329,8 @@ public class BubbleExpandedView extends LinearLayout { mKeyboardVisible = false; mNeedsNewHeight = false; if (mActivityView != null) { - // TODO: Temporary hack to offset the view until we can properly inset Bubbles again. if (sNewInsetsMode == NEW_INSETS_MODE_FULL) { - mStackView.animate() - .setDuration(100) - .translationY(0); + setImeWindowToDisplay(0, 0); } else { mActivityView.setForwardedInsets(Insets.of(0, 0, 0, 0)); } @@ -364,18 +374,61 @@ public class BubbleExpandedView extends LinearLayout { : 0); final int insetsBottom = Math.max(activityViewBottom - keyboardTop, 0); - // TODO: Temporary hack to offset the view until we can properly inset Bubbles again. if (sNewInsetsMode == NEW_INSETS_MODE_FULL) { - mStackView.animate() - .setDuration(100) - .translationY(-insetsBottom) - .withEndAction(() -> mActivityView.onLocationChanged()); + setImeWindowToDisplay(getWidth(), insetsBottom); } else { mActivityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom)); } } } + private void setImeWindowToDisplay(int w, int h) { + if (getVirtualDisplayId() == INVALID_DISPLAY) { + return; + } + if (h == 0 || w == 0) { + if (mImeShowing) { + mVirtualImeView.setVisibility(GONE); + mImeShowing = false; + } + return; + } + final Context virtualDisplayContext = mContext.createDisplayContext( + getVirtualDisplay().getDisplay()); + + if (mVirtualDisplayWindowManager == null) { + mVirtualDisplayWindowManager = + (WindowManager) virtualDisplayContext.getSystemService(Context.WINDOW_SERVICE); + } + if (mVirtualImeView == null) { + mVirtualImeView = new View(virtualDisplayContext); + mVirtualImeView.setVisibility(VISIBLE); + mVirtualDisplayWindowManager.addView(mVirtualImeView, + getVirtualImeViewAttrs(w, h)); + } else { + mVirtualDisplayWindowManager.updateViewLayout(mVirtualImeView, + getVirtualImeViewAttrs(w, h)); + mVirtualImeView.setVisibility(VISIBLE); + } + + mImeShowing = true; + } + + private WindowManager.LayoutParams getVirtualImeViewAttrs(int w, int h) { + // To use TYPE_NAVIGATION_BAR_PANEL instead of TYPE_IME_BAR to bypass the IME window type + // token check when adding the window. + final WindowManager.LayoutParams attrs = + new WindowManager.LayoutParams(w, h, TYPE_NAVIGATION_BAR_PANEL, + FLAG_LAYOUT_NO_LIMITS | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, + TRANSPARENT); + attrs.gravity = Gravity.BOTTOM; + attrs.setTitle(WINDOW_TITLE); + attrs.token = new Binder(); + attrs.providesInsetsTypes = new int[]{ITYPE_IME}; + attrs.alpha = 0.0f; + return attrs; + } + void setStackView(BubbleStackView stackView) { mStackView = stackView; } @@ -569,4 +622,11 @@ public class BubbleExpandedView extends LinearLayout { } return INVALID_DISPLAY; } + + private VirtualDisplay getVirtualDisplay() { + if (usingActivityView()) { + return mActivityView.getVirtualDisplay(); + } + return null; + } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c41029b206515..68a7e681799a6 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5538,6 +5538,11 @@ class DisplayContent extends WindowContainer