blob: f52becaf7b00016bbe785cadb9b60e2c3c1368f6 [file] [log] [blame]
Anthony Chen83092c62016-01-11 17:00:36 -08001package com.android.systemui.statusbar.phone;
2
3import android.content.Context;
Anthony Chen83092c62016-01-11 17:00:36 -08004import android.content.res.Resources;
5import android.graphics.Color;
Jorim Jaggi86905582016-02-09 21:36:09 -08006import android.graphics.Rect;
Anthony Chen83092c62016-01-11 17:00:36 -08007import android.view.LayoutInflater;
8import android.view.View;
Jason Monke59dc402018-08-16 12:05:01 -04009import android.view.ViewGroup;
Selim Cinek0e8d77e2016-11-29 10:35:42 -080010import android.widget.FrameLayout;
Winsonc0d70582016-01-29 10:24:39 -080011
Beverly8fdb5332019-02-04 14:29:49 -050012import androidx.annotation.NonNull;
13import androidx.collection.ArrayMap;
14
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050015import com.android.internal.annotations.VisibleForTesting;
Selim Cinek72fc8db2017-06-06 18:07:47 -070016import com.android.internal.statusbar.StatusBarIcon;
Lucas Dupina291d192018-06-07 13:59:42 -070017import com.android.internal.util.ContrastColorUtil;
Selim Cinekd03518c2018-03-15 12:13:51 -070018import com.android.systemui.Dependency;
Anthony Chen83092c62016-01-11 17:00:36 -080019import com.android.systemui.R;
Beverly1be62f42018-12-19 17:17:48 -050020import com.android.systemui.plugins.DarkIconDispatcher;
21import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
Beverly8fdb5332019-02-04 14:29:49 -050022import com.android.systemui.plugins.statusbar.StatusBarStateController;
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050023import com.android.systemui.statusbar.NotificationListener;
Lucas Dupin20403372019-02-14 19:59:18 -080024import com.android.systemui.statusbar.NotificationMediaManager;
Selim Cinek281c2022016-10-13 19:14:43 -070025import com.android.systemui.statusbar.NotificationShelf;
Anthony Chen83092c62016-01-11 17:00:36 -080026import com.android.systemui.statusbar.StatusBarIconView;
Lucas Dupin9d6172b2019-06-04 15:14:25 -070027import com.android.systemui.statusbar.StatusBarState;
Gus Prevas33619af2018-10-26 15:40:27 -040028import com.android.systemui.statusbar.notification.NotificationEntryManager;
Anthony Chen83092c62016-01-11 17:00:36 -080029import com.android.systemui.statusbar.notification.NotificationUtils;
Ned Burnsf81c4c42019-01-07 14:10:43 -050030import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gus Prevas33619af2018-10-26 15:40:27 -040031import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
Anthony Chen83092c62016-01-11 17:00:36 -080032
33import java.util.ArrayList;
Beverly40770652019-02-15 15:49:49 -050034import java.util.Objects;
Selim Cinek281c2022016-10-13 19:14:43 -070035import java.util.function.Function;
Anthony Chen83092c62016-01-11 17:00:36 -080036
37/**
38 * A controller for the space in the status bar to the left of the system icons. This area is
39 * normally reserved for notifications.
40 */
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080041public class NotificationIconAreaController implements DarkReceiver,
42 StatusBarStateController.StateListener {
Gus Prevas33619af2018-10-26 15:40:27 -040043
Selim Cinek3c9b0542019-06-11 15:41:28 -070044 public static final String HIGH_PRIORITY = "high_priority";
Gus Prevas33619af2018-10-26 15:40:27 -040045
Lucas Dupina291d192018-06-07 13:59:42 -070046 private final ContrastColorUtil mContrastColorUtil;
Selim Cinekd03518c2018-03-15 12:13:51 -070047 private final NotificationEntryManager mEntryManager;
48 private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080049 private final StatusBarStateController mStatusBarStateController;
Lucas Dupin20403372019-02-14 19:59:18 -080050 private final NotificationMediaManager mMediaManager;
Anthony Chen83092c62016-01-11 17:00:36 -080051
52 private int mIconSize;
53 private int mIconHPadding;
54 private int mIconTint = Color.WHITE;
Beverly40770652019-02-15 15:49:49 -050055 private int mCenteredIconTint = Color.WHITE;
Anthony Chen83092c62016-01-11 17:00:36 -080056
Jason Monk2a6ea9c2017-01-26 11:14:51 -050057 private StatusBar mStatusBar;
Anthony Chen83092c62016-01-11 17:00:36 -080058 protected View mNotificationIconArea;
Selim Cinek281c2022016-10-13 19:14:43 -070059 private NotificationIconContainer mNotificationIcons;
Selim Cinek5b5beb012016-11-08 18:11:58 -080060 private NotificationIconContainer mShelfIcons;
Beverly40770652019-02-15 15:49:49 -050061 protected View mCenteredIconArea;
62 private NotificationIconContainer mCenteredIcon;
63 private StatusBarIconView mCenteredIconView;
Jorim Jaggi86905582016-02-09 21:36:09 -080064 private final Rect mTintArea = new Rect();
Jason Monke59dc402018-08-16 12:05:01 -040065 private ViewGroup mNotificationScrollLayout;
Selim Cinek281c2022016-10-13 19:14:43 -070066 private Context mContext;
Selim Cinek9bfc7a52018-06-11 16:09:00 -070067 private boolean mFullyDark;
Lucas Dupin9d6172b2019-06-04 15:14:25 -070068 private boolean mAnimationsEnabled;
Anthony Chen83092c62016-01-11 17:00:36 -080069
Lucas Dupin23a8d3b2018-10-08 20:57:35 -070070 /**
71 * Ratio representing being awake or in ambient mode, where 1 is dark and 0 awake.
72 */
73 private float mDarkAmount;
Lucas Dupin23a8d3b2018-10-08 20:57:35 -070074
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080075 public NotificationIconAreaController(Context context, StatusBar statusBar,
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050076 StatusBarStateController statusBarStateController,
Lucas Dupin20403372019-02-14 19:59:18 -080077 NotificationMediaManager notificationMediaManager) {
Jason Monk2a6ea9c2017-01-26 11:14:51 -050078 mStatusBar = statusBar;
Lucas Dupina291d192018-06-07 13:59:42 -070079 mContrastColorUtil = ContrastColorUtil.getInstance(context);
Selim Cinek281c2022016-10-13 19:14:43 -070080 mContext = context;
Selim Cinekd03518c2018-03-15 12:13:51 -070081 mEntryManager = Dependency.get(NotificationEntryManager.class);
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080082 mStatusBarStateController = statusBarStateController;
83 mStatusBarStateController.addCallback(this);
Lucas Dupin20403372019-02-14 19:59:18 -080084 mMediaManager = notificationMediaManager;
Gus Prevas33619af2018-10-26 15:40:27 -040085
Anthony Chen83092c62016-01-11 17:00:36 -080086 initializeNotificationAreaViews(context);
87 }
88
Xiaohui Cheneb04a992016-03-22 14:58:03 -070089 protected View inflateIconArea(LayoutInflater inflater) {
90 return inflater.inflate(R.layout.notification_icon_area, null);
91 }
92
Anthony Chen83092c62016-01-11 17:00:36 -080093 /**
94 * Initializes the views that will represent the notification area.
95 */
96 protected void initializeNotificationAreaViews(Context context) {
Selim Cinek3e7592d2016-04-11 09:35:54 +080097 reloadDimens(context);
Anthony Chen83092c62016-01-11 17:00:36 -080098
99 LayoutInflater layoutInflater = LayoutInflater.from(context);
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700100 mNotificationIconArea = inflateIconArea(layoutInflater);
Jason Monke59dc402018-08-16 12:05:01 -0400101 mNotificationIcons = mNotificationIconArea.findViewById(R.id.notificationIcons);
Anthony Chen83092c62016-01-11 17:00:36 -0800102
Jason Monkaa573e92017-01-27 17:00:29 -0500103 mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
Beverly40770652019-02-15 15:49:49 -0500104
105 mCenteredIconArea = layoutInflater.inflate(R.layout.center_icon_area, null);
106 mCenteredIcon = mCenteredIconArea.findViewById(R.id.centeredIcon);
Jason Monkaa573e92017-01-27 17:00:29 -0500107 }
108
109 public void setupShelf(NotificationShelf shelf) {
Selim Cinek5b5beb012016-11-08 18:11:58 -0800110 mShelfIcons = shelf.getShelfIcons();
Selim Cinek49014f82016-11-04 14:55:30 -0700111 shelf.setCollapsedIcons(mNotificationIcons);
Anthony Chen83092c62016-01-11 17:00:36 -0800112 }
113
Selim Cinek3e7592d2016-04-11 09:35:54 +0800114 public void onDensityOrFontScaleChanged(Context context) {
115 reloadDimens(context);
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800116 final FrameLayout.LayoutParams params = generateIconLayoutParams();
Selim Cinek3e7592d2016-04-11 09:35:54 +0800117 for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
118 View child = mNotificationIcons.getChildAt(i);
119 child.setLayoutParams(params);
Selim Cinek9ef119c2017-03-01 15:13:36 -0800120 }
121 for (int i = 0; i < mShelfIcons.getChildCount(); i++) {
122 View child = mShelfIcons.getChildAt(i);
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800123 child.setLayoutParams(params);
Selim Cinek3e7592d2016-04-11 09:35:54 +0800124 }
Beverly40770652019-02-15 15:49:49 -0500125 for (int i = 0; i < mCenteredIcon.getChildCount(); i++) {
126 View child = mCenteredIcon.getChildAt(i);
127 child.setLayoutParams(params);
128 }
Selim Cinek3e7592d2016-04-11 09:35:54 +0800129 }
130
131 @NonNull
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800132 private FrameLayout.LayoutParams generateIconLayoutParams() {
133 return new FrameLayout.LayoutParams(
Selim Cinek3e7592d2016-04-11 09:35:54 +0800134 mIconSize + 2 * mIconHPadding, getHeight());
135 }
136
137 private void reloadDimens(Context context) {
138 Resources res = context.getResources();
139 mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
140 mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_padding);
141 }
142
Anthony Chen83092c62016-01-11 17:00:36 -0800143 /**
144 * Returns the view that represents the notification area.
145 */
146 public View getNotificationInnerAreaView() {
147 return mNotificationIconArea;
148 }
149
150 /**
Beverly40770652019-02-15 15:49:49 -0500151 * Returns the view that represents the centered notification area.
152 */
153 public View getCenteredNotificationAreaView() {
154 return mCenteredIconArea;
155 }
156
157 /**
Jason Monkaa573e92017-01-27 17:00:29 -0500158 * See {@link com.android.systemui.statusbar.policy.DarkIconDispatcher#setIconsDarkArea}.
159 * Sets the color that should be used to tint any icons in the notification area.
Jorim Jaggi86905582016-02-09 21:36:09 -0800160 *
161 * @param tintArea the area in which to tint the icons, specified in screen coordinates
Jason Monkaa573e92017-01-27 17:00:29 -0500162 * @param darkIntensity
Jorim Jaggi86905582016-02-09 21:36:09 -0800163 */
Jason Monkaa573e92017-01-27 17:00:29 -0500164 public void onDarkChanged(Rect tintArea, float darkIntensity, int iconTint) {
Jorim Jaggi86905582016-02-09 21:36:09 -0800165 if (tintArea == null) {
166 mTintArea.setEmpty();
167 } else {
168 mTintArea.set(tintArea);
169 }
Beverly40770652019-02-15 15:49:49 -0500170
Evan Lairddbeefe32018-04-03 16:52:41 -0400171 if (mNotificationIconArea != null) {
172 if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) {
173 mIconTint = iconTint;
174 }
175 } else {
176 mIconTint = iconTint;
177 }
178
Beverly40770652019-02-15 15:49:49 -0500179 if (mCenteredIconArea != null) {
180 if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) {
181 mCenteredIconTint = iconTint;
182 }
183 } else {
184 mCenteredIconTint = iconTint;
185 }
186
Anthony Chen83092c62016-01-11 17:00:36 -0800187 applyNotificationIconsTint();
188 }
189
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700190 protected int getHeight() {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500191 return mStatusBar.getStatusBarHeight();
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700192 }
193
Ned Burnsf81c4c42019-01-07 14:10:43 -0500194 protected boolean shouldShowNotificationIcon(NotificationEntry entry,
Gus Prevas33619af2018-10-26 15:40:27 -0400195 boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
Beverly40770652019-02-15 15:49:49 -0500196 boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon) {
197
198 final boolean isCenteredNotificationIcon = entry.centeredIcon != null
199 && Objects.equals(entry.centeredIcon, mCenteredIconView);
200 if (hideCenteredIcon == isCenteredNotificationIcon) {
201 return false;
202 }
Selim Cinekd03518c2018-03-15 12:13:51 -0700203 if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700204 return false;
205 }
Lucas Dupin20403372019-02-14 19:59:18 -0800206 if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
207 return false;
208 }
Gus Prevascaed15c2019-01-18 14:19:51 -0500209 if (!showLowPriority && !entry.isHighPriority()) {
Gus Prevas33619af2018-10-26 15:40:27 -0400210 return false;
211 }
Evan Laird94492852018-10-25 13:43:01 -0400212 if (!entry.isTopLevelChild()) {
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700213 return false;
214 }
Evan Laird94492852018-10-25 13:43:01 -0400215 if (entry.getRow().getVisibility() == View.GONE) {
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700216 return false;
217 }
Evan Laird94492852018-10-25 13:43:01 -0400218 if (entry.isRowDismissed() && hideDismissed) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700219 return false;
220 }
Selim Cinekb0dc61b2018-05-22 18:49:36 -0700221 if (hideRepliedMessages && entry.isLastMessageFromReply()) {
222 return false;
223 }
Julia Reynoldsc861a3d2018-02-15 10:34:49 -0500224 // showAmbient == show in shade but not shelf
Beverly4bae6442019-04-04 09:59:33 -0400225 if ((!showAmbient || mFullyDark) && entry.shouldSuppressStatusBar()) {
Julia Reynoldsc861a3d2018-02-15 10:34:49 -0500226 return false;
227 }
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700228 return true;
229 }
230
Anthony Chen83092c62016-01-11 17:00:36 -0800231 /**
232 * Updates the notifications with the given list of notifications to display.
233 */
Selim Cinekd03518c2018-03-15 12:13:51 -0700234 public void updateNotificationIcons() {
Selim Cinekd03518c2018-03-15 12:13:51 -0700235 updateStatusBarIcons();
Selim Cinek9bfc7a52018-06-11 16:09:00 -0700236 updateShelfIcons();
Beverly40770652019-02-15 15:49:49 -0500237 updateCenterIcon();
Selim Cinek281c2022016-10-13 19:14:43 -0700238
239 applyNotificationIconsTint();
Selim Cinek281c2022016-10-13 19:14:43 -0700240 }
241
Selim Cinek9bfc7a52018-06-11 16:09:00 -0700242 private void updateShelfIcons() {
243 updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
Beverly40770652019-02-15 15:49:49 -0500244 true /* showAmbient */,
Selim Cinekd34e9d82019-06-19 17:24:59 -0700245 true /* showLowPriority */,
Beverly40770652019-02-15 15:49:49 -0500246 false /* hideDismissed */,
247 mFullyDark /* hideRepliedMessages */,
248 mFullyDark /* hideCurrentMedia */,
249 true /* hide centered icon */);
Selim Cinek9bfc7a52018-06-11 16:09:00 -0700250 }
251
Selim Cinekb0dc61b2018-05-22 18:49:36 -0700252 public void updateStatusBarIcons() {
Selim Cinekd03518c2018-03-15 12:13:51 -0700253 updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
Beverly40770652019-02-15 15:49:49 -0500254 false /* showAmbient */,
Selim Cinekd34e9d82019-06-19 17:24:59 -0700255 true /* showLowPriority */,
Gus Prevasdddef392018-11-02 15:41:43 -0400256 true /* hideDismissed */,
Lucas Dupin20403372019-02-14 19:59:18 -0800257 true /* hideRepliedMessages */,
Beverly40770652019-02-15 15:49:49 -0500258 false /* hideCurrentMedia */,
259 true /* hide centered icon */);
260 }
261
262 private void updateCenterIcon() {
263 updateIconsForLayout(entry -> entry.centeredIcon, mCenteredIcon,
264 false /* showAmbient */,
Selim Cinekd34e9d82019-06-19 17:24:59 -0700265 true /* showLowPriority */,
Beverly40770652019-02-15 15:49:49 -0500266 false /* hideDismissed */,
267 false /* hideRepliedMessages */,
268 mFullyDark /* hideCurrentMedia */,
269 false /* hide centered icon */);
Selim Cinekd03518c2018-03-15 12:13:51 -0700270 }
271
Lucas Dupin9d6172b2019-06-04 15:14:25 -0700272 /**
273 * If icons of the status bar should animate when they are added or removed.
274 */
275 public void setAnimationsEnabled(boolean enabled) {
276 mAnimationsEnabled = enabled;
277 updateAnimations();
278 }
279
280 @Override
281 public void onStateChanged(int newState) {
282 updateAnimations();
283 }
284
285 private void updateAnimations() {
286 boolean inShade = mStatusBarStateController.getState() == StatusBarState.SHADE;
287 mCenteredIcon.setAnimationsEnabled(mAnimationsEnabled && inShade);
288 mNotificationIcons.setAnimationsEnabled(mAnimationsEnabled && inShade);
289 }
290
Selim Cinek281c2022016-10-13 19:14:43 -0700291 /**
292 * Updates the notification icons for a host layout. This will ensure that the notification
293 * host layout will have the same icons like the ones in here.
Selim Cinek281c2022016-10-13 19:14:43 -0700294 * @param function A function to look up an icon view based on an entry
295 * @param hostLayout which layout should be updated
Selim Cinek17e1b692016-12-02 18:19:11 -0800296 * @param showAmbient should ambient notification icons be shown
Selim Cinekd03518c2018-03-15 12:13:51 -0700297 * @param hideDismissed should dismissed icons be hidden
Selim Cinekb0dc61b2018-05-22 18:49:36 -0700298 * @param hideRepliedMessages should messages that have been replied to be hidden
Selim Cinek281c2022016-10-13 19:14:43 -0700299 */
Ned Burnsf81c4c42019-01-07 14:10:43 -0500300 private void updateIconsForLayout(Function<NotificationEntry, StatusBarIconView> function,
Gus Prevas33619af2018-10-26 15:40:27 -0400301 NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority,
Beverly40770652019-02-15 15:49:49 -0500302 boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia,
303 boolean hideCenteredIcon) {
Selim Cinek281c2022016-10-13 19:14:43 -0700304 ArrayList<StatusBarIconView> toShow = new ArrayList<>(
305 mNotificationScrollLayout.getChildCount());
Anthony Chen83092c62016-01-11 17:00:36 -0800306
307 // Filter out ambient notifications and notification children.
Selim Cinek281c2022016-10-13 19:14:43 -0700308 for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) {
309 View view = mNotificationScrollLayout.getChildAt(i);
310 if (view instanceof ExpandableNotificationRow) {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500311 NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry();
Gus Prevas33619af2018-10-26 15:40:27 -0400312 if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed,
Beverly40770652019-02-15 15:49:49 -0500313 hideRepliedMessages, hideCurrentMedia, hideCenteredIcon)) {
314 StatusBarIconView iconView = function.apply(ent);
315 if (iconView != null) {
316 toShow.add(iconView);
317 }
Selim Cinek281c2022016-10-13 19:14:43 -0700318 }
Anthony Chen83092c62016-01-11 17:00:36 -0800319 }
Anthony Chen83092c62016-01-11 17:00:36 -0800320 }
321
Selim Cinek72fc8db2017-06-06 18:07:47 -0700322 // In case we are changing the suppression of a group, the replacement shouldn't flicker
323 // and it should just be replaced instead. We therefore look for notifications that were
324 // just replaced by the child or vice-versa to suppress this.
Selim Cinek49014f82016-11-04 14:55:30 -0700325
Selim Cinek72fc8db2017-06-06 18:07:47 -0700326 ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();
Anthony Chen83092c62016-01-11 17:00:36 -0800327 ArrayList<View> toRemove = new ArrayList<>();
Selim Cinek281c2022016-10-13 19:14:43 -0700328 for (int i = 0; i < hostLayout.getChildCount(); i++) {
329 View child = hostLayout.getChildAt(i);
Selim Cinek72fc8db2017-06-06 18:07:47 -0700330 if (!(child instanceof StatusBarIconView)) {
331 continue;
332 }
Anthony Chen83092c62016-01-11 17:00:36 -0800333 if (!toShow.contains(child)) {
Selim Cinek72fc8db2017-06-06 18:07:47 -0700334 boolean iconWasReplaced = false;
335 StatusBarIconView removedIcon = (StatusBarIconView) child;
336 String removedGroupKey = removedIcon.getNotification().getGroupKey();
337 for (int j = 0; j < toShow.size(); j++) {
338 StatusBarIconView candidate = toShow.get(j);
339 if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
340 && candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
341 if (!iconWasReplaced) {
342 iconWasReplaced = true;
343 } else {
344 iconWasReplaced = false;
345 break;
346 }
347 }
348 }
349 if (iconWasReplaced) {
350 ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);
351 if (statusBarIcons == null) {
352 statusBarIcons = new ArrayList<>();
353 replacingIcons.put(removedGroupKey, statusBarIcons);
354 }
355 statusBarIcons.add(removedIcon.getStatusBarIcon());
356 }
357 toRemove.add(removedIcon);
Anthony Chen83092c62016-01-11 17:00:36 -0800358 }
359 }
Selim Cinek72fc8db2017-06-06 18:07:47 -0700360 // removing all duplicates
361 ArrayList<String> duplicates = new ArrayList<>();
362 for (String key : replacingIcons.keySet()) {
363 ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(key);
364 if (statusBarIcons.size() != 1) {
365 duplicates.add(key);
366 }
367 }
368 replacingIcons.removeAll(duplicates);
369 hostLayout.setReplacingIcons(replacingIcons);
Anthony Chen83092c62016-01-11 17:00:36 -0800370
371 final int toRemoveCount = toRemove.size();
372 for (int i = 0; i < toRemoveCount; i++) {
Selim Cinek281c2022016-10-13 19:14:43 -0700373 hostLayout.removeView(toRemove.get(i));
Anthony Chen83092c62016-01-11 17:00:36 -0800374 }
375
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800376 final FrameLayout.LayoutParams params = generateIconLayoutParams();
Anthony Chen83092c62016-01-11 17:00:36 -0800377 for (int i = 0; i < toShow.size(); i++) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700378 StatusBarIconView v = toShow.get(i);
Selim Cinek5b5beb012016-11-08 18:11:58 -0800379 // The view might still be transiently added if it was just removed and added again
380 hostLayout.removeTransientView(v);
Anthony Chen83092c62016-01-11 17:00:36 -0800381 if (v.getParent() == null) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700382 if (hideDismissed) {
383 v.setOnDismissListener(mUpdateStatusBarIcons);
384 }
Selim Cinek281c2022016-10-13 19:14:43 -0700385 hostLayout.addView(v, i, params);
Anthony Chen83092c62016-01-11 17:00:36 -0800386 }
387 }
388
Selim Cinek5b5beb012016-11-08 18:11:58 -0800389 hostLayout.setChangingViewPositions(true);
Anthony Chen83092c62016-01-11 17:00:36 -0800390 // Re-sort notification icons
Selim Cinek281c2022016-10-13 19:14:43 -0700391 final int childCount = hostLayout.getChildCount();
Anthony Chen83092c62016-01-11 17:00:36 -0800392 for (int i = 0; i < childCount; i++) {
Selim Cinek281c2022016-10-13 19:14:43 -0700393 View actual = hostLayout.getChildAt(i);
Anthony Chen83092c62016-01-11 17:00:36 -0800394 StatusBarIconView expected = toShow.get(i);
395 if (actual == expected) {
396 continue;
397 }
Selim Cinek281c2022016-10-13 19:14:43 -0700398 hostLayout.removeView(expected);
399 hostLayout.addView(expected, i);
Anthony Chen83092c62016-01-11 17:00:36 -0800400 }
Selim Cinek5b5beb012016-11-08 18:11:58 -0800401 hostLayout.setChangingViewPositions(false);
Selim Cinek72fc8db2017-06-06 18:07:47 -0700402 hostLayout.setReplacingIcons(null);
Anthony Chen83092c62016-01-11 17:00:36 -0800403 }
404
405 /**
406 * Applies {@link #mIconTint} to the notification icons.
Beverly40770652019-02-15 15:49:49 -0500407 * Applies {@link #mCenteredIconTint} to the center notification icon.
Anthony Chen83092c62016-01-11 17:00:36 -0800408 */
409 private void applyNotificationIconsTint() {
410 for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
Selim Cinek887da3c2017-10-06 13:37:32 -0700411 final StatusBarIconView iv = (StatusBarIconView) mNotificationIcons.getChildAt(i);
412 if (iv.getWidth() != 0) {
Beverly40770652019-02-15 15:49:49 -0500413 updateTintForIcon(iv, mIconTint);
Selim Cinek887da3c2017-10-06 13:37:32 -0700414 } else {
Beverly40770652019-02-15 15:49:49 -0500415 iv.executeOnLayout(() -> updateTintForIcon(iv, mIconTint));
416 }
417 }
418
419 for (int i = 0; i < mCenteredIcon.getChildCount(); i++) {
420 final StatusBarIconView iv = (StatusBarIconView) mCenteredIcon.getChildAt(i);
421 if (iv.getWidth() != 0) {
422 updateTintForIcon(iv, mCenteredIconTint);
423 } else {
424 iv.executeOnLayout(() -> updateTintForIcon(iv, mCenteredIconTint));
Anthony Chen83092c62016-01-11 17:00:36 -0800425 }
Anthony Chen83092c62016-01-11 17:00:36 -0800426 }
427 }
Lucas Dupin987f1932017-05-13 21:02:52 -0700428
Beverly40770652019-02-15 15:49:49 -0500429 private void updateTintForIcon(StatusBarIconView v, int tint) {
Selim Cinek887da3c2017-10-06 13:37:32 -0700430 boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
431 int color = StatusBarIconView.NO_COLOR;
Lucas Dupina291d192018-06-07 13:59:42 -0700432 boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mContrastColorUtil);
Selim Cinek887da3c2017-10-06 13:37:32 -0700433 if (colorize) {
Beverly40770652019-02-15 15:49:49 -0500434 color = DarkIconDispatcher.getTint(mTintArea, v, tint);
Selim Cinek887da3c2017-10-06 13:37:32 -0700435 }
436 v.setStaticDrawableColor(color);
Beverly40770652019-02-15 15:49:49 -0500437 v.setDecorColor(tint);
Selim Cinek887da3c2017-10-06 13:37:32 -0700438 }
439
Lucas Dupin987f1932017-05-13 21:02:52 -0700440 public void setDark(boolean dark) {
441 mNotificationIcons.setDark(dark, false, 0);
442 mShelfIcons.setDark(dark, false, 0);
Beverly40770652019-02-15 15:49:49 -0500443 mCenteredIcon.setDark(dark, false, 0);
444 }
445
446 /**
447 * Shows the icon view given in the center.
448 */
449 public void showIconCentered(NotificationEntry entry) {
450 StatusBarIconView icon = entry == null ? null : entry.centeredIcon;
451 if (!Objects.equals(mCenteredIconView, icon)) {
452 mCenteredIconView = icon;
453 updateNotificationIcons();
454 }
Lucas Dupin987f1932017-05-13 21:02:52 -0700455 }
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800456
Selim Cinek332c23f2018-03-16 17:37:50 -0700457 public void showIconIsolated(StatusBarIconView icon, boolean animated) {
458 mNotificationIcons.showIconIsolated(icon, animated);
459 }
460
461 public void setIsolatedIconLocation(Rect iconDrawingRect, boolean requireStateUpdate) {
462 mNotificationIcons.setIsolatedIconLocation(iconDrawingRect, requireStateUpdate);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800463 }
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700464
Lucas Dupin7fc9dc12019-01-03 09:19:43 -0800465 @Override
466 public void onDozeAmountChanged(float linear, float eased) {
Lucas Dupin7fc9dc12019-01-03 09:19:43 -0800467 mDarkAmount = linear;
Lucas Dupin7fc9dc12019-01-03 09:19:43 -0800468 boolean fullyDark = mDarkAmount == 1f;
469 if (mFullyDark != fullyDark) {
470 mFullyDark = fullyDark;
471 updateShelfIcons();
472 }
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700473 }
Anthony Chen83092c62016-01-11 17:00:36 -0800474}