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

Commit 50df60c9 authored by Matías Hernández's avatar Matías Hernández Committed by Automerger Merge Worker
Browse files

Don't hide approved NLSes in Settings am: ff255c6e

parents 062a9ca5 ff255c6e
Loading
Loading
Loading
Loading
+13 −12
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.widget.Toast;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
@@ -60,8 +61,8 @@ import java.util.List;
@SearchIndexable
public class NotificationAccessSettings extends EmptyTextSettings {
    private static final String TAG = "NotifAccessSettings";
    private static final String ALLOWED_KEY = "allowed";
    private static final String NOT_ALLOWED_KEY = "not_allowed";
    static final String ALLOWED_KEY = "allowed";
    static final String NOT_ALLOWED_KEY = "not_allowed";
    private static final int MAX_CN_LENGTH = 500;

    private static final ManagedServiceSettings.Config CONFIG =
@@ -77,9 +78,9 @@ public class NotificationAccessSettings extends EmptyTextSettings {
                    .setEmptyText(R.string.no_notification_listeners)
                    .build();

    private NotificationManager mNm;
    @VisibleForTesting NotificationManager mNm;
    protected Context mContext;
    private PackageManager mPm;
    @VisibleForTesting PackageManager mPm;
    private DevicePolicyManager mDpm;
    private ServiceListing mServiceListing;
    private IconDrawableFactory mIconDrawableFactory;
@@ -99,12 +100,6 @@ public class NotificationAccessSettings extends EmptyTextSettings {
                .setNoun(CONFIG.noun)
                .setSetting(CONFIG.setting)
                .setTag(CONFIG.tag)
                .setValidator(info -> {
                    if (info.getComponentName().flattenToString().length() > MAX_CN_LENGTH) {
                        return false;
                    }
                    return true;
                })
                .build();
        mServiceListing.addCallback(this::updateList);

@@ -135,7 +130,8 @@ public class NotificationAccessSettings extends EmptyTextSettings {
        mServiceListing.setListening(false);
    }

    private void updateList(List<ServiceInfo> services) {
    @VisibleForTesting
    void updateList(List<ServiceInfo> services) {
        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        final int managedProfileId = Utils.getManagedProfileId(um, UserHandle.myUserId());

@@ -148,6 +144,11 @@ public class NotificationAccessSettings extends EmptyTextSettings {
        services.sort(new PackageItemInfo.DisplayNameComparator(mPm));
        for (ServiceInfo service : services) {
            final ComponentName cn = new ComponentName(service.packageName, service.name);
            boolean isAllowed = mNm.isNotificationListenerAccessGranted(cn);
            if (!isAllowed && cn.flattenToString().length() > MAX_CN_LENGTH) {
                continue;
            }

            CharSequence title = null;
            try {
                title = mPm.getApplicationInfoAsUser(
@@ -192,7 +193,7 @@ public class NotificationAccessSettings extends EmptyTextSettings {
                        return true;
                    });
            pref.setKey(cn.flattenToString());
            if (mNm.isNotificationListenerAccessGranted(cn)) {
            if (isAllowed) {
                allowedCategory.addPreference(pref);
            } else {
                notAllowedCategory.addPreference(pref);
+3 −0
Original line number Diff line number Diff line
@@ -143,6 +143,9 @@ public class NotificationBackend {

    static public CharSequence getDeviceList(ICompanionDeviceManager cdm, LocalBluetoothManager lbm,
            String pkg, int userId) {
        if (cdm == null) {
            return "";
        }
        boolean multiple = false;
        StringBuilder sb = new StringBuilder();

+144 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.notification;

import static com.android.settings.notification.NotificationAccessSettings.ALLOWED_KEY;
import static com.android.settings.notification.NotificationAccessSettings.NOT_ALLOWED_KEY;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;

import androidx.fragment.app.FragmentActivity;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;

import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothManager;

import com.google.common.base.Strings;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;

import java.util.ArrayList;

@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothUtils.class})
public class NotificationAccessSettingsTest {

    private Context mContext;
    private NotificationAccessSettings mAccessSettings;
    @Mock
    private NotificationManager mNotificationManager;
    @Mock
    private PackageManager mPackageManager;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        mContext = RuntimeEnvironment.application;
        ShadowApplication shadowApp = ShadowApplication.getInstance();
        shadowApp.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);

        mAccessSettings = new NotificationAccessSettings();
        FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class).setup().get();
        activity.getSupportFragmentManager().beginTransaction().add(mAccessSettings, null).commit();

        when(mPackageManager.getApplicationInfoAsUser(any(), anyInt(), anyInt())).then(
                (Answer<ApplicationInfo>) invocation -> {
                    ApplicationInfo appInfo = mock(ApplicationInfo.class);
                    when(appInfo.loadLabel(any())).thenReturn(invocation.getArgument(0));
                    return appInfo;
                });

        mAccessSettings.mNm = mNotificationManager;
        mAccessSettings.mPm = mPackageManager;
        ShadowBluetoothUtils.sLocalBluetoothManager = mock(LocalBluetoothManager.class);
    }

    @Test
    public void updateList_enabledLongName_shown() {
        ComponentName longCn = new ComponentName("test.pkg1",
                Strings.repeat("Blah", 200) + "Service");
        ComponentName shortCn = new ComponentName("test.pkg2", "ReasonableService");
        ArrayList<ServiceInfo> services = new ArrayList<>();
        services.add(newServiceInfo(longCn.getPackageName(), longCn.getClassName(), 1));
        services.add(newServiceInfo(shortCn.getPackageName(), shortCn.getClassName(), 2));
        when(mNotificationManager.isNotificationListenerAccessGranted(any())).thenReturn(true);

        mAccessSettings.updateList(services);

        PreferenceScreen screen = mAccessSettings.getPreferenceScreen();
        PreferenceCategory allowed = checkNotNull(screen.findPreference(ALLOWED_KEY));
        PreferenceCategory notAllowed = checkNotNull(screen.findPreference(NOT_ALLOWED_KEY));
        assertThat(allowed.getPreferenceCount()).isEqualTo(2);
        assertThat(allowed.getPreference(0).getKey()).isEqualTo(longCn.flattenToString());
        assertThat(allowed.getPreference(1).getKey()).isEqualTo(shortCn.flattenToString());
        assertThat(notAllowed.getPreferenceCount()).isEqualTo(0);
    }

    @Test
    public void updateList_disabledLongName_notShown() {
        ComponentName longCn = new ComponentName("test.pkg1",
                Strings.repeat("Blah", 200) + "Service");
        ComponentName shortCn = new ComponentName("test.pkg2", "ReasonableService");
        ArrayList<ServiceInfo> services = new ArrayList<>();
        services.add(newServiceInfo(longCn.getPackageName(), longCn.getClassName(), 1));
        services.add(newServiceInfo(shortCn.getPackageName(), shortCn.getClassName(), 2));
        when(mNotificationManager.isNotificationListenerAccessGranted(any())).thenReturn(false);

        mAccessSettings.updateList(services);

        PreferenceScreen screen = mAccessSettings.getPreferenceScreen();
        PreferenceCategory allowed = checkNotNull(screen.findPreference(ALLOWED_KEY));
        PreferenceCategory notAllowed = checkNotNull(screen.findPreference(NOT_ALLOWED_KEY));
        assertThat(allowed.getPreferenceCount()).isEqualTo(0);
        assertThat(notAllowed.getPreferenceCount()).isEqualTo(1);
        assertThat(notAllowed.getPreference(0).getKey()).isEqualTo(shortCn.flattenToString());
    }

    private static ServiceInfo newServiceInfo(String packageName, String serviceName, int uid) {
        ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.packageName = packageName;
        serviceInfo.name = serviceName;
        serviceInfo.applicationInfo = new ApplicationInfo();
        serviceInfo.applicationInfo.uid = uid;
        return serviceInfo;
    }
}