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

Commit 60633f62 authored by Julia Reynolds's avatar Julia Reynolds Committed by Android (Google) Code Review
Browse files

Merge "Allow notification filtering per listener."

parents bd56b6ba eb2b36a5
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -1532,4 +1532,21 @@
        <item>8</item>
        <item>12</item>
    </string-array>

    <!-- Array of titles list for notification listener notification types. [DO NOT TRANSLATE] -->
    <string-array name="notif_types_titles" translatable="false">
        <item>@string/notif_type_ongoing</item>
        <item>@string/notif_type_conversation</item>
        <item>@string/notif_type_alerting</item>
        <item>@string/notif_type_silent</item>
    </string-array>

    <!-- Values of list for notification listener notification types. Values need to match
    android.service.notification.NotificationListenerService. [DO NOT TRANSLATE] -->
    <string-array name="notif_types_values" translatable="false">
        <item>8</item>
        <item>1</item>
        <item>2</item>
        <item>4</item>
    </string-array>
</resources>
+5 −0
Original line number Diff line number Diff line
@@ -8756,6 +8756,11 @@
    </string>
    <string name="notification_listener_disable_warning_confirm">Turn off</string>
    <string name="notification_listener_disable_warning_cancel">Cancel</string>
    <string name="notification_listener_type_title">Allowed notification types</string>
    <string name="notif_type_ongoing">Important ongoing notifications</string>
    <string name="notif_type_conversation">Conversation notifications</string>
    <string name="notif_type_alerting">Alerting notifications</string>
    <string name="notif_type_silent">Silent notifications</string>
    <!-- Title for managing VR (virtual reality) helper services. [CHAR LIMIT=50] -->
    <string name="vr_listeners_title">VR helper services</string>
+17 −0
Original line number Diff line number Diff line
@@ -31,4 +31,21 @@
        android:title="@string/notification_access_detail_switch"
        settings:controller="com.android.settings.applications.specialaccess.notificationaccess.ApprovalPreferenceController"/>

    <MultiSelectListPreference
        android:key="notification_type_filter"
        android:title="@string/notification_listener_type_title"
        android:entries="@array/notif_types_titles"
        android:entryValues="@array/notif_types_values"
        android:summary="%s"
        android:persistent="false"
        style="@style/SettingsMultiSelectListPreference"
        settings:controller="com.android.settings.applications.specialaccess.notificationaccess.TypeFilterPreferenceController"/>/>

    <PreferenceCategory
        android:key="advanced"
        android:order="50"
        settings:initialExpandedChildrenCount="0">


    </PreferenceCategory>
</PreferenceScreen>
 No newline at end of file
+9 −2
Original line number Diff line number Diff line
@@ -42,11 +42,10 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.applications.ApplicationsState;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@@ -91,6 +90,10 @@ public class NotificationAccessDetails extends DashboardFragment {
                .setPackageInfo(mPackageInfo)
                .setPm(context.getPackageManager())
                .setServiceName(mServiceName);
        use(TypeFilterPreferenceController.class)
                .setNm(new NotificationBackend())
                .setCn(mComponentName)
                .setUserId(mUserId);
    }

    @Override
@@ -172,6 +175,8 @@ public class NotificationAccessDetails extends DashboardFragment {
        ApprovalPreferenceController controller = use(ApprovalPreferenceController.class);
        controller.disable(cn);
        controller.updateState(screen.findPreference(controller.getPreferenceKey()));
        TypeFilterPreferenceController dependent1 = use(TypeFilterPreferenceController.class);
        dependent1.updateState(screen.findPreference(dependent1.getPreferenceKey()));
    }

    protected void enable(ComponentName cn) {
@@ -179,6 +184,8 @@ public class NotificationAccessDetails extends DashboardFragment {
        ApprovalPreferenceController controller = use(ApprovalPreferenceController.class);
        controller.enable(cn);
        controller.updateState(screen.findPreference(controller.getPreferenceKey()));
        TypeFilterPreferenceController dependent1 = use(TypeFilterPreferenceController.class);
        dependent1.updateState(screen.findPreference(dependent1.getPreferenceKey()));
    }

    // To save binder calls, load this in the fragment rather than each preference controller
+144 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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 com.android.settings.applications.specialaccess.notificationaccess;

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 android.content.ComponentName;
import android.content.Context;
import android.service.notification.NotificationListenerFilter;

import androidx.preference.MultiSelectListPreference;
import androidx.preference.Preference;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;

import java.util.HashSet;
import java.util.Set;

public class TypeFilterPreferenceController extends BasePreferenceController implements
        PreferenceControllerMixin, Preference.OnPreferenceChangeListener {

    private static final String TAG = "TypeFilterPrefCntlr";

    private ComponentName mCn;
    private int mUserId;
    private NotificationBackend mNm;
    private NotificationListenerFilter mNlf;

    public TypeFilterPreferenceController(Context context, String key) {
        super(context, key);
    }

    public TypeFilterPreferenceController setCn(ComponentName cn) {
        mCn = cn;
        return this;
    }

    public TypeFilterPreferenceController setUserId(int userId) {
        mUserId = userId;
        return this;
    }

    public TypeFilterPreferenceController setNm(NotificationBackend nm) {
        mNm = nm;
        return this;
    }

    @Override
    public int getAvailabilityStatus() {
        if (mNm.isNotificationListenerAccessGranted(mCn)) {
            return AVAILABLE;
        } else {
            return DISABLED_DEPENDENT_SETTING;
        }
    }

    @Override
    public void updateState(Preference pref) {
        mNlf = mNm.getListenerFilter(mCn, mUserId);
        Set<String> values = new HashSet<>();
        Set<String> entries = new HashSet<>();

        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_ONGOING)) {
            values.add(String.valueOf(FLAG_FILTER_TYPE_ONGOING));
            entries.add(mContext.getString(R.string.notif_type_ongoing));
        }
        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_CONVERSATIONS)) {
            values.add(String.valueOf(FLAG_FILTER_TYPE_CONVERSATIONS));
            entries.add(mContext.getString(R.string.notif_type_conversation));
        }
        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_ALERTING)) {
            values.add(String.valueOf(FLAG_FILTER_TYPE_ALERTING));
            entries.add(mContext.getString(R.string.notif_type_alerting));
        }
        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_SILENT)) {
            values.add(String.valueOf(FLAG_FILTER_TYPE_SILENT));
            entries.add(mContext.getString(R.string.notif_type_silent));
        }

        final MultiSelectListPreference preference = (MultiSelectListPreference) pref;
        preference.setValues(values);
        super.updateState(preference);
        pref.setEnabled(getAvailabilityStatus() == AVAILABLE);
    }

    private boolean hasFlag(int value, int flag) {
        return (value & flag) != 0;
    }

    public CharSequence getSummary() {
        Set<String> entries = new HashSet<>();
        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_ONGOING)) {
            entries.add(mContext.getString(R.string.notif_type_ongoing));
        }
        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_CONVERSATIONS)) {
            entries.add(mContext.getString(R.string.notif_type_conversation));
        }
        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_ALERTING)) {
            entries.add(mContext.getString(R.string.notif_type_alerting));
        }
        if (hasFlag(mNlf.getTypes(), FLAG_FILTER_TYPE_SILENT)) {
            entries.add(mContext.getString(R.string.notif_type_silent));
        }
        return String.join(System.lineSeparator(), entries);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        // retrieve latest in case the package filter has changed
        mNlf = mNm.getListenerFilter(mCn, mUserId);

        Set<String> set = (Set<String>) newValue;

        int newFilter = 0;
        for (String filterType : set) {
            newFilter |= Integer.parseInt(filterType);
        }
        mNlf.setTypes(newFilter);
        preference.setSummary(getSummary());
        mNm.setListenerFilter(mCn, mUserId, mNlf);
        return true;
    }

}
 No newline at end of file
Loading