diff --git a/res/layout/zen_mode_settings_button.xml b/res/layout/zen_mode_settings_button.xml
index 82989fc7863..4fe522d799f 100644
--- a/res/layout/zen_mode_settings_button.xml
+++ b/res/layout/zen_mode_settings_button.xml
@@ -30,7 +30,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_on"
android:paddingEnd="8dp" />
@@ -40,7 +40,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_off"
android:paddingEnd="8dp" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 448ececf90e..b33c2c94a9d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6845,6 +6845,9 @@
Do Not Disturb
+
+ Turn on Do Not Disturb
+
Behavior
@@ -6902,6 +6905,9 @@
Add
+
+ Turn on
+
Turn on now
@@ -6920,6 +6926,12 @@
Do Not Disturb was automatically turned on by an app (%s)
+
+ Priority only
+
+
+ %1$s. %2$s
+
Work profile sounds
diff --git a/src/com/android/settings/notification/EnableZenModeDialog.java b/src/com/android/settings/notification/EnableZenModeDialog.java
new file mode 100644
index 00000000000..f683a2116cb
--- /dev/null
+++ b/src/com/android/settings/notification/EnableZenModeDialog.java
@@ -0,0 +1,467 @@
+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;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
index f5169f04500..da540f4100e 100644
--- a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
@@ -16,6 +16,7 @@
package com.android.settings.notification;
+import android.app.FragmentManager;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference;
@@ -31,12 +32,16 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeButtonPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
+ private static final String TAG = "EnableZenModeButton";
protected static final String KEY = "zen_mode_settings_button_container";
private Button mZenButtonOn;
private Button mZenButtonOff;
+ private FragmentManager mFragment;
- public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle) {
+ public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle, FragmentManager
+ fragment) {
super(context, KEY, lifecycle);
+ mFragment = fragment;
}
@Override
@@ -56,11 +61,8 @@ public class ZenModeButtonPreferenceController extends AbstractZenModePreference
if (null == mZenButtonOn) {
mZenButtonOn = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_on_button);
- mZenButtonOn.setOnClickListener(v -> {
- mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, true);
- mBackend.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- });
+ mZenButtonOn.setOnClickListener(v ->
+ new EnableZenModeDialog().show(mFragment, TAG));
}
if (null == mZenButtonOff) {
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 1ee20d30633..a6145c442d1 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -17,6 +17,7 @@
package com.android.settings.notification;
import android.app.AutomaticZenRule;
+import android.app.FragmentManager;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
@@ -50,7 +51,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
protected List getPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, getLifecycle());
+ return buildPreferenceControllers(context, getLifecycle(), getFragmentManager());
}
@Override
@@ -59,11 +60,11 @@ public class ZenModeSettings extends ZenModeSettingsBase {
}
private static List buildPreferenceControllers(Context context,
- Lifecycle lifecycle) {
+ Lifecycle lifecycle, FragmentManager fragmentManager) {
List controllers = new ArrayList<>();
controllers.add(new ZenModeBehaviorPreferenceController(context, lifecycle));
controllers.add(new ZenModeAutomationPreferenceController(context));
- controllers.add(new ZenModeButtonPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
return controllers;
}
@@ -211,7 +212,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
public List getPreferenceControllers(Context
context) {
- return buildPreferenceControllers(context, null);
+ return buildPreferenceControllers(context, null, null);
}
};
}
diff --git a/tests/robotests/src/com/android/settings/notification/EnableZenModeDialogTest.java b/tests/robotests/src/com/android/settings/notification/EnableZenModeDialogTest.java
new file mode 100644
index 00000000000..8b5ef79dcbc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/EnableZenModeDialogTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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());
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java
index 862b8d06afe..ed42890b3e3 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.FragmentManager;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -79,7 +80,8 @@ public class ZenModeButtonPreferenceControllerTest {
mContext = shadowApplication.getApplicationContext();
mContentResolver = RuntimeEnvironment.application.getContentResolver();
- mController = new ZenModeButtonPreferenceController(mContext, mock(Lifecycle.class));
+ mController = new ZenModeButtonPreferenceController(mContext, mock(Lifecycle.class),
+ mock(FragmentManager.class));
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
ReflectionHelpers.setField(mController, "mZenButtonOn", mZenButtonOn);