diff options
author | Jorim Jaggi <jjaggi@google.com> | 2015-01-21 19:22:26 +0100 |
---|---|---|
committer | Jorim Jaggi <jjaggi@google.com> | 2015-02-02 16:14:41 +0100 |
commit | 66ac133971f4e2f80cd7cfff89cc6f8a3f7e899f (patch) | |
tree | 27cf9556032b0af30cd977ceaa8f42f1c19de87e /packages/SystemUI | |
parent | d26b16cbdfd24c6a00f889f5a4dd8a00e2213f7f (diff) | |
download | frameworks_base-66ac133971f4e2f80cd7cfff89cc6f8a3f7e899f.zip frameworks_base-66ac133971f4e2f80cd7cfff89cc6f8a3f7e899f.tar.gz frameworks_base-66ac133971f4e2f80cd7cfff89cc6f8a3f7e899f.tar.bz2 |
Split status bar icon management into separate class
Change-Id: Iaacfcb70ff16d894287603d5fc6351598c7450d6
Diffstat (limited to 'packages/SystemUI')
4 files changed, 280 insertions, 246 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index eaec8fa..dda52d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -507,7 +507,6 @@ public abstract class BaseStatusBar extends SystemUI implements ServiceManager.checkService(DreamService.DREAM_SERVICE)); mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); - mSettingsObserver.onChange(false); // set up mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true, mSettingsObserver); @@ -557,6 +556,7 @@ public abstract class BaseStatusBar extends SystemUI implements createAndAddWindows(); + mSettingsObserver.onChange(false); // set up disable(switches[0], false /* animate */); setSystemUiVisibility(switches[1], 0xffffffff); topAppWindowChanged(switches[2] != 0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 20dd3e7..d02cd17 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -147,6 +147,9 @@ public class StatusBarIconView extends AnimatedImageView { } private boolean updateDrawable(boolean withClear) { + if (mIcon == null) { + return false; + } Drawable drawable = getIcon(mIcon); if (drawable == null) { Log.w(TAG, "No icon for slot " + mSlot); @@ -226,6 +229,12 @@ public class StatusBarIconView extends AnimatedImageView { } @Override + public void onRtlPropertiesChanged(int layoutDirection) { + super.onRtlPropertiesChanged(layoutDirection); + updateDrawable(); + } + + @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); 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 d286441..4ffe9b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -32,7 +32,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.TimeInterpolator; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerNative; @@ -82,14 +81,12 @@ import android.provider.Settings; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; -import android.text.TextUtils; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.view.Display; import android.view.Gravity; -import android.view.HardwareCanvas; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -97,23 +94,17 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; -import android.view.ViewPropertyAnimator; import android.view.ViewStub; -import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; -import android.view.animation.Animation; import android.view.animation.AnimationUtils; -import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.animation.PathInterpolator; -import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.statusbar.StatusBarIcon; @@ -172,7 +163,6 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener; -import com.android.systemui.statusbar.stack.StackScrollAlgorithm; import com.android.systemui.statusbar.stack.StackScrollState.ViewState; import com.android.systemui.volume.VolumeComponent; @@ -212,9 +202,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true; - 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 int STATUS_OR_NAV_TRANSIENT = View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT; private static final long AUTOHIDE_TIMEOUT_MS = 3000; @@ -261,8 +248,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, AccessibilityController mAccessibilityController; int mNaturalBarHeight = -1; - int mIconSize = -1; - int mIconHPadding = -1; + Display mDisplay; Point mCurrentDisplaySize = new Point(); @@ -278,23 +264,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, int mPixelFormat; Object mQueueLock = new Object(); - // viewgroup containing the normal contents of the statusbar - LinearLayout mStatusBarContents; - - // right-hand icons - LinearLayout mSystemIconArea; - LinearLayout mSystemIcons; - - // left-hand icons - LinearLayout mStatusIcons; - LinearLayout mStatusIconsKeyguard; - - // the icons themselves - IconMerger mNotificationIcons; - View mNotificationIconArea; - - // [+> - View mMoreIcon; + StatusBarIconController mIconController; // expanded notifications NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window @@ -419,7 +389,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private boolean mDozing; private boolean mScrimSrcModeEnabled; - private Interpolator mLinearOutSlowIn; private Interpolator mLinearInterpolator = new LinearInterpolator(); private Interpolator mBackdropInterpolator = new AccelerateDecelerateInterpolator(); public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); @@ -610,8 +579,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, updateDisplaySize(); // populates mDisplayMetrics updateResources(); - mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size); - mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null); mStatusBarWindow.mService = this; @@ -689,15 +656,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // figure out which pixel-format to use for the status bar. mPixelFormat = PixelFormat.OPAQUE; - mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area); - mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons); - mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons); - mNotificationIconArea = mStatusBarView.findViewById(R.id.notification_icon_area_inner); - mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons); - mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon); - mNotificationIcons.setOverflowIndicator(mMoreIcon); - mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents); - mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById( R.id.notification_stack_scroller); mStackScroller.setLongPressListener(getNotificationLongClicker()); @@ -741,7 +699,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header); mHeader.setActivityStarter(this); mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header); - mStatusIconsKeyguard = (LinearLayout) mKeyguardStatusBar.findViewById(R.id.statusIcons); mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view); mKeyguardBottomArea = (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area); @@ -756,6 +713,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // set the inital view visibility setAreThereNotifications(); + mIconController = new StatusBarIconController( + mContext, mStatusBarView, mKeyguardStatusBar, this); + // Background thread for any controllers that need it. mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); mHandlerThread.start(); @@ -1177,49 +1137,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mWindowManager.removeView(mHeadsUpNotificationView); } - public void refreshAllStatusBarIcons() { - refreshAllIconsForLayout(mStatusIcons); - refreshAllIconsForLayout(mStatusIconsKeyguard); - refreshAllIconsForLayout(mNotificationIcons); - } - - private void refreshAllIconsForLayout(LinearLayout ll) { - final int count = ll.getChildCount(); - for (int n = 0; n < count; n++) { - View child = ll.getChildAt(n); - if (child instanceof StatusBarIconView) { - ((StatusBarIconView) child).updateDrawable(); - } - } - } - 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); - view.set(icon); - mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams( - LayoutParams.WRAP_CONTENT, mIconSize)); - view = new StatusBarIconView(mContext, slot, null); - view.set(icon); - mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams( - LayoutParams.WRAP_CONTENT, mIconSize)); + mIconController.addSystemIcon(slot, index, viewIndex, icon); } public void updateIcon(String slot, int index, int viewIndex, StatusBarIcon old, StatusBarIcon icon) { - if (SPEW) Log.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex - + " old=" + old + " icon=" + icon); - StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex); - view.set(icon); - view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex); - view.set(icon); + mIconController.updateSystemIcon(slot, index, viewIndex, old, icon); } public void removeIcon(String slot, int index, int viewIndex) { - if (SPEW) Log.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex); - mStatusIcons.removeViewAt(viewIndex); - mStatusIconsKeyguard.removeViewAt(viewIndex); + mIconController.removeSystemIcon(slot, index, viewIndex); } public UserHandle getCurrentUserHandle() { @@ -1339,7 +1267,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mNavigationBarView != null) { mNavigationBarView.setLayoutDirection(layoutDirection); } - refreshAllStatusBarIcons(); } private void updateShowSearchHoldoff() { @@ -1480,69 +1407,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, @Override protected void updateNotifications() { - // TODO: Move this into updateNotificationIcons()? - if (mNotificationIcons == null) return; - mNotificationData.filterAndSort(); updateNotificationShade(); - updateNotificationIcons(); - } - - private void updateNotificationIcons() { - final LinearLayout.LayoutParams params - = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight); - - ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications(); - final int N = activeNotifications.size(); - ArrayList<StatusBarIconView> toShow = new ArrayList<>(N); - - // Filter out notifications with low scores. - for (int i = 0; i < N; i++) { - Entry ent = activeNotifications.get(i); - if (ent.notification.getScore() < HIDE_ICONS_BELOW_SCORE && - !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) { - continue; - } - toShow.add(ent.icon); - } - - if (DEBUG) { - Log.d(TAG, "refreshing icons: " + toShow.size() + - " notifications, mNotificationIcons=" + mNotificationIcons); - } - - ArrayList<View> toRemove = new ArrayList<View>(); - for (int i=0; i<mNotificationIcons.getChildCount(); i++) { - View child = mNotificationIcons.getChildAt(i); - if (!toShow.contains(child)) { - toRemove.add(child); - } - } - - final int toRemoveCount = toRemove.size(); - for (int i = 0; i < toRemoveCount; i++) { - mNotificationIcons.removeView(toRemove.get(i)); - } - - for (int i=0; i<toShow.size(); i++) { - View v = toShow.get(i); - if (v.getParent() == null) { - mNotificationIcons.addView(v, i, params); - } - } - - // Resort notification icons - final int childCount = mNotificationIcons.getChildCount(); - for (int i = 0; i < childCount; i++) { - View actual = mNotificationIcons.getChildAt(i); - StatusBarIconView expected = toShow.get(i); - if (actual == expected) { - continue; - } - mNotificationIcons.removeView(expected); - mNotificationIcons.addView(expected, i); - } + mIconController.updateNotificationIcons(mNotificationData); } @Override @@ -1826,14 +1694,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - public void showClock(boolean show) { - if (mStatusBarView == null) return; - View clock = mStatusBarView.findViewById(R.id.clock); - if (clock != null) { - clock.setVisibility(show ? View.VISIBLE : View.GONE); - } - } - private int adjustDisableFlags(int state) { if (!mLaunchTransitionFadingAway && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) { @@ -1882,17 +1742,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, Log.d(TAG, flagdbg.toString()); if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { - mSystemIconArea.animate().cancel(); if ((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) { - animateStatusBarHide(mSystemIconArea, animate); + mIconController.hideSystemIconArea(animate); } else { - animateStatusBarShow(mSystemIconArea, animate); + mIconController.showSystemIconArea(animate); } } if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) { - boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0; - showClock(show); + boolean visible = (state & StatusBarManager.DISABLE_CLOCK) == 0; + mIconController.setClockVisibility(visible); } if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) { if ((state & StatusBarManager.DISABLE_EXPAND) != 0) { @@ -1916,9 +1775,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) { - animateStatusBarHide(mNotificationIconArea, animate); + mIconController.hideNotificationIconArea(animate); } else { - animateStatusBarShow(mNotificationIconArea, animate); + mIconController.showNotificationIconArea(animate); } } @@ -1929,60 +1788,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - /** - * Animates {@code v}, a view that is part of the status bar, out. - */ - private void animateStatusBarHide(final View v, boolean animate) { - v.animate().cancel(); - if (!animate) { - v.setAlpha(0f); - v.setVisibility(View.INVISIBLE); - return; - } - v.animate() - .alpha(0f) - .setDuration(160) - .setStartDelay(0) - .setInterpolator(ALPHA_OUT) - .withEndAction(new Runnable() { - @Override - public void run() { - v.setVisibility(View.INVISIBLE); - } - }); - } - - /** - * Animates {@code v}, a view that is part of the status bar, in. - */ - private void animateStatusBarShow(View v, boolean animate) { - v.animate().cancel(); - v.setVisibility(View.VISIBLE); - if (!animate) { - v.setAlpha(1f); - return; - } - v.animate() - .alpha(1f) - .setDuration(320) - .setInterpolator(ALPHA_IN) - .setStartDelay(50) - - // We need to clean up any pending end action from animateStatusBarHide if we call - // both hide and show in the same frame before the animation actually gets started. - // cancel() doesn't really remove the end action. - .withEndAction(null); - - // Synchronize the motion with the Keyguard fading if necessary. - if (mKeyguardFadingAway) { - v.animate() - .setDuration(mKeyguardFadingAwayDuration) - .setInterpolator(mLinearOutSlowIn) - .setStartDelay(mKeyguardFadingAwayDelay) - .start(); - } - } - @Override protected BaseStatusBar.H createHandler() { return new PhoneStatusBar.H(); @@ -2667,12 +2472,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mNotificationData.dump(pw, " "); } - int N = mStatusIcons.getChildCount(); - pw.println(" system icons: " + N); - for (int i=0; i<N; i++) { - StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i); - pw.println(" [" + i + "] icon=" + ic); - } + mIconController.dump(pw); if (false) { pw.println("see the logcat for a dump of the views we have created."); @@ -2871,10 +2671,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, updateDisplaySize(); // populates mDisplayMetrics updateResources(); - updateClockSize(); repositionNavigationBar(); updateShowSearchHoldoff(); updateRowStates(); + mIconController.updateResources(); mScreenPinningRequest.onConfigurationChanged(); } @@ -2900,8 +2700,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mUserSetupObserver.onChange(false); mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), true, - mUserSetupObserver, - mCurrentUserId); + mUserSetupObserver, mCurrentUserId); } private void setHeadsUpVisibility(boolean vis) { @@ -2931,8 +2730,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } loadDimens(); - mLinearOutSlowIn = AnimationUtils.loadInterpolator( - mContext, android.R.interpolator.linear_out_slow_in); if (mNotificationPanel != null) { mNotificationPanel.updateResources(); @@ -2945,31 +2742,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - private void updateClockSize() { - if (mStatusBarView == null) return; - TextView clock = (TextView) mStatusBarView.findViewById(R.id.clock); - if (clock != null) { - FontSizeUtils.updateFontSize(clock, R.dimen.status_bar_clock_size); - } - } protected void loadDimens() { final Resources res = mContext.getResources(); mNaturalBarHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); - int newIconSize = res.getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_icon_size); - int newIconHPadding = res.getDimensionPixelSize( - R.dimen.status_bar_icon_padding); - - if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) { -// Log.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding); - mIconHPadding = newIconHPadding; - mIconSize = newIconSize; - //reloadAllNotificationIcons(); // reload the tray - } - mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore); mHeadsUpNotificationDecay = res.getInteger(R.integer.heads_up_notification_decay); @@ -3178,7 +2956,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private boolean mDemoModeAllowed; private boolean mDemoMode; - private DemoStatusIcons mDemoStatusIcons; @Override public void dispatchDemoCommand(String command, Bundle args) { @@ -3207,10 +2984,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, dispatchDemoCommandToView(command, args, R.id.battery); } if (modeChange || command.equals(COMMAND_STATUS)) { - if (mDemoStatusIcons == null) { - mDemoStatusIcons = new DemoStatusIcons(mStatusIcons, mIconSize); - } - mDemoStatusIcons.dispatchDemoCommand(command, args); + mIconController.dispatchDemoCommand(command, args); + } if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) { mNetworkController.dispatchDemoCommand(command, args); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java new file mode 100644 index 0000000..6147e30 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2015 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 com.android.systemui.statusbar.phone; + +import android.app.Notification; +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.internal.statusbar.StatusBarIcon; +import com.android.systemui.FontSizeUtils; +import com.android.systemui.R; +import com.android.systemui.statusbar.NotificationData; +import com.android.systemui.statusbar.StatusBarIconView; + +import java.io.PrintWriter; +import java.util.ArrayList; + +/** + * Controls everything regarding the icons in the status bar and on Keyguard, including, but not + * limited to: notification icons, signal cluster, additional status icons, and clock in the status + * bar. + */ +public class StatusBarIconController { + + private Context mContext; + private PhoneStatusBar mPhoneStatusBar; + private Interpolator mLinearOutSlowIn; + private DemoStatusIcons mDemoStatusIcons; + + private LinearLayout mSystemIconArea; + private LinearLayout mStatusIcons; + private LinearLayout mStatusIconsKeyguard; + private IconMerger mNotificationIcons; + private View mNotificationIconArea; + private TextView mClock; + + private int mIconSize; + private int mIconHPadding; + + public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar, + PhoneStatusBar phoneStatusBar) { + mContext = context; + mPhoneStatusBar = phoneStatusBar; + mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area); + mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons); + mNotificationIconArea = statusBar.findViewById(R.id.notification_icon_area_inner); + mNotificationIcons = (IconMerger) statusBar.findViewById(R.id.notificationIcons); + View moreIcon = statusBar.findViewById(R.id.moreIcon); + mNotificationIcons.setOverflowIndicator(moreIcon); + mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons); + mClock = (TextView) statusBar.findViewById(R.id.clock); + mLinearOutSlowIn = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.linear_out_slow_in); + updateResources(); + } + + public void updateResources() { + mIconSize = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.status_bar_icon_size); + mIconHPadding = mContext.getResources().getDimensionPixelSize( + R.dimen.status_bar_icon_padding); + FontSizeUtils.updateFontSize(mClock, R.dimen.status_bar_clock_size); + } + + public void addSystemIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { + StatusBarIconView view = new StatusBarIconView(mContext, slot, null); + view.set(icon); + mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize)); + view = new StatusBarIconView(mContext, slot, null); + view.set(icon); + mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize)); + } + + public void updateSystemIcon(String slot, int index, int viewIndex, + StatusBarIcon old, StatusBarIcon icon) { + StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex); + view.set(icon); + view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex); + view.set(icon); + } + + public void removeSystemIcon(String slot, int index, int viewIndex) { + mStatusIcons.removeViewAt(viewIndex); + mStatusIconsKeyguard.removeViewAt(viewIndex); + } + + public void updateNotificationIcons(NotificationData notificationData) { + final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + mIconSize + 2*mIconHPadding, mPhoneStatusBar.getStatusBarHeight()); + + ArrayList<NotificationData.Entry> activeNotifications = + notificationData.getActiveNotifications(); + final int N = activeNotifications.size(); + ArrayList<StatusBarIconView> toShow = new ArrayList<>(N); + + // Filter out ambient notifications. + for (int i = 0; i < N; i++) { + NotificationData.Entry ent = activeNotifications.get(i); + if (notificationData.isAmbient(ent.key) + && !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) { + continue; + } + toShow.add(ent.icon); + } + + ArrayList<View> toRemove = new ArrayList<>(); + for (int i=0; i<mNotificationIcons.getChildCount(); i++) { + View child = mNotificationIcons.getChildAt(i); + if (!toShow.contains(child)) { + toRemove.add(child); + } + } + + final int toRemoveCount = toRemove.size(); + for (int i = 0; i < toRemoveCount; i++) { + mNotificationIcons.removeView(toRemove.get(i)); + } + + for (int i=0; i<toShow.size(); i++) { + View v = toShow.get(i); + if (v.getParent() == null) { + mNotificationIcons.addView(v, i, params); + } + } + + // Resort notification icons + final int childCount = mNotificationIcons.getChildCount(); + for (int i = 0; i < childCount; i++) { + View actual = mNotificationIcons.getChildAt(i); + StatusBarIconView expected = toShow.get(i); + if (actual == expected) { + continue; + } + mNotificationIcons.removeView(expected); + mNotificationIcons.addView(expected, i); + } + } + + public void hideSystemIconArea(boolean animate) { + animateHide(mSystemIconArea, animate); + } + + public void showSystemIconArea(boolean animate) { + animateShow(mSystemIconArea, animate); + } + + public void hideNotificationIconArea(boolean animate) { + animateHide(mNotificationIconArea, animate); + } + + public void showNotificationIconArea(boolean animate) { + animateShow(mNotificationIconArea, animate); + } + + public void setClockVisibility(boolean visible) { + mClock.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + public void dump(PrintWriter pw) { + int N = mStatusIcons.getChildCount(); + pw.println(" system icons: " + N); + for (int i=0; i<N; i++) { + StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i); + pw.println(" [" + i + "] icon=" + ic); + } + } + + public void dispatchDemoCommand(String command, Bundle args) { + if (mDemoStatusIcons == null) { + mDemoStatusIcons = new DemoStatusIcons(mStatusIcons, mIconSize); + } + mDemoStatusIcons.dispatchDemoCommand(command, args); + } + + /** + * Hides a view. + */ + private void animateHide(final View v, boolean animate) { + v.animate().cancel(); + if (!animate) { + v.setAlpha(0f); + v.setVisibility(View.INVISIBLE); + return; + } + v.animate() + .alpha(0f) + .setDuration(160) + .setStartDelay(0) + .setInterpolator(PhoneStatusBar.ALPHA_OUT) + .withEndAction(new Runnable() { + @Override + public void run() { + v.setVisibility(View.INVISIBLE); + } + }); + } + + /** + * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable. + */ + private void animateShow(View v, boolean animate) { + v.animate().cancel(); + v.setVisibility(View.VISIBLE); + if (!animate) { + v.setAlpha(1f); + return; + } + v.animate() + .alpha(1f) + .setDuration(320) + .setInterpolator(PhoneStatusBar.ALPHA_IN) + .setStartDelay(50) + + // We need to clean up any pending end action from animateHide if we call + // both hide and show in the same frame before the animation actually gets started. + // cancel() doesn't really remove the end action. + .withEndAction(null); + + // Synchronize the motion with the Keyguard fading if necessary. + if (mPhoneStatusBar.isKeyguardFadingAway()) { + v.animate() + .setDuration(mPhoneStatusBar.getKeyguardFadingAwayDuration()) + .setInterpolator(mLinearOutSlowIn) + .setStartDelay(mPhoneStatusBar.getKeyguardFadingAwayDelay()) + .start(); + } + } +} |