diff --git a/core/java/android/view/animation/AnimationSet.java b/core/java/android/view/animation/AnimationSet.java index 14d3d19851f12..71c74506b9178 100644 --- a/core/java/android/view/animation/AnimationSet.java +++ b/core/java/android/view/animation/AnimationSet.java @@ -114,7 +114,7 @@ public class AnimationSet extends Animation { * Constructor to use when building an AnimationSet from code * * @param shareInterpolator Pass true if all of the animations in this set - * should use the interpolator assocciated with this AnimationSet. + * should use the interpolator associated with this AnimationSet. * Pass false if each animation should use its own interpolator. */ public AnimationSet(boolean shareInterpolator) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index a3b492ce7cf98..24f7d83e41514 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -70,6 +70,7 @@ import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SearchPanelView; import com.android.systemui.SystemUI; +import com.android.systemui.statusbar.phone.BarTransitions; import com.android.systemui.statusbar.policy.NotificationRowLayout; import java.util.ArrayList; @@ -827,7 +828,7 @@ public abstract class BaseStatusBar extends SystemUI implements // Construct the icon. final StatusBarIconView iconView = new StatusBarIconView(mContext, notification.getPackageName() + "/0x" + Integer.toHexString(notification.getId()), - notification.getNotification()); + notification.getNotification(), getStatusBarMode()); iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(), @@ -850,6 +851,10 @@ public abstract class BaseStatusBar extends SystemUI implements return entry; } + protected int getStatusBarMode() { + return BarTransitions.MODE_OPAQUE; + } + protected void addNotificationViews(NotificationData.Entry entry) { // Add the expanded view and icon. int pos = mNotificationData.add(entry); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 5bda813fdaa23..5689bfafd9ad6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -16,6 +16,11 @@ package com.android.systemui.statusbar; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; +import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; + +import android.animation.ObjectAnimator; import android.app.Notification; import android.content.Context; import android.content.pm.PackageManager; @@ -48,10 +53,13 @@ public class StatusBarIconView extends AnimatedImageView { private int mNumberY; private String mNumberText; private Notification mNotification; + private final float mAlphaWhenOpaque; + private final float mAlphaWhenTransparent = 1; - public StatusBarIconView(Context context, String slot, Notification notification) { + public StatusBarIconView(Context context, String slot, Notification notification, int mode) { super(context); final Resources res = context.getResources(); + mAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); mSlot = slot; mNumberPain = new Paint(); mNumberPain.setTextAlign(Paint.Align.CENTER); @@ -68,8 +76,7 @@ public class StatusBarIconView extends AnimatedImageView { final float scale = (float)imageBounds / (float)outerBounds; setScaleX(scale); setScaleY(scale); - final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); - setAlpha(alpha); + setAlpha(getAlphaFor(mode)); } setScaleType(ImageView.ScaleType.CENTER); @@ -78,13 +85,22 @@ public class StatusBarIconView extends AnimatedImageView { public StatusBarIconView(Context context, AttributeSet attrs) { super(context, attrs); final Resources res = context.getResources(); + mAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size); final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size); final float scale = (float)imageBounds / (float)outerBounds; setScaleX(scale); setScaleY(scale); - final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1); - setAlpha(alpha); + setAlpha(getAlphaFor(MODE_OPAQUE)); + } + + public ObjectAnimator animateTransitionTo(int mode) { + return ObjectAnimator.ofFloat(this, "alpha", getAlpha(), getAlphaFor(mode)); + } + + public float getAlphaFor(int mode) { + final boolean isTransparent = mode == MODE_SEMI_TRANSPARENT || mode == MODE_TRANSPARENT; + return isTransparent ? mAlphaWhenTransparent : mAlphaWhenOpaque; } private static boolean streq(String a, String b) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java index 292ea7ceb73f4..318ec5117bde4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java @@ -60,6 +60,10 @@ public class BarTransitions { mSemiTransparent = res.getColor(R.color.status_bar_background_semi_transparent); } + public int getMode() { + return mMode; + } + public void setTransparent(Drawable transparent) { mTransparent = transparent; if (mMode == MODE_TRANSPARENT) { @@ -80,16 +84,24 @@ public class BarTransitions { onTransition(oldMode, mMode, animate); } + protected Integer getBackgroundColor(int mode) { + if (mode == MODE_SEMI_TRANSPARENT) return mSemiTransparent; + if (mode == MODE_OPAQUE) return mOpaque; + return null; + } + protected void onTransition(int oldMode, int newMode, boolean animate) { cancelBackgroundColorAnimation(); - if (animate && oldMode == MODE_SEMI_TRANSPARENT && newMode == MODE_OPAQUE) { - startBackgroundColorAnimation(mSemiTransparent, mOpaque); - } else if (animate && oldMode == MODE_OPAQUE && newMode == MODE_SEMI_TRANSPARENT) { - startBackgroundColorAnimation(mOpaque, mSemiTransparent); - } else if (newMode == MODE_OPAQUE || newMode == MODE_SEMI_TRANSPARENT) { - mTarget.setBackgroundColor(newMode == MODE_OPAQUE ? mOpaque : mSemiTransparent); + Integer oldColor = getBackgroundColor(oldMode); + Integer newColor = getBackgroundColor(newMode); + if (oldColor != null && newColor != null) { + if (animate) { + startBackgroundColorAnimation(oldColor, newColor); + } else { + mTarget.setBackgroundColor(newColor); + } } else { - mTarget.setBackground(newMode == MODE_TRANSPARENT? mTransparent + mTarget.setBackground(newMode == MODE_TRANSPARENT ? mTransparent : newMode == MODE_SEMI_TRANSPARENT ? new ColorDrawable(mSemiTransparent) : new ColorDrawable(mOpaque)); } 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 02346d91fcdc0..fffb130d20286 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -843,7 +843,7 @@ public class PhoneStatusBar extends BaseStatusBar { public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { if (SPEW) Log.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex + " icon=" + icon); - StatusBarIconView view = new StatusBarIconView(mContext, slot, null); + StatusBarIconView view = new StatusBarIconView(mContext, slot, null, getStatusBarMode()); view.set(icon); mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize)); } @@ -1921,6 +1921,11 @@ public class PhoneStatusBar extends BaseStatusBar { } } + @Override + protected int getStatusBarMode() { + return mStatusBarView.getBarTransitions().getMode(); + } + private int updateBarMode(int oldVis, int newVis, BarTransitions transitions, int transientFlag, int transparentFlag, int windowState) { final int oldMode = barMode(oldVis, transientFlag, transparentFlag); @@ -1928,8 +1933,7 @@ public class PhoneStatusBar extends BaseStatusBar { if (oldMode == newMode) { return -1; // no mode change } - boolean animate = windowState == StatusBarManager.WINDOW_STATE_SHOWING - && oldMode == MODE_SEMI_TRANSPARENT && newMode == MODE_OPAQUE; + final boolean animate = windowState == StatusBarManager.WINDOW_STATE_SHOWING; transitions.transitionTo(newMode, animate); return newMode; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index 910d4c4b7199a..2e9ee879c6d91 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -16,20 +16,26 @@ package com.android.systemui.statusbar.phone; +import android.animation.Animator; +import android.animation.AnimatorSet; import android.app.ActivityManager; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.EventLog; import android.util.Log; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import com.android.systemui.EventLogTags; import com.android.systemui.R; +import com.android.systemui.statusbar.StatusBarIconView; + +import java.util.ArrayList; +import java.util.List; public class PhoneStatusBarView extends PanelBar { private static final String TAG = "PhoneStatusBarView"; @@ -49,10 +55,56 @@ public class PhoneStatusBarView extends PanelBar { private final StatusBarTransitions mBarTransitions; private final class StatusBarTransitions extends BarTransitions { + private final int mTransparent; + public StatusBarTransitions(Context context) { super(context, PhoneStatusBarView.this); final Resources res = context.getResources(); - mTransparent = res.getDrawable(R.color.status_bar_background_transparent); + mTransparent = res.getColor(R.color.status_bar_background_transparent); + } + + @Override + protected Integer getBackgroundColor(int mode) { + if (mode == MODE_TRANSPARENT) return mTransparent; + return super.getBackgroundColor(mode); + } + + @Override + protected void onTransition(int oldMode, int newMode, boolean animate) { + super.onTransition(oldMode, newMode, animate); + if (animate) { + List animators = new ArrayList(); + for(StatusBarIconView icon : findStatusBarIcons()) { + animators.add(icon.animateTransitionTo(newMode)); + } + AnimatorSet set = new AnimatorSet(); + set.playTogether(animators); + set.start(); + } else { + for(StatusBarIconView icon : findStatusBarIcons()) { + icon.setAlpha(icon.getAlphaFor(newMode)); + } + } + } + + private List findStatusBarIcons() { + List icons = new ArrayList(); + findStatusBarIcons(icons, findViewById(R.id.moreIcon)); + findStatusBarIcons(icons, findViewById(R.id.statusIcons)); + findStatusBarIcons(icons, findViewById(R.id.notificationIcons)); + return icons; + } + + private void findStatusBarIcons(List icons, View v) { + if (v instanceof StatusBarIconView) { + icons.add((StatusBarIconView) v); + } else if (v instanceof ViewGroup) { + ViewGroup group = (ViewGroup) v; + final int N = group.getChildCount(); + for (int i = 0; i < N; i++) { + findStatusBarIcons(icons, group.getChildAt(i)); + } + } } } diff --git a/policy/src/com/android/internal/policy/impl/BarController.java b/policy/src/com/android/internal/policy/impl/BarController.java index bcecff2821275..554fd1cc737e6 100644 --- a/policy/src/com/android/internal/policy/impl/BarController.java +++ b/policy/src/com/android/internal/policy/impl/BarController.java @@ -20,6 +20,7 @@ import android.app.StatusBarManager; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemClock; import android.util.Slog; import android.view.View; import android.view.WindowManagerPolicy.WindowState; @@ -38,9 +39,12 @@ public class BarController { private static final int TRANSIENT_BAR_SHOWING = 1; private static final int TRANSIENT_BAR_HIDING = 2; + private static final int TRANSPARENT_ANIMATION_DELAY_MS = 1000; + private final String mTag; private final int mTransientFlag; private final int mUnhideFlag; + private final int mTransparentFlag; private final int mStatusBarManagerId; private final Handler mHandler; private final Object mServiceAquireLock = new Object(); @@ -50,11 +54,14 @@ public class BarController { private int mState; private int mTransientBarState; private boolean mPendingShow; + private long mLastTransparent; - public BarController(String tag, int transientFlag, int unhideFlag, int statusBarManagerId) { + public BarController(String tag, int transientFlag, int unhideFlag, int transparentFlag, + int statusBarManagerId) { mTag = "BarController." + tag; mTransientFlag = transientFlag; mUnhideFlag = unhideFlag; + mTransparentFlag = transparentFlag; mStatusBarManagerId = statusBarManagerId; mHandler = new Handler(); } @@ -77,6 +84,10 @@ public class BarController { return mTransientBarState == TRANSIENT_BAR_SHOWING; } + public boolean wasRecentlyTransparent() { + return (SystemClock.uptimeMillis() - mLastTransparent) < TRANSPARENT_ANIMATION_DELAY_MS; + } + public void adjustSystemUiVisibilityLw(int oldVis, int vis) { if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING && (vis & mTransientFlag) == 0) { @@ -181,11 +192,17 @@ public class BarController { vis |= mTransientFlag; // ignore clear requests until transition completes vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile } + if ((vis & mTransparentFlag) != 0 || (oldVis & mTransparentFlag) != 0) { + mLastTransparent = SystemClock.uptimeMillis(); + } return vis; } private void setTransientBarState(int state) { if (mWin != null && state != mTransientBarState) { + if (mTransientBarState == TRANSIENT_BAR_SHOWING || state == TRANSIENT_BAR_SHOWING) { + mLastTransparent = SystemClock.uptimeMillis(); + } mTransientBarState = state; if (DEBUG) Slog.d(mTag, "New state: " + transientBarStateToString(state)); } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index f3e7f0a7bd1aa..da98f27d25a3f 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -556,11 +556,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { private final BarController mStatusBarController = new BarController("StatusBar", View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_UNHIDE, + View.SYSTEM_UI_FLAG_TRANSPARENT_STATUS, StatusBarManager.WINDOW_STATUS_BAR); private final BarController mNavigationBarController = new BarController("NavigationBar", View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_UNHIDE, + View.SYSTEM_UI_FLAG_TRANSPARENT_NAVIGATION, StatusBarManager.WINDOW_NAVIGATION_BAR); private TransientNavigationConfirmation mTransientNavigationConfirmation; @@ -2739,7 +2741,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // We currently want to hide the navigation UI. mNavigationBarController.setBarShowingLw(false); } - if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) { + if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw() + && !mNavigationBarController.wasRecentlyTransparent()) { // 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. @@ -2762,7 +2765,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // We currently want to hide the navigation UI. mNavigationBarController.setBarShowingLw(false); } - if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) { + if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw() + && !mNavigationBarController.wasRecentlyTransparent()) { // 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. @@ -2832,7 +2836,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { mCurLeft, mCurTop, mCurRight, mCurBottom)); } if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() - && !statusBarTransient && !statusBarTransparent) { + && !statusBarTransient && !statusBarTransparent + && !mStatusBarController.wasRecentlyTransparent()) { // 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. @@ -5011,7 +5016,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mForcingShowNavBar && mFocusedWindow.getSurfaceLayer() < mForcingShowNavBarLayer) { tmpVisibility &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; } - final int visibility = updateTransientBarsLw(mLastSystemUiFlags, tmpVisibility); + final int visibility = updateSystemBarsLw(mLastSystemUiFlags, tmpVisibility); final int diff = visibility ^ mLastSystemUiFlags; final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); if (diff == 0 && mLastFocusNeedsMenu == needsMenu @@ -5039,7 +5044,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return diff; } - private int updateTransientBarsLw(int oldVis, int vis) { + private int updateSystemBarsLw(int oldVis, int vis) { if (ImmersiveModeTesting.enabled) { vis = ImmersiveModeTesting.applyForced(mFocusedWindow, vis); }