Merge "Fix refresh of "apps that can interrupt" segment" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
e7c670ea27
@@ -49,7 +49,9 @@ public class CircularIconsPreference extends RestrictedPreference {
|
||||
|
||||
private static final float DISABLED_ITEM_ALPHA = 0.3f;
|
||||
|
||||
record LoadedIcons(ImmutableList<Drawable> icons, int extraItems) { }
|
||||
record LoadedIcons(ImmutableList<Drawable> icons, int extraItems) {
|
||||
static final LoadedIcons EMPTY = new LoadedIcons(ImmutableList.of(), 0);
|
||||
}
|
||||
|
||||
private Executor mUiExecutor;
|
||||
|
||||
@@ -126,6 +128,7 @@ public class CircularIconsPreference extends RestrictedPreference {
|
||||
// We know what icons we want, but haven't yet loaded them.
|
||||
if (mIconSet.size() == 0) {
|
||||
container.setVisibility(View.GONE);
|
||||
mLoadedIcons = LoadedIcons.EMPTY;
|
||||
return;
|
||||
}
|
||||
container.setVisibility(View.VISIBLE);
|
||||
@@ -137,7 +140,7 @@ public class CircularIconsPreference extends RestrictedPreference {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
container.getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
startLoadingIcons(container, mIconSet);
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -22,6 +22,8 @@ import static android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID;
|
||||
import android.app.Application;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -49,6 +51,7 @@ import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Preference with a link and summary about what apps can break through the mode
|
||||
@@ -65,24 +68,26 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
||||
private ZenMode mZenMode;
|
||||
private CircularIconsPreference mPreference;
|
||||
private final Fragment mHost;
|
||||
private final Function<ApplicationInfo, Drawable> mAppIconRetriever;
|
||||
|
||||
ZenModeAppsLinkPreferenceController(Context context, String key, Fragment host,
|
||||
ZenModesBackend backend, ZenHelperBackend helperBackend) {
|
||||
this(context, key, host,
|
||||
ApplicationsState.getInstance((Application) context.getApplicationContext()),
|
||||
backend, helperBackend);
|
||||
backend, helperBackend, appInfo -> Utils.getBadgedIcon(context, appInfo));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ZenModeAppsLinkPreferenceController(Context context, String key, Fragment host,
|
||||
ApplicationsState applicationsState, ZenModesBackend backend,
|
||||
ZenHelperBackend helperBackend) {
|
||||
ZenHelperBackend helperBackend, Function<ApplicationInfo, Drawable> appIconRetriever) {
|
||||
super(context, key, backend);
|
||||
mSummaryHelper = new ZenModeSummaryHelper(mContext, helperBackend);
|
||||
mHelperBackend = helperBackend;
|
||||
mApplicationsState = applicationsState;
|
||||
mUserManager = context.getSystemService(UserManager.class);
|
||||
mHost = host;
|
||||
mAppIconRetriever = appIconRetriever;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,13 +110,18 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
||||
if (zenMode.getPolicy().getAllowedChannels() == ZenPolicy.CHANNEL_POLICY_NONE) {
|
||||
mPreference.setSummary(R.string.zen_mode_apps_none_apps);
|
||||
mPreference.displayIcons(CircularIconSet.EMPTY);
|
||||
if (mAppSession != null) {
|
||||
mAppSession.deactivateSession();
|
||||
}
|
||||
} else {
|
||||
if (TextUtils.isEmpty(mPreference.getSummary())) {
|
||||
mPreference.setSummary(R.string.zen_mode_apps_calculating);
|
||||
}
|
||||
if (mApplicationsState != null && mHost != null) {
|
||||
if (mAppSession == null) {
|
||||
mAppSession = mApplicationsState.newSession(mAppSessionCallbacks,
|
||||
mHost.getLifecycle());
|
||||
} else {
|
||||
mAppSession.activateSession();
|
||||
}
|
||||
triggerUpdateAppsBypassingDnd();
|
||||
}
|
||||
@@ -133,12 +143,16 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr
|
||||
}
|
||||
|
||||
private void displayAppsBypassingDnd(List<AppEntry> allApps) {
|
||||
if (mZenMode.getPolicy().getAllowedChannels() == ZenPolicy.CHANNEL_POLICY_NONE) {
|
||||
// Can get this callback when resuming, if we had CHANNEL_POLICY_PRIORITY and just
|
||||
// switched to CHANNEL_POLICY_NONE.
|
||||
return;
|
||||
}
|
||||
|
||||
ImmutableList<AppEntry> apps = getAppsBypassingDndSortedByName(allApps);
|
||||
|
||||
mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, apps));
|
||||
|
||||
mPreference.displayIcons(new CircularIconSet<>(apps,
|
||||
app -> Utils.getBadgedIcon(mContext, app.info)),
|
||||
app -> mAppIconRetriever.apply(app.info)),
|
||||
APP_ENTRY_EQUIVALENCE);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -103,11 +104,12 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
CircularIconSet.sExecutorService = MoreExecutors.newDirectExecutorService();
|
||||
mPreference = new TestableCircularIconsPreference(mContext);
|
||||
|
||||
when(mApplicationsState.newSession(any(), any())).thenReturn(mSession);
|
||||
|
||||
mController = new ZenModeAppsLinkPreferenceController(
|
||||
mContext, "controller_key", mock(Fragment.class), mApplicationsState,
|
||||
mZenModesBackend, mHelperBackend);
|
||||
mZenModesBackend, mHelperBackend,
|
||||
/* appIconRetriever= */ appInfo -> new ColorDrawable());
|
||||
|
||||
// Ensure the preference view is bound & measured (needed to add child ImageViews).
|
||||
View preferenceView = LayoutInflater.from(mContext).inflate(mPreference.getLayoutResource(),
|
||||
@@ -296,6 +298,89 @@ public final class ZenModeAppsLinkPreferenceControllerTest {
|
||||
verify(mSession, times(2)).rebuild(any(), any(), eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_noneToPriority_loadsBypassingAppsAndListensForChanges() {
|
||||
ZenMode zenModeWithNone = new TestModeBuilder()
|
||||
.setZenPolicy(new ZenPolicy.Builder().allowPriorityChannels(false).build())
|
||||
.build();
|
||||
ZenMode zenModeWithPriority = new TestModeBuilder()
|
||||
.setZenPolicy(new ZenPolicy.Builder().allowPriorityChannels(true).build())
|
||||
.build();
|
||||
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(createAppEntry("test", mContext.getUserId()));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(), false))
|
||||
.thenReturn(List.of("test"));
|
||||
|
||||
mController.updateState(mPreference, zenModeWithNone);
|
||||
|
||||
assertThat(mPreference.getLoadedIcons().icons()).hasSize(0);
|
||||
verifyNoMoreInteractions(mApplicationsState);
|
||||
verifyNoMoreInteractions(mSession);
|
||||
|
||||
mController.updateState(mPreference, zenModeWithPriority);
|
||||
|
||||
verify(mApplicationsState).newSession(any(), any());
|
||||
verify(mSession).rebuild(any(), any(), anyBoolean());
|
||||
mController.mAppSessionCallbacks.onRebuildComplete(appEntries);
|
||||
assertThat(mPreference.getLoadedIcons().icons()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_priorityToNone_clearsBypassingAppsAndStopsListening() {
|
||||
ZenMode zenModeWithNone = new TestModeBuilder()
|
||||
.setZenPolicy(new ZenPolicy.Builder().allowPriorityChannels(false).build())
|
||||
.build();
|
||||
ZenMode zenModeWithPriority = new TestModeBuilder()
|
||||
.setZenPolicy(new ZenPolicy.Builder().allowPriorityChannels(true).build())
|
||||
.build();
|
||||
ArrayList<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
|
||||
appEntries.add(createAppEntry("test", mContext.getUserId()));
|
||||
when(mHelperBackend.getPackagesBypassingDnd(mContext.getUserId(), false))
|
||||
.thenReturn(List.of("test"));
|
||||
|
||||
mController.updateState(mPreference, zenModeWithPriority);
|
||||
|
||||
verify(mApplicationsState).newSession(any(), any());
|
||||
verify(mSession).rebuild(any(), any(), anyBoolean());
|
||||
mController.mAppSessionCallbacks.onRebuildComplete(appEntries);
|
||||
assertThat(mPreference.getLoadedIcons().icons()).hasSize(1);
|
||||
|
||||
mController.updateState(mPreference, zenModeWithNone);
|
||||
|
||||
assertThat(mPreference.getLoadedIcons().icons()).hasSize(0);
|
||||
verify(mSession).deactivateSession();
|
||||
verifyNoMoreInteractions(mSession);
|
||||
verifyNoMoreInteractions(mApplicationsState);
|
||||
|
||||
// An errant callback (triggered by onResume and received asynchronously after
|
||||
// updateState()) is ignored.
|
||||
mController.mAppSessionCallbacks.onRebuildComplete(appEntries);
|
||||
|
||||
assertThat(mPreference.getLoadedIcons().icons()).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_priorityToNoneToPriority_restartsListening() {
|
||||
ZenMode zenModeWithNone = new TestModeBuilder()
|
||||
.setZenPolicy(new ZenPolicy.Builder().allowPriorityChannels(false).build())
|
||||
.build();
|
||||
ZenMode zenModeWithPriority = new TestModeBuilder()
|
||||
.setZenPolicy(new ZenPolicy.Builder().allowPriorityChannels(true).build())
|
||||
.build();
|
||||
|
||||
mController.updateState(mPreference, zenModeWithPriority);
|
||||
verify(mApplicationsState).newSession(any(), any());
|
||||
verify(mSession).rebuild(any(), any(), anyBoolean());
|
||||
|
||||
mController.updateState(mPreference, zenModeWithNone);
|
||||
verifyNoMoreInteractions(mApplicationsState);
|
||||
verify(mSession).deactivateSession();
|
||||
|
||||
mController.updateState(mPreference, zenModeWithPriority);
|
||||
verifyNoMoreInteractions(mApplicationsState);
|
||||
verify(mSession).activateSession();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoCrashIfAppsReadyBeforeRuleAvailable() {
|
||||
mController.mAppSessionCallbacks.onLoadEntriesCompleted();
|
||||
|
||||
Reference in New Issue
Block a user