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

Commit bce3c209 authored by Yuri Lin's avatar Yuri Lin Committed by Android (Google) Code Review
Browse files

Merge "Include permission-based notification allow/bans in dumps."

parents 030f8655 d5b9fec6
Loading
Loading
Loading
Loading
+42 −11
Original line number Diff line number Diff line
@@ -2612,7 +2612,8 @@ public class NotificationManagerService extends SystemService {
    private int pullNotificationStates(int atomTag, List<StatsEvent> data) {
        switch(atomTag) {
            case PACKAGE_NOTIFICATION_PREFERENCES:
                mPreferencesHelper.pullPackagePreferencesStats(data);
                mPreferencesHelper.pullPackagePreferencesStats(data,
                        getAllUsersNotificationPermissions());
                break;
            case PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES:
                mPreferencesHelper.pullPackageChannelPreferencesStats(data);
@@ -5065,16 +5066,18 @@ public class NotificationManagerService extends SystemService {
            final DumpFilter filter = DumpFilter.parseFromArguments(args);
            final long token = Binder.clearCallingIdentity();
            try {
                final ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions =
                        getAllUsersNotificationPermissions();
                if (filter.stats) {
                    dumpJson(pw, filter);
                    dumpJson(pw, filter, pkgPermissions);
                } else if (filter.rvStats) {
                    dumpRemoteViewStats(pw, filter);
                } else if (filter.proto) {
                    dumpProto(fd, filter);
                    dumpProto(fd, filter, pkgPermissions);
                } else if (filter.criticalPriority) {
                    dumpNotificationRecords(pw, filter);
                } else {
                    dumpImpl(pw, filter);
                    dumpImpl(pw, filter, pkgPermissions);
                }
            } finally {
                Binder.restoreCallingIdentity(token);
@@ -5896,12 +5899,38 @@ public class NotificationManagerService extends SystemService {
        return null;
    }

    private void dumpJson(PrintWriter pw, @NonNull DumpFilter filter) {
    // Gets packages that have requested notification permission, and whether that has been
    // allowed/denied, for all users on the device.
    // Returns a single map containing that info keyed by (uid, package name) for all users.
    // Because this calls into mPermissionHelper, this method must never be called with a lock held.
    @VisibleForTesting
    protected ArrayMap<Pair<Integer, String>, Boolean> getAllUsersNotificationPermissions() {
        // don't bother if migration is not enabled
        if (!mEnableAppSettingMigration) {
            return null;
        }
        ArrayMap<Pair<Integer, String>, Boolean> allPermissions = new ArrayMap<>();
        final List<UserInfo> allUsers = mUm.getUsers();
        // for each of these, get the package notification permissions that are associated
        // with this user and add it to the map
        for (UserInfo ui : allUsers) {
            ArrayMap<Pair<Integer, String>, Boolean> userPermissions =
                    mPermissionHelper.getNotificationPermissionValues(
                            ui.getUserHandle().getIdentifier());
            for (Pair<Integer, String> pair : userPermissions.keySet()) {
                allPermissions.put(pair, userPermissions.get(pair));
            }
        }
        return allPermissions;
    }

    private void dumpJson(PrintWriter pw, @NonNull DumpFilter filter,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        JSONObject dump = new JSONObject();
        try {
            dump.put("service", "Notification Manager");
            dump.put("bans", mPreferencesHelper.dumpBansJson(filter));
            dump.put("ranking", mPreferencesHelper.dumpJson(filter));
            dump.put("bans", mPreferencesHelper.dumpBansJson(filter, pkgPermissions));
            dump.put("ranking", mPreferencesHelper.dumpJson(filter, pkgPermissions));
            dump.put("stats", mUsageStats.dumpJson(filter));
            dump.put("channels", mPreferencesHelper.dumpChannelsJson(filter));
        } catch (JSONException e) {
@@ -5919,7 +5948,8 @@ public class NotificationManagerService extends SystemService {
        stats.dump(REPORT_REMOTE_VIEWS, pw, filter);
    }

    private void dumpProto(FileDescriptor fd, @NonNull DumpFilter filter) {
    private void dumpProto(FileDescriptor fd, @NonNull DumpFilter filter,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        final ProtoOutputStream proto = new ProtoOutputStream(fd);
        synchronized (mNotificationLock) {
            int N = mNotificationList.size();
@@ -5986,7 +6016,7 @@ public class NotificationManagerService extends SystemService {

            long rankingToken = proto.start(NotificationServiceDumpProto.RANKING_CONFIG);
            mRankingHelper.dump(proto, filter);
            mPreferencesHelper.dump(proto, filter);
            mPreferencesHelper.dump(proto, filter, pkgPermissions);
            proto.end(rankingToken);
        }

@@ -6009,7 +6039,8 @@ public class NotificationManagerService extends SystemService {
        }
    }

    void dumpImpl(PrintWriter pw, @NonNull DumpFilter filter) {
    void dumpImpl(PrintWriter pw, @NonNull DumpFilter filter,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        pw.print("Current Notification Manager state");
        if (filter.filtered) {
            pw.print(" (filtered to "); pw.print(filter); pw.print(")");
@@ -6088,7 +6119,7 @@ public class NotificationManagerService extends SystemService {
                mRankingHelper.dump(pw, "    ", filter);

                pw.println("\n Notification Preferences:");
                mPreferencesHelper.dump(pw, "    ", filter);
                mPreferencesHelper.dump(pw, "    ", filter, pkgPermissions);

                pw.println("\n  Notification listeners:");
                mListeners.dump(pw, filter);
+189 −23
Original line number Diff line number Diff line
@@ -1931,31 +1931,41 @@ public class PreferencesHelper implements RankingConfig {
    }

    public void dump(PrintWriter pw, String prefix,
            @NonNull NotificationManagerService.DumpFilter filter) {
            @NonNull NotificationManagerService.DumpFilter filter,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        pw.print(prefix);
        pw.println("per-package config version: " + XML_VERSION);

        pw.println("PackagePreferences:");
        synchronized (mPackagePreferences) {
            dumpPackagePreferencesLocked(pw, prefix, filter, mPackagePreferences);
            dumpPackagePreferencesLocked(pw, prefix, filter, mPackagePreferences, pkgPermissions);
        }
        pw.println("Restored without uid:");
        dumpPackagePreferencesLocked(pw, prefix, filter, mRestoredWithoutUids);
        dumpPackagePreferencesLocked(pw, prefix, filter, mRestoredWithoutUids, null);
    }

    public void dump(ProtoOutputStream proto,
            @NonNull NotificationManagerService.DumpFilter filter) {
            @NonNull NotificationManagerService.DumpFilter filter,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        synchronized (mPackagePreferences) {
            dumpPackagePreferencesLocked(proto, RankingHelperProto.RECORDS, filter,
                    mPackagePreferences);
                    mPackagePreferences, pkgPermissions);
        }
        dumpPackagePreferencesLocked(proto, RankingHelperProto.RECORDS_RESTORED_WITHOUT_UID, filter,
                mRestoredWithoutUids);
                mRestoredWithoutUids, null);
    }

    private void dumpPackagePreferencesLocked(PrintWriter pw, String prefix,
            @NonNull NotificationManagerService.DumpFilter filter,
            ArrayMap<String, PackagePreferences> packagePreferences) {
            ArrayMap<String, PackagePreferences> packagePreferences,
            ArrayMap<Pair<Integer, String>, Boolean> packagePermissions) {
        // Used for tracking which package preferences we've seen already for notification
        // permission reasons; after handling packages with local preferences, we'll want to dump
        // the ones with notification permissions set but not local prefs.
        Set<Pair<Integer, String>> pkgsWithPermissionsToHandle = null;
        if (packagePermissions != null) {
            pkgsWithPermissionsToHandle = packagePermissions.keySet();
        }
        final int N = packagePreferences.size();
        for (int i = 0; i < N; i++) {
            final PackagePreferences r = packagePreferences.valueAt(i);
@@ -1966,9 +1976,21 @@ public class PreferencesHelper implements RankingConfig {
                pw.print(" (");
                pw.print(r.uid == UNKNOWN_UID ? "UNKNOWN_UID" : Integer.toString(r.uid));
                pw.print(')');
                if (!mPermissionHelper.isMigrationEnabled() && r.importance != DEFAULT_IMPORTANCE) {
                if (!mPermissionHelper.isMigrationEnabled()) {
                    if (r.importance != DEFAULT_IMPORTANCE) {
                        pw.print(" importance=");
                        pw.print(NotificationListenerService.Ranking.importanceToString(
                                r.importance));
                    }
                } else {
                    Pair<Integer, String> key = new Pair<>(r.uid, r.pkg);
                    if (packagePermissions != null && pkgsWithPermissionsToHandle.contains(key)) {
                        pw.print(" importance=");
                    pw.print(NotificationListenerService.Ranking.importanceToString(r.importance));
                        pw.print(NotificationListenerService.Ranking.importanceToString(
                                packagePermissions.get(key)
                                        ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE));
                        pkgsWithPermissionsToHandle.remove(key);
                    }
                }
                if (r.priority != DEFAULT_PRIORITY) {
                    pw.print(" priority=");
@@ -2007,11 +2029,34 @@ public class PreferencesHelper implements RankingConfig {
                }
            }
        }
        // Handle any remaining packages with permissions
        if (mPermissionHelper.isMigrationEnabled() && pkgsWithPermissionsToHandle != null) {
            for (Pair<Integer, String> p : pkgsWithPermissionsToHandle) {
                // p.first is the uid of this package; p.second is the package name
                if (filter.matches(p.second)) {
                    pw.print(prefix);
                    pw.print("  AppSettings: ");
                    pw.print(p.second);
                    pw.print(" (");
                    pw.print(p.first == UNKNOWN_UID ? "UNKNOWN_UID" : Integer.toString(p.first));
                    pw.print(')');
                    pw.print(" importance=");
                    pw.print(NotificationListenerService.Ranking.importanceToString(
                            packagePermissions.get(p) ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE));
                }
            }
        }
    }

    private static void dumpPackagePreferencesLocked(ProtoOutputStream proto, long fieldId,
    private void dumpPackagePreferencesLocked(ProtoOutputStream proto, long fieldId,
            @NonNull NotificationManagerService.DumpFilter filter,
            ArrayMap<String, PackagePreferences> packagePreferences) {
            ArrayMap<String, PackagePreferences> packagePreferences,
            ArrayMap<Pair<Integer, String>, Boolean> packagePermissions) {
        Set<Pair<Integer, String>> pkgsWithPermissionsToHandle = null;
        if (packagePermissions != null) {
            pkgsWithPermissionsToHandle = packagePermissions.keySet();
        }

        final int N = packagePreferences.size();
        long fToken;
        for (int i = 0; i < N; i++) {
@@ -2021,7 +2066,16 @@ public class PreferencesHelper implements RankingConfig {

                proto.write(RankingHelperProto.RecordProto.PACKAGE, r.pkg);
                proto.write(RankingHelperProto.RecordProto.UID, r.uid);
                if (mPermissionHelper.isMigrationEnabled()) {
                    Pair<Integer, String> key = new Pair<>(r.uid, r.pkg);
                    if (packagePermissions != null && pkgsWithPermissionsToHandle.contains(key)) {
                        proto.write(RankingHelperProto.RecordProto.IMPORTANCE,
                                packagePermissions.get(key) ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE);
                        pkgsWithPermissionsToHandle.remove(key);
                    }
                } else {
                    proto.write(RankingHelperProto.RecordProto.IMPORTANCE, r.importance);
                }
                proto.write(RankingHelperProto.RecordProto.PRIORITY, r.priority);
                proto.write(RankingHelperProto.RecordProto.VISIBILITY, r.visibility);
                proto.write(RankingHelperProto.RecordProto.SHOW_BADGE, r.showBadge);
@@ -2036,28 +2090,82 @@ public class PreferencesHelper implements RankingConfig {
                proto.end(fToken);
            }
        }

        if (mPermissionHelper.isMigrationEnabled() && pkgsWithPermissionsToHandle != null) {
            for (Pair<Integer, String> p : pkgsWithPermissionsToHandle) {
                if (filter.matches(p.second)) {
                    fToken = proto.start(fieldId);
                    proto.write(RankingHelperProto.RecordProto.PACKAGE, p.second);
                    proto.write(RankingHelperProto.RecordProto.UID, p.first);
                    proto.write(RankingHelperProto.RecordProto.IMPORTANCE,
                            packagePermissions.get(p) ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE);
                    proto.end(fToken);
                }
            }
        }
    }

    /**
     * Fills out {@link PackageNotificationPreferences} proto and wraps it in a {@link StatsEvent}.
     */
    public void pullPackagePreferencesStats(List<StatsEvent> events) {
    public void pullPackagePreferencesStats(List<StatsEvent> events,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        Set<Pair<Integer, String>> pkgsWithPermissionsToHandle = null;
        if (pkgPermissions != null) {
            pkgsWithPermissionsToHandle = pkgPermissions.keySet();
        }
        int pulledEvents = 0;
        synchronized (mPackagePreferences) {
            for (int i = 0; i < mPackagePreferences.size(); i++) {
                if (i > NOTIFICATION_PREFERENCES_PULL_LIMIT) {
                if (pulledEvents > NOTIFICATION_PREFERENCES_PULL_LIMIT) {
                    break;
                }
                pulledEvents++;
                SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder()
                        .setAtomId(PACKAGE_NOTIFICATION_PREFERENCES);
                final PackagePreferences r = mPackagePreferences.valueAt(i);
                event.writeInt(r.uid);
                event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
                if (mPermissionHelper.isMigrationEnabled()) {
                    // Even if this package's data is not present, we need to write something;
                    // so default to IMPORTANCE_NONE, since if PM doesn't know about the package
                    // for some reason, notifications are not allowed.
                    int importance = IMPORTANCE_NONE;
                    Pair<Integer, String> key = new Pair<>(r.uid, r.pkg);
                    if (pkgPermissions != null && pkgsWithPermissionsToHandle.contains(key)) {
                        importance = pkgPermissions.get(key) ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE;
                        pkgsWithPermissionsToHandle.remove(key);
                    }
                    event.writeInt(importance);
                } else {
                    event.writeInt(r.importance);
                }
                event.writeInt(r.visibility);
                event.writeInt(r.lockedAppFields);
                events.add(event.build());
            }
        }

        // handle remaining packages with PackageManager permissions but not local settings
        if (mPermissionHelper.isMigrationEnabled() && pkgPermissions != null) {
            for (Pair<Integer, String> p : pkgsWithPermissionsToHandle) {
                if (pulledEvents > NOTIFICATION_PREFERENCES_PULL_LIMIT) {
                    break;
                }
                pulledEvents++;
                SysUiStatsEvent.Builder event = mStatsEventBuilderFactory.newBuilder()
                        .setAtomId(PACKAGE_NOTIFICATION_PREFERENCES);
                event.writeInt(p.first);
                event.addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
                event.writeInt(pkgPermissions.get(p) ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE);

                // fill out the rest of the fields with default values so as not to confuse the
                // builder
                event.writeInt(DEFAULT_VISIBILITY);
                event.writeInt(DEFAULT_LOCKED_APP_FIELDS);
                events.add(event.build());
            }
        }
    }

    /**
@@ -2126,7 +2234,8 @@ public class PreferencesHelper implements RankingConfig {
        }
    }

    public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) {
    public JSONObject dumpJson(NotificationManagerService.DumpFilter filter,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        JSONObject ranking = new JSONObject();
        JSONArray PackagePreferencess = new JSONArray();
        try {
@@ -2134,6 +2243,13 @@ public class PreferencesHelper implements RankingConfig {
        } catch (JSONException e) {
            // pass
        }

        // Track data that we've handled from the permissions-based list
        Set<Pair<Integer, String>> pkgsWithPermissionsToHandle = null;
        if (pkgPermissions != null) {
            pkgsWithPermissionsToHandle = pkgPermissions.keySet();
        }

        synchronized (mPackagePreferences) {
            final int N = mPackagePreferences.size();
            for (int i = 0; i < N; i++) {
@@ -2143,11 +2259,23 @@ public class PreferencesHelper implements RankingConfig {
                    try {
                        PackagePreferences.put("userId", UserHandle.getUserId(r.uid));
                        PackagePreferences.put("packageName", r.pkg);
                        if (mPermissionHelper.isMigrationEnabled()) {
                            Pair<Integer, String> key = new Pair<>(r.uid, r.pkg);
                            if (pkgPermissions != null
                                    && pkgsWithPermissionsToHandle.contains(key)) {
                                PackagePreferences.put("importance",
                                        NotificationListenerService.Ranking.importanceToString(
                                                pkgPermissions.get(key)
                                                        ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE));
                                pkgsWithPermissionsToHandle.remove(key);
                            }
                        } else {
                            if (r.importance != DEFAULT_IMPORTANCE) {
                                PackagePreferences.put("importance",
                                        NotificationListenerService.Ranking.importanceToString(
                                                r.importance));
                            }
                        }
                        if (r.priority != DEFAULT_PRIORITY) {
                            PackagePreferences.put("priority",
                                    Notification.priorityToString(r.priority));
@@ -2176,6 +2304,27 @@ public class PreferencesHelper implements RankingConfig {
                }
            }
        }

        // handle packages for which there are permissions but no local settings
        if (mPermissionHelper.isMigrationEnabled() && pkgsWithPermissionsToHandle != null) {
            for (Pair<Integer, String> p : pkgsWithPermissionsToHandle) {
                if (filter == null || filter.matches(p.second)) {
                    JSONObject PackagePreferences = new JSONObject();
                    try {
                        PackagePreferences.put("userId", UserHandle.getUserId(p.first));
                        PackagePreferences.put("packageName", p.second);
                        PackagePreferences.put("importance",
                                NotificationListenerService.Ranking.importanceToString(
                                        pkgPermissions.get(p)
                                                ? IMPORTANCE_DEFAULT : IMPORTANCE_NONE));
                    } catch (JSONException e) {
                        // pass
                    }
                    PackagePreferencess.put(PackagePreferences);
                }
            }
        }

        try {
            ranking.put("PackagePreferencess", PackagePreferencess);
        } catch (JSONException e) {
@@ -2193,9 +2342,11 @@ public class PreferencesHelper implements RankingConfig {
     * @param filter
     * @return
     */
    public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) {
    public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter,
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        JSONArray bans = new JSONArray();
        Map<Integer, String> packageBans = getPackageBans();
        Map<Integer, String> packageBans = mPermissionHelper.isMigrationEnabled()
                ? getPermissionBasedPackageBans(pkgPermissions) : getPackageBans();
        for (Map.Entry<Integer, String> ban : packageBans.entrySet()) {
            final int userId = UserHandle.getUserId(ban.getKey());
            final String packageName = ban.getValue();
@@ -2228,6 +2379,21 @@ public class PreferencesHelper implements RankingConfig {
        }
    }

    // Same functionality as getPackageBans by extracting the set of packages from the provided
    // map that are disallowed from sending notifications.
    protected Map<Integer, String> getPermissionBasedPackageBans(
            ArrayMap<Pair<Integer, String>, Boolean> pkgPermissions) {
        ArrayMap<Integer, String> packageBans = new ArrayMap<>();
        if (pkgPermissions != null) {
            for (Pair<Integer, String> p : pkgPermissions.keySet()) {
                if (!pkgPermissions.get(p)) {
                    packageBans.put(p.first, p.second);
                }
            }
        }
        return packageBans;
    }

    /**
     * Dump only the channel information as structured JSON for the stats collector.
     *
+6 −0
Original line number Diff line number Diff line
@@ -8507,4 +8507,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
                r.getSbn().getId(), r.getSbn().getTag(), r, false)).isTrue();
    }

    @Test
    public void testGetAllUsersNotificationPermissions_migrationNotEnabled() {
        // make sure we don't bother if the migration is not enabled
        assertThat(mService.getAllUsersNotificationPermissions()).isNull();
    }
}
+34 −3
Original line number Diff line number Diff line
@@ -20,9 +20,7 @@ import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.app.PendingIntent.FLAG_MUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
import static android.content.pm.PackageManager.FEATURE_WATCH;
@@ -38,6 +36,7 @@ import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -84,6 +83,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutServiceInternal;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.session.MediaSession;
@@ -105,8 +105,10 @@ import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.testing.TestablePermissions;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Pair;

import androidx.test.InstrumentationRegistry;

@@ -128,7 +130,6 @@ import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.WindowManagerInternal;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -812,4 +813,34 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase {
        verify(mUsageStats, never()).registerBlocked(any());
        verify(mUsageStats).registerPostedByApp(any());
    }

    @Test
    public void testGetAllUsersNotificationPermissions() {
        // In this case, there are multiple users each with notification permissions (and also,
        // for good measure, some without).
        // make sure the collection returned contains info for all of them
        final List<UserInfo> userInfos = new ArrayList<>();
        userInfos.add(new UserInfo(0, "user0", 0));
        userInfos.add(new UserInfo(1, "user1", 0));
        userInfos.add(new UserInfo(2, "user2", 0));
        when(mUm.getUsers()).thenReturn(userInfos);

        // construct the permissions for each of them
        ArrayMap<Pair<Integer, String>, Boolean> permissions0 = new ArrayMap<>(),
                permissions1 = new ArrayMap<>();
        permissions0.put(new Pair<>(10, "package1"), true);
        permissions0.put(new Pair<>(20, "package2"), false);
        permissions1.put(new Pair<>(11, "package1"), false);
        permissions1.put(new Pair<>(21, "package2"), true);
        when(mPermissionHelper.getNotificationPermissionValues(0)).thenReturn(permissions0);
        when(mPermissionHelper.getNotificationPermissionValues(1)).thenReturn(permissions1);
        when(mPermissionHelper.getNotificationPermissionValues(2)).thenReturn(new ArrayMap<>());

        ArrayMap<Pair<Integer, String>, Boolean> combinedPermissions =
                mService.getAllUsersNotificationPermissions();
        assertTrue(combinedPermissions.get(new Pair<>(10, "package1")));
        assertFalse(combinedPermissions.get(new Pair<>(20, "package2")));
        assertFalse(combinedPermissions.get(new Pair<>(11, "package1")));
        assertTrue(combinedPermissions.get(new Pair<>(21, "package2")));
    }
}
+496 −3

File changed.

Preview size limit exceeded, changes collapsed.