Merge "Use new insets apis for determining the stable/system insets" into rvc-dev am: a1423286b2 am: 5a329f321f
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11739860 Change-Id: I105d4e8e673927b0d924d23cbd27c86344e34b51
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.internal.policy;
|
package com.android.internal.policy;
|
||||||
|
|
||||||
|
import android.graphics.Insets;
|
||||||
import android.graphics.RecordingCanvas;
|
import android.graphics.RecordingCanvas;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RenderNode;
|
import android.graphics.RenderNode;
|
||||||
@@ -69,16 +70,14 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
private ColorDrawable mNavigationBarColor;
|
private ColorDrawable mNavigationBarColor;
|
||||||
private boolean mOldFullscreen;
|
private boolean mOldFullscreen;
|
||||||
private boolean mFullscreen;
|
private boolean mFullscreen;
|
||||||
private final Rect mOldSystemInsets = new Rect();
|
private final Rect mOldSystemBarInsets = new Rect();
|
||||||
private final Rect mOldStableInsets = new Rect();
|
private final Rect mSystemBarInsets = new Rect();
|
||||||
private final Rect mSystemInsets = new Rect();
|
|
||||||
private final Rect mStableInsets = new Rect();
|
|
||||||
private final Rect mTmpRect = new Rect();
|
private final Rect mTmpRect = new Rect();
|
||||||
|
|
||||||
public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
|
public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
|
||||||
Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
|
Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
|
||||||
Drawable userCaptionBackgroundDrawable, int statusBarColor, int navigationBarColor,
|
Drawable userCaptionBackgroundDrawable, int statusBarColor, int navigationBarColor,
|
||||||
boolean fullscreen, Rect systemInsets, Rect stableInsets) {
|
boolean fullscreen, Insets systemBarInsets) {
|
||||||
setName("ResizeFrame");
|
setName("ResizeFrame");
|
||||||
|
|
||||||
mRenderer = renderer;
|
mRenderer = renderer;
|
||||||
@@ -95,10 +94,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
mTargetRect.set(initialBounds);
|
mTargetRect.set(initialBounds);
|
||||||
mFullscreen = fullscreen;
|
mFullscreen = fullscreen;
|
||||||
mOldFullscreen = fullscreen;
|
mOldFullscreen = fullscreen;
|
||||||
mSystemInsets.set(systemInsets);
|
mSystemBarInsets.set(systemBarInsets.toRect());
|
||||||
mStableInsets.set(stableInsets);
|
mOldSystemBarInsets.set(systemBarInsets.toRect());
|
||||||
mOldSystemInsets.set(systemInsets);
|
|
||||||
mOldStableInsets.set(stableInsets);
|
|
||||||
|
|
||||||
// Kick off our draw thread.
|
// Kick off our draw thread.
|
||||||
start();
|
start();
|
||||||
@@ -154,16 +151,13 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
*
|
*
|
||||||
* @param newTargetBounds The new target bounds.
|
* @param newTargetBounds The new target bounds.
|
||||||
* @param fullscreen Whether the window is currently drawing in fullscreen.
|
* @param fullscreen Whether the window is currently drawing in fullscreen.
|
||||||
* @param systemInsets The current visible system insets for the window.
|
* @param systemBarInsets The current visible system insets for the window.
|
||||||
* @param stableInsets The stable insets for the window.
|
|
||||||
*/
|
*/
|
||||||
public void setTargetRect(Rect newTargetBounds, boolean fullscreen, Rect systemInsets,
|
public void setTargetRect(Rect newTargetBounds, boolean fullscreen, Rect systemBarInsets) {
|
||||||
Rect stableInsets) {
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mFullscreen = fullscreen;
|
mFullscreen = fullscreen;
|
||||||
mTargetRect.set(newTargetBounds);
|
mTargetRect.set(newTargetBounds);
|
||||||
mSystemInsets.set(systemInsets);
|
mSystemBarInsets.set(systemBarInsets);
|
||||||
mStableInsets.set(stableInsets);
|
|
||||||
// Notify of a bounds change.
|
// Notify of a bounds change.
|
||||||
pingRenderLocked(false /* drawImmediate */);
|
pingRenderLocked(false /* drawImmediate */);
|
||||||
}
|
}
|
||||||
@@ -247,14 +241,12 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
mNewTargetRect.set(mTargetRect);
|
mNewTargetRect.set(mTargetRect);
|
||||||
if (!mNewTargetRect.equals(mOldTargetRect)
|
if (!mNewTargetRect.equals(mOldTargetRect)
|
||||||
|| mOldFullscreen != mFullscreen
|
|| mOldFullscreen != mFullscreen
|
||||||
|| !mStableInsets.equals(mOldStableInsets)
|
|| !mSystemBarInsets.equals(mOldSystemBarInsets)
|
||||||
|| !mSystemInsets.equals(mOldSystemInsets)
|
|
||||||
|| mReportNextDraw) {
|
|| mReportNextDraw) {
|
||||||
mOldFullscreen = mFullscreen;
|
mOldFullscreen = mFullscreen;
|
||||||
mOldTargetRect.set(mNewTargetRect);
|
mOldTargetRect.set(mNewTargetRect);
|
||||||
mOldSystemInsets.set(mSystemInsets);
|
mOldSystemBarInsets.set(mSystemBarInsets);
|
||||||
mOldStableInsets.set(mStableInsets);
|
redrawLocked(mNewTargetRect, mFullscreen);
|
||||||
redrawLocked(mNewTargetRect, mFullscreen, mSystemInsets, mStableInsets);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,11 +296,8 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
*
|
*
|
||||||
* @param newBounds The window bounds which needs to be drawn.
|
* @param newBounds The window bounds which needs to be drawn.
|
||||||
* @param fullscreen Whether the window is currently drawing in fullscreen.
|
* @param fullscreen Whether the window is currently drawing in fullscreen.
|
||||||
* @param systemInsets The current visible system insets for the window.
|
|
||||||
* @param stableInsets The stable insets for the window.
|
|
||||||
*/
|
*/
|
||||||
private void redrawLocked(Rect newBounds, boolean fullscreen, Rect systemInsets,
|
private void redrawLocked(Rect newBounds, boolean fullscreen) {
|
||||||
Rect stableInsets) {
|
|
||||||
|
|
||||||
// While a configuration change is taking place the view hierarchy might become
|
// While a configuration change is taking place the view hierarchy might become
|
||||||
// inaccessible. For that case we remember the previous metrics to avoid flashes.
|
// inaccessible. For that case we remember the previous metrics to avoid flashes.
|
||||||
@@ -355,7 +344,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
}
|
}
|
||||||
mFrameAndBackdropNode.endRecording();
|
mFrameAndBackdropNode.endRecording();
|
||||||
|
|
||||||
drawColorViews(left, top, width, height, fullscreen, systemInsets, stableInsets);
|
drawColorViews(left, top, width, height, fullscreen);
|
||||||
|
|
||||||
// We need to render the node explicitly
|
// We need to render the node explicitly
|
||||||
mRenderer.drawRenderNode(mFrameAndBackdropNode);
|
mRenderer.drawRenderNode(mFrameAndBackdropNode);
|
||||||
@@ -363,14 +352,13 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
reportDrawIfNeeded();
|
reportDrawIfNeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawColorViews(int left, int top, int width, int height,
|
private void drawColorViews(int left, int top, int width, int height, boolean fullscreen) {
|
||||||
boolean fullscreen, Rect systemInsets, Rect stableInsets) {
|
|
||||||
if (mSystemBarBackgroundNode == null) {
|
if (mSystemBarBackgroundNode == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RecordingCanvas canvas = mSystemBarBackgroundNode.beginRecording(width, height);
|
RecordingCanvas canvas = mSystemBarBackgroundNode.beginRecording(width, height);
|
||||||
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
|
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
|
||||||
final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
|
final int topInset = mSystemBarInsets.top;
|
||||||
if (mStatusBarColor != null) {
|
if (mStatusBarColor != null) {
|
||||||
mStatusBarColor.setBounds(0, 0, left + width, topInset);
|
mStatusBarColor.setBounds(0, 0, left + width, topInset);
|
||||||
mStatusBarColor.draw(canvas);
|
mStatusBarColor.draw(canvas);
|
||||||
@@ -380,7 +368,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
|
|||||||
// don't want the navigation bar background be moving around when resizing in docked mode.
|
// don't want the navigation bar background be moving around when resizing in docked mode.
|
||||||
// However, we need it for the transitions into/out of docked mode.
|
// However, we need it for the transitions into/out of docked mode.
|
||||||
if (mNavigationBarColor != null && fullscreen) {
|
if (mNavigationBarColor != null && fullscreen) {
|
||||||
DecorView.getNavigationBarRect(width, height, stableInsets, systemInsets, mTmpRect, 1f);
|
DecorView.getNavigationBarRect(width, height, mSystemBarInsets, mTmpRect, 1f);
|
||||||
mNavigationBarColor.setBounds(mTmpRect);
|
mNavigationBarColor.setBounds(mTmpRect);
|
||||||
mNavigationBarColor.draw(canvas);
|
mNavigationBarColor.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1050,22 +1050,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getColorViewTopInset(int stableTop, int systemTop) {
|
|
||||||
return Math.min(stableTop, systemTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getColorViewBottomInset(int stableBottom, int systemBottom) {
|
|
||||||
return Math.min(stableBottom, systemBottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getColorViewRightInset(int stableRight, int systemRight) {
|
|
||||||
return Math.min(stableRight, systemRight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getColorViewLeftInset(int stableLeft, int systemLeft) {
|
|
||||||
return Math.min(stableLeft, systemLeft);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
|
public static boolean isNavBarToRightEdge(int bottomInset, int rightInset) {
|
||||||
return bottomInset == 0 && rightInset > 0;
|
return bottomInset == 0 && rightInset > 0;
|
||||||
}
|
}
|
||||||
@@ -1079,14 +1063,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
: isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset;
|
: isNavBarToLeftEdge(bottomInset, leftInset) ? leftInset : bottomInset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect stableInsets,
|
public static void getNavigationBarRect(int canvasWidth, int canvasHeight, Rect systemBarInsets,
|
||||||
Rect contentInsets, Rect outRect, float scale) {
|
Rect outRect, float scale) {
|
||||||
final int bottomInset =
|
final int bottomInset = (int) (systemBarInsets.bottom * scale);
|
||||||
(int) (getColorViewBottomInset(stableInsets.bottom, contentInsets.bottom) * scale);
|
final int leftInset = (int) (systemBarInsets.left * scale);
|
||||||
final int leftInset =
|
final int rightInset = (int) (systemBarInsets.right * scale);
|
||||||
(int) (getColorViewLeftInset(stableInsets.left, contentInsets.left) * scale);
|
|
||||||
final int rightInset =
|
|
||||||
(int) (getColorViewLeftInset(stableInsets.right, contentInsets.right) * scale);
|
|
||||||
final int size = getNavBarSize(bottomInset, rightInset, leftInset);
|
final int size = getNavBarSize(bottomInset, rightInset, leftInset);
|
||||||
if (isNavBarToRightEdge(bottomInset, rightInset)) {
|
if (isNavBarToRightEdge(bottomInset, rightInset)) {
|
||||||
outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
|
outRect.set(canvasWidth - size, 0, canvasWidth, canvasHeight);
|
||||||
@@ -1113,31 +1094,30 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
mLastWindowFlags = attrs.flags;
|
mLastWindowFlags = attrs.flags;
|
||||||
|
|
||||||
if (insets != null) {
|
if (insets != null) {
|
||||||
mLastTopInset = getColorViewTopInset(insets.getStableInsetTop(),
|
final Insets systemBarInsets = insets.getInsets(WindowInsets.Type.systemBars());
|
||||||
insets.getSystemWindowInsetTop());
|
final Insets stableBarInsets = insets.getInsetsIgnoringVisibility(
|
||||||
mLastBottomInset = getColorViewBottomInset(insets.getStableInsetBottom(),
|
WindowInsets.Type.systemBars());
|
||||||
insets.getSystemWindowInsetBottom());
|
mLastTopInset = systemBarInsets.top;
|
||||||
mLastRightInset = getColorViewRightInset(insets.getStableInsetRight(),
|
mLastBottomInset = systemBarInsets.bottom;
|
||||||
insets.getSystemWindowInsetRight());
|
mLastRightInset = systemBarInsets.right;
|
||||||
mLastLeftInset = getColorViewRightInset(insets.getStableInsetLeft(),
|
mLastLeftInset = systemBarInsets.left;
|
||||||
insets.getSystemWindowInsetLeft());
|
|
||||||
|
|
||||||
// Don't animate if the presence of stable insets has changed, because that
|
// Don't animate if the presence of stable insets has changed, because that
|
||||||
// indicates that the window was either just added and received them for the
|
// indicates that the window was either just added and received them for the
|
||||||
// first time, or the window size or position has changed.
|
// first time, or the window size or position has changed.
|
||||||
boolean hasTopStableInset = insets.getStableInsetTop() != 0;
|
boolean hasTopStableInset = stableBarInsets.top != 0;
|
||||||
disallowAnimate |= (hasTopStableInset != mLastHasTopStableInset);
|
disallowAnimate |= (hasTopStableInset != mLastHasTopStableInset);
|
||||||
mLastHasTopStableInset = hasTopStableInset;
|
mLastHasTopStableInset = hasTopStableInset;
|
||||||
|
|
||||||
boolean hasBottomStableInset = insets.getStableInsetBottom() != 0;
|
boolean hasBottomStableInset = stableBarInsets.bottom != 0;
|
||||||
disallowAnimate |= (hasBottomStableInset != mLastHasBottomStableInset);
|
disallowAnimate |= (hasBottomStableInset != mLastHasBottomStableInset);
|
||||||
mLastHasBottomStableInset = hasBottomStableInset;
|
mLastHasBottomStableInset = hasBottomStableInset;
|
||||||
|
|
||||||
boolean hasRightStableInset = insets.getStableInsetRight() != 0;
|
boolean hasRightStableInset = stableBarInsets.right != 0;
|
||||||
disallowAnimate |= (hasRightStableInset != mLastHasRightStableInset);
|
disallowAnimate |= (hasRightStableInset != mLastHasRightStableInset);
|
||||||
mLastHasRightStableInset = hasRightStableInset;
|
mLastHasRightStableInset = hasRightStableInset;
|
||||||
|
|
||||||
boolean hasLeftStableInset = insets.getStableInsetLeft() != 0;
|
boolean hasLeftStableInset = stableBarInsets.left != 0;
|
||||||
disallowAnimate |= (hasLeftStableInset != mLastHasLeftStableInset);
|
disallowAnimate |= (hasLeftStableInset != mLastHasLeftStableInset);
|
||||||
mLastHasLeftStableInset = hasLeftStableInset;
|
mLastHasLeftStableInset = hasLeftStableInset;
|
||||||
|
|
||||||
@@ -2296,7 +2276,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
|
public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
|
||||||
Rect stableInsets) {
|
Rect stableInsets) {
|
||||||
if (mBackdropFrameRenderer != null) {
|
if (mBackdropFrameRenderer != null) {
|
||||||
mBackdropFrameRenderer.setTargetRect(newBounds, fullscreen, systemInsets, stableInsets);
|
mBackdropFrameRenderer.setTargetRect(newBounds, fullscreen, systemInsets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2314,11 +2294,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
|
|||||||
final ThreadedRenderer renderer = getThreadedRenderer();
|
final ThreadedRenderer renderer = getThreadedRenderer();
|
||||||
if (renderer != null) {
|
if (renderer != null) {
|
||||||
loadBackgroundDrawablesIfNeeded();
|
loadBackgroundDrawablesIfNeeded();
|
||||||
|
WindowInsets rootInsets = getRootWindowInsets();
|
||||||
mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
|
mBackdropFrameRenderer = new BackdropFrameRenderer(this, renderer,
|
||||||
initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
|
initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
|
||||||
mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
|
mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
|
||||||
getCurrentColor(mNavigationColorViewState), fullscreen, systemInsets,
|
getCurrentColor(mNavigationColorViewState), fullscreen,
|
||||||
stableInsets);
|
rootInsets.getInsets(WindowInsets.Type.systemBars()));
|
||||||
|
|
||||||
// Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
|
// Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
|
||||||
// If we want to get the shadow shown while resizing, we would need to elevate a new
|
// If we want to get the shadow shown while resizing, we would need to elevate a new
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.app.ActivityManager.TaskSnapshot;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.GraphicBuffer;
|
import android.graphics.GraphicBuffer;
|
||||||
|
import android.graphics.Insets;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.RecordingCanvas;
|
import android.graphics.RecordingCanvas;
|
||||||
@@ -37,8 +38,11 @@ import android.os.Environment;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.view.InsetsSource;
|
||||||
|
import android.view.InsetsState;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.ThreadedRenderer;
|
import android.view.ThreadedRenderer;
|
||||||
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowManager.LayoutParams;
|
import android.view.WindowManager.LayoutParams;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -475,9 +479,12 @@ class TaskSnapshotController {
|
|||||||
final int color = ColorUtils.setAlphaComponent(
|
final int color = ColorUtils.setAlphaComponent(
|
||||||
task.getTaskDescription().getBackgroundColor(), 255);
|
task.getTaskDescription().getBackgroundColor(), 255);
|
||||||
final LayoutParams attrs = mainWindow.getAttrs();
|
final LayoutParams attrs = mainWindow.getAttrs();
|
||||||
|
final InsetsPolicy insetsPolicy = mainWindow.getDisplayContent().getInsetsPolicy();
|
||||||
|
final InsetsState insetsState = insetsPolicy.getInsetsForDispatch(mainWindow);
|
||||||
|
final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrameLw(), insetsState);
|
||||||
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
|
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
|
||||||
attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription(),
|
attrs.privateFlags, attrs.systemUiVisibility, task.getTaskDescription(),
|
||||||
mHighResTaskSnapshotScale, mainWindow.getRequestedInsetsState());
|
mHighResTaskSnapshotScale, insetsState);
|
||||||
final int taskWidth = task.getBounds().width();
|
final int taskWidth = task.getBounds().width();
|
||||||
final int taskHeight = task.getBounds().height();
|
final int taskHeight = task.getBounds().height();
|
||||||
final int width = (int) (taskWidth * mHighResTaskSnapshotScale);
|
final int width = (int) (taskWidth * mHighResTaskSnapshotScale);
|
||||||
@@ -488,7 +495,7 @@ class TaskSnapshotController {
|
|||||||
node.setClipToBounds(false);
|
node.setClipToBounds(false);
|
||||||
final RecordingCanvas c = node.start(width, height);
|
final RecordingCanvas c = node.start(width, height);
|
||||||
c.drawColor(color);
|
c.drawColor(color);
|
||||||
decorPainter.setInsets(mainWindow.getContentInsets(), mainWindow.getStableInsets());
|
decorPainter.setInsets(systemBarInsets);
|
||||||
decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
|
decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
|
||||||
node.end(c);
|
node.end(c);
|
||||||
final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
|
final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
|
||||||
@@ -593,6 +600,13 @@ class TaskSnapshotController {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Rect getSystemBarInsets(Rect frame, InsetsState state) {
|
||||||
|
return state.calculateInsets(frame, null /* ignoringVisibilityState */,
|
||||||
|
false /* isScreenRound */, false /* alwaysConsumeSystemBars */,
|
||||||
|
null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacySystemUiFlags */,
|
||||||
|
null /* typeSideMap */).getInsets(WindowInsets.Type.systemBars()).toRect();
|
||||||
|
}
|
||||||
|
|
||||||
void dump(PrintWriter pw, String prefix) {
|
void dump(PrintWriter pw, String prefix) {
|
||||||
pw.println(prefix + "mHighResTaskSnapshotScale=" + mHighResTaskSnapshotScale);
|
pw.println(prefix + "mHighResTaskSnapshotScale=" + mHighResTaskSnapshotScale);
|
||||||
mCache.dump(pw, prefix);
|
mCache.dump(pw, prefix);
|
||||||
|
|||||||
@@ -39,10 +39,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
|||||||
|
|
||||||
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
|
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
|
||||||
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
|
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
|
||||||
import static com.android.internal.policy.DecorView.getColorViewLeftInset;
|
|
||||||
import static com.android.internal.policy.DecorView.getColorViewTopInset;
|
|
||||||
import static com.android.internal.policy.DecorView.getNavigationBarRect;
|
import static com.android.internal.policy.DecorView.getNavigationBarRect;
|
||||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
|
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
|
||||||
|
import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
|
||||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||||
|
|
||||||
@@ -131,9 +130,8 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
private final IWindowSession mSession;
|
private final IWindowSession mSession;
|
||||||
private final WindowManagerService mService;
|
private final WindowManagerService mService;
|
||||||
private final Rect mTaskBounds;
|
private final Rect mTaskBounds;
|
||||||
private final Rect mStableInsets = new Rect();
|
|
||||||
private final Rect mContentInsets = new Rect();
|
|
||||||
private final Rect mFrame = new Rect();
|
private final Rect mFrame = new Rect();
|
||||||
|
private final Rect mSystemBarInsets = new Rect();
|
||||||
private TaskSnapshot mSnapshot;
|
private TaskSnapshot mSnapshot;
|
||||||
private final RectF mTmpSnapshotSize = new RectF();
|
private final RectF mTmpSnapshotSize = new RectF();
|
||||||
private final RectF mTmpDstFrame = new RectF();
|
private final RectF mTmpDstFrame = new RectF();
|
||||||
@@ -174,6 +172,7 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
final int windowFlags;
|
final int windowFlags;
|
||||||
final int windowPrivateFlags;
|
final int windowPrivateFlags;
|
||||||
final int currentOrientation;
|
final int currentOrientation;
|
||||||
|
final InsetsState insetsState;
|
||||||
synchronized (service.mGlobalLock) {
|
synchronized (service.mGlobalLock) {
|
||||||
final WindowState mainWindow = activity.findMainWindow();
|
final WindowState mainWindow = activity.findMainWindow();
|
||||||
final Task task = activity.getTask();
|
final Task task = activity.getTask();
|
||||||
@@ -241,6 +240,10 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
taskBounds = new Rect();
|
taskBounds = new Rect();
|
||||||
task.getBounds(taskBounds);
|
task.getBounds(taskBounds);
|
||||||
currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
|
currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
|
||||||
|
|
||||||
|
final InsetsPolicy insetsPolicy = topFullscreenOpaqueWindow.getDisplayContent()
|
||||||
|
.getInsetsPolicy();
|
||||||
|
insetsState = insetsPolicy.getInsetsForDispatch(topFullscreenOpaqueWindow);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
|
final int res = session.addToDisplay(window, window.mSeq, layoutParams,
|
||||||
@@ -255,8 +258,7 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
}
|
}
|
||||||
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
|
final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, window,
|
||||||
surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
|
surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, sysUiVis,
|
||||||
windowFlags, windowPrivateFlags, taskBounds,
|
windowFlags, windowPrivateFlags, taskBounds, currentOrientation, insetsState);
|
||||||
currentOrientation, topFullscreenOpaqueWindow.getRequestedInsetsState());
|
|
||||||
window.setOuter(snapshotSurface);
|
window.setOuter(snapshotSurface);
|
||||||
try {
|
try {
|
||||||
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
|
session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
|
||||||
@@ -266,7 +268,9 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// Local call.
|
// Local call.
|
||||||
}
|
}
|
||||||
snapshotSurface.setFrames(tmpFrame, tmpContentInsets, tmpStableInsets);
|
|
||||||
|
final Rect systemBarInsets = getSystemBarInsets(tmpFrame, insetsState);
|
||||||
|
snapshotSurface.setFrames(tmpFrame, systemBarInsets);
|
||||||
snapshotSurface.drawSnapshot();
|
snapshotSurface.drawSnapshot();
|
||||||
return snapshotSurface;
|
return snapshotSurface;
|
||||||
}
|
}
|
||||||
@@ -315,13 +319,12 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void setFrames(Rect frame, Rect contentInsets, Rect stableInsets) {
|
void setFrames(Rect frame, Rect systemBarInsets) {
|
||||||
mFrame.set(frame);
|
mFrame.set(frame);
|
||||||
mContentInsets.set(contentInsets);
|
mSystemBarInsets.set(systemBarInsets);
|
||||||
mStableInsets.set(stableInsets);
|
|
||||||
mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
|
mSizeMismatch = (mFrame.width() != mSnapshot.getSnapshot().getWidth()
|
||||||
|| mFrame.height() != mSnapshot.getSnapshot().getHeight());
|
|| mFrame.height() != mSnapshot.getSnapshot().getHeight());
|
||||||
mSystemBarBackgroundPainter.setInsets(contentInsets, stableInsets);
|
mSystemBarBackgroundPainter.setInsets(systemBarInsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawSnapshot() {
|
private void drawSnapshot() {
|
||||||
@@ -453,9 +456,7 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// However, we also need to make space for the navigation bar on the left side.
|
// However, we also need to make space for the navigation bar on the left side.
|
||||||
final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
|
frame.offset(mSystemBarInsets.left, 0);
|
||||||
mContentInsets.left);
|
|
||||||
frame.offset(colorViewLeftInset, 0);
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,8 +541,6 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
*/
|
*/
|
||||||
static class SystemBarBackgroundPainter {
|
static class SystemBarBackgroundPainter {
|
||||||
|
|
||||||
private final Rect mContentInsets = new Rect();
|
|
||||||
private final Rect mStableInsets = new Rect();
|
|
||||||
private final Paint mStatusBarPaint = new Paint();
|
private final Paint mStatusBarPaint = new Paint();
|
||||||
private final Paint mNavigationBarPaint = new Paint();
|
private final Paint mNavigationBarPaint = new Paint();
|
||||||
private final int mStatusBarColor;
|
private final int mStatusBarColor;
|
||||||
@@ -551,6 +550,7 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
private final int mSysUiVis;
|
private final int mSysUiVis;
|
||||||
private final float mScale;
|
private final float mScale;
|
||||||
private final InsetsState mInsetsState;
|
private final InsetsState mInsetsState;
|
||||||
|
private final Rect mSystemBarInsets = new Rect();
|
||||||
|
|
||||||
SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int sysUiVis,
|
SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int sysUiVis,
|
||||||
TaskDescription taskDescription, float scale, InsetsState insetsState) {
|
TaskDescription taskDescription, float scale, InsetsState insetsState) {
|
||||||
@@ -576,9 +576,8 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
mInsetsState = insetsState;
|
mInsetsState = insetsState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInsets(Rect contentInsets, Rect stableInsets) {
|
void setInsets(Rect systemBarInsets) {
|
||||||
mContentInsets.set(contentInsets);
|
mSystemBarInsets.set(systemBarInsets);
|
||||||
mStableInsets.set(stableInsets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int getStatusBarColorViewHeight() {
|
int getStatusBarColorViewHeight() {
|
||||||
@@ -589,7 +588,7 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)
|
mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)
|
||||||
: STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
|
: STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
|
||||||
mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
|
mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
|
||||||
return (int) (getColorViewTopInset(mStableInsets.top, mContentInsets.top) * mScale);
|
return (int) (mSystemBarInsets.top * mScale);
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -615,8 +614,7 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
int statusBarHeight) {
|
int statusBarHeight) {
|
||||||
if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
|
if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
|
||||||
&& (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
|
&& (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
|
||||||
final int rightInset = (int) (DecorView.getColorViewRightInset(mStableInsets.right,
|
final int rightInset = (int) (mSystemBarInsets.right * mScale);
|
||||||
mContentInsets.right) * mScale);
|
|
||||||
final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
|
final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
|
||||||
c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
|
c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
|
||||||
}
|
}
|
||||||
@@ -625,8 +623,8 @@ class TaskSnapshotSurface implements StartingSurface {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
void drawNavigationBarBackground(Canvas c) {
|
void drawNavigationBarBackground(Canvas c) {
|
||||||
final Rect navigationBarRect = new Rect();
|
final Rect navigationBarRect = new Rect();
|
||||||
getNavigationBarRect(c.getWidth(), c.getHeight(), mStableInsets, mContentInsets,
|
getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect,
|
||||||
navigationBarRect, mScale);
|
mScale);
|
||||||
final boolean visible = isNavigationBarColorViewVisible();
|
final boolean visible = isNavigationBarColorViewVisible();
|
||||||
if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
|
if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
|
||||||
c.drawRect(navigationBarRect, mNavigationBarPaint);
|
c.drawRect(navigationBarRect, mNavigationBarPaint);
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
public void testCalculateSnapshotFrame() {
|
public void testCalculateSnapshotFrame() {
|
||||||
setupSurface(100, 100);
|
setupSurface(100, 100);
|
||||||
final Rect insets = new Rect(0, 10, 0, 10);
|
final Rect insets = new Rect(0, 10, 0, 10);
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
assertEquals(new Rect(0, 0, 100, 80),
|
assertEquals(new Rect(0, 0, 100, 80),
|
||||||
mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
|
mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
|
||||||
}
|
}
|
||||||
@@ -199,7 +199,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
public void testCalculateSnapshotFrame_navBarLeft() {
|
public void testCalculateSnapshotFrame_navBarLeft() {
|
||||||
setupSurface(100, 100);
|
setupSurface(100, 100);
|
||||||
final Rect insets = new Rect(10, 10, 0, 0);
|
final Rect insets = new Rect(10, 10, 0, 0);
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
assertEquals(new Rect(10, 0, 100, 90),
|
assertEquals(new Rect(10, 0, 100, 90),
|
||||||
mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
|
mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
public void testCalculateSnapshotFrame_waterfall() {
|
public void testCalculateSnapshotFrame_waterfall() {
|
||||||
setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
|
setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
|
||||||
final Rect insets = new Rect(0, 10, 0, 10);
|
final Rect insets = new Rect(0, 10, 0, 10);
|
||||||
mSurface.setFrames(new Rect(5, 0, 95, 100), insets, insets);
|
mSurface.setFrames(new Rect(5, 0, 95, 100), insets);
|
||||||
assertEquals(new Rect(0, 0, 90, 90),
|
assertEquals(new Rect(0, 0, 90, 90),
|
||||||
mSurface.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
|
mSurface.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
public void testDrawStatusBarBackground() {
|
public void testDrawStatusBarBackground() {
|
||||||
setupSurface(100, 100);
|
setupSurface(100, 100);
|
||||||
final Rect insets = new Rect(0, 10, 10, 0);
|
final Rect insets = new Rect(0, 10, 10, 0);
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
final Canvas mockCanvas = mock(Canvas.class);
|
final Canvas mockCanvas = mock(Canvas.class);
|
||||||
when(mockCanvas.getWidth()).thenReturn(100);
|
when(mockCanvas.getWidth()).thenReturn(100);
|
||||||
when(mockCanvas.getHeight()).thenReturn(100);
|
when(mockCanvas.getHeight()).thenReturn(100);
|
||||||
@@ -230,7 +230,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
public void testDrawStatusBarBackground_nullFrame() {
|
public void testDrawStatusBarBackground_nullFrame() {
|
||||||
setupSurface(100, 100);
|
setupSurface(100, 100);
|
||||||
final Rect insets = new Rect(0, 10, 10, 0);
|
final Rect insets = new Rect(0, 10, 10, 0);
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
final Canvas mockCanvas = mock(Canvas.class);
|
final Canvas mockCanvas = mock(Canvas.class);
|
||||||
when(mockCanvas.getWidth()).thenReturn(100);
|
when(mockCanvas.getWidth()).thenReturn(100);
|
||||||
when(mockCanvas.getHeight()).thenReturn(100);
|
when(mockCanvas.getHeight()).thenReturn(100);
|
||||||
@@ -243,7 +243,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
public void testDrawStatusBarBackground_nope() {
|
public void testDrawStatusBarBackground_nope() {
|
||||||
setupSurface(100, 100);
|
setupSurface(100, 100);
|
||||||
final Rect insets = new Rect(0, 10, 10, 0);
|
final Rect insets = new Rect(0, 10, 10, 0);
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
final Canvas mockCanvas = mock(Canvas.class);
|
final Canvas mockCanvas = mock(Canvas.class);
|
||||||
when(mockCanvas.getWidth()).thenReturn(100);
|
when(mockCanvas.getWidth()).thenReturn(100);
|
||||||
when(mockCanvas.getHeight()).thenReturn(100);
|
when(mockCanvas.getHeight()).thenReturn(100);
|
||||||
@@ -257,7 +257,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
final Rect insets = new Rect(0, 10, 0, 10);
|
final Rect insets = new Rect(0, 10, 0, 10);
|
||||||
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
||||||
new Rect(0, 0, 100, 100));
|
new Rect(0, 0, 100, 100));
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
final Canvas mockCanvas = mock(Canvas.class);
|
final Canvas mockCanvas = mock(Canvas.class);
|
||||||
when(mockCanvas.getWidth()).thenReturn(100);
|
when(mockCanvas.getWidth()).thenReturn(100);
|
||||||
when(mockCanvas.getHeight()).thenReturn(100);
|
when(mockCanvas.getHeight()).thenReturn(100);
|
||||||
@@ -270,7 +270,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
final Rect insets = new Rect(10, 10, 0, 0);
|
final Rect insets = new Rect(10, 10, 0, 0);
|
||||||
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
||||||
new Rect(0, 0, 100, 100));
|
new Rect(0, 0, 100, 100));
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
final Canvas mockCanvas = mock(Canvas.class);
|
final Canvas mockCanvas = mock(Canvas.class);
|
||||||
when(mockCanvas.getWidth()).thenReturn(100);
|
when(mockCanvas.getWidth()).thenReturn(100);
|
||||||
when(mockCanvas.getHeight()).thenReturn(100);
|
when(mockCanvas.getHeight()).thenReturn(100);
|
||||||
@@ -283,7 +283,7 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
|
|||||||
final Rect insets = new Rect(0, 10, 10, 0);
|
final Rect insets = new Rect(0, 10, 10, 0);
|
||||||
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
|
||||||
new Rect(0, 0, 100, 100));
|
new Rect(0, 0, 100, 100));
|
||||||
mSurface.setFrames(new Rect(0, 0, 100, 100), insets, insets);
|
mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
|
||||||
final Canvas mockCanvas = mock(Canvas.class);
|
final Canvas mockCanvas = mock(Canvas.class);
|
||||||
when(mockCanvas.getWidth()).thenReturn(100);
|
when(mockCanvas.getWidth()).thenReturn(100);
|
||||||
when(mockCanvas.getHeight()).thenReturn(100);
|
when(mockCanvas.getHeight()).thenReturn(100);
|
||||||
|
|||||||
Reference in New Issue
Block a user