1 /*
2  * Copyright (C) 2020 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 
17 package com.android.systemui.statusbar.notification.collection.coordinator;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static junit.framework.Assert.assertFalse;
22 
23 import static org.junit.Assert.assertTrue;
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.ArgumentMatchers.eq;
26 import static org.mockito.Mockito.doAnswer;
27 import static org.mockito.Mockito.never;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31 
32 import android.testing.AndroidTestingRunner;
33 import android.testing.TestableLooper;
34 
35 import androidx.test.filters.SmallTest;
36 
37 import com.android.systemui.SysuiTestCase;
38 import com.android.systemui.dump.DumpManager;
39 import com.android.systemui.keyguard.WakefulnessLifecycle;
40 import com.android.systemui.plugins.statusbar.StatusBarStateController;
41 import com.android.systemui.shade.ShadeStateEvents;
42 import com.android.systemui.shade.ShadeStateEvents.ShadeStateEventsListener;
43 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
44 import com.android.systemui.statusbar.notification.collection.GroupEntry;
45 import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
46 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
47 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
48 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
49 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
50 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
51 import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
52 import com.android.systemui.statusbar.policy.HeadsUpManager;
53 import com.android.systemui.util.concurrency.FakeExecutor;
54 import com.android.systemui.util.time.FakeSystemClock;
55 
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.junit.runner.RunWith;
59 import org.mockito.ArgumentCaptor;
60 import org.mockito.Captor;
61 import org.mockito.Mock;
62 import org.mockito.MockitoAnnotations;
63 import org.mockito.verification.VerificationMode;
64 
65 @SmallTest
66 @RunWith(AndroidTestingRunner.class)
67 @TestableLooper.RunWithLooper
68 public class VisualStabilityCoordinatorTest extends SysuiTestCase {
69 
70     private VisualStabilityCoordinator mCoordinator;
71 
72     @Mock private DumpManager mDumpManager;
73     @Mock private NotifPipeline mNotifPipeline;
74     @Mock private WakefulnessLifecycle mWakefulnessLifecycle;
75     @Mock private StatusBarStateController mStatusBarStateController;
76     @Mock private Pluggable.PluggableListener<NotifStabilityManager> mInvalidateListener;
77     @Mock private HeadsUpManager mHeadsUpManager;
78     @Mock private ShadeStateEvents mShadeStateEvents;
79     @Mock private VisibilityLocationProvider mVisibilityLocationProvider;
80     @Mock private VisualStabilityProvider mVisualStabilityProvider;
81 
82     @Captor private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefulnessObserverCaptor;
83     @Captor private ArgumentCaptor<StatusBarStateController.StateListener> mSBStateListenerCaptor;
84     @Captor private ArgumentCaptor<ShadeStateEventsListener> mNotifPanelEventsCallbackCaptor;
85     @Captor private ArgumentCaptor<NotifStabilityManager> mNotifStabilityManagerCaptor;
86 
87     private FakeSystemClock mFakeSystemClock = new FakeSystemClock();
88     private FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock);
89 
90     private WakefulnessLifecycle.Observer mWakefulnessObserver;
91     private StatusBarStateController.StateListener mStatusBarStateListener;
92     private ShadeStateEvents.ShadeStateEventsListener mNotifPanelEventsCallback;
93     private NotifStabilityManager mNotifStabilityManager;
94     private NotificationEntry mEntry;
95     private GroupEntry mGroupEntry;
96 
97     @Before
setUp()98     public void setUp() {
99         MockitoAnnotations.initMocks(this);
100 
101         mCoordinator = new VisualStabilityCoordinator(
102                 mFakeExecutor,
103                 mDumpManager,
104                 mHeadsUpManager,
105                 mShadeStateEvents,
106                 mStatusBarStateController,
107                 mVisibilityLocationProvider,
108                 mVisualStabilityProvider,
109                 mWakefulnessLifecycle);
110 
111         mCoordinator.attach(mNotifPipeline);
112 
113         // capture arguments:
114         verify(mWakefulnessLifecycle).addObserver(mWakefulnessObserverCaptor.capture());
115         mWakefulnessObserver = mWakefulnessObserverCaptor.getValue();
116 
117         verify(mStatusBarStateController).addCallback(mSBStateListenerCaptor.capture());
118         mStatusBarStateListener = mSBStateListenerCaptor.getValue();
119 
120         verify(mShadeStateEvents).addShadeStateEventsListener(
121                 mNotifPanelEventsCallbackCaptor.capture());
122         mNotifPanelEventsCallback = mNotifPanelEventsCallbackCaptor.getValue();
123 
124         verify(mNotifPipeline).setVisualStabilityManager(mNotifStabilityManagerCaptor.capture());
125         mNotifStabilityManager = mNotifStabilityManagerCaptor.getValue();
126         mNotifStabilityManager.setInvalidationListener(mInvalidateListener);
127 
128         mEntry = new NotificationEntryBuilder()
129                 .setPkg("testPkg1")
130                 .build();
131 
132         mGroupEntry = new GroupEntryBuilder()
133                 .setSummary(mEntry)
134                 .build();
135 
136         when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(false);
137 
138         // Whenever we invalidate, the pipeline runs again, so we invalidate the state
139         doAnswer(i -> {
140             mNotifStabilityManager.onBeginRun();
141             return null;
142         }).when(mInvalidateListener).onPluggableInvalidated(eq(mNotifStabilityManager), any());
143     }
144 
145     @Test
testScreenOff_groupAndSectionChangesAllowed()146     public void testScreenOff_groupAndSectionChangesAllowed() {
147         // GIVEN screen is off, panel isn't expanded and device isn't pulsing
148         setFullyDozed(true);
149         setSleepy(true);
150         setPanelExpanded(false);
151         setPulsing(false);
152 
153         // THEN group changes are allowed
154         assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
155         assertTrue(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
156 
157         // THEN section changes are allowed
158         assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
159     }
160 
161     @Test
testScreenTurningOff_groupAndSectionChangesNotAllowed()162     public void testScreenTurningOff_groupAndSectionChangesNotAllowed() {
163         // GIVEN the screen is turning off (sleepy but partially dozed)
164         setFullyDozed(false);
165         setSleepy(true);
166         setPanelExpanded(true);
167         setPulsing(false);
168 
169         // THEN group changes are NOT allowed
170         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
171         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
172 
173         // THEN section changes are NOT allowed
174         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
175     }
176 
177     @Test
testScreenTurningOn_groupAndSectionChangesNotAllowed()178     public void testScreenTurningOn_groupAndSectionChangesNotAllowed() {
179         // GIVEN the screen is turning on (still fully dozed, not sleepy)
180         setFullyDozed(true);
181         setSleepy(false);
182         setPanelExpanded(true);
183         setPulsing(false);
184 
185         // THEN group changes are NOT allowed
186         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
187         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
188 
189         // THEN section changes are NOT allowed
190         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
191     }
192 
193     @Test
testPanelNotExpanded_groupAndSectionChangesAllowed()194     public void testPanelNotExpanded_groupAndSectionChangesAllowed() {
195         // GIVEN screen is on but the panel isn't expanded and device isn't pulsing
196         setFullyDozed(false);
197         setSleepy(false);
198         setPanelExpanded(false);
199         setPulsing(false);
200 
201         // THEN group changes are allowed
202         assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
203         assertTrue(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
204 
205         // THEN section changes are allowed
206         assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
207     }
208 
209     @Test
testPanelExpanded_groupAndSectionChangesNotAllowed()210     public void testPanelExpanded_groupAndSectionChangesNotAllowed() {
211         // GIVEN the panel true expanded and device isn't pulsing
212         setFullyDozed(false);
213         setSleepy(false);
214         setPanelExpanded(true);
215         setPulsing(false);
216 
217         // THEN group changes are NOT allowed
218         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
219         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
220 
221         // THEN section changes are NOT allowed
222         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
223     }
224 
225     @Test
testPulsing_screenOff_groupAndSectionChangesNotAllowed()226     public void testPulsing_screenOff_groupAndSectionChangesNotAllowed() {
227         // GIVEN the device is pulsing and screen is off
228         setFullyDozed(true);
229         setSleepy(true);
230         setPulsing(true);
231 
232         // THEN group changes are NOT allowed
233         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
234         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
235 
236         // THEN section changes are NOT allowed
237         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
238     }
239 
240     @Test
testPulsing_panelNotExpanded_groupAndSectionChangesNotAllowed()241     public void testPulsing_panelNotExpanded_groupAndSectionChangesNotAllowed() {
242         // GIVEN the device is pulsing and screen is off with the panel not expanded
243         setFullyDozed(true);
244         setSleepy(true);
245         setPanelExpanded(false);
246         setPulsing(true);
247 
248         // THEN group changes are NOT allowed
249         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
250         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
251 
252         // THEN section changes are NOT allowed
253         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
254     }
255 
256     @Test
testOverrideReorderingSuppression_onlySectionChangesAllowed()257     public void testOverrideReorderingSuppression_onlySectionChangesAllowed() {
258         // GIVEN section changes typically wouldn't be allowed because the panel is expanded and
259         // we're not pulsing
260         setFullyDozed(false);
261         setSleepy(false);
262         setPanelExpanded(true);
263         setPulsing(true);
264 
265         // WHEN we temporarily allow section changes for this notification entry
266         mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis());
267 
268         // THEN group changes aren't allowed
269         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
270         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
271 
272         // THEN section changes are allowed for this notification but not other notifications
273         assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
274         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(
275                 new NotificationEntryBuilder()
276                         .setPkg("testPkg2")
277                         .build()));
278     }
279 
280     @Test
testTemporarilyAllowSectionChanges_callsInvalidate()281     public void testTemporarilyAllowSectionChanges_callsInvalidate() {
282         // GIVEN section changes typically wouldn't be allowed because the panel is expanded
283         setFullyDozed(false);
284         setSleepy(false);
285         setPanelExpanded(true);
286         setPulsing(false);
287 
288         // WHEN we temporarily allow section changes for this notification entry
289         mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.uptimeMillis());
290 
291         // THEN the notification list is invalidated
292         verifyStabilityManagerWasInvalidated(times(1));
293     }
294 
295     @Test
testTemporarilyAllowSectionChanges_noInvalidationCalled()296     public void testTemporarilyAllowSectionChanges_noInvalidationCalled() {
297         // GIVEN section changes typically WOULD be allowed
298         setFullyDozed(true);
299         setSleepy(true);
300         setPanelExpanded(false);
301         setPulsing(false);
302 
303         // WHEN we temporarily allow section changes for this notification entry
304         mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis());
305 
306         // THEN invalidate is not called because this entry was never suppressed from reordering
307         verifyStabilityManagerWasInvalidated(never());
308     }
309 
310     @Test
testTemporarilyAllowSectionChangesTimeout()311     public void testTemporarilyAllowSectionChangesTimeout() {
312         // GIVEN section changes typically WOULD be allowed
313         setFullyDozed(true);
314         setSleepy(true);
315         setPanelExpanded(false);
316         setPulsing(false);
317         assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
318 
319         // WHEN we temporarily allow section changes for this notification entry
320         mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis());
321 
322         // THEN invalidate is not called because this entry was never suppressed from reordering;
323         // THEN section changes are allowed for this notification
324         verifyStabilityManagerWasInvalidated(never());
325         assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
326 
327         // WHEN we're pulsing (now disallowing reordering)
328         setPulsing(true);
329 
330         // THEN we're still allowed to reorder this section because it's still in the list of
331         // notifications to allow section changes
332         assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
333 
334         // WHEN the timeout for the temporarily allow section reordering runnable is finsihed
335         mFakeExecutor.advanceClockToNext();
336         mFakeExecutor.runNextReady();
337 
338         // THEN section changes aren't allowed anymore
339         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
340     }
341 
342     @Test
testTemporarilyAllowSectionChanges_isPulsingChangeBeforeTimeout()343     public void testTemporarilyAllowSectionChanges_isPulsingChangeBeforeTimeout() {
344         // GIVEN section changes typically wouldn't be allowed because the device is pulsing
345         setFullyDozed(true);
346         setSleepy(true);
347         setPanelExpanded(false);
348         setPulsing(true);
349 
350         // WHEN we temporarily allow section changes for this notification entry
351         mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis());
352         // can now reorder, so invalidates
353         verifyStabilityManagerWasInvalidated(times(1));
354 
355         // WHEN reordering is now allowed because device isn't pulsing anymore
356         setPulsing(false);
357 
358         // THEN invalidate isn't called a second time since reordering was already allowed
359         verifyStabilityManagerWasInvalidated(times(1));
360     }
361 
362     @Test
testMovingVisibleHeadsUpNotAllowed()363     public void testMovingVisibleHeadsUpNotAllowed() {
364         // GIVEN stability enforcing conditions
365         setPanelExpanded(true);
366         setSleepy(false);
367 
368         // WHEN a notification is alerting and visible
369         when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(true);
370         when(mVisibilityLocationProvider.isInVisibleLocation(any(NotificationEntry.class)))
371                 .thenReturn(true);
372 
373         // VERIFY the notification cannot be reordered
374         assertThat(mNotifStabilityManager.isEntryReorderingAllowed(mEntry)).isFalse();
375         assertThat(mNotifStabilityManager.isSectionChangeAllowed(mEntry)).isFalse();
376     }
377 
378     @Test
testMovingInvisibleHeadsUpAllowed()379     public void testMovingInvisibleHeadsUpAllowed() {
380         // GIVEN stability enforcing conditions
381         setPanelExpanded(true);
382         setSleepy(false);
383 
384         // WHEN a notification is alerting but not visible
385         when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(true);
386         when(mVisibilityLocationProvider.isInVisibleLocation(any(NotificationEntry.class)))
387                 .thenReturn(false);
388 
389         // VERIFY the notification can be reordered
390         assertThat(mNotifStabilityManager.isEntryReorderingAllowed(mEntry)).isTrue();
391         assertThat(mNotifStabilityManager.isSectionChangeAllowed(mEntry)).isTrue();
392     }
393 
394     @Test
testNeverSuppressedChanges_noInvalidationCalled()395     public void testNeverSuppressedChanges_noInvalidationCalled() {
396         // GIVEN no notifications are currently being suppressed from grouping nor being sorted
397 
398         // WHEN device isn't pulsing anymore
399         setPulsing(false);
400 
401         // WHEN fully dozed
402         setFullyDozed(true);
403 
404         // WHEN sleepy
405         setSleepy(true);
406 
407         // WHEN panel isn't expanded
408         setPanelExpanded(false);
409 
410         // THEN we never see any calls to invalidate since there weren't any notifications that
411         // were being suppressed from grouping or section changes
412         verifyStabilityManagerWasInvalidated(never());
413     }
414 
415     @Test
testNotSuppressingGroupChangesAnymore_invalidationCalled()416     public void testNotSuppressingGroupChangesAnymore_invalidationCalled() {
417         // GIVEN visual stability is being maintained b/c panel is expanded
418         setPulsing(false);
419         setFullyDozed(false);
420         setSleepy(false);
421         setPanelExpanded(true);
422 
423         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
424         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
425 
426         // WHEN the panel isn't expanded anymore
427         setPanelExpanded(false);
428 
429         //  invalidate is called because we were previously suppressing a group change
430         verifyStabilityManagerWasInvalidated(times(1));
431     }
432 
433     @Test
testNotLaunchingActivityAnymore_invalidationCalled()434     public void testNotLaunchingActivityAnymore_invalidationCalled() {
435         // GIVEN visual stability is being maintained b/c animation is playing
436         setActivityLaunching(true);
437 
438         assertFalse(mNotifStabilityManager.isPipelineRunAllowed());
439 
440         // WHEN the animation has stopped playing
441         setActivityLaunching(false);
442 
443         // invalidate is called, b/c we were previously suppressing the pipeline from running
444         verifyStabilityManagerWasInvalidated(times(1));
445     }
446 
447     @Test
testNotCollapsingPanelAnymore_invalidationCalled()448     public void testNotCollapsingPanelAnymore_invalidationCalled() {
449         // GIVEN visual stability is being maintained b/c animation is playing
450         setPanelCollapsing(true);
451 
452         assertFalse(mNotifStabilityManager.isPipelineRunAllowed());
453 
454         // WHEN the animation has stopped playing
455         setPanelCollapsing(false);
456 
457         // invalidate is called, b/c we were previously suppressing the pipeline from running
458         verifyStabilityManagerWasInvalidated(times(1));
459     }
460 
461     @Test
testNeverSuppressPipelineRunFromPanelCollapse_noInvalidationCalled()462     public void testNeverSuppressPipelineRunFromPanelCollapse_noInvalidationCalled() {
463         // GIVEN animation is playing
464         setPanelCollapsing(true);
465 
466         // WHEN the animation has stopped playing
467         setPanelCollapsing(false);
468 
469         // THEN invalidate is not called, b/c nothing has been suppressed
470         verifyStabilityManagerWasInvalidated(never());
471     }
472 
473     @Test
testNeverSuppressPipelineRunFromLaunchActivity_noInvalidationCalled()474     public void testNeverSuppressPipelineRunFromLaunchActivity_noInvalidationCalled() {
475         // GIVEN animation is playing
476         setActivityLaunching(true);
477 
478         // WHEN the animation has stopped playing
479         setActivityLaunching(false);
480 
481         // THEN invalidate is not called, b/c nothing has been suppressed
482         verifyStabilityManagerWasInvalidated(never());
483     }
484 
485     @Test
testNotSuppressingEntryReorderingAnymoreWillInvalidate()486     public void testNotSuppressingEntryReorderingAnymoreWillInvalidate() {
487         // GIVEN visual stability is being maintained b/c panel is expanded
488         setPulsing(false);
489         setFullyDozed(false);
490         setSleepy(false);
491         setPanelExpanded(true);
492 
493         assertFalse(mNotifStabilityManager.isEntryReorderingAllowed(mEntry));
494         // The pipeline still has to report back that entry reordering was suppressed
495         mNotifStabilityManager.onEntryReorderSuppressed();
496 
497         // WHEN the panel isn't expanded anymore
498         setPanelExpanded(false);
499 
500         //  invalidate is called because we were previously suppressing an entry reorder
501         verifyStabilityManagerWasInvalidated(times(1));
502     }
503 
504     @Test
testQueryingEntryReorderingButNotReportingReorderSuppressedDoesNotInvalidate()505     public void testQueryingEntryReorderingButNotReportingReorderSuppressedDoesNotInvalidate() {
506         // GIVEN visual stability is being maintained b/c panel is expanded
507         setPulsing(false);
508         setFullyDozed(false);
509         setSleepy(false);
510         setPanelExpanded(true);
511 
512         assertFalse(mNotifStabilityManager.isEntryReorderingAllowed(mEntry));
513 
514         // WHEN the panel isn't expanded anymore
515         setPanelExpanded(false);
516 
517         // invalidate is not called because we were not told that an entry reorder was suppressed
518         verifyStabilityManagerWasInvalidated(never());
519     }
520 
521     @Test
testHeadsUp_allowedToChangeGroupAndSection()522     public void testHeadsUp_allowedToChangeGroupAndSection() {
523         // GIVEN group + section changes disallowed
524         setFullyDozed(false);
525         setSleepy(false);
526         setPanelExpanded(true);
527         setPulsing(true);
528         assertFalse(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
529         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
530         assertFalse(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
531 
532         // GIVEN mEntry is a HUN
533         when(mHeadsUpManager.isAlerting(mEntry.getKey())).thenReturn(true);
534 
535         // THEN group + section changes are allowed
536         assertTrue(mNotifStabilityManager.isGroupChangeAllowed(mEntry));
537         assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
538 
539         // BUT pruning the group for which this is the summary would still NOT be allowed.
540         assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
541     }
542 
verifyStabilityManagerWasInvalidated(VerificationMode mode)543     private void verifyStabilityManagerWasInvalidated(VerificationMode mode) {
544         verify(mInvalidateListener, mode).onPluggableInvalidated(eq(mNotifStabilityManager), any());
545     }
546 
setActivityLaunching(boolean activityLaunching)547     private void setActivityLaunching(boolean activityLaunching) {
548         mNotifPanelEventsCallback.onLaunchingActivityChanged(activityLaunching);
549     }
550 
setPanelCollapsing(boolean collapsing)551     private void setPanelCollapsing(boolean collapsing) {
552         mNotifPanelEventsCallback.onPanelCollapsingChanged(collapsing);
553     }
554 
setPulsing(boolean pulsing)555     private void setPulsing(boolean pulsing) {
556         mStatusBarStateListener.onPulsingChanged(pulsing);
557     }
558 
setFullyDozed(boolean fullyDozed)559     private void setFullyDozed(boolean fullyDozed) {
560         float dozeAmount = fullyDozed ? 1 : 0;
561         mStatusBarStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
562     }
563 
setSleepy(boolean sleepy)564     private void setSleepy(boolean sleepy) {
565         if (sleepy) {
566             mWakefulnessObserver.onFinishedGoingToSleep();
567         } else {
568             mWakefulnessObserver.onStartedWakingUp();
569         }
570     }
571 
setPanelExpanded(boolean expanded)572     private void setPanelExpanded(boolean expanded) {
573         mStatusBarStateListener.onExpandedChanged(expanded);
574     }
575 
576 }
577