DND ixD changes

- Subtext in Settings > Sound updated
- new icons for automatic dnd rules
- no toast when toggling on/off dnd rules
- dnd dialog has a warning if dnd will cause user to miss next alarm

Test: make ROBOTEST_FILTER=ZenModePreferenceControllerTest RunSettingsRoboTests -j40
Fixes: 72494029
Fixes: 72655216
Fixes: 72655609
Change-Id: I9d86d82529079f35e362f93e10914f0a60229cd8
This commit is contained in:
Beverly
2018-02-01 18:14:33 -05:00
committed by Beverly Tai
parent 1297029728
commit 036d7e0bd9
20 changed files with 306 additions and 670 deletions

34
res/drawable/ic_event.xml Normal file
View File

@@ -0,0 +1,34 @@
<!--
Copyright (C) 2018 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.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid
android:color="?android:attr/colorAccent" />
<size
android:width="@dimen/dashboard_tile_image_size"
android:height="@dimen/dashboard_tile_image_size" />
</shape>
</item>
<item
android:width="@dimen/dashboard_tile_foreground_image_size"
android:height="@dimen/dashboard_tile_foreground_image_size"
android:start="@dimen/dashboard_tile_foreground_image_inset"
android:top="@dimen/dashboard_tile_foreground_image_inset"
android:drawable="@drawable/ic_event_white" />
</layer-list>

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M17.0,12.0l-5.0,0.0l0.0,5.0l5.0,0.0l0.0,-5.0zM16.0,1.0l0.0,2.0L8.0,3.0L8.0,1.0L6.0,1.0l0.0,2.0L5.0,3.0c-1.11,0.0 -1.9,0.9 -1.99,2.0L3.0,19.0c0.0,1.0 0.89,2.0 2.0,2.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L21.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0l-1.0,0.0L18.0,1.0l-2.0,0.0zm3.0,18.0L5.0,19.0L5.0,8.0l14.0,0.0l0.0,11.0z"/>
</vector>

View File

@@ -0,0 +1,34 @@
<!--
Copyright (C) 2018 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.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid
android:color="?android:attr/colorAccent" />
<size
android:width="@dimen/dashboard_tile_image_size"
android:height="@dimen/dashboard_tile_image_size" />
</shape>
</item>
<item
android:width="@dimen/dashboard_tile_foreground_image_size"
android:height="@dimen/dashboard_tile_foreground_image_size"
android:start="@dimen/dashboard_tile_foreground_image_inset"
android:top="@dimen/dashboard_tile_foreground_image_inset"
android:drawable="@drawable/ic_timelapse_white" />
</layer-list>

View File

@@ -0,0 +1,25 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M16.24,7.76C15.07,6.59 13.54,6.0 12.0,6.0l0.0,6.0l-4.24,4.24c2.34,2.34 6.14,2.34 8.49,0.0 2.34,-2.34 2.34,-6.14 -0.01,-8.48zM12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zm0.0,18.0c-4.42,0.0 -8.0,-3.58 -8.0,-8.0s3.58,-8.0 8.0,-8.0 8.0,3.58 8.0,8.0 -3.58,8.0 -8.0,8.0z"/>
</vector>

View File

@@ -17,31 +17,25 @@
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="bottom"
android:paddingStart="72dp"
android:paddingEnd="72dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content">
<Button <Button
android:id="@+id/zen_mode_settings_turn_on_button" android:id="@+id/zen_mode_settings_turn_on_button"
style="@style/ActionPrimaryButton" style="@style/ActionPrimaryButton"
android:layout_width="0dp" android:layout_marginStart="@dimen/screen_margin_sides"
android:layout_weight="1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left" android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_on" android:text="@string/zen_mode_button_turn_on"/>
android:paddingEnd="8dp" />
<Button <Button
android:id="@+id/zen_mode_settings_turn_off_button" android:id="@+id/zen_mode_settings_turn_off_button"
style="@style/ActionSecondaryButton" style="@style/ActionSecondaryButton"
android:layout_width="0dp" android:layout_marginStart="@dimen/screen_margin_sides"
android:layout_weight="1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left" android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_off" android:text="@string/zen_mode_button_turn_off" />
android:paddingEnd="8dp" />
</LinearLayout> </LinearLayout>

View File

@@ -23,10 +23,9 @@
<ImageView <ImageView
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="wrap_content" android:layout_width="@dimen/app_icon_size"
android:layout_height="wrap_content" android:layout_height="@dimen/app_icon_size"
android:layout_gravity="center" android:layout_gravity="center"/>
/>
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@@ -6937,6 +6937,21 @@
<!-- [CHAR LIMIT=20] Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. --> <!-- [CHAR LIMIT=20] Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. -->
<string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string> <string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
<!-- Sound settings screen, summary format of do not disturb when on. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_on">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
<!-- Sound settings screen, summary format of do not disturb when off with extra information. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 rule can turn on automatically">%1$s</xliff:g></string>
<!-- Sound settings screen, summary format of do not disturb when off with no extra information. [CHAR LIMIT=NONE] -->
<string name="zen_mode_sound_summary_off">Off</string>
<!-- Summary for the Sound Do not Disturb option when at least one automatic rules is enabled. [CHAR LIMIT=NONE]-->
<plurals name="zen_mode_sound_summary_summary_off_info">
<item quantity="one">1 rule can turn on automatically</item>
<item quantity="other"><xliff:g id="on_count" example="3">%d</xliff:g> rules can turn on automatically</item>
</plurals>
<!-- Work Sounds: Work sound settings section header. [CHAR LIMIT=50] --> <!-- Work Sounds: Work sound settings section header. [CHAR LIMIT=50] -->
<string name="sound_work_settings">Work profile sounds</string> <string name="sound_work_settings">Work profile sounds</string>

View File

@@ -1,467 +0,0 @@
package com.android.settings.notification;
/*
* Copyright (C) 2018 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.
*/
import static android.util.Log.wtf;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Objects;
public class EnableZenModeDialog extends InstrumentedDialogFragment {
private static final String TAG = "EnableZenModeDialog";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
@VisibleForTesting
public static final int FOREVER_CONDITION_INDEX = 0;
@VisibleForTesting
public static final int COUNTDOWN_CONDITION_INDEX = 1;
@VisibleForTesting
public static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
@VisibleForTesting
protected Activity mActivity;
private static final int SECONDS_MS = 1000;
private static final int MINUTES_MS = 60 * SECONDS_MS;
@VisibleForTesting
protected Uri mForeverId;
private int mBucketIndex = -1;
private AlarmManager mAlarmManager;
private int mUserId;
private boolean mAttached;
@VisibleForTesting
protected Context mContext;
private RadioGroup mZenRadioGroup;
@VisibleForTesting
protected LinearLayout mZenRadioGroupContent;
private int MAX_MANUAL_DND_OPTIONS = 3;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
NotificationManager noMan = (NotificationManager) getContext().
getSystemService(Context.NOTIFICATION_SERVICE);
mContext = getContext();
mForeverId = Condition.newId(mContext).appendPath("forever").build();
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mUserId = mContext.getUserId();
mAttached = false;
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
.setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
int checkedId = mZenRadioGroup.getCheckedRadioButtonId();
ConditionTag tag = getConditionTagAt(checkedId);
if (isForever(tag.condition)) {
MetricsLogger.action(getContext(),
MetricsProto.MetricsEvent.
NOTIFICATION_ZEN_MODE_TOGGLE_ON_FOREVER);
} else if (isAlarm(tag.condition)) {
MetricsLogger.action(getContext(),
MetricsProto.MetricsEvent.
NOTIFICATION_ZEN_MODE_TOGGLE_ON_ALARM);
} else if (isCountdown(tag.condition)) {
MetricsLogger.action(getContext(),
MetricsProto.MetricsEvent.
NOTIFICATION_ZEN_MODE_TOGGLE_ON_COUNTDOWN);
} else {
wtf(TAG, "Invalid manual condition: " + tag.condition);
}
// always triggers priority-only dnd with chosen condition
noMan.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
getRealConditionId(tag.condition), TAG);
}
});
View contentView = getContentView();
bindConditions(forever());
builder.setView(contentView);
return builder.create();
}
private void hideAllConditions() {
final int N = mZenRadioGroupContent.getChildCount();
for (int i = 0; i < N; i++) {
mZenRadioGroupContent.getChildAt(i).setVisibility(View.GONE);
}
}
protected View getContentView() {
if (mActivity == null) {
mActivity = getActivity();
}
final LayoutInflater inflater = mActivity.getLayoutInflater();
View contentView = inflater.inflate(R.layout.zen_mode_turn_on_dialog_container, null);
ScrollView container = (ScrollView) contentView.findViewById(R.id.container);
mZenRadioGroup = container.findViewById(R.id.zen_radio_buttons);
mZenRadioGroupContent = container.findViewById(R.id.zen_radio_buttons_content);
for (int i = 0; i < MAX_MANUAL_DND_OPTIONS; i++) {
final View radioButton = inflater.inflate(R.layout.zen_mode_radio_button,
mZenRadioGroup, false);
mZenRadioGroup.addView(radioButton);
radioButton.setId(i);
final View radioButtonContent = inflater.inflate(R.layout.zen_mode_condition,
mZenRadioGroupContent, false);
radioButtonContent.setId(i + MAX_MANUAL_DND_OPTIONS);
mZenRadioGroupContent.addView(radioButtonContent);
}
hideAllConditions();
return contentView;
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_ENABLE_DIALOG;
}
@VisibleForTesting
protected void bind(final Condition condition, final View row, final int rowId) {
if (condition == null) throw new IllegalArgumentException("condition must not be null");
final boolean enabled = condition.state == Condition.STATE_TRUE;
final ConditionTag tag = row.getTag() != null ? (ConditionTag) row.getTag() :
new ConditionTag();
row.setTag(tag);
final boolean first = tag.rb == null;
if (tag.rb == null) {
tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowId);
}
tag.condition = condition;
final Uri conditionId = getConditionId(tag.condition);
if (DEBUG) Log.d(TAG, "bind i=" + mZenRadioGroupContent.indexOfChild(row) + " first="
+ first + " condition=" + conditionId);
tag.rb.setEnabled(enabled);
tag.rb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
tag.rb.setChecked(true);
if (DEBUG) Log.d(TAG, "onCheckedChanged " + conditionId);
MetricsLogger.action(mContext,
MetricsProto.MetricsEvent.QS_DND_CONDITION_SELECT);
announceConditionSelection(tag);
}
}
});
updateUi(tag, row, condition, enabled, rowId, conditionId);
row.setVisibility(View.VISIBLE);
}
@VisibleForTesting
protected ConditionTag getConditionTagAt(int index) {
return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
}
@VisibleForTesting
protected void bindConditions(Condition c) {
// forever
bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
FOREVER_CONDITION_INDEX);
if (c == null) {
bindGenericCountdown();
bindNextAlarm(getTimeUntilNextAlarmCondition());
} else if (isForever(c)) {
getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
bindGenericCountdown();
bindNextAlarm(getTimeUntilNextAlarmCondition());
} else {
if (isAlarm(c)) {
bindGenericCountdown();
bindNextAlarm(c);
getConditionTagAt(COUNTDOWN_ALARM_CONDITION_INDEX).rb.setChecked(true);
} else if (isCountdown(c)) {
bindNextAlarm(getTimeUntilNextAlarmCondition());
bind(c, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
COUNTDOWN_CONDITION_INDEX);
getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
} else {
wtf(TAG, "Invalid manual condition: " + c);
}
}
}
public static Uri getConditionId(Condition condition) {
return condition != null ? condition.id : null;
}
public Condition forever() {
Uri foreverId = Condition.newId(mContext).appendPath("forever").build();
return new Condition(foreverId, foreverSummary(mContext), "", "", 0 /*icon*/,
Condition.STATE_TRUE, 0 /*flags*/);
}
public long getNextAlarm() {
final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
return info != null ? info.getTriggerTime() : 0;
}
@VisibleForTesting
protected boolean isAlarm(Condition c) {
return c != null && ZenModeConfig.isValidCountdownToAlarmConditionId(c.id);
}
@VisibleForTesting
protected boolean isCountdown(Condition c) {
return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
}
private boolean isForever(Condition c) {
return c != null && mForeverId.equals(c.id);
}
private Uri getRealConditionId(Condition condition) {
return isForever(condition) ? null : getConditionId(condition);
}
private String foreverSummary(Context context) {
return context.getString(com.android.internal.R.string.zen_mode_forever);
}
private static void setToMidnight(Calendar calendar) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
}
// Returns a time condition if the next alarm is within the next week.
@VisibleForTesting
protected Condition getTimeUntilNextAlarmCondition() {
GregorianCalendar weekRange = new GregorianCalendar();
setToMidnight(weekRange);
weekRange.add(Calendar.DATE, 6);
final long nextAlarmMs = getNextAlarm();
if (nextAlarmMs > 0) {
GregorianCalendar nextAlarm = new GregorianCalendar();
nextAlarm.setTimeInMillis(nextAlarmMs);
setToMidnight(nextAlarm);
if (weekRange.compareTo(nextAlarm) >= 0) {
return ZenModeConfig.toNextAlarmCondition(mContext, nextAlarmMs,
ActivityManager.getCurrentUser());
}
}
return null;
}
@VisibleForTesting
protected void bindGenericCountdown() {
mBucketIndex = DEFAULT_BUCKET_INDEX;
Condition countdown = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
if (!mAttached || getConditionTagAt(COUNTDOWN_CONDITION_INDEX).condition == null) {
bind(countdown, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
COUNTDOWN_CONDITION_INDEX);
}
}
private void updateUi(ConditionTag tag, View row, Condition condition,
boolean enabled, int rowId, Uri conditionId) {
if (tag.lines == null) {
tag.lines = row.findViewById(android.R.id.content);
}
if (tag.line1 == null) {
tag.line1 = (TextView) row.findViewById(android.R.id.text1);
}
if (tag.line2 == null) {
tag.line2 = (TextView) row.findViewById(android.R.id.text2);
}
final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
: condition.summary;
final String line2 = condition.line2;
tag.line1.setText(line1);
if (TextUtils.isEmpty(line2)) {
tag.line2.setVisibility(View.GONE);
} else {
tag.line2.setVisibility(View.VISIBLE);
tag.line2.setText(line2);
}
tag.lines.setEnabled(enabled);
tag.lines.setAlpha(enabled ? 1 : .4f);
tag.lines.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tag.rb.setChecked(true);
}
});
// minus button
final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onClickTimeButton(row, tag, false /*down*/, rowId);
}
});
// plus button
final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onClickTimeButton(row, tag, true /*up*/, rowId);
}
});
final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
if (rowId == COUNTDOWN_CONDITION_INDEX && time > 0) {
button1.setVisibility(View.VISIBLE);
button2.setVisibility(View.VISIBLE);
if (mBucketIndex > -1) {
button1.setEnabled(mBucketIndex > 0);
button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
} else {
final long span = time - System.currentTimeMillis();
button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,
MAX_BUCKET_MINUTES, ActivityManager.getCurrentUser());
button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
}
button1.setAlpha(button1.isEnabled() ? 1f : .5f);
button2.setAlpha(button2.isEnabled() ? 1f : .5f);
} else {
button1.setVisibility(View.GONE);
button2.setVisibility(View.GONE);
}
}
@VisibleForTesting
protected void bindNextAlarm(Condition c) {
View alarmContent = mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX);
ConditionTag tag = (ConditionTag) alarmContent.getTag();
if (c != null && (!mAttached || tag == null || tag.condition == null)) {
bind(c, alarmContent, COUNTDOWN_ALARM_CONDITION_INDEX);
}
// hide the alarm radio button if there isn't a "next alarm condition"
tag = (ConditionTag) alarmContent.getTag();
boolean showAlarm = tag != null && tag.condition != null;
mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(
showAlarm ? View.VISIBLE : View.GONE);
alarmContent.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
}
private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.QS_DND_TIME, up);
Condition newCondition = null;
final int N = MINUTE_BUCKETS.length;
if (mBucketIndex == -1) {
// not on a known index, search for the next or prev bucket by time
final Uri conditionId = getConditionId(tag.condition);
final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
final long now = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
int j = up ? i : N - 1 - i;
final int bucketMinutes = MINUTE_BUCKETS[j];
final long bucketTime = now + bucketMinutes * MINUTES_MS;
if (up && bucketTime > time || !up && bucketTime < time) {
mBucketIndex = j;
newCondition = ZenModeConfig.toTimeCondition(mContext,
bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
false /*shortVersion*/);
break;
}
}
if (newCondition == null) {
mBucketIndex = DEFAULT_BUCKET_INDEX;
newCondition = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
}
} else {
// on a known index, simply increment or decrement
mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
newCondition = ZenModeConfig.toTimeCondition(mContext,
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
}
bind(newCondition, row, rowId);
tag.rb.setChecked(true);
announceConditionSelection(tag);
}
private void announceConditionSelection(ConditionTag tag) {
// condition will always be priority-only
String modeText = mContext.getString(R.string.zen_interruption_level_priority);
if (tag.line1 != null) {
mZenRadioGroupContent.announceForAccessibility(mContext.getString(
R.string.zen_mode_and_condition, modeText, tag.line1.getText()));
}
}
// used as the view tag on condition rows
@VisibleForTesting
protected static class ConditionTag {
public RadioButton rb;
public View lines;
public TextView line1;
public TextView line2;
public Condition condition;
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2018 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;
import android.app.Dialog;
import android.os.Bundle;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class SettingsEnableZenModeDialog extends InstrumentedDialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new com.android.settingslib.notification.EnableZenModeDialog(
getContext()).createDialog();
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_ENABLE_DIALOG;
}
}

View File

@@ -180,7 +180,7 @@ public class SoundSettings extends DashboardFragment {
SoundSettings fragment, VolumeSeekBarPreference.Callback callback, SoundSettings fragment, VolumeSeekBarPreference.Callback callback,
Lifecycle lifecycle) { Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>(); final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModePreferenceController(context)); controllers.add(new ZenModePreferenceController(context, lifecycle));
controllers.add(new VibrateWhenRingPreferenceController(context)); controllers.add(new VibrateWhenRingPreferenceController(context));
// === Volumes === // === Volumes ===
@@ -264,7 +264,7 @@ public class SoundSettings extends DashboardFragment {
public List<String> getNonIndexableKeys(Context context) { public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context); List<String> keys = super.getNonIndexableKeys(context);
// Duplicate results // Duplicate results
keys.add((new ZenModePreferenceController(context)).getPreferenceKey()); keys.add((new ZenModePreferenceController(context, null)).getPreferenceKey());
return keys; return keys;
} }
}; };

View File

@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.service.notification.ZenModeConfig;
import android.support.v14.preference.PreferenceFragment; import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.util.Slog; import android.util.Slog;
@@ -101,6 +102,13 @@ public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModeP
PackageManager packageManager = mContext.getPackageManager(); PackageManager packageManager = mContext.getPackageManager();
ApplicationInfo info = packageManager.getApplicationInfo( ApplicationInfo info = packageManager.getApplicationInfo(
mRule.getOwner().getPackageName(), 0); mRule.getOwner().getPackageName(), 0);
if (info.isSystemApp()) {
if (ZenModeConfig.isValidScheduleConditionId(mRule.getConditionId())) {
return mContext.getDrawable(R.drawable.ic_timelapse);
} else if (ZenModeConfig.isValidEventConditionId(mRule.getConditionId())) {
return mContext.getDrawable(R.drawable.ic_event);
}
}
return info.loadIcon(packageManager); return info.loadIcon(packageManager);
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to load icon - PackageManager.NameNotFoundException"); Slog.w(TAG, "Unable to load icon - PackageManager.NameNotFoundException");

View File

@@ -22,7 +22,6 @@ import android.content.Context;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceScreen;
import android.widget.Switch; import android.widget.Switch;
import android.widget.Toast;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.LayoutPreference; import com.android.settings.applications.LayoutPreference;
@@ -36,14 +35,11 @@ public class ZenAutomaticRuleSwitchPreferenceController extends
private static final String KEY = "zen_automatic_rule_switch"; private static final String KEY = "zen_automatic_rule_switch";
private AutomaticZenRule mRule; private AutomaticZenRule mRule;
private String mId; private String mId;
private Toast mEnabledToast;
private int mToastTextResource;
private SwitchBar mSwitchBar; private SwitchBar mSwitchBar;
public ZenAutomaticRuleSwitchPreferenceController(Context context, Fragment parent, public ZenAutomaticRuleSwitchPreferenceController(Context context, Fragment parent,
int toastTextResource, Lifecycle lifecycle) { Lifecycle lifecycle) {
super(context, KEY, parent, lifecycle); super(context, KEY, parent, lifecycle);
mToastTextResource = toastTextResource;
} }
@Override @Override
@@ -92,16 +88,5 @@ public class ZenAutomaticRuleSwitchPreferenceController extends
if (enabled == mRule.isEnabled()) return; if (enabled == mRule.isEnabled()) return;
mRule.setEnabled(enabled); mRule.setEnabled(enabled);
mBackend.setZenRule(mId, mRule); mBackend.setZenRule(mId, mRule);
if (enabled) {
final int toastText = mToastTextResource;
if (toastText != 0) {
mEnabledToast = Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT);
mEnabledToast.show();
}
} else {
if (mEnabledToast != null) {
mEnabledToast.cancel();
}
}
} }
} }

View File

@@ -62,7 +62,7 @@ public class ZenModeButtonPreferenceController extends AbstractZenModePreference
mZenButtonOn = (Button) ((LayoutPreference) preference) mZenButtonOn = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_on_button); .findViewById(R.id.zen_mode_settings_turn_on_button);
mZenButtonOn.setOnClickListener(v -> mZenButtonOn.setOnClickListener(v ->
new EnableZenModeDialog().show(mFragment, TAG)); new SettingsEnableZenModeDialog().show(mFragment, TAG));
} }
if (null == mZenButtonOff) { if (null == mZenButtonOff) {

View File

@@ -82,8 +82,7 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
List<AbstractPreferenceController> controllers = new ArrayList<>(); List<AbstractPreferenceController> controllers = new ArrayList<>();
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this, mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
getLifecycle()); getLifecycle());
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this, mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this, getLifecycle());
R.string.zen_event_rule_enabled_toast, getLifecycle());
controllers.add(mHeader); controllers.add(mHeader);
controllers.add(mSwitch); controllers.add(mSwitch);
return controllers; return controllers;

View File

@@ -16,18 +16,56 @@
package com.android.settings.notification; package com.android.settings.notification;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.Slog;
public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenceController { import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenceController
implements LifecycleObserver, OnResume, OnPause {
private static final String KEY_ZEN_MODE = "zen_mode"; private static final String KEY_ZEN_MODE = "zen_mode";
private SettingObserver mSettingObserver;
private ZenModeSettings.SummaryBuilder mSummaryBuilder; private ZenModeSettings.SummaryBuilder mSummaryBuilder;
public ZenModePreferenceController(Context context) { public ZenModePreferenceController(Context context, Lifecycle lifecycle) {
super(context); super(context);
mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context); mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mSettingObserver = new SettingObserver(screen.findPreference(KEY_ZEN_MODE));
}
@Override
public void onResume() {
if (mSettingObserver != null) {
mSettingObserver.register(mContext.getContentResolver());
}
}
@Override
public void onPause() {
if (mSettingObserver != null) {
mSettingObserver.unregister(mContext.getContentResolver());
}
} }
@Override @Override
@@ -44,7 +82,41 @@ public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenc
public void updateState(Preference preference) { public void updateState(Preference preference) {
super.updateState(preference); super.updateState(preference);
if (preference.isEnabled()) { if (preference.isEnabled()) {
preference.setSummary(mSummaryBuilder.getAutomaticRulesSummary()); preference.setSummary(mSummaryBuilder.getSoundSummary());
}
}
class SettingObserver extends ContentObserver {
private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
Settings.Global.ZEN_MODE_CONFIG_ETAG);
private final Preference mPreference;
public SettingObserver(Preference preference) {
super(new Handler());
mPreference = preference;
}
public void register(ContentResolver cr) {
cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL);
cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL);
}
public void unregister(ContentResolver cr) {
cr.unregisterContentObserver(this);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (ZEN_MODE_URI.equals(uri)) {
updateState(mPreference);
}
if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
updateState(mPreference);
}
} }
} }
} }

View File

@@ -200,8 +200,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
List<AbstractPreferenceController> controllers = new ArrayList<>(); List<AbstractPreferenceController> controllers = new ArrayList<>();
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this, mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
getLifecycle()); getLifecycle());
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this, mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this, getLifecycle());
R.string.zen_schedule_rule_enabled_toast, getLifecycle());
controllers.add(mHeader); controllers.add(mHeader);
controllers.add(mSwitch); controllers.add(mSwitch);

View File

@@ -115,6 +115,26 @@ public class ZenModeSettings extends ZenModeSettingsBase {
return mContext.getString(R.string.zen_mode_behavior_summary_custom); return mContext.getString(R.string.zen_mode_behavior_summary_custom);
} }
String getSoundSummary() {
int zenMode = NotificationManager.from(mContext).getZenMode();
if (zenMode != Settings.Global.ZEN_MODE_OFF) {
Policy policy = NotificationManager.from(mContext).getNotificationPolicy();
return mContext.getString(R.string.zen_mode_sound_summary_on,
getBehaviorSettingSummary(policy, zenMode));
} else {
final int count = getEnabledAutomaticRulesCount();
if (count > 0) {
return mContext.getString(R.string.zen_mode_sound_summary_off_with_info,
mContext.getResources().getQuantityString(
R.plurals.zen_mode_sound_summary_summary_off_info,
count, count));
}
return mContext.getString(R.string.zen_mode_sound_summary_off);
}
}
String getAutomaticRulesSummary() { String getAutomaticRulesSummary() {
final int count = getEnabledAutomaticRulesCount(); final int count = getEnabledAutomaticRulesCount();
return count == 0 ? mContext.getString(R.string.zen_mode_settings_summary_off) return count == 0 ? mContext.getString(R.string.zen_mode_settings_summary_off)

View File

@@ -119,13 +119,21 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
final LinearLayout v = (LinearLayout) LayoutInflater.from(mContext).inflate( final LinearLayout v = (LinearLayout) LayoutInflater.from(mContext).inflate(
R.layout.zen_rule_type, null, false); R.layout.zen_rule_type, null, false);
LoadIconTask task = new LoadIconTask((ImageView) v.findViewById(R.id.icon)); ImageView iconView = v.findViewById(R.id.icon);
task.execute(info);
((TextView) v.findViewById(R.id.title)).setText(ri.title); ((TextView) v.findViewById(R.id.title)).setText(ri.title);
if (!ri.isSystem) { if (!ri.isSystem) {
LoadIconTask task = new LoadIconTask(iconView);
task.execute(info);
TextView subtitle = (TextView) v.findViewById(R.id.subtitle); TextView subtitle = (TextView) v.findViewById(R.id.subtitle);
subtitle.setText(info.loadLabel(mPm)); subtitle.setText(info.loadLabel(mPm));
subtitle.setVisibility(View.VISIBLE); subtitle.setVisibility(View.VISIBLE);
} else {
if (ZenModeConfig.isValidScheduleConditionId(ri.defaultConditionId)) {
iconView.setImageDrawable(mContext.getDrawable(R.drawable.ic_timelapse));
} else if (ZenModeConfig.isValidEventConditionId(ri.defaultConditionId)) {
iconView.setImageDrawable(mContext.getDrawable(R.drawable.ic_event));
}
} }
v.setOnClickListener(new View.OnClickListener() { v.setOnClickListener(new View.OnClickListener() {
@Override @Override

View File

@@ -1,152 +0,0 @@
/*
* Copyright (C) 2018 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;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.net.Uri;
import android.service.notification.Condition;
import android.view.LayoutInflater;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class EnableZenModeDialogTest {
private EnableZenModeDialog mController;
@Mock
private Context mContext;
@Mock
private Activity mActivity;
@Mock
private Fragment mFragment;
private Context mShadowContext;
private LayoutInflater mLayoutInflater;
private Condition mCountdownCondition;
private Condition mAlarmCondition;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mShadowContext = RuntimeEnvironment.application;
when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
when(mContext.getApplicationContext()).thenReturn(mContext);
when(mFragment.getContext()).thenReturn(mShadowContext);
mLayoutInflater = LayoutInflater.from(mShadowContext);
when(mActivity.getLayoutInflater()).thenReturn(mLayoutInflater);
mController = spy(new EnableZenModeDialog());
mController.mContext = mContext;
mController.mActivity = mActivity;
mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
.thenReturn("testSummary");
mController.getContentView();
// these methods use static calls to ZenModeConfig which would normally fail in robotests,
// so instead do nothing:
doNothing().when(mController).bindGenericCountdown();
doReturn(null).when(mController).getTimeUntilNextAlarmCondition();
doNothing().when(mController).bindNextAlarm(any());
// as a result of doing nothing above, must bind manually:
Uri alarm = Condition.newId(mContext).appendPath("alarm").build();
mAlarmCondition = new Condition(alarm, "alarm", "", "", 0, 0, 0);
Uri countdown = Condition.newId(mContext).appendPath("countdown").build();
mCountdownCondition = new Condition(countdown, "countdown", "", "", 0, 0, 0);
mController.bind(mCountdownCondition,
mController.mZenRadioGroupContent.getChildAt(
EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX),
EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX);
mController.bind(mAlarmCondition,
mController.mZenRadioGroupContent.getChildAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX),
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX);
}
@Test
public void testForeverChecked() {
mController.bindConditions(mController.forever());
assertTrue(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
@Test
public void testNoneChecked() {
mController.bindConditions(null);
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
@Test
public void testAlarmChecked() {
doReturn(false).when(mController).isCountdown(mAlarmCondition);
doReturn(true).when(mController).isAlarm(mAlarmCondition);
mController.bindConditions(mAlarmCondition);
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertTrue(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
@Test
public void testCountdownChecked() {
doReturn(false).when(mController).isAlarm(mCountdownCondition);
doReturn(true).when(mController).isCountdown(mCountdownCondition);
mController.bindConditions(mCountdownCondition);
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
.isChecked());
assertTrue(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
.isChecked());
assertFalse(mController.getConditionTagAt(
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
}
}

View File

@@ -19,6 +19,7 @@ package com.android.settings.notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.NotificationManager.Policy; import android.app.NotificationManager.Policy;
import android.content.Context; import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import com.android.settings.R; import com.android.settings.R;
@@ -63,7 +64,7 @@ public class ZenModePreferenceControllerTest {
ShadowApplication shadowApplication = ShadowApplication.getInstance(); ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager); shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
mContext = shadowApplication.getApplicationContext(); mContext = shadowApplication.getApplicationContext();
mController = new ZenModePreferenceController(mContext); mController = new ZenModePreferenceController(mContext, null);
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy); when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
mSummaryBuilder = spy(new ZenModeSettings.SummaryBuilder(mContext)); mSummaryBuilder = spy(new ZenModeSettings.SummaryBuilder(mContext));
ReflectionHelpers.setField(mController, "mSummaryBuilder", mSummaryBuilder); ReflectionHelpers.setField(mController, "mSummaryBuilder", mSummaryBuilder);
@@ -76,16 +77,16 @@ public class ZenModePreferenceControllerTest {
} }
@Test @Test
public void updateState_preferenceEnabled_shouldSetSummary() { public void updateState_automaticRuleEnabled_shouldSetSummary() {
when(mPreference.isEnabled()).thenReturn(true); when(mPreference.isEnabled()).thenReturn(true);
mController.updateState(mPreference); mController.updateState(mPreference);
verify(mPreference).setSummary(mContext.getString(R.string.zen_mode_settings_summary_off)); verify(mPreference).setSummary(mContext.getResources().getString(
R.string.zen_mode_sound_summary_off));
doReturn(1).when(mSummaryBuilder).getEnabledAutomaticRulesCount(); doReturn(1).when(mSummaryBuilder).getEnabledAutomaticRulesCount();
mController.updateState(mPreference); mController.updateState(mPreference);
verify(mPreference).setSummary(mContext.getResources().getQuantityString( verify(mPreference).setSummary(mSummaryBuilder.getSoundSummary());
R.plurals.zen_mode_settings_summary_on, 1, 1));
} }
@Test @Test