Refactor preference controllers to receive and mutate ZenMode/ZenPolicy

Also fixed a handful of style issues / warnings along the way.

Fixes: 341950853
Fixes: 341910620
Test: atest com.android.settings.notification.modes
Flag: android.app.modes_ui
Change-Id: I65900941fcdf53824caf052fd0a24401c1bfb476
This commit is contained in:
Matías Hernández
2024-05-23 15:51:03 +00:00
parent 51dc721031
commit 43d67b0080
17 changed files with 213 additions and 199 deletions

View File

@@ -16,9 +16,10 @@
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import android.app.AutomaticZenRule;
import android.app.Flags; import android.app.Flags;
import android.content.Context; import android.content.Context;
import android.service.notification.ZenPolicy;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -26,11 +27,17 @@ import androidx.preference.Preference;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.google.common.base.Preconditions;
import java.util.function.Function;
/** /**
* Base class for any preference controllers pertaining to any single Zen mode. * Base class for any preference controllers pertaining to any single Zen mode.
*/ */
abstract class AbstractZenModePreferenceController extends AbstractPreferenceController { abstract class AbstractZenModePreferenceController extends AbstractPreferenceController {
private static final String TAG = "AbstractZenModePreferenceController";
@Nullable @Nullable
protected ZenModesBackend mBackend; protected ZenModesBackend mBackend;
@@ -38,7 +45,7 @@ abstract class AbstractZenModePreferenceController extends AbstractPreferenceCon
private ZenMode mZenMode; private ZenMode mZenMode;
@NonNull @NonNull
final String mKey; private final String mKey;
// ZenModesBackend should only be passed in if the preference controller may set the user's // ZenModesBackend should only be passed in if the preference controller may set the user's
// policy for this zen mode. Otherwise, if the preference controller is essentially read-only // policy for this zen mode. Otherwise, if the preference controller is essentially read-only
@@ -67,20 +74,56 @@ abstract class AbstractZenModePreferenceController extends AbstractPreferenceCon
updateState(preference); updateState(preference);
} }
@Nullable @Override
public ZenMode getMode() { public final void updateState(Preference preference) {
return mZenMode; super.updateState(preference);
if (mZenMode != null) {
updateState(preference, mZenMode);
}
} }
@Nullable abstract void updateState(Preference preference, @NonNull ZenMode zenMode);
public AutomaticZenRule getAZR() {
if (mZenMode == null || mZenMode.getRule() == null) { @Override
public final CharSequence getSummary() {
if (mZenMode != null) {
return getSummary(mZenMode);
} else {
return null; return null;
} }
return mZenMode.getRule();
} }
/** Implementations of this class should override @Nullable
* {@link AbstractPreferenceController#updateState(Preference)} to specify what should protected CharSequence getSummary(@NonNull ZenMode zenMode) {
* happen when the preference is updated */ return null;
}
/**
* Subclasses should call this method (or a more specific one, like {@link #savePolicy} from
* their {@code onPreferenceChange()} or similar, in order to apply changes to the mode being
* edited (e.g. {@code saveMode(mode -> { mode.setX(value); return mode; } }.
*
* @param updater Function to update the {@link ZenMode}. Modifying and returning the same
* instance is ok.
*/
protected final boolean saveMode(Function<ZenMode, ZenMode> updater) {
Preconditions.checkState(mBackend != null);
ZenMode mode = mZenMode;
if (mode == null) {
Log.wtf(TAG, "Cannot save mode, it hasn't been loaded (" + getClass() + ")");
return false;
}
mode = updater.apply(mode);
mBackend.updateMode(mode);
return true;
}
protected final boolean savePolicy(Function<ZenPolicy.Builder, ZenPolicy.Builder> updater) {
return saveMode(mode -> {
ZenPolicy.Builder policyBuilder = new ZenPolicy.Builder(mode.getPolicy());
policyBuilder = updater.apply(policyBuilder);
mode.setPolicy(policyBuilder.build());
return mode;
});
}
} }

View File

@@ -26,6 +26,7 @@ import android.app.AutomaticZenRule;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenPolicy; import android.service.notification.ZenPolicy;
import android.util.Log; import android.util.Log;
@@ -150,14 +151,6 @@ class ZenMode {
} }
} }
/**
* Use sparingly. If you're updating a policy field, use
* {@link #setPolicy(android.service.notification.ZenPolicy)} instead.
*/
public void setAzr(@NonNull AutomaticZenRule newRule) {
mRule = newRule;
}
/** /**
* Updates the {@link ZenPolicy} of the associated {@link AutomaticZenRule} based on the * Updates the {@link ZenPolicy} of the associated {@link AutomaticZenRule} based on the
* supplied policy. In some cases this involves conversions, so that the following call * supplied policy. In some cases this involves conversions, so that the following call
@@ -204,6 +197,13 @@ class ZenMode {
mRule.setZenPolicy(policy); mRule.setZenPolicy(policy);
} }
@NonNull
public ZenDeviceEffects getDeviceEffects() {
return mRule.getDeviceEffects() != null
? mRule.getDeviceEffects()
: new ZenDeviceEffects.Builder().build();
}
public boolean canBeDeleted() { public boolean canBeDeleted() {
return !mIsManualDnd; return !mIsManualDnd;
} }

View File

@@ -20,12 +20,15 @@ import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_I
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
public class ZenModeCallsLinkPreferenceController extends AbstractZenModePreferenceController { class ZenModeCallsLinkPreferenceController extends AbstractZenModePreferenceController {
private ZenModeSummaryHelper mSummaryHelper; private final ZenModeSummaryHelper mSummaryHelper;
public ZenModeCallsLinkPreferenceController(Context context, String key, public ZenModeCallsLinkPreferenceController(Context context, String key,
ZenModesBackend backend) { ZenModesBackend backend) {
@@ -34,16 +37,15 @@ public class ZenModeCallsLinkPreferenceController extends AbstractZenModePrefere
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(MODE_ID, getMode().getId()); bundle.putString(MODE_ID, zenMode.getId());
// TODO(b/332937635): Update metrics category // TODO(b/332937635): Update metrics category
preference.setIntent(new SubSettingLauncher(mContext) preference.setIntent(new SubSettingLauncher(mContext)
.setDestination(ZenModeCallsFragment.class.getName()) .setDestination(ZenModeCallsFragment.class.getName())
.setSourceMetricsCategory(0) .setSourceMetricsCategory(0)
.setArguments(bundle) .setArguments(bundle)
.toIntent()); .toIntent());
preference.setSummary(mSummaryHelper.getCallsSettingSummary(getMode())); preference.setSummary(mSummaryHelper.getCallsSettingSummary(zenMode));
} }
} }

View File

@@ -16,16 +16,10 @@
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_ALARMS;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_EVENTS;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_MEDIA;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REMINDERS;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_SYSTEM;
import android.app.AutomaticZenRule;
import android.content.Context; import android.content.Context;
import android.service.notification.ZenDeviceEffects; import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenPolicy;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.TwoStatePreference; import androidx.preference.TwoStatePreference;
@@ -38,9 +32,9 @@ public class ZenModeDisplayEffectPreferenceController extends AbstractZenModePre
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
TwoStatePreference pref = (TwoStatePreference) preference; TwoStatePreference pref = (TwoStatePreference) preference;
ZenDeviceEffects effects = getMode().getRule().getDeviceEffects(); ZenDeviceEffects effects = zenMode.getRule().getDeviceEffects();
if (effects == null) { if (effects == null) {
pref.setChecked(false); pref.setChecked(false);
} else { } else {
@@ -62,13 +56,11 @@ public class ZenModeDisplayEffectPreferenceController extends AbstractZenModePre
} }
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
final boolean allow = (Boolean) newValue; final boolean allow = (Boolean) newValue;
return saveMode(zenMode -> {
ZenDeviceEffects currEffects = getMode().getRule().getDeviceEffects(); ZenDeviceEffects.Builder updatedEffects = new ZenDeviceEffects.Builder(
ZenDeviceEffects.Builder updatedEffects = currEffects == null zenMode.getDeviceEffects());
? new ZenDeviceEffects.Builder()
: new ZenDeviceEffects.Builder(getMode().getRule().getDeviceEffects());
switch (getPreferenceKey()) { switch (getPreferenceKey()) {
case "effect_greyscale": case "effect_greyscale":
updatedEffects.setShouldDisplayGrayscale(allow); updatedEffects.setShouldDisplayGrayscale(allow);
@@ -83,12 +75,8 @@ public class ZenModeDisplayEffectPreferenceController extends AbstractZenModePre
updatedEffects.setShouldUseNightMode(allow); updatedEffects.setShouldUseNightMode(allow);
break; break;
} }
AutomaticZenRule updatedAzr = new AutomaticZenRule.Builder(getMode().getRule()) zenMode.getRule().setDeviceEffects(updatedEffects.build());
.setDeviceEffects(updatedEffects.build()) return zenMode;
.build(); });
getMode().setAzr(updatedAzr);
mBackend.updateMode(getMode());
return true;
} }
} }

View File

@@ -20,12 +20,15 @@ import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_I
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
public class ZenModeDisplayLinkPreferenceController extends AbstractZenModePreferenceController { class ZenModeDisplayLinkPreferenceController extends AbstractZenModePreferenceController {
ZenModeSummaryHelper mSummaryHelper; private final ZenModeSummaryHelper mSummaryHelper;
public ZenModeDisplayLinkPreferenceController(Context context, String key, public ZenModeDisplayLinkPreferenceController(Context context, String key,
ZenModesBackend backend) { ZenModesBackend backend) {
@@ -34,10 +37,9 @@ public class ZenModeDisplayLinkPreferenceController extends AbstractZenModePrefe
} }
@Override @Override
public void updateState(Preference preference) { void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(MODE_ID, getMode().getId()); bundle.putString(MODE_ID, zenMode.getId());
// TODO(b/332937635): Update metrics category // TODO(b/332937635): Update metrics category
preference.setIntent(new SubSettingLauncher(mContext) preference.setIntent(new SubSettingLauncher(mContext)
.setDestination(ZenModeDisplayFragment.class.getName()) .setDestination(ZenModeDisplayFragment.class.getName())
@@ -47,7 +49,7 @@ public class ZenModeDisplayLinkPreferenceController extends AbstractZenModePrefe
} }
@Override @Override
public CharSequence getSummary() { public CharSequence getSummary(@NonNull ZenMode zenMode) {
return mSummaryHelper.getDisplayEffectsSummary(getMode()); return mSummaryHelper.getDisplayEffectsSummary(zenMode);
} }
} }

View File

@@ -47,9 +47,8 @@ class ZenModeHeaderController extends AbstractZenModePreferenceController {
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
ZenMode mode = getMode(); if (mFragment == null) {
if (mode == null || mFragment == null) {
return; return;
} }
@@ -62,9 +61,9 @@ class ZenModeHeaderController extends AbstractZenModePreferenceController {
} }
FutureUtil.whenDone( FutureUtil.whenDone(
mode.getIcon(IconLoader.getInstance(mContext)), zenMode.getIcon(IconLoader.getInstance(mContext)),
icon -> mHeaderController.setIcon(icon) icon -> mHeaderController.setIcon(icon)
.setLabel(mode.getRule().getName()) .setLabel(zenMode.getRule().getName())
.done(false /* rebindActions */), .done(false /* rebindActions */),
mContext.getMainExecutor()); mContext.getMainExecutor());
} }

View File

@@ -20,10 +20,13 @@ import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_I
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
public class ZenModeMessagesLinkPreferenceController extends AbstractZenModePreferenceController { class ZenModeMessagesLinkPreferenceController extends AbstractZenModePreferenceController {
private final ZenModeSummaryHelper mSummaryHelper; private final ZenModeSummaryHelper mSummaryHelper;
public ZenModeMessagesLinkPreferenceController(Context context, String key, public ZenModeMessagesLinkPreferenceController(Context context, String key,
@@ -33,11 +36,9 @@ public class ZenModeMessagesLinkPreferenceController extends AbstractZenModePref
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(MODE_ID, getMode().getId()); bundle.putString(MODE_ID, zenMode.getId());
// TODO(b/332937635): Update metrics category // TODO(b/332937635): Update metrics category
preference.setIntent(new SubSettingLauncher(mContext) preference.setIntent(new SubSettingLauncher(mContext)
.setDestination(ZenModeMessagesFragment.class.getName()) .setDestination(ZenModeMessagesFragment.class.getName())
@@ -46,6 +47,6 @@ public class ZenModeMessagesLinkPreferenceController extends AbstractZenModePref
.toIntent()); .toIntent());
preference.setEnabled(true); preference.setEnabled(true);
preference.setSummary(mSummaryHelper.getMessagesSettingSummary(getMode().getPolicy())); preference.setSummary(mSummaryHelper.getMessagesSettingSummary(zenMode.getPolicy()));
} }
} }

View File

@@ -20,12 +20,16 @@ import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_I
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
public class ZenModeNotifVisLinkPreferenceController extends AbstractZenModePreferenceController { class ZenModeNotifVisLinkPreferenceController extends AbstractZenModePreferenceController {
private final ZenModeSummaryHelper mSummaryBuilder;
ZenModeSummaryHelper mSummaryBuilder;
public ZenModeNotifVisLinkPreferenceController(Context context, String key, public ZenModeNotifVisLinkPreferenceController(Context context, String key,
ZenModesBackend backend) { ZenModesBackend backend) {
super(context, key, backend); super(context, key, backend);
@@ -33,10 +37,9 @@ public class ZenModeNotifVisLinkPreferenceController extends AbstractZenModePref
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(MODE_ID, getMode().getId()); bundle.putString(MODE_ID, zenMode.getId());
// TODO(b/332937635): Update metrics category // TODO(b/332937635): Update metrics category
preference.setIntent(new SubSettingLauncher(mContext) preference.setIntent(new SubSettingLauncher(mContext)
.setDestination(ZenModeNotifVisFragment.class.getName()) .setDestination(ZenModeNotifVisFragment.class.getName())
@@ -46,7 +49,7 @@ public class ZenModeNotifVisLinkPreferenceController extends AbstractZenModePref
} }
@Override @Override
public CharSequence getSummary() { public CharSequence getSummary(@NonNull ZenMode zenMode) {
return mSummaryBuilder.getBlockedEffectsSummary(getMode()); return mSummaryBuilder.getBlockedEffectsSummary(zenMode);
} }
} }

View File

@@ -18,9 +18,12 @@ package com.android.settings.notification.modes;
import android.content.Context; import android.content.Context;
import android.service.notification.ZenPolicy; import android.service.notification.ZenPolicy;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.CheckBoxPreference; import androidx.preference.CheckBoxPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.widget.DisabledCheckBoxPreference; import com.android.settings.widget.DisabledCheckBoxPreference;
public class ZenModeNotifVisPreferenceController extends AbstractZenModePreferenceController public class ZenModeNotifVisPreferenceController extends AbstractZenModePreferenceController
@@ -53,13 +56,13 @@ public class ZenModeNotifVisPreferenceController extends AbstractZenModePreferen
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
boolean suppressed = !getMode().getPolicy().isVisualEffectAllowed(mEffect, false); boolean suppressed = !zenMode.getPolicy().isVisualEffectAllowed(mEffect, false);
boolean parentSuppressed = false; boolean parentSuppressed = false;
if (mParentSuppressedEffects != null) { if (mParentSuppressedEffects != null) {
for (@ZenPolicy.VisualEffect int parentEffect : mParentSuppressedEffects) { for (@ZenPolicy.VisualEffect int parentEffect : mParentSuppressedEffects) {
if (!getMode().getPolicy().isVisualEffectAllowed(parentEffect, true)) { if (!zenMode.getPolicy().isVisualEffectAllowed(parentEffect, true)) {
parentSuppressed = true; parentSuppressed = true;
} }
} }
@@ -77,15 +80,6 @@ public class ZenModeNotifVisPreferenceController extends AbstractZenModePreferen
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowEffect = !((Boolean) newValue); final boolean allowEffect = !((Boolean) newValue);
return savePolicy(policy -> policy.showVisualEffect(mEffect, allowEffect));
if (getMode().getPolicy().isVisualEffectAllowed(mEffect, true) != allowEffect) {
ZenPolicy diffPolicy = new ZenPolicy.Builder()
.showVisualEffect(mEffect, allowEffect)
.build();
getMode().setPolicy(diffPolicy);
mBackend.updateMode(getMode());
}
return true;
} }
} }

View File

@@ -16,20 +16,22 @@
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID; import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
/** /**
* Preference with a link and summary about what other sounds can break through the mode * Preference with a link and summary about what other sounds can break through the mode
*/ */
public class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceController { class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceController {
ZenModeSummaryHelper mSummaryHelper; private final ZenModeSummaryHelper mSummaryHelper;
public ZenModeOtherLinkPreferenceController(Context context, String key, public ZenModeOtherLinkPreferenceController(Context context, String key,
ZenModesBackend backend) { ZenModesBackend backend) {
@@ -38,15 +40,14 @@ public class ZenModeOtherLinkPreferenceController extends AbstractZenModePrefere
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(MODE_ID, getMode().getId()); bundle.putString(MODE_ID, zenMode.getId());
preference.setIntent(new SubSettingLauncher(mContext) preference.setIntent(new SubSettingLauncher(mContext)
.setDestination(ZenModeOtherFragment.class.getName()) .setDestination(ZenModeOtherFragment.class.getName())
.setSourceMetricsCategory(0) .setSourceMetricsCategory(0)
.setArguments(bundle) .setArguments(bundle)
.toIntent()); .toIntent());
preference.setSummary(mSummaryHelper.getOtherSoundCategoriesSummary(getMode())); preference.setSummary(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode));
} }
} }

View File

@@ -23,11 +23,12 @@ import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REMINDERS
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_SYSTEM; import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_SYSTEM;
import android.content.Context; import android.content.Context;
import android.service.notification.ZenPolicy;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.TwoStatePreference; import androidx.preference.TwoStatePreference;
public class ZenModeOtherPreferenceController extends AbstractZenModePreferenceController class ZenModeOtherPreferenceController extends AbstractZenModePreferenceController
implements Preference.OnPreferenceChangeListener { implements Preference.OnPreferenceChangeListener {
public ZenModeOtherPreferenceController(Context context, String key, public ZenModeOtherPreferenceController(Context context, String key,
@@ -36,24 +37,15 @@ public class ZenModeOtherPreferenceController extends AbstractZenModePreferenceC
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
TwoStatePreference pref = (TwoStatePreference) preference; TwoStatePreference pref = (TwoStatePreference) preference;
pref.setChecked(getMode().getPolicy().isCategoryAllowed(getCategory(), true)); pref.setChecked(zenMode.getPolicy().isCategoryAllowed(getCategory(), true));
} }
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allow = (Boolean) newValue; final boolean allow = (Boolean) newValue;
return savePolicy(policy -> policy.allowCategory(getCategory(), allow));
ZenPolicy diffPolicy = new ZenPolicy.Builder()
.allowCategory(getCategory(), allow)
.build();
getMode().setPolicy(diffPolicy);
mBackend.updateMode(getMode());
return true;
} }
private int getCategory() { private int getCategory() {

View File

@@ -16,21 +16,22 @@
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID; import static com.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.preference.Preference; import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
/** /**
* Preference with a link and summary about what calls and messages can break through the mode * Preference with a link and summary about what calls and messages can break through the mode
*/ */
public class ZenModePeopleLinkPreferenceController extends AbstractZenModePreferenceController { class ZenModePeopleLinkPreferenceController extends AbstractZenModePreferenceController {
ZenModeSummaryHelper mSummaryHelper; private final ZenModeSummaryHelper mSummaryHelper;
public ZenModePeopleLinkPreferenceController(Context context, String key, public ZenModePeopleLinkPreferenceController(Context context, String key,
ZenModesBackend backend) { ZenModesBackend backend) {
@@ -39,16 +40,15 @@ public class ZenModePeopleLinkPreferenceController extends AbstractZenModePrefer
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putString(MODE_ID, getMode().getId()); bundle.putString(MODE_ID, zenMode.getId());
// TODO(b/332937635): Update metrics category // TODO(b/332937635): Update metrics category
preference.setIntent(new SubSettingLauncher(mContext) preference.setIntent(new SubSettingLauncher(mContext)
.setDestination(ZenModePeopleFragment.class.getName()) .setDestination(ZenModePeopleFragment.class.getName())
.setSourceMetricsCategory(0) .setSourceMetricsCategory(0)
.setArguments(bundle) .setArguments(bundle)
.toIntent()); .toIntent());
preference.setSummary(mSummaryHelper.getPeopleSummary(getMode())); preference.setSummary(mSummaryHelper.getPeopleSummary(zenMode));
} }
} }

View File

@@ -36,10 +36,13 @@ import android.provider.Contacts;
import android.service.notification.ConversationChannelWrapper; import android.service.notification.ConversationChannelWrapper;
import android.service.notification.ZenPolicy; import android.service.notification.ZenPolicy;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
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.settings.notification.app.ConversationListSettings; import com.android.settings.notification.app.ConversationListSettings;
@@ -59,7 +62,7 @@ import java.util.Map;
* bypass DND for calls or messages, which may be one of the following values: starred contacts, all * bypass DND for calls or messages, which may be one of the following values: starred contacts, all
* contacts, priority conversations (for messages only), anyone, or no one. * contacts, priority conversations (for messages only), anyone, or no one.
*/ */
public class ZenModePrioritySendersPreferenceController class ZenModePrioritySendersPreferenceController
extends AbstractZenModePreferenceController { extends AbstractZenModePreferenceController {
private final boolean mIsMessages; // if this is false, then this preference is for calls private final boolean mIsMessages; // if this is false, then this preference is for calls
@@ -124,12 +127,12 @@ public class ZenModePrioritySendersPreferenceController
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
if (mIsMessages) { if (mIsMessages) {
updateChannelCounts(); updateChannelCounts();
} }
final int currContactsSetting = getPrioritySenders(); final int currContactsSetting = getPrioritySenders(zenMode.getPolicy());
final int currConversationsSetting = getPriorityConversationSenders(); final int currConversationsSetting = getPriorityConversationSenders(zenMode.getPolicy());
for (SelectorWithWidgetPreference pref : mSelectorPreferences) { for (SelectorWithWidgetPreference pref : mSelectorPreferences) {
// for each preference, check whether the current state matches what this state // for each preference, check whether the current state matches what this state
// would look like if the button were checked. // would look like if the button were checked.
@@ -173,17 +176,17 @@ public class ZenModePrioritySendersPreferenceController
mNumImportantConversations = numImportantConversations; mNumImportantConversations = numImportantConversations;
} }
private int getPrioritySenders() { private int getPrioritySenders(ZenPolicy policy) {
if (mIsMessages) { if (mIsMessages) {
return getMode().getPolicy().getPriorityMessageSenders(); return policy.getPriorityMessageSenders();
} else { } else {
return getMode().getPolicy().getPriorityCallSenders(); return policy.getPriorityCallSenders();
} }
} }
private int getPriorityConversationSenders() { private int getPriorityConversationSenders(ZenPolicy policy) {
if (mIsMessages) { if (mIsMessages) {
return getMode().getPolicy().getPriorityConversationSenders(); return policy.getPriorityConversationSenders();
} }
return CONVERSATION_SENDERS_UNSET; return CONVERSATION_SENDERS_UNSET;
} }
@@ -421,27 +424,29 @@ public class ZenModePrioritySendersPreferenceController
new SelectorWithWidgetPreference.OnClickListener() { new SelectorWithWidgetPreference.OnClickListener() {
@Override @Override
public void onRadioButtonClicked(SelectorWithWidgetPreference preference) { public void onRadioButtonClicked(SelectorWithWidgetPreference preference) {
savePolicy(policy -> {
ZenPolicy previousPolicy = policy.build();
// The settingsToSaveOnClick function takes whether the preference is a // The settingsToSaveOnClick function takes whether the preference is a
// checkbox into account to determine whether this selection is checked or unchecked. // checkbox into account to determine whether this selection is checked or
// unchecked.
final int[] settingsToSave = settingsToSaveOnClick(preference, final int[] settingsToSave = settingsToSaveOnClick(preference,
getPrioritySenders(), getPriorityConversationSenders()); getPrioritySenders(previousPolicy),
getPriorityConversationSenders(previousPolicy));
final int prioritySendersSetting = settingsToSave[0]; final int prioritySendersSetting = settingsToSave[0];
final int priorityConvosSetting = settingsToSave[1]; final int priorityConvosSetting = settingsToSave[1];
ZenPolicy.Builder diffPolicy = new ZenPolicy.Builder();
if (prioritySendersSetting != PEOPLE_TYPE_UNSET) { if (prioritySendersSetting != PEOPLE_TYPE_UNSET) {
if (mIsMessages) { if (mIsMessages) {
diffPolicy.allowMessages(prioritySendersSetting); policy.allowMessages(prioritySendersSetting);
} else { } else {
diffPolicy.allowCalls(prioritySendersSetting); policy.allowCalls(prioritySendersSetting);
} }
} }
if (mIsMessages && priorityConvosSetting != CONVERSATION_SENDERS_UNSET) { if (mIsMessages && priorityConvosSetting != CONVERSATION_SENDERS_UNSET) {
diffPolicy.allowConversations(priorityConvosSetting); policy.allowConversations(priorityConvosSetting);
} }
getMode().setPolicy(diffPolicy.build()); return policy;
mBackend.updateMode(getMode()); });
} }
}; };
} }

View File

@@ -17,20 +17,17 @@
package com.android.settings.notification.modes; package com.android.settings.notification.modes;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE;
import static android.service.notification.ZenPolicy.PEOPLE_TYPE_NONE;
import static android.service.notification.ZenPolicy.STATE_ALLOW; import static android.service.notification.ZenPolicy.STATE_ALLOW;
import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.provider.Settings;
import android.service.notification.ZenPolicy; import androidx.annotation.NonNull;
import android.util.Log;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference; import androidx.preference.TwoStatePreference;
import com.android.settings.R; import com.android.settings.R;
public class ZenModeRepeatCallersPreferenceController extends AbstractZenModePreferenceController class ZenModeRepeatCallersPreferenceController extends AbstractZenModePreferenceController
implements Preference.OnPreferenceChangeListener { implements Preference.OnPreferenceChangeListener {
private final int mRepeatCallersThreshold; private final int mRepeatCallersThreshold;
@@ -43,14 +40,12 @@ public class ZenModeRepeatCallersPreferenceController extends AbstractZenModePre
} }
@Override @Override
public void updateState(Preference preference) { public void updateState(Preference preference, @NonNull ZenMode zenMode) {
super.updateState(preference);
TwoStatePreference pref = (TwoStatePreference) preference; TwoStatePreference pref = (TwoStatePreference) preference;
boolean anyCallersCanBypassDnd = boolean anyCallersCanBypassDnd =
getMode().getPolicy().getPriorityCategoryCalls() == STATE_ALLOW zenMode.getPolicy().getPriorityCategoryCalls() == STATE_ALLOW
&& getMode().getPolicy().getPriorityCallSenders() == PEOPLE_TYPE_ANYONE; && zenMode.getPolicy().getPriorityCallSenders() == PEOPLE_TYPE_ANYONE;
// if any caller can bypass dnd then repeat callers preference is disabled // if any caller can bypass dnd then repeat callers preference is disabled
if (anyCallersCanBypassDnd) { if (anyCallersCanBypassDnd) {
pref.setEnabled(false); pref.setEnabled(false);
@@ -58,21 +53,16 @@ public class ZenModeRepeatCallersPreferenceController extends AbstractZenModePre
} else { } else {
pref.setEnabled(true); pref.setEnabled(true);
pref.setChecked( pref.setChecked(
getMode().getPolicy().getPriorityCategoryRepeatCallers() == STATE_ALLOW); zenMode.getPolicy().getPriorityCategoryRepeatCallers() == STATE_ALLOW);
} }
setRepeatCallerSummary(preference); setRepeatCallerSummary(preference);
} }
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
final boolean allowRepeatCallers = (Boolean) newValue; final boolean allowRepeatCallers = (Boolean) newValue;
ZenPolicy diffPolicy = new ZenPolicy.Builder() return savePolicy(policy -> policy.allowRepeatCallers(allowRepeatCallers));
.allowRepeatCallers(allowRepeatCallers)
.build();
getMode().setPolicy(diffPolicy);
mBackend.updateMode(getMode());
return true;
} }
private void setRepeatCallerSummary(Preference preference) { private void setRepeatCallerSummary(Preference preference) {

View File

@@ -30,7 +30,6 @@ import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_MESSAGES;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REMINDERS; import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REMINDERS;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS; import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS;
import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_SYSTEM; import static android.service.notification.ZenPolicy.PRIORITY_CATEGORY_SYSTEM;
import static android.service.notification.ZenPolicy.STATE_DISALLOW;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_AMBIENT; import static android.service.notification.ZenPolicy.VISUAL_EFFECT_AMBIENT;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_BADGE; import static android.service.notification.ZenPolicy.VISUAL_EFFECT_BADGE;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT; import static android.service.notification.ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT;
@@ -44,7 +43,6 @@ import android.icu.text.MessageFormat;
import android.service.notification.ZenDeviceEffects; import android.service.notification.ZenDeviceEffects;
import android.service.notification.ZenPolicy; import android.service.notification.ZenPolicy;
import android.util.SparseArray;
import com.android.settings.R; import com.android.settings.R;
import java.util.ArrayList; import java.util.ArrayList;
@@ -54,10 +52,10 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.function.Predicate; import java.util.function.Predicate;
public class ZenModeSummaryHelper { class ZenModeSummaryHelper {
private Context mContext; private final Context mContext;
private ZenModesBackend mBackend; private final ZenModesBackend mBackend;
public ZenModeSummaryHelper(Context context, ZenModesBackend backend) { public ZenModeSummaryHelper(Context context, ZenModesBackend backend) {
mContext = context; mContext = context;

View File

@@ -39,7 +39,7 @@ import java.util.Map;
* containing links to each individual mode. This is a central controller that populates and updates * containing links to each individual mode. This is a central controller that populates and updates
* all the preferences that then lead to a mode configuration page. * all the preferences that then lead to a mode configuration page.
*/ */
public class ZenModesListPreferenceController extends BasePreferenceController { class ZenModesListPreferenceController extends BasePreferenceController {
protected static final String KEY = "zen_modes_list"; protected static final String KEY = "zen_modes_list";
@Nullable @Nullable

View File

@@ -19,18 +19,16 @@ package com.android.settings.notification.modes;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.ZenPolicy.STATE_ALLOW; import static android.service.notification.ZenPolicy.STATE_ALLOW;
import static android.service.notification.ZenPolicy.STATE_DISALLOW; import static android.service.notification.ZenPolicy.STATE_DISALLOW;
import static android.service.notification.ZenPolicy.STATE_UNSET;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_LIGHTS; import static android.service.notification.ZenPolicy.VISUAL_EFFECT_LIGHTS;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST; import static android.service.notification.ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_PEEK; import static android.service.notification.ZenPolicy.VISUAL_EFFECT_PEEK;
import static android.service.notification.ZenPolicy.VISUAL_EFFECT_STATUS_BAR; import static android.service.notification.ZenPolicy.VISUAL_EFFECT_STATUS_BAR;
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.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
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;
@@ -41,12 +39,10 @@ import android.content.res.Resources;
import android.net.Uri; import android.net.Uri;
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.ZenDeviceEffects;
import android.service.notification.ZenPolicy; import android.service.notification.ZenPolicy;
import androidx.preference.TwoStatePreference;
import com.android.settings.notification.zen.ZenModeVisEffectPreferenceController;
import com.android.settings.widget.DisabledCheckBoxPreference; import com.android.settings.widget.DisabledCheckBoxPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@@ -162,7 +158,7 @@ public final class ZenModeNotifVisPreferenceControllerTest {
assertThat(captor.getValue().getPolicy().getVisualEffectStatusBar()) assertThat(captor.getValue().getPolicy().getVisualEffectStatusBar())
.isEqualTo(STATE_DISALLOW); .isEqualTo(STATE_DISALLOW);
assertThat(captor.getValue().getPolicy().getVisualEffectNotificationList()) assertThat(captor.getValue().getPolicy().getVisualEffectNotificationList())
.isEqualTo(STATE_UNSET); .isEqualTo(STATE_DISALLOW); // Untouched
} }
@Test @Test
@@ -211,7 +207,7 @@ public final class ZenModeNotifVisPreferenceControllerTest {
assertThat(captor.getValue().getPolicy().getVisualEffectPeek()) assertThat(captor.getValue().getPolicy().getVisualEffectPeek())
.isEqualTo(STATE_ALLOW); .isEqualTo(STATE_ALLOW);
assertThat(captor.getValue().getPolicy().getVisualEffectNotificationList()) assertThat(captor.getValue().getPolicy().getVisualEffectNotificationList())
.isEqualTo(STATE_UNSET); .isEqualTo(STATE_DISALLOW); // Untouched
} }
@Test @Test
@@ -236,6 +232,6 @@ public final class ZenModeNotifVisPreferenceControllerTest {
assertThat(captor.getValue().getPolicy().getVisualEffectPeek()) assertThat(captor.getValue().getPolicy().getVisualEffectPeek())
.isEqualTo(STATE_DISALLOW); .isEqualTo(STATE_DISALLOW);
assertThat(captor.getValue().getPolicy().getVisualEffectNotificationList()) assertThat(captor.getValue().getPolicy().getVisualEffectNotificationList())
.isEqualTo(STATE_UNSET); .isEqualTo(STATE_ALLOW); // Untouched
} }
} }