diff options
| author | 2017-11-13 21:43:56 +0000 | |
|---|---|---|
| committer | 2017-11-13 21:43:56 +0000 | |
| commit | 059004e27b6152b248b1625c79185939a4b5dc3a (patch) | |
| tree | 342909f80538beae255c870579229d7b83a1670e | |
| parent | 2dd2cbcb12a21adccd3c349590a01e7ed009f679 (diff) | |
| parent | 7bb06e012a33c94c68b173bc8f276f78e0d60764 (diff) | |
Merge "Revert "Support insets on secondary displays""
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/Instrumentation.java | 44 | ||||
| -rw-r--r-- | core/java/android/view/DisplayFrames.java | 189 | ||||
| -rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 62 | ||||
| -rw-r--r-- | core/proto/android/server/windowmanagerservice.proto | 6 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Rect.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/policy/PhoneWindowManager.java | 1228 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/DisplayContent.java | 39 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/RootWindowContainer.java | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 49 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java | 80 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java | 39 |
14 files changed, 946 insertions, 808 deletions
diff --git a/api/current.txt b/api/current.txt index 59e0fc7c2419..89bdf41e82a9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4943,7 +4943,6 @@ package android.app { method public void setInTouchMode(boolean); method public void start(); method public android.app.Activity startActivitySync(android.content.Intent); - method public android.app.Activity startActivitySync(android.content.Intent, android.os.Bundle); method public deprecated void startAllocCounting(); method public void startPerformanceSnapshot(); method public void startProfiling(); diff --git a/api/system-current.txt b/api/system-current.txt index 62e23c86dc16..6bf5db1dfed8 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5129,7 +5129,6 @@ package android.app { method public void setInTouchMode(boolean); method public void start(); method public android.app.Activity startActivitySync(android.content.Intent); - method public android.app.Activity startActivitySync(android.content.Intent, android.os.Bundle); method public deprecated void startAllocCounting(); method public void startPerformanceSnapshot(); method public void startProfiling(); diff --git a/api/test-current.txt b/api/test-current.txt index abf58649e221..d5882d00183e 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4972,7 +4972,6 @@ package android.app { method public void setInTouchMode(boolean); method public void start(); method public android.app.Activity startActivitySync(android.content.Intent); - method public android.app.Activity startActivitySync(android.content.Intent, android.os.Bundle); method public deprecated void startAllocCounting(); method public void startPerformanceSnapshot(); method public void startProfiling(); diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index d49e11f47fea..e260967f92d0 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -17,7 +17,6 @@ package android.app; import android.annotation.IntDef; -import android.annotation.Nullable; import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; @@ -419,51 +418,22 @@ public class Instrumentation { * different process. In addition, if the given Intent resolves to * multiple activities, instead of displaying a dialog for the user to * select an activity, an exception will be thrown. - * + * * <p>The function returns as soon as the activity goes idle following the * call to its {@link Activity#onCreate}. Generally this means it has gone * through the full initialization including {@link Activity#onResume} and * drawn and displayed its initial window. - * + * * @param intent Description of the activity to start. - * + * * @see Context#startActivity - * @see #startActivitySync(Intent, Bundle) */ public Activity startActivitySync(Intent intent) { - return startActivitySync(intent, null /* options */); - } - - /** - * Start a new activity and wait for it to begin running before returning. - * In addition to being synchronous, this method as some semantic - * differences from the standard {@link Context#startActivity} call: the - * activity component is resolved before talking with the activity manager - * (its class name is specified in the Intent that this method ultimately - * starts), and it does not allow you to start activities that run in a - * different process. In addition, if the given Intent resolves to - * multiple activities, instead of displaying a dialog for the user to - * select an activity, an exception will be thrown. - * - * <p>The function returns as soon as the activity goes idle following the - * call to its {@link Activity#onCreate}. Generally this means it has gone - * through the full initialization including {@link Activity#onResume} and - * drawn and displayed its initial window. - * - * @param intent Description of the activity to start. - * @param options Additional options for how the Activity should be started. - * May be null if there are no options. See {@link android.app.ActivityOptions} - * for how to build the Bundle supplied here; there are no supported definitions - * for building it manually. - * - * @see Context#startActivity(Intent, Bundle) - */ - public Activity startActivitySync(Intent intent, @Nullable Bundle options) { validateNotAppThread(); synchronized (mSync) { intent = new Intent(intent); - + ActivityInfo ai = intent.resolveActivityInfo( getTargetContext().getPackageManager(), 0); if (ai == null) { @@ -477,7 +447,7 @@ public class Instrumentation { + myProc + " resolved to different process " + ai.processName + ": " + intent); } - + intent.setComponent(new ComponentName( ai.applicationInfo.packageName, ai.name)); final ActivityWaiter aw = new ActivityWaiter(intent); @@ -487,7 +457,7 @@ public class Instrumentation { } mWaitingActivities.add(aw); - getTargetContext().startActivity(intent, options); + getTargetContext().startActivity(intent); do { try { @@ -495,7 +465,7 @@ public class Instrumentation { } catch (InterruptedException e) { } } while (mWaitingActivities.contains(aw)); - + return aw.activity; } } diff --git a/core/java/android/view/DisplayFrames.java b/core/java/android/view/DisplayFrames.java deleted file mode 100644 index e6861d83d2fd..000000000000 --- a/core/java/android/view/DisplayFrames.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package android.view; - -import static android.view.Surface.ROTATION_180; -import static android.view.Surface.ROTATION_270; -import static android.view.Surface.ROTATION_90; -import static com.android.server.wm.proto.DisplayFramesProto.STABLE_BOUNDS; - -import android.graphics.Rect; -import android.util.proto.ProtoOutputStream; - -import java.io.PrintWriter; - -/** - * Container class for all the display frames that affect how we do window layout on a display. - * @hide - */ -public class DisplayFrames { - public final int mDisplayId; - - /** - * The current size of the screen; really; extends into the overscan area of the screen and - * doesn't account for any system elements like the status bar. - */ - public final Rect mOverscan = new Rect(); - - /** - * The current visible size of the screen; really; (ir)regardless of whether the status bar can - * be hidden but not extending into the overscan area. - */ - public final Rect mUnrestricted = new Rect(); - - /** Like mOverscan*, but allowed to move into the overscan region where appropriate. */ - public final Rect mRestrictedOverscan = new Rect(); - - /** - * The current size of the screen; these may be different than (0,0)-(dw,dh) if the status bar - * can't be hidden; in that case it effectively carves out that area of the display from all - * other windows. - */ - public final Rect mRestricted = new Rect(); - - /** - * During layout, the current screen borders accounting for any currently visible system UI - * elements. - */ - public final Rect mSystem = new Rect(); - - /** For applications requesting stable content insets, these are them. */ - public final Rect mStable = new Rect(); - - /** - * For applications requesting stable content insets but have also set the fullscreen window - * flag, these are the stable dimensions without the status bar. - */ - public final Rect mStableFullscreen = new Rect(); - - /** - * During layout, the current screen borders with all outer decoration (status bar, input method - * dock) accounted for. - */ - public final Rect mCurrent = new Rect(); - - /** - * During layout, the frame in which content should be displayed to the user, accounting for all - * screen decoration except for any space they deem as available for other content. This is - * usually the same as mCurrent*, but may be larger if the screen decor has supplied content - * insets. - */ - public final Rect mContent = new Rect(); - - /** - * During layout, the frame in which voice content should be displayed to the user, accounting - * for all screen decoration except for any space they deem as available for other content. - */ - public final Rect mVoiceContent = new Rect(); - - /** During layout, the current screen borders along which input method windows are placed. */ - public final Rect mDock = new Rect(); - - private final Rect mDisplayInfoOverscan = new Rect(); - private final Rect mRotatedDisplayInfoOverscan = new Rect(); - public int mDisplayWidth; - public int mDisplayHeight; - - public int mRotation; - - public DisplayFrames(int displayId, DisplayInfo info) { - mDisplayId = displayId; - onDisplayInfoUpdated(info); - } - - public void onDisplayInfoUpdated(DisplayInfo info) { - mDisplayWidth = info.logicalWidth; - mDisplayHeight = info.logicalHeight; - mRotation = info.rotation; - mDisplayInfoOverscan.set( - info.overscanLeft, info.overscanTop, info.overscanRight, info.overscanBottom); - } - - public void onBeginLayout() { - switch (mRotation) { - case ROTATION_90: - mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.top; - mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.right; - mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.bottom; - mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.left; - break; - case ROTATION_180: - mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.right; - mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.bottom; - mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.left; - mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.top; - break; - case ROTATION_270: - mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.bottom; - mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.left; - mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.top; - mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.right; - break; - default: - mRotatedDisplayInfoOverscan.set(mDisplayInfoOverscan); - break; - } - - mRestrictedOverscan.set(0, 0, mDisplayWidth, mDisplayHeight); - mOverscan.set(mRestrictedOverscan); - mSystem.set(mRestrictedOverscan); - mUnrestricted.set(mRotatedDisplayInfoOverscan); - mUnrestricted.right = mDisplayWidth - mUnrestricted.right; - mUnrestricted.bottom = mDisplayHeight - mUnrestricted.bottom; - mRestricted.set(mUnrestricted); - mDock.set(mUnrestricted); - mContent.set(mUnrestricted); - mVoiceContent.set(mUnrestricted); - mStable.set(mUnrestricted); - mStableFullscreen.set(mUnrestricted); - mCurrent.set(mUnrestricted); - - } - - public int getInputMethodWindowVisibleHeight() { - return mDock.bottom - mCurrent.bottom; - } - - public void writeToProto(ProtoOutputStream proto, long fieldId) { - final long token = proto.start(fieldId); - mStable.writeToProto(proto, STABLE_BOUNDS); - proto.end(token); - } - - public void dump(String prefix, PrintWriter pw) { - pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight - + " r=" + mRotation); - final String myPrefix = prefix + " "; - dumpFrame(mStable, "mStable", myPrefix, pw); - dumpFrame(mStableFullscreen, "mStableFullscreen", myPrefix, pw); - dumpFrame(mDock, "mDock", myPrefix, pw); - dumpFrame(mCurrent, "mCurrent", myPrefix, pw); - dumpFrame(mSystem, "mSystem", myPrefix, pw); - dumpFrame(mContent, "mContent", myPrefix, pw); - dumpFrame(mVoiceContent, "mVoiceContent", myPrefix, pw); - dumpFrame(mOverscan, "mOverscan", myPrefix, pw); - dumpFrame(mRestrictedOverscan, "mRestrictedOverscan", myPrefix, pw); - dumpFrame(mRestricted, "mRestricted", myPrefix, pw); - dumpFrame(mUnrestricted, "mUnrestricted", myPrefix, pw); - dumpFrame(mDisplayInfoOverscan, "mDisplayInfoOverscan", myPrefix, pw); - dumpFrame(mRotatedDisplayInfoOverscan, "mRotatedDisplayInfoOverscan", myPrefix, pw); - } - - private void dumpFrame(Rect frame, String name, String prefix, PrintWriter pw) { - pw.print(prefix + name + "="); frame.printShortString(pw); pw.println(); - } -} diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 534335bf4743..ebe3633de402 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -66,6 +66,7 @@ import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType; import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.app.ActivityManager.StackId; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.CompatibilityInfo; @@ -721,6 +722,12 @@ public interface WindowManagerPolicy { public void setInitialDisplaySize(Display display, int width, int height, int density); /** + * Called by window manager to set the overscan region that should be used for the + * given display. + */ + public void setDisplayOverscan(Display display, int left, int top, int right, int bottom); + + /** * Check permissions when adding a window. * * @param attrs The window's LayoutParams. @@ -1166,10 +1173,14 @@ public interface WindowManagerPolicy { /** * Called when layout of the windows is about to start. * - * @param displayFrames frames of the display we are doing layout on. + * @param displayId Id of the display we are doing layout on. + * @param displayWidth The current full width of the screen. + * @param displayHeight The current full height of the screen. + * @param displayRotation The current rotation being applied to the base window. * @param uiMode The current uiMode in configuration. */ - default void beginLayoutLw(DisplayFrames displayFrames, int uiMode) {} + public void beginLayoutLw(int displayId, int displayWidth, int displayHeight, + int displayRotation, int uiMode); /** * Returns the bottom-most layer of the system decor, above which no policy decor should @@ -1178,28 +1189,37 @@ public interface WindowManagerPolicy { public int getSystemDecorLayerLw(); /** - * Called for each window attached to the window manager as layout is proceeding. The - * implementation of this function must take care of setting the window's frame, either here or - * in finishLayout(). + * Return the rectangle of the screen that is available for applications to run in. + * This will be called immediately after {@link #beginLayoutLw}. + * + * @param r The rectangle to be filled with the boundaries available to applications. + */ + public void getContentRectLw(Rect r); + + /** + * Called for each window attached to the window manager as layout is + * proceeding. The implementation of this function must take care of + * setting the window's frame, either here or in finishLayout(). * * @param win The window being positioned. * @param attached For sub-windows, the window it is attached to; this * window will already have had layoutWindow() called on it * so you can use its Rect. Otherwise null. - * @param displayFrames The display frames. */ - default void layoutWindowLw( - WindowState win, WindowState attached, DisplayFrames displayFrames) {} + public void layoutWindowLw(WindowState win, WindowState attached); /** - * Return the insets for the areas covered by system windows. These values are computed on the - * most recent layout, so they are not guaranteed to be correct. + * Return the insets for the areas covered by system windows. These values + * are computed on the most recent layout, so they are not guaranteed to + * be correct. * * @param attrs The LayoutParams of the window. * @param taskBounds The bounds of the task this window is on or {@code null} if no task is * associated with the window. - * @param displayFrames display frames. + * @param displayRotation Rotation of the display. + * @param displayWidth The width of the display. + * @param displayHeight The height of the display. * @param outContentInsets The areas covered by system windows, expressed as positive insets. * @param outStableInsets The areas covered by stable system windows irrespective of their * current visibility. Expressed as positive insets. @@ -1207,11 +1227,16 @@ public interface WindowManagerPolicy { * @return Whether to always consume the navigation bar. * See {@link #isNavBarForcedShownLw(WindowState)}. */ - default boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, - DisplayFrames displayFrames, Rect outContentInsets, Rect outStableInsets, - Rect outOutsets) { - return false; - } + public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, + int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, + Rect outStableInsets, Rect outOutsets); + + /** + * Called when layout of the windows is finished. After this function has + * returned, all windows given to layoutWindow() <em>must</em> have had a + * frame assigned. + */ + public void finishLayoutLw(); /** Layout state may have changed (so another layout will be performed) */ static final int FINISH_LAYOUT_REDO_LAYOUT = 0x0001; @@ -1628,6 +1653,11 @@ public interface WindowManagerPolicy { public void showGlobalActions(); /** + * @return The current height of the input method window. + */ + public int getInputMethodWindowVisibleHeightLw(); + + /** * Called when the current user changes. Guaranteed to be called before the broadcast * of the new user id is made to all listeners. * diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 0228edb03a83..4d48a4299281 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -48,6 +48,7 @@ message RootWindowContainerProto { /* represents PhoneWindowManager */ message WindowManagerPolicyProto { + optional .android.graphics.RectProto stable_bounds = 1; } /* represents AppTransition */ @@ -100,13 +101,8 @@ message DisplayProto { optional .android.view.DisplayInfoProto display_info = 10; optional int32 rotation = 11; optional ScreenRotationAnimationProto screen_rotation_animation = 12; - optional DisplayFramesProto display_frames = 13; } -/* represents DisplayFrames */ -message DisplayFramesProto { - optional .android.graphics.RectProto stable_bounds = 1; -} /* represents DockedStackDividerController */ message DockedStackDividerControllerProto { diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index aff942da78d1..3dc928de60df 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -475,19 +475,6 @@ public final class Rect implements Parcelable { } /** - * If the specified rectangle intersects this rectangle, set this rectangle to that - * intersection, otherwise set this rectangle to the empty rectangle. - * @see #inset(int, int, int, int) but without checking if the rects overlap. - * @hide - */ - public void intersectUnchecked(Rect other) { - left = Math.max(left, other.left); - top = Math.max(top, other.top); - right = Math.min(right, other.right); - bottom = Math.min(bottom, other.bottom); - } - - /** * If rectangles a and b intersect, return true and set this rectangle to * that intersection, otherwise return false and do not change this * rectangle. No check is performed to see if either rectangle is empty. diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index a11d28279840..7837940434aa 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -59,8 +59,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW; @@ -68,7 +66,6 @@ import static android.view.WindowManager.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; @@ -126,8 +123,11 @@ import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; +import static com.android.server.wm.proto.WindowManagerPolicyProto.STABLE_BOUNDS; + import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.ActivityManager.StackId; import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityThread; @@ -210,7 +210,6 @@ import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import android.view.Display; -import android.view.DisplayFrames; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.IApplicationToken; @@ -597,6 +596,47 @@ public class PhoneWindowManager implements WindowManagerPolicy { PointerLocationView mPointerLocationView; + // The current size of the screen; really; extends into the overscan area of + // the screen and doesn't account for any system elements like the status bar. + int mOverscanScreenLeft, mOverscanScreenTop; + int mOverscanScreenWidth, mOverscanScreenHeight; + // The current visible size of the screen; really; (ir)regardless of whether the status + // bar can be hidden but not extending into the overscan area. + int mUnrestrictedScreenLeft, mUnrestrictedScreenTop; + int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight; + // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate. + int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop; + int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight; + // The current size of the screen; these may be different than (0,0)-(dw,dh) + // if the status bar can't be hidden; in that case it effectively carves out + // that area of the display from all other windows. + int mRestrictedScreenLeft, mRestrictedScreenTop; + int mRestrictedScreenWidth, mRestrictedScreenHeight; + // During layout, the current screen borders accounting for any currently + // visible system UI elements. + int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom; + // For applications requesting stable content insets, these are them. + int mStableLeft, mStableTop, mStableRight, mStableBottom; + // For applications requesting stable content insets but have also set the + // fullscreen window flag, these are the stable dimensions without the status bar. + int mStableFullscreenLeft, mStableFullscreenTop; + int mStableFullscreenRight, mStableFullscreenBottom; + // During layout, the current screen borders with all outer decoration + // (status bar, input method dock) accounted for. + int mCurLeft, mCurTop, mCurRight, mCurBottom; + // During layout, the frame in which content should be displayed + // to the user, accounting for all screen decoration except for any + // space they deem as available for other content. This is usually + // the same as mCur*, but may be larger if the screen decor has supplied + // content insets. + int mContentLeft, mContentTop, mContentRight, mContentBottom; + // During layout, the frame in which voice content should be displayed + // to the user, accounting for all screen decoration except for any + // space they deem as available for other content. + int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom; + // During layout, the current screen borders along which input method + // windows are placed. + int mDockLeft, mDockTop, mDockRight, mDockBottom; // During layout, the layer at which the doc window is placed. int mDockLayer; // During layout, this is the layer of the status bar. @@ -694,11 +734,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { Display mDisplay; + private int mDisplayRotation; + int mLandscapeRotation = 0; // default landscape rotation int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation int mPortraitRotation = 0; // default portrait rotation int mUpsideDownRotation = 0; // "other" portrait rotation + int mOverscanLeft = 0; + int mOverscanTop = 0; + int mOverscanRight = 0; + int mOverscanBottom = 0; + // What we do when the user long presses on home private int mLongPressOnHomeBehavior; @@ -1014,7 +1061,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { View.NAVIGATION_BAR_UNHIDE, View.NAVIGATION_BAR_TRANSLUCENT, StatusBarManager.WINDOW_NAVIGATION_BAR, - FLAG_TRANSLUCENT_NAVIGATION, + WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, View.NAVIGATION_BAR_TRANSPARENT); private final BarController.OnBarVisibilityChangedListener mNavBarVisibilityListener = @@ -2021,7 +2068,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { context.registerReceiver(mMultiuserReceiver, filter); // monitor for system gestures - // TODO(multi-display): Needs to be display specific. mSystemGestures = new SystemGesturesPointerEventListener(context, new SystemGesturesPointerEventListener.Callbacks() { @Override @@ -2268,6 +2314,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mForceDefaultOrientation; } + @Override + public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { + // TODO(multi-display): Define policy for secondary displays. + if (display.getDisplayId() == DEFAULT_DISPLAY) { + mOverscanLeft = left; + mOverscanTop = top; + mOverscanRight = right; + mOverscanBottom = bottom; + } + } + public void updateSettings() { ContentResolver resolver = mContext.getContentResolver(); boolean updateRotation = false; @@ -4264,16 +4321,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override - // TODO: Should probably be moved into DisplayFrames. public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, - DisplayFrames displayFrames, Rect outContentInsets, Rect outStableInsets, - Rect outOutsets) { + int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, + Rect outStableInsets, Rect outOutsets) { final int fl = PolicyControl.getWindowFlags(null, attrs); final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs); final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility); - final int displayRotation = displayFrames.mRotation; - final int displayWidth = displayFrames.mDisplayWidth; - final int displayHeight = displayFrames.mDisplayHeight; final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl); if (useOutsets) { @@ -4296,33 +4349,34 @@ public class PhoneWindowManager implements WindowManagerPolicy { int availRight, availBottom; if (canHideNavigationBar() && (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { - availRight = displayFrames.mUnrestricted.right; - availBottom = displayFrames.mUnrestricted.bottom; + availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; + availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; } else { - availRight = displayFrames.mRestricted.right; - availBottom = displayFrames.mRestricted.bottom; + availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; + availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; } - outStableInsets.set(displayFrames.mStable.left, displayFrames.mStable.top, - availRight - displayFrames.mStable.right, - availBottom - displayFrames.mStable.bottom); - if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { if ((fl & FLAG_FULLSCREEN) != 0) { - outContentInsets.set(displayFrames.mStableFullscreen.left, - displayFrames.mStableFullscreen.top, - availRight - displayFrames.mStableFullscreen.right, - availBottom - displayFrames.mStableFullscreen.bottom); + outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop, + availRight - mStableFullscreenRight, + availBottom - mStableFullscreenBottom); } else { - outContentInsets.set(outStableInsets); + outContentInsets.set(mStableLeft, mStableTop, + availRight - mStableRight, availBottom - mStableBottom); } } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) { outContentInsets.setEmpty(); + } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { + outContentInsets.set(mCurLeft, mCurTop, + availRight - mCurRight, availBottom - mCurBottom); } else { - outContentInsets.set(displayFrames.mCurrent.left, displayFrames.mCurrent.top, - availRight - displayFrames.mCurrent.right, - availBottom - displayFrames.mCurrent.bottom); + outContentInsets.set(mCurLeft, mCurTop, + availRight - mCurRight, availBottom - mCurBottom); } + outStableInsets.set(mStableLeft, mStableTop, + availRight - mStableRight, availBottom - mStableBottom); if (taskBounds != null) { calculateRelevantTaskInsets(taskBounds, outContentInsets, displayWidth, displayHeight); @@ -4359,11 +4413,68 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) { - displayFrames.onBeginLayout(); - // TODO(multi-display): This doesn't seem right...Maybe only apply to default display? - mSystemGestures.screenWidth = displayFrames.mUnrestricted.width(); - mSystemGestures.screenHeight = displayFrames.mUnrestricted.height(); + public void beginLayoutLw(int displayId, int displayWidth, int displayHeight, + int displayRotation, int uiMode) { + final boolean isDefaultDisplay = displayId == DEFAULT_DISPLAY; + mDisplayRotation = displayRotation; + final int overscanLeft, overscanTop, overscanRight, overscanBottom; + if (isDefaultDisplay) { + switch (displayRotation) { + case Surface.ROTATION_90: + overscanLeft = mOverscanTop; + overscanTop = mOverscanRight; + overscanRight = mOverscanBottom; + overscanBottom = mOverscanLeft; + break; + case Surface.ROTATION_180: + overscanLeft = mOverscanRight; + overscanTop = mOverscanBottom; + overscanRight = mOverscanLeft; + overscanBottom = mOverscanTop; + break; + case Surface.ROTATION_270: + overscanLeft = mOverscanBottom; + overscanTop = mOverscanLeft; + overscanRight = mOverscanTop; + overscanBottom = mOverscanRight; + break; + default: + overscanLeft = mOverscanLeft; + overscanTop = mOverscanTop; + overscanRight = mOverscanRight; + overscanBottom = mOverscanBottom; + break; + } + } else { + overscanLeft = 0; + overscanTop = 0; + overscanRight = 0; + overscanBottom = 0; + } + mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0; + mOverscanScreenTop = mRestrictedOverscanScreenTop = 0; + mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth; + mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight; + mSystemLeft = 0; + mSystemTop = 0; + mSystemRight = displayWidth; + mSystemBottom = displayHeight; + mUnrestrictedScreenLeft = overscanLeft; + mUnrestrictedScreenTop = overscanTop; + mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight; + mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom; + mRestrictedScreenLeft = mUnrestrictedScreenLeft; + mRestrictedScreenTop = mUnrestrictedScreenTop; + mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth; + mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight; + mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft + = mCurLeft = mUnrestrictedScreenLeft; + mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop + = mCurTop = mUnrestrictedScreenTop; + mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight + = mCurRight = displayWidth - overscanRight; + mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom + = mCurBottom = displayHeight - overscanBottom; mDockLayer = 0x10000000; mStatusBarLayer = -1; @@ -4373,13 +4484,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { final Rect of = mTmpOverscanFrame; final Rect vf = mTmpVisibleFrame; final Rect dcf = mTmpDecorFrame; - vf.set(displayFrames.mDock); - of.set(displayFrames.mDock); - df.set(displayFrames.mDock); - pf.set(displayFrames.mDock); + pf.left = df.left = of.left = vf.left = mDockLeft; + pf.top = df.top = of.top = vf.top = mDockTop; + pf.right = df.right = of.right = vf.right = mDockRight; + pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom; dcf.setEmpty(); // Decor frame N/A for system bars. - if (displayFrames.mDisplayId == DEFAULT_DISPLAY) { + if (isDefaultDisplay) { // For purposes of putting out fake window up to steal focus, we will // drive nav being hidden only by whether it is requested. final int sysui = mLastSystemUiFlags; @@ -4398,9 +4509,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { && mStatusBar.getAttrs().height == MATCH_PARENT && mStatusBar.getAttrs().width == MATCH_PARENT; - // When the navigation bar isn't visible, we put up a fake input window to catch all - // touch events. This way we can detect when the user presses anywhere to bring back the - // nav bar and ensure the application doesn't see the event. + // When the navigation bar isn't visible, we put up a fake + // input window to catch all touch events. This way we can + // detect when the user presses anywhere to bring back the nav + // bar and ensure the application doesn't see the event. if (navVisible || navAllowedHidden) { if (mInputConsumer != null) { mHandler.sendMessage( @@ -4416,32 +4528,30 @@ public class PhoneWindowManager implements WindowManagerPolicy { InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL); } - // For purposes of positioning and showing the nav bar, if we have decided that it can't - // be hidden (because of the screen aspect ratio), then take that into account. + // For purposes of positioning and showing the nav bar, if we have + // decided that it can't be hidden (because of the screen aspect ratio), + // then take that into account. navVisible |= !canHideNavigationBar(); - boolean updateSysUiVisibility = layoutNavigationBar(displayFrames, uiMode, dcf, - navVisible, navTranslucent, navAllowedHidden, statusBarExpandedNotKeyguard); - if (DEBUG_LAYOUT) Slog.i(TAG, "mDock rect:" + displayFrames.mDock); - updateSysUiVisibility |= layoutStatusBar( - displayFrames, pf, df, of, vf, dcf, sysui, isKeyguardShowing); + boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight, + displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent, + navAllowedHidden, statusBarExpandedNotKeyguard); + if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", + mDockLeft, mDockTop, mDockRight, mDockBottom)); + updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing); if (updateSysUiVisibility) { updateSystemUiVisibilityLw(); } } - layoutScreenDecorWindows(displayFrames, pf, df, dcf); + layoutScreenDecorWindows(displayId, displayWidth, displayHeight, pf, df, dcf); } - private void layoutScreenDecorWindows(DisplayFrames displayFrames, Rect pf, Rect df, Rect dcf) { + private void layoutScreenDecorWindows(int displayId, int displayWidth, int displayHeight, + Rect pf, Rect df, Rect dcf) { if (mScreenDecorWindows.isEmpty()) { return; } - final int displayId = displayFrames.mDisplayId; - final Rect dockFrame = displayFrames.mDock; - final int displayHeight = displayFrames.mDisplayHeight; - final int displayWidth = displayFrames.mDisplayWidth; - for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) { final WindowState w = mScreenDecorWindows.valueAt(i); if (w.getDisplayId() != displayId || !w.isVisibleLw()) { @@ -4458,10 +4568,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Docked at left or top. if (frame.bottom >= displayHeight) { // Docked left. - dockFrame.left = Math.max(frame.right, dockFrame.left); + mDockLeft = Math.max(frame.right, mDockLeft); } else if (frame.right >= displayWidth ) { // Docked top. - dockFrame.top = Math.max(frame.bottom, dockFrame.top); + mDockTop = Math.max(frame.bottom, mDockTop); } else { Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w + " not docked on left or top of display. frame=" + frame @@ -4471,10 +4581,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Docked at right or bottom. if (frame.top <= 0) { // Docked right. - dockFrame.right = Math.min(frame.left, dockFrame.right); + mDockRight = Math.min(frame.left, mDockRight); } else if (frame.left <= 0) { // Docked bottom. - dockFrame.bottom = Math.min(frame.top, dockFrame.bottom); + mDockBottom = Math.min(frame.top, mDockBottom); } else { Slog.w(TAG, "layoutScreenDecorWindows: Ignoring decor win=" + w + " not docked on right or bottom" + " of display. frame=" + frame @@ -4488,165 +4598,194 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - displayFrames.mRestricted.set(dockFrame); - displayFrames.mCurrent.set(dockFrame); - displayFrames.mVoiceContent.set(dockFrame); - displayFrames.mSystem.set(dockFrame); - displayFrames.mContent.set(dockFrame); - displayFrames.mRestrictedOverscan.set(dockFrame); + mContentTop = mSystemTop = mVoiceContentTop = mCurTop = mRestrictedScreenTop = mDockTop; + mContentLeft = mSystemLeft = mVoiceContentLeft = mCurLeft = mRestrictedScreenLeft + = mRestrictedOverscanScreenLeft = mDockLeft; + mContentBottom = mSystemBottom = mVoiceContentBottom = mCurBottom = mDockBottom; + mContentRight = mSystemRight = mVoiceContentRight = mCurRight = mDockRight; + + mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; + mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop; + mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; + mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop; } - private boolean layoutStatusBar(DisplayFrames displayFrames, Rect pf, Rect df, Rect of, Rect vf, - Rect dcf, int sysui, boolean isKeyguardShowing) { + private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui, + boolean isKeyguardShowing) { // decide where the status bar goes ahead of time - if (mStatusBar == null) { - return false; - } - // apply any navigation bar insets - of.set(displayFrames.mUnrestricted); - df.set(displayFrames.mUnrestricted); - pf.set(displayFrames.mUnrestricted); - vf.set(displayFrames.mStable); - - mStatusBarLayer = mStatusBar.getSurfaceLayer(); - - // Let the status bar determine its size. - mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, - vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */, - dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */); - - // For layout, the status bar is always at the top with our fixed height. - displayFrames.mStable.top = displayFrames.mUnrestricted.top + mStatusBarHeight; - - boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; - boolean statusBarTranslucent = (sysui - & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0; - if (!isKeyguardShowing) { - statusBarTranslucent &= areTranslucentBarsAllowed(); - } - - // If the status bar is hidden, we don't want to cause windows behind it to scroll. - if (mStatusBar.isVisibleLw() && !statusBarTransient) { - // Status bar may go away, so the screen area it occupies is available to apps but just - // covering them when the status bar is visible. - final Rect dockFrame = displayFrames.mDock; - dockFrame.top = displayFrames.mStable.top; - displayFrames.mContent.set(dockFrame); - displayFrames.mVoiceContent.set(dockFrame); - - if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + String.format( - "dock=%s content=%s cur=%s", dockFrame.toString(), - displayFrames.mContent.toString(), displayFrames.mCurrent.toString())); - - if (!mStatusBar.isAnimatingLw() && !statusBarTranslucent + if (mStatusBar != null) { + // apply any navigation bar insets + pf.left = df.left = of.left = mUnrestrictedScreenLeft; + pf.top = df.top = of.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; + pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + + mUnrestrictedScreenTop; + vf.left = mStableLeft; + vf.top = mStableTop; + vf.right = mStableRight; + vf.bottom = mStableBottom; + + mStatusBarLayer = mStatusBar.getSurfaceLayer(); + + // Let the status bar determine its size. + mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, + vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */, + dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */); + + // For layout, the status bar is always at the top with our fixed height. + mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; + + boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; + boolean statusBarTranslucent = (sysui + & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0; + if (!isKeyguardShowing) { + statusBarTranslucent &= areTranslucentBarsAllowed(); + } + + // If the status bar is hidden, we don't want to cause + // windows behind it to scroll. + if (mStatusBar.isVisibleLw() && !statusBarTransient) { + // Status bar may go away, so the screen area it occupies + // is available to apps but just covering them when the + // status bar is visible. + mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; + + mContentTop = mVoiceContentTop = mCurTop = mDockTop; + mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; + mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; + mContentRight = mVoiceContentRight = mCurRight = mDockRight; + + if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + + String.format( + "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", + mDockLeft, mDockTop, mDockRight, mDockBottom, + mContentLeft, mContentTop, mContentRight, mContentBottom, + mCurLeft, mCurTop, mCurRight, mCurBottom)); + } + if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() + && !statusBarTransient && !statusBarTranslucent && !mStatusBarController.wasRecentlyTranslucent()) { - // If the opaque status bar is currently requested to be visible, and not in the - // process of animating on or off, then we can tell the app that it is covered by it. - displayFrames.mSystem.top = displayFrames.mStable.top; + // If the opaque status bar is currently requested to be visible, + // and not in the process of animating on or off, then + // we can tell the app that it is covered by it. + mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; + } + if (mStatusBarController.checkHiddenLw()) { + return true; } } - return mStatusBarController.checkHiddenLw(); + return false; } - private boolean layoutNavigationBar(DisplayFrames displayFrames, int uiMode, Rect dcf, + private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation, + int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf, boolean navVisible, boolean navTranslucent, boolean navAllowedHidden, boolean statusBarExpandedNotKeyguard) { - if (mNavigationBar == null) { - return false; - } - boolean transientNavBarShowing = mNavigationBarController.isTransientShowing(); - // Force the navigation bar to its appropriate place and size. We need to do this directly, - // instead of relying on it to bubble up from the nav bar, because this needs to change - // atomically with screen rotations. - final int rotation = displayFrames.mRotation; - final int displayHeight = displayFrames.mDisplayHeight; - final int displayWidth = displayFrames.mDisplayWidth; - final Rect dockFrame = displayFrames.mDock; - mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, rotation); - - if (mNavigationBarPosition == NAV_BAR_BOTTOM) { - // It's a system nav bar or a portrait screen; nav bar goes on bottom. - final int top = displayFrames.mUnrestricted.bottom - - getNavigationBarHeight(rotation, uiMode); - mTmpNavigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom); - displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top; - if (transientNavBarShowing) { - mNavigationBarController.setBarShowingLw(true); - } else if (navVisible) { - mNavigationBarController.setBarShowingLw(true); - dockFrame.bottom = displayFrames.mRestricted.bottom - = displayFrames.mRestrictedOverscan.bottom = top; - } else { - // We currently want to hide the navigation UI - unless we expanded the status bar. - mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); - } - if (navVisible && !navTranslucent && !navAllowedHidden - && !mNavigationBar.isAnimatingLw() - && !mNavigationBarController.wasRecentlyTranslucent()) { - // If the opaque nav bar is currently requested to be visible and not in the process - // of animating on or off, then we can tell the app that it is covered by it. - displayFrames.mSystem.bottom = top; - } - } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { - // Landscape screen; nav bar goes to the right. - final int left = displayFrames.mUnrestricted.right - - getNavigationBarWidth(rotation, uiMode); - mTmpNavigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight); - displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left; - if (transientNavBarShowing) { - mNavigationBarController.setBarShowingLw(true); - } else if (navVisible) { - mNavigationBarController.setBarShowingLw(true); - dockFrame.right = displayFrames.mRestricted.right - = displayFrames.mRestrictedOverscan.right = left; - } else { - // We currently want to hide the navigation UI - unless we expanded the status bar. - mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); - } - if (navVisible && !navTranslucent && !navAllowedHidden - && !mNavigationBar.isAnimatingLw() - && !mNavigationBarController.wasRecentlyTranslucent()) { - // If the nav bar is currently requested to be visible, and not in the process of - // animating on or off, then we can tell the app that it is covered by it. - displayFrames.mSystem.right = left; - } - } else if (mNavigationBarPosition == NAV_BAR_LEFT) { - // Seascape screen; nav bar goes to the left. - final int right = displayFrames.mUnrestricted.left - - getNavigationBarWidth(rotation, uiMode); - mTmpNavigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight); - displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right; - if (transientNavBarShowing) { - mNavigationBarController.setBarShowingLw(true); - } else if (navVisible) { - mNavigationBarController.setBarShowingLw(true); - dockFrame.left = displayFrames.mRestricted.left = - displayFrames.mRestrictedOverscan.left = right; - } else { - // We currently want to hide the navigation UI - unless we expanded the status bar. - mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); + if (mNavigationBar != null) { + boolean transientNavBarShowing = mNavigationBarController.isTransientShowing(); + // Force the navigation bar to its appropriate place and + // size. We need to do this directly, instead of relying on + // it to bubble up from the nav bar, because this needs to + // change atomically with screen rotations. + mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, + displayRotation); + if (mNavigationBarPosition == NAV_BAR_BOTTOM) { + // It's a system nav bar or a portrait screen; nav bar goes on bottom. + int top = displayHeight - overscanBottom + - getNavigationBarHeight(displayRotation, uiMode); + mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom); + mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; + if (transientNavBarShowing) { + mNavigationBarController.setBarShowingLw(true); + } else if (navVisible) { + mNavigationBarController.setBarShowingLw(true); + mDockBottom = mTmpNavigationFrame.top; + mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop; + mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop; + } else { + // We currently want to hide the navigation UI - unless we expanded the status + // bar. + mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); + } + if (navVisible && !navTranslucent && !navAllowedHidden + && !mNavigationBar.isAnimatingLw() + && !mNavigationBarController.wasRecentlyTranslucent()) { + // If the opaque nav bar is currently requested to be visible, + // and not in the process of animating on or off, then + // we can tell the app that it is covered by it. + mSystemBottom = mTmpNavigationFrame.top; + } + } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { + // Landscape screen; nav bar goes to the right. + int left = displayWidth - overscanRight + - getNavigationBarWidth(displayRotation, uiMode); + mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight); + mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; + if (transientNavBarShowing) { + mNavigationBarController.setBarShowingLw(true); + } else if (navVisible) { + mNavigationBarController.setBarShowingLw(true); + mDockRight = mTmpNavigationFrame.left; + mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; + mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; + } else { + // We currently want to hide the navigation UI - unless we expanded the status + // bar. + mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); + } + if (navVisible && !navTranslucent && !navAllowedHidden + && !mNavigationBar.isAnimatingLw() + && !mNavigationBarController.wasRecentlyTranslucent()) { + // If the nav bar is currently requested to be visible, + // and not in the process of animating on or off, then + // we can tell the app that it is covered by it. + mSystemRight = mTmpNavigationFrame.left; + } + } else if (mNavigationBarPosition == NAV_BAR_LEFT) { + // Seascape screen; nav bar goes to the left. + int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode); + mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight); + mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right; + if (transientNavBarShowing) { + mNavigationBarController.setBarShowingLw(true); + } else if (navVisible) { + mNavigationBarController.setBarShowingLw(true); + mDockLeft = mTmpNavigationFrame.right; + // TODO: not so sure about those: + mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft; + mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; + mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; + } else { + // We currently want to hide the navigation UI - unless we expanded the status + // bar. + mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); + } + if (navVisible && !navTranslucent && !navAllowedHidden + && !mNavigationBar.isAnimatingLw() + && !mNavigationBarController.wasRecentlyTranslucent()) { + // If the nav bar is currently requested to be visible, + // and not in the process of animating on or off, then + // we can tell the app that it is covered by it. + mSystemLeft = mTmpNavigationFrame.right; + } } - if (navVisible && !navTranslucent && !navAllowedHidden - && !mNavigationBar.isAnimatingLw() - && !mNavigationBarController.wasRecentlyTranslucent()) { - // If the nav bar is currently requested to be visible, and not in the process of - // animating on or off, then we can tell the app that it is covered by it. - displayFrames.mSystem.left = right; + // Make sure the content and current rectangles are updated to + // account for the restrictions from the navigation bar. + mContentTop = mVoiceContentTop = mCurTop = mDockTop; + mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; + mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; + mContentRight = mVoiceContentRight = mCurRight = mDockRight; + mStatusBarLayer = mNavigationBar.getSurfaceLayer(); + // And compute the final frame. + mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, + mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, + mTmpNavigationFrame, mTmpNavigationFrame); + if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); + if (mNavigationBarController.checkHiddenLw()) { + return true; } } - - // Make sure the content and current rectangles are updated to account for the restrictions - // from the navigation bar. - displayFrames.mCurrent.set(dockFrame); - displayFrames.mVoiceContent.set(dockFrame); - displayFrames.mContent.set(dockFrame); - mStatusBarLayer = mNavigationBar.getSurfaceLayer(); - // And compute the final frame. - mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, - mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, - mTmpNavigationFrame, mTmpNavigationFrame); - if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); - return mNavigationBarController.checkHiddenLw(); + return false; } private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { @@ -4674,26 +4813,32 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } - private void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, - boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf, - DisplayFrames displayFrames) { + @Override + public void getContentRectLw(Rect r) { + r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); + } + + void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, + boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) { if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { - // Here's a special case: if this attached window is a panel that is above the dock - // window, and the window it is attached to is below the dock window, then the frames we - // computed for the window it is attached to can not be used because the dock is - // effectively part of the underlying window and the attached window is floating on top - // of the whole thing. So, we ignore the attached window and explicitly compute the - // frames that would be appropriate without the dock. - vf.set(displayFrames.mDock); - cf.set(displayFrames.mDock); - of.set(displayFrames.mDock); - df.set(displayFrames.mDock); + // Here's a special case: if this attached window is a panel that is + // above the dock window, and the window it is attached to is below + // the dock window, then the frames we computed for the window it is + // attached to can not be used because the dock is effectively part + // of the underlying window and the attached window is floating on top + // of the whole thing. So, we ignore the attached window and explicitly + // compute the frames that would be appropriate without the dock. + df.left = of.left = cf.left = vf.left = mDockLeft; + df.top = of.top = cf.top = vf.top = mDockTop; + df.right = of.right = cf.right = vf.right = mDockRight; + df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom; } else { - // The effective display frame of the attached window depends on whether it is taking - // care of insetting its content. If not, we need to use the parent's content frame so - // that the entire window is positioned within that content. Otherwise we can use the - // overscan frame and let the attached window take care of positioning its content - // appropriately. + // The effective display frame of the attached window depends on + // whether it is taking care of insetting its content. If not, + // we need to use the parent's content frame so that the entire + // window is positioned within that content. Otherwise we can use + // the overscan frame and let the attached window take care of + // positioning its content appropriately. if (adjust != SOFT_INPUT_ADJUST_RESIZE) { // Set the content frame of the attached window to the parent's decor frame // (same as content frame when IME isn't present) if specifically requested by @@ -4702,37 +4847,51 @@ public class PhoneWindowManager implements WindowManagerPolicy { cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0 ? attached.getContentFrameLw() : attached.getOverscanFrameLw()); } else { - // If the window is resizing, then we want to base the content frame on our attached - // content frame to resize...however, things can be tricky if the attached window is - // NOT in resize mode, in which case its content frame will be larger. - // Ungh. So to deal with that, make sure the content frame we end up using is not - // covering the IM dock. + // If the window is resizing, then we want to base the content + // frame on our attached content frame to resize... however, + // things can be tricky if the attached window is NOT in resize + // mode, in which case its content frame will be larger. + // Ungh. So to deal with that, make sure the content frame + // we end up using is not covering the IM dock. cf.set(attached.getContentFrameLw()); if (attached.isVoiceInteraction()) { - cf.intersectUnchecked(displayFrames.mVoiceContent); + if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft; + if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop; + if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight; + if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom; } else if (attached.getSurfaceLayer() < mDockLayer) { - cf.intersectUnchecked(displayFrames.mContent); + if (cf.left < mContentLeft) cf.left = mContentLeft; + if (cf.top < mContentTop) cf.top = mContentTop; + if (cf.right > mContentRight) cf.right = mContentRight; + if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; } } df.set(insetDecors ? attached.getDisplayFrameLw() : cf); of.set(insetDecors ? attached.getOverscanFrameLw() : cf); vf.set(attached.getVisibleFrameLw()); } - // The LAYOUT_IN_SCREEN flag is used to determine whether the attached window should be - // positioned relative to its parent or the entire screen. - pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 ? attached.getFrameLw() : df); - } - - private void applyStableConstraints(int sysui, int fl, Rect r, DisplayFrames displayFrames) { - if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) == 0) { - return; - } - // If app is requesting a stable layout, don't let the content insets go below the stable - // values. - if ((fl & FLAG_FULLSCREEN) != 0) { - r.intersectUnchecked(displayFrames.mStableFullscreen); - } else { - r.intersectUnchecked(displayFrames.mStable); + // The LAYOUT_IN_SCREEN flag is used to determine whether the attached + // window should be positioned relative to its parent or the entire + // screen. + pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 + ? attached.getFrameLw() : df); + } + + private void applyStableConstraints(int sysui, int fl, Rect r) { + if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { + // If app is requesting a stable layout, don't let the + // content insets go below the stable values. + if ((fl & FLAG_FULLSCREEN) != 0) { + if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; + if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; + if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; + if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; + } else { + if (r.left < mStableLeft) r.left = mStableLeft; + if (r.top < mStableTop) r.top = mStableTop; + if (r.right > mStableRight) r.right = mStableRight; + if (r.bottom > mStableBottom) r.bottom = mStableBottom; + } } } @@ -4747,7 +4906,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public void layoutWindowLw(WindowState win, WindowState attached, DisplayFrames displayFrames) { + public void layoutWindowLw(WindowState win, WindowState attached) { // We've already done the navigation bar, status bar, and all screen decor windows. If the // status bar can receive input, we need to layout it again to accommodate for the IME // window. @@ -4761,10 +4920,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); if (needsToOffsetInputMethodTarget) { if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state"); - offsetInputMethodWindowLw(mLastInputMethodWindow, displayFrames); + offsetInputMethodWindowLw(mLastInputMethodWindow); } - final int type = attrs.type; final int fl = PolicyControl.getWindowFlags(win, attrs); final int pfl = attrs.privateFlags; final int sim = attrs.softInputMode; @@ -4785,83 +4943,120 @@ public class PhoneWindowManager implements WindowManagerPolicy { final int adjust = sim & SOFT_INPUT_MASK_ADJUST; - sf.set(displayFrames.mStable); + if (isDefaultDisplay) { + sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom); + } else { + sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom); + } - if (type == TYPE_INPUT_METHOD) { - vf.set(displayFrames.mDock); - cf.set(displayFrames.mDock); - of.set(displayFrames.mDock); - df.set(displayFrames.mDock); - pf.set(displayFrames.mDock); + if (!isDefaultDisplay) { + // TODO: Need to fix this and above to take into account decor windows. + if (attached != null) { + // If this window is attached to another, our display + // frame is the same as the one we are attached to. + setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); + } else { + // Give the window full screen. + pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; + pf.top = df.top = of.top = cf.top = mOverscanScreenTop; + pf.right = df.right = of.right = cf.right + = mOverscanScreenLeft + mOverscanScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom + = mOverscanScreenTop + mOverscanScreenHeight; + } + } else if (attrs.type == TYPE_INPUT_METHOD) { + pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; + pf.top = df.top = of.top = cf.top = vf.top = mDockTop; + pf.right = df.right = of.right = cf.right = vf.right = mDockRight; // IM dock windows layout below the nav bar... - pf.bottom = df.bottom = of.bottom = displayFrames.mUnrestricted.bottom; + pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; // ...with content insets above the nav bar - cf.bottom = vf.bottom = displayFrames.mStable.bottom; + cf.bottom = vf.bottom = mStableBottom; if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) { // The status bar forces the navigation bar while it's visible. Make sure the IME // avoids the navigation bar in that case. if (mNavigationBarPosition == NAV_BAR_RIGHT) { - pf.right = df.right = of.right = cf.right = vf.right = - displayFrames.mStable.right; + pf.right = df.right = of.right = cf.right = vf.right = mStableRight; } else if (mNavigationBarPosition == NAV_BAR_LEFT) { - pf.left = df.left = of.left = cf.left = vf.left = displayFrames.mStable.left; + pf.left = df.left = of.left = cf.left = vf.left = mStableLeft; } } // IM dock windows always go to the bottom of the screen. attrs.gravity = Gravity.BOTTOM; mDockLayer = win.getSurfaceLayer(); - } else if (type == TYPE_VOICE_INTERACTION) { - of.set(displayFrames.mUnrestricted); - df.set(displayFrames.mUnrestricted); - pf.set(displayFrames.mUnrestricted); + } else if (attrs.type == TYPE_VOICE_INTERACTION) { + pf.left = df.left = of.left = mUnrestrictedScreenLeft; + pf.top = df.top = of.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; if (adjust != SOFT_INPUT_ADJUST_RESIZE) { - cf.set(displayFrames.mDock); + cf.left = mDockLeft; + cf.top = mDockTop; + cf.right = mDockRight; + cf.bottom = mDockBottom; } else { - cf.set(displayFrames.mContent); + cf.left = mContentLeft; + cf.top = mContentTop; + cf.right = mContentRight; + cf.bottom = mContentBottom; } if (adjust != SOFT_INPUT_ADJUST_NOTHING) { - vf.set(displayFrames.mCurrent); + vf.left = mCurLeft; + vf.top = mCurTop; + vf.right = mCurRight; + vf.bottom = mCurBottom; } else { vf.set(cf); } - } else if (type == TYPE_WALLPAPER) { - layoutWallpaper(displayFrames, pf, df, of, cf); + } else if (attrs.type == TYPE_WALLPAPER) { + layoutWallpaper(win, pf, df, of, cf); } else if (win == mStatusBar) { - of.set(displayFrames.mUnrestricted); - df.set(displayFrames.mUnrestricted); - pf.set(displayFrames.mUnrestricted); - cf.set(displayFrames.mStable); - vf.set(displayFrames.mStable); + pf.left = df.left = of.left = mUnrestrictedScreenLeft; + pf.top = df.top = of.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; + pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop; + cf.left = vf.left = mStableLeft; + cf.top = vf.top = mStableTop; + cf.right = vf.right = mStableRight; + vf.bottom = mStableBottom; if (adjust == SOFT_INPUT_ADJUST_RESIZE) { - cf.bottom = displayFrames.mContent.bottom; + cf.bottom = mContentBottom; } else { - cf.bottom = displayFrames.mDock.bottom; - vf.bottom = displayFrames.mContent.bottom; + cf.bottom = mDockBottom; + vf.bottom = mContentBottom; } } else { - dcf.set(displayFrames.mSystem); - final boolean inheritTranslucentDecor = - (attrs.privateFlags & PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; + + // Default policy decor for the default display + dcf.left = mSystemLeft; + dcf.top = mSystemTop; + dcf.right = mSystemRight; + dcf.bottom = mSystemBottom; + final boolean inheritTranslucentDecor = (attrs.privateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; final boolean isAppWindow = - type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW; + attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && + attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; final boolean topAtRest = win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw(); if (isAppWindow && !inheritTranslucentDecor && !topAtRest) { if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 - && (fl & FLAG_FULLSCREEN) == 0 - && (fl & FLAG_TRANSLUCENT_STATUS) == 0 - && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 + && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0 + && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0 + && (fl & WindowManager.LayoutParams. + FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) { // Ensure policy decor includes status bar - dcf.top = displayFrames.mStable.top; + dcf.top = mStableTop; } - if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0 + if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 - && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) { + && (fl & WindowManager.LayoutParams. + FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) { // Ensure policy decor includes navigation bar - dcf.bottom = displayFrames.mStable.bottom; - dcf.right = displayFrames.mStable.right; + dcf.bottom = mStableBottom; + dcf.right = mStableRight; } } @@ -4869,83 +5064,117 @@ public class PhoneWindowManager implements WindowManagerPolicy { == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN, INSET_DECOR"); - // This is the case for a normal activity window: we want it to cover all of the - // screen space, and it can take care of moving its contents to account for screen - // decorations that intrude into that space. + // This is the case for a normal activity window: we want it + // to cover all of the screen space, and it can take care of + // moving its contents to account for screen decorations that + // intrude into that space. if (attached != null) { // If this window is attached to another, our display // frame is the same as the one we are attached to. - setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf, - displayFrames); + setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); } else { - if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) { - // Status bar panels are the only windows who can go on top of the status - // bar. They are protected by the STATUS_BAR_SERVICE permission, so they - // have the same privileges as the status bar itself. + if (attrs.type == TYPE_STATUS_BAR_PANEL + || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { + // Status bar panels are the only windows who can go on top of + // the status bar. They are protected by the STATUS_BAR_SERVICE + // permission, so they have the same privileges as the status + // bar itself. // // However, they should still dodge the navigation bar if it exists. pf.left = df.left = of.left = hasNavBar - ? displayFrames.mDock.left : displayFrames.mUnrestricted.left; - pf.top = df.top = of.top = displayFrames.mUnrestricted.top; + ? mDockLeft : mUnrestrictedScreenLeft; + pf.top = df.top = of.top = mUnrestrictedScreenTop; pf.right = df.right = of.right = hasNavBar - ? displayFrames.mRestricted.right - : displayFrames.mUnrestricted.right; + ? mRestrictedScreenLeft+mRestrictedScreenWidth + : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; pf.bottom = df.bottom = of.bottom = hasNavBar - ? displayFrames.mRestricted.bottom - : displayFrames.mUnrestricted.bottom; + ? mRestrictedScreenTop+mRestrictedScreenHeight + : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; if (DEBUG_LAYOUT) Slog.v(TAG, String.format( "Laying out status bar window: (%d,%d - %d,%d)", pf.left, pf.top, pf.right, pf.bottom)); } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 - && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) { + && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { // Asking to layout into the overscan region, so give it that pure // unrestricted area. - of.set(displayFrames.mOverscan); - df.set(displayFrames.mOverscan); - pf.set(displayFrames.mOverscan); + pf.left = df.left = of.left = mOverscanScreenLeft; + pf.top = df.top = of.top = mOverscanScreenTop; + pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth; + pf.bottom = df.bottom = of.bottom = mOverscanScreenTop + + mOverscanScreenHeight; } else if (canHideNavigationBar() && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 - && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) { - // Asking for layout as if the nav bar is hidden, lets the application - // extend into the unrestricted overscan screen area. We only do this for - // application windows to ensure no window that can be above the nav bar can - // do this. - df.set(displayFrames.mOverscan); - pf.set(displayFrames.mOverscan); - // We need to tell the app about where the frame inside the overscan is, so - // it can inset its content by that amount -- it didn't ask to actually - // extend itself into the overscan region. - of.set(displayFrames.mUnrestricted); + && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { + // Asking for layout as if the nav bar is hidden, lets the + // application extend into the unrestricted overscan screen area. We + // only do this for application windows to ensure no window that + // can be above the nav bar can do this. + pf.left = df.left = mOverscanScreenLeft; + pf.top = df.top = mOverscanScreenTop; + pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; + pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; + // We need to tell the app about where the frame inside the overscan + // is, so it can inset its content by that amount -- it didn't ask + // to actually extend itself into the overscan region. + of.left = mUnrestrictedScreenLeft; + of.top = mUnrestrictedScreenTop; + of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; + of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; } else { - df.set(displayFrames.mRestrictedOverscan); - pf.set(displayFrames.mRestrictedOverscan); + pf.left = df.left = mRestrictedOverscanScreenLeft; + pf.top = df.top = mRestrictedOverscanScreenTop; + pf.right = df.right = mRestrictedOverscanScreenLeft + + mRestrictedOverscanScreenWidth; + pf.bottom = df.bottom = mRestrictedOverscanScreenTop + + mRestrictedOverscanScreenHeight; // We need to tell the app about where the frame inside the overscan // is, so it can inset its content by that amount -- it didn't ask // to actually extend itself into the overscan region. - of.set(displayFrames.mUnrestricted); + of.left = mUnrestrictedScreenLeft; + of.top = mUnrestrictedScreenTop; + of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; + of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; } if ((fl & FLAG_FULLSCREEN) == 0) { if (win.isVoiceInteraction()) { - cf.set(displayFrames.mVoiceContent); + cf.left = mVoiceContentLeft; + cf.top = mVoiceContentTop; + cf.right = mVoiceContentRight; + cf.bottom = mVoiceContentBottom; } else { if (adjust != SOFT_INPUT_ADJUST_RESIZE) { - cf.set(displayFrames.mDock); + cf.left = mDockLeft; + cf.top = mDockTop; + cf.right = mDockRight; + cf.bottom = mDockBottom; } else { - cf.set(displayFrames.mContent); + cf.left = mContentLeft; + cf.top = mContentTop; + cf.right = mContentRight; + cf.bottom = mContentBottom; } } } else { - // Full screen windows are always given a layout that is as if the status - // bar and other transient decors are gone. This is to avoid bad states when - // moving from a window that is not hiding the status bar to one that is. - cf.set(displayFrames.mRestricted); + // Full screen windows are always given a layout that is as if the + // status bar and other transient decors are gone. This is to avoid + // bad states when moving from a window that is not hding the + // status bar to one that is. + cf.left = mRestrictedScreenLeft; + cf.top = mRestrictedScreenTop; + cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth; + cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight; } - applyStableConstraints(sysUiFl, fl, cf, displayFrames); + applyStableConstraints(sysUiFl, fl, cf); if (adjust != SOFT_INPUT_ADJUST_NOTHING) { - vf.set(displayFrames.mCurrent); + vf.left = mCurLeft; + vf.top = mCurTop; + vf.right = mCurRight; + vf.bottom = mCurBottom; } else { vf.set(cf); } @@ -4953,70 +5182,86 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { - if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() - + "): IN_SCREEN"); + if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + + "): IN_SCREEN"); // A window that has requested to fill the entire screen just // gets everything, period. - if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_STATUS_BAR_SUB_PANEL) { - cf.set(displayFrames.mUnrestricted); - of.set(displayFrames.mUnrestricted); - df.set(displayFrames.mUnrestricted); - pf.set(displayFrames.mUnrestricted); - if (hasNavBar) { - pf.left = df.left = of.left = cf.left = displayFrames.mDock.left; - pf.right = df.right = of.right = cf.right = displayFrames.mRestricted.right; - pf.bottom = df.bottom = of.bottom = cf.bottom = - displayFrames.mRestricted.bottom; - } + if (attrs.type == TYPE_STATUS_BAR_PANEL + || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { + pf.left = df.left = of.left = cf.left = hasNavBar + ? mDockLeft : mUnrestrictedScreenLeft; + pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = cf.right = hasNavBar + ? mRestrictedScreenLeft + mRestrictedScreenWidth + : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar + ? mRestrictedScreenTop + mRestrictedScreenHeight + : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; if (DEBUG_LAYOUT) Slog.v(TAG, String.format( "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", pf.left, pf.top, pf.right, pf.bottom)); - } else if (type == TYPE_VOLUME_OVERLAY) { + } else if (attrs.type == TYPE_VOLUME_OVERLAY) { // Volume overlay covers everything, including the status and navbar - cf.set(displayFrames.mUnrestricted); - of.set(displayFrames.mUnrestricted); - df.set(displayFrames.mUnrestricted); - pf.set(displayFrames.mUnrestricted); + pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; + pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = cf.right = + mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = + mUnrestrictedScreenTop + mUnrestrictedScreenHeight; if (DEBUG_LAYOUT) Slog.v(TAG, String.format( "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", pf.left, pf.top, pf.right, pf.bottom)); - } else if (type == TYPE_NAVIGATION_BAR || type == TYPE_NAVIGATION_BAR_PANEL) { + } else if (attrs.type == TYPE_NAVIGATION_BAR + || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { // The navigation bar has Real Ultimate Power. - of.set(displayFrames.mUnrestricted); - df.set(displayFrames.mUnrestricted); - pf.set(displayFrames.mUnrestricted); + pf.left = df.left = of.left = mUnrestrictedScreenLeft; + pf.top = df.top = of.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = mUnrestrictedScreenLeft + + mUnrestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + + mUnrestrictedScreenHeight; if (DEBUG_LAYOUT) Slog.v(TAG, String.format( "Laying out navigation bar window: (%d,%d - %d,%d)", pf.left, pf.top, pf.right, pf.bottom)); - } else if ((type == TYPE_SECURE_SYSTEM_OVERLAY || type == TYPE_SCREENSHOT) + } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY + || attrs.type == TYPE_BOOT_PROGRESS + || attrs.type == TYPE_SCREENSHOT) && ((fl & FLAG_FULLSCREEN) != 0)) { // Fullscreen secure system overlays get what they ask for. Screenshot region // selection overlay should also expand to full screen. - cf.set(displayFrames.mOverscan); - of.set(displayFrames.mOverscan); - df.set(displayFrames.mOverscan); - pf.set(displayFrames.mOverscan); - } else if (type == TYPE_BOOT_PROGRESS) { + pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; + pf.top = df.top = of.top = cf.top = mOverscanScreenTop; + pf.right = df.right = of.right = cf.right = mOverscanScreenLeft + + mOverscanScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop + + mOverscanScreenHeight; + } else if (attrs.type == TYPE_BOOT_PROGRESS) { // Boot progress screen always covers entire display. - cf.set(displayFrames.mOverscan); - of.set(displayFrames.mOverscan); - df.set(displayFrames.mOverscan); - pf.set(displayFrames.mOverscan); + pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; + pf.top = df.top = of.top = cf.top = mOverscanScreenTop; + pf.right = df.right = of.right = cf.right = mOverscanScreenLeft + + mOverscanScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop + + mOverscanScreenHeight; } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 - && type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW) { - // Asking to layout into the overscan region, so give it that pure unrestricted - // area. - cf.set(displayFrames.mOverscan); - of.set(displayFrames.mOverscan); - df.set(displayFrames.mOverscan); - pf.set(displayFrames.mOverscan); + && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { + // Asking to layout into the overscan region, so give it that pure + // unrestricted area. + pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; + pf.top = df.top = of.top = cf.top = mOverscanScreenTop; + pf.right = df.right = of.right = cf.right + = mOverscanScreenLeft + mOverscanScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom + = mOverscanScreenTop + mOverscanScreenHeight; } else if (canHideNavigationBar() && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 - && (type == TYPE_STATUS_BAR - || type == TYPE_TOAST - || type == TYPE_DOCK_DIVIDER - || type == TYPE_VOICE_INTERACTION_STARTING - || (type >= FIRST_APPLICATION_WINDOW && type <= LAST_SUB_WINDOW))) { + && (attrs.type == TYPE_STATUS_BAR + || attrs.type == TYPE_TOAST + || attrs.type == TYPE_DOCK_DIVIDER + || attrs.type == TYPE_VOICE_INTERACTION_STARTING + || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW + && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { // Asking for layout as if the nav bar is hidden, lets the // application extend into the unrestricted screen area. We // only do this for application windows (or toasts) to ensure no window that @@ -5024,76 +5269,102 @@ public class PhoneWindowManager implements WindowManagerPolicy { // XXX This assumes that an app asking for this will also // ask for layout in only content. We can't currently figure out // what the screen would be if only laying out to hide the nav bar. - cf.set(displayFrames.mUnrestricted); - of.set(displayFrames.mUnrestricted); - df.set(displayFrames.mUnrestricted); - pf.set(displayFrames.mUnrestricted); + pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; + pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; + pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft + + mUnrestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop + + mUnrestrictedScreenHeight; } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) { - of.set(displayFrames.mRestricted); - df.set(displayFrames.mRestricted); - pf.set(displayFrames.mRestricted); + pf.left = df.left = of.left = mRestrictedScreenLeft; + pf.top = df.top = of.top = mRestrictedScreenTop; + pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop + + mRestrictedScreenHeight; if (adjust != SOFT_INPUT_ADJUST_RESIZE) { - cf.set(displayFrames.mDock); + cf.left = mDockLeft; + cf.top = mDockTop; + cf.right = mDockRight; + cf.bottom = mDockBottom; } else { - cf.set(displayFrames.mContent); + cf.left = mContentLeft; + cf.top = mContentTop; + cf.right = mContentRight; + cf.bottom = mContentBottom; } } else { - cf.set(displayFrames.mRestricted); - of.set(displayFrames.mRestricted); - df.set(displayFrames.mRestricted); - pf.set(displayFrames.mRestricted); + pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; + pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; + pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft + + mRestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop + + mRestrictedScreenHeight; } - applyStableConstraints(sysUiFl, fl, cf,displayFrames); + applyStableConstraints(sysUiFl, fl, cf); if (adjust != SOFT_INPUT_ADJUST_NOTHING) { - vf.set(displayFrames.mCurrent); + vf.left = mCurLeft; + vf.top = mCurTop; + vf.right = mCurRight; + vf.bottom = mCurBottom; } else { vf.set(cf); } } else if (attached != null) { - if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() - + "): attached to " + attached); + if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + + "): attached to " + attached); // A child window should be placed inside of the same visible // frame that its parent had. - setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf, - displayFrames); + setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf); } else { if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window"); // Otherwise, a normal window must be placed inside the content // of all screen decorations. - if (type == TYPE_STATUS_BAR_PANEL || type == TYPE_VOLUME_OVERLAY) { + if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) { // Status bar panels and the volume dialog are the only windows who can go on - // top of the status bar. They are protected by the STATUS_BAR_SERVICE - // permission, so they have the same privileges as the status bar itself. - cf.set(displayFrames.mRestricted); - of.set(displayFrames.mRestricted); - df.set(displayFrames.mRestricted); - pf.set(displayFrames.mRestricted); - } else if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) { + // top of the status bar. They are protected by the STATUS_BAR_SERVICE + // permission, so they have the same privileges as the status + // bar itself. + pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; + pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; + pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft + + mRestrictedScreenWidth; + pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop + + mRestrictedScreenHeight; + } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) { // These dialogs are stable to interim decor changes. - cf.set(displayFrames.mStable); - of.set(displayFrames.mStable); - df.set(displayFrames.mStable); - pf.set(displayFrames.mStable); + pf.left = df.left = of.left = cf.left = mStableLeft; + pf.top = df.top = of.top = cf.top = mStableTop; + pf.right = df.right = of.right = cf.right = mStableRight; + pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom; } else { - pf.set(displayFrames.mContent); + pf.left = mContentLeft; + pf.top = mContentTop; + pf.right = mContentRight; + pf.bottom = mContentBottom; if (win.isVoiceInteraction()) { - cf.set(displayFrames.mVoiceContent); - of.set(displayFrames.mVoiceContent); - df.set(displayFrames.mVoiceContent); + df.left = of.left = cf.left = mVoiceContentLeft; + df.top = of.top = cf.top = mVoiceContentTop; + df.right = of.right = cf.right = mVoiceContentRight; + df.bottom = of.bottom = cf.bottom = mVoiceContentBottom; } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) { - cf.set(displayFrames.mDock); - of.set(displayFrames.mDock); - df.set(displayFrames.mDock); + df.left = of.left = cf.left = mDockLeft; + df.top = of.top = cf.top = mDockTop; + df.right = of.right = cf.right = mDockRight; + df.bottom = of.bottom = cf.bottom = mDockBottom; } else { - cf.set(displayFrames.mContent); - of.set(displayFrames.mContent); - df.set(displayFrames.mContent); + df.left = of.left = cf.left = mContentLeft; + df.top = of.top = cf.top = mContentTop; + df.right = of.right = cf.right = mContentRight; + df.bottom = of.bottom = cf.bottom = mContentBottom; } if (adjust != SOFT_INPUT_ADJUST_NOTHING) { - vf.set(displayFrames.mCurrent); + vf.left = mCurLeft; + vf.top = mCurTop; + vf.right = mCurRight; + vf.bottom = mCurBottom; } else { vf.set(cf); } @@ -5103,11 +5374,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. // Also, we don't allow windows in multi-window mode to extend out of the screen. - if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && type != TYPE_SYSTEM_ERROR + if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR && !win.isInMultiWindowMode()) { df.left = df.top = -10000; df.right = df.bottom = 10000; - if (type != TYPE_WALLPAPER) { + if (attrs.type != TYPE_WALLPAPER) { of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000; of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; } @@ -5123,7 +5394,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { osf.set(cf.left, cf.top, cf.right, cf.bottom); int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); if (outset > 0) { - int rotation = displayFrames.mRotation; + int rotation = mDisplayRotation; if (rotation == Surface.ROTATION_0) { osf.bottom += outset; } else if (rotation == Surface.ROTATION_90) { @@ -5140,7 +5411,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() + ": sim=#" + Integer.toHexString(sim) - + " attach=" + attached + " type=" + type + + " attach=" + attached + " type=" + attrs.type + String.format(" flags=0x%08x", fl) + " pf=" + pf.toShortString() + " df=" + df.toShortString() + " of=" + of.toShortString() @@ -5153,42 +5424,62 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Dock windows carve out the bottom of the screen, so normal windows // can't appear underneath them. - if (type == TYPE_INPUT_METHOD && win.isVisibleLw() + if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw() && !win.getGivenInsetsPendingLw()) { setLastInputMethodWindowLw(null, null); - offsetInputMethodWindowLw(win, displayFrames); + offsetInputMethodWindowLw(win); } - if (type == TYPE_VOICE_INTERACTION && win.isVisibleLw() + if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw() && !win.getGivenInsetsPendingLw()) { - offsetVoiceInputWindowLw(win, displayFrames); + offsetVoiceInputWindowLw(win); } } - private void layoutWallpaper(DisplayFrames displayFrames, Rect pf, Rect df, Rect of, Rect cf) { - // The wallpaper has Real Ultimate Power, but we want to tell it about the overscan area. - df.set(displayFrames.mOverscan); - pf.set(displayFrames.mOverscan); - cf.set(displayFrames.mUnrestricted); - of.set(displayFrames.mUnrestricted); + private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) { + + // The wallpaper also has Real Ultimate Power, but we want to tell + // it about the overscan area. + pf.left = df.left = mOverscanScreenLeft; + pf.top = df.top = mOverscanScreenTop; + pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; + pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; + of.left = cf.left = mUnrestrictedScreenLeft; + of.top = cf.top = mUnrestrictedScreenTop; + of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; + of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; } - private void offsetInputMethodWindowLw(WindowState win, DisplayFrames displayFrames) { + private void offsetInputMethodWindowLw(WindowState win) { int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); top += win.getGivenContentInsetsLw().top; - displayFrames.mContent.bottom = Math.min(displayFrames.mContent.bottom, top); - displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top); + if (mContentBottom > top) { + mContentBottom = top; + } + if (mVoiceContentBottom > top) { + mVoiceContentBottom = top; + } top = win.getVisibleFrameLw().top; top += win.getGivenVisibleInsetsLw().top; - displayFrames.mCurrent.bottom = Math.min(displayFrames.mCurrent.bottom, top); + if (mCurBottom > top) { + mCurBottom = top; + } if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" - + displayFrames.mDock.bottom + " mContentBottom=" - + displayFrames.mContent.bottom + " mCurBottom=" + displayFrames.mCurrent.bottom); + + mDockBottom + " mContentBottom=" + + mContentBottom + " mCurBottom=" + mCurBottom); } - private void offsetVoiceInputWindowLw(WindowState win, DisplayFrames displayFrames) { + private void offsetVoiceInputWindowLw(WindowState win) { int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); top += win.getGivenContentInsetsLw().top; - displayFrames.mVoiceContent.bottom = Math.min(displayFrames.mVoiceContent.bottom, top); + if (mVoiceContentBottom > top) { + mVoiceContentBottom = top; + } + } + + /** {@inheritDoc} */ + @Override + public void finishLayoutLw() { + return; } /** {@inheritDoc} */ @@ -8041,6 +8332,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } @Override + public int getInputMethodWindowVisibleHeightLw() { + return mDockBottom - mCurBottom; + } + + @Override public void setCurrentUserLw(int newUserId) { mCurrentUserId = newUserId; if (mKeyguardDelegate != null) { @@ -8129,6 +8425,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); + new Rect(mStableLeft, mStableTop, mStableRight, mStableBottom).writeToProto(proto, + STABLE_BOUNDS); proto.end(token); } @@ -8234,6 +8532,58 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); + pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); + pw.print(","); pw.print(mOverscanScreenTop); + pw.print(") "); pw.print(mOverscanScreenWidth); + pw.print("x"); pw.println(mOverscanScreenHeight); + if (mOverscanLeft != 0 || mOverscanTop != 0 + || mOverscanRight != 0 || mOverscanBottom != 0) { + pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); + pw.print(" top="); pw.print(mOverscanTop); + pw.print(" right="); pw.print(mOverscanRight); + pw.print(" bottom="); pw.println(mOverscanBottom); + } + pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); + pw.print(mRestrictedOverscanScreenLeft); + pw.print(","); pw.print(mRestrictedOverscanScreenTop); + pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); + pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); + pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); + pw.print(","); pw.print(mUnrestrictedScreenTop); + pw.print(") "); pw.print(mUnrestrictedScreenWidth); + pw.print("x"); pw.println(mUnrestrictedScreenHeight); + pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); + pw.print(","); pw.print(mRestrictedScreenTop); + pw.print(") "); pw.print(mRestrictedScreenWidth); + pw.print("x"); pw.println(mRestrictedScreenHeight); + pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); + pw.print(","); pw.print(mStableFullscreenTop); + pw.print(")-("); pw.print(mStableFullscreenRight); + pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); + pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); + pw.print(","); pw.print(mStableTop); + pw.print(")-("); pw.print(mStableRight); + pw.print(","); pw.print(mStableBottom); pw.println(")"); + pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); + pw.print(","); pw.print(mSystemTop); + pw.print(")-("); pw.print(mSystemRight); + pw.print(","); pw.print(mSystemBottom); pw.println(")"); + pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); + pw.print(","); pw.print(mCurTop); + pw.print(")-("); pw.print(mCurRight); + pw.print(","); pw.print(mCurBottom); pw.println(")"); + pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); + pw.print(","); pw.print(mContentTop); + pw.print(")-("); pw.print(mContentRight); + pw.print(","); pw.print(mContentBottom); pw.println(")"); + pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); + pw.print(","); pw.print(mVoiceContentTop); + pw.print(")-("); pw.print(mVoiceContentRight); + pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); + pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); + pw.print(","); pw.print(mDockTop); + pw.print(")-("); pw.print(mDockRight); + pw.print(","); pw.print(mDockBottom); pw.println(")"); pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index c4b810f7d30b..67d62e103f17 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -104,7 +104,6 @@ import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE; import static com.android.server.wm.proto.DisplayProto.ABOVE_APP_WINDOWS; import static com.android.server.wm.proto.DisplayProto.BELOW_APP_WINDOWS; -import static com.android.server.wm.proto.DisplayProto.DISPLAY_FRAMES; import static com.android.server.wm.proto.DisplayProto.DISPLAY_INFO; import static com.android.server.wm.proto.DisplayProto.DOCKED_STACK_DIVIDER_CONTROLLER; import static com.android.server.wm.proto.DisplayProto.DPI; @@ -148,7 +147,6 @@ import android.view.WindowManagerPolicy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ToBooleanFunction; import com.android.internal.view.IInputMethodClient; -import android.view.DisplayFrames; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -224,8 +222,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private final DisplayInfo mDisplayInfo = new DisplayInfo(); private final Display mDisplay; private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); - DisplayFrames mDisplayFrames; - /** * For default display it contains real metrics, empty for others. * @see WindowManagerService#createWatermarkInTransaction() @@ -289,6 +285,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private boolean mLastWallpaperVisible = false; private Rect mBaseDisplayRect = new Rect(); + private Rect mContentRect = new Rect(); // Accessed directly by all users. private boolean mLayoutNeeded; @@ -548,7 +545,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo w.mLayoutNeeded = false; w.prelayout(); final boolean firstLayout = !w.isLaidOut(); - mService.mPolicy.layoutWindowLw(w, null, mDisplayFrames); + mService.mPolicy.layoutWindowLw(w, null); w.mLayoutSeq = mService.mLayoutSeq; // If this is the first layout, we need to initialize the last inset values as @@ -589,7 +586,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } w.mLayoutNeeded = false; w.prelayout(); - mService.mPolicy.layoutWindowLw(w, w.getParentWindow(), mDisplayFrames); + mService.mPolicy.layoutWindowLw(w, w.getParentWindow()); w.mLayoutSeq = mService.mLayoutSeq; if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame + " mContainingFrame=" + w.mContainingFrame @@ -761,7 +758,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo display.getMetrics(mDisplayMetrics); isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; mService = service; - mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo); initializeDisplayBaseInfo(); mDividerControllerLocked = new DockedStackDividerController(service, this); mPinnedStackControllerLocked = new PinnedStackController(service, this); @@ -1133,13 +1129,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return true; } - void configureDisplayPolicy() { - mService.mPolicy.setInitialDisplaySize(getDisplay(), - mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity); - - mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo); - } - /** * Update {@link #mDisplayInfo} and other internal variables when display is rotated or config * changed. @@ -1755,7 +1744,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } void getContentRect(Rect out) { - out.set(mDisplayFrames.mContent); + out.set(mContentRect); } TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) { @@ -1858,8 +1847,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mTmpRect2.setEmpty(); for (int stackNdx = mTaskStackContainers.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final TaskStack stack = mTaskStackContainers.getChildAt(stackNdx); - stack.setTouchExcludeRegion(focusedTask, delta, mTouchExcludeRegion, - mDisplayFrames.mContent, mTmpRect2); + stack.setTouchExcludeRegion( + focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2); } // If we removed the focused task above, add it back and only leave its // outside touch area in the exclusion. TapDectector is not interested in @@ -2036,7 +2025,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final boolean imeOnTop = (imeDockSide == DOCKED_TOP); final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM); final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock(); - final int imeHeight = mDisplayFrames.getInputMethodWindowVisibleHeight(); + final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw(); final boolean imeHeightChanged = imeVisible && imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor(); @@ -2178,7 +2167,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo if (screenRotationAnimation != null) { screenRotationAnimation.writeToProto(proto, SCREEN_ROTATION_ANIMATION); } - mDisplayFrames.writeToProto(proto, DISPLAY_FRAMES); proto.end(token); } @@ -2258,9 +2246,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo pw.println(subPrefix + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment); } - - pw.println(); - mDisplayFrames.dump(prefix, pw); } @Override @@ -2886,22 +2871,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final int dw = mDisplayInfo.logicalWidth; final int dh = mDisplayInfo.logicalHeight; + if (DEBUG_LAYOUT) { Slog.v(TAG, "-------------------------------------"); Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh); } - mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo); - // TODO: Not sure if we really need to set the rotation here since we are updating from the - // display info above... - mDisplayFrames.mRotation = mRotation; - mService.mPolicy.beginLayoutLw(mDisplayFrames, getConfiguration().uiMode); + mService.mPolicy.beginLayoutLw(mDisplayId, dw, dh, mRotation, getConfiguration().uiMode); if (isDefaultDisplay) { // Not needed on non-default displays. mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw(); mService.mScreenRect.set(0, 0, dw, dh); } + mService.mPolicy.getContentRectLw(mContentRect); + int seq = mService.mLayoutSeq + 1; if (seq < 0) seq = 0; mService.mLayoutSeq = seq; @@ -2931,6 +2915,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mService.mInputMonitor.updateInputWindowsLw(false /*force*/); } + mService.mPolicy.finishLayoutLw(); mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER); } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index f541926ea304..bcb6e6736d04 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -247,7 +247,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { if (mService.mDisplayManagerInternal != null) { mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager( displayId, displayInfo); - dc.configureDisplayPolicy(); + mService.configureDisplayPolicyLocked(dc); // Tap Listeners are supported for: // 1. All physical displays (multi-display). diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index df51be18936d..06527675349a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -245,7 +245,6 @@ import com.android.server.LocalServices; import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.input.InputManagerService; -import android.view.DisplayFrames; import com.android.server.power.ShutdownThread; import com.android.server.utils.PriorityDump; @@ -1453,19 +1452,23 @@ public class WindowManagerService extends IWindowManager.Stub prepareNoneTransitionForRelaunching(atoken); } - final DisplayFrames displayFrames = displayContent.mDisplayFrames; - // TODO: Not sure if onDisplayInfoUpdated() call is needed. - displayFrames.onDisplayInfoUpdated(displayContent.getDisplayInfo()); - final Rect taskBounds; - if (atoken != null && atoken.getTask() != null) { - taskBounds = mTmpRect; - atoken.getTask().getBounds(mTmpRect); + if (displayContent.isDefaultDisplay) { + final DisplayInfo displayInfo = displayContent.getDisplayInfo(); + final Rect taskBounds; + if (atoken != null && atoken.getTask() != null) { + taskBounds = mTmpRect; + atoken.getTask().getBounds(mTmpRect); + } else { + taskBounds = null; + } + if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayInfo.rotation, + displayInfo.logicalWidth, displayInfo.logicalHeight, outContentInsets, + outStableInsets, outOutsets)) { + res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR; + } } else { - taskBounds = null; - } - if (mPolicy.getInsetHintLw(win.mAttrs, taskBounds, displayFrames, outContentInsets, - outStableInsets, outOutsets)) { - res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_NAV_BAR; + outContentInsets.setEmpty(); + outStableInsets.setEmpty(); } if (mInTouchMode) { @@ -4665,7 +4668,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN); - getDefaultDisplayContentLocked().configureDisplayPolicy(); + configureDisplayPolicyLocked(getDefaultDisplayContentLocked()); } try { @@ -5522,7 +5525,7 @@ public class WindowManagerService extends IWindowManager.Stub if (!mDisplayReady) { return; } - displayContent.configureDisplayPolicy(); + configureDisplayPolicyLocked(displayContent); displayContent.setLayoutNeeded(); final int displayId = displayContent.getDisplayId(); @@ -5543,6 +5546,18 @@ public class WindowManagerService extends IWindowManager.Stub mWindowPlacerLocked.performSurfacePlacement(); } + void configureDisplayPolicyLocked(DisplayContent displayContent) { + mPolicy.setInitialDisplaySize(displayContent.getDisplay(), + displayContent.mBaseDisplayWidth, + displayContent.mBaseDisplayHeight, + displayContent.mBaseDisplayDensity); + + DisplayInfo displayInfo = displayContent.getDisplayInfo(); + mPolicy.setDisplayOverscan(displayContent.getDisplay(), + displayInfo.overscanLeft, displayInfo.overscanTop, + displayInfo.overscanRight, displayInfo.overscanBottom); + } + /** * Get an array with display ids ordered by focus priority - last items should be given * focus first. Sparse array just maps position to displayId. @@ -7355,9 +7370,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public int getInputMethodWindowVisibleHeight() { synchronized (mWindowMap) { - // TODO(multi-display): Have caller pass in the display they are interested in. - final DisplayContent dc = getDefaultDisplayContentLocked(); - return dc.mDisplayFrames.getInputMethodWindowVisibleHeight(); + return mPolicy.getInputMethodWindowVisibleHeightLw(); } } diff --git a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java index f23bd6209614..9c805446fb9b 100644 --- a/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/ScreenDecorWindowTests.java @@ -16,12 +16,8 @@ package com.android.server.wm; -import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.graphics.Color.BLUE; import static android.graphics.Color.RED; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; -import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Gravity.BOTTOM; import static android.view.Gravity.LEFT; import static android.view.Gravity.RIGHT; @@ -37,23 +33,16 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static org.junit.Assert.assertEquals; import android.app.Activity; -import android.app.ActivityOptions; import android.app.Instrumentation; import android.content.Context; -import android.content.Intent; import android.graphics.PixelFormat; import android.graphics.Point; -import android.hardware.display.DisplayManager; -import android.hardware.display.VirtualDisplay; -import android.media.ImageReader; import android.os.Handler; import android.platform.test.annotations.Presubmit; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; +import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; -import android.util.Pair; -import android.view.Display; -import android.view.DisplayInfo; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; @@ -62,6 +51,7 @@ import android.widget.TextView; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -75,6 +65,7 @@ import java.util.ArrayList; */ // TODO: Add test for FLAG_FULLSCREEN which hides the status bar and also other flags. // TODO: Test non-Activity windows. +// TODO: Test secondary display. @SmallTest // TODO(b/68957554) //@Presubmit @@ -87,26 +78,22 @@ public class ScreenDecorWindowTests { private WindowManager mWm; private ArrayList<View> mWindows = new ArrayList<>(); + @Rule + public ActivityTestRule<TestActivity> mTestActivityRule = new ActivityTestRule<>( + TestActivity.class, false /* initialTouchMode */, false /* launchActivity */); private Activity mTestActivity; - private VirtualDisplay mDisplay; - private ImageReader mImageReader; private int mDecorThickness; private int mHalfDecorThickness; @Before public void setUp() { - final Pair<VirtualDisplay, ImageReader> result = createDisplay(); - mDisplay = result.first; - mImageReader = result.second; - final Display display = mDisplay.getDisplay(); - final Context dContext = mContext.createDisplayContext(display); - mWm = dContext.getSystemService(WindowManager.class); - mTestActivity = startActivityOnDisplay(TestActivity.class, display.getDisplayId()); + mWm = mContext.getSystemService(WindowManager.class); final Point size = new Point(); - mDisplay.getDisplay().getRealSize(size); + mWm.getDefaultDisplay().getSize(size); mDecorThickness = Math.min(size.x, size.y) / 3; mHalfDecorThickness = mDecorThickness / 2; + mTestActivity = launchActivity(mTestActivityRule); } @After @@ -114,9 +101,7 @@ public class ScreenDecorWindowTests { while (!mWindows.isEmpty()) { removeWindow(mWindows.get(0)); } - finishActivity(mTestActivity); - mDisplay.release(); - mImageReader.close(); + finishActivity(mTestActivityRule); } @Test @@ -274,46 +259,21 @@ public class ScreenDecorWindowTests { Assert.assertTrue("Excepted " + first + " >= " + second, first >= second); } - private void finishActivity(Activity a) { - if (a == null) { - return; - } - a.finish(); - waitForIdle(); - } - - private void waitForIdle() { - mInstrumentation.waitForIdleSync(); - } - - private Activity startActivityOnDisplay(Class<?> cls, int displayId) { - final Intent intent = new Intent(mContext, cls); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); - final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchDisplayId(displayId); - final Activity activity = mInstrumentation.startActivitySync(intent, options.toBundle()); + private Activity launchActivity(ActivityTestRule activityRule) { + final Activity activity = activityRule.launchActivity(null); waitForIdle(); - - assertEquals(displayId, activity.getDisplay().getDisplayId()); return activity; } - private Pair<VirtualDisplay, ImageReader> createDisplay() { - final DisplayManager dm = mContext.getSystemService(DisplayManager.class); - final DisplayInfo displayInfo = new DisplayInfo(); - final Display defaultDisplay = dm.getDisplay(DEFAULT_DISPLAY); - defaultDisplay.getDisplayInfo(displayInfo); - final String name = "ScreenDecorWindowTests"; - int flags = VIRTUAL_DISPLAY_FLAG_PRESENTATION | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; - - final ImageReader imageReader = ImageReader.newInstance( - displayInfo.logicalWidth, displayInfo.logicalHeight, PixelFormat.RGBA_8888, 2); - - final VirtualDisplay display = dm.createVirtualDisplay(name, displayInfo.logicalWidth, - displayInfo.logicalHeight, displayInfo.logicalDensityDpi, imageReader.getSurface(), - flags); + private void finishActivity(ActivityTestRule activityRule) { + final Activity activity = activityRule.getActivity(); + if (activity != null) { + activity.finish(); + } + } - return Pair.create(display, imageReader); + private void waitForIdle() { + mInstrumentation.waitForIdleSync(); } public static class TestActivity extends Activity { diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 53d0bfbb5cf7..5134c26ddf91 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -133,6 +133,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override + public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { + + } + + @Override public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) { return 0; } @@ -285,11 +290,40 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override + public void beginLayoutLw(int displayId, int displayWidth, int displayHeight, + int displayRotation, int uiMode) { + + } + + @Override public int getSystemDecorLayerLw() { return 0; } @Override + public void getContentRectLw(Rect r) { + + } + + @Override + public void layoutWindowLw(WindowState win, + WindowState attached) { + + } + + @Override + public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, + int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, + Rect outStableInsets, Rect outOutsets) { + return false; + } + + @Override + public void finishLayoutLw() { + + } + + @Override public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { } @@ -548,6 +582,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override + public int getInputMethodWindowVisibleHeightLw() { + return 0; + } + + @Override public void setCurrentUserLw(int newUserId) { } |