Merge "Add the IME insets to virtual display for bubble" into rvc-dev
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 1098fa1..635ed13 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -29,6 +29,7 @@
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 @@
}
/**
+ * @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 2ead37a..4257ce0 100644
--- a/core/java/android/window/TaskEmbedder.java
+++ b/core/java/android/window/TaskEmbedder.java
@@ -23,7 +23,6 @@
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.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 @@
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 1c0598b..6f85dc2 100644
--- a/core/java/android/window/VirtualDisplayTaskEmbedder.java
+++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java
@@ -251,6 +251,14 @@
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 e367927..b3c2c6d 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 @@
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.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 @@
*/
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 @@
private WindowManager mWindowManager;
private BubbleStackView mStackView;
+ private View mVirtualImeView;
+ private WindowManager mVirtualDisplayWindowManager;
+ private boolean mImeShowing = false;
private ActivityView.StateCallback mStateCallback = new ActivityView.StateCallback() {
@Override
@@ -317,11 +330,8 @@
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));
}
@@ -365,18 +375,61 @@
: 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;
}
@@ -570,4 +623,11 @@
}
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 e109ded..9868446 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5640,6 +5640,11 @@
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 bbc6c2b..42c1a07 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 @@
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 351743f..56986c2 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.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 @@
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 @@
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 @@
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 f831287..2444c24 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 @@
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());