Remove onBeforeNotificationAdded call

By moving where appOps of notifications gets set

When appOps change:
 StatusBar detects appOp change and propogates change to
 ForegroundServiceController which stores appOp change
 (in case notification hasn't been added yet).
 This controller will also update the appOps of the relevant
 pending/visible notification

When a notification is added/updated:
 ForegroundServiceNotificationListener updates the
 relevant notification's appOps

Test: atest NotificationEntryManagerTest NotificationDataTest
Test: atest ForegroundServiceControllerTest
Change-Id: I3af4a2cf599d3eba7a0ba6006b3919730e5e658a
This commit is contained in:
Beverly
2019-10-18 14:30:46 -04:00
parent cabc32d247
commit 201cdd5026
12 changed files with 214 additions and 285 deletions

View File

@@ -21,10 +21,13 @@ import android.util.ArraySet;
import android.util.SparseArray;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Tracks state of foreground services and notifications related to foreground services per user.
*/
@@ -33,9 +36,11 @@ public class ForegroundServiceController {
private final SparseArray<ForegroundServicesUserState> mUserServices = new SparseArray<>();
private final Object mMutex = new Object();
private final NotificationEntryManager mEntryManager;
@Inject
public ForegroundServiceController() {
public ForegroundServiceController(NotificationEntryManager entryManager) {
mEntryManager = entryManager;
}
/**
@@ -90,11 +95,18 @@ public class ForegroundServiceController {
}
/**
* Records active app ops. App Ops are stored in FSC in addition to NotificationData in
* case they change before we have a notification to tag.
* Records active app ops and updates the app op for the pending or visible notifications
* with the given parameters.
* App Ops are stored in FSC in addition to NotificationEntry in case they change before we
* have a notification to tag.
* @param appOpCode code for appOp to add/remove
* @param uid of user the notification is sent to
* @param packageName package that created the notification
* @param active whether the appOpCode is active or not
*/
public void onAppOpChanged(int code, int uid, String packageName, boolean active) {
public void onAppOpChanged(int appOpCode, int uid, String packageName, boolean active) {
int userId = UserHandle.getUserId(uid);
// Record active app ops
synchronized (mMutex) {
ForegroundServicesUserState userServices = mUserServices.get(userId);
if (userServices == null) {
@@ -102,9 +114,30 @@ public class ForegroundServiceController {
mUserServices.put(userId, userServices);
}
if (active) {
userServices.addOp(packageName, code);
userServices.addOp(packageName, appOpCode);
} else {
userServices.removeOp(packageName, code);
userServices.removeOp(packageName, appOpCode);
}
}
// Update appOp if there's an associated pending or visible notification:
final String foregroundKey = getStandardLayoutKey(userId, packageName);
if (foregroundKey != null) {
final NotificationEntry entry = mEntryManager.getPendingOrCurrentNotif(foregroundKey);
if (entry != null
&& uid == entry.getSbn().getUid()
&& packageName.equals(entry.getSbn().getPackageName())) {
boolean changed;
synchronized (entry.mActiveAppOps) {
if (active) {
changed = entry.mActiveAppOps.add(appOpCode);
} else {
changed = entry.mActiveAppOps.remove(appOpCode);
}
}
if (changed) {
mEntryManager.updateNotifications("appOpChanged pkg=" + packageName);
}
}
}
}

View File

@@ -21,6 +21,7 @@ import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.Log;
import com.android.internal.statusbar.NotificationVisibility;
@@ -40,6 +41,7 @@ public class ForegroundServiceNotificationListener {
private final Context mContext;
private final ForegroundServiceController mForegroundServiceController;
private final NotificationEntryManager mEntryManager;
@Inject
public ForegroundServiceNotificationListener(Context context,
@@ -47,15 +49,16 @@ public class ForegroundServiceNotificationListener {
NotificationEntryManager notificationEntryManager) {
mContext = context;
mForegroundServiceController = foregroundServiceController;
notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
mEntryManager = notificationEntryManager;
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
addNotification(entry.getSbn(), entry.getImportance());
addNotification(entry, entry.getImportance());
}
@Override
public void onPostEntryUpdated(NotificationEntry entry) {
updateNotification(entry.getSbn(), entry.getImportance());
public void onPreEntryUpdated(NotificationEntry entry) {
updateNotification(entry, entry.getImportance());
}
@Override
@@ -67,15 +70,14 @@ public class ForegroundServiceNotificationListener {
}
});
notificationEntryManager.addNotificationLifetimeExtender(
new ForegroundServiceLifetimeExtender());
mEntryManager.addNotificationLifetimeExtender(new ForegroundServiceLifetimeExtender());
}
/**
* @param sbn notification that was just posted
* @param entry notification that was just posted
*/
private void addNotification(StatusBarNotification sbn, int importance) {
updateNotification(sbn, importance);
private void addNotification(NotificationEntry entry, int importance) {
updateNotification(entry, importance);
}
/**
@@ -113,9 +115,10 @@ public class ForegroundServiceNotificationListener {
}
/**
* @param sbn notification that was just changed in some way
* @param entry notification that was just changed in some way
*/
private void updateNotification(StatusBarNotification sbn, int newImportance) {
private void updateNotification(NotificationEntry entry, int newImportance) {
final StatusBarNotification sbn = entry.getSbn();
mForegroundServiceController.updateUserState(
sbn.getUserId(),
userState -> {
@@ -143,8 +146,22 @@ public class ForegroundServiceNotificationListener {
}
}
}
tagForeground(entry);
return true;
},
true /* create if not found */);
}
private void tagForeground(NotificationEntry entry) {
final StatusBarNotification sbn = entry.getSbn();
ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
sbn.getUserId(),
sbn.getPackageName());
if (activeOps != null) {
synchronized (entry.mActiveAppOps) {
entry.mActiveAppOps.clear();
entry.mActiveAppOps.addAll(activeOps);
}
}
}
}

View File

@@ -20,12 +20,12 @@ import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import androidx.annotation.NonNull;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import androidx.annotation.NonNull;
/**
* Listener interface for changes sent by NotificationEntryManager.
*/
@@ -37,13 +37,6 @@ 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

@@ -262,9 +262,6 @@ public class NotificationEntryManager implements
listener.onEntryInflated(entry, inflatedFlags);
}
mNotificationData.add(entry);
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onBeforeNotificationAdded(entry);
}
updateNotifications("onAsyncInflationFinished");
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onNotificationAdded(entry);
@@ -563,6 +560,18 @@ public class NotificationEntryManager implements
return mPendingNotifications.values();
}
/**
* Gets the pending or visible notification entry with the given key. Returns null if
* notification doesn't exist.
*/
public NotificationEntry getPendingOrCurrentNotif(String key) {
if (mPendingNotifications.containsKey(key)) {
return mPendingNotifications.get(key);
} else {
return mNotificationData.get(key);
}
}
private void extendLifetime(NotificationEntry entry, NotificationLifetimeExtender extender) {
NotificationLifetimeExtender activeExtender = mRetainedNotifications.get(entry);
if (activeExtender != null && activeExtender != extender) {

View File

@@ -18,10 +18,6 @@ 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;
@@ -70,11 +66,6 @@ public class NotificationListController {
boolean removedByUser) {
mListContainer.cleanUpViewStateForEntry(entry);
}
@Override
public void onBeforeNotificationAdded(NotificationEntry entry) {
tagForeground(entry.getSbn());
}
};
private final DeviceProvisionedListener mDeviceProvisionedListener =
@@ -84,29 +75,4 @@ public class NotificationListController {
mEntryManager.updateNotifications("device provisioned changed");
}
};
// 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("app opp changed pkg=" + pkg);
}
}
}

View File

@@ -225,24 +225,6 @@ public class NotificationData {
updateRankingAndSort(ranking, reason);
}
public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
synchronized (mEntries) {
final int len = mEntries.size();
for (int i = 0; i < len; i++) {
NotificationEntry entry = mEntries.valueAt(i);
if (uid == entry.getSbn().getUid()
&& pkg.equals(entry.getSbn().getPackageName())
&& key.equals(entry.getKey())) {
if (showIcon) {
entry.mActiveAppOps.add(appOp);
} else {
entry.mActiveAppOps.remove(appOp);
}
}
}
}
}
/**
* Returns true if this notification should be displayed in the high-priority notifications
* section

View File

@@ -130,7 +130,7 @@ public final class NotificationEntry {
private Throwable mDebugThrowable;
public CharSequence remoteInputTextWhenReset;
public long lastRemoteInputSent = NOT_LAUNCHED_YET;
public ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
public final ArraySet<Integer> mActiveAppOps = new ArraySet<>(3);
public CharSequence headsUpStatusBarText;
public CharSequence headsUpStatusBarTextPublic;

View File

@@ -617,7 +617,6 @@ public class StatusBar extends SystemUI implements DemoMode,
public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
Dependency.get(MAIN_HANDLER).post(() -> {
mForegroundServiceController.onAppOpChanged(code, uid, packageName, active);
mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active);
});
}

View File

@@ -21,11 +21,15 @@ import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
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.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.os.Bundle;
@@ -42,6 +46,8 @@ import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,26 +56,103 @@ import org.mockito.ArgumentCaptor;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ForegroundServiceControllerTest extends SysuiTestCase {
@UserIdInt private static final int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
@UserIdInt private static final int USERID_TWO = USERID_ONE + 1;
private ForegroundServiceController mFsc;
private ForegroundServiceNotificationListener mListener;
private NotificationEntryListener mEntryListener;
private NotificationEntryManager mEntryManager;
@Before
public void setUp() throws Exception {
mFsc = new ForegroundServiceController();
NotificationEntryManager notificationEntryManager = mock(NotificationEntryManager.class);
mEntryManager = mock(NotificationEntryManager.class);
mFsc = new ForegroundServiceController(mEntryManager);
mListener = new ForegroundServiceNotificationListener(
mContext, mFsc, notificationEntryManager);
mContext, mFsc, mEntryManager);
ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
ArgumentCaptor.forClass(NotificationEntryListener.class);
verify(notificationEntryManager).addNotificationEntryListener(
verify(mEntryManager).addNotificationEntryListener(
entryListenerCaptor.capture());
mEntryListener = entryListenerCaptor.getValue();
}
@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.getPendingOrCurrentNotif(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.getPendingOrCurrentNotif(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.getPendingOrCurrentNotif(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
@@ -339,12 +422,12 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
assertTrue(mFsc.isSystemAlertWarningNeeded(USERID_ONE, PKG1));
}
private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
private StatusBarNotification makeMockSBN(int userId, String pkg, int id, String tag,
int flags) {
final Notification n = mock(Notification.class);
n.extras = new Bundle();
n.flags = flags;
return makeMockSBN(userid, pkg, id, tag, n);
return makeMockSBN(userId, pkg, id, tag, n);
}
private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
@@ -360,10 +443,10 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
return sbn;
}
private StatusBarNotification makeMockFgSBN(int userid, String pkg, int id,
private StatusBarNotification makeMockFgSBN(int uid, String pkg, int id,
boolean usesStdLayout) {
StatusBarNotification sbn =
makeMockSBN(userid, pkg, id, "foo", Notification.FLAG_FOREGROUND_SERVICE);
makeMockSBN(uid, pkg, id, "foo", Notification.FLAG_FOREGROUND_SERVICE);
if (usesStdLayout) {
sbn.getNotification().contentView = null;
sbn.getNotification().headsUpContentView = null;
@@ -374,8 +457,8 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
return sbn;
}
private StatusBarNotification makeMockFgSBN(int userid, String pkg) {
return makeMockSBN(userid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
private StatusBarNotification makeMockFgSBN(int uid, String pkg) {
return makeMockSBN(uid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
}
private StatusBarNotification makeMockDisclosure(int userid, String[] pkgs) {
@@ -392,6 +475,19 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
return sbn;
}
private NotificationEntry addFgEntry() {
NotificationEntry entry = createFgEntry();
mEntryListener.onPendingEntryAdded(entry);
return entry;
}
private NotificationEntry createFgEntry() {
return new NotificationEntryBuilder()
.setSbn(makeMockFgSBN(0, TEST_PACKAGE_NAME, 1000, true))
.setImportance(NotificationManager.IMPORTANCE_DEFAULT)
.build();
}
private void entryRemoved(StatusBarNotification notification) {
mEntryListener.onEntryRemoved(
new NotificationEntryBuilder()
@@ -414,6 +510,10 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
.setSbn(notification)
.setImportance(importance)
.build();
mEntryListener.onPostEntryUpdated(entry);
mEntryListener.onPreEntryUpdated(entry);
}
@UserIdInt private static final int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
@UserIdInt private static final int USERID_TWO = USERID_ONE + 1;
private static final String TEST_PACKAGE_NAME = "test";
}

View File

@@ -140,6 +140,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Mock private RowInflaterTask mAsyncInflationTask;
@Mock private NotificationRowBinder mMockedRowBinder;
private int mId;
private NotificationEntry mEntry;
private StatusBarNotification mSbn;
private TestableNotificationEntryManager mEntryManager;
@@ -243,18 +244,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
when(mListContainer.getViewParentForNotification(any())).thenReturn(
new FrameLayout(mContext));
Notification.Builder n = new Notification.Builder(mContext, "")
.setSmallIcon(R.drawable.ic_person)
.setContentTitle("Title")
.setContentText("Text");
mEntry = new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
.setUid(TEST_UID)
.setNotification(n.build())
.setUser(new UserHandle(ActivityManager.getCurrentUser()))
.build();
mEntry = createNotification();
mSbn = mEntry.getSbn();
mEntry.expandedIcon = mock(StatusBarIconView.class);
@@ -607,6 +597,22 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
any(NotificationVisibility.class), anyBoolean());
}
private NotificationEntry createNotification() {
Notification.Builder n = new Notification.Builder(mContext, "")
.setSmallIcon(R.drawable.ic_person)
.setContentTitle("Title")
.setContentText("Text");
return new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
.setUid(TEST_UID)
.setId(mId++)
.setNotification(n.build())
.setUser(new UserHandle(ActivityManager.getCurrentUser()))
.build();
}
private Notification.Action createAction() {
return new Notification.Action.Builder(
Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),

View File

@@ -16,24 +16,16 @@
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.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.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArraySet;
import androidx.test.filters.SmallTest;
@@ -123,107 +115,6 @@ public class NotificationListControllerTest extends SysuiTestCase {
verify(mEntryManager).updateNotifications(anyString());
}
@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.getKey());
// WHEN we are notified of a new app op
mController.updateNotificationsForAppOp(
AppOpsManager.OP_CAMERA,
entry.getSbn().getUid(),
entry.getSbn().getPackageName(),
true);
// THEN the app op is added to the entry
assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
// THEN updateNotifications(TEST) is called
verify(mEntryManager, times(1)).updateNotifications(anyString());
}
@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(TEST)
verify(mEntryManager, never()).updateNotifications(anyString());
}
@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.getSbn().getUserId(),
entry.getSbn().getPackageName())).thenReturn(entry.getKey());
when(mForegroundServiceController.getAppOps(entry.getSbn().getUserId(),
entry.getSbn().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.getSbn().getUserId(),
entry.getSbn().getPackageName())).thenReturn(entry.getKey());
when(mForegroundServiceController.getAppOps(entry.getSbn().getUserId(),
entry.getSbn().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.getSbn().getUserId(),
entry.getSbn().getPackageName())).thenReturn(ops);
when(mForegroundServiceController.getStandardLayoutKey(
entry.getSbn().getUserId(),
entry.getSbn().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++;

View File

@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.notification.collection;
import static android.app.AppOpsManager.OP_ACCEPT_HANDOVER;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.Notification.CATEGORY_ALARM;
import static android.app.Notification.CATEGORY_CALL;
import static android.app.Notification.CATEGORY_EVENT;
@@ -56,7 +54,6 @@ import android.content.pm.PackageManager;
import android.graphics.drawable.Icon;
import android.media.session.MediaSession;
import android.os.Bundle;
import android.os.Process;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.SnoozeCriterion;
@@ -64,7 +61,6 @@ import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.util.ArraySet;
import androidx.test.filters.SmallTest;
@@ -159,69 +155,6 @@ public class NotificationDataTest extends SysuiTestCase {
assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().getChannel());
}
@Test
public void testAllRelevantNotisTaggedWithAppOps() throws Exception {
mNotificationData.add(mRow.getEntry());
ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
.createRow();
mNotificationData.add(row2.getEntry());
ExpandableNotificationRow diffPkg =
new NotificationTestHelper(getContext(), mDependency).createRow("pkg", 4000,
Process.myUserHandle());
mNotificationData.add(diffPkg.getEntry());
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_CAMERA);
expectedOps.add(OP_ACCEPT_HANDOVER);
for (int op : expectedOps) {
mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
NotificationTestHelper.PKG, mRow.getEntry().getKey(), true);
mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
NotificationTestHelper.PKG, row2.getEntry().getKey(), true);
}
for (int op : expectedOps) {
assertTrue(mRow.getEntry().getKey() + " doesn't have op " + op,
mNotificationData.get(mRow.getEntry().getKey()).mActiveAppOps.contains(op));
assertTrue(row2.getEntry().getKey() + " doesn't have op " + op,
mNotificationData.get(row2.getEntry().getKey()).mActiveAppOps.contains(op));
assertFalse(diffPkg.getEntry().getKey() + " has op " + op,
mNotificationData.get(diffPkg.getEntry().getKey()).mActiveAppOps.contains(op));
}
}
@Test
public void testAppOpsRemoval() throws Exception {
mNotificationData.add(mRow.getEntry());
ExpandableNotificationRow row2 = new NotificationTestHelper(getContext(), mDependency)
.createRow();
mNotificationData.add(row2.getEntry());
ArraySet<Integer> expectedOps = new ArraySet<>();
expectedOps.add(OP_CAMERA);
expectedOps.add(OP_ACCEPT_HANDOVER);
for (int op : expectedOps) {
mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
NotificationTestHelper.PKG, row2.getEntry().getKey(), true);
}
expectedOps.remove(OP_ACCEPT_HANDOVER);
mNotificationData.updateAppOp(OP_ACCEPT_HANDOVER, NotificationTestHelper.UID,
NotificationTestHelper.PKG, row2.getEntry().getKey(), false);
assertTrue(mRow.getEntry().getKey() + " doesn't have op " + OP_CAMERA,
mNotificationData.get(mRow.getEntry().getKey()).mActiveAppOps.contains(OP_CAMERA));
assertTrue(row2.getEntry().getKey() + " doesn't have op " + OP_CAMERA,
mNotificationData.get(row2.getEntry().getKey()).mActiveAppOps.contains(OP_CAMERA));
assertFalse(mRow.getEntry().getKey() + " has op " + OP_ACCEPT_HANDOVER,
mNotificationData.get(mRow.getEntry().getKey())
.mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
assertFalse(row2.getEntry().getKey() + " has op " + OP_ACCEPT_HANDOVER,
mNotificationData.get(row2.getEntry().getKey())
.mActiveAppOps.contains(OP_ACCEPT_HANDOVER));
}
@Test
public void testGetNotificationsForCurrentUser_shouldFilterNonCurrentUserNotifications()
throws Exception {