Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a77f0597 authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Store uids in listener filters

Since listeners can see notifications in managed users, we
need to differentiate between pakgs in hte primary and managed profiles.

Test: atest
Bug: 173052211
Change-Id: I3dca45adab7f1330f7f1523547ddc556cb41184c
parent a6ae10c4
Loading
Loading
Loading
Loading
+16 −6
Original line number Diff line number Diff line
@@ -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;
+25 −17
Original line number Diff line number Diff line
@@ -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();
    }
}
+31 −10
Original line number Diff line number Diff line
@@ -175,6 +175,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;
@@ -8958,7 +8959,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;
@@ -9562,7 +9564,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 = ",";
@@ -9720,6 +9723,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
@@ -9749,15 +9764,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);
                            }
                        }
                    }
@@ -9782,10 +9799,14 @@ public class NotificationManagerService extends SystemService {
                XmlUtils.writeIntAttribute(out, ATT_TYPES, nlf.getTypes());
                out.endTag(null, TAG_APPROVED);

                for (VersionedPackage ai : nlf.getDisallowedPackages()) {
                    if (!TextUtils.isEmpty(ai.getPackageName())) {
                        out.startTag(null, TAG_DISALLOWED);
                XmlUtils.writeStringAttribute(
                        out, ATT_PKGS, String.join(XML_SEPARATOR, nlf.getDisallowedPackages()));
                        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);
            }
+32 −9
Original line number Diff line number Diff line
@@ -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();
    }

}
+2 −2
Original line number Diff line number Diff line
@@ -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);