Distinguish the profile of DND-bypassing apps

Bug: 353273192
Test: atest ZenModeAppsLinkPreferenceControllerTest ZenModesSummaryHelperTest
Flag: android.app.modes_ui
Change-Id: I31d8836dbba38d04c9ab3b3180025cb8ddcfbe6d
This commit is contained in:
Matías Hernández
2024-07-15 20:38:51 +02:00
parent 2db5d1618f
commit da3ae255e3
6 changed files with 194 additions and 86 deletions

View File

@@ -19,28 +19,32 @@ package com.android.settings.notification.modes;
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
import static android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.ArraySet;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.core.text.BidiFormatter;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Preference with a link and summary about what apps can break through the mode
@@ -51,12 +55,21 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
private final ZenModeSummaryHelper mSummaryHelper;
private final ApplicationsState mApplicationsState;
private final UserManager mUserManager;
private ApplicationsState.Session mAppSession;
private final ZenHelperBackend mHelperBackend;
private ZenMode mZenMode;
private Preference mPreference;
private final Fragment mHost;
ZenModeAppsLinkPreferenceController(Context context, String key, Fragment host,
ZenModesBackend backend, ZenHelperBackend helperBackend) {
this(context, key, host,
ApplicationsState.getInstance((Application) context.getApplicationContext()),
backend, helperBackend);
}
@VisibleForTesting
ZenModeAppsLinkPreferenceController(Context context, String key, Fragment host,
ApplicationsState applicationsState, ZenModesBackend backend,
ZenHelperBackend helperBackend) {
@@ -64,6 +77,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
mSummaryHelper = new ZenModeSummaryHelper(mContext, helperBackend);
mHelperBackend = helperBackend;
mApplicationsState = applicationsState;
mUserManager = context.getSystemService(UserManager.class);
mHost = host;
}
@@ -90,10 +104,10 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
if (mApplicationsState != null && mHost != null) {
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, mHost.getLifecycle());
}
triggerUpdateAppsBypassingDndSummaryText();
triggerUpdateAppsBypassingDnd();
}
private void triggerUpdateAppsBypassingDndSummaryText() {
private void triggerUpdateAppsBypassingDnd() {
if (mAppSession == null) {
return;
}
@@ -108,31 +122,28 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
mAppSession.rebuild(filter, ApplicationsState.ALPHA_COMPARATOR, false);
}
private void updateAppsBypassingDndSummaryText(List<ApplicationsState.AppEntry> apps) {
Set<String> appNames = getAppsBypassingDnd(apps);
mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, appNames));
private void displayAppsBypassingDnd(List<AppEntry> allApps) {
ImmutableList<AppEntry> apps = getAppsBypassingDndSortedByName(allApps);
mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, apps));
}
@VisibleForTesting
ArraySet<String> getAppsBypassingDnd(@NonNull List<ApplicationsState.AppEntry> apps) {
ArraySet<String> appsBypassingDnd = new ArraySet<>();
ImmutableList<AppEntry> getAppsBypassingDndSortedByName(@NonNull List<AppEntry> allApps) {
Multimap<Integer, String> packagesBypassingDnd = HashMultimap.create();
for (UserHandle userHandle : mUserManager.getUserProfiles()) {
packagesBypassingDnd.putAll(userHandle.getIdentifier(),
mHelperBackend.getPackagesBypassingDnd(userHandle.getIdentifier(),
/* includeConversationChannels= */ false));
}
Map<String, String> pkgLabelMap = new HashMap<String, String>();
for (ApplicationsState.AppEntry entry : apps) {
if (entry.info != null) {
pkgLabelMap.put(entry.info.packageName, entry.label);
}
}
for (String pkg : mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(),
/* includeConversationChannels= */ false)) {
// Settings may hide some packages from the user, so if they're not present here
// we skip displaying them, even if they bypass dnd.
if (pkgLabelMap.get(pkg) == null) {
continue;
}
appsBypassingDnd.add(BidiFormatter.getInstance().unicodeWrap(pkgLabelMap.get(pkg)));
}
return appsBypassingDnd;
return ImmutableList.copyOf(
allApps.stream()
.filter(app -> packagesBypassingDnd.containsEntry(
UserHandle.getUserId(app.info.uid), app.info.packageName))
.sorted(Comparator.comparing((AppEntry app) -> app.label)
.thenComparing(app -> UserHandle.getUserId(app.info.uid)))
.toList());
}
@VisibleForTesting
@@ -145,12 +156,12 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
@Override
public void onPackageListChanged() {
triggerUpdateAppsBypassingDndSummaryText();
triggerUpdateAppsBypassingDnd();
}
@Override
public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
updateAppsBypassingDndSummaryText(apps);
displayAppsBypassingDnd(apps);
}
@Override
@@ -171,7 +182,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
@Override
public void onLoadEntriesCompleted() {
triggerUpdateAppsBypassingDndSummaryText();
triggerUpdateAppsBypassingDnd();
}
};
}