Merge "Remove onBeforeNotificationAdded call"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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++;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user