Merge "Create NotificationListController"

This commit is contained in:
Ned Burns
2019-01-17 16:12:25 +00:00
committed by Android (Google) Code Review
6 changed files with 384 additions and 142 deletions

View File

@@ -33,6 +33,13 @@ public interface NotificationEntryListener {
default void onPendingEntryAdded(NotificationEntry entry) {
}
// TODO: Combine this with onPreEntryUpdated into "onBeforeEntryFiltered" or similar
/**
* Called when a new entry is created but before it has been filtered or displayed to the user.
*/
default void onBeforeNotificationAdded(NotificationEntry entry) {
}
/**
* Called when a new entry is created.
*/

View File

@@ -18,11 +18,9 @@ package com.android.systemui.statusbar.notification;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -41,7 +39,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationInflater;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.leak.LeakDetector;
@@ -68,8 +65,6 @@ public class NotificationEntryManager implements
@VisibleForTesting
protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>();
private final DeviceProvisionedController mDeviceProvisionedController =
Dependency.get(DeviceProvisionedController.class);
private final ForegroundServiceController mForegroundServiceController =
Dependency.get(ForegroundServiceController.class);
@@ -81,25 +76,12 @@ public class NotificationEntryManager implements
private NotificationListenerService.RankingMap mLatestRankingMap;
@VisibleForTesting
protected NotificationData mNotificationData;
private NotificationListContainer mListContainer;
@VisibleForTesting
final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders
= new ArrayList<>();
private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>();
private final DeviceProvisionedController.DeviceProvisionedListener
mDeviceProvisionedListener =
new DeviceProvisionedController.DeviceProvisionedListener() {
@Override
public void onDeviceProvisionedChanged() {
updateNotifications();
}
};
public void destroy() {
mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("NotificationEntryManager state:");
@@ -151,9 +133,6 @@ public class NotificationEntryManager implements
HeadsUpManager headsUpManager) {
mPresenter = presenter;
mNotificationData.setHeadsUpManager(headsUpManager);
mListContainer = listContainer;
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
}
/** Adds multiple {@link NotificationLifetimeExtender}s. */
@@ -227,7 +206,9 @@ public class NotificationEntryManager implements
listener.onEntryInflated(entry, inflatedFlags);
}
mNotificationData.add(entry);
tagForeground(entry.notification);
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onBeforeNotificationAdded(entry);
}
updateNotifications();
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onNotificationAdded(entry);
@@ -283,7 +264,6 @@ public class NotificationEntryManager implements
if (entry.rowExists()) {
entry.removeRow();
mListContainer.cleanUpViewStateForEntry(entry);
}
// Let's remove the children if this was a summary
@@ -368,19 +348,6 @@ public class NotificationEntryManager implements
}
}
@VisibleForTesting
void tagForeground(StatusBarNotification notification) {
ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
notification.getUserId(), notification.getPackageName());
if (activeOps != null) {
int N = activeOps.size();
for (int i = 0; i < N; i++) {
updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
notification.getPackageName(), true);
}
}
}
@Override
public void addNotification(StatusBarNotification notification,
NotificationListenerService.RankingMap ranking) {
@@ -391,15 +358,6 @@ public class NotificationEntryManager implements
}
}
public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
String foregroundKey = mForegroundServiceController.getStandardLayoutKey(
UserHandle.getUserId(uid), pkg);
if (foregroundKey != null) {
mNotificationData.updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
updateNotifications();
}
}
private void updateNotificationInternal(StatusBarNotification notification,
NotificationListenerService.RankingMap ranking) throws InflationException {
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
@@ -452,8 +410,9 @@ public class NotificationEntryManager implements
public void updateNotifications() {
mNotificationData.filterAndSort();
mPresenter.updateNotificationViews();
if (mPresenter != null) {
mPresenter.updateNotificationViews();
}
}
public void updateNotificationRanking(NotificationListenerService.RankingMap rankingMap) {

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2019 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;
import static com.android.internal.util.Preconditions.checkNotNull;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
/**
* Root controller for the list of notifications in the shade.
*
* TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy
* domain-specific behavior (ARC, etc) to subcontrollers.
*/
public class NotificationListController {
private final NotificationEntryManager mEntryManager;
private final NotificationListContainer mListContainer;
private final ForegroundServiceController mForegroundServiceController;
private final DeviceProvisionedController mDeviceProvisionedController;
public NotificationListController(
NotificationEntryManager entryManager,
NotificationListContainer listContainer,
ForegroundServiceController foregroundServiceController,
DeviceProvisionedController deviceProvisionedController) {
mEntryManager = checkNotNull(entryManager);
mListContainer = checkNotNull(listContainer);
mForegroundServiceController = checkNotNull(foregroundServiceController);
mDeviceProvisionedController = checkNotNull(deviceProvisionedController);
}
/**
* Causes the controller to register listeners on its dependencies. This method must be called
* before the controller is ready to perform its duties.
*/
public void bind() {
mEntryManager.addNotificationEntryListener(mEntryListener);
mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
}
/** Should be called when the list controller is being destroyed. */
public void destroy() {
mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
}
@SuppressWarnings("FieldCanBeLocal")
private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
@Override
public void onEntryRemoved(
NotificationEntry entry,
NotificationVisibility visibility,
boolean removedByUser) {
mListContainer.cleanUpViewStateForEntry(entry);
}
@Override
public void onBeforeNotificationAdded(NotificationEntry entry) {
tagForeground(entry.notification);
}
};
private final DeviceProvisionedListener mDeviceProvisionedListener =
new DeviceProvisionedListener() {
@Override
public void onDeviceProvisionedChanged() {
mEntryManager.updateNotifications();
}
};
// TODO: This method is horrifically inefficient
private void tagForeground(StatusBarNotification notification) {
ArraySet<Integer> activeOps =
mForegroundServiceController.getAppOps(
notification.getUserId(), notification.getPackageName());
if (activeOps != null) {
int len = activeOps.size();
for (int i = 0; i < len; i++) {
updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
notification.getPackageName(), true);
}
}
}
/** When an app op changes, propagate that change to notifications. */
public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
String foregroundKey =
mForegroundServiceController.getStandardLayoutKey(UserHandle.getUserId(uid), pkg);
if (foregroundKey != null) {
mEntryManager
.getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
mEntryManager.updateNotifications();
}
}
}

View File

@@ -196,6 +196,7 @@ import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationListController;
import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -387,6 +388,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private NotificationGutsManager mGutsManager;
protected NotificationLogger mNotificationLogger;
protected NotificationEntryManager mEntryManager;
private NotificationListController mNotificationListController;
private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private NotificationRowBinder mNotificationRowBinder;
protected NotificationViewHierarchyManager mViewHierarchyManager;
@@ -593,7 +595,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
mForegroundServiceController.onAppOpChanged(code, uid, packageName, active);
Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active);
});
}
@@ -1044,6 +1046,13 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager,
mNotificationAlertingManager);
mNotificationListController =
new NotificationListController(
mEntryManager,
(NotificationListContainer) mStackScroller,
mForegroundServiceController,
mDeviceProvisionedController);
mAppOpsController.addCallback(APP_OPS, this);
mNotificationListener.setUpWithPresenter(mPresenter);
mNotificationShelf.setOnActivatedListener(mPresenter);
@@ -1056,6 +1065,7 @@ public class StatusBar extends SystemUI implements DemoMode,
this, Dependency.get(BubbleController.class), mNotificationActivityStarter));
mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);
mNotificationListController.bind();
}
/**
@@ -2831,7 +2841,7 @@ public class StatusBar extends SystemUI implements DemoMode,
} catch (RemoteException e) {
// Ignore.
}
mEntryManager.destroy();
mNotificationListController.destroy();
// End old BaseStatusBar.destroy().
if (mStatusBarWindow != null) {
mWindowManager.removeViewImmediate(mStatusBarWindow);

View File

@@ -22,19 +22,15 @@ import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -49,7 +45,6 @@ import android.service.notification.StatusBarNotification;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
@@ -79,8 +74,6 @@ import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -346,7 +339,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
verify(mEntryListener, never()).onInflationError(any(), any());
verify(mListContainer).cleanUpViewStateForEntry(mEntry);
verify(mPresenter).updateNotificationViews();
verify(mEntryListener).onEntryRemoved(
mEntry, null, false /* removedByUser */);
@@ -400,90 +392,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntry, null, false /* removedByUser */);
}
@Test
public void testUpdateAppOps_foregroundNoti() {
com.android.systemui.util.Assert.isNotMainThread();
when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
.thenReturn(mEntry.key);
mEntry.setRow(mRow);
mEntryManager.getNotificationData().add(mEntry);
mEntryManager.updateNotificationsForAppOp(
AppOpsManager.OP_CAMERA, mEntry.notification.getUid(),
mEntry.notification.getPackageName(), true);
verify(mPresenter, times(1)).updateNotificationViews();
assertTrue(mEntryManager.getNotificationData().get(mEntry.key).mActiveAppOps.contains(
AppOpsManager.OP_CAMERA));
}
@Test
public void testUpdateAppOps_otherNoti() {
com.android.systemui.util.Assert.isNotMainThread();
when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
.thenReturn(null);
mEntryManager.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
verify(mPresenter, never()).updateNotificationViews();
}
@Test
public void testAddNotificationExistingAppOps() {
mEntry.setRow(mRow);
mEntryManager.getNotificationData().add(mEntry);
ArraySet<Integer> expected = new ArraySet<>();
expected.add(3);
expected.add(235);
expected.add(1);
when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
mEntry.notification.getPackageName())).thenReturn(expected);
when(mForegroundServiceController.getStandardLayoutKey(
mEntry.notification.getUserId(),
mEntry.notification.getPackageName())).thenReturn(mEntry.key);
mEntryManager.tagForeground(mEntry.notification);
Assert.assertEquals(expected.size(), mEntry.mActiveAppOps.size());
for (int op : expected) {
assertTrue("Entry missing op " + op, mEntry.mActiveAppOps.contains(op));
}
}
@Test
public void testAdd_noExistingAppOps() {
mEntry.setRow(mRow);
mEntryManager.getNotificationData().add(mEntry);
when(mForegroundServiceController.getStandardLayoutKey(
mEntry.notification.getUserId(),
mEntry.notification.getPackageName())).thenReturn(mEntry.key);
when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
mEntry.notification.getPackageName())).thenReturn(null);
mEntryManager.tagForeground(mEntry.notification);
Assert.assertEquals(0, mEntry.mActiveAppOps.size());
}
@Test
public void testAdd_existingAppOpsNotForegroundNoti() {
mEntry.setRow(mRow);
mEntryManager.getNotificationData().add(mEntry);
ArraySet<Integer> ops = new ArraySet<>();
ops.add(3);
ops.add(235);
ops.add(1);
when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
mEntry.notification.getPackageName())).thenReturn(ops);
when(mForegroundServiceController.getStandardLayoutKey(
mEntry.notification.getUserId(),
mEntry.notification.getPackageName())).thenReturn("something else");
mEntryManager.tagForeground(mEntry.notification);
Assert.assertEquals(0, mEntry.mActiveAppOps.size());
}
@Test
public void testUpdateNotificationRanking() {
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);

View File

@@ -0,0 +1,241 @@
/*
* Copyright (C) 2019 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;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.Notification;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class NotificationListControllerTest extends SysuiTestCase {
private NotificationListController mController;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotificationListContainer mListContainer;
@Mock private ForegroundServiceController mForegroundServiceController;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
@Captor private ArgumentCaptor<DeviceProvisionedListener> mProvisionedCaptor;
private NotificationEntryListener mEntryListener;
private DeviceProvisionedListener mProvisionedListener;
// TODO: Remove this once EntryManager no longer needs to be mocked
private NotificationData mNotificationData = new NotificationData();
private int mNextNotifId = 0;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
mController = new NotificationListController(
mEntryManager,
mListContainer,
mForegroundServiceController,
mDeviceProvisionedController);
mController.bind();
// Capture callbacks passed to mocks
verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
mEntryListener = mEntryListenerCaptor.getValue();
verify(mDeviceProvisionedController).addCallback(mProvisionedCaptor.capture());
mProvisionedListener = mProvisionedCaptor.getValue();
}
@Test
public void testCleanUpViewStateOnEntryRemoved() {
final NotificationEntry entry = buildEntry();
mEntryListener.onEntryRemoved(
entry,
NotificationVisibility.obtain(entry.key, 0, 0, true),
false);
verify(mListContainer).cleanUpViewStateForEntry(entry);
}
@Test
public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
mProvisionedListener.onDeviceProvisionedChanged();
verify(mEntryManager).updateNotifications();
}
@Test
public void testAppOps_appOpAddedToForegroundNotif() {
// GIVEN a notification associated with a foreground service
final NotificationEntry entry = buildEntry();
mNotificationData.add(entry);
when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
.thenReturn(entry.key);
// WHEN we are notified of a new app op
mController.updateNotificationsForAppOp(
AppOpsManager.OP_CAMERA,
entry.notification.getUid(),
entry.notification.getPackageName(),
true);
// THEN the app op is added to the entry
assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
// THEN updateNotifications() is called
verify(mEntryManager, times(1)).updateNotifications();
}
@Test
public void testAppOps_appOpAddedToUnrelatedNotif() {
// GIVEN No current foreground notifs
when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
.thenReturn(null);
// WHEN An unrelated notification gets a new app op
mController.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
// THEN We never call updateNotifications()
verify(mEntryManager, never()).updateNotifications();
}
@Test
public void testAppOps_addNotificationWithExistingAppOps() {
// GIVEN a notification with three associated app ops that is associated with a foreground
// service
final NotificationEntry entry = buildEntry();
mNotificationData.add(entry);
ArraySet<Integer> expected = new ArraySet<>();
expected.add(3);
expected.add(235);
expected.add(1);
when(mForegroundServiceController.getStandardLayoutKey(
entry.notification.getUserId(),
entry.notification.getPackageName())).thenReturn(entry.key);
when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
entry.notification.getPackageName())).thenReturn(expected);
// WHEN the notification is added
mEntryListener.onBeforeNotificationAdded(entry);
// THEN the entry is tagged with all three app ops
assertEquals(expected.size(), entry.mActiveAppOps.size());
for (int op : expected) {
assertTrue("Entry missing op " + op, entry.mActiveAppOps.contains(op));
}
}
@Test
public void testAdd_addNotificationWithNoExistingAppOps() {
// GIVEN a notification with NO associated app ops
final NotificationEntry entry = buildEntry();
mNotificationData.add(entry);
when(mForegroundServiceController.getStandardLayoutKey(
entry.notification.getUserId(),
entry.notification.getPackageName())).thenReturn(entry.key);
when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
entry.notification.getPackageName())).thenReturn(null);
// WHEN the notification is added
mEntryListener.onBeforeNotificationAdded(entry);
// THEN the entry doesn't have any app ops associated with it
assertEquals(0, entry.mActiveAppOps.size());
}
@Test
public void testAdd_addNonForegroundNotificationWithExistingAppOps() {
// GIVEN a notification with app ops that isn't associated with a foreground service
final NotificationEntry entry = buildEntry();
mNotificationData.add(entry);
ArraySet<Integer> ops = new ArraySet<>();
ops.add(3);
ops.add(235);
ops.add(1);
when(mForegroundServiceController.getAppOps(entry.notification.getUserId(),
entry.notification.getPackageName())).thenReturn(ops);
when(mForegroundServiceController.getStandardLayoutKey(
entry.notification.getUserId(),
entry.notification.getPackageName())).thenReturn("something else");
// WHEN the notification is added
mEntryListener.onBeforeNotificationAdded(entry);
// THEN the entry doesn't have any app ops associated with it
assertEquals(0, entry.mActiveAppOps.size());
}
private NotificationEntry buildEntry() {
mNextNotifId++;
Notification.Builder n = new Notification.Builder(mContext, "")
.setSmallIcon(R.drawable.ic_person)
.setContentTitle("Title")
.setContentText("Text");
StatusBarNotification notification =
new StatusBarNotification(
TEST_PACKAGE_NAME,
TEST_PACKAGE_NAME,
mNextNotifId,
null,
TEST_UID,
0,
n.build(),
new UserHandle(ActivityManager.getCurrentUser()),
null,
0);
return new NotificationEntry(notification);
}
private static final String TEST_PACKAGE_NAME = "test";
private static final int TEST_UID = 0;
}