blob: 64725896cce5abf5aeea03dd4cd4041618a7d075 [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;
Jason Monkd97204c2018-12-21 15:49:04 -050043import com.android.systemui.statusbar.StatusBarStateController;
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;
75
Eliot Courtney8f56b0e2017-12-14 18:54:28 +090076 // Dependency mocks:
77 @Mock private NotificationEntryManager mEntryManager;
78 @Mock private NotificationListener mListener;
Ned Burns761af0d2019-01-03 13:51:29 -050079 @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
Eliot Courtney8f56b0e2017-12-14 18:54:28 +090080
Ned Burnsf81c4c42019-01-07 14:10:43 -050081 private NotificationEntry mEntry;
Eliot Courtney3985ad52017-11-17 16:51:52 +090082 private TestableNotificationLogger mLogger;
Ned Burns761af0d2019-01-03 13:51:29 -050083 private NotificationEntryListener mNotificationEntryListener;
Chris Wren2e89e8d2018-05-17 18:55:42 -040084 private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
Eliot Courtney3985ad52017-11-17 16:51:52 +090085
86 @Before
Gus Prevasca1b6f72018-12-28 10:53:11 -050087 public void setUp() {
Eliot Courtney3985ad52017-11-17 16:51:52 +090088 MockitoAnnotations.initMocks(this);
Eliot Courtney8f56b0e2017-12-14 18:54:28 +090089 mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
90 mDependency.injectTestDependency(NotificationListener.class, mListener);
Eliot Courtney3985ad52017-11-17 16:51:52 +090091
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090092 when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
Eliot Courtney3985ad52017-11-17 16:51:52 +090093
Gus Prevasca1b6f72018-12-28 10:53:11 -050094 StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
95 0, null, TEST_UID,
Eliot Courtney3985ad52017-11-17 16:51:52 +090096 0, new Notification(), UserHandle.CURRENT, null, 0);
Ned Burnsf81c4c42019-01-07 14:10:43 -050097 mEntry = new NotificationEntry(sbn);
Evan Laird94492852018-10-25 13:43:01 -040098 mEntry.setRow(mRow);
Eliot Courtney3985ad52017-11-17 16:51:52 +090099
Jason Monkd97204c2018-12-21 15:49:04 -0500100 mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
101 mEntryManager, mock(StatusBarStateController.class), mBarService);
Jason Monk297c04e2018-08-23 17:16:59 -0400102 mLogger.setUpWithContainer(mListContainer);
Ned Burns761af0d2019-01-03 13:51:29 -0500103 verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
104 mNotificationEntryListener = mEntryListenerCaptor.getValue();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900105 }
106
107 @Test
108 public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception {
Chris Wren2e89e8d2018-05-17 18:55:42 -0400109 NotificationVisibility[] newlyVisibleKeys = {
110 NotificationVisibility.obtain(mEntry.key, 0, 1, true)
111 };
112 NotificationVisibility[] noLongerVisibleKeys = {};
Gus Prevasca1b6f72018-12-28 10:53:11 -0500113 doAnswer(invocation -> {
Chris Wren2e89e8d2018-05-17 18:55:42 -0400114 try {
115 assertArrayEquals(newlyVisibleKeys,
116 (NotificationVisibility[]) invocation.getArguments()[0]);
117 assertArrayEquals(noLongerVisibleKeys,
118 (NotificationVisibility[]) invocation.getArguments()[1]);
119 } catch (AssertionError error) {
120 mErrorQueue.offer(error);
121 }
122 return null;
123 }
124 ).when(mBarService).onNotificationVisibilityChanged(any(NotificationVisibility[].class),
125 any(NotificationVisibility[].class));
126
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900127 when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900128 when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900129 mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
Jason Monk6dceace2018-05-15 20:24:07 -0400130 TestableLooper.get(this).processAllMessages();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900131 waitForUiOffloadThread();
132
Chris Wren2e89e8d2018-05-17 18:55:42 -0400133 if(!mErrorQueue.isEmpty()) {
134 throw mErrorQueue.poll();
135 }
Eliot Courtney3985ad52017-11-17 16:51:52 +0900136
137 // |mEntry| won't change visibility, so it shouldn't be reported again:
138 Mockito.reset(mBarService);
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900139 mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
Jason Monk6dceace2018-05-15 20:24:07 -0400140 TestableLooper.get(this).processAllMessages();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900141 waitForUiOffloadThread();
142
143 verify(mBarService, never()).onNotificationVisibilityChanged(any(), any());
144 }
145
146 @Test
147 public void testStoppingNotificationLoggingReportsCurrentNotifications()
148 throws Exception {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900149 when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900150 when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry));
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900151 mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
Jason Monk6dceace2018-05-15 20:24:07 -0400152 TestableLooper.get(this).processAllMessages();
Eliot Courtney3985ad52017-11-17 16:51:52 +0900153 waitForUiOffloadThread();
154 Mockito.reset(mBarService);
155
156 mLogger.stopNotificationLogging();
157 waitForUiOffloadThread();
158 // The visibility objects are recycled by NotificationLogger, so we can't use specific
159 // matchers here.
160 verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
161 }
162
163 private class TestableNotificationLogger extends NotificationLogger {
164
Gus Prevasca1b6f72018-12-28 10:53:11 -0500165 TestableNotificationLogger(NotificationListener notificationListener,
Jason Monkd97204c2018-12-21 15:49:04 -0500166 UiOffloadThread uiOffloadThread,
167 NotificationEntryManager entryManager,
168 StatusBarStateController statusBarStateController,
169 IStatusBarService barService) {
170 super(notificationListener, uiOffloadThread, entryManager, statusBarStateController);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900171 mBarService = barService;
Jason Monk6dceace2018-05-15 20:24:07 -0400172 // Make this on the current thread so we can wait for it during tests.
173 mHandler = Handler.createAsync(Looper.myLooper());
Eliot Courtney3985ad52017-11-17 16:51:52 +0900174 }
175
Gus Prevasca1b6f72018-12-28 10:53:11 -0500176 OnChildLocationsChangedListener
Eliot Courtney3985ad52017-11-17 16:51:52 +0900177 getChildLocationsChangedListenerForTest() {
178 return mNotificationLocationsChangedListener;
179 }
Eliot Courtney3985ad52017-11-17 16:51:52 +0900180 }
181}