13985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney/* 23985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * Copyright (C) 2017 The Android Open Source Project 33985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * 43985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * Licensed under the Apache License, Version 2.0 (the "License"); 53985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * you may not use this file except in compliance with the License. 63985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * You may obtain a copy of the License at 73985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * 83985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * http://www.apache.org/licenses/LICENSE-2.0 93985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * 103985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * Unless required by applicable law or agreed to in writing, software 113985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * distributed under the License is distributed on an "AS IS" BASIS, 123985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * See the License for the specific language governing permissions and 143985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney * limitations under the License. 153985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney */ 163985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 173985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneypackage com.android.systemui.statusbar; 183985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 192e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wrenimport static org.junit.Assert.assertArrayEquals; 203985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport static org.mockito.ArgumentMatchers.any; 212e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wrenimport static org.mockito.Mockito.doAnswer; 223985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport static org.mockito.Mockito.never; 233985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport static org.mockito.Mockito.times; 243985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport static org.mockito.Mockito.verify; 253985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport static org.mockito.Mockito.when; 263985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 273985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.app.Notification; 283985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.os.Handler; 293985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.os.Looper; 302e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wrenimport android.os.RemoteException; 313985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.os.UserHandle; 323985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.service.notification.StatusBarNotification; 333985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.support.test.filters.SmallTest; 343985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.testing.AndroidTestingRunner; 353985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport android.testing.TestableLooper; 363985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 373985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport com.android.internal.statusbar.IStatusBarService; 383985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport com.android.internal.statusbar.NotificationVisibility; 393985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport com.android.systemui.SysuiTestCase; 403985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 413985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport com.google.android.collect.Lists; 423985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 433985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport org.junit.Before; 443985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport org.junit.Test; 453985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport org.junit.runner.RunWith; 463985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport org.mockito.Mock; 473985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport org.mockito.Mockito; 483985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneyimport org.mockito.MockitoAnnotations; 492e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wrenimport org.mockito.stubbing.Answer; 502e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren 512e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wrenimport java.util.concurrent.ConcurrentLinkedQueue; 523985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 533985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney@SmallTest 543985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney@RunWith(AndroidTestingRunner.class) 556dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk@TestableLooper.RunWithLooper(setAsMainLooper = true) 563985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtneypublic class NotificationLoggerTest extends SysuiTestCase { 573985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney private static final String TEST_PACKAGE_NAME = "test"; 583985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney private static final int TEST_UID = 0; 593985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 603985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney @Mock private NotificationPresenter mPresenter; 612b4c3a08fcfcb60c527a1a372318e5ef4ce2d49cEliot Courtney @Mock private NotificationListContainer mListContainer; 623985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney @Mock private IStatusBarService mBarService; 633985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney @Mock private NotificationData mNotificationData; 643985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney @Mock private ExpandableNotificationRow mRow; 653985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 668f56b0e3452dcc940319708061a3a22a4d994027Eliot Courtney // Dependency mocks: 678f56b0e3452dcc940319708061a3a22a4d994027Eliot Courtney @Mock private NotificationEntryManager mEntryManager; 688f56b0e3452dcc940319708061a3a22a4d994027Eliot Courtney @Mock private NotificationListener mListener; 698f56b0e3452dcc940319708061a3a22a4d994027Eliot Courtney 703985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney private NotificationData.Entry mEntry; 713985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney private StatusBarNotification mSbn; 723985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney private TestableNotificationLogger mLogger; 732e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>(); 743985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 753985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney @Before 762e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren public void setUp() throws RemoteException { 773985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney MockitoAnnotations.initMocks(this); 788f56b0e3452dcc940319708061a3a22a4d994027Eliot Courtney mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); 798f56b0e3452dcc940319708061a3a22a4d994027Eliot Courtney mDependency.injectTestDependency(NotificationListener.class, mListener); 803985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 81a6d8cf294dfb587f130fdecc5e6897e75de7bf45Eliot Courtney when(mEntryManager.getNotificationData()).thenReturn(mNotificationData); 823985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 833985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 843985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 0, new Notification(), UserHandle.CURRENT, null, 0); 853985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney mEntry = new NotificationData.Entry(mSbn); 863985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney mEntry.row = mRow; 873985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 886c313d3224c878d832db3ed833f4a3dd3786fb1fEliot Courtney mLogger = new TestableNotificationLogger(mBarService); 894a96b36fd9857cd3d3534ed0396ec3d7155a324cEliot Courtney mLogger.setUpWithEntryManager(mEntryManager, mListContainer); 903985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney } 913985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 923985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney @Test 933985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney public void testOnChildLocationsChangedReportsVisibilityChanged() throws Exception { 942e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren NotificationVisibility[] newlyVisibleKeys = { 952e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren NotificationVisibility.obtain(mEntry.key, 0, 1, true) 962e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren }; 972e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren NotificationVisibility[] noLongerVisibleKeys = {}; 982e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren doAnswer((Answer) invocation -> { 992e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren try { 1002e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren assertArrayEquals(newlyVisibleKeys, 1012e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren (NotificationVisibility[]) invocation.getArguments()[0]); 1022e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren assertArrayEquals(noLongerVisibleKeys, 1032e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren (NotificationVisibility[]) invocation.getArguments()[1]); 1042e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren } catch (AssertionError error) { 1052e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren mErrorQueue.offer(error); 1062e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren } 1072e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren return null; 1082e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren } 1092e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren ).when(mBarService).onNotificationVisibilityChanged(any(NotificationVisibility[].class), 1102e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren any(NotificationVisibility[].class)); 1112e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren 1122b4c3a08fcfcb60c527a1a372318e5ef4ce2d49cEliot Courtney when(mListContainer.isInVisibleLocation(any())).thenReturn(true); 1133985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry)); 1142b4c3a08fcfcb60c527a1a372318e5ef4ce2d49cEliot Courtney mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged(); 1156dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk TestableLooper.get(this).processAllMessages(); 1163985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney waitForUiOffloadThread(); 1173985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1182e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren if(!mErrorQueue.isEmpty()) { 1192e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren throw mErrorQueue.poll(); 1202e89e8d893acfe571ad6f5555baccb1b5e55abb7Chris Wren } 1213985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1223985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney // |mEntry| won't change visibility, so it shouldn't be reported again: 1233985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney Mockito.reset(mBarService); 1242b4c3a08fcfcb60c527a1a372318e5ef4ce2d49cEliot Courtney mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged(); 1256dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk TestableLooper.get(this).processAllMessages(); 1263985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney waitForUiOffloadThread(); 1273985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1283985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney verify(mBarService, never()).onNotificationVisibilityChanged(any(), any()); 1293985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney } 1303985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1313985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney @Test 1323985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney public void testStoppingNotificationLoggingReportsCurrentNotifications() 1333985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney throws Exception { 1342b4c3a08fcfcb60c527a1a372318e5ef4ce2d49cEliot Courtney when(mListContainer.isInVisibleLocation(any())).thenReturn(true); 1353985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney when(mNotificationData.getActiveNotifications()).thenReturn(Lists.newArrayList(mEntry)); 1362b4c3a08fcfcb60c527a1a372318e5ef4ce2d49cEliot Courtney mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged(); 1376dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk TestableLooper.get(this).processAllMessages(); 1383985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney waitForUiOffloadThread(); 1393985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney Mockito.reset(mBarService); 1403985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1413985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney mLogger.stopNotificationLogging(); 1423985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney waitForUiOffloadThread(); 1433985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney // The visibility objects are recycled by NotificationLogger, so we can't use specific 1443985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney // matchers here. 1453985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any()); 1463985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney } 1473985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1483985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney private class TestableNotificationLogger extends NotificationLogger { 1493985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1506c313d3224c878d832db3ed833f4a3dd3786fb1fEliot Courtney public TestableNotificationLogger(IStatusBarService barService) { 1513985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney mBarService = barService; 1526dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk // Make this on the current thread so we can wait for it during tests. 1536dceace0eddd08156e6b71c17e3de4ed5f4f2f41Jason Monk mHandler = Handler.createAsync(Looper.myLooper()); 1543985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney } 1553985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1562b4c3a08fcfcb60c527a1a372318e5ef4ce2d49cEliot Courtney public OnChildLocationsChangedListener 1573985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney getChildLocationsChangedListenerForTest() { 1583985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney return mNotificationLocationsChangedListener; 1593985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney } 1603985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney 1613985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney public Handler getHandlerForTest() { 1623985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney return mHandler; 1633985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney } 1643985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney } 1653985ad5773cd4573525cbfb00e132b960a83ef48Eliot Courtney} 166