diff options
8 files changed, 113 insertions, 16 deletions
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index 1098fa175336..635ed138cc65 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; @@ -444,6 +445,14 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd } /** + * @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 2ead37a9397d..4257ce084829 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 1c0598b1d216..6f85dc263a4d 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 bb2365559f74..07db3bef3dc1 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 c41029b20651..68a7e681799a 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<DisplayContent.DisplayChildWindowCo Slog.w(TAG, "Failed to deliver showInsets", e); } } + + @Override + public boolean isClientControlled() { + return false; + } } /** diff --git a/services/core/java/com/android/server/wm/InsetsControlTarget.java b/services/core/java/com/android/server/wm/InsetsControlTarget.java index bbc6c2bd4bcd..42c1a078c7e8 100644 --- a/services/core/java/com/android/server/wm/InsetsControlTarget.java +++ b/services/core/java/com/android/server/wm/InsetsControlTarget.java @@ -61,4 +61,12 @@ interface InsetsControlTarget { default boolean canShowTransient() { return false; } + + /** + * Returns {@code true} if the object controlling the insets is on client. + */ + default boolean isClientControlled() { + return true; + } + } diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 351743f962b9..56986c2e7e41 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -38,6 +38,7 @@ import android.view.InsetsState; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.function.TriConsumer; import com.android.server.wm.SurfaceAnimator.AnimationType; import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; @@ -288,6 +289,7 @@ class InsetsSourceProvider { t.deferTransactionUntil(leash, barrier, frameNumber); } mControlTarget = target; + updateVisibility(); mControl = new InsetsSourceControl(mSource.getType(), leash, new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top)); } @@ -330,13 +332,16 @@ class InsetsSourceProvider { updateVisibility(); } - private void setServerVisible(boolean serverVisible) { + @VisibleForTesting + void setServerVisible(boolean serverVisible) { mServerVisible = serverVisible; updateVisibility(); } private void updateVisibility() { - mSource.setVisible(mServerVisible && mClientVisible); + final boolean isClientControlled = mControlTarget != null + && mControlTarget.isClientControlled(); + mSource.setVisible(mServerVisible && (!isClientControlled || mClientVisible)); } InsetsSourceControl getControl(InsetsControlTarget target) { @@ -408,10 +413,10 @@ class InsetsSourceProvider { public void onAnimationCancelled(SurfaceControl animationLeash) { if (mAdapter == this) { mStateController.notifyControlRevoked(mControlTarget, InsetsSourceProvider.this); - setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); mControl = null; mControlTarget = null; mAdapter = null; + setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index f83128705a2a..2444c24b5e4a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -221,7 +221,7 @@ public class InsetsPolicyTest extends WindowTestsBase { addNonFocusableWindow(TYPE_STATUS_BAR, "statusBar") .getControllableInsetProvider().getSource().setVisible(false); addNonFocusableWindow(TYPE_NAVIGATION_BAR, "navBar") - .getControllableInsetProvider().getSource().setVisible(true); + .getControllableInsetProvider().setServerVisible(true); final InsetsPolicy policy = spy(mDisplayContent.getInsetsPolicy()); doNothing().when(policy).startAnimation(anyBoolean(), any(), any()); |