From 8f5701bd9f1149d672d63758e522dcfaaa258a73 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Mon, 4 Apr 2016 18:36:02 -0700 Subject: [PATCH] Only force drawing status bar background if target >= N Since forcing it all the time has the potential of breaking compatibility with apps, we don't want to do this. Instead, we only force it if the app targets >= N. We communicate this to window manager with PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND. We introduced this for 2-up split-screen. If we have an app that doesn't draw the status bar background by itself, we just force the whole bar to be black. The same applies for windows that used translucent status bar - we also force the whole bar to be black Bug: 27285627 Change-Id: I7f1ceaa364f8a4e851935f77aa5e8d913bf11791 --- core/java/android/view/WindowManager.java | 7 +++ .../android/internal/policy/DecorView.java | 10 ++-- .../android/internal/policy/PhoneWindow.java | 7 ++- .../server/policy/PhoneWindowManager.java | 50 +++++++++++++------ 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index ddad23aa721af..584233c434f13 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1239,6 +1239,13 @@ public interface WindowManager extends ViewManager { */ public static final int PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME = 0x00010000; + /** + * Flag to indicate that this window is always drawing the status bar background, no matter + * what the other flags are. + * @hide + */ + public static final int PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND = 0x00020000; + /** * Control flags that are private to the platform. * @hide diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index 0c916c052e174..f9ac5632b49b9 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -45,7 +45,6 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.Shader; import android.graphics.drawable.Drawable; -import android.os.Build; import android.os.RemoteException; import android.util.DisplayMetrics; import android.util.Log; @@ -81,6 +80,8 @@ import static android.app.ActivityManager.StackId; import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static android.os.Build.VERSION_CODES.M; +import static android.os.Build.VERSION_CODES.N; import static android.view.View.MeasureSpec.AT_MOST; import static android.view.View.MeasureSpec.EXACTLY; import static android.view.View.MeasureSpec.getMode; @@ -171,7 +172,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind private final Interpolator mShowInterpolator; private final Interpolator mHideInterpolator; private final int mBarEnterExitDuration; - private final boolean mForceWindowDrawsStatusBarBackground; + final boolean mForceWindowDrawsStatusBarBackground; private final int mSemiTransparentStatusBarColor; private final BackgroundFallback mBackgroundFallback = new BackgroundFallback(); @@ -236,7 +237,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind mBarEnterExitDuration = context.getResources().getInteger( R.integer.dock_enter_exit_duration); mForceWindowDrawsStatusBarBackground = context.getResources().getBoolean( - R.bool.config_forceWindowDrawsStatusBarBackground); + R.bool.config_forceWindowDrawsStatusBarBackground) + && context.getApplicationInfo().targetSdkVersion >= N; mSemiTransparentStatusBarColor = context.getResources().getColor( R.color.system_bar_background_semi_transparent, null /* theme */); @@ -2210,7 +2212,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind public void onDestroyActionMode(ActionMode mode) { mWrapped.onDestroyActionMode(mode); final boolean isMncApp = mContext.getApplicationInfo().targetSdkVersion - >= Build.VERSION_CODES.M; + >= M; final boolean isPrimary; final boolean isFloating; if (isMncApp) { diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index c64328bffc698..d2ff9bc4c7d44 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -2435,6 +2435,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000); } + WindowManager.LayoutParams params = getAttributes(); + // Non-floating windows on high end devices must put up decor beneath the system bars and // therefore must know about visibility changes of those. if (!mIsFloating && ActivityManager.isHighEndGfx()) { @@ -2444,6 +2446,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags()); } + if (mDecor.mForceWindowDrawsStatusBarBackground) { + params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; + } } if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) { decor.setSystemUiVisibility( @@ -2459,8 +2464,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } - WindowManager.LayoutParams params = getAttributes(); - if (!hasSoftInputMode()) { params.softInputMode = a.getInt( R.styleable.Window_windowSoftInputMode, diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fb56a0c7ee3e0..5ce451fb71260 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -692,9 +692,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private final LogDecelerateInterpolator mLogDecelerateInterpolator = new LogDecelerateInterpolator(100, 0); - private boolean mForceWindowDrawsStatusBarBackground; private final MutableBoolean mTmpBoolean = new MutableBoolean(false); - private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_DISABLE_POINTER_LOCATION = 2; private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; @@ -1745,8 +1743,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mScreenshotChordEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_enableScreenshotChord); - mForceWindowDrawsStatusBarBackground = mContext.getResources().getBoolean( - R.bool.config_forceWindowDrawsStatusBarBackground); mGlobalKeyManager = new GlobalKeyManager(mContext); @@ -2217,9 +2213,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) { attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; } + final boolean forceWindowDrawsStatusBarBackground = + (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) + != 0; if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 - || (mForceWindowDrawsStatusBarBackground - && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT)) { + || forceWindowDrawsStatusBarBackground + && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) { attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; } } @@ -4274,6 +4273,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } final int fl = PolicyControl.getWindowFlags(win, attrs); + final int pfl = attrs.privateFlags; final int sim = attrs.softInputMode; final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null); @@ -4369,7 +4369,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0 && (fl & WindowManager.LayoutParams. FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 - && !mForceWindowDrawsStatusBarBackground) { + && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) { // Ensure policy decor includes status bar dcf.top = mStableTop; } @@ -7243,6 +7243,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { return vis; } + private boolean drawsSystemBarBackground(WindowState win) { + return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; + } + + private boolean forcesDrawStatusBarBackground(WindowState win) { + return win == null || (win.getAttrs().privateFlags + & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; + } + private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); final boolean freeformStackVisible = @@ -7256,11 +7265,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; // apply translucent bar vis flags - WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen + WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen ? mStatusBar : mTopFullscreenOpaqueWindowState; - vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis); - vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis); + vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); + vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); + final int dockedVis = mStatusBarController.applyTranslucentFlagLw( + mTopDockedOpaqueWindowState, 0, 0); + + final boolean fullscreenDrawsStatusBarBackground = + (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) + && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) + || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); + final boolean dockedDrawsStatusBarBackground = + (drawsSystemBarBackground(mTopDockedOpaqueWindowState) + && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) + || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); // prevent status bar interaction from clearing certain flags int type = win.getAttrs().type; @@ -7277,18 +7297,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { vis = (vis & ~flags) | (oldVis & flags); } - if ((!areTranslucentBarsAllowed() && transWin != mStatusBar) + if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { + vis |= View.STATUS_BAR_TRANSPARENT; + vis &= ~View.STATUS_BAR_TRANSLUCENT; + } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) || forceOpaqueStatusBar) { vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); } vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); - if (mForceWindowDrawsStatusBarBackground) { - vis |= View.STATUS_BAR_TRANSPARENT; - vis &= ~View.STATUS_BAR_TRANSLUCENT; - } - // update status bar boolean immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;