• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.systemui.statusbar.phone;
2 
3 import android.content.Context;
4 import android.content.res.ColorStateList;
5 import android.content.res.Resources;
6 import android.graphics.Color;
7 import android.graphics.Rect;
8 import android.support.annotation.NonNull;
9 import android.view.LayoutInflater;
10 import android.view.View;
11 import android.widget.ImageView;
12 import android.widget.LinearLayout;
13 
14 import com.android.internal.util.NotificationColorUtil;
15 import com.android.systemui.R;
16 import com.android.systemui.statusbar.NotificationData;
17 import com.android.systemui.statusbar.StatusBarIconView;
18 import com.android.systemui.statusbar.notification.NotificationUtils;
19 
20 import java.util.ArrayList;
21 
22 /**
23  * A controller for the space in the status bar to the left of the system icons. This area is
24  * normally reserved for notifications.
25  */
26 public class NotificationIconAreaController {
27     private final NotificationColorUtil mNotificationColorUtil;
28 
29     private int mIconSize;
30     private int mIconHPadding;
31     private int mIconTint = Color.WHITE;
32 
33     private PhoneStatusBar mPhoneStatusBar;
34     protected View mNotificationIconArea;
35     private IconMerger mNotificationIcons;
36     private ImageView mMoreIcon;
37     private final Rect mTintArea = new Rect();
38 
NotificationIconAreaController(Context context, PhoneStatusBar phoneStatusBar)39     public NotificationIconAreaController(Context context, PhoneStatusBar phoneStatusBar) {
40         mPhoneStatusBar = phoneStatusBar;
41         mNotificationColorUtil = NotificationColorUtil.getInstance(context);
42 
43         initializeNotificationAreaViews(context);
44     }
45 
inflateIconArea(LayoutInflater inflater)46     protected View inflateIconArea(LayoutInflater inflater) {
47         return inflater.inflate(R.layout.notification_icon_area, null);
48     }
49 
50     /**
51      * Initializes the views that will represent the notification area.
52      */
initializeNotificationAreaViews(Context context)53     protected void initializeNotificationAreaViews(Context context) {
54         reloadDimens(context);
55 
56         LayoutInflater layoutInflater = LayoutInflater.from(context);
57         mNotificationIconArea = inflateIconArea(layoutInflater);
58 
59         mNotificationIcons =
60                 (IconMerger) mNotificationIconArea.findViewById(R.id.notificationIcons);
61 
62         mMoreIcon = (ImageView) mNotificationIconArea.findViewById(R.id.moreIcon);
63         if (mMoreIcon != null) {
64             mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
65             mNotificationIcons.setOverflowIndicator(mMoreIcon);
66         }
67     }
68 
onDensityOrFontScaleChanged(Context context)69     public void onDensityOrFontScaleChanged(Context context) {
70         reloadDimens(context);
71         final LinearLayout.LayoutParams params = generateIconLayoutParams();
72         for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
73             View child = mNotificationIcons.getChildAt(i);
74             child.setLayoutParams(params);
75         }
76     }
77 
78     @NonNull
generateIconLayoutParams()79     private LinearLayout.LayoutParams generateIconLayoutParams() {
80         return new LinearLayout.LayoutParams(
81                 mIconSize + 2 * mIconHPadding, getHeight());
82     }
83 
reloadDimens(Context context)84     private void reloadDimens(Context context) {
85         Resources res = context.getResources();
86         mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
87         mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_padding);
88     }
89 
90     /**
91      * Returns the view that represents the notification area.
92      */
getNotificationInnerAreaView()93     public View getNotificationInnerAreaView() {
94         return mNotificationIconArea;
95     }
96 
97     /**
98      * See {@link StatusBarIconController#setIconsDarkArea}.
99      *
100      * @param tintArea the area in which to tint the icons, specified in screen coordinates
101      */
setTintArea(Rect tintArea)102     public void setTintArea(Rect tintArea) {
103         if (tintArea == null) {
104             mTintArea.setEmpty();
105         } else {
106             mTintArea.set(tintArea);
107         }
108         applyNotificationIconsTint();
109     }
110 
111     /**
112      * Sets the color that should be used to tint any icons in the notification area. If this
113      * method is not called, the default tint is {@link Color#WHITE}.
114      */
setIconTint(int iconTint)115     public void setIconTint(int iconTint) {
116         mIconTint = iconTint;
117         if (mMoreIcon != null) {
118             mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
119         }
120         applyNotificationIconsTint();
121     }
122 
getHeight()123     protected int getHeight() {
124         return mPhoneStatusBar.getStatusBarHeight();
125     }
126 
shouldShowNotification(NotificationData.Entry entry, NotificationData notificationData)127     protected boolean shouldShowNotification(NotificationData.Entry entry,
128             NotificationData notificationData) {
129         if (notificationData.isAmbient(entry.key)
130                 && !NotificationData.showNotificationEvenIfUnprovisioned(entry.notification)) {
131             return false;
132         }
133         if (!PhoneStatusBar.isTopLevelChild(entry)) {
134             return false;
135         }
136         if (entry.row.getVisibility() == View.GONE) {
137             return false;
138         }
139 
140         return true;
141     }
142 
143     /**
144      * Updates the notifications with the given list of notifications to display.
145      */
updateNotificationIcons(NotificationData notificationData)146     public void updateNotificationIcons(NotificationData notificationData) {
147         final LinearLayout.LayoutParams params = generateIconLayoutParams();
148 
149         ArrayList<NotificationData.Entry> activeNotifications =
150                 notificationData.getActiveNotifications();
151         final int size = activeNotifications.size();
152         ArrayList<StatusBarIconView> toShow = new ArrayList<>(size);
153 
154         // Filter out ambient notifications and notification children.
155         for (int i = 0; i < size; i++) {
156             NotificationData.Entry ent = activeNotifications.get(i);
157             if (shouldShowNotification(ent, notificationData)) {
158                 toShow.add(ent.icon);
159             }
160         }
161 
162         ArrayList<View> toRemove = new ArrayList<>();
163         for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
164             View child = mNotificationIcons.getChildAt(i);
165             if (!toShow.contains(child)) {
166                 toRemove.add(child);
167             }
168         }
169 
170         final int toRemoveCount = toRemove.size();
171         for (int i = 0; i < toRemoveCount; i++) {
172             mNotificationIcons.removeView(toRemove.get(i));
173         }
174 
175         for (int i = 0; i < toShow.size(); i++) {
176             View v = toShow.get(i);
177             if (v.getParent() == null) {
178                 mNotificationIcons.addView(v, i, params);
179             }
180         }
181 
182         // Re-sort notification icons
183         final int childCount = mNotificationIcons.getChildCount();
184         for (int i = 0; i < childCount; i++) {
185             View actual = mNotificationIcons.getChildAt(i);
186             StatusBarIconView expected = toShow.get(i);
187             if (actual == expected) {
188                 continue;
189             }
190             mNotificationIcons.removeView(expected);
191             mNotificationIcons.addView(expected, i);
192         }
193 
194         applyNotificationIconsTint();
195     }
196 
197     /**
198      * Applies {@link #mIconTint} to the notification icons.
199      */
applyNotificationIconsTint()200     private void applyNotificationIconsTint() {
201         for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
202             StatusBarIconView v = (StatusBarIconView) mNotificationIcons.getChildAt(i);
203             boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
204             boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mNotificationColorUtil);
205             if (colorize) {
206                 v.setImageTintList(ColorStateList.valueOf(
207                         StatusBarIconController.getTint(mTintArea, v, mIconTint)));
208             }
209         }
210     }
211 }
212