blob: cd9772237d5929dcd4567ac053ba82f822ac7c49 [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;
Selim Cinek5dc581a2019-06-19 17:24:59 -07007import android.provider.Settings;
Anthony Chen83092c62016-01-11 17:00:36 -08008import android.view.LayoutInflater;
9import android.view.View;
Jason Monke59dc402018-08-16 12:05:01 -040010import android.view.ViewGroup;
Selim Cinek0e8d77e2016-11-29 10:35:42 -080011import android.widget.FrameLayout;
Winsonc0d70582016-01-29 10:24:39 -080012
Beverly8fdb5332019-02-04 14:29:49 -050013import androidx.annotation.NonNull;
14import androidx.collection.ArrayMap;
15
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 Cinek195dfc52019-05-30 19:35:05 -070018import com.android.settingslib.Utils;
Selim Cinekd03518c2018-03-15 12:13:51 -070019import com.android.systemui.Dependency;
Selim Cinek195dfc52019-05-30 19:35:05 -070020import com.android.systemui.Interpolators;
Anthony Chen83092c62016-01-11 17:00:36 -080021import com.android.systemui.R;
Beverly1be62f42018-12-19 17:17:48 -050022import com.android.systemui.plugins.DarkIconDispatcher;
23import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
Beverly8fdb5332019-02-04 14:29:49 -050024import com.android.systemui.plugins.statusbar.StatusBarStateController;
Selim Cinek999230c2019-06-19 15:36:44 -070025import com.android.systemui.statusbar.CrossFadeHelper;
Lucas Dupin20403372019-02-14 19:59:18 -080026import com.android.systemui.statusbar.NotificationMediaManager;
Selim Cinek281c2022016-10-13 19:14:43 -070027import com.android.systemui.statusbar.NotificationShelf;
Anthony Chen83092c62016-01-11 17:00:36 -080028import com.android.systemui.statusbar.StatusBarIconView;
Selim Cinek195dfc52019-05-30 19:35:05 -070029import com.android.systemui.statusbar.StatusBarState;
Gus Prevas33619af2018-10-26 15:40:27 -040030import com.android.systemui.statusbar.notification.NotificationEntryManager;
Anthony Chen83092c62016-01-11 17:00:36 -080031import com.android.systemui.statusbar.notification.NotificationUtils;
Selim Cinek820ba2d2019-06-18 18:59:09 -070032import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
Ned Burnsf81c4c42019-01-07 14:10:43 -050033import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gus Prevas33619af2018-10-26 15:40:27 -040034import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
Selim Cinek5dc581a2019-06-19 17:24:59 -070035import com.android.systemui.tuner.TunerService;
Anthony Chen83092c62016-01-11 17:00:36 -080036
37import java.util.ArrayList;
Beverly40770652019-02-15 15:49:49 -050038import java.util.Objects;
Selim Cinek281c2022016-10-13 19:14:43 -070039import java.util.function.Function;
Anthony Chen83092c62016-01-11 17:00:36 -080040
41/**
42 * A controller for the space in the status bar to the left of the system icons. This area is
43 * normally reserved for notifications.
44 */
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080045public class NotificationIconAreaController implements DarkReceiver,
Selim Cinek820ba2d2019-06-18 18:59:09 -070046 StatusBarStateController.StateListener,
47 NotificationWakeUpCoordinator.WakeUpListener {
Gus Prevas33619af2018-10-26 15:40:27 -040048
Selim Cinekda330ff2019-06-11 15:41:28 -070049 public static final String HIGH_PRIORITY = "high_priority";
Selim Cinek195dfc52019-05-30 19:35:05 -070050 private static final long AOD_ICONS_APPEAR_DURATION = 200;
Gus Prevas33619af2018-10-26 15:40:27 -040051
Lucas Dupina291d192018-06-07 13:59:42 -070052 private final ContrastColorUtil mContrastColorUtil;
Selim Cinekd03518c2018-03-15 12:13:51 -070053 private final NotificationEntryManager mEntryManager;
54 private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080055 private final StatusBarStateController mStatusBarStateController;
Lucas Dupin20403372019-02-14 19:59:18 -080056 private final NotificationMediaManager mMediaManager;
Selim Cinek820ba2d2019-06-18 18:59:09 -070057 private final NotificationWakeUpCoordinator mWakeUpCoordinator;
58 private final KeyguardBypassController mBypassController;
Selim Cinek195dfc52019-05-30 19:35:05 -070059 private final DozeParameters mDozeParameters;
Anthony Chen83092c62016-01-11 17:00:36 -080060
Selim Cinek5dc581a2019-06-19 17:24:59 -070061 private boolean mShowSilentOnLockscreen = true;
Anthony Chen83092c62016-01-11 17:00:36 -080062 private int mIconSize;
63 private int mIconHPadding;
64 private int mIconTint = Color.WHITE;
Beverly40770652019-02-15 15:49:49 -050065 private int mCenteredIconTint = Color.WHITE;
Anthony Chen83092c62016-01-11 17:00:36 -080066
Jason Monk2a6ea9c2017-01-26 11:14:51 -050067 private StatusBar mStatusBar;
Anthony Chen83092c62016-01-11 17:00:36 -080068 protected View mNotificationIconArea;
Selim Cinek281c2022016-10-13 19:14:43 -070069 private NotificationIconContainer mNotificationIcons;
Selim Cinek5b5beb012016-11-08 18:11:58 -080070 private NotificationIconContainer mShelfIcons;
Beverly40770652019-02-15 15:49:49 -050071 protected View mCenteredIconArea;
72 private NotificationIconContainer mCenteredIcon;
Selim Cinek195dfc52019-05-30 19:35:05 -070073 private NotificationIconContainer mAodIcons;
Beverly40770652019-02-15 15:49:49 -050074 private StatusBarIconView mCenteredIconView;
Jorim Jaggi86905582016-02-09 21:36:09 -080075 private final Rect mTintArea = new Rect();
Jason Monke59dc402018-08-16 12:05:01 -040076 private ViewGroup mNotificationScrollLayout;
Selim Cinek281c2022016-10-13 19:14:43 -070077 private Context mContext;
Selim Cinek195dfc52019-05-30 19:35:05 -070078 private int mAodIconAppearTranslation;
Anthony Chen83092c62016-01-11 17:00:36 -080079
Selim Cinek195dfc52019-05-30 19:35:05 -070080 private boolean mAnimationsEnabled;
81 private int mAodIconTint;
82 private boolean mFullyHidden;
Selim Cinek999230c2019-06-19 15:36:44 -070083 private boolean mAodIconsVisible;
Lucas Dupin23a8d3b2018-10-08 20:57:35 -070084
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080085 public NotificationIconAreaController(Context context, StatusBar statusBar,
Julia Reynolds12ad7ca2019-01-28 09:29:16 -050086 StatusBarStateController statusBarStateController,
Selim Cinek820ba2d2019-06-18 18:59:09 -070087 NotificationWakeUpCoordinator wakeUpCoordinator,
88 KeyguardBypassController keyguardBypassController,
Lucas Dupin20403372019-02-14 19:59:18 -080089 NotificationMediaManager notificationMediaManager) {
Jason Monk2a6ea9c2017-01-26 11:14:51 -050090 mStatusBar = statusBar;
Lucas Dupina291d192018-06-07 13:59:42 -070091 mContrastColorUtil = ContrastColorUtil.getInstance(context);
Selim Cinek281c2022016-10-13 19:14:43 -070092 mContext = context;
Selim Cinekd03518c2018-03-15 12:13:51 -070093 mEntryManager = Dependency.get(NotificationEntryManager.class);
Lucas Dupin7fc9dc12019-01-03 09:19:43 -080094 mStatusBarStateController = statusBarStateController;
95 mStatusBarStateController.addCallback(this);
Lucas Dupin20403372019-02-14 19:59:18 -080096 mMediaManager = notificationMediaManager;
Selim Cinek195dfc52019-05-30 19:35:05 -070097 mDozeParameters = DozeParameters.getInstance(mContext);
Selim Cinek820ba2d2019-06-18 18:59:09 -070098 mWakeUpCoordinator = wakeUpCoordinator;
99 wakeUpCoordinator.addListener(this);
100 mBypassController = keyguardBypassController;
Gus Prevas33619af2018-10-26 15:40:27 -0400101
Anthony Chen83092c62016-01-11 17:00:36 -0800102 initializeNotificationAreaViews(context);
Selim Cinek195dfc52019-05-30 19:35:05 -0700103 reloadAodColor();
Selim Cinek5dc581a2019-06-19 17:24:59 -0700104
105 TunerService tunerService = Dependency.get(TunerService.class);
106 tunerService.addTunable((key, newValue) -> {
107 mShowSilentOnLockscreen = "1".equals(newValue);
108 }, Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS);
Anthony Chen83092c62016-01-11 17:00:36 -0800109 }
110
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700111 protected View inflateIconArea(LayoutInflater inflater) {
112 return inflater.inflate(R.layout.notification_icon_area, null);
113 }
114
Anthony Chen83092c62016-01-11 17:00:36 -0800115 /**
116 * Initializes the views that will represent the notification area.
117 */
118 protected void initializeNotificationAreaViews(Context context) {
Selim Cinek3e7592d2016-04-11 09:35:54 +0800119 reloadDimens(context);
Anthony Chen83092c62016-01-11 17:00:36 -0800120
121 LayoutInflater layoutInflater = LayoutInflater.from(context);
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700122 mNotificationIconArea = inflateIconArea(layoutInflater);
Jason Monke59dc402018-08-16 12:05:01 -0400123 mNotificationIcons = mNotificationIconArea.findViewById(R.id.notificationIcons);
Anthony Chen83092c62016-01-11 17:00:36 -0800124
Jason Monkaa573e92017-01-27 17:00:29 -0500125 mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
Beverly40770652019-02-15 15:49:49 -0500126
127 mCenteredIconArea = layoutInflater.inflate(R.layout.center_icon_area, null);
128 mCenteredIcon = mCenteredIconArea.findViewById(R.id.centeredIcon);
Selim Cinek195dfc52019-05-30 19:35:05 -0700129
130 initAodIcons();
131 }
132
133 public void initAodIcons() {
134 boolean changed = mAodIcons != null;
135 if (changed) {
136 mAodIcons.setAnimationsEnabled(false);
137 mAodIcons.removeAllViews();
138 }
139 mAodIcons = mStatusBar.getStatusBarWindow().findViewById(
140 R.id.clock_notification_icon_container);
141 mAodIcons.setOnLockScreen(true);
Selim Cinek999230c2019-06-19 15:36:44 -0700142 updateAodIconsVisibility(false /* animate */);
Selim Cinek195dfc52019-05-30 19:35:05 -0700143 updateAnimations();
144 if (changed) {
Selim Cinek999230c2019-06-19 15:36:44 -0700145 updateAodNotificationIcons();
Selim Cinek195dfc52019-05-30 19:35:05 -0700146 }
Jason Monkaa573e92017-01-27 17:00:29 -0500147 }
148
149 public void setupShelf(NotificationShelf shelf) {
Selim Cinek5b5beb012016-11-08 18:11:58 -0800150 mShelfIcons = shelf.getShelfIcons();
Selim Cinek49014f82016-11-04 14:55:30 -0700151 shelf.setCollapsedIcons(mNotificationIcons);
Anthony Chen83092c62016-01-11 17:00:36 -0800152 }
153
Selim Cinek3e7592d2016-04-11 09:35:54 +0800154 public void onDensityOrFontScaleChanged(Context context) {
155 reloadDimens(context);
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800156 final FrameLayout.LayoutParams params = generateIconLayoutParams();
Selim Cinek3e7592d2016-04-11 09:35:54 +0800157 for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
158 View child = mNotificationIcons.getChildAt(i);
159 child.setLayoutParams(params);
Selim Cinek9ef119c2017-03-01 15:13:36 -0800160 }
161 for (int i = 0; i < mShelfIcons.getChildCount(); i++) {
162 View child = mShelfIcons.getChildAt(i);
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800163 child.setLayoutParams(params);
Selim Cinek3e7592d2016-04-11 09:35:54 +0800164 }
Beverly40770652019-02-15 15:49:49 -0500165 for (int i = 0; i < mCenteredIcon.getChildCount(); i++) {
166 View child = mCenteredIcon.getChildAt(i);
167 child.setLayoutParams(params);
168 }
Selim Cinek195dfc52019-05-30 19:35:05 -0700169 for (int i = 0; i < mAodIcons.getChildCount(); i++) {
170 View child = mAodIcons.getChildAt(i);
171 child.setLayoutParams(params);
172 }
Selim Cinek3e7592d2016-04-11 09:35:54 +0800173 }
174
175 @NonNull
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800176 private FrameLayout.LayoutParams generateIconLayoutParams() {
177 return new FrameLayout.LayoutParams(
Selim Cinek3e7592d2016-04-11 09:35:54 +0800178 mIconSize + 2 * mIconHPadding, getHeight());
179 }
180
181 private void reloadDimens(Context context) {
182 Resources res = context.getResources();
183 mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
184 mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_padding);
Selim Cinek195dfc52019-05-30 19:35:05 -0700185 mAodIconAppearTranslation = res.getDimensionPixelSize(
186 R.dimen.shelf_appear_translation);
Selim Cinek3e7592d2016-04-11 09:35:54 +0800187 }
188
Anthony Chen83092c62016-01-11 17:00:36 -0800189 /**
190 * Returns the view that represents the notification area.
191 */
192 public View getNotificationInnerAreaView() {
193 return mNotificationIconArea;
194 }
195
196 /**
Beverly40770652019-02-15 15:49:49 -0500197 * Returns the view that represents the centered notification area.
198 */
199 public View getCenteredNotificationAreaView() {
200 return mCenteredIconArea;
201 }
202
203 /**
Jason Monkaa573e92017-01-27 17:00:29 -0500204 * See {@link com.android.systemui.statusbar.policy.DarkIconDispatcher#setIconsDarkArea}.
205 * Sets the color that should be used to tint any icons in the notification area.
Jorim Jaggi86905582016-02-09 21:36:09 -0800206 *
207 * @param tintArea the area in which to tint the icons, specified in screen coordinates
Jason Monkaa573e92017-01-27 17:00:29 -0500208 * @param darkIntensity
Jorim Jaggi86905582016-02-09 21:36:09 -0800209 */
Jason Monkaa573e92017-01-27 17:00:29 -0500210 public void onDarkChanged(Rect tintArea, float darkIntensity, int iconTint) {
Jorim Jaggi86905582016-02-09 21:36:09 -0800211 if (tintArea == null) {
212 mTintArea.setEmpty();
213 } else {
214 mTintArea.set(tintArea);
215 }
Beverly40770652019-02-15 15:49:49 -0500216
Evan Lairddbeefe32018-04-03 16:52:41 -0400217 if (mNotificationIconArea != null) {
218 if (DarkIconDispatcher.isInArea(tintArea, mNotificationIconArea)) {
219 mIconTint = iconTint;
220 }
221 } else {
222 mIconTint = iconTint;
223 }
224
Beverly40770652019-02-15 15:49:49 -0500225 if (mCenteredIconArea != null) {
226 if (DarkIconDispatcher.isInArea(tintArea, mCenteredIconArea)) {
227 mCenteredIconTint = iconTint;
228 }
229 } else {
230 mCenteredIconTint = iconTint;
231 }
232
Anthony Chen83092c62016-01-11 17:00:36 -0800233 applyNotificationIconsTint();
234 }
235
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700236 protected int getHeight() {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500237 return mStatusBar.getStatusBarHeight();
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700238 }
239
Ned Burnsf81c4c42019-01-07 14:10:43 -0500240 protected boolean shouldShowNotificationIcon(NotificationEntry entry,
Gus Prevas33619af2018-10-26 15:40:27 -0400241 boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
Selim Cinek820ba2d2019-06-18 18:59:09 -0700242 boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon,
Beverlyfd3b1dca2019-06-25 16:21:00 -0400243 boolean hidePulsing, boolean onlyShowCenteredIcon) {
Beverly40770652019-02-15 15:49:49 -0500244
Beverlyfd3b1dca2019-06-25 16:21:00 -0400245 final boolean isCenteredNotificationIcon = mCenteredIconView != null
246 && entry.centeredIcon != null
Beverly40770652019-02-15 15:49:49 -0500247 && Objects.equals(entry.centeredIcon, mCenteredIconView);
Beverlyfd3b1dca2019-06-25 16:21:00 -0400248 if (onlyShowCenteredIcon) {
249 return isCenteredNotificationIcon;
250 }
251 if (hideCenteredIcon && isCenteredNotificationIcon) {
Beverly40770652019-02-15 15:49:49 -0500252 return false;
253 }
Selim Cinekd03518c2018-03-15 12:13:51 -0700254 if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700255 return false;
256 }
Lucas Dupin20403372019-02-14 19:59:18 -0800257 if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
258 return false;
259 }
Gus Prevascaed15c2019-01-18 14:19:51 -0500260 if (!showLowPriority && !entry.isHighPriority()) {
Gus Prevas33619af2018-10-26 15:40:27 -0400261 return false;
262 }
Evan Laird94492852018-10-25 13:43:01 -0400263 if (!entry.isTopLevelChild()) {
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700264 return false;
265 }
Evan Laird94492852018-10-25 13:43:01 -0400266 if (entry.getRow().getVisibility() == View.GONE) {
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700267 return false;
268 }
Evan Laird94492852018-10-25 13:43:01 -0400269 if (entry.isRowDismissed() && hideDismissed) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700270 return false;
271 }
Selim Cinekb0dc61b2018-05-22 18:49:36 -0700272 if (hideRepliedMessages && entry.isLastMessageFromReply()) {
273 return false;
274 }
Julia Reynoldsc861a3d2018-02-15 10:34:49 -0500275 // showAmbient == show in shade but not shelf
Selim Cinek195dfc52019-05-30 19:35:05 -0700276 if (!showAmbient && entry.shouldSuppressStatusBar()) {
Julia Reynoldsc861a3d2018-02-15 10:34:49 -0500277 return false;
278 }
Selim Cinek820ba2d2019-06-18 18:59:09 -0700279 if (hidePulsing && entry.showingPulsing()) {
280 return false;
281 }
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700282 return true;
283 }
284
Anthony Chen83092c62016-01-11 17:00:36 -0800285 /**
286 * Updates the notifications with the given list of notifications to display.
287 */
Selim Cinekd03518c2018-03-15 12:13:51 -0700288 public void updateNotificationIcons() {
Selim Cinekd03518c2018-03-15 12:13:51 -0700289 updateStatusBarIcons();
Selim Cinek9bfc7a52018-06-11 16:09:00 -0700290 updateShelfIcons();
Beverly40770652019-02-15 15:49:49 -0500291 updateCenterIcon();
Selim Cinek999230c2019-06-19 15:36:44 -0700292 updateAodNotificationIcons();
Selim Cinek281c2022016-10-13 19:14:43 -0700293
294 applyNotificationIconsTint();
Selim Cinek281c2022016-10-13 19:14:43 -0700295 }
296
Selim Cinek9bfc7a52018-06-11 16:09:00 -0700297 private void updateShelfIcons() {
298 updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
Beverly40770652019-02-15 15:49:49 -0500299 true /* showAmbient */,
Selim Cinek195dfc52019-05-30 19:35:05 -0700300 true /* showLowPriority */,
Beverly40770652019-02-15 15:49:49 -0500301 false /* hideDismissed */,
Selim Cinek195dfc52019-05-30 19:35:05 -0700302 false /* hideRepliedMessages */,
303 false /* hideCurrentMedia */,
Beverlyfd3b1dca2019-06-25 16:21:00 -0400304 false /* hide centered icon */,
305 false /* hidePulsing */,
306 false /* onlyShowCenteredIcon */);
Selim Cinek9bfc7a52018-06-11 16:09:00 -0700307 }
308
Selim Cinekb0dc61b2018-05-22 18:49:36 -0700309 public void updateStatusBarIcons() {
Selim Cinekd03518c2018-03-15 12:13:51 -0700310 updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
Beverly40770652019-02-15 15:49:49 -0500311 false /* showAmbient */,
Selim Cinek5dc581a2019-06-19 17:24:59 -0700312 true /* showLowPriority */,
Gus Prevasdddef392018-11-02 15:41:43 -0400313 true /* hideDismissed */,
Lucas Dupin20403372019-02-14 19:59:18 -0800314 true /* hideRepliedMessages */,
Beverly40770652019-02-15 15:49:49 -0500315 false /* hideCurrentMedia */,
Selim Cinek820ba2d2019-06-18 18:59:09 -0700316 true /* hide centered icon */,
Beverlyfd3b1dca2019-06-25 16:21:00 -0400317 false /* hidePulsing */,
318 false /* onlyShowCenteredIcon */);
Beverly40770652019-02-15 15:49:49 -0500319 }
320
321 private void updateCenterIcon() {
322 updateIconsForLayout(entry -> entry.centeredIcon, mCenteredIcon,
323 false /* showAmbient */,
Selim Cinek195dfc52019-05-30 19:35:05 -0700324 true /* showLowPriority */,
Beverly40770652019-02-15 15:49:49 -0500325 false /* hideDismissed */,
326 false /* hideRepliedMessages */,
Selim Cinek195dfc52019-05-30 19:35:05 -0700327 false /* hideCurrentMedia */,
Selim Cinek820ba2d2019-06-18 18:59:09 -0700328 false /* hide centered icon */,
Beverlyfd3b1dca2019-06-25 16:21:00 -0400329 false /* hidePulsing */,
330 true/* onlyShowCenteredIcon */);
Selim Cinekd03518c2018-03-15 12:13:51 -0700331 }
332
Selim Cinek999230c2019-06-19 15:36:44 -0700333 public void updateAodNotificationIcons() {
Selim Cinek195dfc52019-05-30 19:35:05 -0700334 updateIconsForLayout(entry -> entry.aodIcon, mAodIcons,
335 false /* showAmbient */,
Selim Cinek5dc581a2019-06-19 17:24:59 -0700336 mShowSilentOnLockscreen /* showLowPriority */,
Selim Cinek195dfc52019-05-30 19:35:05 -0700337 true /* hideDismissed */,
338 true /* hideRepliedMessages */,
339 true /* hideCurrentMedia */,
Selim Cinek820ba2d2019-06-18 18:59:09 -0700340 true /* hide centered icon */,
Beverlyfd3b1dca2019-06-25 16:21:00 -0400341 mBypassController.getBypassEnabled() /* hidePulsing */,
342 false /* onlyShowCenteredIcon */);
Selim Cinek195dfc52019-05-30 19:35:05 -0700343 }
344
Selim Cinek281c2022016-10-13 19:14:43 -0700345 /**
346 * Updates the notification icons for a host layout. This will ensure that the notification
347 * host layout will have the same icons like the ones in here.
Selim Cinek281c2022016-10-13 19:14:43 -0700348 * @param function A function to look up an icon view based on an entry
349 * @param hostLayout which layout should be updated
Selim Cinek17e1b692016-12-02 18:19:11 -0800350 * @param showAmbient should ambient notification icons be shown
Selim Cinekd03518c2018-03-15 12:13:51 -0700351 * @param hideDismissed should dismissed icons be hidden
Selim Cinekb0dc61b2018-05-22 18:49:36 -0700352 * @param hideRepliedMessages should messages that have been replied to be hidden
Selim Cinek820ba2d2019-06-18 18:59:09 -0700353 * @param hidePulsing should pulsing notifications be hidden
Selim Cinek281c2022016-10-13 19:14:43 -0700354 */
Ned Burnsf81c4c42019-01-07 14:10:43 -0500355 private void updateIconsForLayout(Function<NotificationEntry, StatusBarIconView> function,
Gus Prevas33619af2018-10-26 15:40:27 -0400356 NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority,
Beverly40770652019-02-15 15:49:49 -0500357 boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia,
Beverlyfd3b1dca2019-06-25 16:21:00 -0400358 boolean hideCenteredIcon, boolean hidePulsing, boolean onlyShowCenteredIcon) {
Selim Cinek281c2022016-10-13 19:14:43 -0700359 ArrayList<StatusBarIconView> toShow = new ArrayList<>(
360 mNotificationScrollLayout.getChildCount());
Anthony Chen83092c62016-01-11 17:00:36 -0800361
362 // Filter out ambient notifications and notification children.
Selim Cinek281c2022016-10-13 19:14:43 -0700363 for (int i = 0; i < mNotificationScrollLayout.getChildCount(); i++) {
364 View view = mNotificationScrollLayout.getChildAt(i);
365 if (view instanceof ExpandableNotificationRow) {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500366 NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry();
Gus Prevas33619af2018-10-26 15:40:27 -0400367 if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed,
Beverlyfd3b1dca2019-06-25 16:21:00 -0400368 hideRepliedMessages, hideCurrentMedia, hideCenteredIcon, hidePulsing,
369 onlyShowCenteredIcon)) {
Beverly40770652019-02-15 15:49:49 -0500370 StatusBarIconView iconView = function.apply(ent);
371 if (iconView != null) {
372 toShow.add(iconView);
373 }
Selim Cinek281c2022016-10-13 19:14:43 -0700374 }
Anthony Chen83092c62016-01-11 17:00:36 -0800375 }
Anthony Chen83092c62016-01-11 17:00:36 -0800376 }
377
Selim Cinek72fc8db2017-06-06 18:07:47 -0700378 // In case we are changing the suppression of a group, the replacement shouldn't flicker
379 // and it should just be replaced instead. We therefore look for notifications that were
380 // just replaced by the child or vice-versa to suppress this.
Selim Cinek49014f82016-11-04 14:55:30 -0700381
Selim Cinek72fc8db2017-06-06 18:07:47 -0700382 ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();
Anthony Chen83092c62016-01-11 17:00:36 -0800383 ArrayList<View> toRemove = new ArrayList<>();
Selim Cinek281c2022016-10-13 19:14:43 -0700384 for (int i = 0; i < hostLayout.getChildCount(); i++) {
385 View child = hostLayout.getChildAt(i);
Selim Cinek72fc8db2017-06-06 18:07:47 -0700386 if (!(child instanceof StatusBarIconView)) {
387 continue;
388 }
Anthony Chen83092c62016-01-11 17:00:36 -0800389 if (!toShow.contains(child)) {
Selim Cinek72fc8db2017-06-06 18:07:47 -0700390 boolean iconWasReplaced = false;
391 StatusBarIconView removedIcon = (StatusBarIconView) child;
392 String removedGroupKey = removedIcon.getNotification().getGroupKey();
393 for (int j = 0; j < toShow.size(); j++) {
394 StatusBarIconView candidate = toShow.get(j);
395 if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
396 && candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
397 if (!iconWasReplaced) {
398 iconWasReplaced = true;
399 } else {
400 iconWasReplaced = false;
401 break;
402 }
403 }
404 }
405 if (iconWasReplaced) {
406 ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);
407 if (statusBarIcons == null) {
408 statusBarIcons = new ArrayList<>();
409 replacingIcons.put(removedGroupKey, statusBarIcons);
410 }
411 statusBarIcons.add(removedIcon.getStatusBarIcon());
412 }
413 toRemove.add(removedIcon);
Anthony Chen83092c62016-01-11 17:00:36 -0800414 }
415 }
Selim Cinek72fc8db2017-06-06 18:07:47 -0700416 // removing all duplicates
417 ArrayList<String> duplicates = new ArrayList<>();
418 for (String key : replacingIcons.keySet()) {
419 ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(key);
420 if (statusBarIcons.size() != 1) {
421 duplicates.add(key);
422 }
423 }
424 replacingIcons.removeAll(duplicates);
425 hostLayout.setReplacingIcons(replacingIcons);
Anthony Chen83092c62016-01-11 17:00:36 -0800426
427 final int toRemoveCount = toRemove.size();
428 for (int i = 0; i < toRemoveCount; i++) {
Selim Cinek281c2022016-10-13 19:14:43 -0700429 hostLayout.removeView(toRemove.get(i));
Anthony Chen83092c62016-01-11 17:00:36 -0800430 }
431
Selim Cinek0e8d77e2016-11-29 10:35:42 -0800432 final FrameLayout.LayoutParams params = generateIconLayoutParams();
Anthony Chen83092c62016-01-11 17:00:36 -0800433 for (int i = 0; i < toShow.size(); i++) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700434 StatusBarIconView v = toShow.get(i);
Selim Cinek5b5beb012016-11-08 18:11:58 -0800435 // The view might still be transiently added if it was just removed and added again
436 hostLayout.removeTransientView(v);
Anthony Chen83092c62016-01-11 17:00:36 -0800437 if (v.getParent() == null) {
Selim Cinekd03518c2018-03-15 12:13:51 -0700438 if (hideDismissed) {
439 v.setOnDismissListener(mUpdateStatusBarIcons);
440 }
Selim Cinek281c2022016-10-13 19:14:43 -0700441 hostLayout.addView(v, i, params);
Anthony Chen83092c62016-01-11 17:00:36 -0800442 }
443 }
444
Selim Cinek5b5beb012016-11-08 18:11:58 -0800445 hostLayout.setChangingViewPositions(true);
Anthony Chen83092c62016-01-11 17:00:36 -0800446 // Re-sort notification icons
Selim Cinek281c2022016-10-13 19:14:43 -0700447 final int childCount = hostLayout.getChildCount();
Anthony Chen83092c62016-01-11 17:00:36 -0800448 for (int i = 0; i < childCount; i++) {
Selim Cinek281c2022016-10-13 19:14:43 -0700449 View actual = hostLayout.getChildAt(i);
Anthony Chen83092c62016-01-11 17:00:36 -0800450 StatusBarIconView expected = toShow.get(i);
451 if (actual == expected) {
452 continue;
453 }
Selim Cinek281c2022016-10-13 19:14:43 -0700454 hostLayout.removeView(expected);
455 hostLayout.addView(expected, i);
Anthony Chen83092c62016-01-11 17:00:36 -0800456 }
Selim Cinek5b5beb012016-11-08 18:11:58 -0800457 hostLayout.setChangingViewPositions(false);
Selim Cinek72fc8db2017-06-06 18:07:47 -0700458 hostLayout.setReplacingIcons(null);
Anthony Chen83092c62016-01-11 17:00:36 -0800459 }
460
461 /**
462 * Applies {@link #mIconTint} to the notification icons.
Beverly40770652019-02-15 15:49:49 -0500463 * Applies {@link #mCenteredIconTint} to the center notification icon.
Anthony Chen83092c62016-01-11 17:00:36 -0800464 */
465 private void applyNotificationIconsTint() {
466 for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
Selim Cinek887da3c2017-10-06 13:37:32 -0700467 final StatusBarIconView iv = (StatusBarIconView) mNotificationIcons.getChildAt(i);
468 if (iv.getWidth() != 0) {
Beverly40770652019-02-15 15:49:49 -0500469 updateTintForIcon(iv, mIconTint);
Selim Cinek887da3c2017-10-06 13:37:32 -0700470 } else {
Beverly40770652019-02-15 15:49:49 -0500471 iv.executeOnLayout(() -> updateTintForIcon(iv, mIconTint));
472 }
473 }
474
475 for (int i = 0; i < mCenteredIcon.getChildCount(); i++) {
476 final StatusBarIconView iv = (StatusBarIconView) mCenteredIcon.getChildAt(i);
477 if (iv.getWidth() != 0) {
478 updateTintForIcon(iv, mCenteredIconTint);
479 } else {
480 iv.executeOnLayout(() -> updateTintForIcon(iv, mCenteredIconTint));
Anthony Chen83092c62016-01-11 17:00:36 -0800481 }
Anthony Chen83092c62016-01-11 17:00:36 -0800482 }
Selim Cinek195dfc52019-05-30 19:35:05 -0700483
484 updateAodIconColors();
Anthony Chen83092c62016-01-11 17:00:36 -0800485 }
Lucas Dupin987f1932017-05-13 21:02:52 -0700486
Beverly40770652019-02-15 15:49:49 -0500487 private void updateTintForIcon(StatusBarIconView v, int tint) {
Selim Cinek887da3c2017-10-06 13:37:32 -0700488 boolean isPreL = Boolean.TRUE.equals(v.getTag(R.id.icon_is_pre_L));
489 int color = StatusBarIconView.NO_COLOR;
Lucas Dupina291d192018-06-07 13:59:42 -0700490 boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mContrastColorUtil);
Selim Cinek887da3c2017-10-06 13:37:32 -0700491 if (colorize) {
Beverly40770652019-02-15 15:49:49 -0500492 color = DarkIconDispatcher.getTint(mTintArea, v, tint);
Selim Cinek887da3c2017-10-06 13:37:32 -0700493 }
494 v.setStaticDrawableColor(color);
Beverly40770652019-02-15 15:49:49 -0500495 v.setDecorColor(tint);
Selim Cinek887da3c2017-10-06 13:37:32 -0700496 }
497
Beverly40770652019-02-15 15:49:49 -0500498 /**
499 * Shows the icon view given in the center.
500 */
501 public void showIconCentered(NotificationEntry entry) {
502 StatusBarIconView icon = entry == null ? null : entry.centeredIcon;
503 if (!Objects.equals(mCenteredIconView, icon)) {
504 mCenteredIconView = icon;
505 updateNotificationIcons();
506 }
Lucas Dupin987f1932017-05-13 21:02:52 -0700507 }
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800508
Selim Cinek332c23f2018-03-16 17:37:50 -0700509 public void showIconIsolated(StatusBarIconView icon, boolean animated) {
510 mNotificationIcons.showIconIsolated(icon, animated);
511 }
512
513 public void setIsolatedIconLocation(Rect iconDrawingRect, boolean requireStateUpdate) {
514 mNotificationIcons.setIsolatedIconLocation(iconDrawingRect, requireStateUpdate);
Selim Cinekaa9db1f2018-02-27 17:35:47 -0800515 }
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700516
Lucas Dupin7fc9dc12019-01-03 09:19:43 -0800517 @Override
Selim Cinek195dfc52019-05-30 19:35:05 -0700518 public void onDozingChanged(boolean isDozing) {
519 boolean animate = mDozeParameters.getAlwaysOn()
520 && !mDozeParameters.getDisplayNeedsBlanking();
521 mAodIcons.setDozing(isDozing, animate, 0);
522 }
523
524 public void setAnimationsEnabled(boolean enabled) {
525 mAnimationsEnabled = enabled;
526 updateAnimations();
527 }
528
529 @Override
530 public void onStateChanged(int newState) {
Selim Cinek999230c2019-06-19 15:36:44 -0700531 updateAodIconsVisibility(false /* animate */);
Selim Cinek195dfc52019-05-30 19:35:05 -0700532 updateAnimations();
533 }
534
535 private void updateAnimations() {
536 boolean inShade = mStatusBarStateController.getState() == StatusBarState.SHADE;
537 mAodIcons.setAnimationsEnabled(mAnimationsEnabled && !inShade);
538 mCenteredIcon.setAnimationsEnabled(mAnimationsEnabled && inShade);
539 mNotificationIcons.setAnimationsEnabled(mAnimationsEnabled && inShade);
540 }
541
542 public void onThemeChanged() {
543 reloadAodColor();
544 updateAodIconColors();
545 }
546
547 public void appearAodIcons() {
548 DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
549 if (dozeParameters.shouldControlScreenOff()) {
550 mAodIcons.setTranslationY(-mAodIconAppearTranslation);
551 mAodIcons.setAlpha(0);
552 mAodIcons.animate()
553 .setInterpolator(Interpolators.DECELERATE_QUINT)
554 .translationY(0)
555 .setDuration(AOD_ICONS_APPEAR_DURATION)
556 .start();
557 mAodIcons.animate()
558 .alpha(1)
559 .setInterpolator(Interpolators.LINEAR)
560 .setDuration(AOD_ICONS_APPEAR_DURATION)
561 .start();
Lucas Dupin7fc9dc12019-01-03 09:19:43 -0800562 }
Lucas Dupin23a8d3b2018-10-08 20:57:35 -0700563 }
Selim Cinek195dfc52019-05-30 19:35:05 -0700564
565 private void reloadAodColor() {
566 mAodIconTint = Utils.getColorAttrDefaultColor(mContext,
567 R.attr.wallpaperTextColor);
568 }
569 private void updateAodIconColors() {
570 for (int i = 0; i < mAodIcons.getChildCount(); i++) {
571 final StatusBarIconView iv = (StatusBarIconView) mAodIcons.getChildAt(i);
572 if (iv.getWidth() != 0) {
573 updateTintForIcon(iv, mAodIconTint);
574 } else {
575 iv.executeOnLayout(() -> updateTintForIcon(iv, mAodIconTint));
576 }
577 }
578 }
579
Selim Cinek820ba2d2019-06-18 18:59:09 -0700580 @Override
581 public void onFullyHiddenChanged(boolean fullyHidden) {
Selim Cinek999230c2019-06-19 15:36:44 -0700582 boolean animate = true;
583 if (!mBypassController.getBypassEnabled()) {
584 animate = mDozeParameters.getAlwaysOn() && !mDozeParameters.getDisplayNeedsBlanking();
585 // We only want the appear animations to happen when the notifications get fully hidden,
586 // since otherwise the unhide animation overlaps
587 animate &= fullyHidden;
Selim Cinek820ba2d2019-06-18 18:59:09 -0700588 }
Selim Cinek999230c2019-06-19 15:36:44 -0700589 updateAodIconsVisibility(animate);
590 updateAodNotificationIcons();
Selim Cinek820ba2d2019-06-18 18:59:09 -0700591 }
592
593 @Override
594 public void onPulseExpansionChanged(boolean expandingChanged) {
595 if (expandingChanged) {
Selim Cinek999230c2019-06-19 15:36:44 -0700596 updateAodIconsVisibility(true /* animate */);
Selim Cinek195dfc52019-05-30 19:35:05 -0700597 }
598 }
599
Selim Cinek999230c2019-06-19 15:36:44 -0700600 private void updateAodIconsVisibility(boolean animate) {
Selim Cinek820ba2d2019-06-18 18:59:09 -0700601 boolean visible = mBypassController.getBypassEnabled()
602 || mWakeUpCoordinator.getNotificationsFullyHidden();
603 if (mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
604 visible = false;
605 }
606 if (visible && mWakeUpCoordinator.isPulseExpanding()) {
607 visible = false;
608 }
Selim Cinek999230c2019-06-19 15:36:44 -0700609 if (mAodIconsVisible != visible) {
610 mAodIconsVisible = visible;
611 mAodIcons.animate().cancel();
612 if (animate) {
613 boolean wasFullyInvisible = mAodIcons.getVisibility() != View.VISIBLE;
614 if (mAodIconsVisible) {
615 if (wasFullyInvisible) {
616 // No fading here, let's just appear the icons instead!
617 mAodIcons.setVisibility(View.VISIBLE);
618 mAodIcons.setAlpha(1.0f);
619 appearAodIcons();
620 } else {
621 // We were fading out, let's fade in instead
622 CrossFadeHelper.fadeIn(mAodIcons);
623 }
624 } else {
625 CrossFadeHelper.fadeOut(mAodIcons);
626 }
627 } else {
628 mAodIcons.setAlpha(1.0f);
629 mAodIcons.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
630 }
631 }
Selim Cinek195dfc52019-05-30 19:35:05 -0700632 }
Anthony Chen83092c62016-01-11 17:00:36 -0800633}