From fa10423fa00f3495e451016acba9b6848eb995c9 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Fri, 20 Jun 2014 16:10:14 -0700 Subject: Add stable insets for stable system windows Adds a new kind of inset that only accounts for stable system windows like the system or navigation bar. Bug: 15457292 Change-Id: I681b711f6f40a94c25b7acd3a44eb3539486afab --- .../service/wallpaper/WallpaperService.java | 6 +- core/java/android/view/IWindow.aidl | 3 +- core/java/android/view/IWindowSession.aidl | 2 +- core/java/android/view/SurfaceView.java | 6 +- core/java/android/view/View.java | 7 ++ core/java/android/view/ViewRootImpl.java | 50 +++++++++---- core/java/android/view/WindowInsets.java | 81 +++++++++++++++++----- core/java/android/view/WindowManagerPolicy.java | 4 +- .../com/android/internal/view/BaseIWindow.java | 2 +- 9 files changed, 121 insertions(+), 40 deletions(-) (limited to 'core') diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 03ce4e0..f3c26c8 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -154,6 +154,7 @@ public abstract class WallpaperService extends Service { final Rect mWinFrame = new Rect(); final Rect mOverscanInsets = new Rect(); final Rect mContentInsets = new Rect(); + final Rect mStableInsets = new Rect(); final Configuration mConfiguration = new Configuration(); final WindowManager.LayoutParams mLayout @@ -253,7 +254,8 @@ public abstract class WallpaperService extends Service { final BaseIWindow mWindow = new BaseIWindow() { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, boolean reportDraw, Configuration newConfig) { + Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Configuration newConfig) { Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0); mCaller.sendMessage(msg); @@ -628,7 +630,7 @@ public abstract class WallpaperService extends Service { final int relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mConfiguration, mSurfaceHolder.mSurface); + mVisibleInsets, mStableInsets, mConfiguration, mSurfaceHolder.mSurface); if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface + ", frame=" + mWinFrame); diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 3670eed..3e7aae0 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -46,7 +46,8 @@ oneway interface IWindow { void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor); void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets, - in Rect visibleInsets, boolean reportDraw, in Configuration newConfig); + in Rect visibleInsets, in Rect stableInsets, boolean reportDraw, + in Configuration newConfig); void moved(int newX, int newY); void dispatchAppVisibility(boolean visible); void dispatchGetNewSurface(); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index fa5bd88..0f3f182 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -89,7 +89,7 @@ interface IWindowSession { int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, out Rect outFrame, out Rect outOverscanInsets, - out Rect outContentInsets, out Rect outVisibleInsets, + out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets, out Configuration outConfig, out Surface outSurface); /** diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 4a2cc1a..a2a4540 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -105,6 +105,7 @@ public class SurfaceView extends View { final Rect mWinFrame = new Rect(); final Rect mOverscanInsets = new Rect(); final Rect mContentInsets = new Rect(); + final Rect mStableInsets = new Rect(); final Configuration mConfiguration = new Configuration(); static final int KEEP_SCREEN_ON_MSG = 1; @@ -518,7 +519,7 @@ public class SurfaceView extends View { visible ? VISIBLE : GONE, WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mConfiguration, mNewSurface); + mVisibleInsets, mStableInsets, mConfiguration, mNewSurface); if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mReportDrawNeeded = true; } @@ -653,7 +654,8 @@ public class SurfaceView extends View { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, boolean reportDraw, Configuration newConfig) { + Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Configuration newConfig) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { if (DEBUG) Log.v( diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 33b6d6c..3b2e1d1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -19805,6 +19805,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final Rect mVisibleInsets = new Rect(); /** + * For windows that are full-screen but using insets to layout inside + * of the screen decorations, these are the current insets for the + * stable system windows. + */ + final Rect mStableInsets = new Rect(); + + /** * The internal insets given by this window. This value is * supplied by the client (through * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3219330..5def940 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -21,7 +21,6 @@ import android.animation.LayoutTransition; import android.app.ActivityManagerNative; import android.content.ClipDescription; import android.content.ComponentCallbacks; -import android.content.ComponentCallbacks2; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.CompatibilityInfo; @@ -205,7 +204,7 @@ public final class ViewRootImpl implements ViewParent, /** Set to true while in performTraversals for detecting when die(true) is called from internal * callbacks such as onMeasure, onPreDraw, onDraw and deferring doDie() until later. */ boolean mIsInTraversal; - boolean mFitSystemWindowsRequested; + boolean mApplyInsetsRequested; boolean mLayoutRequested; boolean mFirst; boolean mReportNextDraw; @@ -257,11 +256,13 @@ public final class ViewRootImpl implements ViewParent, final Rect mPendingOverscanInsets = new Rect(); final Rect mPendingVisibleInsets = new Rect(); + final Rect mPendingStableInsets = new Rect(); final Rect mPendingContentInsets = new Rect(); final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets = new ViewTreeObserver.InternalInsetsInfo(); - final Rect mFitSystemWindowsInsets = new Rect(); + final Rect mDispatchContentInsets = new Rect(); + final Rect mDispatchStableInsets = new Rect(); final Configuration mLastConfiguration = new Configuration(); final Configuration mPendingConfiguration = new Configuration(); @@ -532,6 +533,7 @@ public final class ViewRootImpl implements ViewParent, } mPendingOverscanInsets.set(0, 0, 0, 0); mPendingContentInsets.set(mAttachInfo.mContentInsets); + mPendingStableInsets.set(mAttachInfo.mStableInsets); mPendingVisibleInsets.set(0, 0, 0, 0); if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow); if (res < WindowManagerGlobal.ADD_OKAY) { @@ -816,7 +818,7 @@ public final class ViewRootImpl implements ViewParent, @Override public void requestFitSystemWindows() { checkThread(); - mFitSystemWindowsRequested = true; + mApplyInsetsRequested = true; scheduleTraversals(); } @@ -1161,7 +1163,8 @@ public final class ViewRootImpl implements ViewParent, } void dispatchApplyInsets(View host) { - mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets); + mDispatchContentInsets.set(mAttachInfo.mContentInsets); + mDispatchStableInsets.set(mAttachInfo.mStableInsets); boolean isRound = false; if ((mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN) != 0 && mDisplay.getDisplayId() == 0) { @@ -1171,7 +1174,8 @@ public final class ViewRootImpl implements ViewParent, com.android.internal.R.bool.config_windowIsRound); } host.dispatchApplyWindowInsets(new WindowInsets( - mFitSystemWindowsInsets, isRound)); + mDispatchContentInsets, null /* windowDecorInsets */, + mDispatchStableInsets, isRound)); } private void performTraversals() { @@ -1310,6 +1314,9 @@ public final class ViewRootImpl implements ViewParent, if (!mPendingContentInsets.equals(mAttachInfo.mContentInsets)) { insetsChanged = true; } + if (!mPendingStableInsets.equals(mAttachInfo.mStableInsets)) { + insetsChanged = true; + } if (!mPendingVisibleInsets.equals(mAttachInfo.mVisibleInsets)) { mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets); if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: " @@ -1383,8 +1390,8 @@ public final class ViewRootImpl implements ViewParent, & WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN) != 0; } - if (mFitSystemWindowsRequested) { - mFitSystemWindowsRequested = false; + if (mApplyInsetsRequested) { + mApplyInsetsRequested = false; mLastOverscanRequested = mAttachInfo.mOverscanRequested; dispatchApplyInsets(host); if (mLayoutRequested) { @@ -1469,6 +1476,7 @@ public final class ViewRootImpl implements ViewParent, + " overscan=" + mPendingOverscanInsets.toShortString() + " content=" + mPendingContentInsets.toShortString() + " visible=" + mPendingVisibleInsets.toShortString() + + " visible=" + mPendingStableInsets.toShortString() + " surface=" + mSurface); if (mPendingConfiguration.seq != 0) { @@ -1484,6 +1492,8 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mContentInsets); final boolean visibleInsetsChanged = !mPendingVisibleInsets.equals( mAttachInfo.mVisibleInsets); + final boolean stableInsetsChanged = !mPendingStableInsets.equals( + mAttachInfo.mStableInsets); if (contentInsetsChanged) { if (mWidth > 0 && mHeight > 0 && lp != null && ((lp.systemUiVisibility|lp.subtreeSystemUiVisibility) @@ -1558,12 +1568,19 @@ public final class ViewRootImpl implements ViewParent, // Need to relayout with content insets. contentInsetsChanged = true; } + if (stableInsetsChanged) { + mAttachInfo.mStableInsets.set(mPendingStableInsets); + if (DEBUG_LAYOUT) Log.v(TAG, "Decor insets changing to: " + + mAttachInfo.mStableInsets); + // Need to relayout with content insets. + contentInsetsChanged = true; + } if (contentInsetsChanged || mLastSystemUiVisibility != - mAttachInfo.mSystemUiVisibility || mFitSystemWindowsRequested + mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested || mLastOverscanRequested != mAttachInfo.mOverscanRequested) { mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility; mLastOverscanRequested = mAttachInfo.mOverscanRequested; - mFitSystemWindowsRequested = false; + mApplyInsetsRequested = false; dispatchApplyInsets(host); } if (visibleInsetsChanged) { @@ -3065,6 +3082,7 @@ public final class ViewRootImpl implements ViewParent, if (mWinFrame.equals(args.arg1) && mPendingOverscanInsets.equals(args.arg5) && mPendingContentInsets.equals(args.arg2) + && mPendingStableInsets.equals(args.arg6) && mPendingVisibleInsets.equals(args.arg3) && args.arg4 == null) { break; @@ -3082,6 +3100,7 @@ public final class ViewRootImpl implements ViewParent, mWinFrame.set((Rect) args.arg1); mPendingOverscanInsets.set((Rect) args.arg5); mPendingContentInsets.set((Rect) args.arg2); + mPendingStableInsets.set((Rect) args.arg6); mPendingVisibleInsets.set((Rect) args.arg3); args.recycle(); @@ -5167,7 +5186,7 @@ public final class ViewRootImpl implements ViewParent, (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, - mPendingConfiguration, mSurface); + mPendingStableInsets, mPendingConfiguration, mSurface); //Log.d(TAG, "<<<<<< BACK FROM relayout"); if (restore) { params.restore(); @@ -5178,6 +5197,7 @@ public final class ViewRootImpl implements ViewParent, mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets); mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets); mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets); + mTranslator.translateRectInScreenToAppWindow(mPendingStableInsets); } return relayoutResult; } @@ -5446,7 +5466,7 @@ public final class ViewRootImpl implements ViewParent, } public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, boolean reportDraw, Configuration newConfig) { + Rect visibleInsets, Rect stableInsets, boolean reportDraw, Configuration newConfig) { if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": frame=" + frame.toShortString() + " contentInsets=" + contentInsets.toShortString() + " visibleInsets=" + visibleInsets.toShortString() @@ -5465,6 +5485,7 @@ public final class ViewRootImpl implements ViewParent, args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets; args.arg4 = sameProcessCall && newConfig != null ? new Configuration(newConfig) : newConfig; args.arg5 = sameProcessCall ? new Rect(overscanInsets) : overscanInsets; + args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets; msg.obj = args; mHandler.sendMessage(msg); } @@ -6292,11 +6313,12 @@ public final class ViewRootImpl implements ViewParent, @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, boolean reportDraw, Configuration newConfig) { + Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Configuration newConfig) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(frame, overscanInsets, contentInsets, - visibleInsets, reportDraw, newConfig); + visibleInsets, stableInsets, reportDraw, newConfig); } } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 1d2f1bf..1832cc3 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -30,13 +30,16 @@ import android.graphics.Rect; * @see View#onApplyWindowInsets(WindowInsets) */ public final class WindowInsets { + private Rect mSystemWindowInsets; private Rect mWindowDecorInsets; + private Rect mStableInsets; private Rect mTempRect; private boolean mIsRound; private boolean mSystemWindowInsetsConsumed = false; private boolean mWindowDecorInsetsConsumed = false; + private boolean mStableInsetsConsumed = false; private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0); @@ -49,29 +52,21 @@ public final class WindowInsets { public static final WindowInsets CONSUMED; static { - CONSUMED = new WindowInsets(EMPTY_RECT, EMPTY_RECT); - CONSUMED.mSystemWindowInsetsConsumed = true; - CONSUMED.mWindowDecorInsetsConsumed = true; - } - - /** @hide */ - public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets) { - this(systemWindowInsets, windowDecorInsets, false); - } - - /** @hide */ - public WindowInsets(Rect systemWindowInsets, boolean isRound) { - this(systemWindowInsets, null, isRound); + CONSUMED = new WindowInsets(null, null, null, false); } /** @hide */ - public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, boolean isRound) { + public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets, + boolean isRound) { mSystemWindowInsetsConsumed = systemWindowInsets == null; mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets; mWindowDecorInsetsConsumed = windowDecorInsets == null; mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : windowDecorInsets; + mStableInsetsConsumed = stableInsets == null; + mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : stableInsets; + mIsRound = isRound; } @@ -83,14 +78,16 @@ public final class WindowInsets { public WindowInsets(WindowInsets src) { mSystemWindowInsets = src.mSystemWindowInsets; mWindowDecorInsets = src.mWindowDecorInsets; + mStableInsets = src.mStableInsets; mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed; mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed; + mStableInsetsConsumed = src.mStableInsetsConsumed; mIsRound = src.mIsRound; } /** @hide */ public WindowInsets(Rect systemWindowInsets) { - this(systemWindowInsets, null); + this(systemWindowInsets, null, null, false); } /** @@ -272,7 +269,7 @@ public final class WindowInsets { * @hide Pending API */ public boolean isConsumed() { - return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed; + return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed && mStableInsetsConsumed; } /** @@ -381,9 +378,57 @@ public final class WindowInsets { return result; } + /** + * @hide + */ + public int getStableInsetTop() { + return mStableInsets.top; + } + + /** + * @hide + */ + public int getStableInsetLeft() { + return mStableInsets.left; + } + + /** + * @hide + */ + public int getStableInsetRight() { + return mStableInsets.right; + } + + /** + * @hide + */ + public int getStableInsetBottom() { + return mStableInsets.bottom; + } + + /** + * @hide + */ + public boolean hasStableInsets() { + return mStableInsets.top != 0 || mStableInsets.left != 0 || mStableInsets.right != 0 + || mStableInsets.bottom != 0; + } + + /** + * @hide + */ + public WindowInsets consumeStableInsets() { + final WindowInsets result = new WindowInsets(this); + result.mStableInsets = EMPTY_RECT; + result.mStableInsetsConsumed = true; + return result; + } + @Override public String toString() { - return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets + " windowDecorInsets=" + - mWindowDecorInsets + (isRound() ? "round}" : "}"); + return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets + + " windowDecorInsets=" + mWindowDecorInsets + + " stableInsets=" + mStableInsets + + (isRound() ? " round}" : "}"); } } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 024600d..ee542a1 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -149,9 +149,11 @@ public interface WindowManagerPolicy { * are visible. * @param decorFrame The decor frame specified by policy specific to this window, * to use for proper cropping during animation. + * @param stableFrame The frame around which stable system decoration is positioned. */ public void computeFrameLw(Rect parentFrame, Rect displayFrame, - Rect overlayFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame); + Rect overlayFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame, + Rect stableFrame); /** * Retrieve the current frame of the window that has been assigned by diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 86c9fe3..50a7a5e 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -35,7 +35,7 @@ public class BaseIWindow extends IWindow.Stub { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, boolean reportDraw, Configuration newConfig) { + Rect visibleInsets, Rect stableInsets, boolean reportDraw, Configuration newConfig) { if (reportDraw) { try { mSession.finishDrawing(this); -- cgit v1.1