Merge "Store uids in listener filters" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8cc6496b0e
@@ -20,6 +20,7 @@ import static android.service.notification.NotificationListenerService.FLAG_FILT
|
||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
|
||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_SILENT;
|
||||
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.ArraySet;
|
||||
@@ -31,7 +32,7 @@ import android.util.ArraySet;
|
||||
*/
|
||||
public class NotificationListenerFilter implements Parcelable {
|
||||
private int mAllowedNotificationTypes;
|
||||
private ArraySet<String> mDisallowedPackages;
|
||||
private ArraySet<VersionedPackage> mDisallowedPackages;
|
||||
|
||||
public NotificationListenerFilter() {
|
||||
mAllowedNotificationTypes = FLAG_FILTER_TYPE_CONVERSATIONS
|
||||
@@ -41,7 +42,7 @@ public class NotificationListenerFilter implements Parcelable {
|
||||
mDisallowedPackages = new ArraySet<>();
|
||||
}
|
||||
|
||||
public NotificationListenerFilter(int types, ArraySet<String> pkgs) {
|
||||
public NotificationListenerFilter(int types, ArraySet<VersionedPackage> pkgs) {
|
||||
mAllowedNotificationTypes = types;
|
||||
mDisallowedPackages = pkgs;
|
||||
}
|
||||
@@ -51,7 +52,8 @@ public class NotificationListenerFilter implements Parcelable {
|
||||
*/
|
||||
protected NotificationListenerFilter(Parcel in) {
|
||||
mAllowedNotificationTypes = in.readInt();
|
||||
mDisallowedPackages = (ArraySet<String>) in.readArraySet(String.class.getClassLoader());
|
||||
mDisallowedPackages = (ArraySet<VersionedPackage>) in.readArraySet(
|
||||
VersionedPackage.class.getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,7 +79,7 @@ public class NotificationListenerFilter implements Parcelable {
|
||||
return (mAllowedNotificationTypes & type) != 0;
|
||||
}
|
||||
|
||||
public boolean isPackageAllowed(String pkg) {
|
||||
public boolean isPackageAllowed(VersionedPackage pkg) {
|
||||
return !mDisallowedPackages.contains(pkg);
|
||||
}
|
||||
|
||||
@@ -85,7 +87,7 @@ public class NotificationListenerFilter implements Parcelable {
|
||||
return mAllowedNotificationTypes;
|
||||
}
|
||||
|
||||
public ArraySet<String> getDisallowedPackages() {
|
||||
public ArraySet<VersionedPackage> getDisallowedPackages() {
|
||||
return mDisallowedPackages;
|
||||
}
|
||||
|
||||
@@ -93,10 +95,18 @@ public class NotificationListenerFilter implements Parcelable {
|
||||
mAllowedNotificationTypes = types;
|
||||
}
|
||||
|
||||
public void setDisallowedPackages(ArraySet<String> pkgs) {
|
||||
public void setDisallowedPackages(ArraySet<VersionedPackage> pkgs) {
|
||||
mDisallowedPackages = pkgs;
|
||||
}
|
||||
|
||||
public void removePackage(VersionedPackage pkg) {
|
||||
mDisallowedPackages.remove(pkg);
|
||||
}
|
||||
|
||||
public void addPackage(VersionedPackage pkg) {
|
||||
mDisallowedPackages.add(pkg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
package android.service.notification;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
|
||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
|
||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
|
||||
import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_SILENT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.os.Parcel;
|
||||
import android.util.ArraySet;
|
||||
|
||||
@@ -45,16 +45,19 @@ public class NotificationListenerFilterTest {
|
||||
assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_SILENT)).isTrue();
|
||||
assertThat(nlf.getTypes()).isEqualTo(FLAG_FILTER_TYPE_CONVERSATIONS
|
||||
| FLAG_FILTER_TYPE_ALERTING
|
||||
| FLAG_FILTER_TYPE_SILENT);
|
||||
| FLAG_FILTER_TYPE_SILENT
|
||||
| FLAG_FILTER_TYPE_ONGOING);
|
||||
|
||||
assertThat(nlf.getDisallowedPackages()).isEmpty();
|
||||
assertThat(nlf.isPackageAllowed("pkg1")).isTrue();
|
||||
assertThat(nlf.isPackageAllowed(new VersionedPackage("any", 0))).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testConstructor() {
|
||||
ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1", "pkg2"});
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
VersionedPackage a2= new VersionedPackage("pkg2", 2142534);
|
||||
ArraySet<VersionedPackage> pkgs = new ArraySet<>(new VersionedPackage[] {a1, a2});
|
||||
NotificationListenerFilter nlf =
|
||||
new NotificationListenerFilter(FLAG_FILTER_TYPE_ALERTING, pkgs);
|
||||
assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_CONVERSATIONS)).isFalse();
|
||||
@@ -62,20 +65,21 @@ public class NotificationListenerFilterTest {
|
||||
assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_SILENT)).isFalse();
|
||||
assertThat(nlf.getTypes()).isEqualTo(FLAG_FILTER_TYPE_ALERTING);
|
||||
|
||||
assertThat(nlf.getDisallowedPackages()).contains("pkg1");
|
||||
assertThat(nlf.getDisallowedPackages()).contains("pkg2");
|
||||
assertThat(nlf.isPackageAllowed("pkg1")).isFalse();
|
||||
assertThat(nlf.isPackageAllowed("pkg2")).isFalse();
|
||||
assertThat(nlf.getDisallowedPackages()).contains(a1);
|
||||
assertThat(nlf.getDisallowedPackages()).contains(a2);
|
||||
assertThat(nlf.isPackageAllowed(a1)).isFalse();
|
||||
assertThat(nlf.isPackageAllowed(a2)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetDisallowedPackages() {
|
||||
NotificationListenerFilter nlf = new NotificationListenerFilter();
|
||||
|
||||
ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1"});
|
||||
ArraySet<VersionedPackage> pkgs = new ArraySet<>(
|
||||
new VersionedPackage[] {new VersionedPackage("pkg1", 0)});
|
||||
nlf.setDisallowedPackages(pkgs);
|
||||
|
||||
assertThat(nlf.isPackageAllowed("pkg1")).isFalse();
|
||||
assertThat(nlf.isPackageAllowed(new VersionedPackage("pkg1", 0))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,7 +98,9 @@ public class NotificationListenerFilterTest {
|
||||
@Test
|
||||
public void testDescribeContents() {
|
||||
final int expected = 0;
|
||||
ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1", "pkg2"});
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
VersionedPackage a2= new VersionedPackage("pkg2", 2142534);
|
||||
ArraySet<VersionedPackage> pkgs = new ArraySet<>(new VersionedPackage[] {a1, a2});
|
||||
NotificationListenerFilter nlf =
|
||||
new NotificationListenerFilter(FLAG_FILTER_TYPE_ALERTING, pkgs);
|
||||
assertThat(nlf.describeContents()).isEqualTo(expected);
|
||||
@@ -102,7 +108,9 @@ public class NotificationListenerFilterTest {
|
||||
|
||||
@Test
|
||||
public void testParceling() {
|
||||
ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1", "pkg2"});
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
VersionedPackage a2= new VersionedPackage("pkg2", 2142534);
|
||||
ArraySet<VersionedPackage> pkgs = new ArraySet<>(new VersionedPackage[] {a1, a2});
|
||||
NotificationListenerFilter nlf =
|
||||
new NotificationListenerFilter(FLAG_FILTER_TYPE_ALERTING, pkgs);
|
||||
|
||||
@@ -116,9 +124,9 @@ public class NotificationListenerFilterTest {
|
||||
assertThat(nlf1.isTypeAllowed(FLAG_FILTER_TYPE_SILENT)).isFalse();
|
||||
assertThat(nlf1.getTypes()).isEqualTo(FLAG_FILTER_TYPE_ALERTING);
|
||||
|
||||
assertThat(nlf1.getDisallowedPackages()).contains("pkg1");
|
||||
assertThat(nlf1.getDisallowedPackages()).contains("pkg2");
|
||||
assertThat(nlf1.isPackageAllowed("pkg1")).isFalse();
|
||||
assertThat(nlf1.isPackageAllowed("pkg2")).isFalse();
|
||||
assertThat(nlf1.getDisallowedPackages()).contains(a1);
|
||||
assertThat(nlf1.getDisallowedPackages()).contains(a2);
|
||||
assertThat(nlf1.isPackageAllowed(a1)).isFalse();
|
||||
assertThat(nlf1.isPackageAllowed(a2)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@ import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutServiceInternal;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.media.AudioAttributes;
|
||||
@@ -8969,7 +8970,8 @@ public class NotificationManagerService extends SystemService {
|
||||
NotificationListenerFilter nls = mListeners.getNotificationListenerFilter(listener.mKey);
|
||||
if (nls != null
|
||||
&& (!nls.isTypeAllowed(notificationType)
|
||||
|| !nls.isPackageAllowed(sbn.getPackageName()))) {
|
||||
|| !nls.isPackageAllowed(
|
||||
new VersionedPackage(sbn.getPackageName(), sbn.getUid())))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -9580,7 +9582,8 @@ public class NotificationManagerService extends SystemService {
|
||||
static final String TAG_REQUESTED_LISTENER = "listener";
|
||||
static final String ATT_COMPONENT = "component";
|
||||
static final String ATT_TYPES = "types";
|
||||
static final String ATT_PKGS = "pkgs";
|
||||
static final String ATT_PKG = "pkg";
|
||||
static final String ATT_UID = "uid";
|
||||
static final String TAG_APPROVED = "allowed";
|
||||
static final String TAG_DISALLOWED= "disallowed";
|
||||
static final String XML_SEPARATOR = ",";
|
||||
@@ -9738,6 +9741,18 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clean up anything in the disallowed pkgs list
|
||||
for (int i = 0; i < pkgList.length; i++) {
|
||||
String pkg = pkgList[i];
|
||||
int userId = UserHandle.getUserId(uidList[i]);
|
||||
for (int j = mRequestedNotificationListeners.size() - 1; j >= 0; j--) {
|
||||
NotificationListenerFilter nlf = mRequestedNotificationListeners.valueAt(j);
|
||||
|
||||
VersionedPackage ai = new VersionedPackage(pkg, uidList[i]);
|
||||
nlf.removePackage(ai);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -9767,15 +9782,17 @@ public class NotificationManagerService extends SystemService {
|
||||
int approved = FLAG_FILTER_TYPE_CONVERSATIONS | FLAG_FILTER_TYPE_ALERTING
|
||||
| FLAG_FILTER_TYPE_SILENT | FLAG_FILTER_TYPE_ONGOING;
|
||||
|
||||
ArraySet<String> disallowedPkgs = new ArraySet<>();
|
||||
ArraySet<VersionedPackage> disallowedPkgs = new ArraySet<>();
|
||||
final int listenerOuterDepth = parser.getDepth();
|
||||
while (XmlUtils.nextElementWithin(parser, listenerOuterDepth)) {
|
||||
if (TAG_APPROVED.equals(parser.getName())) {
|
||||
approved = XmlUtils.readIntAttribute(parser, ATT_TYPES);
|
||||
} else if (TAG_DISALLOWED.equals(parser.getName())) {
|
||||
String pkgs = XmlUtils.readStringAttribute(parser, ATT_PKGS);
|
||||
if (!TextUtils.isEmpty(pkgs)) {
|
||||
disallowedPkgs = new ArraySet<>(pkgs.split(XML_SEPARATOR));
|
||||
String pkg = XmlUtils.readStringAttribute(parser, ATT_PKG);
|
||||
int uid = XmlUtils.readIntAttribute(parser, ATT_UID);
|
||||
if (!TextUtils.isEmpty(pkg)) {
|
||||
VersionedPackage ai = new VersionedPackage(pkg, uid);
|
||||
disallowedPkgs.add(ai);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9800,10 +9817,14 @@ public class NotificationManagerService extends SystemService {
|
||||
XmlUtils.writeIntAttribute(out, ATT_TYPES, nlf.getTypes());
|
||||
out.endTag(null, TAG_APPROVED);
|
||||
|
||||
out.startTag(null, TAG_DISALLOWED);
|
||||
XmlUtils.writeStringAttribute(
|
||||
out, ATT_PKGS, String.join(XML_SEPARATOR, nlf.getDisallowedPackages()));
|
||||
out.endTag(null, TAG_DISALLOWED);
|
||||
for (VersionedPackage ai : nlf.getDisallowedPackages()) {
|
||||
if (!TextUtils.isEmpty(ai.getPackageName())) {
|
||||
out.startTag(null, TAG_DISALLOWED);
|
||||
XmlUtils.writeStringAttribute(out, ATT_PKG, ai.getPackageName());
|
||||
XmlUtils.writeIntAttribute(out, ATT_UID, ai.getVersionCode());
|
||||
out.endTag(null, TAG_DISALLOWED);
|
||||
}
|
||||
}
|
||||
|
||||
out.endTag(null, TAG_REQUESTED_LISTENER);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.INotificationManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.VersionedPackage;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
@@ -83,11 +84,10 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
String xml = "<req_listeners>"
|
||||
+ "<listener component=\"" + mCn1.flattenToString() + "\" user=\"0\">"
|
||||
+ "<allowed types=\"7\" />"
|
||||
+ "<disallowed pkgs=\"\" />"
|
||||
+ "</listener>"
|
||||
+ "<listener component=\"" + mCn2.flattenToString() + "\" user=\"10\">"
|
||||
+ "<allowed types=\"4\" />"
|
||||
+ "<disallowed pkgs=\"something\" />"
|
||||
+ "<disallowed pkg=\"pkg1\" uid=\"243\"/>"
|
||||
+ "</listener>"
|
||||
+ "</req_listeners>";
|
||||
|
||||
@@ -103,8 +103,9 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
@Test
|
||||
public void testWriteExtraTag() throws Exception {
|
||||
NotificationListenerFilter nlf = new NotificationListenerFilter(7, new ArraySet<>());
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
NotificationListenerFilter nlf2 =
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new String[] {"something"}));
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1}));
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn1, 0), nlf);
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn2, 10), nlf2);
|
||||
|
||||
@@ -134,16 +135,18 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
|
||||
assertThat(mListeners.getNotificationListenerFilter(Pair.create(mCn2, 10)).getTypes())
|
||||
.isEqualTo(4);
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
assertThat(mListeners.getNotificationListenerFilter(Pair.create(mCn2, 10))
|
||||
.getDisallowedPackages())
|
||||
.contains("something");
|
||||
.contains(a1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUserRemoved() {
|
||||
NotificationListenerFilter nlf = new NotificationListenerFilter(7, new ArraySet<>());
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
NotificationListenerFilter nlf2 =
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new String[] {"something"}));
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1}));
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn1, 0), nlf);
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn2, 10), nlf2);
|
||||
|
||||
@@ -157,8 +160,9 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
@Test
|
||||
public void testOnUserUnlocked() {
|
||||
// one exists already, say from xml
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
NotificationListenerFilter nlf =
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new String[] {"something"}));
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1}));
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn2, 0), nlf);
|
||||
|
||||
// new service exists or backfilling on upgrade to S
|
||||
@@ -188,7 +192,7 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
.isEqualTo(4);
|
||||
assertThat(mListeners.getNotificationListenerFilter(Pair.create(mCn2, 0))
|
||||
.getDisallowedPackages())
|
||||
.contains("something");
|
||||
.contains(a1);
|
||||
|
||||
assertThat(mListeners.getNotificationListenerFilter(
|
||||
Pair.create(si.getComponentName(), 0)).getTypes())
|
||||
@@ -205,8 +209,9 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
@Test
|
||||
public void testOnPackageChanged() {
|
||||
NotificationListenerFilter nlf = new NotificationListenerFilter(7, new ArraySet<>());
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
NotificationListenerFilter nlf2 =
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new String[] {"something"}));
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1}));
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn1, 0), nlf);
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn2, 10), nlf2);
|
||||
|
||||
@@ -224,8 +229,9 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
@Test
|
||||
public void testOnPackageChanged_removing() {
|
||||
NotificationListenerFilter nlf = new NotificationListenerFilter(7, new ArraySet<>());
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
NotificationListenerFilter nlf2 =
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new String[] {"something"}));
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1}));
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn1, 0), nlf);
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn2, 0), nlf2);
|
||||
|
||||
@@ -239,4 +245,21 @@ public class NotificationListenersTest extends UiServiceTestCase {
|
||||
.isEqualTo(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPackageChanged_removingDisallowedPackage() {
|
||||
NotificationListenerFilter nlf = new NotificationListenerFilter(7, new ArraySet<>());
|
||||
VersionedPackage a1 = new VersionedPackage("pkg1", 243);
|
||||
NotificationListenerFilter nlf2 =
|
||||
new NotificationListenerFilter(4, new ArraySet<>(new VersionedPackage[] {a1}));
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn1, 0), nlf);
|
||||
mListeners.setNotificationListenerFilter(Pair.create(mCn2, 0), nlf2);
|
||||
|
||||
String[] pkgs = new String[] {"pkg1"};
|
||||
int[] uids = new int[] {243};
|
||||
mListeners.onPackagesChanged(true, pkgs, uids);
|
||||
|
||||
assertThat(mListeners.getNotificationListenerFilter(Pair.create(mCn1, 0))
|
||||
.getDisallowedPackages()).isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -464,7 +464,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
|
||||
// Setup managed services
|
||||
when(mNlf.isTypeAllowed(anyInt())).thenReturn(true);
|
||||
when(mNlf.isPackageAllowed(anyString())).thenReturn(true);
|
||||
when(mNlf.isPackageAllowed(any())).thenReturn(true);
|
||||
when(mNlf.isPackageAllowed(null)).thenReturn(true);
|
||||
when(mListeners.getNotificationListenerFilter(any())).thenReturn(mNlf);
|
||||
mListener = mListeners.new ManagedServiceInfo(
|
||||
@@ -7307,7 +7307,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
|
||||
@Test
|
||||
public void testIsVisibleToListener_disallowedPackage() {
|
||||
when(mNlf.isPackageAllowed(null)).thenReturn(false);
|
||||
when(mNlf.isPackageAllowed(any())).thenReturn(false);
|
||||
|
||||
StatusBarNotification sbn = mock(StatusBarNotification.class);
|
||||
when(sbn.getUserId()).thenReturn(10);
|
||||
|
||||
Reference in New Issue
Block a user