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

Commit 7b14bd63 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add filtering to notifications sent to NLSes"

parents 1573c52b 51582aed
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import android.service.notification.Condition;
import android.service.notification.IConditionListener;
import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
import android.service.notification.IConditionProvider;
import android.service.notification.INotificationListener;
import android.service.notification.INotificationListener;
import android.service.notification.NotificationListenerFilter;
import android.service.notification.StatusBarNotification;
import android.service.notification.StatusBarNotification;
import android.app.AutomaticZenRule;
import android.app.AutomaticZenRule;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig;
@@ -224,4 +225,7 @@ interface INotificationManager
    boolean getPrivateNotificationsAllowed();
    boolean getPrivateNotificationsAllowed();


    long pullStats(long startNs, int report, boolean doAgg, out List<ParcelFileDescriptor> stats);
    long pullStats(long startNs, int report, boolean doAgg, out List<ParcelFileDescriptor> stats);

    NotificationListenerFilter getListenerFilter(in ComponentName cn, int userId);
    void setListenerFilter(in ComponentName cn, int userId, in NotificationListenerFilter nlf);
}
}
+20 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (c) 2020, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.service.notification;

parcelable NotificationListenerFilter;
+102 −0
Original line number Original line Diff line number Diff line
/**
 * Copyright (c) 2020, The Android Open Source Project
 *
 * Licensed under the Apache License,  2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.service.notification;

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_SILENT;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;

/**
 * Specifies a filter for what types of notifications should be bridged to notification listeners.
 * Each requested listener will have their own filter instance.
 * @hide
 */
public class NotificationListenerFilter implements Parcelable {
    private int mAllowedNotificationTypes;
    private ArraySet<String> mDisallowedPackages;

    public NotificationListenerFilter() {
        mAllowedNotificationTypes = FLAG_FILTER_TYPE_CONVERSATIONS
                | FLAG_FILTER_TYPE_ALERTING
                | FLAG_FILTER_TYPE_SILENT;
        mDisallowedPackages = new ArraySet<>();
    }

    public NotificationListenerFilter(int types, ArraySet<String> pkgs) {
        mAllowedNotificationTypes = types;
        mDisallowedPackages = pkgs;
    }

    /**
     * @hide
     */
    protected NotificationListenerFilter(Parcel in) {
        mAllowedNotificationTypes = in.readInt();
        mDisallowedPackages = (ArraySet<String>) in.readArraySet(String.class.getClassLoader());
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mAllowedNotificationTypes);
        dest.writeArraySet(mDisallowedPackages);
    }

    public static final Creator<NotificationListenerFilter> CREATOR =
            new Creator<NotificationListenerFilter>() {
                @Override
                public NotificationListenerFilter createFromParcel(Parcel in) {
                    return new NotificationListenerFilter(in);
                }

                @Override
                public NotificationListenerFilter[] newArray(int size) {
                    return new NotificationListenerFilter[size];
                }
            };

    public boolean isTypeAllowed(int type) {
        return (mAllowedNotificationTypes & type) != 0;
    }

    public boolean isPackageAllowed(String pkg) {
        return !mDisallowedPackages.contains(pkg);
    }

    public int getTypes() {
        return mAllowedNotificationTypes;
    }

    public ArraySet<String> getDisallowedPackages() {
        return mDisallowedPackages;
    }

    public void setTypes(int types) {
        mAllowedNotificationTypes = types;
    }

    public void setDisallowedPackages(ArraySet<String> pkgs) {
        mDisallowedPackages = pkgs;
    }

    @Override
    public int describeContents() {
        return 0;
    }
}
+17 −0
Original line number Original line Diff line number Diff line
@@ -241,6 +241,23 @@ public abstract class NotificationListenerService extends Service {
    })
    })
    public @interface NotificationCancelReason{};
    public @interface NotificationCancelReason{};


    /**
     * A flag value indicating that this notification listener can see conversation type
     * notifications.
     * @hide
     */
    public static final int FLAG_FILTER_TYPE_CONVERSATIONS = 1;
    /**
     * A flag value indicating that this notification listener can see altering type notifications.
     * @hide
     */
    public static final int FLAG_FILTER_TYPE_ALERTING = 2;
    /**
     * A flag value indicating that this notification listener can see silent type notifications.
     * @hide
     */
    public static final int FLAG_FILTER_TYPE_SILENT = 4;

    /**
    /**
     * The full trim of the StatusBarNotification including all its features.
     * The full trim of the StatusBarNotification including all its features.
     *
     *
+124 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package 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_SILENT;

import static com.google.common.truth.Truth.assertThat;

import android.app.NotificationChannel;
import android.os.Parcel;
import android.util.ArraySet;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
@SmallTest
public class NotificationListenerFilterTest {

    @Test
    public void testEmptyConstructor() {
        NotificationListenerFilter nlf = new NotificationListenerFilter();
        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_CONVERSATIONS)).isTrue();
        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_ALERTING)).isTrue();
        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_SILENT)).isTrue();
        assertThat(nlf.getTypes()).isEqualTo(FLAG_FILTER_TYPE_CONVERSATIONS
                | FLAG_FILTER_TYPE_ALERTING
                | FLAG_FILTER_TYPE_SILENT);

        assertThat(nlf.getDisallowedPackages()).isEmpty();
        assertThat(nlf.isPackageAllowed("pkg1")).isTrue();
    }


    @Test
    public void testConstructor() {
        ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1", "pkg2"});
        NotificationListenerFilter nlf =
                new NotificationListenerFilter(FLAG_FILTER_TYPE_ALERTING, pkgs);
        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_CONVERSATIONS)).isFalse();
        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_ALERTING)).isTrue();
        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();
    }

    @Test
    public void testSetDisallowedPackages() {
        NotificationListenerFilter nlf = new NotificationListenerFilter();

        ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1"});
        nlf.setDisallowedPackages(pkgs);

        assertThat(nlf.isPackageAllowed("pkg1")).isFalse();
    }

    @Test
    public void testSetTypes() {
        NotificationListenerFilter nlf = new NotificationListenerFilter();

        nlf.setTypes(FLAG_FILTER_TYPE_ALERTING | FLAG_FILTER_TYPE_SILENT);

        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_CONVERSATIONS)).isFalse();
        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_ALERTING)).isTrue();
        assertThat(nlf.isTypeAllowed(FLAG_FILTER_TYPE_SILENT)).isTrue();
        assertThat(nlf.getTypes()).isEqualTo(FLAG_FILTER_TYPE_ALERTING
                | FLAG_FILTER_TYPE_SILENT);
    }

    @Test
    public void testDescribeContents() {
        final int expected = 0;
        ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1", "pkg2"});
        NotificationListenerFilter nlf =
                new NotificationListenerFilter(FLAG_FILTER_TYPE_ALERTING, pkgs);
        assertThat(nlf.describeContents()).isEqualTo(expected);
    }

    @Test
    public void testParceling() {
        ArraySet<String> pkgs = new ArraySet<>(new String[] {"pkg1", "pkg2"});
        NotificationListenerFilter nlf =
                new NotificationListenerFilter(FLAG_FILTER_TYPE_ALERTING, pkgs);

        Parcel parcel = Parcel.obtain();
        nlf.writeToParcel(parcel, 0);
        parcel.setDataPosition(0);
        NotificationListenerFilter nlf1 =
                NotificationListenerFilter.CREATOR.createFromParcel(parcel);
        assertThat(nlf1.isTypeAllowed(FLAG_FILTER_TYPE_CONVERSATIONS)).isFalse();
        assertThat(nlf1.isTypeAllowed(FLAG_FILTER_TYPE_ALERTING)).isTrue();
        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();
    }
}
Loading