diff options
| author | 2020-09-16 16:32:48 +0000 | |
|---|---|---|
| committer | 2020-09-16 16:32:48 +0000 | |
| commit | 125d1725cdf75dd3ae855ca6dfb194a074e2649e (patch) | |
| tree | e4ad011545cb437945097f47d705a93904e92f6e /packages/SystemUI/tests | |
| parent | d0d1ca7ce89f967567c6dc022bdd2ab6f7008d2e (diff) | |
| parent | 8ec5bcb3d0cd9efd27cda5e309755d8b9be2f57c (diff) | |
DO NOT MERGE Revert "Remove app ops indicators from notifications" am: 8ec5bcb3d0
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12615554
Change-Id: Ib5170725586b432972ab4b29129c1cadb53d50e1
Diffstat (limited to 'packages/SystemUI/tests')
7 files changed, 537 insertions, 1 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index e967a5d607eb..60f0cd9da5f2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -82,7 +82,8 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { allowTestableLooperAsMainThread(); MockitoAnnotations.initMocks(this); - mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler); + mFsc = new ForegroundServiceController( + mEntryManager, mAppOpsController, mMainHandler); mListener = new ForegroundServiceNotificationListener( mContext, mFsc, mEntryManager, mNotifPipeline, mock(ForegroundServiceLifetimeExtender.class), mClock); @@ -114,6 +115,85 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { } @Test + public void testAppOps_appOpChangedBeforeNotificationExists() { + // GIVEN app op exists, but notification doesn't exist in NEM yet + NotificationEntry entry = createFgEntry(); + mFsc.onAppOpChanged( + AppOpsManager.OP_CAMERA, + entry.getSbn().getUid(), + entry.getSbn().getPackageName(), + true); + assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); + + // WHEN the notification is added + mEntryListener.onPendingEntryAdded(entry); + + // THEN the app op is added to the entry + Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); + } + + @Test + public void testAppOps_appOpAddedToForegroundNotif() { + // GIVEN a notification associated with a foreground service + NotificationEntry entry = addFgEntry(); + when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry); + + // WHEN we are notified of a new app op for this notification + mFsc.onAppOpChanged( + AppOpsManager.OP_CAMERA, + entry.getSbn().getUid(), + entry.getSbn().getPackageName(), + true); + + // THEN the app op is added to the entry + Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); + + // THEN notification views are updated since the notification is visible + verify(mEntryManager, times(1)).updateNotifications(anyString()); + } + + @Test + public void testAppOpsAlreadyAdded() { + // GIVEN a foreground service associated notification that already has the correct app op + NotificationEntry entry = addFgEntry(); + entry.mActiveAppOps.add(AppOpsManager.OP_CAMERA); + when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry); + + // WHEN we are notified of the same app op for this notification + mFsc.onAppOpChanged( + AppOpsManager.OP_CAMERA, + entry.getSbn().getUid(), + entry.getSbn().getPackageName(), + true); + + // THEN the app op still exists in the notification entry + Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); + + // THEN notification views aren't updated since nothing changed + verify(mEntryManager, never()).updateNotifications(anyString()); + } + + @Test + public void testAppOps_appOpNotAddedToUnrelatedNotif() { + // GIVEN no notification entries correspond to the newly updated appOp + NotificationEntry entry = addFgEntry(); + when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(null); + + // WHEN a new app op is detected + mFsc.onAppOpChanged( + AppOpsManager.OP_CAMERA, + entry.getSbn().getUid(), + entry.getSbn().getPackageName(), + true); + + // THEN we won't see appOps on the entry + Assert.assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); + + // THEN notification views aren't updated since nothing changed + verify(mEntryManager, never()).updateNotifications(anyString()); + } + + @Test public void testAppOpsCRUD() { // no crash on remove that doesn't exist mFsc.onAppOpChanged(9, 1000, "pkg1", false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java index 80fa8cc7d931..92a2c8738344 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java @@ -211,6 +211,19 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { } @Test + public void testUpdateNotificationViews_appOps() throws Exception { + NotificationEntry entry0 = createEntry(); + entry0.setRow(spy(entry0.getRow())); + when(mEntryManager.getVisibleNotifications()).thenReturn( + Lists.newArrayList(entry0)); + mListContainer.addContainerView(entry0.getRow()); + + mViewHierarchyManager.updateNotificationViews(); + + verify(entry0.getRow(), times(1)).showAppOpsIcons(any()); + } + + @Test public void testReentrantCallsToOnDynamicPrivacyChangedPostForLater() { // GIVEN a ListContainer that will make a re-entrant call to updateNotificationViews() mMadeReentrantCall = false; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java index ae39035e8666..314b19140e7a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java @@ -72,6 +72,8 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { private Notification mNotification; private AppOpsCoordinator mAppOpsCoordinator; private NotifFilter mForegroundFilter; + private NotifCollectionListener mNotifCollectionListener; + private AppOpsController.Callback mAppOpsCallback; private NotifLifetimeExtender mForegroundNotifLifetimeExtender; private FakeSystemClock mClock = new FakeSystemClock(); @@ -108,6 +110,18 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { lifetimeExtenderCaptor.capture()); mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue(); + // capture notifCollectionListener + ArgumentCaptor<NotifCollectionListener> notifCollectionCaptor = + ArgumentCaptor.forClass(NotifCollectionListener.class); + verify(mNotifPipeline, times(1)).addCollectionListener( + notifCollectionCaptor.capture()); + mNotifCollectionListener = notifCollectionCaptor.getValue(); + + // capture app ops callback + ArgumentCaptor<AppOpsController.Callback> appOpsCaptor = + ArgumentCaptor.forClass(AppOpsController.Callback.class); + verify(mAppOpsController).addCallback(any(int[].class), appOpsCaptor.capture()); + mAppOpsCallback = appOpsCaptor.getValue(); } @Test @@ -201,4 +215,134 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { assertFalse(mForegroundNotifLifetimeExtender .shouldExtendLifetime(mEntry, NotificationListenerService.REASON_CLICK)); } + + @Test + public void testAppOpsUpdateOnlyAppliedToRelevantNotificationWithStandardLayout() { + // GIVEN three current notifications, two with the same key but from different users + NotificationEntry entry1 = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .setPkg(TEST_PKG) + .setId(1) + .build(); + NotificationEntry entry2 = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .setPkg(TEST_PKG) + .setId(2) + .build(); + NotificationEntry entry3_diffUser = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID + 1)) + .setPkg(TEST_PKG) + .setId(2) + .build(); + when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3_diffUser)); + + // GIVEN that only entry2 has a standard layout + when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG)) + .thenReturn(new ArraySet<>(List.of(entry2.getKey()))); + + // WHEN a new app ops code comes in + mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true); + mExecutor.runAllReady(); + + // THEN entry2's app ops are updated, but no one else's are + assertEquals( + new ArraySet<>(), + entry1.mActiveAppOps); + assertEquals( + new ArraySet<>(List.of(47)), + entry2.mActiveAppOps); + assertEquals( + new ArraySet<>(), + entry3_diffUser.mActiveAppOps); + } + + @Test + public void testAppOpsUpdateAppliedToAllNotificationsWithStandardLayouts() { + // GIVEN three notifications with standard layouts + NotificationEntry entry1 = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .setPkg(TEST_PKG) + .setId(1) + .build(); + NotificationEntry entry2 = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .setPkg(TEST_PKG) + .setId(2) + .build(); + NotificationEntry entry3 = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .setPkg(TEST_PKG) + .setId(3) + .build(); + when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3)); + when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG)) + .thenReturn(new ArraySet<>(List.of(entry1.getKey(), entry2.getKey(), + entry3.getKey()))); + + // WHEN a new app ops code comes in + mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true); + mExecutor.runAllReady(); + + // THEN all entries get updated + assertEquals( + new ArraySet<>(List.of(47)), + entry1.mActiveAppOps); + assertEquals( + new ArraySet<>(List.of(47)), + entry2.mActiveAppOps); + assertEquals( + new ArraySet<>(List.of(47)), + entry3.mActiveAppOps); + } + + @Test + public void testAppOpsAreRemoved() { + // GIVEN One notification which is associated with app ops + NotificationEntry entry = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .setPkg(TEST_PKG) + .setId(2) + .build(); + when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry)); + when(mForegroundServiceController.getStandardLayoutKeys(0, TEST_PKG)) + .thenReturn(new ArraySet<>(List.of(entry.getKey()))); + + // GIVEN that the notification's app ops are already [47, 33] + mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true); + mAppOpsCallback.onActiveStateChanged(33, NOTIF_USER_ID, TEST_PKG, true); + mExecutor.runAllReady(); + assertEquals( + new ArraySet<>(List.of(47, 33)), + entry.mActiveAppOps); + + // WHEN one of the app ops is removed + mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, false); + mExecutor.runAllReady(); + + // THEN the entry's active app ops are updated as well + assertEquals( + new ArraySet<>(List.of(33)), + entry.mActiveAppOps); + } + + @Test + public void testNullAppOps() { + // GIVEN one notification with app ops + NotificationEntry entry = new NotificationEntryBuilder() + .setUser(new UserHandle(NOTIF_USER_ID)) + .setPkg(TEST_PKG) + .setId(2) + .build(); + entry.mActiveAppOps.clear(); + entry.mActiveAppOps.addAll(List.of(47, 33)); + + // WHEN the notification is updated and the foreground service controller returns null for + // this notification + when(mForegroundServiceController.getAppOps(entry.getSbn().getUser().getIdentifier(), + entry.getSbn().getPackageName())).thenReturn(null); + mNotifCollectionListener.onEntryUpdated(entry); + + // THEN the entry's active app ops is updated to empty + assertTrue(entry.mActiveAppOps.isEmpty()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java new file mode 100644 index 000000000000..43d8b50bcf72 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.statusbar.notification.row; + +import static android.app.AppOpsManager.OP_CAMERA; +import static android.app.AppOpsManager.OP_RECORD_AUDIO; +import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Notification; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.UserHandle; +import android.service.notification.StatusBarNotification; +import android.test.suitebuilder.annotation.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.UiThreadTest; +import android.util.ArraySet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.internal.logging.testing.UiEventLoggerFake; +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.CountDownLatch; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@UiThreadTest +public class AppOpsInfoTest extends SysuiTestCase { + private static final String TEST_PACKAGE_NAME = "test_package"; + private static final int TEST_UID = 1; + + private AppOpsInfo mAppOpsInfo; + private final PackageManager mMockPackageManager = mock(PackageManager.class); + private final NotificationGuts mGutsParent = mock(NotificationGuts.class); + private StatusBarNotification mSbn; + private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake(); + + @Before + public void setUp() throws Exception { + // Inflate the layout + final LayoutInflater layoutInflater = LayoutInflater.from(mContext); + mAppOpsInfo = (AppOpsInfo) layoutInflater.inflate(R.layout.app_ops_info, null); + mAppOpsInfo.setGutsParent(mGutsParent); + + // PackageManager must return a packageInfo and applicationInfo. + final PackageInfo packageInfo = new PackageInfo(); + packageInfo.packageName = TEST_PACKAGE_NAME; + when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt())) + .thenReturn(packageInfo); + final ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.uid = TEST_UID; // non-zero + when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn( + applicationInfo); + + mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, + new Notification(), UserHandle.CURRENT, null, 0); + } + + @Test + public void testBindNotification_SetsTextApplicationName() { + when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); + final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname); + assertTrue(textView.getText().toString().contains("App Name")); + } + + @Test + public void testBindNotification_SetsPackageIcon() { + final Drawable iconDrawable = mock(Drawable.class); + when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class))) + .thenReturn(iconDrawable); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); + final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon); + assertEquals(iconDrawable, iconView.getDrawable()); + } + + @Test + public void testBindNotification_SetsOnClickListenerForSettings() throws Exception { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + final CountDownLatch latch = new CountDownLatch(1); + mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid, + ArraySet<Integer> ops) -> { + assertEquals(TEST_PACKAGE_NAME, pkg); + assertEquals(expectedOps, ops); + assertEquals(TEST_UID, uid); + latch.countDown(); + }, mSbn, mUiEventLogger, expectedOps); + + final View settingsButton = mAppOpsInfo.findViewById(R.id.settings); + settingsButton.performClick(); + // Verify that listener was triggered. + assertEquals(0, latch.getCount()); + } + + @Test + public void testBindNotification_LogsOpen() throws Exception { + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>()); + assertEquals(1, mUiEventLogger.numLogs()); + assertEquals(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN.getId(), + mUiEventLogger.eventId(0)); + } + + @Test + public void testOk() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + final CountDownLatch latch = new CountDownLatch(1); + mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid, + ArraySet<Integer> ops) -> { + assertEquals(TEST_PACKAGE_NAME, pkg); + assertEquals(expectedOps, ops); + assertEquals(TEST_UID, uid); + latch.countDown(); + }, mSbn, mUiEventLogger, expectedOps); + + final View okButton = mAppOpsInfo.findViewById(R.id.ok); + okButton.performClick(); + assertEquals(1, latch.getCount()); + verify(mGutsParent, times(1)).closeControls(eq(okButton), anyBoolean()); + } + + @Test + public void testPrompt_camera() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); + TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); + assertEquals("This app is using the camera.", prompt.getText()); + } + + @Test + public void testPrompt_mic() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_RECORD_AUDIO); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); + TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); + assertEquals("This app is using the microphone.", prompt.getText()); + } + + @Test + public void testPrompt_overlay() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_SYSTEM_ALERT_WINDOW); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); + TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); + assertEquals("This app is displaying over other apps on your screen.", prompt.getText()); + } + + @Test + public void testPrompt_camera_mic() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + expectedOps.add(OP_RECORD_AUDIO); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); + TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); + assertEquals("This app is using the microphone and camera.", prompt.getText()); + } + + @Test + public void testPrompt_camera_mic_overlay() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + expectedOps.add(OP_RECORD_AUDIO); + expectedOps.add(OP_SYSTEM_ALERT_WINDOW); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); + TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); + assertEquals("This app is displaying over other apps on your screen and using" + + " the microphone and camera.", prompt.getText()); + } + + @Test + public void testPrompt_camera_overlay() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_CAMERA); + expectedOps.add(OP_SYSTEM_ALERT_WINDOW); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); + TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); + assertEquals("This app is displaying over other apps on your screen and using" + + " the camera.", prompt.getText()); + } + + @Test + public void testPrompt_mic_overlay() { + ArraySet<Integer> expectedOps = new ArraySet<>(); + expectedOps.add(OP_RECORD_AUDIO); + expectedOps.add(OP_SYSTEM_ALERT_WINDOW); + mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps); + TextView prompt = mAppOpsInfo.findViewById(R.id.prompt); + assertEquals("This app is displaying over other apps on your screen and using" + + " the microphone.", prompt.getText()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index 4758d2318889..2684cc29aa93 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -35,10 +35,12 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.AppOpsManager; import android.app.NotificationChannel; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import android.util.ArraySet; import android.view.View; import androidx.test.filters.SmallTest; @@ -211,6 +213,46 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { } @Test + public void testShowAppOps_noHeader() { + // public notification is custom layout - no header + mGroupRow.setSensitive(true, true); + mGroupRow.setAppOpsOnClickListener(null); + mGroupRow.showAppOpsIcons(null); + } + + @Test + public void testShowAppOpsIcons_header() { + NotificationContentView publicLayout = mock(NotificationContentView.class); + mGroupRow.setPublicLayout(publicLayout); + NotificationContentView privateLayout = mock(NotificationContentView.class); + mGroupRow.setPrivateLayout(privateLayout); + NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class); + when(mockContainer.getNotificationChildCount()).thenReturn(1); + mGroupRow.setChildrenContainer(mockContainer); + + ArraySet<Integer> ops = new ArraySet<>(); + ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS); + mGroupRow.showAppOpsIcons(ops); + + verify(mockContainer, times(1)).showAppOpsIcons(ops); + verify(privateLayout, times(1)).showAppOpsIcons(ops); + verify(publicLayout, times(1)).showAppOpsIcons(ops); + + } + + @Test + public void testAppOpsOnClick() { + ExpandableNotificationRow.OnAppOpsClickListener l = mock( + ExpandableNotificationRow.OnAppOpsClickListener.class); + View view = mock(View.class); + + mGroupRow.setAppOpsOnClickListener(l); + + mGroupRow.getAppOpsOnClickListener().onClick(view); + verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any()); + } + + @Test public void testHeadsUpAnimatingAwayListener() { mGroupRow.setHeadsUpAnimatingAway(true); Assert.assertEquals(true, mHeadsUpAnimatingAway); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java index b02f2746ce7a..ed4f8b330e23 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java @@ -76,6 +76,32 @@ public class NotificationContentViewTest extends SysuiTestCase { @Test @UiThreadTest + public void testShowAppOpsIcons() { + View mockContracted = mock(NotificationHeaderView.class); + when(mockContracted.findViewById(com.android.internal.R.id.mic)) + .thenReturn(mockContracted); + View mockExpanded = mock(NotificationHeaderView.class); + when(mockExpanded.findViewById(com.android.internal.R.id.mic)) + .thenReturn(mockExpanded); + View mockHeadsUp = mock(NotificationHeaderView.class); + when(mockHeadsUp.findViewById(com.android.internal.R.id.mic)) + .thenReturn(mockHeadsUp); + + mView.setContractedChild(mockContracted); + mView.setExpandedChild(mockExpanded); + mView.setHeadsUpChild(mockHeadsUp); + + ArraySet<Integer> ops = new ArraySet<>(); + ops.add(AppOpsManager.OP_RECORD_AUDIO); + mView.showAppOpsIcons(ops); + + verify(mockContracted, times(1)).setVisibility(View.VISIBLE); + verify(mockExpanded, times(1)).setVisibility(View.VISIBLE); + verify(mockHeadsUp, times(1)).setVisibility(View.VISIBLE); + } + + @Test + @UiThreadTest public void testExpandButtonFocusIsCalled() { View mockContractedEB = mock(NotificationExpandButton.class); View mockContracted = mock(NotificationHeaderView.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index d2ff2ad8a684..0c6409b38d21 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -421,6 +421,7 @@ public class NotificationTestHelper { mBindStage, mock(OnExpandClickListener.class), mock(NotificationMediaManager.class), + mock(ExpandableNotificationRow.OnAppOpsClickListener.class), mock(FalsingManager.class), mStatusBarStateController, mPeopleNotificationIdentifier); |