Populate new fields in modes created via Settings

Type and trigger description on creation; trigger description on update.

Bug: 317370174
Bug: 320997361
Test: atest ZenModeScheduleRuleSettingsTest ZenModeEventRuleSettingsTest
Change-Id: Idb1edcc8829b54ec85494966eb391e52012a5348
This commit is contained in:
Matías Hernández
2024-03-21 11:08:46 +01:00
parent 958d17bb69
commit a1d8044cbf
10 changed files with 145 additions and 20 deletions

View File

@@ -19,6 +19,7 @@ package com.android.settings.notification.zen;
import static android.app.NotificationManager.EXTRA_AUTOMATIC_RULE_ID; import static android.app.NotificationManager.EXTRA_AUTOMATIC_RULE_ID;
import android.app.AutomaticZenRule; import android.app.AutomaticZenRule;
import android.app.Flags;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ComponentName; import android.content.ComponentName;
@@ -28,11 +29,9 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ComponentInfo; import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.provider.Settings; import android.provider.Settings;
import android.service.notification.ConditionProviderService; import android.service.notification.ConditionProviderService;
import android.util.Log; import android.util.Log;
import android.util.Slog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -41,7 +40,6 @@ import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Map; import java.util.Map;
import java.util.Objects;
abstract public class AbstractZenModeAutomaticRulePreferenceController extends abstract public class AbstractZenModeAutomaticRulePreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin { AbstractZenModePreferenceController implements PreferenceControllerMixin {
@@ -166,9 +164,20 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends
public void onOk(String ruleName, Fragment parent) { public void onOk(String ruleName, Fragment parent) {
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK); SettingsEnums.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
AutomaticZenRule rule = new AutomaticZenRule(ruleName, mRuleInfo.serviceComponent, AutomaticZenRule rule;
mRuleInfo.configurationActivity, mRuleInfo.defaultConditionId, null, if (Flags.modesApi() && Flags.modesUi()) {
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); rule = new AutomaticZenRule.Builder(ruleName, mRuleInfo.defaultConditionId)
.setType(mRuleInfo.type)
.setOwner(mRuleInfo.serviceComponent)
.setConfigurationActivity(mRuleInfo.configurationActivity)
.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY)
.setTriggerDescription(mRuleInfo.defaultTriggerDescription)
.build();
} else {
rule = new AutomaticZenRule(ruleName, mRuleInfo.serviceComponent,
mRuleInfo.configurationActivity, mRuleInfo.defaultConditionId, null,
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
}
String savedRuleId = mBackend.addZenRule(rule); String savedRuleId = mBackend.addZenRule(rule);
if (savedRuleId != null) { if (savedRuleId != null) {
parent.startActivity(getRuleIntent(mRuleInfo.settingsAction, null, parent.startActivity(getRuleIntent(mRuleInfo.settingsAction, null,

View File

@@ -138,7 +138,7 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
mEvent.userId = Integer.parseInt(key[0]); mEvent.userId = Integer.parseInt(key[0]);
mEvent.calendarId = key[1].equals("") ? null : Long.parseLong(key[1]); mEvent.calendarId = key[1].equals("") ? null : Long.parseLong(key[1]);
mEvent.calName = key[2].equals("") ? null : key[2]; mEvent.calName = key[2].equals("") ? null : key[2];
updateRule(ZenModeConfig.toEventConditionId(mEvent)); updateEventRule(mEvent);
return true; return true;
} }
}); });
@@ -160,7 +160,7 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
final int reply = Integer.parseInt((String) newValue); final int reply = Integer.parseInt((String) newValue);
if (reply == mEvent.reply) return false; if (reply == mEvent.reply) return false;
mEvent.reply = reply; mEvent.reply = reply;
updateRule(ZenModeConfig.toEventConditionId(mEvent)); updateEventRule(mEvent);
return true; return true;
} }
}); });

View File

@@ -24,9 +24,10 @@ import android.app.NotificationManager;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.service.notification.ConditionProviderService; import android.service.notification.ConditionProviderService;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
@@ -162,8 +163,21 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
updatePreference(mActionButtons); updatePreference(mActionButtons);
} }
protected void updateRule(Uri newConditionId) { protected void updateScheduleRule(ZenModeConfig.ScheduleInfo schedule) {
mRule.setConditionId(newConditionId); mRule.setConditionId(ZenModeConfig.toScheduleConditionId(schedule));
if (Flags.modesApi() && Flags.modesUi()) {
mRule.setTriggerDescription(
SystemZenRules.getTriggerDescriptionForScheduleTime(mContext, schedule));
}
mBackend.updateZenRule(mId, mRule);
}
protected void updateEventRule(ZenModeConfig.EventInfo event) {
mRule.setConditionId(ZenModeConfig.toEventConditionId(event));
if (Flags.modesApi() && Flags.modesUi()) {
mRule.setTriggerDescription(
SystemZenRules.getTriggerDescriptionForScheduleEvent(mContext, event));
}
mBackend.updateZenRule(mId, mRule); mBackend.updateZenRule(mId, mRule);
} }

View File

@@ -108,7 +108,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute); if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute);
mSchedule.startHour = hour; mSchedule.startHour = hour;
mSchedule.startMinute = minute; mSchedule.startMinute = minute;
updateRule(ZenModeConfig.toScheduleConditionId(mSchedule)); updateScheduleRule(mSchedule);
return true; return true;
} }
}); });
@@ -130,7 +130,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute); if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute);
mSchedule.endHour = hour; mSchedule.endHour = hour;
mSchedule.endMinute = minute; mSchedule.endMinute = minute;
updateRule(ZenModeConfig.toScheduleConditionId(mSchedule)); updateScheduleRule(mSchedule);
return true; return true;
} }
}); });
@@ -142,7 +142,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
@Override @Override
public boolean onPreferenceChange(Preference preference, Object o) { public boolean onPreferenceChange(Preference preference, Object o) {
mSchedule.exitAtAlarm = (Boolean) o; mSchedule.exitAtAlarm = (Boolean) o;
updateRule(ZenModeConfig.toScheduleConditionId(mSchedule)); updateScheduleRule(mSchedule);
return true; return true;
} }
}); });
@@ -214,7 +214,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
if (Arrays.equals(days, mSchedule.days)) return; if (Arrays.equals(days, mSchedule.days)) return;
if (DEBUG) Log.d(TAG, "days.onChanged days=" + Arrays.toString(days)); if (DEBUG) Log.d(TAG, "days.onChanged days=" + Arrays.toString(days));
mSchedule.days = days; mSchedule.days = days;
updateRule(ZenModeConfig.toScheduleConditionId(mSchedule)); updateScheduleRule(mSchedule);
} }
}) })
.setOnDismissListener(new OnDismissListener() { .setOnDismissListener(new OnDismissListener() {

View File

@@ -29,6 +29,7 @@ import android.util.Log;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.dashboard.RestrictedDashboardFragment; import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -59,7 +60,12 @@ abstract public class ZenModeSettingsBase extends RestrictedDashboardFragment {
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
mContext = context; mContext = context;
mBackend = ZenModeBackend.getInstance(mContext); setBackend(ZenModeBackend.getInstance(mContext));
}
@VisibleForTesting
void setBackend(ZenModeBackend backend) {
mBackend = backend;
} }
@Override @Override

View File

@@ -1,5 +1,7 @@
package com.android.settings.notification.zen; package com.android.settings.notification.zen;
import android.annotation.Nullable;
import android.app.AutomaticZenRule;
import android.content.ComponentName; import android.content.ComponentName;
import android.net.Uri; import android.net.Uri;
@@ -35,7 +37,9 @@ public class ZenRuleInfo {
public String title; public String title;
public String settingsAction; public String settingsAction;
public ComponentName configurationActivity; public ComponentName configurationActivity;
@AutomaticZenRule.Type public int type;
public Uri defaultConditionId; public Uri defaultConditionId;
@Nullable public String defaultTriggerDescription;
public ComponentName serviceComponent; public ComponentName serviceComponent;
public boolean isSystem; public boolean isSystem;
public CharSequence packageLabel; public CharSequence packageLabel;

View File

@@ -17,6 +17,7 @@
package com.android.settings.notification.zen; package com.android.settings.notification.zen;
import android.app.AutomaticZenRule; import android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -25,6 +26,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ScheduleInfo; import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@@ -141,6 +143,11 @@ public class ZenRulePreference extends PrimarySwitchPreference {
private String computeRuleSummary(AutomaticZenRule rule) { private String computeRuleSummary(AutomaticZenRule rule) {
if (rule != null) { if (rule != null) {
if (Flags.modesApi() && Flags.modesUi()
&& !TextUtils.isEmpty(rule.getTriggerDescription())) {
return rule.getTriggerDescription();
}
// handle schedule-based rules // handle schedule-based rules
ScheduleInfo schedule = ScheduleInfo schedule =
ZenModeConfig.tryParseScheduleConditionId(rule.getConditionId()); ZenModeConfig.tryParseScheduleConditionId(rule.getConditionId());

View File

@@ -16,7 +16,9 @@
package com.android.settings.notification.zen; package com.android.settings.notification.zen;
import android.app.AutomaticZenRule;
import android.app.Dialog; import android.app.Dialog;
import android.app.Flags;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context; import android.content.Context;
@@ -29,6 +31,7 @@ import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.service.notification.SystemZenRules;
import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -178,6 +181,11 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
rt.title = mContext.getString(R.string.zen_schedule_rule_type_name); rt.title = mContext.getString(R.string.zen_schedule_rule_type_name);
rt.packageName = ZenModeConfig.getEventConditionProvider().getPackageName(); rt.packageName = ZenModeConfig.getEventConditionProvider().getPackageName();
rt.defaultConditionId = ZenModeConfig.toScheduleConditionId(schedule); rt.defaultConditionId = ZenModeConfig.toScheduleConditionId(schedule);
if (Flags.modesApi() && Flags.modesUi()) {
rt.type = AutomaticZenRule.TYPE_SCHEDULE_TIME;
rt.defaultTriggerDescription = SystemZenRules.getTriggerDescriptionForScheduleTime(
mContext, schedule);
}
rt.serviceComponent = ZenModeConfig.getScheduleConditionProvider(); rt.serviceComponent = ZenModeConfig.getScheduleConditionProvider();
rt.isSystem = true; rt.isSystem = true;
return rt; return rt;
@@ -193,6 +201,11 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
rt.title = mContext.getString(R.string.zen_event_rule_type_name); rt.title = mContext.getString(R.string.zen_event_rule_type_name);
rt.packageName = ZenModeConfig.getScheduleConditionProvider().getPackageName(); rt.packageName = ZenModeConfig.getScheduleConditionProvider().getPackageName();
rt.defaultConditionId = ZenModeConfig.toEventConditionId(event); rt.defaultConditionId = ZenModeConfig.toEventConditionId(event);
if (Flags.modesApi() && Flags.modesUi()) {
rt.type = AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
rt.defaultTriggerDescription = SystemZenRules.getTriggerDescriptionForScheduleEvent(
mContext, event);
}
rt.serviceComponent = ZenModeConfig.getEventConditionProvider(); rt.serviceComponent = ZenModeConfig.getEventConditionProvider();
rt.isSystem = true; rt.isSystem = true;
return rt; return rt;

View File

@@ -16,17 +16,26 @@
package com.android.settings.notification.zen; package com.android.settings.notification.zen;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
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 android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.Uri;
import android.os.Looper; import android.os.Looper;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenModeConfig;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -34,6 +43,7 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
@@ -51,11 +61,15 @@ import java.util.List;
}) })
public class ZenModeEventRuleSettingsTest { public class ZenModeEventRuleSettingsTest {
@Mock @Rule
private FragmentActivity mActivity; public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
@Mock
private FragmentActivity mActivity;
@Mock @Mock
private Intent mIntent; private Intent mIntent;
@Mock
private ZenModeBackend mBackend;
private ZenModeEventRuleSettings mFragment; private ZenModeEventRuleSettings mFragment;
private Context mContext; private Context mContext;
@@ -92,6 +106,26 @@ public class ZenModeEventRuleSettingsTest {
//should not crash //should not crash
} }
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
public void updateEventRule_updatesConditionAndTriggerDescription() {
mFragment.setBackend(mBackend);
mFragment.mId = "id";
mFragment.mRule = new AutomaticZenRule.Builder("name", Uri.parse("condition")).build();
ZenModeConfig.EventInfo eventInfo = new ZenModeConfig.EventInfo();
eventInfo.calendarId = 1L;
eventInfo.calName = "My events";
mFragment.updateEventRule(eventInfo);
verify(mBackend).updateZenRule(eq("id"),
eq(new AutomaticZenRule.Builder(
"name",
ZenModeConfig.toEventConditionId(eventInfo))
.setTriggerDescription("My events")
.build()));
}
@Test @Test
public void testNoDuplicateCalendars() { public void testNoDuplicateCalendars() {
List<ZenModeEventRuleSettings.CalendarInfo> calendarsList = new ArrayList<>(); List<ZenModeEventRuleSettings.CalendarInfo> calendarsList = new ArrayList<>();

View File

@@ -16,17 +16,26 @@
package com.android.settings.notification.zen; package com.android.settings.notification.zen;
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
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 android.app.AutomaticZenRule;
import android.app.Flags;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.Uri;
import android.os.Looper; import android.os.Looper;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenModeConfig;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -34,25 +43,33 @@ import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R; import com.android.settings.R;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowToast; import org.robolectric.shadows.ShadowToast;
import java.util.Calendar;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = { @Config(shadows = {
com.android.settings.testutils.shadow.ShadowFragment.class, com.android.settings.testutils.shadow.ShadowFragment.class,
}) })
public class ZenModeScheduleRuleSettingsTest { public class ZenModeScheduleRuleSettingsTest {
@Mock @Rule
private FragmentActivity mActivity; public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
@Mock
private FragmentActivity mActivity;
@Mock @Mock
private Intent mIntent; private Intent mIntent;
@Mock
private ZenModeBackend mBackend;
private ZenModeScheduleRuleSettings mFragment; private ZenModeScheduleRuleSettings mFragment;
private Context mContext; private Context mContext;
@@ -88,4 +105,25 @@ public class ZenModeScheduleRuleSettingsTest {
//should not crash //should not crash
} }
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
public void updateScheduleRule_updatesConditionAndTriggerDescription() {
mFragment.setBackend(mBackend);
mFragment.mId = "id";
mFragment.mRule = new AutomaticZenRule.Builder("name", Uri.parse("condition")).build();
ZenModeConfig.ScheduleInfo scheduleInfo = new ZenModeConfig.ScheduleInfo();
scheduleInfo.days = new int[] { Calendar.MONDAY };
scheduleInfo.startHour = 1;
scheduleInfo.endHour = 2;
mFragment.updateScheduleRule(scheduleInfo);
ArgumentCaptor<AutomaticZenRule> updatedRuleCaptor = ArgumentCaptor.forClass(
AutomaticZenRule.class);
verify(mBackend).updateZenRule(eq("id"), updatedRuleCaptor.capture());
assertThat(updatedRuleCaptor.getValue().getConditionId())
.isEqualTo(ZenModeConfig.toScheduleConditionId(scheduleInfo));
assertThat(updatedRuleCaptor.getValue().getTriggerDescription()).isNotEmpty();
}
} }