Merge "Distinguish the profile of DND-bypassing apps" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
d133ec93ab
@@ -9357,6 +9357,8 @@
|
|||||||
other {{app_1}, {app_2}, and # more can interrupt}
|
other {{app_1}, {app_2}, and # more can interrupt}
|
||||||
}
|
}
|
||||||
</string>
|
</string>
|
||||||
|
<!-- Priority Modes: Entry in the "apps that can bypass DND" list that corresponds to a work profile app (e.g. "Chrome (Work)" [CHAR LIMIT=15]. -->
|
||||||
|
<string name="zen_mode_apps_work_app"><xliff:g id="app_label" example="Chrome">%s</xliff:g> (Work)</string>
|
||||||
<!-- Text displayed (for a brief time) while the list of bypassing apps is being fetched. Will be replaced by a zen_mode_apps_subtext. [CHAR_LIMIT=60] -->
|
<!-- Text displayed (for a brief time) while the list of bypassing apps is being fetched. Will be replaced by a zen_mode_apps_subtext. [CHAR_LIMIT=60] -->
|
||||||
<string name="zen_mode_apps_calculating">Calculating\u2026</string>
|
<string name="zen_mode_apps_calculating">Calculating\u2026</string>
|
||||||
|
|
||||||
|
@@ -19,28 +19,32 @@ package com.android.settings.notification.modes;
|
|||||||
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
|
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
|
||||||
import static android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID;
|
import static android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArraySet;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.core.text.BidiFormatter;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
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.ZenMode;
|
||||||
import com.android.settingslib.notification.modes.ZenModesBackend;
|
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.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
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
|
* 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 ZenModeSummaryHelper mSummaryHelper;
|
||||||
private final ApplicationsState mApplicationsState;
|
private final ApplicationsState mApplicationsState;
|
||||||
|
private final UserManager mUserManager;
|
||||||
private ApplicationsState.Session mAppSession;
|
private ApplicationsState.Session mAppSession;
|
||||||
private final ZenHelperBackend mHelperBackend;
|
private final ZenHelperBackend mHelperBackend;
|
||||||
private ZenMode mZenMode;
|
private ZenMode mZenMode;
|
||||||
private Preference mPreference;
|
private Preference mPreference;
|
||||||
private final Fragment mHost;
|
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,
|
ZenModeAppsLinkPreferenceController(Context context, String key, Fragment host,
|
||||||
ApplicationsState applicationsState, ZenModesBackend backend,
|
ApplicationsState applicationsState, ZenModesBackend backend,
|
||||||
ZenHelperBackend helperBackend) {
|
ZenHelperBackend helperBackend) {
|
||||||
@@ -64,6 +77,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
|||||||
mSummaryHelper = new ZenModeSummaryHelper(mContext, helperBackend);
|
mSummaryHelper = new ZenModeSummaryHelper(mContext, helperBackend);
|
||||||
mHelperBackend = helperBackend;
|
mHelperBackend = helperBackend;
|
||||||
mApplicationsState = applicationsState;
|
mApplicationsState = applicationsState;
|
||||||
|
mUserManager = context.getSystemService(UserManager.class);
|
||||||
mHost = host;
|
mHost = host;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,10 +104,10 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
|||||||
if (mApplicationsState != null && mHost != null) {
|
if (mApplicationsState != null && mHost != null) {
|
||||||
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, mHost.getLifecycle());
|
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks, mHost.getLifecycle());
|
||||||
}
|
}
|
||||||
triggerUpdateAppsBypassingDndSummaryText();
|
triggerUpdateAppsBypassingDnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void triggerUpdateAppsBypassingDndSummaryText() {
|
private void triggerUpdateAppsBypassingDnd() {
|
||||||
if (mAppSession == null) {
|
if (mAppSession == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -108,31 +122,28 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
|||||||
mAppSession.rebuild(filter, ApplicationsState.ALPHA_COMPARATOR, false);
|
mAppSession.rebuild(filter, ApplicationsState.ALPHA_COMPARATOR, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAppsBypassingDndSummaryText(List<ApplicationsState.AppEntry> apps) {
|
private void displayAppsBypassingDnd(List<AppEntry> allApps) {
|
||||||
Set<String> appNames = getAppsBypassingDnd(apps);
|
ImmutableList<AppEntry> apps = getAppsBypassingDndSortedByName(allApps);
|
||||||
mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, appNames));
|
|
||||||
|
mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, apps));
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
ArraySet<String> getAppsBypassingDnd(@NonNull List<ApplicationsState.AppEntry> apps) {
|
ImmutableList<AppEntry> getAppsBypassingDndSortedByName(@NonNull List<AppEntry> allApps) {
|
||||||
ArraySet<String> appsBypassingDnd = new ArraySet<>();
|
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>();
|
return ImmutableList.copyOf(
|
||||||
for (ApplicationsState.AppEntry entry : apps) {
|
allApps.stream()
|
||||||
if (entry.info != null) {
|
.filter(app -> packagesBypassingDnd.containsEntry(
|
||||||
pkgLabelMap.put(entry.info.packageName, entry.label);
|
UserHandle.getUserId(app.info.uid), app.info.packageName))
|
||||||
}
|
.sorted(Comparator.comparing((AppEntry app) -> app.label)
|
||||||
}
|
.thenComparing(app -> UserHandle.getUserId(app.info.uid)))
|
||||||
for (String pkg : mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(),
|
.toList());
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -145,12 +156,12 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPackageListChanged() {
|
public void onPackageListChanged() {
|
||||||
triggerUpdateAppsBypassingDndSummaryText();
|
triggerUpdateAppsBypassingDnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
|
public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
|
||||||
updateAppsBypassingDndSummaryText(apps);
|
displayAppsBypassingDnd(apps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -171,7 +182,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadEntriesCompleted() {
|
public void onLoadEntriesCompleted() {
|
||||||
triggerUpdateAppsBypassingDndSummaryText();
|
triggerUpdateAppsBypassingDnd();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
package com.android.settings.notification.modes;
|
package com.android.settings.notification.modes;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Application;
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -29,7 +28,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.core.view.MenuProvider;
|
import androidx.core.view.MenuProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
import com.android.settingslib.notification.modes.ZenMode;
|
import com.android.settingslib.notification.modes.ZenMode;
|
||||||
|
|
||||||
@@ -58,9 +56,7 @@ public class ZenModeFragment extends ZenModeFragmentBase {
|
|||||||
prefControllers.add(new ZenModePeopleLinkPreferenceController(
|
prefControllers.add(new ZenModePeopleLinkPreferenceController(
|
||||||
context, "zen_mode_people", mHelperBackend));
|
context, "zen_mode_people", mHelperBackend));
|
||||||
prefControllers.add(new ZenModeAppsLinkPreferenceController(
|
prefControllers.add(new ZenModeAppsLinkPreferenceController(
|
||||||
context, "zen_mode_apps", this,
|
context, "zen_mode_apps", this, mBackend, mHelperBackend));
|
||||||
ApplicationsState.getInstance((Application) context.getApplicationContext()),
|
|
||||||
mBackend, mHelperBackend));
|
|
||||||
prefControllers.add(new ZenModeOtherLinkPreferenceController(
|
prefControllers.add(new ZenModeOtherLinkPreferenceController(
|
||||||
context, "zen_other_settings", mHelperBackend));
|
context, "zen_other_settings", mHelperBackend));
|
||||||
prefControllers.add(new ZenModeDisplayLinkPreferenceController(
|
prefControllers.add(new ZenModeDisplayLinkPreferenceController(
|
||||||
|
@@ -49,17 +49,18 @@ import android.util.ArrayMap;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
import androidx.core.text.BidiFormatter;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
import com.android.settingslib.notification.modes.ZenMode;
|
import com.android.settingslib.notification.modes.ZenMode;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
class ZenModeSummaryHelper {
|
class ZenModeSummaryHelper {
|
||||||
@@ -412,7 +413,7 @@ class ZenModeSummaryHelper {
|
|||||||
* on the given mode and provided set of apps.
|
* on the given mode and provided set of apps.
|
||||||
*/
|
*/
|
||||||
public @NonNull String getAppsSummary(@NonNull ZenMode zenMode,
|
public @NonNull String getAppsSummary(@NonNull ZenMode zenMode,
|
||||||
@Nullable Set<String> appsBypassing) {
|
@Nullable List<AppEntry> appsBypassing) {
|
||||||
if (zenMode.getPolicy().getAllowedChannels() == ZenPolicy.CHANNEL_POLICY_PRIORITY) {
|
if (zenMode.getPolicy().getAllowedChannels() == ZenPolicy.CHANNEL_POLICY_PRIORITY) {
|
||||||
return formatAppsList(appsBypassing);
|
return formatAppsList(appsBypassing);
|
||||||
} else if (zenMode.getPolicy().getAllowedChannels() == ZenPolicy.CHANNEL_POLICY_NONE) {
|
} else if (zenMode.getPolicy().getAllowedChannels() == ZenPolicy.CHANNEL_POLICY_NONE) {
|
||||||
@@ -424,28 +425,34 @@ class ZenModeSummaryHelper {
|
|||||||
/**
|
/**
|
||||||
* Generates a formatted string declaring which apps can interrupt in the style of
|
* Generates a formatted string declaring which apps can interrupt in the style of
|
||||||
* "App, App2, and 4 more can interrupt."
|
* "App, App2, and 4 more can interrupt."
|
||||||
* Apps selected for explicit mention are selected in order from the provided set sorted
|
* Apps selected for explicit mention are picked in order from the provided list.
|
||||||
* alphabetically.
|
|
||||||
*/
|
*/
|
||||||
public @NonNull String formatAppsList(@Nullable Set<String> appsBypassingDnd) {
|
@VisibleForTesting
|
||||||
|
public @NonNull String formatAppsList(@Nullable List<AppEntry> appsBypassingDnd) {
|
||||||
if (appsBypassingDnd == null) {
|
if (appsBypassingDnd == null) {
|
||||||
return mContext.getResources().getString(R.string.zen_mode_apps_priority_apps);
|
return mContext.getResources().getString(R.string.zen_mode_apps_priority_apps);
|
||||||
}
|
}
|
||||||
final int numAppsBypassingDnd = appsBypassingDnd.size();
|
List<String> appNames = appsBypassingDnd.stream().limit(3)
|
||||||
String[] appsBypassingDndArr = appsBypassingDnd.toArray(new String[numAppsBypassingDnd]);
|
.map(app -> {
|
||||||
// Sorts the provided apps alphabetically.
|
String appName = BidiFormatter.getInstance().unicodeWrap(app.label);
|
||||||
Arrays.sort(appsBypassingDndArr);
|
if (app.isManagedProfile()) {
|
||||||
|
appName = mContext.getString(R.string.zen_mode_apps_work_app, appName);
|
||||||
|
}
|
||||||
|
return appName;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
|
||||||
MessageFormat msgFormat = new MessageFormat(
|
MessageFormat msgFormat = new MessageFormat(
|
||||||
mContext.getString(R.string.zen_mode_apps_subtext),
|
mContext.getString(R.string.zen_mode_apps_subtext),
|
||||||
Locale.getDefault());
|
Locale.getDefault());
|
||||||
Map<String, Object> args = new HashMap<>();
|
Map<String, Object> args = new HashMap<>();
|
||||||
args.put("count", numAppsBypassingDnd);
|
args.put("count", appsBypassingDnd.size());
|
||||||
if (numAppsBypassingDnd >= 1) {
|
if (appNames.size() >= 1) {
|
||||||
args.put("app_1", appsBypassingDndArr[0]);
|
args.put("app_1", appNames.get(0));
|
||||||
if (numAppsBypassingDnd >= 2) {
|
if (appNames.size() >= 2) {
|
||||||
args.put("app_2", appsBypassingDndArr[1]);
|
args.put("app_2", appNames.get(1));
|
||||||
if (numAppsBypassingDnd == 3) {
|
if (appNames.size() == 3) {
|
||||||
args.put("app_3", appsBypassingDndArr[2]);
|
args.put("app_3", appNames.get(2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,17 +22,22 @@ import static android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
|
|
||||||
import android.app.Flags;
|
import android.app.Flags;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.platform.test.annotations.EnableFlags;
|
import android.platform.test.annotations.EnableFlags;
|
||||||
import android.platform.test.flag.junit.SetFlagsRule;
|
import android.platform.test.flag.junit.SetFlagsRule;
|
||||||
import android.service.notification.ZenPolicy;
|
import android.service.notification.ZenPolicy;
|
||||||
@@ -41,6 +46,7 @@ import androidx.fragment.app.Fragment;
|
|||||||
|
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settingslib.notification.modes.TestModeBuilder;
|
import com.android.settingslib.notification.modes.TestModeBuilder;
|
||||||
import com.android.settingslib.notification.modes.ZenMode;
|
import com.android.settingslib.notification.modes.ZenMode;
|
||||||
@@ -58,6 +64,7 @@ import org.robolectric.RuntimeEnvironment;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@EnableFlags(Flags.FLAG_MODES_UI)
|
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||||
@@ -90,13 +97,13 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
|||||||
mZenModesBackend, mHelperBackend);
|
mZenModesBackend, mHelperBackend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ApplicationsState.AppEntry createAppEntry(String packageName, String label) {
|
private AppEntry createAppEntry(String packageName, int userId) {
|
||||||
ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
|
ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||||
entry.info = new ApplicationInfo();
|
applicationInfo.packageName = packageName;
|
||||||
entry.info.packageName = packageName;
|
applicationInfo.uid = UserHandle.getUid(userId, new Random().nextInt(100));
|
||||||
entry.label = label;
|
AppEntry appEntry = new AppEntry(mContext, applicationInfo, 1);
|
||||||
entry.info.uid = 0;
|
appEntry.label = packageName;
|
||||||
return entry;
|
return appEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZenMode createPriorityChannelsZenMode() {
|
private ZenMode createPriorityChannelsZenMode() {
|
||||||
@@ -137,14 +144,52 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAppsBypassingDnd() {
|
public void testGetAppsBypassingDnd() {
|
||||||
ApplicationsState.AppEntry entry = createAppEntry("test", "testLabel");
|
ApplicationsState.AppEntry app1 = createAppEntry("app1", mContext.getUserId());
|
||||||
ApplicationsState.AppEntry entryConv = createAppEntry("test_conv", "test_convLabel");
|
ApplicationsState.AppEntry app2 = createAppEntry("app2", mContext.getUserId());
|
||||||
List<ApplicationsState.AppEntry> appEntries = List.of(entry, entryConv);
|
List<ApplicationsState.AppEntry> allApps = List.of(app1, app2);
|
||||||
|
|
||||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(),
|
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(),
|
||||||
false)).thenReturn(List.of("test"));
|
false)).thenReturn(List.of("app1"));
|
||||||
|
|
||||||
assertThat(mController.getAppsBypassingDnd(appEntries)).containsExactly("testLabel");
|
assertThat(mController.getAppsBypassingDndSortedByName(allApps)).containsExactly(app1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAppsBypassingDnd_sortsByName() {
|
||||||
|
ApplicationsState.AppEntry appC = createAppEntry("C", mContext.getUserId());
|
||||||
|
ApplicationsState.AppEntry appA = createAppEntry("A", mContext.getUserId());
|
||||||
|
ApplicationsState.AppEntry appB = createAppEntry("B", mContext.getUserId());
|
||||||
|
List<ApplicationsState.AppEntry> allApps = List.of(appC, appA, appB);
|
||||||
|
|
||||||
|
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId()), anyBoolean()))
|
||||||
|
.thenReturn(List.of("B", "C", "A"));
|
||||||
|
|
||||||
|
assertThat(mController.getAppsBypassingDndSortedByName(allApps))
|
||||||
|
.containsExactly(appA, appB, appC).inOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAppsBypassingDnd_withWorkProfile_includesProfileAndSorts() {
|
||||||
|
UserInfo workProfile = new UserInfo(10, "Work Profile", 0);
|
||||||
|
workProfile.userType = UserManager.USER_TYPE_PROFILE_MANAGED;
|
||||||
|
UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||||
|
shadowOf(userManager).addProfile(mContext.getUserId(), 10, workProfile);
|
||||||
|
|
||||||
|
ApplicationsState.AppEntry personalCopy = createAppEntry("app", mContext.getUserId());
|
||||||
|
ApplicationsState.AppEntry workCopy = createAppEntry("app", 10);
|
||||||
|
ApplicationsState.AppEntry otherPersonal = createAppEntry("p2", mContext.getUserId());
|
||||||
|
ApplicationsState.AppEntry otherWork = createAppEntry("w2", 10);
|
||||||
|
List<ApplicationsState.AppEntry> allApps = List.of(workCopy, personalCopy, otherPersonal,
|
||||||
|
otherWork);
|
||||||
|
|
||||||
|
when(mHelperBackend.getPackagesBypassingDnd(eq(mContext.getUserId()), anyBoolean()))
|
||||||
|
.thenReturn(List.of("app", "p2"));
|
||||||
|
when(mHelperBackend.getPackagesBypassingDnd(eq(10), anyBoolean()))
|
||||||
|
.thenReturn(List.of("app"));
|
||||||
|
|
||||||
|
// Personal copy before work copy (names match).
|
||||||
|
assertThat(mController.getAppsBypassingDndSortedByName(allApps))
|
||||||
|
.containsExactly(personalCopy, workCopy, otherPersonal).inOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -156,7 +201,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
|||||||
|
|
||||||
// Create some applications.
|
// Create some applications.
|
||||||
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||||
appEntries.add(createAppEntry("test", "pkgLabel"));
|
appEntries.add(createAppEntry("test", mContext.getUserId()));
|
||||||
|
|
||||||
when(mHelperBackend.getPackagesBypassingDnd(
|
when(mHelperBackend.getPackagesBypassingDnd(
|
||||||
mContext.getUserId(), false))
|
mContext.getUserId(), false))
|
||||||
@@ -170,7 +215,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
|||||||
|
|
||||||
// Manually triggers the callback that will happen on rebuild.
|
// Manually triggers the callback that will happen on rebuild.
|
||||||
mController.mAppSessionCallbacks.onRebuildComplete(appEntries);
|
mController.mAppSessionCallbacks.onRebuildComplete(appEntries);
|
||||||
assertThat(String.valueOf(preference.getSummary())).isEqualTo("pkgLabel can interrupt");
|
assertThat(String.valueOf(preference.getSummary())).isEqualTo("test can interrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -28,10 +28,16 @@ import static android.service.notification.ZenPolicy.VISUAL_EFFECT_LIGHTS;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
|
|
||||||
import android.app.Flags;
|
import android.app.Flags;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.platform.test.annotations.EnableFlags;
|
import android.platform.test.annotations.EnableFlags;
|
||||||
import android.platform.test.flag.junit.SetFlagsRule;
|
import android.platform.test.flag.junit.SetFlagsRule;
|
||||||
import android.service.notification.Condition;
|
import android.service.notification.Condition;
|
||||||
@@ -39,9 +45,12 @@ import android.service.notification.ZenDeviceEffects;
|
|||||||
import android.service.notification.ZenModeConfig;
|
import android.service.notification.ZenModeConfig;
|
||||||
import android.service.notification.ZenPolicy;
|
import android.service.notification.ZenPolicy;
|
||||||
|
|
||||||
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
import com.android.settingslib.notification.modes.TestModeBuilder;
|
import com.android.settingslib.notification.modes.TestModeBuilder;
|
||||||
import com.android.settingslib.notification.modes.ZenMode;
|
import com.android.settingslib.notification.modes.ZenMode;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -50,10 +59,12 @@ import org.mockito.MockitoAnnotations;
|
|||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
public class ZenModesSummaryHelperTest {
|
public class ZenModesSummaryHelperTest {
|
||||||
|
private static final int WORK_PROFILE_ID = 3;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ZenHelperBackend mBackend;
|
private ZenHelperBackend mBackend;
|
||||||
|
|
||||||
@@ -69,6 +80,11 @@ public class ZenModesSummaryHelperTest {
|
|||||||
mContext = RuntimeEnvironment.application;
|
mContext = RuntimeEnvironment.application;
|
||||||
mBackend = new ZenHelperBackend(mContext);
|
mBackend = new ZenHelperBackend(mContext);
|
||||||
mSummaryHelper = new ZenModeSummaryHelper(mContext, mBackend);
|
mSummaryHelper = new ZenModeSummaryHelper(mContext, mBackend);
|
||||||
|
|
||||||
|
UserInfo workProfile = new UserInfo(WORK_PROFILE_ID, "Work Profile", 0);
|
||||||
|
workProfile.userType = UserManager.USER_TYPE_PROFILE_MANAGED;
|
||||||
|
UserManager userManager = mContext.getSystemService(UserManager.class);
|
||||||
|
shadowOf(userManager).addProfile(mContext.getUserId(), WORK_PROFILE_ID, workProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -306,7 +322,7 @@ public class ZenModesSummaryHelperTest {
|
|||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assertThat(mSummaryHelper.getAppsSummary(zenMode, new LinkedHashSet<>())).isEqualTo("None");
|
assertThat(mSummaryHelper.getAppsSummary(zenMode, ImmutableList.of())).isEqualTo("None");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -321,40 +337,58 @@ public class ZenModesSummaryHelperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAppsSummary_formatAppsListEmpty() {
|
public void formatAppsList_listEmpty() {
|
||||||
Set<String> apps = new LinkedHashSet<>();
|
ImmutableList<AppEntry> apps = ImmutableList.of();
|
||||||
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("No apps can interrupt");
|
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("No apps can interrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAppsSummary_formatAppsListSingle() {
|
public void formatAppsList_single() {
|
||||||
Set<String> apps = Set.of("My App");
|
ImmutableList<AppEntry> apps = ImmutableList.of(newAppEntry("My App"));
|
||||||
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App can interrupt");
|
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App can interrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAppsSummary_formatAppsListTwo() {
|
public void formatAppsList_two() {
|
||||||
Set<String> apps = Set.of("My App", "SecondApp");
|
ImmutableList<AppEntry> apps = ImmutableList.of(newAppEntry("My App"),
|
||||||
|
newAppEntry("SecondApp"));
|
||||||
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App and SecondApp "
|
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App and SecondApp "
|
||||||
+ "can interrupt");
|
+ "can interrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAppsSummary_formatAppsListThree() {
|
public void formatAppsList_three() {
|
||||||
Set<String> apps = Set.of("My App", "SecondApp", "ThirdApp");
|
ImmutableList<AppEntry> apps = ImmutableList.of(newAppEntry("My App"),
|
||||||
|
newAppEntry("SecondApp"), newAppEntry("ThirdApp"));
|
||||||
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App, SecondApp, "
|
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App, SecondApp, "
|
||||||
+ "and ThirdApp can interrupt");
|
+ "and ThirdApp can interrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAppsSummary_formatAppsListMany() {
|
public void formatAppsList_many() {
|
||||||
Set<String> apps = Set.of("My App", "SecondApp", "ThirdApp", "FourthApp",
|
ImmutableList<AppEntry> apps = ImmutableList.of(newAppEntry("My App"),
|
||||||
"FifthApp", "SixthApp");
|
newAppEntry("SecondApp"), newAppEntry("ThirdApp"), newAppEntry("FourthApp"),
|
||||||
// Note that apps are selected alphabetically.
|
newAppEntry("FifthApp"), newAppEntry("SixthApp"));
|
||||||
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("FifthApp, FourthApp, "
|
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App, SecondApp, "
|
||||||
+ "and 4 more can interrupt");
|
+ "and 4 more can interrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatAppsList_singleWorkProfile() {
|
||||||
|
ImmutableList<AppEntry> apps = ImmutableList.of(newAppEntry("My App", WORK_PROFILE_ID));
|
||||||
|
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App (Work) can interrupt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatAppsList_mixOfProfiles() {
|
||||||
|
ImmutableList<AppEntry> apps = ImmutableList.of(
|
||||||
|
newAppEntry("My App", mContext.getUserId()),
|
||||||
|
newAppEntry("My App", WORK_PROFILE_ID),
|
||||||
|
newAppEntry("SecondApp", mContext.getUserId()));
|
||||||
|
assertThat(mSummaryHelper.formatAppsList(apps)).isEqualTo("My App, My App (Work), "
|
||||||
|
+ "and SecondApp can interrupt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAppsSummary_priorityApps() {
|
public void getAppsSummary_priorityApps() {
|
||||||
ZenMode zenMode = new TestModeBuilder()
|
ZenMode zenMode = new TestModeBuilder()
|
||||||
@@ -362,13 +396,26 @@ public class ZenModesSummaryHelperTest {
|
|||||||
.allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
|
.allowChannels(ZenPolicy.CHANNEL_POLICY_PRIORITY)
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
Set<String> apps = Set.of("My App", "SecondApp", "ThirdApp", "FourthApp",
|
ImmutableList<AppEntry> apps = ImmutableList.of(newAppEntry("My App"),
|
||||||
"FifthApp", "SixthApp");
|
newAppEntry("SecondApp"), newAppEntry("ThirdApp"), newAppEntry("FourthApp"),
|
||||||
|
newAppEntry("FifthApp"), newAppEntry("SixthApp"));
|
||||||
|
|
||||||
assertThat(mSummaryHelper.getAppsSummary(zenMode, apps)).isEqualTo("FifthApp, FourthApp, "
|
assertThat(mSummaryHelper.getAppsSummary(zenMode, apps)).isEqualTo("My App, SecondApp, "
|
||||||
+ "and 4 more can interrupt");
|
+ "and 4 more can interrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AppEntry newAppEntry(String name) {
|
||||||
|
return newAppEntry(name, mContext.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private AppEntry newAppEntry(String name, int userId) {
|
||||||
|
ApplicationInfo applicationInfo = new ApplicationInfo();
|
||||||
|
applicationInfo.uid = UserHandle.getUid(userId, new Random().nextInt(100));
|
||||||
|
AppEntry appEntry = new AppEntry(mContext, applicationInfo, 1);
|
||||||
|
appEntry.label = name;
|
||||||
|
return appEntry;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@EnableFlags(Flags.FLAG_MODES_UI)
|
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||||
public void getSoundSummary_off_noRules() {
|
public void getSoundSummary_off_noRules() {
|
||||||
|
Reference in New Issue
Block a user