diff options
3 files changed, 135 insertions, 6 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a8e66ec..789fe40 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -2479,6 +2479,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * @hide + * + * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked + * out of the public fields to keep the undefined bits out of the developer's way. + * + * Flag to specify that the status bar should temporarily overlay underlying content + * that is otherwise assuming the status bar is hidden. The status bar will typically + * have some degree of transparency while in this temporary overlay mode. + */ + public static final int STATUS_BAR_OVERLAY = 0x04000000; + + /** + * @hide */ public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index d98f08e..498d869 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -132,6 +132,9 @@ public class PhoneStatusBar extends BaseStatusBar { private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER; + private static final long AUTOHIDE_TIMEOUT_MS = 3000; + private static final float TRANSPARENT_ALPHA = 0.7f; + // fling gesture tuning parameters, scaled to display density private float mSelfExpandVelocityPx; // classic value: 2000px/s private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up") @@ -304,6 +307,15 @@ public class PhoneStatusBar extends BaseStatusBar { } }; + private boolean mAutohideSuspended; + + private final Runnable mAutohide = new Runnable() { + @Override + public void run() { + int requested = mSystemUiVisibility & ~View.STATUS_BAR_OVERLAY; + notifyUiVisibilityChanged(requested); + }}; + @Override public void start() { mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) @@ -1384,6 +1396,8 @@ public class PhoneStatusBar extends BaseStatusBar { } visibilityChanged(true); + + suspendAutohide(); } public void animateCollapsePanels() { @@ -1666,6 +1680,11 @@ public class PhoneStatusBar extends BaseStatusBar { mPostCollapseCleanup.run(); mPostCollapseCleanup = null; } + + // Reschedule suspended auto-hide if necessary + if (mAutohideSuspended) { + scheduleAutohide(); + } } /** @@ -1812,6 +1831,7 @@ public class PhoneStatusBar extends BaseStatusBar { hideCling(); } + suspendAutohide(); return false; } @@ -1855,10 +1875,41 @@ public class PhoneStatusBar extends BaseStatusBar { setStatusBarLowProfile(lightsOut); } - notifyUiVisibilityChanged(); + if (0 != (diff & View.STATUS_BAR_OVERLAY)) { + boolean overlay = 0 != (vis & View.STATUS_BAR_OVERLAY); + if (overlay) { + setTransparent(true); + scheduleAutohide(); + } else { + setTransparent(false); + cancelAutohide(); + } + } + notifyUiVisibilityChanged(mSystemUiVisibility); } } + private void suspendAutohide() { + mHandler.removeCallbacks(mAutohide); + mAutohideSuspended = (0 != (mSystemUiVisibility & View.STATUS_BAR_OVERLAY)); + } + + private void cancelAutohide() { + mAutohideSuspended = false; + mHandler.removeCallbacks(mAutohide); + } + + private void scheduleAutohide() { + cancelAutohide(); + mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS); + } + + private void setTransparent(boolean transparent) { + float alpha = transparent ? TRANSPARENT_ALPHA : 1; + if (DEBUG) Slog.d(TAG, "Setting alpha to " + alpha); + mStatusBarView.setAlpha(alpha); + } + private void setStatusBarLowProfile(boolean lightsOut) { if (mLightsOutAnimation == null) { final View notifications = mStatusBarView.findViewById(R.id.notification_icon_area); @@ -1913,9 +1964,9 @@ public class PhoneStatusBar extends BaseStatusBar { } } - private void notifyUiVisibilityChanged() { + private void notifyUiVisibilityChanged(int vis) { try { - mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility); + mWindowManagerService.statusBarVisibilityChanged(vis); } catch (RemoteException ex) { } } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 9283243..2988727 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -146,6 +146,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; + static public final String ACTION_HIDEYBARS = "android.intent.action.HIDEYBARS"; + /** * These are the system UI flags that, when changing, can cause the layout * of the screen to change. @@ -544,6 +546,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { } MyOrientationListener mOrientationListener; + private static final int HIDEYBARS_NONE = 0; + private static final int HIDEYBARS_SHOWING = 1; + private static final int HIDEYBARS_HIDING = 2; + private int mHideybars; + + BroadcastReceiver mHideybarsReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + receivedHideybars(intent.getAction()); + } + }; + IStatusBarService getStatusBarService() { synchronized (mServiceAquireLock) { if (mStatusBarService == null) { @@ -892,6 +906,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); context.registerReceiver(mMultiuserReceiver, filter); + // register for hideybars + filter = new IntentFilter(); + filter.addAction(ACTION_HIDEYBARS); + context.registerReceiver(mHideybarsReceiver, filter); + mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); mLongPressVibePattern = getLongIntArray(mContext.getResources(), com.android.internal.R.array.config_longPressVibePattern); @@ -2480,6 +2499,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public int adjustSystemUiVisibilityLw(int visibility) { + if (mHideybars == HIDEYBARS_SHOWING && 0 == (visibility & View.STATUS_BAR_OVERLAY)) { + mHideybars = HIDEYBARS_HIDING; + mStatusBar.hideLw(true); + } // Reset any bits in mForceClearingStatusBarVisibility that // are now clear. mResettingSystemUiFlags &= visibility; @@ -2715,9 +2738,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // For layout, the status bar is always at the top with our fixed height. mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; + boolean statusBarOverlay = (mLastSystemUiFlags & View.STATUS_BAR_OVERLAY) != 0; + // If the status bar is hidden, we don't want to cause // windows behind it to scroll. - if (mStatusBar.isVisibleLw()) { + if (mStatusBar.isVisibleLw() && !statusBarOverlay) { // 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. @@ -2735,12 +2760,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { mContentLeft, mContentTop, mContentRight, mContentBottom, mCurLeft, mCurTop, mCurRight, mCurBottom)); } - if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()) { + if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() && !statusBarOverlay) { // If the 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 (mHideybars == HIDEYBARS_HIDING && !mStatusBar.isVisibleLw()) { + // Hideybars have finished animating out, cleanup and reset alpha + mHideybars = HIDEYBARS_NONE; + updateSystemUiVisibilityLw(); + } } } } @@ -3320,7 +3350,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the // case though. - if (topIsFullscreen) { + if (mHideybars == HIDEYBARS_SHOWING) { + if (mStatusBar.showLw(true)) { + changes |= FINISH_LAYOUT_REDO_LAYOUT; + } + } else if (topIsFullscreen) { if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar"); if (mStatusBar.hideLw(true)) { changes |= FINISH_LAYOUT_REDO_LAYOUT; @@ -4060,6 +4094,23 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + private void receivedHideybars(String action) { + synchronized(mLock) { + if (action.equals(ACTION_HIDEYBARS)) { + if (mHideybars == HIDEYBARS_SHOWING) { + if (DEBUG) Slog.d(TAG, "Not showing hideybars, already shown"); + return; + } + if (mStatusBar.isDisplayedLw()) { + if (DEBUG) Slog.d(TAG, "Not showing hideybars, status bar already visible"); + return; + } + mHideybars = HIDEYBARS_SHOWING; + updateSystemUiVisibilityLw(); + } + } + } + @Override public void screenTurnedOff(int why) { EventLog.writeEvent(70000, 0); @@ -4794,12 +4845,27 @@ public class PhoneWindowManager implements WindowManagerPolicy { // will quickly lose focus once it correctly gets hidden. return 0; } + int tmpVisibility = mFocusedWindow.getSystemUiVisibility() & ~mResettingSystemUiFlags & ~mForceClearedSystemUiFlags; if (mForcingShowNavBar && mFocusedWindow.getSurfaceLayer() < mForcingShowNavBarLayer) { tmpVisibility &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; } + + boolean hideybarsAllowed = + (mFocusedWindow.getAttrs().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 + || mFocusedWindow.getAttrs().type == TYPE_STATUS_BAR; + if (mHideybars == HIDEYBARS_SHOWING) { + if (!hideybarsAllowed) { + mHideybars = HIDEYBARS_NONE; + } else { + tmpVisibility |= View.STATUS_BAR_OVERLAY; + if ((mLastSystemUiFlags & View.STATUS_BAR_OVERLAY) == 0) { + mStatusBar.showLw(true); + } + } + } final int visibility = tmpVisibility; int diff = visibility ^ mLastSystemUiFlags; final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); |