Change zen schedules page to use switches.
Also add clearer summaries for schedule and calendar events (rather than just "Off" and "On"): for schedules, list the days & times for which the schedule is active, and for events, the calendar whose events it triggers on. Bug: 190180868 Bug: 215564123 Test: manual for switches, ZenRuleScheduleHelperTest for descriptions Change-Id: I3ad579503adae0a66dfa3093b4e3df77db0ede31
This commit is contained in:
@@ -42,7 +42,6 @@ import com.android.settings.R;
|
|||||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@@ -56,8 +55,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
|
|||||||
|
|
||||||
public static final String ACTION = Settings.ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS;
|
public static final String ACTION = Settings.ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS;
|
||||||
|
|
||||||
// per-instance to ensure we're always using the current locale
|
private final ZenRuleScheduleHelper mScheduleHelper = new ZenRuleScheduleHelper();
|
||||||
private final SimpleDateFormat mDayFormat = new SimpleDateFormat("EEE");
|
|
||||||
|
|
||||||
private Preference mDays;
|
private Preference mDays;
|
||||||
private TimePickerPreference mStart;
|
private TimePickerPreference mStart;
|
||||||
@@ -149,30 +147,11 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateDays() {
|
private void updateDays() {
|
||||||
// Compute an ordered, delimited list of day names based on the persisted user config.
|
String desc = mScheduleHelper.getDaysDescription(mContext, mSchedule);
|
||||||
final int[] days = mSchedule.days;
|
if (desc != null) {
|
||||||
if (days != null && days.length > 0) {
|
mDays.setSummary(desc);
|
||||||
final StringBuilder sb = new StringBuilder();
|
mDays.notifyDependencyChange(false);
|
||||||
final Calendar c = Calendar.getInstance();
|
return;
|
||||||
int[] daysOfWeek = ZenModeScheduleDaysSelection.getDaysOfWeekForLocale(c);
|
|
||||||
for (int i = 0; i < daysOfWeek.length; i++) {
|
|
||||||
final int day = daysOfWeek[i];
|
|
||||||
for (int j = 0; j < days.length; j++) {
|
|
||||||
if (day == days[j]) {
|
|
||||||
c.set(Calendar.DAY_OF_WEEK, day);
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
sb.append(mContext.getString(R.string.summary_divider_text));
|
|
||||||
}
|
|
||||||
sb.append(mDayFormat.format(c.getTime()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sb.length() > 0) {
|
|
||||||
mDays.setSummary(sb);
|
|
||||||
mDays.notifyDependencyChange(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mDays.setSummary(R.string.zen_mode_schedule_rule_days_none);
|
mDays.setSummary(R.string.zen_mode_schedule_rule_days_none);
|
||||||
mDays.notifyDependencyChange(true);
|
mDays.notifyDependencyChange(true);
|
||||||
|
@@ -23,22 +23,20 @@ import android.content.Intent;
|
|||||||
import android.content.pm.ComponentInfo;
|
import android.content.pm.ComponentInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.service.notification.ZenModeConfig;
|
import android.service.notification.ZenModeConfig;
|
||||||
import android.view.View;
|
import android.service.notification.ZenModeConfig.ScheduleInfo;
|
||||||
import android.widget.CheckBox;
|
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceViewHolder;
|
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.utils.ManagedServiceSettings;
|
import com.android.settings.utils.ManagedServiceSettings;
|
||||||
import com.android.settings.utils.ZenServiceListing;
|
import com.android.settings.utils.ZenServiceListing;
|
||||||
|
import com.android.settingslib.PrimarySwitchPreference;
|
||||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||||
import com.android.settingslib.widget.TwoTargetPreference;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ZenRulePreference extends TwoTargetPreference {
|
public class ZenRulePreference extends PrimarySwitchPreference {
|
||||||
private static final ManagedServiceSettings.Config CONFIG =
|
private static final ManagedServiceSettings.Config CONFIG =
|
||||||
ZenModeAutomationSettings.getConditionProviderConfig();
|
ZenModeAutomationSettings.getConditionProviderConfig();
|
||||||
final String mId;
|
final String mId;
|
||||||
@@ -53,14 +51,13 @@ public class ZenRulePreference extends TwoTargetPreference {
|
|||||||
CharSequence mName;
|
CharSequence mName;
|
||||||
|
|
||||||
private Intent mIntent;
|
private Intent mIntent;
|
||||||
private boolean mChecked;
|
|
||||||
private CheckBox mCheckBox;
|
private final ZenRuleScheduleHelper mScheduleHelper = new ZenRuleScheduleHelper();
|
||||||
|
|
||||||
public ZenRulePreference(Context context,
|
public ZenRulePreference(Context context,
|
||||||
final Map.Entry<String, AutomaticZenRule> ruleEntry,
|
final Map.Entry<String, AutomaticZenRule> ruleEntry,
|
||||||
Fragment parent, MetricsFeatureProvider metricsProvider) {
|
Fragment parent, MetricsFeatureProvider metricsProvider) {
|
||||||
super(context);
|
super(context);
|
||||||
setLayoutResource(R.layout.preference_checkable_two_target);
|
|
||||||
mBackend = ZenModeBackend.getInstance(context);
|
mBackend = ZenModeBackend.getInstance(context);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mRule = ruleEntry.getValue();
|
mRule = ruleEntry.getValue();
|
||||||
@@ -72,50 +69,11 @@ public class ZenRulePreference extends TwoTargetPreference {
|
|||||||
mServiceListing.reloadApprovedServices();
|
mServiceListing.reloadApprovedServices();
|
||||||
mPref = this;
|
mPref = this;
|
||||||
mMetricsFeatureProvider = metricsProvider;
|
mMetricsFeatureProvider = metricsProvider;
|
||||||
mChecked = mRule.isEnabled();
|
|
||||||
setAttributes(mRule);
|
setAttributes(mRule);
|
||||||
setWidgetLayoutResource(getSecondTargetResId());
|
setWidgetLayoutResource(getSecondTargetResId());
|
||||||
}
|
|
||||||
|
|
||||||
protected int getSecondTargetResId() {
|
// initialize the checked state of the preference
|
||||||
if (mIntent != null) {
|
super.setChecked(mRule.isEnabled());
|
||||||
return R.layout.zen_rule_widget;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
|
||||||
super.onBindViewHolder(view);
|
|
||||||
View settingsWidget = view.findViewById(android.R.id.widget_frame);
|
|
||||||
View divider = view.findViewById(R.id.two_target_divider);
|
|
||||||
if (mIntent != null) {
|
|
||||||
divider.setVisibility(View.VISIBLE);
|
|
||||||
settingsWidget.setVisibility(View.VISIBLE);
|
|
||||||
settingsWidget.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
mContext.startActivity(mIntent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
divider.setVisibility(View.GONE);
|
|
||||||
settingsWidget.setVisibility(View.GONE);
|
|
||||||
settingsWidget.setOnClickListener(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
View checkboxContainer = view.findViewById(R.id.checkbox_container);
|
|
||||||
if (checkboxContainer != null) {
|
|
||||||
checkboxContainer.setOnClickListener(mOnCheckBoxClickListener);
|
|
||||||
}
|
|
||||||
mCheckBox = (CheckBox) view.findViewById(com.android.internal.R.id.checkbox);
|
|
||||||
if (mCheckBox != null) {
|
|
||||||
mCheckBox.setChecked(mChecked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChecked() {
|
|
||||||
return mChecked;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updatePreference(AutomaticZenRule rule) {
|
public void updatePreference(AutomaticZenRule rule) {
|
||||||
@@ -126,34 +84,24 @@ public class ZenRulePreference extends TwoTargetPreference {
|
|||||||
|
|
||||||
if (mRule.isEnabled() != rule.isEnabled()) {
|
if (mRule.isEnabled() != rule.isEnabled()) {
|
||||||
setChecked(rule.isEnabled());
|
setChecked(rule.isEnabled());
|
||||||
setSummary(computeRuleSummary(rule));
|
|
||||||
}
|
}
|
||||||
|
setSummary(computeRuleSummary(rule));
|
||||||
mRule = rule;
|
mRule = rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick() {
|
public void onClick() {
|
||||||
mOnCheckBoxClickListener.onClick(null);
|
mContext.startActivity(mIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setChecked(boolean checked) {
|
@Override
|
||||||
mChecked = checked;
|
public void setChecked(boolean checked) {
|
||||||
if (mCheckBox != null) {
|
mRule.setEnabled(checked);
|
||||||
mCheckBox.setChecked(checked);
|
mBackend.updateZenRule(mId, mRule);
|
||||||
}
|
setAttributes(mRule);
|
||||||
|
super.setChecked(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
private View.OnClickListener mOnCheckBoxClickListener = new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
mRule.setEnabled(!mChecked);
|
|
||||||
mBackend.updateZenRule(mId, mRule);
|
|
||||||
setChecked(mRule.isEnabled());
|
|
||||||
setAttributes(mRule);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected void setAttributes(AutomaticZenRule rule) {
|
protected void setAttributes(AutomaticZenRule rule) {
|
||||||
final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
|
final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
|
||||||
rule.getConditionId(), true);
|
rule.getConditionId(), true);
|
||||||
@@ -178,6 +126,30 @@ public class ZenRulePreference extends TwoTargetPreference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String computeRuleSummary(AutomaticZenRule rule) {
|
private String computeRuleSummary(AutomaticZenRule rule) {
|
||||||
|
if (rule != null) {
|
||||||
|
// handle schedule-based rules
|
||||||
|
ScheduleInfo schedule =
|
||||||
|
ZenModeConfig.tryParseScheduleConditionId(rule.getConditionId());
|
||||||
|
if (schedule != null) {
|
||||||
|
String desc = mScheduleHelper.getDaysAndTimeSummary(mContext, schedule);
|
||||||
|
return (desc != null) ? desc :
|
||||||
|
mContext.getResources().getString(
|
||||||
|
R.string.zen_mode_schedule_rule_days_none);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle event-based rules
|
||||||
|
ZenModeConfig.EventInfo event =
|
||||||
|
ZenModeConfig.tryParseEventConditionId(rule.getConditionId());
|
||||||
|
if (event != null) {
|
||||||
|
if (event.calName != null) {
|
||||||
|
return event.calName;
|
||||||
|
} else {
|
||||||
|
return mContext.getResources().getString(
|
||||||
|
R.string.zen_mode_event_rule_calendar_any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (rule == null || !rule.isEnabled())
|
return (rule == null || !rule.isEnabled())
|
||||||
? mContext.getResources().getString(R.string.switch_off_text)
|
? mContext.getResources().getString(R.string.switch_off_text)
|
||||||
: mContext.getResources().getString(R.string.switch_on_text);
|
: mContext.getResources().getString(R.string.switch_on_text);
|
||||||
|
@@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.notification.zen;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.service.notification.ZenModeConfig.ScheduleInfo;
|
||||||
|
import android.text.format.DateFormat;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for shared functionality regarding descriptions of custom zen rule schedules.
|
||||||
|
*/
|
||||||
|
public class ZenRuleScheduleHelper {
|
||||||
|
// per-instance to ensure we're always using the current locale
|
||||||
|
private SimpleDateFormat mDayFormat;
|
||||||
|
|
||||||
|
// Default constructor, which will use the current locale.
|
||||||
|
public ZenRuleScheduleHelper() {
|
||||||
|
mDayFormat = new SimpleDateFormat("EEE");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor for tests to provide an explicit locale
|
||||||
|
@VisibleForTesting
|
||||||
|
public ZenRuleScheduleHelper(Locale locale) {
|
||||||
|
mDayFormat = new SimpleDateFormat("EEE", locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an ordered, comma-separated list of the days that a schedule applies, or null if no
|
||||||
|
* days.
|
||||||
|
*/
|
||||||
|
public String getDaysDescription(Context context, ScheduleInfo schedule) {
|
||||||
|
// Compute an ordered, delimited list of day names based on the persisted user config.
|
||||||
|
final int[] days = schedule.days;
|
||||||
|
if (days != null && days.length > 0) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
final Calendar c = Calendar.getInstance();
|
||||||
|
int[] daysOfWeek = ZenModeScheduleDaysSelection.getDaysOfWeekForLocale(c);
|
||||||
|
for (int i = 0; i < daysOfWeek.length; i++) {
|
||||||
|
final int day = daysOfWeek[i];
|
||||||
|
for (int j = 0; j < days.length; j++) {
|
||||||
|
if (day == days[j]) {
|
||||||
|
c.set(Calendar.DAY_OF_WEEK, day);
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append(context.getString(R.string.summary_divider_text));
|
||||||
|
}
|
||||||
|
sb.append(mDayFormat.format(c.getTime()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an ordered summarized list of the days on which this schedule applies, with
|
||||||
|
* adjacent days grouped together ("Sun-Wed" instead of "Sun,Mon,Tue,Wed").
|
||||||
|
*/
|
||||||
|
public String getShortDaysSummary(Context context, ScheduleInfo schedule) {
|
||||||
|
// Compute a list of days with contiguous days grouped together, for example: "Sun-Thu" or
|
||||||
|
// "Sun-Mon,Wed,Fri"
|
||||||
|
final int[] days = schedule.days;
|
||||||
|
if (days != null && days.length > 0) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
final Calendar cStart = Calendar.getInstance();
|
||||||
|
final Calendar cEnd = Calendar.getInstance();
|
||||||
|
int[] daysOfWeek = ZenModeScheduleDaysSelection.getDaysOfWeekForLocale(cStart);
|
||||||
|
// the i for loop goes through days in order as determined by locale. as we walk through
|
||||||
|
// the days of the week, keep track of "start" and "last seen" as indicators for
|
||||||
|
// what's contiguous, and initialize them to something not near actual indices
|
||||||
|
int startDay = Integer.MIN_VALUE;
|
||||||
|
int lastSeenDay = Integer.MIN_VALUE;
|
||||||
|
for (int i = 0; i < daysOfWeek.length; i++) {
|
||||||
|
final int day = daysOfWeek[i];
|
||||||
|
|
||||||
|
// by default, output if this day is *not* included in the schedule, and thus
|
||||||
|
// ends a previously existing block. if this day is included in the schedule
|
||||||
|
// after all (as will be determined in the inner for loop), then output will be set
|
||||||
|
// to false.
|
||||||
|
boolean output = (i == lastSeenDay + 1);
|
||||||
|
for (int j = 0; j < days.length; j++) {
|
||||||
|
if (day == days[j]) {
|
||||||
|
// match for this day in the schedule (indicated by counter i)
|
||||||
|
if (i == lastSeenDay + 1) {
|
||||||
|
// contiguous to the block we're walking through right now, record it
|
||||||
|
// (specifically, i, the day index) and move on to the next day
|
||||||
|
lastSeenDay = i;
|
||||||
|
output = false;
|
||||||
|
} else {
|
||||||
|
// it's a match, but not 1 past the last match, we are starting a new
|
||||||
|
// block
|
||||||
|
startDay = i;
|
||||||
|
lastSeenDay = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is a match on the last day, also make sure to output at the end
|
||||||
|
// of this loop, and mark the day as the last day we'll have seen in the
|
||||||
|
// scheduled days.
|
||||||
|
if (i == daysOfWeek.length - 1) {
|
||||||
|
output = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// output in either of 2 cases: this day is not a match, so has ended any previous
|
||||||
|
// block, or this day *is* a match but is the last day of the week, so we need to
|
||||||
|
// summarize
|
||||||
|
if (output) {
|
||||||
|
// either describe just the single day if startDay == lastSeenDay, or
|
||||||
|
// output "startDay - lastSeenDay" as a group
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append(context.getString(R.string.summary_divider_text));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startDay == lastSeenDay) {
|
||||||
|
// last group was only one day
|
||||||
|
cStart.set(Calendar.DAY_OF_WEEK, daysOfWeek[startDay]);
|
||||||
|
sb.append(mDayFormat.format(cStart.getTime()));
|
||||||
|
} else {
|
||||||
|
// last group was a contiguous group of days, so group them together
|
||||||
|
cStart.set(Calendar.DAY_OF_WEEK, daysOfWeek[startDay]);
|
||||||
|
cEnd.set(Calendar.DAY_OF_WEEK, daysOfWeek[lastSeenDay]);
|
||||||
|
sb.append(context.getString(R.string.summary_range_symbol_combination,
|
||||||
|
mDayFormat.format(cStart.getTime()),
|
||||||
|
mDayFormat.format(cEnd.getTime())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for representing the specified time in string format.
|
||||||
|
*/
|
||||||
|
private String timeString(Context context, int hour, int minute) {
|
||||||
|
final Calendar c = Calendar.getInstance();
|
||||||
|
c.set(Calendar.HOUR_OF_DAY, hour);
|
||||||
|
c.set(Calendar.MINUTE, minute);
|
||||||
|
return DateFormat.getTimeFormat(context).format(c.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combination description for a zen rule schedule including both day summary and time bounds.
|
||||||
|
*/
|
||||||
|
public String getDaysAndTimeSummary(Context context, ScheduleInfo schedule) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
String daysSummary = getShortDaysSummary(context, schedule);
|
||||||
|
if (daysSummary == null) {
|
||||||
|
// no use outputting times without dates
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
sb.append(daysSummary);
|
||||||
|
sb.append(context.getString(R.string.summary_divider_text));
|
||||||
|
sb.append(context.getString(R.string.summary_range_symbol_combination,
|
||||||
|
timeString(context, schedule.startHour, schedule.startMinute),
|
||||||
|
timeString(context, schedule.endHour, schedule.endMinute)));
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.notification.zen;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.LocaleList;
|
||||||
|
import android.service.notification.ZenModeConfig.ScheduleInfo;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ZenRuleScheduleHelperTest {
|
||||||
|
private ZenRuleScheduleHelper mScheduleHelper;
|
||||||
|
private ScheduleInfo mScheduleInfo;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Resources mResources;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
// explicitly initialize to Locale.US just for ease of explicitly testing the string values
|
||||||
|
// of the days of the week if the test locale doesn't happen to be in the US
|
||||||
|
mScheduleHelper = new ZenRuleScheduleHelper(Locale.US);
|
||||||
|
mScheduleInfo = new ScheduleInfo();
|
||||||
|
|
||||||
|
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
|
when(mContext.getResources()).thenReturn(mResources);
|
||||||
|
|
||||||
|
// Resources will be called upon to join strings together, either to get a divider
|
||||||
|
// or a combination of two strings. Conveniently, these have different signatures.
|
||||||
|
// Divider method calls getString(string divider id)
|
||||||
|
when(mResources.getString(anyInt())).thenReturn(",");
|
||||||
|
|
||||||
|
// Combination method calls getString(combination id, first item, second item)
|
||||||
|
// and returns "first - second"
|
||||||
|
when(mResources.getString(anyInt(), anyString(), anyString())).thenAnswer(
|
||||||
|
invocation -> {
|
||||||
|
return invocation.getArgument(1).toString() // first item
|
||||||
|
+ "-"
|
||||||
|
+ invocation.getArgument(2).toString(); // second item
|
||||||
|
});
|
||||||
|
|
||||||
|
// for locale used in time format
|
||||||
|
Configuration config = new Configuration();
|
||||||
|
config.setLocales(new LocaleList(Locale.US));
|
||||||
|
when(mResources.getConfiguration()).thenReturn(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDaysDescription() {
|
||||||
|
// Test various cases of where the days are set.
|
||||||
|
// No days
|
||||||
|
mScheduleInfo.days = new int[] {};
|
||||||
|
assertThat(mScheduleHelper.getDaysDescription(mContext, mScheduleInfo)).isNull();
|
||||||
|
|
||||||
|
// one day
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.FRIDAY};
|
||||||
|
assertThat(mScheduleHelper.getDaysDescription(mContext, mScheduleInfo)).isEqualTo("Fri");
|
||||||
|
|
||||||
|
// Monday through Friday
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY,
|
||||||
|
Calendar.THURSDAY, Calendar.FRIDAY};
|
||||||
|
assertThat(mScheduleHelper.getDaysDescription(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Mon,Tue,Wed,Thu,Fri");
|
||||||
|
|
||||||
|
// Some scattered days of the week
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.SUNDAY, Calendar.WEDNESDAY, Calendar.THURSDAY,
|
||||||
|
Calendar.SATURDAY};
|
||||||
|
assertThat(mScheduleHelper.getDaysDescription(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Sun,Wed,Thu,Sat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getShortDaysSummary_noOrSingleDays() {
|
||||||
|
// Test various cases for grouping and not-grouping of days.
|
||||||
|
// No days
|
||||||
|
mScheduleInfo.days = new int[]{};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo)).isNull();
|
||||||
|
|
||||||
|
// A single day at the beginning of the week
|
||||||
|
mScheduleInfo.days = new int[]{Calendar.SUNDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo)).isEqualTo("Sun");
|
||||||
|
|
||||||
|
// A single day in the middle of the week
|
||||||
|
mScheduleInfo.days = new int[]{Calendar.THURSDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo)).isEqualTo("Thu");
|
||||||
|
|
||||||
|
// A single day at the end of the week
|
||||||
|
mScheduleInfo.days = new int[]{Calendar.SATURDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo)).isEqualTo("Sat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getShortDaysSummary_oneGroup() {
|
||||||
|
// The whole week
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY,
|
||||||
|
Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Sun-Sat");
|
||||||
|
|
||||||
|
// Various cases of one big group
|
||||||
|
// Sunday through Thursday
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY,
|
||||||
|
Calendar.WEDNESDAY, Calendar.THURSDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Sun-Thu");
|
||||||
|
|
||||||
|
// Wednesday through Saturday
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.WEDNESDAY, Calendar.THURSDAY,
|
||||||
|
Calendar.FRIDAY, Calendar.SATURDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Wed-Sat");
|
||||||
|
|
||||||
|
// Monday through Friday
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.MONDAY, Calendar.TUESDAY,
|
||||||
|
Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Mon-Fri");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getShortDaysSummary_mixed() {
|
||||||
|
// cases combining groups and single days scattered around
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.SUNDAY, Calendar.TUESDAY,
|
||||||
|
Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.SATURDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Sun,Tue-Thu,Sat");
|
||||||
|
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY,
|
||||||
|
Calendar.WEDNESDAY, Calendar.FRIDAY, Calendar.SATURDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Sun-Wed,Fri-Sat");
|
||||||
|
|
||||||
|
mScheduleInfo.days = new int[] {Calendar.MONDAY, Calendar.WEDNESDAY,
|
||||||
|
Calendar.FRIDAY, Calendar.SATURDAY};
|
||||||
|
assertThat(mScheduleHelper.getShortDaysSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Mon,Wed,Fri-Sat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getDaysAndTimeSummary() {
|
||||||
|
// Combination days & time settings
|
||||||
|
// No days, no output, even if the times are set.
|
||||||
|
mScheduleInfo.startHour = 10;
|
||||||
|
mScheduleInfo.endHour = 16;
|
||||||
|
mScheduleInfo.days = new int[]{};
|
||||||
|
assertThat(mScheduleHelper.getDaysAndTimeSummary(mContext, mScheduleInfo)).isNull();
|
||||||
|
|
||||||
|
// If there are days then they are combined with the time combination
|
||||||
|
mScheduleInfo.days = new int[]{Calendar.SUNDAY, Calendar.MONDAY, Calendar.WEDNESDAY};
|
||||||
|
assertThat(mScheduleHelper.getDaysAndTimeSummary(mContext, mScheduleInfo))
|
||||||
|
.isEqualTo("Sun-Mon,Wed,10:00 AM-4:00 PM");
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user