From 3e11bf33a6094da92d97702213aa12c67b21c4d1 Mon Sep 17 00:00:00 2001 From: Filip Gruszczynski Date: Mon, 20 Apr 2015 08:40:57 -0700 Subject: Support for devices with a chin. Information about the chin is now part of the config.xml instead of the theme. It is retrieved by WindowManagerService and passed to the clients as insets. Clients can adjust their behavior in a way that makes it invisible to the user, that part of the surface doesn't actually exist. Bug: 19908853 Change-Id: Iedf57bf3c848201b854f91ffeb3b59187d375c1f --- .../service/wallpaper/WallpaperService.java | 34 +++++++++++++++++----- core/java/android/view/IWindow.aidl | 2 +- core/java/android/view/IWindowSession.aidl | 6 ++-- core/java/android/view/SurfaceView.java | 6 ++-- core/java/android/view/View.java | 15 ++++++++++ core/java/android/view/ViewRootImpl.java | 31 +++++++++++++++----- core/java/android/view/WindowManagerPolicy.java | 4 ++- 7 files changed, 77 insertions(+), 21 deletions(-) (limited to 'core/java/android') diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 016541fe3e90..5420cadf5420 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -18,7 +18,6 @@ package android.service.wallpaper; import android.content.res.TypedArray; import android.graphics.Canvas; -import android.os.SystemProperties; import android.view.WindowInsets; import com.android.internal.R; @@ -161,9 +160,11 @@ public abstract class WallpaperService extends Service { final Rect mOverscanInsets = new Rect(); final Rect mContentInsets = new Rect(); final Rect mStableInsets = new Rect(); + final Rect mOutsets = new Rect(); final Rect mDispatchedOverscanInsets = new Rect(); final Rect mDispatchedContentInsets = new Rect(); final Rect mDispatchedStableInsets = new Rect(); + final Rect mDispatchedOutsets = new Rect(); final Rect mFinalSystemInsets = new Rect(); final Rect mFinalStableInsets = new Rect(); final Configuration mConfiguration = new Configuration(); @@ -270,7 +271,7 @@ public abstract class WallpaperService extends Service { final BaseIWindow mWindow = new BaseIWindow() { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0); @@ -661,30 +662,35 @@ public abstract class WallpaperService extends Service { mInputEventReceiver = new WallpaperInputEventReceiver( mInputChannel, Looper.myLooper()); } - + mSurfaceHolder.mSurfaceLock.lock(); mDrawingAllowed = true; if (!fixedSize) { mLayout.surfaceInsets.set(mIWallpaperEngine.mDisplayPadding); + mLayout.surfaceInsets.left += mOutsets.left; + mLayout.surfaceInsets.top += mOutsets.top; + mLayout.surfaceInsets.right += mOutsets.right; + mLayout.surfaceInsets.bottom += mOutsets.bottom; } else { mLayout.surfaceInsets.set(0, 0, 0, 0); } final int relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, View.VISIBLE, 0, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mStableInsets, mConfiguration, mSurfaceHolder.mSurface); + mVisibleInsets, mStableInsets, mOutsets, mConfiguration, + mSurfaceHolder.mSurface); if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface + ", frame=" + mWinFrame); - + int w = mWinFrame.width(); int h = mWinFrame.height(); if (!fixedSize) { final Rect padding = mIWallpaperEngine.mDisplayPadding; - w += padding.left + padding.right; - h += padding.top + padding.bottom; + w += padding.left + padding.right + mOutsets.left + mOutsets.right; + h += padding.top + padding.bottom + mOutsets.top + mOutsets.bottom; mOverscanInsets.left += padding.left; mOverscanInsets.top += padding.top; mOverscanInsets.right += padding.right; @@ -708,9 +714,14 @@ public abstract class WallpaperService extends Service { mCurHeight = h; } + if (DEBUG) { + Log.v(TAG, "Wallpaper size has changed: (" + mCurWidth + ", " + mCurHeight); + } + insetsChanged |= !mDispatchedOverscanInsets.equals(mOverscanInsets); insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets); insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets); + insetsChanged |= !mDispatchedOutsets.equals(mOutsets); mSurfaceHolder.setSurfaceFrameSize(w, h); mSurfaceHolder.mSurfaceLock.unlock(); @@ -770,13 +781,20 @@ public abstract class WallpaperService extends Service { if (insetsChanged) { mDispatchedOverscanInsets.set(mOverscanInsets); + mDispatchedOverscanInsets.left += mOutsets.left; + mDispatchedOverscanInsets.top += mOutsets.top; + mDispatchedOverscanInsets.right += mOutsets.right; + mDispatchedOverscanInsets.bottom += mOutsets.bottom; mDispatchedContentInsets.set(mContentInsets); mDispatchedStableInsets.set(mStableInsets); + mDispatchedOutsets.set(mOutsets); mFinalSystemInsets.set(mDispatchedOverscanInsets); mFinalStableInsets.set(mDispatchedStableInsets); - mFinalSystemInsets.bottom = mIWallpaperEngine.mDisplayPadding.bottom; WindowInsets insets = new WindowInsets(mFinalSystemInsets, null, mFinalStableInsets, mWindowIsRound); + if (DEBUG) { + Log.v(TAG, "dispatching insets=" + insets); + } onApplyWindowInsets(insets); } diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 9fc80fcf4235..b738ba0feaed 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -46,7 +46,7 @@ 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, in Rect stableInsets, boolean reportDraw, + in Rect visibleInsets, in Rect stableInsets, in Rect outsets, boolean reportDraw, in Configuration newConfig); void moved(int newX, int newY); void dispatchAppVisibility(boolean visible); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 63e1a855b1cc..ed609856277a 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -79,11 +79,13 @@ interface IWindowSession { * contents to make sure the user can see it. This is different than * outContentInsets in that these insets change transiently, * so complex relayout of the window should not happen based on them. + * @param outOutsets Rect in which is placed the dead area of the screen that we would like to + * treat as real display. Example of such area is a chin in some models of wearable devices. * @param outConfiguration New configuration of window, if it is now * becoming visible and the global configuration has changed since it * was last displayed. * @param outSurface Object in which is placed the new display surface. - * + * * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS}, * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}. */ @@ -91,7 +93,7 @@ interface IWindowSession { int requestedWidth, int requestedHeight, int viewVisibility, int flags, out Rect outFrame, out Rect outOverscanInsets, out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets, - out Configuration outConfig, out Surface outSurface); + out Rect outOutsets, out Configuration outConfig, out Surface outSurface); /** * If a call to relayout() asked to have the surface destroy deferred, diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 49be57d1bc0a..160c66208e7f 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -106,6 +106,7 @@ public class SurfaceView extends View { final Rect mOverscanInsets = new Rect(); final Rect mContentInsets = new Rect(); final Rect mStableInsets = new Rect(); + final Rect mOutsets = new Rect(); final Configuration mConfiguration = new Configuration(); static final int KEEP_SCREEN_ON_MSG = 1; @@ -519,7 +520,8 @@ public class SurfaceView extends View { visible ? VISIBLE : GONE, WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY, mWinFrame, mOverscanInsets, mContentInsets, - mVisibleInsets, mStableInsets, mConfiguration, mNewSurface); + mVisibleInsets, mStableInsets, mOutsets, mConfiguration, + mNewSurface); if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) { mReportDrawNeeded = true; } @@ -654,7 +656,7 @@ public class SurfaceView extends View { @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { SurfaceView surfaceView = mSurfaceView.get(); if (surfaceView != null) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 3c058729880a..aeb4ac6e0023 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6666,6 +6666,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS); } + /** + * Returns the outsets, which areas of the device that aren't a surface, but we would like to + * treat them as such. + * @hide + */ + public void getOutsets(Rect outOutsetRect) { + outOutsetRect.set(mAttachInfo.mOutsets); + } + /** * Returns the visibility status for this view. * @@ -20311,6 +20320,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ final Rect mStableInsets = new Rect(); + /** + * For windows that include areas that are not covered by real surface these are the outsets + * for real surface. + */ + final Rect mOutsets = new Rect(); + /** * The internal insets given by this window. This value is * supplied by the client (through diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 113ad8dfb2be..a182ef1fb251 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -261,6 +261,7 @@ public final class ViewRootImpl implements ViewParent, final Rect mPendingVisibleInsets = new Rect(); final Rect mPendingStableInsets = new Rect(); final Rect mPendingContentInsets = new Rect(); + final Rect mPendingOutsets = new Rect(); final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets = new ViewTreeObserver.InternalInsetsInfo(); @@ -1222,8 +1223,14 @@ public final class ViewRootImpl implements ViewParent, void dispatchApplyInsets(View host) { mDispatchContentInsets.set(mAttachInfo.mContentInsets); mDispatchStableInsets.set(mAttachInfo.mStableInsets); - host.dispatchApplyWindowInsets(new WindowInsets( - mDispatchContentInsets, null /* windowDecorInsets */, + Rect outsets = mAttachInfo.mOutsets; + Rect contentInsets = mDispatchContentInsets; + if (outsets.left > 0 || outsets.top > 0 || outsets.right > 0 || outsets.bottom > 0) { + contentInsets = new Rect(contentInsets.left + outsets.left, + contentInsets.top + outsets.top, contentInsets.right + outsets.right, + contentInsets.bottom + outsets.bottom); + } + host.dispatchApplyWindowInsets(new WindowInsets(contentInsets, null /* windowDecorInsets */, mDispatchStableInsets, mWindowIsRound)); } @@ -1369,6 +1376,9 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_LAYOUT) Log.v(TAG, "Visible insets changing to: " + mAttachInfo.mVisibleInsets); } + if (!mPendingOutsets.equals(mAttachInfo.mOutsets)) { + insetsChanged = true; + } if (lp.width == ViewGroup.LayoutParams.WRAP_CONTENT || lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) { windowSizeMayChange = true; @@ -1545,6 +1555,7 @@ public final class ViewRootImpl implements ViewParent, mAttachInfo.mVisibleInsets); final boolean stableInsetsChanged = !mPendingStableInsets.equals( mAttachInfo.mStableInsets); + final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets); if (contentInsetsChanged) { if (mWidth > 0 && mHeight > 0 && lp != null && ((lp.systemUiVisibility|lp.subtreeSystemUiVisibility) @@ -1628,9 +1639,11 @@ public final class ViewRootImpl implements ViewParent, } if (contentInsetsChanged || mLastSystemUiVisibility != mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested - || mLastOverscanRequested != mAttachInfo.mOverscanRequested) { + || mLastOverscanRequested != mAttachInfo.mOverscanRequested + || outsetsChanged) { mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility; mLastOverscanRequested = mAttachInfo.mOverscanRequested; + mAttachInfo.mOutsets.set(mPendingOutsets); mApplyInsetsRequested = false; dispatchApplyInsets(host); } @@ -3201,6 +3214,7 @@ public final class ViewRootImpl implements ViewParent, && mPendingContentInsets.equals(args.arg2) && mPendingStableInsets.equals(args.arg6) && mPendingVisibleInsets.equals(args.arg3) + && mPendingOutsets.equals(args.arg7) && args.arg4 == null) { break; } @@ -3219,6 +3233,7 @@ public final class ViewRootImpl implements ViewParent, mPendingContentInsets.set((Rect) args.arg2); mPendingStableInsets.set((Rect) args.arg6); mPendingVisibleInsets.set((Rect) args.arg3); + mPendingOutsets.set((Rect) args.arg7); args.recycle(); @@ -5317,7 +5332,7 @@ public final class ViewRootImpl implements ViewParent, (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, - mPendingStableInsets, mPendingConfiguration, mSurface); + mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface); //Log.d(TAG, "<<<<<< BACK FROM relayout"); if (restore) { params.restore(); @@ -5593,7 +5608,8 @@ public final class ViewRootImpl implements ViewParent, } public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, Configuration newConfig) { + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, + Configuration newConfig) { if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": frame=" + frame.toShortString() + " contentInsets=" + contentInsets.toShortString() + " visibleInsets=" + visibleInsets.toShortString() @@ -5613,6 +5629,7 @@ public final class ViewRootImpl implements ViewParent, args.arg4 = sameProcessCall && newConfig != null ? new Configuration(newConfig) : newConfig; args.arg5 = sameProcessCall ? new Rect(overscanInsets) : overscanInsets; args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets; + args.arg7 = sameProcessCall ? new Rect(outsets) : outsets; msg.obj = args; mHandler.sendMessage(msg); } @@ -6492,12 +6509,12 @@ public final class ViewRootImpl implements ViewParent, @Override public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, + Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { viewAncestor.dispatchResized(frame, overscanInsets, contentInsets, - visibleInsets, stableInsets, reportDraw, newConfig); + visibleInsets, stableInsets, outsets, reportDraw, newConfig); } } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 780ca990c841..71cb8899cb11 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -158,10 +158,12 @@ public interface WindowManagerPolicy { * @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. + * @param outsetFrame The frame that includes areas that aren't part of the surface but we + * want to treat them as such. */ public void computeFrameLw(Rect parentFrame, Rect displayFrame, Rect overlayFrame, Rect contentFrame, Rect visibleFrame, Rect decorFrame, - Rect stableFrame); + Rect stableFrame, Rect outsetFrame); /** * Retrieve the current frame of the window that has been assigned by -- cgit v1.2.3