Merge "Add the IME insets to virtual display for bubble" into rvc-dev am: 75c82108f6

Change-Id: Ic4d3d31a5e332ca31cf85d0da380da9f19961810
This commit is contained in:
TreeHugger Robot
2020-05-01 04:14:30 +00:00
committed by Automerger Merge Worker
8 changed files with 113 additions and 16 deletions

View File

@@ -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.

View File

@@ -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.
*

View File

@@ -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.

View File

@@ -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
@@ -317,11 +330,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));
}
@@ -365,18 +375,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;
}
@@ -570,4 +623,11 @@ public class BubbleExpandedView extends LinearLayout {
}
return INVALID_DISPLAY;
}
private VirtualDisplay getVirtualDisplay() {
if (usingActivityView()) {
return mActivityView.getVirtualDisplay();
}
return null;
}
}

View File

@@ -5640,6 +5640,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
Slog.w(TAG, "Failed to deliver showInsets", e);
}
}
@Override
public boolean isClientControlled() {
return false;
}
}
/**

View File

@@ -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;
}
}

View File

@@ -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()));
}
}

View File

@@ -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());