blob: 4716552e94a164ad75866f8e1d71e470919f5bd2 [file] [log] [blame]
Julia Reynolds0842fe82015-10-01 14:34:22 -04001/**
John Spurlock86005342014-05-23 11:58:00 -04002 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.volume;
18
John Spurlock3e077012014-11-29 13:22:21 -050019import android.animation.LayoutTransition;
John Spurlock530052a2014-11-30 16:26:19 -050020import android.animation.LayoutTransition.TransitionListener;
Selim Cinek9c4a7072014-11-21 17:44:34 +010021import android.app.ActivityManager;
John Spurlock86005342014-05-23 11:58:00 -040022import android.content.Context;
23import android.content.Intent;
John Spurlock856edeb2014-06-01 20:36:47 -040024import android.content.SharedPreferences;
25import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
John Spurlock814ee6ab2015-05-18 11:16:38 -040026import android.content.res.Configuration;
John Spurlock86005342014-05-23 11:58:00 -040027import android.net.Uri;
John Spurlock530052a2014-11-30 16:26:19 -050028import android.os.AsyncTask;
John Spurlock86005342014-05-23 11:58:00 -040029import android.os.Handler;
30import android.os.Looper;
31import android.os.Message;
32import android.provider.Settings;
John Spurlockae641c92014-06-30 18:11:40 -040033import android.provider.Settings.Global;
John Spurlock86005342014-05-23 11:58:00 -040034import android.service.notification.Condition;
John Spurlock856edeb2014-06-01 20:36:47 -040035import android.service.notification.ZenModeConfig;
John Spurlockb2278d62015-04-07 12:47:12 -040036import android.service.notification.ZenModeConfig.ZenRule;
John Spurlockc90e6fe2014-10-28 11:21:42 -040037import android.text.TextUtils;
John Spurlock8be53ea2015-05-29 12:04:21 -040038import android.text.format.DateFormat;
Jason Monkbe3235a2017-04-05 09:29:53 -040039import android.text.format.DateUtils;
John Spurlock530052a2014-11-30 16:26:19 -050040import android.util.ArraySet;
John Spurlock86005342014-05-23 11:58:00 -040041import android.util.AttributeSet;
John Spurlock856edeb2014-06-01 20:36:47 -040042import android.util.Log;
John Spurlock8f8ecd62014-08-27 17:46:03 -040043import android.util.MathUtils;
John Spurlock86005342014-05-23 11:58:00 -040044import android.view.LayoutInflater;
45import android.view.View;
John Spurlock3e077012014-11-29 13:22:21 -050046import android.view.ViewGroup;
John Spurlock86005342014-05-23 11:58:00 -040047import android.widget.CompoundButton;
48import android.widget.CompoundButton.OnCheckedChangeListener;
Jason Monkbe3235a2017-04-05 09:29:53 -040049import android.widget.FrameLayout;
John Spurlock86005342014-05-23 11:58:00 -040050import android.widget.ImageView;
51import android.widget.LinearLayout;
52import android.widget.RadioButton;
Julia Reynolds656f9862016-06-01 11:37:29 -040053import android.widget.RadioGroup;
John Spurlock86005342014-05-23 11:58:00 -040054import android.widget.TextView;
55
Chris Wren9e7283f2015-05-08 17:23:47 -040056import com.android.internal.logging.MetricsLogger;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010057import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
John Spurlockf55b7f22015-04-13 19:21:26 -040058import com.android.systemui.Prefs;
John Spurlock86005342014-05-23 11:58:00 -040059import com.android.systemui.R;
60import com.android.systemui.statusbar.policy.ZenModeController;
61
John Spurlock530052a2014-11-30 16:26:19 -050062import java.io.FileDescriptor;
63import java.io.PrintWriter;
John Spurlock86005342014-05-23 11:58:00 -040064import java.util.Arrays;
Julia Reynolds0842fe82015-10-01 14:34:22 -040065import java.util.Calendar;
66import java.util.GregorianCalendar;
John Spurlock8be53ea2015-05-29 12:04:21 -040067import java.util.Locale;
John Spurlock856edeb2014-06-01 20:36:47 -040068import java.util.Objects;
John Spurlock86005342014-05-23 11:58:00 -040069
Jason Monkbe3235a2017-04-05 09:29:53 -040070public class ZenModePanel extends FrameLayout {
John Spurlockae641c92014-06-30 18:11:40 -040071 private static final String TAG = "ZenModePanel";
72 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock856edeb2014-06-01 20:36:47 -040073
Jason Monkbe3235a2017-04-05 09:29:53 -040074 public static final int STATE_MODIFY = 0;
75 public static final int STATE_AUTO_RULE = 1;
76 public static final int STATE_OFF = 2;
77
John Spurlock50806fc2014-07-15 10:22:02 -040078 private static final int SECONDS_MS = 1000;
79 private static final int MINUTES_MS = 60 * SECONDS_MS;
80
Julia Reynolds0ca82fe2015-11-05 11:08:02 -050081 private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
John Spurlock856edeb2014-06-01 20:36:47 -040082 private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
83 private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
84 private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
John Spurlockae641c92014-06-30 18:11:40 -040085 private static final int FOREVER_CONDITION_INDEX = 0;
John Spurlock530052a2014-11-30 16:26:19 -050086 private static final int COUNTDOWN_CONDITION_INDEX = 1;
Julia Reynolds0842fe82015-10-01 14:34:22 -040087 private static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -040088 private static final int COUNTDOWN_CONDITION_COUNT = 2;
John Spurlock856edeb2014-06-01 20:36:47 -040089
John Spurlockf55b7f22015-04-13 19:21:26 -040090 public static final Intent ZEN_SETTINGS
91 = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
92 public static final Intent ZEN_PRIORITY_SETTINGS
93 = new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
John Spurlock86005342014-05-23 11:58:00 -040094
Jason Monkbe3235a2017-04-05 09:29:53 -040095 private static final long TRANSITION_DURATION = 300;
96
John Spurlock7f1df5e2014-05-31 19:11:40 -040097 private final Context mContext;
Muyuan Li94fa1df2016-03-23 12:09:38 -070098 protected final LayoutInflater mInflater;
John Spurlock86005342014-05-23 11:58:00 -040099 private final H mHandler = new H();
John Spurlockf55b7f22015-04-13 19:21:26 -0400100 private final ZenPrefs mPrefs;
John Spurlock530052a2014-11-30 16:26:19 -0500101 private final TransitionHelper mTransitionHelper = new TransitionHelper();
John Spurlock0b688502014-12-22 15:13:30 -0500102 private final Uri mForeverId;
Julia Reynolds03c548f2016-12-14 15:02:38 -0500103 private final ConfigurableTexts mConfigurableTexts;
John Spurlock856edeb2014-06-01 20:36:47 -0400104
John Spurlockeb2727b2014-07-19 23:11:36 -0400105 private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
John Spurlockae641c92014-06-30 18:11:40 -0400106
Muyuan Li8303bd22016-03-23 20:08:26 -0700107 protected SegmentedButtons mZenButtons;
John Spurlockf55b7f22015-04-13 19:21:26 -0400108 private View mZenIntroduction;
John Spurlockd9c75db2015-04-28 11:19:13 -0400109 private TextView mZenIntroductionMessage;
John Spurlockf55b7f22015-04-13 19:21:26 -0400110 private View mZenIntroductionConfirm;
John Spurlockd8963232015-06-08 16:26:12 -0400111 private TextView mZenIntroductionCustomize;
Muyuan Li94fa1df2016-03-23 12:09:38 -0700112 protected LinearLayout mZenConditions;
John Spurlock8be53ea2015-05-29 12:04:21 -0400113 private TextView mZenAlarmWarning;
Julia Reynolds656f9862016-06-01 11:37:29 -0400114 private RadioGroup mZenRadioGroup;
115 private LinearLayout mZenRadioGroupContent;
John Spurlockae641c92014-06-30 18:11:40 -0400116
John Spurlock86005342014-05-23 11:58:00 -0400117 private Callback mCallback;
118 private ZenModeController mController;
John Spurlockad680d42015-01-30 15:48:15 -0500119 private boolean mCountdownConditionSupported;
John Spurlock86005342014-05-23 11:58:00 -0400120 private boolean mRequestingConditions;
John Spurlock4db0d982014-08-13 09:19:03 -0400121 private Condition mExitCondition;
John Spurlock856edeb2014-06-01 20:36:47 -0400122 private int mBucketIndex = -1;
John Spurlockae641c92014-06-30 18:11:40 -0400123 private boolean mExpanded;
John Spurlock530052a2014-11-30 16:26:19 -0500124 private boolean mHidden;
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400125 private int mSessionZen;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400126 private int mAttachedZen;
John Spurlock3e077012014-11-29 13:22:21 -0500127 private boolean mAttached;
John Spurlock4db0d982014-08-13 09:19:03 -0400128 private Condition mSessionExitCondition;
John Spurlock4db0d982014-08-13 09:19:03 -0400129 private Condition[] mConditions;
130 private Condition mTimeCondition;
John Spurlockcbd7a312015-06-21 10:46:28 -0400131 private boolean mVoiceCapable;
John Spurlock86005342014-05-23 11:58:00 -0400132
Muyuan Li8b270902016-06-10 10:26:45 -0700133 protected int mZenModeConditionLayoutId;
134 protected int mZenModeButtonLayoutId;
Jason Monkbe3235a2017-04-05 09:29:53 -0400135 private View mEmpty;
136 private TextView mEmptyText;
137 private ImageView mEmptyIcon;
138 private View mAutoRule;
139 private TextView mAutoTitle;
140 private int mState = STATE_MODIFY;
141 private ViewGroup mEdit;
Muyuan Li8b270902016-06-10 10:26:45 -0700142
John Spurlock86005342014-05-23 11:58:00 -0400143 public ZenModePanel(Context context, AttributeSet attrs) {
144 super(context, attrs);
John Spurlock7f1df5e2014-05-31 19:11:40 -0400145 mContext = context;
John Spurlockf55b7f22015-04-13 19:21:26 -0400146 mPrefs = new ZenPrefs();
Jason Monkb2eb67b2017-07-11 10:13:31 -0400147 mInflater = LayoutInflater.from(mContext);
John Spurlock0b688502014-12-22 15:13:30 -0500148 mForeverId = Condition.newId(mContext).appendPath("forever").build();
Julia Reynolds03c548f2016-12-14 15:02:38 -0500149 mConfigurableTexts = new ConfigurableTexts(mContext);
John Spurlockcbd7a312015-06-21 10:46:28 -0400150 mVoiceCapable = Util.isVoiceCapable(mContext);
Muyuan Li8b270902016-06-10 10:26:45 -0700151 mZenModeConditionLayoutId = R.layout.zen_mode_condition;
152 mZenModeButtonLayoutId = R.layout.zen_mode_button;
John Spurlock856edeb2014-06-01 20:36:47 -0400153 if (DEBUG) Log.d(mTag, "new ZenModePanel");
154 }
155
John Spurlock530052a2014-11-30 16:26:19 -0500156 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
157 pw.println("ZenModePanel state:");
158 pw.print(" mCountdownConditionSupported="); pw.println(mCountdownConditionSupported);
John Spurlock530052a2014-11-30 16:26:19 -0500159 pw.print(" mRequestingConditions="); pw.println(mRequestingConditions);
160 pw.print(" mAttached="); pw.println(mAttached);
161 pw.print(" mHidden="); pw.println(mHidden);
162 pw.print(" mExpanded="); pw.println(mExpanded);
163 pw.print(" mSessionZen="); pw.println(mSessionZen);
164 pw.print(" mAttachedZen="); pw.println(mAttachedZen);
John Spurlockd9c75db2015-04-28 11:19:13 -0400165 pw.print(" mConfirmedPriorityIntroduction=");
166 pw.println(mPrefs.mConfirmedPriorityIntroduction);
167 pw.print(" mConfirmedSilenceIntroduction=");
168 pw.println(mPrefs.mConfirmedSilenceIntroduction);
John Spurlockcbd7a312015-06-21 10:46:28 -0400169 pw.print(" mVoiceCapable="); pw.println(mVoiceCapable);
John Spurlock530052a2014-11-30 16:26:19 -0500170 mTransitionHelper.dump(fd, pw, args);
171 }
172
Muyuan Li8303bd22016-03-23 20:08:26 -0700173 protected void createZenButtons() {
Jason Monkbe3235a2017-04-05 09:29:53 -0400174 mZenButtons = findViewById(R.id.zen_buttons);
John Spurlock4f1163c2015-04-02 17:41:21 -0400175 mZenButtons.addButton(R.string.interruption_level_none_twoline,
John Spurlockbd1abe62015-06-10 17:18:38 -0400176 R.string.interruption_level_none_with_warning,
John Spurlock4f1163c2015-04-02 17:41:21 -0400177 Global.ZEN_MODE_NO_INTERRUPTIONS);
178 mZenButtons.addButton(R.string.interruption_level_alarms_twoline,
John Spurlocka1c7ffe2015-06-08 15:34:05 -0400179 R.string.interruption_level_alarms,
John Spurlock4f1163c2015-04-02 17:41:21 -0400180 Global.ZEN_MODE_ALARMS);
181 mZenButtons.addButton(R.string.interruption_level_priority_twoline,
John Spurlocka1c7ffe2015-06-08 15:34:05 -0400182 R.string.interruption_level_priority,
John Spurlock4291fb72014-09-16 17:02:23 -0400183 Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
John Spurlockae641c92014-06-30 18:11:40 -0400184 mZenButtons.setCallback(mZenButtonsCallback);
Muyuan Li8303bd22016-03-23 20:08:26 -0700185 }
John Spurlockae641c92014-06-30 18:11:40 -0400186
Muyuan Li8303bd22016-03-23 20:08:26 -0700187 @Override
188 protected void onFinishInflate() {
189 super.onFinishInflate();
190 createZenButtons();
John Spurlockf55b7f22015-04-13 19:21:26 -0400191 mZenIntroduction = findViewById(R.id.zen_introduction);
Jason Monkbe3235a2017-04-05 09:29:53 -0400192 mZenIntroductionMessage = findViewById(R.id.zen_introduction_message);
John Spurlockf55b7f22015-04-13 19:21:26 -0400193 mZenIntroductionConfirm = findViewById(R.id.zen_introduction_confirm);
Jason Monkbe3235a2017-04-05 09:29:53 -0400194 mZenIntroductionConfirm.setOnClickListener(v -> confirmZenIntroduction());
195 mZenIntroductionCustomize = findViewById(R.id.zen_introduction_customize);
196 mZenIntroductionCustomize.setOnClickListener(v -> {
197 confirmZenIntroduction();
198 if (mCallback != null) {
199 mCallback.onPrioritySettings();
John Spurlockf55b7f22015-04-13 19:21:26 -0400200 }
201 });
Julia Reynolds03c548f2016-12-14 15:02:38 -0500202 mConfigurableTexts.add(mZenIntroductionCustomize, R.string.zen_priority_customize_button);
John Spurlockf55b7f22015-04-13 19:21:26 -0400203
Jason Monkbe3235a2017-04-05 09:29:53 -0400204 mZenConditions = findViewById(R.id.zen_conditions);
205 mZenAlarmWarning = findViewById(R.id.zen_alarm_warning);
206 mZenRadioGroup = findViewById(R.id.zen_radio_buttons);
207 mZenRadioGroupContent = findViewById(R.id.zen_radio_buttons_content);
208
209 mEdit = findViewById(R.id.edit_container);
210
211 mEmpty = findViewById(android.R.id.empty);
212 mEmpty.setVisibility(INVISIBLE);
213 mEmptyText = mEmpty.findViewById(android.R.id.title);
214 mEmptyIcon = mEmpty.findViewById(android.R.id.icon);
215
216 mAutoRule = findViewById(R.id.auto_rule);
217 mAutoTitle = mAutoRule.findViewById(android.R.id.title);
218 mAutoRule.setVisibility(INVISIBLE);
219 }
220
221 public void setEmptyState(int icon, int text) {
222 mEmptyIcon.post(() -> {
223 mEmptyIcon.setImageResource(icon);
224 mEmptyText.setText(text);
225 });
226 }
227
228 public void setAutoText(CharSequence text) {
229 mAutoTitle.post(() -> mAutoTitle.setText(text));
230 }
231
232 public void setState(int state) {
233 if (mState == state) return;
234 transitionFrom(getView(mState), getView(state));
235 mState = state;
236 }
237
238 private void transitionFrom(View from, View to) {
239 from.post(() -> {
240 // TODO: Better transitions
241 to.setAlpha(0);
242 to.setVisibility(VISIBLE);
243 to.bringToFront();
244 to.animate().cancel();
245 to.animate().alpha(1)
246 .setDuration(TRANSITION_DURATION)
247 .withEndAction(() -> from.setVisibility(INVISIBLE))
248 .start();
249 });
250 }
251
252 private View getView(int state) {
253 switch (state) {
254 case STATE_AUTO_RULE:
255 return mAutoRule;
256 case STATE_OFF:
257 return mEmpty;
258 default:
259 return mEdit;
260 }
John Spurlock814ee6ab2015-05-18 11:16:38 -0400261 }
John Spurlock530052a2014-11-30 16:26:19 -0500262
John Spurlock814ee6ab2015-05-18 11:16:38 -0400263 @Override
264 protected void onConfigurationChanged(Configuration newConfig) {
265 super.onConfigurationChanged(newConfig);
Julia Reynolds03c548f2016-12-14 15:02:38 -0500266 mConfigurableTexts.update();
John Spurlock814ee6ab2015-05-18 11:16:38 -0400267 if (mZenButtons != null) {
Julia Reynolds03c548f2016-12-14 15:02:38 -0500268 mZenButtons.update();
Yongjiang Wucf3984192016-02-20 18:28:10 +0800269 }
John Spurlock3e077012014-11-29 13:22:21 -0500270 }
271
John Spurlockf55b7f22015-04-13 19:21:26 -0400272 private void confirmZenIntroduction() {
John Spurlockd9c75db2015-04-28 11:19:13 -0400273 final String prefKey = prefKeyForConfirmation(getSelectedZen(Global.ZEN_MODE_OFF));
274 if (prefKey == null) return;
275 if (DEBUG) Log.d(TAG, "confirmZenIntroduction " + prefKey);
276 Prefs.putBoolean(mContext, prefKey, true);
John Spurlockf55b7f22015-04-13 19:21:26 -0400277 mHandler.sendEmptyMessage(H.UPDATE_WIDGETS);
278 }
279
John Spurlockd9c75db2015-04-28 11:19:13 -0400280 private static String prefKeyForConfirmation(int zen) {
281 switch (zen) {
282 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
283 return Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION;
284 case Global.ZEN_MODE_NO_INTERRUPTIONS:
285 return Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION;
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -0500286 case Global.ZEN_MODE_ALARMS:
287 return Prefs.Key.DND_CONFIRMED_ALARM_INTRODUCTION;
John Spurlockd9c75db2015-04-28 11:19:13 -0400288 default:
289 return null;
John Spurlock530052a2014-11-30 16:26:19 -0500290 }
John Spurlock86005342014-05-23 11:58:00 -0400291 }
292
Jason Monk035a9362017-04-20 15:51:16 -0400293 private void onAttach() {
Jason Monkbe3235a2017-04-05 09:29:53 -0400294 setExpanded(true);
John Spurlock3e077012014-11-29 13:22:21 -0500295 mAttached = true;
Jason Monk035a9362017-04-20 15:51:16 -0400296 mAttachedZen = mController.getZen();
297 ZenRule manualRule = mController.getManualRule();
298 mExitCondition = manualRule != null ? manualRule.condition : null;
299 if (DEBUG) Log.d(mTag, "onAttach " + mAttachedZen + " " + manualRule);
300 handleUpdateManualRule(manualRule);
301 mZenButtons.setSelectedValue(mAttachedZen, false);
John Spurlock8f8ecd62014-08-27 17:46:03 -0400302 mSessionZen = mAttachedZen;
John Spurlock530052a2014-11-30 16:26:19 -0500303 mTransitionHelper.clear();
Julia Reynoldsb44ef7e2016-06-02 15:29:16 -0400304 mController.addCallback(mZenCallback);
John Spurlock530052a2014-11-30 16:26:19 -0500305 setSessionExitCondition(copy(mExitCondition));
John Spurlock50806fc2014-07-15 10:22:02 -0400306 updateWidgets();
John Spurlock3e077012014-11-29 13:22:21 -0500307 setRequestingConditions(!mHidden);
Jason Monk2d77c0f2017-05-30 16:08:50 -0400308 ensureSelection();
John Spurlock856edeb2014-06-01 20:36:47 -0400309 }
310
Jason Monk035a9362017-04-20 15:51:16 -0400311 private void onDetach() {
312 if (DEBUG) Log.d(mTag, "onDetach");
Jason Monkbe3235a2017-04-05 09:29:53 -0400313 setExpanded(false);
John Spurlock8f8ecd62014-08-27 17:46:03 -0400314 checkForAttachedZenChange();
John Spurlock3e077012014-11-29 13:22:21 -0500315 mAttached = false;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400316 mAttachedZen = -1;
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400317 mSessionZen = -1;
Julia Reynoldsb44ef7e2016-06-02 15:29:16 -0400318 mController.removeCallback(mZenCallback);
John Spurlock530052a2014-11-30 16:26:19 -0500319 setSessionExitCondition(null);
John Spurlock3e077012014-11-29 13:22:21 -0500320 setRequestingConditions(false);
John Spurlock530052a2014-11-30 16:26:19 -0500321 mTransitionHelper.clear();
322 }
323
Jason Monk035a9362017-04-20 15:51:16 -0400324 @Override
325 public void onVisibilityAggregated(boolean isVisible) {
326 super.onVisibilityAggregated(isVisible);
327 if (isVisible == mAttached) return;
328 if (isVisible) {
329 onAttach();
330 } else {
331 onDetach();
332 }
333 }
334
John Spurlock530052a2014-11-30 16:26:19 -0500335 private void setSessionExitCondition(Condition condition) {
336 if (Objects.equals(condition, mSessionExitCondition)) return;
337 if (DEBUG) Log.d(mTag, "mSessionExitCondition=" + getConditionId(condition));
338 mSessionExitCondition = condition;
John Spurlock856edeb2014-06-01 20:36:47 -0400339 }
340
John Spurlockeb2727b2014-07-19 23:11:36 -0400341 public void setHidden(boolean hidden) {
342 if (mHidden == hidden) return;
John Spurlock3e077012014-11-29 13:22:21 -0500343 if (DEBUG) Log.d(mTag, "hidden=" + hidden);
John Spurlockeb2727b2014-07-19 23:11:36 -0400344 mHidden = hidden;
John Spurlock3e077012014-11-29 13:22:21 -0500345 setRequestingConditions(mAttached && !mHidden);
John Spurlockeb2727b2014-07-19 23:11:36 -0400346 updateWidgets();
347 }
348
John Spurlock8f8ecd62014-08-27 17:46:03 -0400349 private void checkForAttachedZenChange() {
350 final int selectedZen = getSelectedZen(-1);
351 if (DEBUG) Log.d(mTag, "selectedZen=" + selectedZen);
352 if (selectedZen != mAttachedZen) {
353 if (DEBUG) Log.d(mTag, "attachedZen: " + mAttachedZen + " -> " + selectedZen);
354 if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
355 mPrefs.trackNoneSelected();
356 }
357 }
358 }
359
John Spurlockae641c92014-06-30 18:11:40 -0400360 private void setExpanded(boolean expanded) {
361 if (expanded == mExpanded) return;
John Spurlockf88d8082015-03-25 18:09:51 -0400362 if (DEBUG) Log.d(mTag, "setExpanded " + expanded);
John Spurlockae641c92014-06-30 18:11:40 -0400363 mExpanded = expanded;
364 updateWidgets();
John Spurlockae641c92014-06-30 18:11:40 -0400365 fireExpanded();
John Spurlock86005342014-05-23 11:58:00 -0400366 }
367
368 /** Start or stop requesting relevant zen mode exit conditions */
John Spurlock530052a2014-11-30 16:26:19 -0500369 private void setRequestingConditions(final boolean requesting) {
John Spurlock86005342014-05-23 11:58:00 -0400370 if (mRequestingConditions == requesting) return;
John Spurlock856edeb2014-06-01 20:36:47 -0400371 if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);
John Spurlock86005342014-05-23 11:58:00 -0400372 mRequestingConditions = requesting;
John Spurlock856edeb2014-06-01 20:36:47 -0400373 if (mRequestingConditions) {
John Spurlockb2278d62015-04-07 12:47:12 -0400374 mTimeCondition = parseExistingTimeCondition(mContext, mExitCondition);
John Spurlock4db0d982014-08-13 09:19:03 -0400375 if (mTimeCondition != null) {
John Spurlock856edeb2014-06-01 20:36:47 -0400376 mBucketIndex = -1;
377 } else {
378 mBucketIndex = DEFAULT_BUCKET_INDEX;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400379 mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100380 MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400381 }
382 if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400383
John Spurlock4db0d982014-08-13 09:19:03 -0400384 mConditions = null; // reset conditions
385 handleUpdateConditions();
John Spurlock856edeb2014-06-01 20:36:47 -0400386 } else {
John Spurlock530052a2014-11-30 16:26:19 -0500387 hideAllConditions();
John Spurlock856edeb2014-06-01 20:36:47 -0400388 }
John Spurlock86005342014-05-23 11:58:00 -0400389 }
390
Muyuan Li94fa1df2016-03-23 12:09:38 -0700391 protected void addZenConditions(int count) {
392 for (int i = 0; i < count; i++) {
Jason Monkbe3235a2017-04-05 09:29:53 -0400393 final View rb = mInflater.inflate(mZenModeButtonLayoutId, mEdit, false);
Julia Reynolds656f9862016-06-01 11:37:29 -0400394 rb.setId(i);
395 mZenRadioGroup.addView(rb);
Jason Monkbe3235a2017-04-05 09:29:53 -0400396 final View rbc = mInflater.inflate(mZenModeConditionLayoutId, mEdit, false);
Julia Reynolds656f9862016-06-01 11:37:29 -0400397 rbc.setId(i + count);
398 mZenRadioGroupContent.addView(rbc);
Muyuan Li94fa1df2016-03-23 12:09:38 -0700399 }
400 }
401
John Spurlockeb2727b2014-07-19 23:11:36 -0400402 public void init(ZenModeController controller) {
John Spurlock86005342014-05-23 11:58:00 -0400403 mController = controller;
John Spurlockad680d42015-01-30 15:48:15 -0500404 mCountdownConditionSupported = mController.isCountdownConditionSupported();
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400405 final int countdownDelta = mCountdownConditionSupported ? COUNTDOWN_CONDITION_COUNT : 0;
John Spurlockad680d42015-01-30 15:48:15 -0500406 final int minConditions = 1 /*forever*/ + countdownDelta;
Muyuan Li94fa1df2016-03-23 12:09:38 -0700407 addZenConditions(minConditions);
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400408 mSessionZen = getSelectedZen(-1);
John Spurlockb2278d62015-04-07 12:47:12 -0400409 handleUpdateManualRule(mController.getManualRule());
John Spurlock4db0d982014-08-13 09:19:03 -0400410 if (DEBUG) Log.d(mTag, "init mExitCondition=" + mExitCondition);
John Spurlock530052a2014-11-30 16:26:19 -0500411 hideAllConditions();
John Spurlockae641c92014-06-30 18:11:40 -0400412 }
413
John Spurlock4db0d982014-08-13 09:19:03 -0400414 private void setExitCondition(Condition exitCondition) {
John Spurlock25c34212014-11-12 09:16:49 -0500415 if (Objects.equals(mExitCondition, exitCondition)) return;
John Spurlock4db0d982014-08-13 09:19:03 -0400416 mExitCondition = exitCondition;
John Spurlock530052a2014-11-30 16:26:19 -0500417 if (DEBUG) Log.d(mTag, "mExitCondition=" + getConditionId(mExitCondition));
John Spurlock89f060a2014-07-16 21:03:15 -0400418 updateWidgets();
John Spurlockae641c92014-06-30 18:11:40 -0400419 }
420
John Spurlock4db0d982014-08-13 09:19:03 -0400421 private static Uri getConditionId(Condition condition) {
422 return condition != null ? condition.id : null;
423 }
424
John Spurlockb2278d62015-04-07 12:47:12 -0400425 private Uri getRealConditionId(Condition condition) {
426 return isForever(condition) ? null : getConditionId(condition);
427 }
428
John Spurlock4db0d982014-08-13 09:19:03 -0400429 private static boolean sameConditionId(Condition lhs, Condition rhs) {
430 return lhs == null ? rhs == null : rhs != null && lhs.id.equals(rhs.id);
431 }
432
433 private static Condition copy(Condition condition) {
434 return condition == null ? null : condition.copy();
435 }
436
John Spurlock86005342014-05-23 11:58:00 -0400437 public void setCallback(Callback callback) {
438 mCallback = callback;
439 }
440
John Spurlockb2278d62015-04-07 12:47:12 -0400441 private void handleUpdateManualRule(ZenRule rule) {
442 final int zen = rule != null ? rule.zenMode : Global.ZEN_MODE_OFF;
443 handleUpdateZen(zen);
Jason Monkbe3235a2017-04-05 09:29:53 -0400444 final Condition c = rule == null ? null
445 : rule.condition != null ? rule.condition
446 : createCondition(rule.conditionId);
John Spurlockb2278d62015-04-07 12:47:12 -0400447 handleExitConditionChanged(c);
448 }
449
Jason Monkbe3235a2017-04-05 09:29:53 -0400450 private Condition createCondition(Uri conditionId) {
451 if (ZenModeConfig.isValidCountdownConditionId(conditionId)) {
452 long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
453 int mins = (int) ((time - System.currentTimeMillis() + DateUtils.MINUTE_IN_MILLIS / 2)
454 / DateUtils.MINUTE_IN_MILLIS);
455 Condition c = ZenModeConfig.toTimeCondition(mContext, time, mins,
456 ActivityManager.getCurrentUser(), false);
457 return c;
458 }
Jason Monk2d77c0f2017-05-30 16:08:50 -0400459 // If there is a manual rule, but it has no condition listed then it is forever.
460 return forever();
Jason Monkbe3235a2017-04-05 09:29:53 -0400461 }
462
John Spurlockae641c92014-06-30 18:11:40 -0400463 private void handleUpdateZen(int zen) {
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400464 if (mSessionZen != -1 && mSessionZen != zen) {
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400465 mSessionZen = zen;
John Spurlockae641c92014-06-30 18:11:40 -0400466 }
Chris Wren4572cbc2015-06-29 11:27:18 -0400467 mZenButtons.setSelectedValue(zen, false /* fromClick */);
John Spurlockae641c92014-06-30 18:11:40 -0400468 updateWidgets();
John Spurlock530052a2014-11-30 16:26:19 -0500469 handleUpdateConditions();
470 if (mExpanded) {
471 final Condition selected = getSelectedCondition();
472 if (!Objects.equals(mExitCondition, selected)) {
473 select(selected);
474 }
475 }
476 }
477
John Spurlockb2278d62015-04-07 12:47:12 -0400478 private void handleExitConditionChanged(Condition exitCondition) {
479 setExitCondition(exitCondition);
480 if (DEBUG) Log.d(mTag, "handleExitConditionChanged " + mExitCondition);
Jason Monkbe3235a2017-04-05 09:29:53 -0400481 if (exitCondition == null) return;
John Spurlockb2278d62015-04-07 12:47:12 -0400482 final int N = getVisibleConditions();
483 for (int i = 0; i < N; i++) {
484 final ConditionTag tag = getConditionTagAt(i);
Jason Monkbe3235a2017-04-05 09:29:53 -0400485 if (tag != null && sameConditionId(tag.condition, mExitCondition)) {
486 bind(exitCondition, mZenRadioGroupContent.getChildAt(i), i);
Jason Monk2d77c0f2017-05-30 16:08:50 -0400487 tag.rb.setChecked(true);
Jason Monkbe3235a2017-04-05 09:29:53 -0400488 return;
John Spurlockb2278d62015-04-07 12:47:12 -0400489 }
490 }
Jason Monkbe3235a2017-04-05 09:29:53 -0400491 if (mCountdownConditionSupported && ZenModeConfig.isValidCountdownConditionId(
492 exitCondition.id)) {
493 bind(exitCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
494 COUNTDOWN_CONDITION_INDEX);
Jason Monk2d77c0f2017-05-30 16:08:50 -0400495 getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
Jason Monkbe3235a2017-04-05 09:29:53 -0400496 }
John Spurlockb2278d62015-04-07 12:47:12 -0400497 }
498
John Spurlock530052a2014-11-30 16:26:19 -0500499 private Condition getSelectedCondition() {
500 final int N = getVisibleConditions();
501 for (int i = 0; i < N; i++) {
502 final ConditionTag tag = getConditionTagAt(i);
503 if (tag != null && tag.rb.isChecked()) {
504 return tag.condition;
505 }
506 }
507 return null;
John Spurlockae641c92014-06-30 18:11:40 -0400508 }
509
510 private int getSelectedZen(int defValue) {
511 final Object zen = mZenButtons.getSelectedValue();
512 return zen != null ? (Integer) zen : defValue;
513 }
514
515 private void updateWidgets() {
John Spurlock530052a2014-11-30 16:26:19 -0500516 if (mTransitionHelper.isTransitioning()) {
517 mTransitionHelper.pendingUpdateWidgets();
518 return;
519 }
John Spurlockae641c92014-06-30 18:11:40 -0400520 final int zen = getSelectedZen(Global.ZEN_MODE_OFF);
John Spurlockae641c92014-06-30 18:11:40 -0400521 final boolean zenImportant = zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
522 final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -0500523 final boolean zenAlarm = zen == Global.ZEN_MODE_ALARMS;
John Spurlockd9c75db2015-04-28 11:19:13 -0400524 final boolean introduction = (zenImportant && !mPrefs.mConfirmedPriorityIntroduction
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -0500525 || zenNone && !mPrefs.mConfirmedSilenceIntroduction
526 || zenAlarm && !mPrefs.mConfirmedAlarmIntroduction);
John Spurlockae641c92014-06-30 18:11:40 -0400527
John Spurlockeb2727b2014-07-19 23:11:36 -0400528 mZenButtons.setVisibility(mHidden ? GONE : VISIBLE);
John Spurlockf55b7f22015-04-13 19:21:26 -0400529 mZenIntroduction.setVisibility(introduction ? VISIBLE : GONE);
John Spurlockd9c75db2015-04-28 11:19:13 -0400530 if (introduction) {
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -0500531 int message = zenImportant
Julia Reynolds03c548f2016-12-14 15:02:38 -0500532 ? R.string.zen_priority_introduction
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -0500533 : zenAlarm
534 ? R.string.zen_alarms_introduction
535 : mVoiceCapable
536 ? R.string.zen_silence_introduction_voice
537 : R.string.zen_silence_introduction;
538 mConfigurableTexts.add(mZenIntroductionMessage, message);
Julia Reynolds03c548f2016-12-14 15:02:38 -0500539 mConfigurableTexts.update();
John Spurlockd9c75db2015-04-28 11:19:13 -0400540 mZenIntroductionCustomize.setVisibility(zenImportant ? VISIBLE : GONE);
541 }
John Spurlock8be53ea2015-05-29 12:04:21 -0400542 final String warning = computeAlarmWarningText(zenNone);
543 mZenAlarmWarning.setVisibility(warning != null ? VISIBLE : GONE);
544 mZenAlarmWarning.setText(warning);
545 }
546
547 private String computeAlarmWarningText(boolean zenNone) {
548 if (!zenNone) {
549 return null;
550 }
551 final long now = System.currentTimeMillis();
552 final long nextAlarm = mController.getNextAlarm();
553 if (nextAlarm < now) {
554 return null;
555 }
556 int warningRes = 0;
557 if (mSessionExitCondition == null || isForever(mSessionExitCondition)) {
558 warningRes = R.string.zen_alarm_warning_indef;
559 } else {
560 final long time = ZenModeConfig.tryParseCountdownConditionId(mSessionExitCondition.id);
561 if (time > now && nextAlarm < time) {
562 warningRes = R.string.zen_alarm_warning;
563 }
564 }
565 if (warningRes == 0) {
566 return null;
567 }
568 final boolean soon = (nextAlarm - now) < 24 * 60 * 60 * 1000;
569 final boolean is24 = DateFormat.is24HourFormat(mContext, ActivityManager.getCurrentUser());
570 final String skeleton = soon ? (is24 ? "Hm" : "hma") : (is24 ? "EEEHm" : "EEEhma");
571 final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
572 final CharSequence formattedTime = DateFormat.format(pattern, nextAlarm);
573 final int templateRes = soon ? R.string.alarm_template : R.string.alarm_template_far;
574 final String template = getResources().getString(templateRes, formattedTime);
575 return getResources().getString(warningRes, template);
John Spurlock89f060a2014-07-16 21:03:15 -0400576 }
577
John Spurlockb2278d62015-04-07 12:47:12 -0400578 private static Condition parseExistingTimeCondition(Context context, Condition condition) {
John Spurlock4db0d982014-08-13 09:19:03 -0400579 if (condition == null) return null;
580 final long time = ZenModeConfig.tryParseCountdownConditionId(condition.id);
John Spurlock856edeb2014-06-01 20:36:47 -0400581 if (time == 0) return null;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400582 final long now = System.currentTimeMillis();
583 final long span = time - now;
John Spurlock856edeb2014-06-01 20:36:47 -0400584 if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
John Spurlockb2278d62015-04-07 12:47:12 -0400585 return ZenModeConfig.toTimeCondition(context,
Julia Reynolds0842fe82015-10-01 14:34:22 -0400586 time, Math.round(span / (float) MINUTES_MS), ActivityManager.getCurrentUser(),
John Spurlockbbde2672015-05-13 15:42:04 -0400587 false /*shortVersion*/);
John Spurlock86005342014-05-23 11:58:00 -0400588 }
589
John Spurlock4db0d982014-08-13 09:19:03 -0400590 private void handleUpdateConditions() {
John Spurlock530052a2014-11-30 16:26:19 -0500591 if (mTransitionHelper.isTransitioning()) {
John Spurlock530052a2014-11-30 16:26:19 -0500592 return;
593 }
John Spurlock4db0d982014-08-13 09:19:03 -0400594 final int conditionCount = mConditions == null ? 0 : mConditions.length;
595 if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);
John Spurlock4db0d982014-08-13 09:19:03 -0400596 // forever
Julia Reynolds656f9862016-06-01 11:37:29 -0400597 bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
Julia Reynolds0842fe82015-10-01 14:34:22 -0400598 FOREVER_CONDITION_INDEX);
John Spurlock4db0d982014-08-13 09:19:03 -0400599 // countdown
John Spurlock0b688502014-12-22 15:13:30 -0500600 if (mCountdownConditionSupported && mTimeCondition != null) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400601 bind(mTimeCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
Julia Reynolds0842fe82015-10-01 14:34:22 -0400602 COUNTDOWN_CONDITION_INDEX);
John Spurlock86005342014-05-23 11:58:00 -0400603 }
Julia Reynolds0842fe82015-10-01 14:34:22 -0400604 // countdown until alarm
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400605 if (mCountdownConditionSupported) {
606 Condition nextAlarmCondition = getTimeUntilNextAlarmCondition();
607 if (nextAlarmCondition != null) {
Julia Reynoldsc3960f62016-06-02 14:04:31 -0400608 mZenRadioGroup.getChildAt(
609 COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.VISIBLE);
610 mZenRadioGroupContent.getChildAt(
611 COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.VISIBLE);
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400612 bind(nextAlarmCondition,
Julia Reynolds656f9862016-06-01 11:37:29 -0400613 mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX),
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400614 COUNTDOWN_ALARM_CONDITION_INDEX);
Julia Reynoldsc3960f62016-06-02 14:04:31 -0400615 } else {
616 mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.GONE);
617 mZenRadioGroupContent.getChildAt(
618 COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.GONE);
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400619 }
John Spurlock4db0d982014-08-13 09:19:03 -0400620 }
John Spurlock3e077012014-11-29 13:22:21 -0500621 // ensure something is selected
Jason Monkbe3235a2017-04-05 09:29:53 -0400622 if (mExpanded) {
John Spurlock3e077012014-11-29 13:22:21 -0500623 ensureSelection();
624 }
Jason Monke138f552016-01-18 09:21:45 -0500625 mZenConditions.setVisibility(mSessionZen != Global.ZEN_MODE_OFF ? View.VISIBLE : View.GONE);
John Spurlock4db0d982014-08-13 09:19:03 -0400626 }
627
John Spurlock0b688502014-12-22 15:13:30 -0500628 private Condition forever() {
John Spurlockb2278d62015-04-07 12:47:12 -0400629 return new Condition(mForeverId, foreverSummary(mContext), "", "", 0 /*icon*/,
630 Condition.STATE_TRUE, 0 /*flags*/);
John Spurlock0b688502014-12-22 15:13:30 -0500631 }
632
John Spurlockb2278d62015-04-07 12:47:12 -0400633 private static String foreverSummary(Context context) {
634 return context.getString(com.android.internal.R.string.zen_mode_forever);
John Spurlock0b688502014-12-22 15:13:30 -0500635 }
636
Julia Reynolds0842fe82015-10-01 14:34:22 -0400637 // Returns a time condition if the next alarm is within the next week.
638 private Condition getTimeUntilNextAlarmCondition() {
639 GregorianCalendar weekRange = new GregorianCalendar();
640 final long now = weekRange.getTimeInMillis();
641 setToMidnight(weekRange);
Dan Sandler12d33932015-12-29 15:45:39 -0500642 weekRange.add(Calendar.DATE, 6);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400643 final long nextAlarmMs = mController.getNextAlarm();
644 if (nextAlarmMs > 0) {
645 GregorianCalendar nextAlarm = new GregorianCalendar();
646 nextAlarm.setTimeInMillis(nextAlarmMs);
647 setToMidnight(nextAlarm);
648
649 if (weekRange.compareTo(nextAlarm) >= 0) {
Julia Reynolds5edde5f2016-11-11 14:30:51 -0500650 return ZenModeConfig.toTimeCondition(mContext, nextAlarmMs,
651 Math.round((nextAlarmMs - now) / (float) MINUTES_MS),
652 ActivityManager.getCurrentUser(), true);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400653 }
654 }
655 return null;
656 }
657
658 private void setToMidnight(Calendar calendar) {
659 calendar.set(Calendar.HOUR_OF_DAY, 0);
660 calendar.set(Calendar.MINUTE, 0);
661 calendar.set(Calendar.SECOND, 0);
662 calendar.set(Calendar.MILLISECOND, 0);
663 }
664
John Spurlock856edeb2014-06-01 20:36:47 -0400665 private ConditionTag getConditionTagAt(int index) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400666 return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
John Spurlock856edeb2014-06-01 20:36:47 -0400667 }
668
John Spurlock530052a2014-11-30 16:26:19 -0500669 private int getVisibleConditions() {
670 int rt = 0;
Julia Reynolds656f9862016-06-01 11:37:29 -0400671 final int N = mZenRadioGroupContent.getChildCount();
John Spurlock530052a2014-11-30 16:26:19 -0500672 for (int i = 0; i < N; i++) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400673 rt += mZenRadioGroupContent.getChildAt(i).getVisibility() == VISIBLE ? 1 : 0;
John Spurlock530052a2014-11-30 16:26:19 -0500674 }
675 return rt;
676 }
677
678 private void hideAllConditions() {
Julia Reynolds656f9862016-06-01 11:37:29 -0400679 final int N = mZenRadioGroupContent.getChildCount();
John Spurlock530052a2014-11-30 16:26:19 -0500680 for (int i = 0; i < N; i++) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400681 mZenRadioGroupContent.getChildAt(i).setVisibility(GONE);
John Spurlock530052a2014-11-30 16:26:19 -0500682 }
683 }
684
John Spurlock3e077012014-11-29 13:22:21 -0500685 private void ensureSelection() {
John Spurlock856edeb2014-06-01 20:36:47 -0400686 // are we left without anything selected? if so, set a default
John Spurlock530052a2014-11-30 16:26:19 -0500687 final int visibleConditions = getVisibleConditions();
688 if (visibleConditions == 0) return;
689 for (int i = 0; i < visibleConditions; i++) {
690 final ConditionTag tag = getConditionTagAt(i);
691 if (tag != null && tag.rb.isChecked()) {
692 if (DEBUG) Log.d(mTag, "Not selecting a default, checked=" + tag.condition);
John Spurlock856edeb2014-06-01 20:36:47 -0400693 return;
694 }
695 }
John Spurlock530052a2014-11-30 16:26:19 -0500696 final ConditionTag foreverTag = getConditionTagAt(FOREVER_CONDITION_INDEX);
697 if (foreverTag == null) return;
John Spurlock856edeb2014-06-01 20:36:47 -0400698 if (DEBUG) Log.d(mTag, "Selecting a default");
John Spurlock8f8ecd62014-08-27 17:46:03 -0400699 final int favoriteIndex = mPrefs.getMinuteIndex();
Jason Monkbe3235a2017-04-05 09:29:53 -0400700 if (mExitCondition != null && mExitCondition.equals(mTimeCondition)) {
701 getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
Jason Monk035a9362017-04-20 15:51:16 -0400702 } else if (favoriteIndex == -1 || !mCountdownConditionSupported ||
703 mAttachedZen != Global.ZEN_MODE_OFF) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400704 foreverTag.rb.setChecked(true);
John Spurlock856edeb2014-06-01 20:36:47 -0400705 } else {
Selim Cinek9c4a7072014-11-21 17:44:34 +0100706 mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
707 MINUTE_BUCKETS[favoriteIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400708 mBucketIndex = favoriteIndex;
Julia Reynolds656f9862016-06-01 11:37:29 -0400709 bind(mTimeCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
Julia Reynolds0842fe82015-10-01 14:34:22 -0400710 COUNTDOWN_CONDITION_INDEX);
Julia Reynolds656f9862016-06-01 11:37:29 -0400711 getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
John Spurlock856edeb2014-06-01 20:36:47 -0400712 }
713 }
714
John Spurlockb2278d62015-04-07 12:47:12 -0400715 private static boolean isCountdown(Condition c) {
John Spurlock530052a2014-11-30 16:26:19 -0500716 return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
717 }
718
John Spurlock0b688502014-12-22 15:13:30 -0500719 private boolean isForever(Condition c) {
720 return c != null && mForeverId.equals(c.id);
721 }
722
Julia Reynolds0842fe82015-10-01 14:34:22 -0400723 private void bind(final Condition condition, final View row, final int rowId) {
John Spurlock0b688502014-12-22 15:13:30 -0500724 if (condition == null) throw new IllegalArgumentException("condition must not be null");
725 final boolean enabled = condition.state == Condition.STATE_TRUE;
John Spurlock856edeb2014-06-01 20:36:47 -0400726 final ConditionTag tag =
727 row.getTag() != null ? (ConditionTag) row.getTag() : new ConditionTag();
728 row.setTag(tag);
John Spurlock530052a2014-11-30 16:26:19 -0500729 final boolean first = tag.rb == null;
John Spurlock856edeb2014-06-01 20:36:47 -0400730 if (tag.rb == null) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400731 tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowId);
John Spurlock856edeb2014-06-01 20:36:47 -0400732 }
John Spurlock4db0d982014-08-13 09:19:03 -0400733 tag.condition = condition;
John Spurlock530052a2014-11-30 16:26:19 -0500734 final Uri conditionId = getConditionId(tag.condition);
Julia Reynolds656f9862016-06-01 11:37:29 -0400735 if (DEBUG) Log.d(mTag, "bind i=" + mZenRadioGroupContent.indexOfChild(row) + " first="
736 + first + " condition=" + conditionId);
John Spurlock856edeb2014-06-01 20:36:47 -0400737 tag.rb.setEnabled(enabled);
738 tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
John Spurlock86005342014-05-23 11:58:00 -0400739 @Override
740 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
John Spurlockae641c92014-06-30 18:11:40 -0400741 if (mExpanded && isChecked) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400742 tag.rb.setChecked(true);
John Spurlock530052a2014-11-30 16:26:19 -0500743 if (DEBUG) Log.d(mTag, "onCheckedChanged " + conditionId);
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500744 MetricsLogger.action(mContext, MetricsEvent.QS_DND_CONDITION_SELECT);
John Spurlock4db0d982014-08-13 09:19:03 -0400745 select(tag.condition);
John Spurlocka0457c22014-09-26 13:22:08 -0400746 announceConditionSelection(tag);
John Spurlock86005342014-05-23 11:58:00 -0400747 }
748 }
749 });
John Spurlocka0457c22014-09-26 13:22:08 -0400750
John Spurlockc90e6fe2014-10-28 11:21:42 -0400751 if (tag.lines == null) {
752 tag.lines = row.findViewById(android.R.id.content);
John Spurlock86005342014-05-23 11:58:00 -0400753 }
John Spurlockc90e6fe2014-10-28 11:21:42 -0400754 if (tag.line1 == null) {
755 tag.line1 = (TextView) row.findViewById(android.R.id.text1);
Julia Reynolds03c548f2016-12-14 15:02:38 -0500756 mConfigurableTexts.add(tag.line1);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400757 }
758 if (tag.line2 == null) {
759 tag.line2 = (TextView) row.findViewById(android.R.id.text2);
Julia Reynolds03c548f2016-12-14 15:02:38 -0500760 mConfigurableTexts.add(tag.line2);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400761 }
John Spurlock0b688502014-12-22 15:13:30 -0500762 final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
763 : condition.summary;
764 final String line2 = condition.line2;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400765 tag.line1.setText(line1);
766 if (TextUtils.isEmpty(line2)) {
767 tag.line2.setVisibility(GONE);
768 } else {
769 tag.line2.setVisibility(VISIBLE);
770 tag.line2.setText(line2);
771 }
772 tag.lines.setEnabled(enabled);
773 tag.lines.setAlpha(enabled ? 1 : .4f);
John Spurlocka0457c22014-09-26 13:22:08 -0400774
John Spurlock86005342014-05-23 11:58:00 -0400775 final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
776 button1.setOnClickListener(new OnClickListener() {
777 @Override
778 public void onClick(View v) {
Julia Reynolds0842fe82015-10-01 14:34:22 -0400779 onClickTimeButton(row, tag, false /*down*/, rowId);
John Spurlock86005342014-05-23 11:58:00 -0400780 }
781 });
782
783 final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
784 button2.setOnClickListener(new OnClickListener() {
785 @Override
786 public void onClick(View v) {
Julia Reynolds0842fe82015-10-01 14:34:22 -0400787 onClickTimeButton(row, tag, true /*up*/, rowId);
John Spurlock86005342014-05-23 11:58:00 -0400788 }
789 });
John Spurlockc90e6fe2014-10-28 11:21:42 -0400790 tag.lines.setOnClickListener(new OnClickListener() {
John Spurlock86005342014-05-23 11:58:00 -0400791 @Override
792 public void onClick(View v) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400793 tag.rb.setChecked(true);
John Spurlock86005342014-05-23 11:58:00 -0400794 }
795 });
John Spurlock856edeb2014-06-01 20:36:47 -0400796
John Spurlock530052a2014-11-30 16:26:19 -0500797 final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400798 if (rowId != COUNTDOWN_ALARM_CONDITION_INDEX && time > 0) {
John Spurlock530052a2014-11-30 16:26:19 -0500799 button1.setVisibility(VISIBLE);
800 button2.setVisibility(VISIBLE);
John Spurlock856edeb2014-06-01 20:36:47 -0400801 if (mBucketIndex > -1) {
802 button1.setEnabled(mBucketIndex > 0);
803 button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
804 } else {
805 final long span = time - System.currentTimeMillis();
806 button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400807 final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100808 MAX_BUCKET_MINUTES, ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400809 button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
810 }
811
812 button1.setAlpha(button1.isEnabled() ? 1f : .5f);
813 button2.setAlpha(button2.isEnabled() ? 1f : .5f);
John Spurlock86005342014-05-23 11:58:00 -0400814 } else {
John Spurlock530052a2014-11-30 16:26:19 -0500815 button1.setVisibility(GONE);
816 button2.setVisibility(GONE);
John Spurlock86005342014-05-23 11:58:00 -0400817 }
John Spurlocka0457c22014-09-26 13:22:08 -0400818 // wire up interaction callbacks for newly-added condition rows
John Spurlock530052a2014-11-30 16:26:19 -0500819 if (first) {
John Spurlocka0457c22014-09-26 13:22:08 -0400820 Interaction.register(tag.rb, mInteractionCallback);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400821 Interaction.register(tag.lines, mInteractionCallback);
John Spurlocka0457c22014-09-26 13:22:08 -0400822 Interaction.register(button1, mInteractionCallback);
823 Interaction.register(button2, mInteractionCallback);
824 }
John Spurlock530052a2014-11-30 16:26:19 -0500825 row.setVisibility(VISIBLE);
John Spurlocka0457c22014-09-26 13:22:08 -0400826 }
827
828 private void announceConditionSelection(ConditionTag tag) {
829 final int zen = getSelectedZen(Global.ZEN_MODE_OFF);
830 String modeText;
831 switch(zen) {
832 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
John Spurlockd9c75db2015-04-28 11:19:13 -0400833 modeText = mContext.getString(R.string.interruption_level_priority);
John Spurlocka0457c22014-09-26 13:22:08 -0400834 break;
835 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlockd9c75db2015-04-28 11:19:13 -0400836 modeText = mContext.getString(R.string.interruption_level_none);
John Spurlocka0457c22014-09-26 13:22:08 -0400837 break;
John Spurlock4f1163c2015-04-02 17:41:21 -0400838 case Global.ZEN_MODE_ALARMS:
John Spurlockd9c75db2015-04-28 11:19:13 -0400839 modeText = mContext.getString(R.string.interruption_level_alarms);
John Spurlock4f1163c2015-04-02 17:41:21 -0400840 break;
841 default:
John Spurlocka0457c22014-09-26 13:22:08 -0400842 return;
843 }
844 announceForAccessibility(mContext.getString(R.string.zen_mode_and_condition, modeText,
John Spurlockc90e6fe2014-10-28 11:21:42 -0400845 tag.line1.getText()));
John Spurlock856edeb2014-06-01 20:36:47 -0400846 }
847
Julia Reynolds0842fe82015-10-01 14:34:22 -0400848 private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500849 MetricsLogger.action(mContext, MetricsEvent.QS_DND_TIME, up);
John Spurlock856edeb2014-06-01 20:36:47 -0400850 Condition newCondition = null;
851 final int N = MINUTE_BUCKETS.length;
852 if (mBucketIndex == -1) {
853 // not on a known index, search for the next or prev bucket by time
John Spurlock4db0d982014-08-13 09:19:03 -0400854 final Uri conditionId = getConditionId(tag.condition);
855 final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
John Spurlock856edeb2014-06-01 20:36:47 -0400856 final long now = System.currentTimeMillis();
857 for (int i = 0; i < N; i++) {
858 int j = up ? i : N - 1 - i;
859 final int bucketMinutes = MINUTE_BUCKETS[j];
860 final long bucketTime = now + bucketMinutes * MINUTES_MS;
861 if (up && bucketTime > time || !up && bucketTime < time) {
862 mBucketIndex = j;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400863 newCondition = ZenModeConfig.toTimeCondition(mContext,
Julia Reynolds0842fe82015-10-01 14:34:22 -0400864 bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
John Spurlockbbde2672015-05-13 15:42:04 -0400865 false /*shortVersion*/);
John Spurlock856edeb2014-06-01 20:36:47 -0400866 break;
867 }
868 }
869 if (newCondition == null) {
870 mBucketIndex = DEFAULT_BUCKET_INDEX;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400871 newCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100872 MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400873 }
874 } else {
875 // on a known index, simply increment or decrement
876 mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
John Spurlockc90e6fe2014-10-28 11:21:42 -0400877 newCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100878 MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400879 }
John Spurlock4db0d982014-08-13 09:19:03 -0400880 mTimeCondition = newCondition;
Julia Reynolds0842fe82015-10-01 14:34:22 -0400881 bind(mTimeCondition, row, rowId);
Julia Reynolds656f9862016-06-01 11:37:29 -0400882 tag.rb.setChecked(true);
John Spurlock4db0d982014-08-13 09:19:03 -0400883 select(mTimeCondition);
John Spurlocka0457c22014-09-26 13:22:08 -0400884 announceConditionSelection(tag);
John Spurlock856edeb2014-06-01 20:36:47 -0400885 }
886
John Spurlock530052a2014-11-30 16:26:19 -0500887 private void select(final Condition condition) {
John Spurlock4db0d982014-08-13 09:19:03 -0400888 if (DEBUG) Log.d(mTag, "select " + condition);
John Spurlockb2278d62015-04-07 12:47:12 -0400889 if (mSessionZen == -1 || mSessionZen == Global.ZEN_MODE_OFF) {
890 if (DEBUG) Log.d(mTag, "Ignoring condition selection outside of manual zen");
891 return;
892 }
893 final Uri realConditionId = getRealConditionId(condition);
John Spurlock856edeb2014-06-01 20:36:47 -0400894 if (mController != null) {
John Spurlock530052a2014-11-30 16:26:19 -0500895 AsyncTask.execute(new Runnable() {
896 @Override
897 public void run() {
John Spurlockb2278d62015-04-07 12:47:12 -0400898 mController.setZen(mSessionZen, realConditionId, TAG + ".selectCondition");
John Spurlock530052a2014-11-30 16:26:19 -0500899 }
900 });
John Spurlock856edeb2014-06-01 20:36:47 -0400901 }
John Spurlock4db0d982014-08-13 09:19:03 -0400902 setExitCondition(condition);
John Spurlockb2278d62015-04-07 12:47:12 -0400903 if (realConditionId == null) {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400904 mPrefs.setMinuteIndex(-1);
John Spurlock530052a2014-11-30 16:26:19 -0500905 } else if (isCountdown(condition) && mBucketIndex != -1) {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400906 mPrefs.setMinuteIndex(mBucketIndex);
John Spurlock86005342014-05-23 11:58:00 -0400907 }
John Spurlock530052a2014-11-30 16:26:19 -0500908 setSessionExitCondition(copy(condition));
John Spurlock86005342014-05-23 11:58:00 -0400909 }
910
John Spurlock86005342014-05-23 11:58:00 -0400911 private void fireInteraction() {
912 if (mCallback != null) {
913 mCallback.onInteraction();
914 }
915 }
916
John Spurlockae641c92014-06-30 18:11:40 -0400917 private void fireExpanded() {
918 if (mCallback != null) {
919 mCallback.onExpanded(mExpanded);
920 }
921 }
922
John Spurlock86005342014-05-23 11:58:00 -0400923 private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
924 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400925 public void onManualRuleChanged(ZenRule rule) {
926 mHandler.obtainMessage(H.MANUAL_RULE_CHANGED, rule).sendToTarget();
John Spurlock856edeb2014-06-01 20:36:47 -0400927 }
John Spurlock86005342014-05-23 11:58:00 -0400928 };
929
930 private final class H extends Handler {
John Spurlockb2278d62015-04-07 12:47:12 -0400931 private static final int MANUAL_RULE_CHANGED = 2;
John Spurlockf55b7f22015-04-13 19:21:26 -0400932 private static final int UPDATE_WIDGETS = 3;
John Spurlock86005342014-05-23 11:58:00 -0400933
934 private H() {
935 super(Looper.getMainLooper());
936 }
937
938 @Override
939 public void handleMessage(Message msg) {
John Spurlockf55b7f22015-04-13 19:21:26 -0400940 switch (msg.what) {
John Spurlockf55b7f22015-04-13 19:21:26 -0400941 case MANUAL_RULE_CHANGED: handleUpdateManualRule((ZenRule) msg.obj); break;
942 case UPDATE_WIDGETS: updateWidgets(); break;
John Spurlock86005342014-05-23 11:58:00 -0400943 }
944 }
945 }
946
947 public interface Callback {
John Spurlockf55b7f22015-04-13 19:21:26 -0400948 void onPrioritySettings();
John Spurlock86005342014-05-23 11:58:00 -0400949 void onInteraction();
John Spurlockae641c92014-06-30 18:11:40 -0400950 void onExpanded(boolean expanded);
John Spurlock86005342014-05-23 11:58:00 -0400951 }
John Spurlock856edeb2014-06-01 20:36:47 -0400952
953 // used as the view tag on condition rows
954 private static class ConditionTag {
955 RadioButton rb;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400956 View lines;
957 TextView line1;
958 TextView line2;
John Spurlock4db0d982014-08-13 09:19:03 -0400959 Condition condition;
John Spurlock856edeb2014-06-01 20:36:47 -0400960 }
961
John Spurlockf55b7f22015-04-13 19:21:26 -0400962 private final class ZenPrefs implements OnSharedPreferenceChangeListener {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400963 private final int mNoneDangerousThreshold;
John Spurlock856edeb2014-06-01 20:36:47 -0400964
965 private int mMinuteIndex;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400966 private int mNoneSelected;
John Spurlockd9c75db2015-04-28 11:19:13 -0400967 private boolean mConfirmedPriorityIntroduction;
968 private boolean mConfirmedSilenceIntroduction;
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -0500969 private boolean mConfirmedAlarmIntroduction;
John Spurlock856edeb2014-06-01 20:36:47 -0400970
John Spurlockf55b7f22015-04-13 19:21:26 -0400971 private ZenPrefs() {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400972 mNoneDangerousThreshold = mContext.getResources()
973 .getInteger(R.integer.zen_mode_alarm_warning_threshold);
John Spurlockf55b7f22015-04-13 19:21:26 -0400974 Prefs.registerListener(mContext, this);
John Spurlock856edeb2014-06-01 20:36:47 -0400975 updateMinuteIndex();
John Spurlock8f8ecd62014-08-27 17:46:03 -0400976 updateNoneSelected();
John Spurlockd9c75db2015-04-28 11:19:13 -0400977 updateConfirmedPriorityIntroduction();
978 updateConfirmedSilenceIntroduction();
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -0500979 updateConfirmedAlarmIntroduction();
John Spurlock8f8ecd62014-08-27 17:46:03 -0400980 }
981
982 public void trackNoneSelected() {
983 mNoneSelected = clampNoneSelected(mNoneSelected + 1);
984 if (DEBUG) Log.d(mTag, "Setting none selected: " + mNoneSelected + " threshold="
985 + mNoneDangerousThreshold);
John Spurlockf55b7f22015-04-13 19:21:26 -0400986 Prefs.putInt(mContext, Prefs.Key.DND_NONE_SELECTED, mNoneSelected);
John Spurlock856edeb2014-06-01 20:36:47 -0400987 }
988
989 public int getMinuteIndex() {
990 return mMinuteIndex;
991 }
992
993 public void setMinuteIndex(int minuteIndex) {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400994 minuteIndex = clampIndex(minuteIndex);
John Spurlock856edeb2014-06-01 20:36:47 -0400995 if (minuteIndex == mMinuteIndex) return;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400996 mMinuteIndex = clampIndex(minuteIndex);
John Spurlock856edeb2014-06-01 20:36:47 -0400997 if (DEBUG) Log.d(mTag, "Setting favorite minute index: " + mMinuteIndex);
John Spurlockf55b7f22015-04-13 19:21:26 -0400998 Prefs.putInt(mContext, Prefs.Key.DND_FAVORITE_BUCKET_INDEX, mMinuteIndex);
John Spurlock856edeb2014-06-01 20:36:47 -0400999 }
1000
1001 @Override
1002 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
1003 updateMinuteIndex();
John Spurlock8f8ecd62014-08-27 17:46:03 -04001004 updateNoneSelected();
John Spurlockd9c75db2015-04-28 11:19:13 -04001005 updateConfirmedPriorityIntroduction();
1006 updateConfirmedSilenceIntroduction();
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -05001007 updateConfirmedAlarmIntroduction();
John Spurlock856edeb2014-06-01 20:36:47 -04001008 }
1009
1010 private void updateMinuteIndex() {
John Spurlockf55b7f22015-04-13 19:21:26 -04001011 mMinuteIndex = clampIndex(Prefs.getInt(mContext,
1012 Prefs.Key.DND_FAVORITE_BUCKET_INDEX, DEFAULT_BUCKET_INDEX));
John Spurlock856edeb2014-06-01 20:36:47 -04001013 if (DEBUG) Log.d(mTag, "Favorite minute index: " + mMinuteIndex);
1014 }
1015
John Spurlock8f8ecd62014-08-27 17:46:03 -04001016 private int clampIndex(int index) {
1017 return MathUtils.constrain(index, -1, MINUTE_BUCKETS.length - 1);
1018 }
1019
1020 private void updateNoneSelected() {
John Spurlockf55b7f22015-04-13 19:21:26 -04001021 mNoneSelected = clampNoneSelected(Prefs.getInt(mContext,
1022 Prefs.Key.DND_NONE_SELECTED, 0));
John Spurlock8f8ecd62014-08-27 17:46:03 -04001023 if (DEBUG) Log.d(mTag, "None selected: " + mNoneSelected);
1024 }
1025
1026 private int clampNoneSelected(int noneSelected) {
1027 return MathUtils.constrain(noneSelected, 0, Integer.MAX_VALUE);
John Spurlock856edeb2014-06-01 20:36:47 -04001028 }
John Spurlockf55b7f22015-04-13 19:21:26 -04001029
John Spurlockd9c75db2015-04-28 11:19:13 -04001030 private void updateConfirmedPriorityIntroduction() {
John Spurlockf55b7f22015-04-13 19:21:26 -04001031 final boolean confirmed = Prefs.getBoolean(mContext,
1032 Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, false);
John Spurlockd9c75db2015-04-28 11:19:13 -04001033 if (confirmed == mConfirmedPriorityIntroduction) return;
1034 mConfirmedPriorityIntroduction = confirmed;
1035 if (DEBUG) Log.d(mTag, "Confirmed priority introduction: "
1036 + mConfirmedPriorityIntroduction);
1037 }
1038
1039 private void updateConfirmedSilenceIntroduction() {
1040 final boolean confirmed = Prefs.getBoolean(mContext,
1041 Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION, false);
1042 if (confirmed == mConfirmedSilenceIntroduction) return;
1043 mConfirmedSilenceIntroduction = confirmed;
1044 if (DEBUG) Log.d(mTag, "Confirmed silence introduction: "
1045 + mConfirmedSilenceIntroduction);
John Spurlockf55b7f22015-04-13 19:21:26 -04001046 }
Julia Reynoldsd7a00aa2017-02-16 15:01:36 -05001047
1048 private void updateConfirmedAlarmIntroduction() {
1049 final boolean confirmed = Prefs.getBoolean(mContext,
1050 Prefs.Key.DND_CONFIRMED_ALARM_INTRODUCTION, false);
1051 if (confirmed == mConfirmedAlarmIntroduction) return;
1052 mConfirmedAlarmIntroduction = confirmed;
1053 if (DEBUG) Log.d(mTag, "Confirmed alarm introduction: "
1054 + mConfirmedAlarmIntroduction);
1055 }
John Spurlock856edeb2014-06-01 20:36:47 -04001056 }
John Spurlockae641c92014-06-30 18:11:40 -04001057
Muyuan Li8303bd22016-03-23 20:08:26 -07001058 protected final SegmentedButtons.Callback mZenButtonsCallback = new SegmentedButtons.Callback() {
John Spurlockae641c92014-06-30 18:11:40 -04001059 @Override
Chris Wren4572cbc2015-06-29 11:27:18 -04001060 public void onSelected(final Object value, boolean fromClick) {
John Spurlockb2278d62015-04-07 12:47:12 -04001061 if (value != null && mZenButtons.isShown() && isAttachedToWindow()) {
John Spurlockd9c75db2015-04-28 11:19:13 -04001062 final int zen = (Integer) value;
Chris Wren4572cbc2015-06-29 11:27:18 -04001063 if (fromClick) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -05001064 MetricsLogger.action(mContext, MetricsEvent.QS_DND_ZEN_SELECT, zen);
Chris Wren4572cbc2015-06-29 11:27:18 -04001065 }
John Spurlockd9c75db2015-04-28 11:19:13 -04001066 if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + zen);
John Spurlockb2278d62015-04-07 12:47:12 -04001067 final Uri realConditionId = getRealConditionId(mSessionExitCondition);
John Spurlock530052a2014-11-30 16:26:19 -05001068 AsyncTask.execute(new Runnable() {
1069 @Override
1070 public void run() {
John Spurlockd9c75db2015-04-28 11:19:13 -04001071 mController.setZen(zen, realConditionId, TAG + ".selectZen");
1072 if (zen != Global.ZEN_MODE_OFF) {
1073 Prefs.putInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, zen);
1074 }
John Spurlock530052a2014-11-30 16:26:19 -05001075 }
1076 });
John Spurlockae641c92014-06-30 18:11:40 -04001077 }
1078 }
John Spurlocka0457c22014-09-26 13:22:08 -04001079
1080 @Override
1081 public void onInteraction() {
1082 fireInteraction();
1083 }
1084 };
1085
1086 private final Interaction.Callback mInteractionCallback = new Interaction.Callback() {
1087 @Override
1088 public void onInteraction() {
1089 fireInteraction();
1090 }
John Spurlockae641c92014-06-30 18:11:40 -04001091 };
John Spurlock530052a2014-11-30 16:26:19 -05001092
1093 private final class TransitionHelper implements TransitionListener, Runnable {
1094 private final ArraySet<View> mTransitioningViews = new ArraySet<View>();
1095
1096 private boolean mTransitioning;
John Spurlock530052a2014-11-30 16:26:19 -05001097 private boolean mPendingUpdateWidgets;
1098
1099 public void clear() {
1100 mTransitioningViews.clear();
Julia Reynolds0842fe82015-10-01 14:34:22 -04001101 mPendingUpdateWidgets = false;
John Spurlock530052a2014-11-30 16:26:19 -05001102 }
1103
1104 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1105 pw.println(" TransitionHelper state:");
John Spurlock530052a2014-11-30 16:26:19 -05001106 pw.print(" mPendingUpdateWidgets="); pw.println(mPendingUpdateWidgets);
1107 pw.print(" mTransitioning="); pw.println(mTransitioning);
1108 pw.print(" mTransitioningViews="); pw.println(mTransitioningViews);
1109 }
1110
John Spurlock530052a2014-11-30 16:26:19 -05001111 public void pendingUpdateWidgets() {
1112 mPendingUpdateWidgets = true;
1113 }
1114
1115 public boolean isTransitioning() {
1116 return !mTransitioningViews.isEmpty();
1117 }
1118
1119 @Override
1120 public void startTransition(LayoutTransition transition,
1121 ViewGroup container, View view, int transitionType) {
1122 mTransitioningViews.add(view);
1123 updateTransitioning();
1124 }
1125
1126 @Override
1127 public void endTransition(LayoutTransition transition,
1128 ViewGroup container, View view, int transitionType) {
1129 mTransitioningViews.remove(view);
1130 updateTransitioning();
1131 }
1132
1133 @Override
1134 public void run() {
1135 if (DEBUG) Log.d(mTag, "TransitionHelper run"
Julia Reynolds0842fe82015-10-01 14:34:22 -04001136 + " mPendingUpdateWidgets=" + mPendingUpdateWidgets);
John Spurlock530052a2014-11-30 16:26:19 -05001137 if (mPendingUpdateWidgets) {
1138 updateWidgets();
1139 }
Julia Reynolds0842fe82015-10-01 14:34:22 -04001140 mPendingUpdateWidgets = false;
John Spurlock530052a2014-11-30 16:26:19 -05001141 }
1142
1143 private void updateTransitioning() {
1144 final boolean transitioning = isTransitioning();
1145 if (mTransitioning == transitioning) return;
1146 mTransitioning = transitioning;
1147 if (DEBUG) Log.d(mTag, "TransitionHelper mTransitioning=" + mTransitioning);
1148 if (!mTransitioning) {
Julia Reynolds0842fe82015-10-01 14:34:22 -04001149 if (mPendingUpdateWidgets) {
John Spurlock530052a2014-11-30 16:26:19 -05001150 mHandler.post(this);
1151 } else {
Julia Reynolds0842fe82015-10-01 14:34:22 -04001152 mPendingUpdateWidgets = false;
John Spurlock530052a2014-11-30 16:26:19 -05001153 }
1154 }
1155 }
1156 }
John Spurlock86005342014-05-23 11:58:00 -04001157}