blob: b70b45b9db842228ab51710233d3b386d6a40666 [file] [log] [blame]
Eliot Courtney2b4c3a02017-11-27 13:27:46 +09001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar;
18
19import android.content.Context;
20import android.content.res.Resources;
Lucas Dupin16013822018-05-17 18:00:16 -070021import android.os.Trace;
Selim Cinek6f0a62a2019-04-09 18:40:12 -070022import android.os.UserHandle;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090023import android.util.Log;
24import android.view.View;
25import android.view.ViewGroup;
26
27import com.android.systemui.R;
Selim Cinekfdf80332019-03-07 17:29:55 -080028import com.android.systemui.bubbles.BubbleData;
Beverly80110912019-02-13 12:20:57 -050029import com.android.systemui.plugins.statusbar.StatusBarStateController;
Selim Cinek6f0a62a2019-04-09 18:40:12 -070030import com.android.systemui.statusbar.notification.DynamicPrivacyController;
Rohan Shah20790b82018-07-02 17:21:04 -070031import com.android.systemui.statusbar.notification.NotificationEntryManager;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090032import com.android.systemui.statusbar.notification.VisualStabilityManager;
Ned Burnsf81c4c42019-01-07 14:10:43 -050033import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Rohan Shah20790b82018-07-02 17:21:04 -070034import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
35import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090036import com.android.systemui.statusbar.phone.NotificationGroupManager;
Jason Monk297c04e2018-08-23 17:16:59 -040037import com.android.systemui.statusbar.phone.ShadeController;
Ned Burnsd4a69f72019-06-19 19:49:19 -040038import com.android.systemui.util.Assert;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090039
40import java.util.ArrayList;
41import java.util.HashMap;
42import java.util.List;
43import java.util.Stack;
44
Jason Monk27d01a622018-12-10 15:57:09 -050045import javax.inject.Inject;
46import javax.inject.Singleton;
47
Jason Monk09f4d372018-12-20 15:30:54 -050048import dagger.Lazy;
49
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090050/**
51 * NotificationViewHierarchyManager manages updating the view hierarchy of notification views based
52 * on their group structure. For example, if a notification becomes bundled with another,
53 * NotificationViewHierarchyManager will update the view hierarchy to reflect that. It also will
54 * tell NotificationListContainer which notifications to display, and inform it of changes to those
55 * notifications that might affect their display.
56 */
Jason Monk27d01a622018-12-10 15:57:09 -050057@Singleton
Selim Cinek6f0a62a2019-04-09 18:40:12 -070058public class NotificationViewHierarchyManager implements DynamicPrivacyController.Listener {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090059 private static final String TAG = "NotificationViewHierarchyManager";
60
Evan Laird94492852018-10-25 13:43:01 -040061 //TODO: change this top <Entry, List<Entry>>?
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090062 private final HashMap<ExpandableNotificationRow, List<ExpandableNotificationRow>>
63 mTmpChildOrderMap = new HashMap<>();
Eliot Courtney6c313d32017-12-14 19:57:51 +090064
65 // Dependencies:
Jason Monk09f4d372018-12-20 15:30:54 -050066 protected final NotificationLockscreenUserManager mLockscreenUserManager;
67 protected final NotificationGroupManager mGroupManager;
68 protected final VisualStabilityManager mVisualStabilityManager;
Beverly80110912019-02-13 12:20:57 -050069 private final SysuiStatusBarStateController mStatusBarStateController;
Jason Monk09f4d372018-12-20 15:30:54 -050070 private final NotificationEntryManager mEntryManager;
Jason Monk297c04e2018-08-23 17:16:59 -040071
72 // Lazy
Jason Monk09f4d372018-12-20 15:30:54 -050073 private final Lazy<ShadeController> mShadeController;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090074
75 /**
76 * {@code true} if notifications not part of a group should by default be rendered in their
77 * expanded state. If {@code false}, then only the first notification will be expanded if
78 * possible.
79 */
80 private final boolean mAlwaysExpandNonGroupedNotification;
Selim Cinekfdf80332019-03-07 17:29:55 -080081 private final BubbleData mBubbleData;
Selim Cinek6f0a62a2019-04-09 18:40:12 -070082 private final DynamicPrivacyController mDynamicPrivacyController;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090083
84 private NotificationPresenter mPresenter;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090085 private NotificationListContainer mListContainer;
86
Ned Burnsd4a69f72019-06-19 19:49:19 -040087 // Used to help track down re-entrant calls to our update methods, which will cause bugs.
88 private boolean mPerformingUpdate;
89
Jason Monk27d01a622018-12-10 15:57:09 -050090 @Inject
Jason Monk09f4d372018-12-20 15:30:54 -050091 public NotificationViewHierarchyManager(Context context,
92 NotificationLockscreenUserManager notificationLockscreenUserManager,
93 NotificationGroupManager groupManager,
94 VisualStabilityManager visualStabilityManager,
Beverly80110912019-02-13 12:20:57 -050095 StatusBarStateController statusBarStateController,
Jason Monk09f4d372018-12-20 15:30:54 -050096 NotificationEntryManager notificationEntryManager,
Selim Cinekfdf80332019-03-07 17:29:55 -080097 Lazy<ShadeController> shadeController,
Selim Cinek6f0a62a2019-04-09 18:40:12 -070098 BubbleData bubbleData,
99 DynamicPrivacyController privacyController) {
Jason Monk09f4d372018-12-20 15:30:54 -0500100 mLockscreenUserManager = notificationLockscreenUserManager;
101 mGroupManager = groupManager;
102 mVisualStabilityManager = visualStabilityManager;
Beverly80110912019-02-13 12:20:57 -0500103 mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
Jason Monk09f4d372018-12-20 15:30:54 -0500104 mEntryManager = notificationEntryManager;
Jason Monk09f4d372018-12-20 15:30:54 -0500105 mShadeController = shadeController;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900106 Resources res = context.getResources();
107 mAlwaysExpandNonGroupedNotification =
108 res.getBoolean(R.bool.config_alwaysExpandNonGroupedNotifications);
Selim Cinekfdf80332019-03-07 17:29:55 -0800109 mBubbleData = bubbleData;
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700110 mDynamicPrivacyController = privacyController;
111 privacyController.addListener(this);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900112 }
113
114 public void setUpWithPresenter(NotificationPresenter presenter,
Jason Monk297c04e2018-08-23 17:16:59 -0400115 NotificationListContainer listContainer) {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900116 mPresenter = presenter;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900117 mListContainer = listContainer;
118 }
119
120 /**
121 * Updates the visual representation of the notifications.
122 */
Evan Laird94492852018-10-25 13:43:01 -0400123 //TODO: Rewrite this to focus on Entries, or some other data object instead of views
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900124 public void updateNotificationViews() {
Ned Burnsd4a69f72019-06-19 19:49:19 -0400125 Assert.isMainThread();
126 beginUpdate();
127
Ned Burnsf81c4c42019-01-07 14:10:43 -0500128 ArrayList<NotificationEntry> activeNotifications = mEntryManager.getNotificationData()
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900129 .getActiveNotifications();
130 ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
131 final int N = activeNotifications.size();
132 for (int i = 0; i < N; i++) {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500133 NotificationEntry ent = activeNotifications.get(i);
Selim Cinekfdf80332019-03-07 17:29:55 -0800134 if (ent.isRowDismissed() || ent.isRowRemoved()
Mark Renouf71a3af62019-04-08 15:02:54 -0400135 || (mBubbleData.hasBubbleWithKey(ent.key) && !ent.showInShadeWhenBubble())) {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900136 // we don't want to update removed notifications because they could
137 // temporarily become children if they were isolated before.
138 continue;
139 }
Mady Mellor5549dd22018-11-06 18:07:34 -0800140
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900141 int userId = ent.notification.getUserId();
142
143 // Display public version of the notification if we need to redact.
144 // TODO: This area uses a lot of calls into NotificationLockscreenUserManager.
145 // We can probably move some of this code there.
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700146 int currentUserId = mLockscreenUserManager.getCurrentUserId();
147 boolean devicePublic = mLockscreenUserManager.isLockscreenPublicMode(currentUserId);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900148 boolean userPublic = devicePublic
149 || mLockscreenUserManager.isLockscreenPublicMode(userId);
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700150 if (userPublic && mDynamicPrivacyController.isDynamicallyUnlocked()
151 && (userId == currentUserId || userId == UserHandle.USER_ALL
152 || !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) {
153 userPublic = false;
154 }
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900155 boolean needsRedaction = mLockscreenUserManager.needsRedaction(ent);
156 boolean sensitive = userPublic && needsRedaction;
157 boolean deviceSensitive = devicePublic
158 && !mLockscreenUserManager.userAllowsPrivateNotificationsInPublic(
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700159 currentUserId);
Evan Laird94492852018-10-25 13:43:01 -0400160 ent.getRow().setSensitive(sensitive, deviceSensitive);
161 ent.getRow().setNeedsRedaction(needsRedaction);
162 if (mGroupManager.isChildInGroupWithSummary(ent.notification)) {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500163 NotificationEntry summary = mGroupManager.getGroupSummary(ent.notification);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900164 List<ExpandableNotificationRow> orderedChildren =
Evan Laird94492852018-10-25 13:43:01 -0400165 mTmpChildOrderMap.get(summary.getRow());
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900166 if (orderedChildren == null) {
167 orderedChildren = new ArrayList<>();
Evan Laird94492852018-10-25 13:43:01 -0400168 mTmpChildOrderMap.put(summary.getRow(), orderedChildren);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900169 }
Evan Laird94492852018-10-25 13:43:01 -0400170 orderedChildren.add(ent.getRow());
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900171 } else {
Evan Laird94492852018-10-25 13:43:01 -0400172 toShow.add(ent.getRow());
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900173 }
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900174 }
175
Rohan Shah524cf7b2018-03-15 14:40:02 -0700176 ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900177 for (int i=0; i< mListContainer.getContainerChildCount(); i++) {
178 View child = mListContainer.getContainerChildAt(i);
179 if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) {
Rohan Shah524cf7b2018-03-15 14:40:02 -0700180 ExpandableNotificationRow row = (ExpandableNotificationRow) child;
181
182 // Blocking helper is effectively a detached view. Don't bother removing it from the
183 // layout.
184 if (!row.isBlockingHelperShowing()) {
185 viewsToRemove.add((ExpandableNotificationRow) child);
186 }
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900187 }
188 }
189
Rohan Shah524cf7b2018-03-15 14:40:02 -0700190 for (ExpandableNotificationRow viewToRemove : viewsToRemove) {
191 if (mGroupManager.isChildInGroupWithSummary(viewToRemove.getStatusBarNotification())) {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900192 // we are only transferring this notification to its parent, don't generate an
193 // animation
194 mListContainer.setChildTransferInProgress(true);
195 }
Rohan Shah524cf7b2018-03-15 14:40:02 -0700196 if (viewToRemove.isSummaryWithChildren()) {
197 viewToRemove.removeAllChildren();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900198 }
Rohan Shah524cf7b2018-03-15 14:40:02 -0700199 mListContainer.removeContainerView(viewToRemove);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900200 mListContainer.setChildTransferInProgress(false);
201 }
202
203 removeNotificationChildren();
204
205 for (int i = 0; i < toShow.size(); i++) {
206 View v = toShow.get(i);
207 if (v.getParent() == null) {
208 mVisualStabilityManager.notifyViewAddition(v);
209 mListContainer.addContainerView(v);
Selim Cinekfdf80332019-03-07 17:29:55 -0800210 } else if (!mListContainer.containsView(v)) {
211 // the view is added somewhere else. Let's make sure
212 // the ordering works properly below, by excluding these
213 toShow.remove(v);
214 i--;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900215 }
216 }
217
218 addNotificationChildrenAndSort();
219
220 // So after all this work notifications still aren't sorted correctly.
221 // Let's do that now by advancing through toShow and mListContainer in
222 // lock-step, making sure mListContainer matches what we see in toShow.
223 int j = 0;
224 for (int i = 0; i < mListContainer.getContainerChildCount(); i++) {
225 View child = mListContainer.getContainerChildAt(i);
226 if (!(child instanceof ExpandableNotificationRow)) {
227 // We don't care about non-notification views.
228 continue;
229 }
Rohan Shah524cf7b2018-03-15 14:40:02 -0700230 if (((ExpandableNotificationRow) child).isBlockingHelperShowing()) {
231 // Don't count/reorder notifications that are showing the blocking helper!
232 continue;
233 }
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900234
235 ExpandableNotificationRow targetChild = toShow.get(j);
236 if (child != targetChild) {
237 // Oops, wrong notification at this position. Put the right one
238 // here and advance both lists.
239 if (mVisualStabilityManager.canReorderNotification(targetChild)) {
240 mListContainer.changeViewPosition(targetChild, i);
241 } else {
242 mVisualStabilityManager.addReorderingAllowedCallback(mEntryManager);
243 }
244 }
245 j++;
246
247 }
248
249 mVisualStabilityManager.onReorderingFinished();
250 // clear the map again for the next usage
251 mTmpChildOrderMap.clear();
252
Ned Burnsd4a69f72019-06-19 19:49:19 -0400253 updateRowStatesInternal();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900254
255 mListContainer.onNotificationViewUpdateFinished();
Ned Burnsd4a69f72019-06-19 19:49:19 -0400256
257 endUpdate();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900258 }
259
260 private void addNotificationChildrenAndSort() {
261 // Let's now add all notification children which are missing
262 boolean orderChanged = false;
263 for (int i = 0; i < mListContainer.getContainerChildCount(); i++) {
264 View view = mListContainer.getContainerChildAt(i);
265 if (!(view instanceof ExpandableNotificationRow)) {
266 // We don't care about non-notification views.
267 continue;
268 }
269
270 ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
271 List<ExpandableNotificationRow> children = parent.getNotificationChildren();
272 List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent);
273
274 for (int childIndex = 0; orderedChildren != null && childIndex < orderedChildren.size();
275 childIndex++) {
276 ExpandableNotificationRow childView = orderedChildren.get(childIndex);
277 if (children == null || !children.contains(childView)) {
278 if (childView.getParent() != null) {
279 Log.wtf(TAG, "trying to add a notification child that already has " +
280 "a parent. class:" + childView.getParent().getClass() +
281 "\n child: " + childView);
282 // This shouldn't happen. We can recover by removing it though.
283 ((ViewGroup) childView.getParent()).removeView(childView);
284 }
285 mVisualStabilityManager.notifyViewAddition(childView);
286 parent.addChildNotification(childView, childIndex);
287 mListContainer.notifyGroupChildAdded(childView);
288 }
289 }
290
291 // Finally after removing and adding has been performed we can apply the order.
292 orderChanged |= parent.applyChildOrder(orderedChildren, mVisualStabilityManager,
293 mEntryManager);
294 }
295 if (orderChanged) {
296 mListContainer.generateChildOrderChangedEvent();
297 }
298 }
299
300 private void removeNotificationChildren() {
301 // First let's remove all children which don't belong in the parents
302 ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>();
303 for (int i = 0; i < mListContainer.getContainerChildCount(); i++) {
304 View view = mListContainer.getContainerChildAt(i);
305 if (!(view instanceof ExpandableNotificationRow)) {
306 // We don't care about non-notification views.
307 continue;
308 }
309
310 ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
311 List<ExpandableNotificationRow> children = parent.getNotificationChildren();
312 List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent);
313
314 if (children != null) {
315 toRemove.clear();
316 for (ExpandableNotificationRow childRow : children) {
317 if ((orderedChildren == null
318 || !orderedChildren.contains(childRow))
319 && !childRow.keepInParent()) {
320 toRemove.add(childRow);
321 }
322 }
323 for (ExpandableNotificationRow remove : toRemove) {
324 parent.removeChildNotification(remove);
325 if (mEntryManager.getNotificationData().get(
326 remove.getStatusBarNotification().getKey()) == null) {
327 // We only want to add an animation if the view is completely removed
328 // otherwise it's just a transfer
329 mListContainer.notifyGroupChildRemoved(remove,
330 parent.getChildrenContainer());
331 }
332 }
333 }
334 }
335 }
336
337 /**
338 * Updates expanded, dimmed and locked states of notification rows.
339 */
340 public void updateRowStates() {
Ned Burnsd4a69f72019-06-19 19:49:19 -0400341 Assert.isMainThread();
342 beginUpdate();
343 updateRowStatesInternal();
344 endUpdate();
345 }
346
347 private void updateRowStatesInternal() {
Lucas Dupin16013822018-05-17 18:00:16 -0700348 Trace.beginSection("NotificationViewHierarchyManager#updateRowStates");
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900349 final int N = mListContainer.getContainerChildCount();
350
351 int visibleNotifications = 0;
Jason Monk297c04e2018-08-23 17:16:59 -0400352 boolean onKeyguard = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900353 int maxNotifications = -1;
Jason Monk297c04e2018-08-23 17:16:59 -0400354 if (onKeyguard) {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900355 maxNotifications = mPresenter.getMaxNotificationsWhileLocked(true /* recompute */);
356 }
357 mListContainer.setMaxDisplayedNotifications(maxNotifications);
358 Stack<ExpandableNotificationRow> stack = new Stack<>();
359 for (int i = N - 1; i >= 0; i--) {
360 View child = mListContainer.getContainerChildAt(i);
361 if (!(child instanceof ExpandableNotificationRow)) {
362 continue;
363 }
364 stack.push((ExpandableNotificationRow) child);
365 }
366 while(!stack.isEmpty()) {
367 ExpandableNotificationRow row = stack.pop();
Ned Burnsf81c4c42019-01-07 14:10:43 -0500368 NotificationEntry entry = row.getEntry();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900369 boolean isChildNotification =
370 mGroupManager.isChildInGroupWithSummary(entry.notification);
371
Jason Monk297c04e2018-08-23 17:16:59 -0400372 row.setOnKeyguard(onKeyguard);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900373
Jason Monk297c04e2018-08-23 17:16:59 -0400374 if (!onKeyguard) {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900375 // If mAlwaysExpandNonGroupedNotification is false, then only expand the
376 // very first notification and if it's not a child of grouped notifications.
377 row.setSystemExpanded(mAlwaysExpandNonGroupedNotification
378 || (visibleNotifications == 0 && !isChildNotification
379 && !row.isLowPriority()));
380 }
381
Jason Monk09f4d372018-12-20 15:30:54 -0500382 entry.getRow().setOnAmbient(mShadeController.get().isDozing());
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900383 int userId = entry.notification.getUserId();
384 boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
Evan Laird94492852018-10-25 13:43:01 -0400385 entry.notification) && !entry.isRowRemoved();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900386 boolean showOnKeyguard = mLockscreenUserManager.shouldShowOnKeyguard(entry
387 .notification);
Selim Cinek3bf2d202018-10-16 17:30:05 -0700388 if (!showOnKeyguard) {
389 // min priority notifications should show if their summary is showing
390 if (mGroupManager.isChildInGroupWithSummary(entry.notification)) {
Ned Burnsf81c4c42019-01-07 14:10:43 -0500391 NotificationEntry summary = mGroupManager.getLogicalGroupSummary(
Selim Cinek3bf2d202018-10-16 17:30:05 -0700392 entry.notification);
393 if (summary != null && mLockscreenUserManager.shouldShowOnKeyguard(
Evan Laird94492852018-10-25 13:43:01 -0400394 summary.notification)) {
Selim Cinek3bf2d202018-10-16 17:30:05 -0700395 showOnKeyguard = true;
396 }
397 }
398 }
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900399 if (suppressedSummary
Pavel Grafov65152632018-03-26 15:14:45 +0100400 || mLockscreenUserManager.shouldHideNotifications(userId)
Jason Monk297c04e2018-08-23 17:16:59 -0400401 || (onKeyguard && !showOnKeyguard)) {
Evan Laird94492852018-10-25 13:43:01 -0400402 entry.getRow().setVisibility(View.GONE);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900403 } else {
Evan Laird94492852018-10-25 13:43:01 -0400404 boolean wasGone = entry.getRow().getVisibility() == View.GONE;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900405 if (wasGone) {
Evan Laird94492852018-10-25 13:43:01 -0400406 entry.getRow().setVisibility(View.VISIBLE);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900407 }
Evan Laird94492852018-10-25 13:43:01 -0400408 if (!isChildNotification && !entry.getRow().isRemoved()) {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900409 if (wasGone) {
410 // notify the scroller of a child addition
Evan Laird94492852018-10-25 13:43:01 -0400411 mListContainer.generateAddAnimation(entry.getRow(),
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900412 !showOnKeyguard /* fromMoreCard */);
413 }
414 visibleNotifications++;
415 }
416 }
417 if (row.isSummaryWithChildren()) {
418 List<ExpandableNotificationRow> notificationChildren =
419 row.getNotificationChildren();
420 int size = notificationChildren.size();
421 for (int i = size - 1; i >= 0; i--) {
422 stack.push(notificationChildren.get(i));
423 }
424 }
Dan Sandler83b70a02018-01-24 23:20:18 -0500425
Julia Reynoldsfc640012018-02-21 12:25:27 -0500426 row.showAppOpsIcons(entry.mActiveAppOps);
Gus Prevas7306b902018-12-11 10:57:06 -0500427 row.setLastAudiblyAlertedMs(entry.lastAudiblyAlertedMs);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900428 }
429
Lucas Dupin16013822018-05-17 18:00:16 -0700430 Trace.beginSection("NotificationPresenter#onUpdateRowStates");
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900431 mPresenter.onUpdateRowStates();
Lucas Dupin16013822018-05-17 18:00:16 -0700432 Trace.endSection();
433 Trace.endSection();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900434 }
Selim Cinek6f0a62a2019-04-09 18:40:12 -0700435
436 @Override
437 public void onDynamicPrivacyChanged() {
438 updateNotificationViews();
439 }
Ned Burnsd4a69f72019-06-19 19:49:19 -0400440
441 private void beginUpdate() {
442 if (mPerformingUpdate) {
443 throw new IllegalStateException("Re-entrant code during update.");
444 }
445 mPerformingUpdate = true;
446 }
447
448 private void endUpdate() {
449 if (!mPerformingUpdate) {
450 throw new IllegalStateException("Manager state has become desynced.");
451 }
452 mPerformingUpdate = false;
453 }
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900454}