blob: 00cd04f9ddfd87e68aedfdb8329e200868d1f19c [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;
John Spurlock530052a2014-11-30 16:26:19 -050039import android.util.ArraySet;
John Spurlock86005342014-05-23 11:58:00 -040040import android.util.AttributeSet;
John Spurlock856edeb2014-06-01 20:36:47 -040041import android.util.Log;
John Spurlock8f8ecd62014-08-27 17:46:03 -040042import android.util.MathUtils;
John Spurlock86005342014-05-23 11:58:00 -040043import android.view.LayoutInflater;
44import android.view.View;
John Spurlock3e077012014-11-29 13:22:21 -050045import android.view.ViewGroup;
John Spurlock86005342014-05-23 11:58:00 -040046import android.widget.CompoundButton;
47import android.widget.CompoundButton.OnCheckedChangeListener;
48import android.widget.ImageView;
49import android.widget.LinearLayout;
50import android.widget.RadioButton;
Julia Reynolds656f9862016-06-01 11:37:29 -040051import android.widget.RadioGroup;
John Spurlock86005342014-05-23 11:58:00 -040052import android.widget.TextView;
53
Chris Wren9e7283f2015-05-08 17:23:47 -040054import com.android.internal.logging.MetricsLogger;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050055import com.android.internal.logging.MetricsProto.MetricsEvent;
John Spurlockf55b7f22015-04-13 19:21:26 -040056import com.android.systemui.Prefs;
John Spurlock86005342014-05-23 11:58:00 -040057import com.android.systemui.R;
58import com.android.systemui.statusbar.policy.ZenModeController;
59
John Spurlock530052a2014-11-30 16:26:19 -050060import java.io.FileDescriptor;
61import java.io.PrintWriter;
John Spurlock86005342014-05-23 11:58:00 -040062import java.util.Arrays;
Julia Reynolds0842fe82015-10-01 14:34:22 -040063import java.util.Calendar;
64import java.util.GregorianCalendar;
John Spurlock8be53ea2015-05-29 12:04:21 -040065import java.util.Locale;
John Spurlock856edeb2014-06-01 20:36:47 -040066import java.util.Objects;
John Spurlock86005342014-05-23 11:58:00 -040067
68public class ZenModePanel extends LinearLayout {
John Spurlockae641c92014-06-30 18:11:40 -040069 private static final String TAG = "ZenModePanel";
70 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock856edeb2014-06-01 20:36:47 -040071
John Spurlock50806fc2014-07-15 10:22:02 -040072 private static final int SECONDS_MS = 1000;
73 private static final int MINUTES_MS = 60 * SECONDS_MS;
74
Julia Reynolds0ca82fe2015-11-05 11:08:02 -050075 private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
John Spurlock856edeb2014-06-01 20:36:47 -040076 private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
77 private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
78 private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
John Spurlockae641c92014-06-30 18:11:40 -040079 private static final int FOREVER_CONDITION_INDEX = 0;
John Spurlock530052a2014-11-30 16:26:19 -050080 private static final int COUNTDOWN_CONDITION_INDEX = 1;
Julia Reynolds0842fe82015-10-01 14:34:22 -040081 private static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -040082 private static final int COUNTDOWN_CONDITION_COUNT = 2;
John Spurlock856edeb2014-06-01 20:36:47 -040083
John Spurlockf55b7f22015-04-13 19:21:26 -040084 public static final Intent ZEN_SETTINGS
85 = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
86 public static final Intent ZEN_PRIORITY_SETTINGS
87 = new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
John Spurlock86005342014-05-23 11:58:00 -040088
John Spurlock7f1df5e2014-05-31 19:11:40 -040089 private final Context mContext;
Muyuan Li94fa1df2016-03-23 12:09:38 -070090 protected final LayoutInflater mInflater;
John Spurlock86005342014-05-23 11:58:00 -040091 private final H mHandler = new H();
John Spurlockf55b7f22015-04-13 19:21:26 -040092 private final ZenPrefs mPrefs;
John Spurlock530052a2014-11-30 16:26:19 -050093 private final TransitionHelper mTransitionHelper = new TransitionHelper();
John Spurlock0b688502014-12-22 15:13:30 -050094 private final Uri mForeverId;
John Spurlockd8963232015-06-08 16:26:12 -040095 private final SpTexts mSpTexts;
John Spurlock856edeb2014-06-01 20:36:47 -040096
John Spurlockeb2727b2014-07-19 23:11:36 -040097 private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
John Spurlockae641c92014-06-30 18:11:40 -040098
Muyuan Li8303bd22016-03-23 20:08:26 -070099 protected SegmentedButtons mZenButtons;
John Spurlockf55b7f22015-04-13 19:21:26 -0400100 private View mZenIntroduction;
John Spurlockd9c75db2015-04-28 11:19:13 -0400101 private TextView mZenIntroductionMessage;
John Spurlockf55b7f22015-04-13 19:21:26 -0400102 private View mZenIntroductionConfirm;
John Spurlockd8963232015-06-08 16:26:12 -0400103 private TextView mZenIntroductionCustomize;
Muyuan Li94fa1df2016-03-23 12:09:38 -0700104 protected LinearLayout mZenConditions;
John Spurlock8be53ea2015-05-29 12:04:21 -0400105 private TextView mZenAlarmWarning;
Julia Reynolds656f9862016-06-01 11:37:29 -0400106 private RadioGroup mZenRadioGroup;
107 private LinearLayout mZenRadioGroupContent;
John Spurlockae641c92014-06-30 18:11:40 -0400108
John Spurlock86005342014-05-23 11:58:00 -0400109 private Callback mCallback;
110 private ZenModeController mController;
John Spurlockad680d42015-01-30 15:48:15 -0500111 private boolean mCountdownConditionSupported;
John Spurlock86005342014-05-23 11:58:00 -0400112 private boolean mRequestingConditions;
John Spurlock4db0d982014-08-13 09:19:03 -0400113 private Condition mExitCondition;
John Spurlock856edeb2014-06-01 20:36:47 -0400114 private int mBucketIndex = -1;
John Spurlockae641c92014-06-30 18:11:40 -0400115 private boolean mExpanded;
John Spurlock530052a2014-11-30 16:26:19 -0500116 private boolean mHidden;
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400117 private int mSessionZen;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400118 private int mAttachedZen;
John Spurlock3e077012014-11-29 13:22:21 -0500119 private boolean mAttached;
John Spurlock4db0d982014-08-13 09:19:03 -0400120 private Condition mSessionExitCondition;
John Spurlock4db0d982014-08-13 09:19:03 -0400121 private Condition[] mConditions;
122 private Condition mTimeCondition;
John Spurlockcbd7a312015-06-21 10:46:28 -0400123 private boolean mVoiceCapable;
John Spurlock86005342014-05-23 11:58:00 -0400124
125 public ZenModePanel(Context context, AttributeSet attrs) {
126 super(context, attrs);
John Spurlock7f1df5e2014-05-31 19:11:40 -0400127 mContext = context;
John Spurlockf55b7f22015-04-13 19:21:26 -0400128 mPrefs = new ZenPrefs();
John Spurlockf7d22132014-07-10 19:03:00 -0400129 mInflater = LayoutInflater.from(mContext.getApplicationContext());
John Spurlock0b688502014-12-22 15:13:30 -0500130 mForeverId = Condition.newId(mContext).appendPath("forever").build();
John Spurlockd8963232015-06-08 16:26:12 -0400131 mSpTexts = new SpTexts(mContext);
John Spurlockcbd7a312015-06-21 10:46:28 -0400132 mVoiceCapable = Util.isVoiceCapable(mContext);
John Spurlock856edeb2014-06-01 20:36:47 -0400133 if (DEBUG) Log.d(mTag, "new ZenModePanel");
134 }
135
John Spurlock530052a2014-11-30 16:26:19 -0500136 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
137 pw.println("ZenModePanel state:");
138 pw.print(" mCountdownConditionSupported="); pw.println(mCountdownConditionSupported);
John Spurlock530052a2014-11-30 16:26:19 -0500139 pw.print(" mRequestingConditions="); pw.println(mRequestingConditions);
140 pw.print(" mAttached="); pw.println(mAttached);
141 pw.print(" mHidden="); pw.println(mHidden);
142 pw.print(" mExpanded="); pw.println(mExpanded);
143 pw.print(" mSessionZen="); pw.println(mSessionZen);
144 pw.print(" mAttachedZen="); pw.println(mAttachedZen);
John Spurlockd9c75db2015-04-28 11:19:13 -0400145 pw.print(" mConfirmedPriorityIntroduction=");
146 pw.println(mPrefs.mConfirmedPriorityIntroduction);
147 pw.print(" mConfirmedSilenceIntroduction=");
148 pw.println(mPrefs.mConfirmedSilenceIntroduction);
John Spurlockcbd7a312015-06-21 10:46:28 -0400149 pw.print(" mVoiceCapable="); pw.println(mVoiceCapable);
John Spurlock530052a2014-11-30 16:26:19 -0500150 mTransitionHelper.dump(fd, pw, args);
151 }
152
Muyuan Li8303bd22016-03-23 20:08:26 -0700153 protected void createZenButtons() {
John Spurlockae641c92014-06-30 18:11:40 -0400154 mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
John Spurlock4f1163c2015-04-02 17:41:21 -0400155 mZenButtons.addButton(R.string.interruption_level_none_twoline,
John Spurlockbd1abe62015-06-10 17:18:38 -0400156 R.string.interruption_level_none_with_warning,
John Spurlock4f1163c2015-04-02 17:41:21 -0400157 Global.ZEN_MODE_NO_INTERRUPTIONS);
158 mZenButtons.addButton(R.string.interruption_level_alarms_twoline,
John Spurlocka1c7ffe2015-06-08 15:34:05 -0400159 R.string.interruption_level_alarms,
John Spurlock4f1163c2015-04-02 17:41:21 -0400160 Global.ZEN_MODE_ALARMS);
161 mZenButtons.addButton(R.string.interruption_level_priority_twoline,
John Spurlocka1c7ffe2015-06-08 15:34:05 -0400162 R.string.interruption_level_priority,
John Spurlock4291fb72014-09-16 17:02:23 -0400163 Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
John Spurlockae641c92014-06-30 18:11:40 -0400164 mZenButtons.setCallback(mZenButtonsCallback);
Muyuan Li8303bd22016-03-23 20:08:26 -0700165 }
John Spurlockae641c92014-06-30 18:11:40 -0400166
Muyuan Li8303bd22016-03-23 20:08:26 -0700167 @Override
168 protected void onFinishInflate() {
169 super.onFinishInflate();
170 createZenButtons();
John Spurlockf55b7f22015-04-13 19:21:26 -0400171 mZenIntroduction = findViewById(R.id.zen_introduction);
John Spurlockd9c75db2015-04-28 11:19:13 -0400172 mZenIntroductionMessage = (TextView) findViewById(R.id.zen_introduction_message);
John Spurlockd8963232015-06-08 16:26:12 -0400173 mSpTexts.add(mZenIntroductionMessage);
John Spurlockf55b7f22015-04-13 19:21:26 -0400174 mZenIntroductionConfirm = findViewById(R.id.zen_introduction_confirm);
175 mZenIntroductionConfirm.setOnClickListener(new OnClickListener() {
176 @Override
177 public void onClick(View v) {
178 confirmZenIntroduction();
179 }
180 });
John Spurlockd8963232015-06-08 16:26:12 -0400181 mZenIntroductionCustomize = (TextView) findViewById(R.id.zen_introduction_customize);
John Spurlockf55b7f22015-04-13 19:21:26 -0400182 mZenIntroductionCustomize.setOnClickListener(new OnClickListener() {
183 @Override
184 public void onClick(View v) {
185 confirmZenIntroduction();
186 if (mCallback != null) {
187 mCallback.onPrioritySettings();
188 }
189 }
190 });
John Spurlockd8963232015-06-08 16:26:12 -0400191 mSpTexts.add(mZenIntroductionCustomize);
John Spurlockf55b7f22015-04-13 19:21:26 -0400192
John Spurlockae641c92014-06-30 18:11:40 -0400193 mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
John Spurlock8be53ea2015-05-29 12:04:21 -0400194 mZenAlarmWarning = (TextView) findViewById(R.id.zen_alarm_warning);
Julia Reynolds656f9862016-06-01 11:37:29 -0400195 mZenRadioGroup = (RadioGroup) findViewById(R.id.zen_radio_buttons);
196 mZenRadioGroupContent = (LinearLayout) findViewById(R.id.zen_radio_buttons_content);
John Spurlock814ee6ab2015-05-18 11:16:38 -0400197 }
John Spurlock530052a2014-11-30 16:26:19 -0500198
John Spurlock814ee6ab2015-05-18 11:16:38 -0400199 @Override
200 protected void onConfigurationChanged(Configuration newConfig) {
201 super.onConfigurationChanged(newConfig);
202 if (mZenButtons != null) {
203 mZenButtons.updateLocale();
204 }
John Spurlock3e077012014-11-29 13:22:21 -0500205 }
206
John Spurlockf55b7f22015-04-13 19:21:26 -0400207 private void confirmZenIntroduction() {
John Spurlockd9c75db2015-04-28 11:19:13 -0400208 final String prefKey = prefKeyForConfirmation(getSelectedZen(Global.ZEN_MODE_OFF));
209 if (prefKey == null) return;
210 if (DEBUG) Log.d(TAG, "confirmZenIntroduction " + prefKey);
211 Prefs.putBoolean(mContext, prefKey, true);
John Spurlockf55b7f22015-04-13 19:21:26 -0400212 mHandler.sendEmptyMessage(H.UPDATE_WIDGETS);
213 }
214
John Spurlockd9c75db2015-04-28 11:19:13 -0400215 private static String prefKeyForConfirmation(int zen) {
216 switch (zen) {
217 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
218 return Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION;
219 case Global.ZEN_MODE_NO_INTERRUPTIONS:
220 return Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION;
221 default:
222 return null;
John Spurlock530052a2014-11-30 16:26:19 -0500223 }
John Spurlock86005342014-05-23 11:58:00 -0400224 }
225
226 @Override
John Spurlock856edeb2014-06-01 20:36:47 -0400227 protected void onAttachedToWindow() {
228 super.onAttachedToWindow();
229 if (DEBUG) Log.d(mTag, "onAttachedToWindow");
John Spurlock3e077012014-11-29 13:22:21 -0500230 mAttached = true;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400231 mAttachedZen = getSelectedZen(-1);
232 mSessionZen = mAttachedZen;
John Spurlock530052a2014-11-30 16:26:19 -0500233 mTransitionHelper.clear();
Julia Reynoldsb44ef7e2016-06-02 15:29:16 -0400234 mController.addCallback(mZenCallback);
John Spurlock530052a2014-11-30 16:26:19 -0500235 setSessionExitCondition(copy(mExitCondition));
John Spurlock50806fc2014-07-15 10:22:02 -0400236 updateWidgets();
John Spurlock3e077012014-11-29 13:22:21 -0500237 setRequestingConditions(!mHidden);
John Spurlock856edeb2014-06-01 20:36:47 -0400238 }
239
240 @Override
241 protected void onDetachedFromWindow() {
242 super.onDetachedFromWindow();
243 if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
John Spurlock8f8ecd62014-08-27 17:46:03 -0400244 checkForAttachedZenChange();
John Spurlock3e077012014-11-29 13:22:21 -0500245 mAttached = false;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400246 mAttachedZen = -1;
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400247 mSessionZen = -1;
Julia Reynoldsb44ef7e2016-06-02 15:29:16 -0400248 mController.removeCallback(mZenCallback);
John Spurlock530052a2014-11-30 16:26:19 -0500249 setSessionExitCondition(null);
John Spurlock3e077012014-11-29 13:22:21 -0500250 setRequestingConditions(false);
John Spurlock530052a2014-11-30 16:26:19 -0500251 mTransitionHelper.clear();
252 }
253
254 private void setSessionExitCondition(Condition condition) {
255 if (Objects.equals(condition, mSessionExitCondition)) return;
256 if (DEBUG) Log.d(mTag, "mSessionExitCondition=" + getConditionId(condition));
257 mSessionExitCondition = condition;
John Spurlock856edeb2014-06-01 20:36:47 -0400258 }
259
John Spurlockeb2727b2014-07-19 23:11:36 -0400260 public void setHidden(boolean hidden) {
261 if (mHidden == hidden) return;
John Spurlock3e077012014-11-29 13:22:21 -0500262 if (DEBUG) Log.d(mTag, "hidden=" + hidden);
John Spurlockeb2727b2014-07-19 23:11:36 -0400263 mHidden = hidden;
John Spurlock3e077012014-11-29 13:22:21 -0500264 setRequestingConditions(mAttached && !mHidden);
John Spurlockeb2727b2014-07-19 23:11:36 -0400265 updateWidgets();
266 }
267
John Spurlock8f8ecd62014-08-27 17:46:03 -0400268 private void checkForAttachedZenChange() {
269 final int selectedZen = getSelectedZen(-1);
270 if (DEBUG) Log.d(mTag, "selectedZen=" + selectedZen);
271 if (selectedZen != mAttachedZen) {
272 if (DEBUG) Log.d(mTag, "attachedZen: " + mAttachedZen + " -> " + selectedZen);
273 if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
274 mPrefs.trackNoneSelected();
275 }
276 }
277 }
278
John Spurlockae641c92014-06-30 18:11:40 -0400279 private void setExpanded(boolean expanded) {
280 if (expanded == mExpanded) return;
John Spurlockf88d8082015-03-25 18:09:51 -0400281 if (DEBUG) Log.d(mTag, "setExpanded " + expanded);
John Spurlockae641c92014-06-30 18:11:40 -0400282 mExpanded = expanded;
John Spurlockb2278d62015-04-07 12:47:12 -0400283 if (mExpanded && isShown()) {
John Spurlock3e077012014-11-29 13:22:21 -0500284 ensureSelection();
285 }
John Spurlockae641c92014-06-30 18:11:40 -0400286 updateWidgets();
John Spurlockae641c92014-06-30 18:11:40 -0400287 fireExpanded();
John Spurlock86005342014-05-23 11:58:00 -0400288 }
289
290 /** Start or stop requesting relevant zen mode exit conditions */
John Spurlock530052a2014-11-30 16:26:19 -0500291 private void setRequestingConditions(final boolean requesting) {
John Spurlock86005342014-05-23 11:58:00 -0400292 if (mRequestingConditions == requesting) return;
John Spurlock856edeb2014-06-01 20:36:47 -0400293 if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);
John Spurlock86005342014-05-23 11:58:00 -0400294 mRequestingConditions = requesting;
John Spurlock856edeb2014-06-01 20:36:47 -0400295 if (mRequestingConditions) {
John Spurlockb2278d62015-04-07 12:47:12 -0400296 mTimeCondition = parseExistingTimeCondition(mContext, mExitCondition);
John Spurlock4db0d982014-08-13 09:19:03 -0400297 if (mTimeCondition != null) {
John Spurlock856edeb2014-06-01 20:36:47 -0400298 mBucketIndex = -1;
299 } else {
300 mBucketIndex = DEFAULT_BUCKET_INDEX;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400301 mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100302 MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400303 }
304 if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400305
John Spurlock4db0d982014-08-13 09:19:03 -0400306 mConditions = null; // reset conditions
307 handleUpdateConditions();
John Spurlock856edeb2014-06-01 20:36:47 -0400308 } else {
John Spurlock530052a2014-11-30 16:26:19 -0500309 hideAllConditions();
John Spurlock856edeb2014-06-01 20:36:47 -0400310 }
John Spurlock86005342014-05-23 11:58:00 -0400311 }
312
Muyuan Li94fa1df2016-03-23 12:09:38 -0700313 protected void addZenConditions(int count) {
314 for (int i = 0; i < count; i++) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400315 final View rb = mInflater.inflate(R.layout.zen_mode_button, this, false);
316 rb.setId(i);
317 mZenRadioGroup.addView(rb);
318 final View rbc = mInflater.inflate(R.layout.zen_mode_condition, this, false);
319 rbc.setId(i + count);
320 mZenRadioGroupContent.addView(rbc);
Muyuan Li94fa1df2016-03-23 12:09:38 -0700321 }
322 }
323
John Spurlockeb2727b2014-07-19 23:11:36 -0400324 public void init(ZenModeController controller) {
John Spurlock86005342014-05-23 11:58:00 -0400325 mController = controller;
John Spurlockad680d42015-01-30 15:48:15 -0500326 mCountdownConditionSupported = mController.isCountdownConditionSupported();
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400327 final int countdownDelta = mCountdownConditionSupported ? COUNTDOWN_CONDITION_COUNT : 0;
John Spurlockad680d42015-01-30 15:48:15 -0500328 final int minConditions = 1 /*forever*/ + countdownDelta;
Muyuan Li94fa1df2016-03-23 12:09:38 -0700329 addZenConditions(minConditions);
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400330 mSessionZen = getSelectedZen(-1);
John Spurlockb2278d62015-04-07 12:47:12 -0400331 handleUpdateManualRule(mController.getManualRule());
John Spurlock4db0d982014-08-13 09:19:03 -0400332 if (DEBUG) Log.d(mTag, "init mExitCondition=" + mExitCondition);
John Spurlock530052a2014-11-30 16:26:19 -0500333 hideAllConditions();
John Spurlockae641c92014-06-30 18:11:40 -0400334 }
335
Jason Monke2f47712014-09-09 09:35:55 -0400336 public void updateLocale() {
John Spurlock4291fb72014-09-16 17:02:23 -0400337 mZenButtons.updateLocale();
Jason Monke2f47712014-09-09 09:35:55 -0400338 }
339
John Spurlock4db0d982014-08-13 09:19:03 -0400340 private void setExitCondition(Condition exitCondition) {
John Spurlock25c34212014-11-12 09:16:49 -0500341 if (Objects.equals(mExitCondition, exitCondition)) return;
John Spurlock4db0d982014-08-13 09:19:03 -0400342 mExitCondition = exitCondition;
John Spurlock530052a2014-11-30 16:26:19 -0500343 if (DEBUG) Log.d(mTag, "mExitCondition=" + getConditionId(mExitCondition));
John Spurlock89f060a2014-07-16 21:03:15 -0400344 updateWidgets();
John Spurlockae641c92014-06-30 18:11:40 -0400345 }
346
John Spurlock4db0d982014-08-13 09:19:03 -0400347 private static Uri getConditionId(Condition condition) {
348 return condition != null ? condition.id : null;
349 }
350
John Spurlockb2278d62015-04-07 12:47:12 -0400351 private Uri getRealConditionId(Condition condition) {
352 return isForever(condition) ? null : getConditionId(condition);
353 }
354
John Spurlock4db0d982014-08-13 09:19:03 -0400355 private static boolean sameConditionId(Condition lhs, Condition rhs) {
356 return lhs == null ? rhs == null : rhs != null && lhs.id.equals(rhs.id);
357 }
358
359 private static Condition copy(Condition condition) {
360 return condition == null ? null : condition.copy();
361 }
362
John Spurlock86005342014-05-23 11:58:00 -0400363 public void setCallback(Callback callback) {
364 mCallback = callback;
365 }
366
John Spurlockb2278d62015-04-07 12:47:12 -0400367 private void handleUpdateManualRule(ZenRule rule) {
368 final int zen = rule != null ? rule.zenMode : Global.ZEN_MODE_OFF;
369 handleUpdateZen(zen);
370 final Condition c = rule != null ? rule.condition : null;
371 handleExitConditionChanged(c);
372 }
373
John Spurlockae641c92014-06-30 18:11:40 -0400374 private void handleUpdateZen(int zen) {
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400375 if (mSessionZen != -1 && mSessionZen != zen) {
John Spurlockd9c75db2015-04-28 11:19:13 -0400376 setExpanded(isShown());
John Spurlockfbb3d6f2014-07-17 11:17:11 -0400377 mSessionZen = zen;
John Spurlockae641c92014-06-30 18:11:40 -0400378 }
Chris Wren4572cbc2015-06-29 11:27:18 -0400379 mZenButtons.setSelectedValue(zen, false /* fromClick */);
John Spurlockae641c92014-06-30 18:11:40 -0400380 updateWidgets();
John Spurlock530052a2014-11-30 16:26:19 -0500381 handleUpdateConditions();
382 if (mExpanded) {
383 final Condition selected = getSelectedCondition();
384 if (!Objects.equals(mExitCondition, selected)) {
385 select(selected);
386 }
387 }
388 }
389
John Spurlockb2278d62015-04-07 12:47:12 -0400390 private void handleExitConditionChanged(Condition exitCondition) {
391 setExitCondition(exitCondition);
392 if (DEBUG) Log.d(mTag, "handleExitConditionChanged " + mExitCondition);
393 final int N = getVisibleConditions();
394 for (int i = 0; i < N; i++) {
395 final ConditionTag tag = getConditionTagAt(i);
396 if (tag != null) {
397 if (sameConditionId(tag.condition, mExitCondition)) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400398 bind(exitCondition, mZenRadioGroupContent.getChildAt(i), i);
John Spurlockb2278d62015-04-07 12:47:12 -0400399 }
400 }
401 }
402 }
403
John Spurlock530052a2014-11-30 16:26:19 -0500404 private Condition getSelectedCondition() {
405 final int N = getVisibleConditions();
406 for (int i = 0; i < N; i++) {
407 final ConditionTag tag = getConditionTagAt(i);
408 if (tag != null && tag.rb.isChecked()) {
409 return tag.condition;
410 }
411 }
412 return null;
John Spurlockae641c92014-06-30 18:11:40 -0400413 }
414
415 private int getSelectedZen(int defValue) {
416 final Object zen = mZenButtons.getSelectedValue();
417 return zen != null ? (Integer) zen : defValue;
418 }
419
420 private void updateWidgets() {
John Spurlock530052a2014-11-30 16:26:19 -0500421 if (mTransitionHelper.isTransitioning()) {
422 mTransitionHelper.pendingUpdateWidgets();
423 return;
424 }
John Spurlockae641c92014-06-30 18:11:40 -0400425 final int zen = getSelectedZen(Global.ZEN_MODE_OFF);
John Spurlockae641c92014-06-30 18:11:40 -0400426 final boolean zenImportant = zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
427 final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
John Spurlockd9c75db2015-04-28 11:19:13 -0400428 final boolean introduction = (zenImportant && !mPrefs.mConfirmedPriorityIntroduction
429 || zenNone && !mPrefs.mConfirmedSilenceIntroduction);
John Spurlockae641c92014-06-30 18:11:40 -0400430
John Spurlockeb2727b2014-07-19 23:11:36 -0400431 mZenButtons.setVisibility(mHidden ? GONE : VISIBLE);
John Spurlockf55b7f22015-04-13 19:21:26 -0400432 mZenIntroduction.setVisibility(introduction ? VISIBLE : GONE);
John Spurlockd9c75db2015-04-28 11:19:13 -0400433 if (introduction) {
434 mZenIntroductionMessage.setText(zenImportant ? R.string.zen_priority_introduction
John Spurlockcbd7a312015-06-21 10:46:28 -0400435 : mVoiceCapable ? R.string.zen_silence_introduction_voice
John Spurlockd9c75db2015-04-28 11:19:13 -0400436 : R.string.zen_silence_introduction);
437 mZenIntroductionCustomize.setVisibility(zenImportant ? VISIBLE : GONE);
438 }
John Spurlock8be53ea2015-05-29 12:04:21 -0400439 final String warning = computeAlarmWarningText(zenNone);
440 mZenAlarmWarning.setVisibility(warning != null ? VISIBLE : GONE);
441 mZenAlarmWarning.setText(warning);
442 }
443
444 private String computeAlarmWarningText(boolean zenNone) {
445 if (!zenNone) {
446 return null;
447 }
448 final long now = System.currentTimeMillis();
449 final long nextAlarm = mController.getNextAlarm();
450 if (nextAlarm < now) {
451 return null;
452 }
453 int warningRes = 0;
454 if (mSessionExitCondition == null || isForever(mSessionExitCondition)) {
455 warningRes = R.string.zen_alarm_warning_indef;
456 } else {
457 final long time = ZenModeConfig.tryParseCountdownConditionId(mSessionExitCondition.id);
458 if (time > now && nextAlarm < time) {
459 warningRes = R.string.zen_alarm_warning;
460 }
461 }
462 if (warningRes == 0) {
463 return null;
464 }
465 final boolean soon = (nextAlarm - now) < 24 * 60 * 60 * 1000;
466 final boolean is24 = DateFormat.is24HourFormat(mContext, ActivityManager.getCurrentUser());
467 final String skeleton = soon ? (is24 ? "Hm" : "hma") : (is24 ? "EEEHm" : "EEEhma");
468 final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
469 final CharSequence formattedTime = DateFormat.format(pattern, nextAlarm);
470 final int templateRes = soon ? R.string.alarm_template : R.string.alarm_template_far;
471 final String template = getResources().getString(templateRes, formattedTime);
472 return getResources().getString(warningRes, template);
John Spurlock89f060a2014-07-16 21:03:15 -0400473 }
474
John Spurlockb2278d62015-04-07 12:47:12 -0400475 private static Condition parseExistingTimeCondition(Context context, Condition condition) {
John Spurlock4db0d982014-08-13 09:19:03 -0400476 if (condition == null) return null;
477 final long time = ZenModeConfig.tryParseCountdownConditionId(condition.id);
John Spurlock856edeb2014-06-01 20:36:47 -0400478 if (time == 0) return null;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400479 final long now = System.currentTimeMillis();
480 final long span = time - now;
John Spurlock856edeb2014-06-01 20:36:47 -0400481 if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
John Spurlockb2278d62015-04-07 12:47:12 -0400482 return ZenModeConfig.toTimeCondition(context,
Julia Reynolds0842fe82015-10-01 14:34:22 -0400483 time, Math.round(span / (float) MINUTES_MS), ActivityManager.getCurrentUser(),
John Spurlockbbde2672015-05-13 15:42:04 -0400484 false /*shortVersion*/);
John Spurlock86005342014-05-23 11:58:00 -0400485 }
486
John Spurlock4db0d982014-08-13 09:19:03 -0400487 private void handleUpdateConditions() {
John Spurlock530052a2014-11-30 16:26:19 -0500488 if (mTransitionHelper.isTransitioning()) {
John Spurlock530052a2014-11-30 16:26:19 -0500489 return;
490 }
John Spurlock4db0d982014-08-13 09:19:03 -0400491 final int conditionCount = mConditions == null ? 0 : mConditions.length;
492 if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);
John Spurlock4db0d982014-08-13 09:19:03 -0400493 // forever
Julia Reynolds656f9862016-06-01 11:37:29 -0400494 bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
Julia Reynolds0842fe82015-10-01 14:34:22 -0400495 FOREVER_CONDITION_INDEX);
John Spurlock4db0d982014-08-13 09:19:03 -0400496 // countdown
John Spurlock0b688502014-12-22 15:13:30 -0500497 if (mCountdownConditionSupported && mTimeCondition != null) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400498 bind(mTimeCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
Julia Reynolds0842fe82015-10-01 14:34:22 -0400499 COUNTDOWN_CONDITION_INDEX);
John Spurlock86005342014-05-23 11:58:00 -0400500 }
Julia Reynolds0842fe82015-10-01 14:34:22 -0400501 // countdown until alarm
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400502 if (mCountdownConditionSupported) {
503 Condition nextAlarmCondition = getTimeUntilNextAlarmCondition();
504 if (nextAlarmCondition != null) {
Julia Reynoldsc3960f62016-06-02 14:04:31 -0400505 mZenRadioGroup.getChildAt(
506 COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.VISIBLE);
507 mZenRadioGroupContent.getChildAt(
508 COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.VISIBLE);
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400509 bind(nextAlarmCondition,
Julia Reynolds656f9862016-06-01 11:37:29 -0400510 mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX),
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400511 COUNTDOWN_ALARM_CONDITION_INDEX);
Julia Reynoldsc3960f62016-06-02 14:04:31 -0400512 } else {
513 mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.GONE);
514 mZenRadioGroupContent.getChildAt(
515 COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.GONE);
Julia Reynolds8e2d2bb2015-10-01 14:34:22 -0400516 }
John Spurlock4db0d982014-08-13 09:19:03 -0400517 }
John Spurlock3e077012014-11-29 13:22:21 -0500518 // ensure something is selected
John Spurlockb2278d62015-04-07 12:47:12 -0400519 if (mExpanded && isShown()) {
John Spurlock3e077012014-11-29 13:22:21 -0500520 ensureSelection();
521 }
Jason Monke138f552016-01-18 09:21:45 -0500522 mZenConditions.setVisibility(mSessionZen != Global.ZEN_MODE_OFF ? View.VISIBLE : View.GONE);
John Spurlock4db0d982014-08-13 09:19:03 -0400523 }
524
John Spurlock0b688502014-12-22 15:13:30 -0500525 private Condition forever() {
John Spurlockb2278d62015-04-07 12:47:12 -0400526 return new Condition(mForeverId, foreverSummary(mContext), "", "", 0 /*icon*/,
527 Condition.STATE_TRUE, 0 /*flags*/);
John Spurlock0b688502014-12-22 15:13:30 -0500528 }
529
John Spurlockb2278d62015-04-07 12:47:12 -0400530 private static String foreverSummary(Context context) {
531 return context.getString(com.android.internal.R.string.zen_mode_forever);
John Spurlock0b688502014-12-22 15:13:30 -0500532 }
533
Julia Reynolds0842fe82015-10-01 14:34:22 -0400534 // Returns a time condition if the next alarm is within the next week.
535 private Condition getTimeUntilNextAlarmCondition() {
536 GregorianCalendar weekRange = new GregorianCalendar();
537 final long now = weekRange.getTimeInMillis();
538 setToMidnight(weekRange);
Dan Sandler12d33932015-12-29 15:45:39 -0500539 weekRange.add(Calendar.DATE, 6);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400540 final long nextAlarmMs = mController.getNextAlarm();
541 if (nextAlarmMs > 0) {
542 GregorianCalendar nextAlarm = new GregorianCalendar();
543 nextAlarm.setTimeInMillis(nextAlarmMs);
544 setToMidnight(nextAlarm);
545
546 if (weekRange.compareTo(nextAlarm) >= 0) {
Julia Reynolds5edde5f2016-11-11 14:30:51 -0500547 return ZenModeConfig.toTimeCondition(mContext, nextAlarmMs,
548 Math.round((nextAlarmMs - now) / (float) MINUTES_MS),
549 ActivityManager.getCurrentUser(), true);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400550 }
551 }
552 return null;
553 }
554
555 private void setToMidnight(Calendar calendar) {
556 calendar.set(Calendar.HOUR_OF_DAY, 0);
557 calendar.set(Calendar.MINUTE, 0);
558 calendar.set(Calendar.SECOND, 0);
559 calendar.set(Calendar.MILLISECOND, 0);
560 }
561
John Spurlock856edeb2014-06-01 20:36:47 -0400562 private ConditionTag getConditionTagAt(int index) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400563 return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
John Spurlock856edeb2014-06-01 20:36:47 -0400564 }
565
John Spurlock530052a2014-11-30 16:26:19 -0500566 private int getVisibleConditions() {
567 int rt = 0;
Julia Reynolds656f9862016-06-01 11:37:29 -0400568 final int N = mZenRadioGroupContent.getChildCount();
John Spurlock530052a2014-11-30 16:26:19 -0500569 for (int i = 0; i < N; i++) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400570 rt += mZenRadioGroupContent.getChildAt(i).getVisibility() == VISIBLE ? 1 : 0;
John Spurlock530052a2014-11-30 16:26:19 -0500571 }
572 return rt;
573 }
574
575 private void hideAllConditions() {
Julia Reynolds656f9862016-06-01 11:37:29 -0400576 final int N = mZenRadioGroupContent.getChildCount();
John Spurlock530052a2014-11-30 16:26:19 -0500577 for (int i = 0; i < N; i++) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400578 mZenRadioGroupContent.getChildAt(i).setVisibility(GONE);
John Spurlock530052a2014-11-30 16:26:19 -0500579 }
580 }
581
John Spurlock3e077012014-11-29 13:22:21 -0500582 private void ensureSelection() {
John Spurlock856edeb2014-06-01 20:36:47 -0400583 // are we left without anything selected? if so, set a default
John Spurlock530052a2014-11-30 16:26:19 -0500584 final int visibleConditions = getVisibleConditions();
585 if (visibleConditions == 0) return;
586 for (int i = 0; i < visibleConditions; i++) {
587 final ConditionTag tag = getConditionTagAt(i);
588 if (tag != null && tag.rb.isChecked()) {
589 if (DEBUG) Log.d(mTag, "Not selecting a default, checked=" + tag.condition);
John Spurlock856edeb2014-06-01 20:36:47 -0400590 return;
591 }
592 }
John Spurlock530052a2014-11-30 16:26:19 -0500593 final ConditionTag foreverTag = getConditionTagAt(FOREVER_CONDITION_INDEX);
594 if (foreverTag == null) return;
John Spurlock856edeb2014-06-01 20:36:47 -0400595 if (DEBUG) Log.d(mTag, "Selecting a default");
John Spurlock8f8ecd62014-08-27 17:46:03 -0400596 final int favoriteIndex = mPrefs.getMinuteIndex();
John Spurlock530052a2014-11-30 16:26:19 -0500597 if (favoriteIndex == -1 || !mCountdownConditionSupported) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400598 foreverTag.rb.setChecked(true);
John Spurlock856edeb2014-06-01 20:36:47 -0400599 } else {
Selim Cinek9c4a7072014-11-21 17:44:34 +0100600 mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
601 MINUTE_BUCKETS[favoriteIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400602 mBucketIndex = favoriteIndex;
Julia Reynolds656f9862016-06-01 11:37:29 -0400603 bind(mTimeCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
Julia Reynolds0842fe82015-10-01 14:34:22 -0400604 COUNTDOWN_CONDITION_INDEX);
Julia Reynolds656f9862016-06-01 11:37:29 -0400605 getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
John Spurlock856edeb2014-06-01 20:36:47 -0400606 }
607 }
608
John Spurlockb2278d62015-04-07 12:47:12 -0400609 private static boolean isCountdown(Condition c) {
John Spurlock530052a2014-11-30 16:26:19 -0500610 return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
611 }
612
John Spurlock0b688502014-12-22 15:13:30 -0500613 private boolean isForever(Condition c) {
614 return c != null && mForeverId.equals(c.id);
615 }
616
Julia Reynolds0842fe82015-10-01 14:34:22 -0400617 private void bind(final Condition condition, final View row, final int rowId) {
John Spurlock0b688502014-12-22 15:13:30 -0500618 if (condition == null) throw new IllegalArgumentException("condition must not be null");
619 final boolean enabled = condition.state == Condition.STATE_TRUE;
John Spurlock856edeb2014-06-01 20:36:47 -0400620 final ConditionTag tag =
621 row.getTag() != null ? (ConditionTag) row.getTag() : new ConditionTag();
622 row.setTag(tag);
John Spurlock530052a2014-11-30 16:26:19 -0500623 final boolean first = tag.rb == null;
John Spurlock856edeb2014-06-01 20:36:47 -0400624 if (tag.rb == null) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400625 tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowId);
John Spurlock856edeb2014-06-01 20:36:47 -0400626 }
John Spurlock4db0d982014-08-13 09:19:03 -0400627 tag.condition = condition;
John Spurlock530052a2014-11-30 16:26:19 -0500628 final Uri conditionId = getConditionId(tag.condition);
Julia Reynolds656f9862016-06-01 11:37:29 -0400629 if (DEBUG) Log.d(mTag, "bind i=" + mZenRadioGroupContent.indexOfChild(row) + " first="
630 + first + " condition=" + conditionId);
John Spurlock856edeb2014-06-01 20:36:47 -0400631 tag.rb.setEnabled(enabled);
632 tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
John Spurlock86005342014-05-23 11:58:00 -0400633 @Override
634 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
John Spurlockae641c92014-06-30 18:11:40 -0400635 if (mExpanded && isChecked) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400636 tag.rb.setChecked(true);
John Spurlock530052a2014-11-30 16:26:19 -0500637 if (DEBUG) Log.d(mTag, "onCheckedChanged " + conditionId);
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500638 MetricsLogger.action(mContext, MetricsEvent.QS_DND_CONDITION_SELECT);
John Spurlock4db0d982014-08-13 09:19:03 -0400639 select(tag.condition);
John Spurlocka0457c22014-09-26 13:22:08 -0400640 announceConditionSelection(tag);
John Spurlock86005342014-05-23 11:58:00 -0400641 }
642 }
643 });
John Spurlocka0457c22014-09-26 13:22:08 -0400644
John Spurlockc90e6fe2014-10-28 11:21:42 -0400645 if (tag.lines == null) {
646 tag.lines = row.findViewById(android.R.id.content);
John Spurlock86005342014-05-23 11:58:00 -0400647 }
John Spurlockc90e6fe2014-10-28 11:21:42 -0400648 if (tag.line1 == null) {
649 tag.line1 = (TextView) row.findViewById(android.R.id.text1);
John Spurlockd8963232015-06-08 16:26:12 -0400650 mSpTexts.add(tag.line1);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400651 }
652 if (tag.line2 == null) {
653 tag.line2 = (TextView) row.findViewById(android.R.id.text2);
John Spurlockd8963232015-06-08 16:26:12 -0400654 mSpTexts.add(tag.line2);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400655 }
John Spurlock0b688502014-12-22 15:13:30 -0500656 final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
657 : condition.summary;
658 final String line2 = condition.line2;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400659 tag.line1.setText(line1);
660 if (TextUtils.isEmpty(line2)) {
661 tag.line2.setVisibility(GONE);
662 } else {
663 tag.line2.setVisibility(VISIBLE);
664 tag.line2.setText(line2);
665 }
666 tag.lines.setEnabled(enabled);
667 tag.lines.setAlpha(enabled ? 1 : .4f);
John Spurlocka0457c22014-09-26 13:22:08 -0400668
John Spurlock86005342014-05-23 11:58:00 -0400669 final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
670 button1.setOnClickListener(new OnClickListener() {
671 @Override
672 public void onClick(View v) {
Julia Reynolds0842fe82015-10-01 14:34:22 -0400673 onClickTimeButton(row, tag, false /*down*/, rowId);
John Spurlock86005342014-05-23 11:58:00 -0400674 }
675 });
676
677 final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
678 button2.setOnClickListener(new OnClickListener() {
679 @Override
680 public void onClick(View v) {
Julia Reynolds0842fe82015-10-01 14:34:22 -0400681 onClickTimeButton(row, tag, true /*up*/, rowId);
John Spurlock86005342014-05-23 11:58:00 -0400682 }
683 });
John Spurlockc90e6fe2014-10-28 11:21:42 -0400684 tag.lines.setOnClickListener(new OnClickListener() {
John Spurlock86005342014-05-23 11:58:00 -0400685 @Override
686 public void onClick(View v) {
Julia Reynolds656f9862016-06-01 11:37:29 -0400687 tag.rb.setChecked(true);
John Spurlock86005342014-05-23 11:58:00 -0400688 }
689 });
John Spurlock856edeb2014-06-01 20:36:47 -0400690
John Spurlock530052a2014-11-30 16:26:19 -0500691 final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
Julia Reynolds0842fe82015-10-01 14:34:22 -0400692 if (rowId != COUNTDOWN_ALARM_CONDITION_INDEX && time > 0) {
John Spurlock530052a2014-11-30 16:26:19 -0500693 button1.setVisibility(VISIBLE);
694 button2.setVisibility(VISIBLE);
John Spurlock856edeb2014-06-01 20:36:47 -0400695 if (mBucketIndex > -1) {
696 button1.setEnabled(mBucketIndex > 0);
697 button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
698 } else {
699 final long span = time - System.currentTimeMillis();
700 button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400701 final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100702 MAX_BUCKET_MINUTES, ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400703 button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
704 }
705
706 button1.setAlpha(button1.isEnabled() ? 1f : .5f);
707 button2.setAlpha(button2.isEnabled() ? 1f : .5f);
John Spurlock86005342014-05-23 11:58:00 -0400708 } else {
John Spurlock530052a2014-11-30 16:26:19 -0500709 button1.setVisibility(GONE);
710 button2.setVisibility(GONE);
John Spurlock86005342014-05-23 11:58:00 -0400711 }
John Spurlocka0457c22014-09-26 13:22:08 -0400712 // wire up interaction callbacks for newly-added condition rows
John Spurlock530052a2014-11-30 16:26:19 -0500713 if (first) {
John Spurlocka0457c22014-09-26 13:22:08 -0400714 Interaction.register(tag.rb, mInteractionCallback);
John Spurlockc90e6fe2014-10-28 11:21:42 -0400715 Interaction.register(tag.lines, mInteractionCallback);
John Spurlocka0457c22014-09-26 13:22:08 -0400716 Interaction.register(button1, mInteractionCallback);
717 Interaction.register(button2, mInteractionCallback);
718 }
John Spurlock530052a2014-11-30 16:26:19 -0500719 row.setVisibility(VISIBLE);
John Spurlocka0457c22014-09-26 13:22:08 -0400720 }
721
722 private void announceConditionSelection(ConditionTag tag) {
723 final int zen = getSelectedZen(Global.ZEN_MODE_OFF);
724 String modeText;
725 switch(zen) {
726 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
John Spurlockd9c75db2015-04-28 11:19:13 -0400727 modeText = mContext.getString(R.string.interruption_level_priority);
John Spurlocka0457c22014-09-26 13:22:08 -0400728 break;
729 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlockd9c75db2015-04-28 11:19:13 -0400730 modeText = mContext.getString(R.string.interruption_level_none);
John Spurlocka0457c22014-09-26 13:22:08 -0400731 break;
John Spurlock4f1163c2015-04-02 17:41:21 -0400732 case Global.ZEN_MODE_ALARMS:
John Spurlockd9c75db2015-04-28 11:19:13 -0400733 modeText = mContext.getString(R.string.interruption_level_alarms);
John Spurlock4f1163c2015-04-02 17:41:21 -0400734 break;
735 default:
John Spurlocka0457c22014-09-26 13:22:08 -0400736 return;
737 }
738 announceForAccessibility(mContext.getString(R.string.zen_mode_and_condition, modeText,
John Spurlockc90e6fe2014-10-28 11:21:42 -0400739 tag.line1.getText()));
John Spurlock856edeb2014-06-01 20:36:47 -0400740 }
741
Julia Reynolds0842fe82015-10-01 14:34:22 -0400742 private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500743 MetricsLogger.action(mContext, MetricsEvent.QS_DND_TIME, up);
John Spurlock856edeb2014-06-01 20:36:47 -0400744 Condition newCondition = null;
745 final int N = MINUTE_BUCKETS.length;
746 if (mBucketIndex == -1) {
747 // not on a known index, search for the next or prev bucket by time
John Spurlock4db0d982014-08-13 09:19:03 -0400748 final Uri conditionId = getConditionId(tag.condition);
749 final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
John Spurlock856edeb2014-06-01 20:36:47 -0400750 final long now = System.currentTimeMillis();
751 for (int i = 0; i < N; i++) {
752 int j = up ? i : N - 1 - i;
753 final int bucketMinutes = MINUTE_BUCKETS[j];
754 final long bucketTime = now + bucketMinutes * MINUTES_MS;
755 if (up && bucketTime > time || !up && bucketTime < time) {
756 mBucketIndex = j;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400757 newCondition = ZenModeConfig.toTimeCondition(mContext,
Julia Reynolds0842fe82015-10-01 14:34:22 -0400758 bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
John Spurlockbbde2672015-05-13 15:42:04 -0400759 false /*shortVersion*/);
John Spurlock856edeb2014-06-01 20:36:47 -0400760 break;
761 }
762 }
763 if (newCondition == null) {
764 mBucketIndex = DEFAULT_BUCKET_INDEX;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400765 newCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100766 MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400767 }
768 } else {
769 // on a known index, simply increment or decrement
770 mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
John Spurlockc90e6fe2014-10-28 11:21:42 -0400771 newCondition = ZenModeConfig.toTimeCondition(mContext,
Selim Cinek9c4a7072014-11-21 17:44:34 +0100772 MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
John Spurlock856edeb2014-06-01 20:36:47 -0400773 }
John Spurlock4db0d982014-08-13 09:19:03 -0400774 mTimeCondition = newCondition;
Julia Reynolds0842fe82015-10-01 14:34:22 -0400775 bind(mTimeCondition, row, rowId);
Julia Reynolds656f9862016-06-01 11:37:29 -0400776 tag.rb.setChecked(true);
John Spurlock4db0d982014-08-13 09:19:03 -0400777 select(mTimeCondition);
John Spurlocka0457c22014-09-26 13:22:08 -0400778 announceConditionSelection(tag);
John Spurlock856edeb2014-06-01 20:36:47 -0400779 }
780
John Spurlock530052a2014-11-30 16:26:19 -0500781 private void select(final Condition condition) {
John Spurlock4db0d982014-08-13 09:19:03 -0400782 if (DEBUG) Log.d(mTag, "select " + condition);
John Spurlockb2278d62015-04-07 12:47:12 -0400783 if (mSessionZen == -1 || mSessionZen == Global.ZEN_MODE_OFF) {
784 if (DEBUG) Log.d(mTag, "Ignoring condition selection outside of manual zen");
785 return;
786 }
787 final Uri realConditionId = getRealConditionId(condition);
John Spurlock856edeb2014-06-01 20:36:47 -0400788 if (mController != null) {
John Spurlock530052a2014-11-30 16:26:19 -0500789 AsyncTask.execute(new Runnable() {
790 @Override
791 public void run() {
John Spurlockb2278d62015-04-07 12:47:12 -0400792 mController.setZen(mSessionZen, realConditionId, TAG + ".selectCondition");
John Spurlock530052a2014-11-30 16:26:19 -0500793 }
794 });
John Spurlock856edeb2014-06-01 20:36:47 -0400795 }
John Spurlock4db0d982014-08-13 09:19:03 -0400796 setExitCondition(condition);
John Spurlockb2278d62015-04-07 12:47:12 -0400797 if (realConditionId == null) {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400798 mPrefs.setMinuteIndex(-1);
John Spurlock530052a2014-11-30 16:26:19 -0500799 } else if (isCountdown(condition) && mBucketIndex != -1) {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400800 mPrefs.setMinuteIndex(mBucketIndex);
John Spurlock86005342014-05-23 11:58:00 -0400801 }
John Spurlock530052a2014-11-30 16:26:19 -0500802 setSessionExitCondition(copy(condition));
John Spurlock86005342014-05-23 11:58:00 -0400803 }
804
John Spurlock86005342014-05-23 11:58:00 -0400805 private void fireInteraction() {
806 if (mCallback != null) {
807 mCallback.onInteraction();
808 }
809 }
810
John Spurlockae641c92014-06-30 18:11:40 -0400811 private void fireExpanded() {
812 if (mCallback != null) {
813 mCallback.onExpanded(mExpanded);
814 }
815 }
816
John Spurlock86005342014-05-23 11:58:00 -0400817 private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
818 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400819 public void onManualRuleChanged(ZenRule rule) {
820 mHandler.obtainMessage(H.MANUAL_RULE_CHANGED, rule).sendToTarget();
John Spurlock856edeb2014-06-01 20:36:47 -0400821 }
John Spurlock86005342014-05-23 11:58:00 -0400822 };
823
824 private final class H extends Handler {
John Spurlockb2278d62015-04-07 12:47:12 -0400825 private static final int MANUAL_RULE_CHANGED = 2;
John Spurlockf55b7f22015-04-13 19:21:26 -0400826 private static final int UPDATE_WIDGETS = 3;
John Spurlock86005342014-05-23 11:58:00 -0400827
828 private H() {
829 super(Looper.getMainLooper());
830 }
831
832 @Override
833 public void handleMessage(Message msg) {
John Spurlockf55b7f22015-04-13 19:21:26 -0400834 switch (msg.what) {
John Spurlockf55b7f22015-04-13 19:21:26 -0400835 case MANUAL_RULE_CHANGED: handleUpdateManualRule((ZenRule) msg.obj); break;
836 case UPDATE_WIDGETS: updateWidgets(); break;
John Spurlock86005342014-05-23 11:58:00 -0400837 }
838 }
839 }
840
841 public interface Callback {
John Spurlockf55b7f22015-04-13 19:21:26 -0400842 void onPrioritySettings();
John Spurlock86005342014-05-23 11:58:00 -0400843 void onInteraction();
John Spurlockae641c92014-06-30 18:11:40 -0400844 void onExpanded(boolean expanded);
John Spurlock86005342014-05-23 11:58:00 -0400845 }
John Spurlock856edeb2014-06-01 20:36:47 -0400846
847 // used as the view tag on condition rows
848 private static class ConditionTag {
849 RadioButton rb;
John Spurlockc90e6fe2014-10-28 11:21:42 -0400850 View lines;
851 TextView line1;
852 TextView line2;
John Spurlock4db0d982014-08-13 09:19:03 -0400853 Condition condition;
John Spurlock856edeb2014-06-01 20:36:47 -0400854 }
855
John Spurlockf55b7f22015-04-13 19:21:26 -0400856 private final class ZenPrefs implements OnSharedPreferenceChangeListener {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400857 private final int mNoneDangerousThreshold;
John Spurlock856edeb2014-06-01 20:36:47 -0400858
859 private int mMinuteIndex;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400860 private int mNoneSelected;
John Spurlockd9c75db2015-04-28 11:19:13 -0400861 private boolean mConfirmedPriorityIntroduction;
862 private boolean mConfirmedSilenceIntroduction;
John Spurlock856edeb2014-06-01 20:36:47 -0400863
John Spurlockf55b7f22015-04-13 19:21:26 -0400864 private ZenPrefs() {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400865 mNoneDangerousThreshold = mContext.getResources()
866 .getInteger(R.integer.zen_mode_alarm_warning_threshold);
John Spurlockf55b7f22015-04-13 19:21:26 -0400867 Prefs.registerListener(mContext, this);
John Spurlock856edeb2014-06-01 20:36:47 -0400868 updateMinuteIndex();
John Spurlock8f8ecd62014-08-27 17:46:03 -0400869 updateNoneSelected();
John Spurlockd9c75db2015-04-28 11:19:13 -0400870 updateConfirmedPriorityIntroduction();
871 updateConfirmedSilenceIntroduction();
John Spurlock8f8ecd62014-08-27 17:46:03 -0400872 }
873
874 public void trackNoneSelected() {
875 mNoneSelected = clampNoneSelected(mNoneSelected + 1);
876 if (DEBUG) Log.d(mTag, "Setting none selected: " + mNoneSelected + " threshold="
877 + mNoneDangerousThreshold);
John Spurlockf55b7f22015-04-13 19:21:26 -0400878 Prefs.putInt(mContext, Prefs.Key.DND_NONE_SELECTED, mNoneSelected);
John Spurlock856edeb2014-06-01 20:36:47 -0400879 }
880
881 public int getMinuteIndex() {
882 return mMinuteIndex;
883 }
884
885 public void setMinuteIndex(int minuteIndex) {
John Spurlock8f8ecd62014-08-27 17:46:03 -0400886 minuteIndex = clampIndex(minuteIndex);
John Spurlock856edeb2014-06-01 20:36:47 -0400887 if (minuteIndex == mMinuteIndex) return;
John Spurlock8f8ecd62014-08-27 17:46:03 -0400888 mMinuteIndex = clampIndex(minuteIndex);
John Spurlock856edeb2014-06-01 20:36:47 -0400889 if (DEBUG) Log.d(mTag, "Setting favorite minute index: " + mMinuteIndex);
John Spurlockf55b7f22015-04-13 19:21:26 -0400890 Prefs.putInt(mContext, Prefs.Key.DND_FAVORITE_BUCKET_INDEX, mMinuteIndex);
John Spurlock856edeb2014-06-01 20:36:47 -0400891 }
892
893 @Override
894 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
895 updateMinuteIndex();
John Spurlock8f8ecd62014-08-27 17:46:03 -0400896 updateNoneSelected();
John Spurlockd9c75db2015-04-28 11:19:13 -0400897 updateConfirmedPriorityIntroduction();
898 updateConfirmedSilenceIntroduction();
John Spurlock856edeb2014-06-01 20:36:47 -0400899 }
900
901 private void updateMinuteIndex() {
John Spurlockf55b7f22015-04-13 19:21:26 -0400902 mMinuteIndex = clampIndex(Prefs.getInt(mContext,
903 Prefs.Key.DND_FAVORITE_BUCKET_INDEX, DEFAULT_BUCKET_INDEX));
John Spurlock856edeb2014-06-01 20:36:47 -0400904 if (DEBUG) Log.d(mTag, "Favorite minute index: " + mMinuteIndex);
905 }
906
John Spurlock8f8ecd62014-08-27 17:46:03 -0400907 private int clampIndex(int index) {
908 return MathUtils.constrain(index, -1, MINUTE_BUCKETS.length - 1);
909 }
910
911 private void updateNoneSelected() {
John Spurlockf55b7f22015-04-13 19:21:26 -0400912 mNoneSelected = clampNoneSelected(Prefs.getInt(mContext,
913 Prefs.Key.DND_NONE_SELECTED, 0));
John Spurlock8f8ecd62014-08-27 17:46:03 -0400914 if (DEBUG) Log.d(mTag, "None selected: " + mNoneSelected);
915 }
916
917 private int clampNoneSelected(int noneSelected) {
918 return MathUtils.constrain(noneSelected, 0, Integer.MAX_VALUE);
John Spurlock856edeb2014-06-01 20:36:47 -0400919 }
John Spurlockf55b7f22015-04-13 19:21:26 -0400920
John Spurlockd9c75db2015-04-28 11:19:13 -0400921 private void updateConfirmedPriorityIntroduction() {
John Spurlockf55b7f22015-04-13 19:21:26 -0400922 final boolean confirmed = Prefs.getBoolean(mContext,
923 Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, false);
John Spurlockd9c75db2015-04-28 11:19:13 -0400924 if (confirmed == mConfirmedPriorityIntroduction) return;
925 mConfirmedPriorityIntroduction = confirmed;
926 if (DEBUG) Log.d(mTag, "Confirmed priority introduction: "
927 + mConfirmedPriorityIntroduction);
928 }
929
930 private void updateConfirmedSilenceIntroduction() {
931 final boolean confirmed = Prefs.getBoolean(mContext,
932 Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION, false);
933 if (confirmed == mConfirmedSilenceIntroduction) return;
934 mConfirmedSilenceIntroduction = confirmed;
935 if (DEBUG) Log.d(mTag, "Confirmed silence introduction: "
936 + mConfirmedSilenceIntroduction);
John Spurlockf55b7f22015-04-13 19:21:26 -0400937 }
John Spurlock856edeb2014-06-01 20:36:47 -0400938 }
John Spurlockae641c92014-06-30 18:11:40 -0400939
Muyuan Li8303bd22016-03-23 20:08:26 -0700940 protected final SegmentedButtons.Callback mZenButtonsCallback = new SegmentedButtons.Callback() {
John Spurlockae641c92014-06-30 18:11:40 -0400941 @Override
Chris Wren4572cbc2015-06-29 11:27:18 -0400942 public void onSelected(final Object value, boolean fromClick) {
John Spurlockb2278d62015-04-07 12:47:12 -0400943 if (value != null && mZenButtons.isShown() && isAttachedToWindow()) {
John Spurlockd9c75db2015-04-28 11:19:13 -0400944 final int zen = (Integer) value;
Chris Wren4572cbc2015-06-29 11:27:18 -0400945 if (fromClick) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500946 MetricsLogger.action(mContext, MetricsEvent.QS_DND_ZEN_SELECT, zen);
Chris Wren4572cbc2015-06-29 11:27:18 -0400947 }
John Spurlockd9c75db2015-04-28 11:19:13 -0400948 if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + zen);
John Spurlockb2278d62015-04-07 12:47:12 -0400949 final Uri realConditionId = getRealConditionId(mSessionExitCondition);
John Spurlock530052a2014-11-30 16:26:19 -0500950 AsyncTask.execute(new Runnable() {
951 @Override
952 public void run() {
John Spurlockd9c75db2015-04-28 11:19:13 -0400953 mController.setZen(zen, realConditionId, TAG + ".selectZen");
954 if (zen != Global.ZEN_MODE_OFF) {
955 Prefs.putInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, zen);
956 }
John Spurlock530052a2014-11-30 16:26:19 -0500957 }
958 });
John Spurlockae641c92014-06-30 18:11:40 -0400959 }
960 }
John Spurlocka0457c22014-09-26 13:22:08 -0400961
962 @Override
963 public void onInteraction() {
964 fireInteraction();
965 }
966 };
967
968 private final Interaction.Callback mInteractionCallback = new Interaction.Callback() {
969 @Override
970 public void onInteraction() {
971 fireInteraction();
972 }
John Spurlockae641c92014-06-30 18:11:40 -0400973 };
John Spurlock530052a2014-11-30 16:26:19 -0500974
975 private final class TransitionHelper implements TransitionListener, Runnable {
976 private final ArraySet<View> mTransitioningViews = new ArraySet<View>();
977
978 private boolean mTransitioning;
John Spurlock530052a2014-11-30 16:26:19 -0500979 private boolean mPendingUpdateWidgets;
980
981 public void clear() {
982 mTransitioningViews.clear();
Julia Reynolds0842fe82015-10-01 14:34:22 -0400983 mPendingUpdateWidgets = false;
John Spurlock530052a2014-11-30 16:26:19 -0500984 }
985
986 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
987 pw.println(" TransitionHelper state:");
John Spurlock530052a2014-11-30 16:26:19 -0500988 pw.print(" mPendingUpdateWidgets="); pw.println(mPendingUpdateWidgets);
989 pw.print(" mTransitioning="); pw.println(mTransitioning);
990 pw.print(" mTransitioningViews="); pw.println(mTransitioningViews);
991 }
992
John Spurlock530052a2014-11-30 16:26:19 -0500993 public void pendingUpdateWidgets() {
994 mPendingUpdateWidgets = true;
995 }
996
997 public boolean isTransitioning() {
998 return !mTransitioningViews.isEmpty();
999 }
1000
1001 @Override
1002 public void startTransition(LayoutTransition transition,
1003 ViewGroup container, View view, int transitionType) {
1004 mTransitioningViews.add(view);
1005 updateTransitioning();
1006 }
1007
1008 @Override
1009 public void endTransition(LayoutTransition transition,
1010 ViewGroup container, View view, int transitionType) {
1011 mTransitioningViews.remove(view);
1012 updateTransitioning();
1013 }
1014
1015 @Override
1016 public void run() {
1017 if (DEBUG) Log.d(mTag, "TransitionHelper run"
Julia Reynolds0842fe82015-10-01 14:34:22 -04001018 + " mPendingUpdateWidgets=" + mPendingUpdateWidgets);
John Spurlock530052a2014-11-30 16:26:19 -05001019 if (mPendingUpdateWidgets) {
1020 updateWidgets();
1021 }
Julia Reynolds0842fe82015-10-01 14:34:22 -04001022 mPendingUpdateWidgets = false;
John Spurlock530052a2014-11-30 16:26:19 -05001023 }
1024
1025 private void updateTransitioning() {
1026 final boolean transitioning = isTransitioning();
1027 if (mTransitioning == transitioning) return;
1028 mTransitioning = transitioning;
1029 if (DEBUG) Log.d(mTag, "TransitionHelper mTransitioning=" + mTransitioning);
1030 if (!mTransitioning) {
Julia Reynolds0842fe82015-10-01 14:34:22 -04001031 if (mPendingUpdateWidgets) {
John Spurlock530052a2014-11-30 16:26:19 -05001032 mHandler.post(this);
1033 } else {
Julia Reynolds0842fe82015-10-01 14:34:22 -04001034 mPendingUpdateWidgets = false;
John Spurlock530052a2014-11-30 16:26:19 -05001035 }
1036 }
1037 }
1038 }
John Spurlock86005342014-05-23 11:58:00 -04001039}