blob: d47700b6f3e07785be8857091d5470442a949281 [file] [log] [blame]
Eliot Courtney3985ad52017-11-17 16:51:52 +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
Rohan Shah20790b82018-07-02 17:21:04 -070014 * limitations under the License
Eliot Courtney3985ad52017-11-17 16:51:52 +090015 */
16
Rohan Shah20790b82018-07-02 17:21:04 -070017package com.android.systemui.statusbar.notification.logging;
Eliot Courtney3985ad52017-11-17 16:51:52 +090018
Chris Wren2e89e8d2018-05-17 18:55:42 -040019import static org.junit.Assert.assertArrayEquals;
Eliot Courtney3985ad52017-11-17 16:51:52 +090020import static org.mockito.ArgumentMatchers.any;
Chris Wren2e89e8d2018-05-17 18:55:42 -040021import static org.mockito.Mockito.doAnswer;
Jason Monkd97204c2018-12-21 15:49:04 -050022import static org.mockito.Mockito.mock;
Eliot Courtney3985ad52017-11-17 16:51:52 +090023import static org.mockito.Mockito.never;
24import static org.mockito.Mockito.times;
25import static org.mockito.Mockito.verify;
26import static org.mockito.Mockito.when;
27
28import android.app.Notification;
29import android.os.Handler;
30import android.os.Looper;
31import android.os.UserHandle;
Eliot Courtney3985ad52017-11-17 16:51:52 +090032import android.service.notification.StatusBarNotification;
33import android.support.test.filters.SmallTest;
34import android.testing.AndroidTestingRunner;
35import android.testing.TestableLooper;
36
37import com.android.internal.statusbar.IStatusBarService;
38import com.android.internal.statusbar.NotificationVisibility;
Jason Monkd97204c2018-12-21 15:49:04 -050039import com.android.systemui.Dependency;
Eliot Courtney3985ad52017-11-17 16:51:52 +090040import com.android.systemui.SysuiTestCase;
Jason Monkd97204c2018-12-21 15:49:04 -050041import com.android.systemui.UiOffloadThread;
Rohan Shah20790b82018-07-02 17:21:04 -070042import com.android.systemui.statusbar.NotificationListener;
Beverly8fdb5332019-02-04 14:29:49 -050043import com.android.systemui.statusbar.StatusBarStateControllerImpl;
Ned Burns761af0d2019-01-03 13:51:29 -050044import com.android.systemui.statusbar.notification.NotificationEntryListener;
Jason Monka716bac2018-12-05 15:48:21 -050045import com.android.systemui.statusbar.notification.NotificationEntryManager;
Ned Burnsf81c4c42019-01-07 14:10:43 -050046import com.android.systemui.statusbar.notification.collection.NotificationData;
47import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Rohan Shah20790b82018-07-02 17:21:04 -070048import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
49import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
Jason Monka716bac2018-12-05 15:48:21 -050050
Eliot Courtney3985ad52017-11-17 16:51:52 +090051import com.google.android.collect.Lists;
52
53import org.junit.Before;
54import org.junit.Test;
55import org.junit.runner.RunWith;
Ned Burns761af0d2019-01-03 13:51:29 -050056import org.mockito.ArgumentCaptor;
57import org.mockito.Captor;
Eliot Courtney3985ad52017-11-17 16:51:52 +090058import org.mockito.Mock;
59import org.mockito.Mockito;
60import org.mockito.MockitoAnnotations;
Chris Wren2e89e8d2018-05-17 18:55:42 -040061
62import java.util.concurrent.ConcurrentLinkedQueue;
Eliot Courtney3985ad52017-11-17 16:51:52 +090063
64@SmallTest
65@RunWith(AndroidTestingRunner.class)
Jason Monka716bac2018-12-05 15:48:21 -050066@TestableLooper.RunWithLooper
Eliot Courtney3985ad52017-11-17 16:51:52 +090067public class NotificationLoggerTest extends SysuiTestCase {
68 private static final String TEST_PACKAGE_NAME = "test";
69 private static final int TEST_UID = 0;
70
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090071 @Mock private NotificationListContainer mListContainer;
Eliot Courtney3985ad52017-11-17 16:51:52 +090072 @Mock private IStatusBarService mBarService;
73 @Mock private NotificationData mNotificationData;
74 @Mock private ExpandableNotificationRow mRow;
Tony Mak202f25d2019-01-07 14:40:39 +000075 @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
Eliot Courtney3985ad52017-11-17 16:51:52 +090076
Eliot Courtney8f56b0e2017-12-14 18:54:28 +090077 // Dependency mocks:
78 @Mock private NotificationEntryManager mEntryManager;
79 @Mock private NotificationListener mListener;
Ned Burns761af0d2019-01-03 13:51:29 -050080 @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
Eliot Courtney8f56b0e2017-12-14 18:54:28 +090081
Ned Burnsf81c4c42019-01-07 14:10:43 -050082 private NotificationEntry mEntry;
Eliot Courtney3985ad52017-11-17 16:51:52 +090083 private TestableNotificationLogger mLogger;
Ned Burns761af0d2019-01-03 13:51:29 -050084 private NotificationEntryListener mNotificationEntryListener;
Chris Wren2e89e8d2018-05-17 18:55:42 -040085 private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
Eliot Courtney3985ad52017-11-17 16:51:52 +090086
87 @Before
Gus Prevasca1b6f72018-12-28 10:53:11 -050088 public void setUp() {
Eliot Courtney3985ad52017-11-17 16:51:52 +090089 MockitoAnnotations.initMocks(this);
Eliot Courtney8f56b0e2017-12-14 18:54:28 +090090 mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
91 mDependency.injectTestDependency(NotificationListener.class, mListener);
Eliot Courtney3985ad52017-11-17 16:51:52 +090092
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090093 when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
Eliot Courtney3985ad52017-11-17 16:51:52 +090094
Gus Prevasca1b6f72018-12-28 10:53:11 -050095 StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
96 0, null, TEST_UID,
Eliot Courtney3985ad52017-11-17 16:51:52 +090097 0, new Notification(), UserHandle.CURRENT, null, 0);
Ned Burnsf81c4c42019-01-07 14:10:43 -050098 mEntry = new NotificationEntry(sbn);
Evan Laird94492852018-10-25 13:43:01 -040099 mEntry.setRow(mRow);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900100
Jason Monkd97204c2018-12-21 15:49:04 -0500101 mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
Beverly8fdb5332019-02-04 14:29:49 -0500102 mEntryManager, mock(StatusBarStateControllerImpl.class), mBarService,
Tony Mak202f25d2019-01-07 14:40:39 +0000103 mExpansionStateLogger);
Jason Monk297c04e2018-08-23 17:16:59 -0400104 mLogger.setUpWithContainer(mListContainer);
Ned Burns761af0d2019-01-03 13:51:29 -0500105 verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
106 mNotificationEntryListener = mEntryListenerCaptor.getValue();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900107 }
108
109 @Test
110 public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception {
Chris Wren2e89e8d2018-05-17 18:55:42 -0400111 NotificationVisibility[] newlyVisibleKeys = {
112 NotificationVisibility.obtain(mEntry.key, 0, 1, true)
113 };
114 NotificationVisibility[] noLongerVisibleKeys = {};
Gus Prevasca1b6f72018-12-28 10:53:11 -0500115 doAnswer(invocation -> {
Chris Wren2e89e8d2018-05-17 18:55:42 -0400116 try {
117 assertArrayEquals(newlyVisibleKeys,
118 (NotificationVisibility[]) invocation.getArguments()[0]);
119 assertArrayEquals(noLongerVisibleKeys,
120 (NotificationVisibility[]) invocation.getArguments()[1]);
121 } catch (AssertionError error) {
122 mErrorQueue.offer(error);
123 }
124 return null;
125 }
126 ).when(mBarService).onNotificationVisibilityChanged(any(NotificationVisibility[].class),
127 any(NotificationVisibility[].class));
128
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900129 when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900130 when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900131 mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
Jason Monk6dceace2018-05-15 20:24:07 -0400132 TestableLooper.get(this).processAllMessages();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900133 waitForUiOffloadThread();
134
Chris Wren2e89e8d2018-05-17 18:55:42 -0400135 if(!mErrorQueue.isEmpty()) {
136 throw mErrorQueue.poll();
137 }
Eliot Courtney3985ad52017-11-17 16:51:52 +0900138
139 // |mEntry| won't change visibility, so it shouldn't be reported again:
140 Mockito.reset(mBarService);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900141 mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
Jason Monk6dceace2018-05-15 20:24:07 -0400142 TestableLooper.get(this).processAllMessages();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900143 waitForUiOffloadThread();
144
145 verify(mBarService, never()).onNotificationVisibilityChanged(any(), any());
146 }
147
148 @Test
149 public void testStoppingNotificationLoggingReportsCurrentNotifications()
150 throws Exception {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900151 when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900152 when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900153 mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
Jason Monk6dceace2018-05-15 20:24:07 -0400154 TestableLooper.get(this).processAllMessages();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900155 waitForUiOffloadThread();
156 Mockito.reset(mBarService);
157
158 mLogger.stopNotificationLogging();
159 waitForUiOffloadThread();
160 // The visibility objects are recycled by NotificationLogger, so we can't use specific
161 // matchers here.
162 verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
163 }
164
165 private class TestableNotificationLogger extends NotificationLogger {
166
Gus Prevasca1b6f72018-12-28 10:53:11 -0500167 TestableNotificationLogger(NotificationListener notificationListener,
Jason Monkd97204c2018-12-21 15:49:04 -0500168 UiOffloadThread uiOffloadThread,
169 NotificationEntryManager entryManager,
Beverly8fdb5332019-02-04 14:29:49 -0500170 StatusBarStateControllerImpl statusBarStateController,
Tony Mak202f25d2019-01-07 14:40:39 +0000171 IStatusBarService barService,
172 ExpansionStateLogger expansionStateLogger) {
173 super(notificationListener, uiOffloadThread, entryManager, statusBarStateController,
174 expansionStateLogger);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900175 mBarService = barService;
Jason Monk6dceace2018-05-15 20:24:07 -0400176 // Make this on the current thread so we can wait for it during tests.
177 mHandler = Handler.createAsync(Looper.myLooper());
Eliot Courtney3985ad52017-11-17 16:51:52 +0900178 }
179
Gus Prevasca1b6f72018-12-28 10:53:11 -0500180 OnChildLocationsChangedListener
Eliot Courtney3985ad52017-11-17 16:51:52 +0900181 getChildLocationsChangedListenerForTest() {
182 return mNotificationLocationsChangedListener;
183 }
Eliot Courtney3985ad52017-11-17 16:51:52 +0900184 }
185}