blob: 8fcda59011e95db36fbf679b74bb5f771fc10d68 [file] [log] [blame]
John Spurlock3c4076a2015-02-24 12:12:25 -05001/*
2 * Copyright (C) 2015 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.qs.tiles;
18
19import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
23import android.content.SharedPreferences;
John Spurlockcd863ad2015-04-07 14:01:28 -040024import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
Sudheer Shanka1c7cda82015-12-31 14:46:02 +000025import android.os.UserManager;
John Spurlock3c4076a2015-02-24 12:12:25 -050026import android.provider.Settings;
27import android.provider.Settings.Global;
28import android.view.LayoutInflater;
29import android.view.View;
30import android.view.View.OnAttachStateChangeListener;
31import android.view.ViewGroup;
Julia Reynolds20aef8a2016-05-04 16:44:08 -040032import android.widget.Switch;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +000033import android.widget.Toast;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050034
Chris Wren457a21c2015-05-06 17:50:34 -040035import com.android.internal.logging.MetricsLogger;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050036import com.android.internal.logging.MetricsProto.MetricsEvent;
Andrew Flynn82862572015-04-01 14:22:37 -040037import com.android.systemui.Prefs;
John Spurlock3c4076a2015-02-24 12:12:25 -050038import com.android.systemui.R;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +000039import com.android.systemui.SysUIToast;
John Spurlock3c4076a2015-02-24 12:12:25 -050040import com.android.systemui.qs.QSTile;
41import com.android.systemui.statusbar.policy.ZenModeController;
42import com.android.systemui.volume.ZenModePanel;
43
44/** Quick settings tile: Do not disturb **/
45public class DndTile extends QSTile<QSTile.BooleanState> {
John Spurlock036e7cb2015-06-15 13:49:57 -040046
John Spurlockd9c75db2015-04-28 11:19:13 -040047 private static final Intent ZEN_SETTINGS =
48 new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
49
50 private static final Intent ZEN_PRIORITY_SETTINGS =
51 new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
John Spurlock3c4076a2015-02-24 12:12:25 -050052
53 private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
54 private static final String EXTRA_VISIBLE = "visible";
John Spurlock3c4076a2015-02-24 12:12:25 -050055
John Spurlock036e7cb2015-06-15 13:49:57 -040056 private static final QSTile.Icon TOTAL_SILENCE =
57 ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
58
59 private final AnimationIcon mDisable =
Jason Monk1aec93f2016-03-01 09:39:30 -050060 new AnimationIcon(R.drawable.ic_dnd_disable_animation,
61 R.drawable.ic_qs_dnd_off);
John Spurlock036e7cb2015-06-15 13:49:57 -040062 private final AnimationIcon mDisableTotalSilence =
Jason Monk1aec93f2016-03-01 09:39:30 -050063 new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation,
64 R.drawable.ic_qs_dnd_off);
John Spurlock036e7cb2015-06-15 13:49:57 -040065
John Spurlock3c4076a2015-02-24 12:12:25 -050066 private final ZenModeController mController;
67 private final DndDetailAdapter mDetailAdapter;
68
69 private boolean mListening;
John Spurlock3c4076a2015-02-24 12:12:25 -050070 private boolean mShowingDetail;
Yuta Yamada99fd2772016-10-06 17:40:19 +090071 private boolean mReceiverRegistered;
John Spurlock3c4076a2015-02-24 12:12:25 -050072
73 public DndTile(Host host) {
74 super(host);
75 mController = host.getZenModeController();
76 mDetailAdapter = new DndDetailAdapter();
John Spurlock3c4076a2015-02-24 12:12:25 -050077 mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
Yuta Yamada99fd2772016-10-06 17:40:19 +090078 mReceiverRegistered = true;
79 }
80
81 @Override
82 protected void handleDestroy() {
83 super.handleDestroy();
84 if (mReceiverRegistered) {
85 mContext.unregisterReceiver(mReceiver);
86 mReceiverRegistered = false;
87 }
John Spurlock3c4076a2015-02-24 12:12:25 -050088 }
89
90 public static void setVisible(Context context, boolean visible) {
Andrew Flynn82862572015-04-01 14:22:37 -040091 Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
John Spurlock3c4076a2015-02-24 12:12:25 -050092 }
93
94 public static boolean isVisible(Context context) {
Andrew Flynn82862572015-04-01 14:22:37 -040095 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */);
John Spurlock3c4076a2015-02-24 12:12:25 -050096 }
97
John Spurlockf88d8082015-03-25 18:09:51 -040098 public static void setCombinedIcon(Context context, boolean combined) {
Andrew Flynn82862572015-04-01 14:22:37 -040099 Prefs.putBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, combined);
John Spurlockf88d8082015-03-25 18:09:51 -0400100 }
101
102 public static boolean isCombinedIcon(Context context) {
Andrew Flynn82862572015-04-01 14:22:37 -0400103 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON,
104 false /* defaultValue */);
John Spurlockf88d8082015-03-25 18:09:51 -0400105 }
106
John Spurlock3c4076a2015-02-24 12:12:25 -0500107 @Override
108 public DetailAdapter getDetailAdapter() {
109 return mDetailAdapter;
110 }
111
112 @Override
Jason Monk62b63a02016-02-02 15:15:31 -0500113 public BooleanState newTileState() {
John Spurlock3c4076a2015-02-24 12:12:25 -0500114 return new BooleanState();
115 }
116
117 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -0500118 public Intent getLongClickIntent() {
119 return ZEN_SETTINGS;
120 }
121
122 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500123 public void handleClick() {
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000124 if (mController.isVolumeRestricted()) {
125 // Collapse the panels, so the user can see the toast.
126 mHost.collapsePanels();
127 SysUIToast.makeText(mContext, mContext.getString(
128 com.android.internal.R.string.error_message_change_not_allowed),
129 Toast.LENGTH_LONG).show();
130 return;
131 }
Chris Wren9e7283f2015-05-08 17:23:47 -0400132 MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
John Spurlock3c4076a2015-02-24 12:12:25 -0500133 if (mState.value) {
John Spurlockb2278d62015-04-07 12:47:12 -0400134 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500135 } else {
Jason Monk48e093e2016-07-15 10:37:07 -0400136 showDetail(true);
John Spurlockd9c75db2015-04-28 11:19:13 -0400137 int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
138 mController.setZen(zen, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500139 }
140 }
141
142 @Override
Jason Monk39c98e62016-03-16 09:18:35 -0400143 public CharSequence getTileLabel() {
144 return mContext.getString(R.string.quick_settings_dnd_label);
145 }
146
147 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500148 protected void handleUpdateState(BooleanState state, Object arg) {
149 final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
John Spurlockb1688f62015-05-12 15:52:38 -0400150 final boolean newValue = zen != Global.ZEN_MODE_OFF;
151 final boolean valueChanged = state.value != newValue;
152 state.value = newValue;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000153 checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
John Spurlock3c4076a2015-02-24 12:12:25 -0500154 switch (zen) {
155 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
156 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
157 state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);
158 state.contentDescription = mContext.getString(
159 R.string.accessibility_quick_settings_dnd_priority_on);
160 break;
161 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock036e7cb2015-06-15 13:49:57 -0400162 state.icon = TOTAL_SILENCE;
John Spurlock3c4076a2015-02-24 12:12:25 -0500163 state.label = mContext.getString(R.string.quick_settings_dnd_none_label);
164 state.contentDescription = mContext.getString(
165 R.string.accessibility_quick_settings_dnd_none_on);
166 break;
John Spurlock4f1163c2015-04-02 17:41:21 -0400167 case Global.ZEN_MODE_ALARMS:
168 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
169 state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);
170 state.contentDescription = mContext.getString(
171 R.string.accessibility_quick_settings_dnd_alarms_on);
172 break;
John Spurlock3c4076a2015-02-24 12:12:25 -0500173 default:
John Spurlock036e7cb2015-06-15 13:49:57 -0400174 state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;
John Spurlock3c4076a2015-02-24 12:12:25 -0500175 state.label = mContext.getString(R.string.quick_settings_dnd_label);
176 state.contentDescription = mContext.getString(
Julia Reynolds20aef8a2016-05-04 16:44:08 -0400177 R.string.accessibility_quick_settings_dnd);
John Spurlock3c4076a2015-02-24 12:12:25 -0500178 break;
179 }
180 if (mShowingDetail && !state.value) {
181 showDetail(false);
182 }
John Spurlockb1688f62015-05-12 15:52:38 -0400183 if (valueChanged) {
184 fireToggleStateChanged(state.value);
185 }
Julia Reynolds20aef8a2016-05-04 16:44:08 -0400186 state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
187 = Switch.class.getName();
John Spurlock3c4076a2015-02-24 12:12:25 -0500188 }
189
190 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400191 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500192 return MetricsEvent.QS_DND;
Chris Wren457a21c2015-05-06 17:50:34 -0400193 }
194
195 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500196 protected String composeChangeAnnouncement() {
197 if (mState.value) {
198 return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
199 } else {
200 return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_off);
201 }
202 }
203
204 @Override
205 public void setListening(boolean listening) {
206 if (mListening == listening) return;
207 mListening = listening;
208 if (mListening) {
209 mController.addCallback(mZenCallback);
Andrew Flynn82862572015-04-01 14:22:37 -0400210 Prefs.registerListener(mContext, mPrefListener);
John Spurlock3c4076a2015-02-24 12:12:25 -0500211 } else {
212 mController.removeCallback(mZenCallback);
Andrew Flynn82862572015-04-01 14:22:37 -0400213 Prefs.unregisterListener(mContext, mPrefListener);
John Spurlock3c4076a2015-02-24 12:12:25 -0500214 }
215 }
216
Jason Monkc3f42c12016-02-05 12:33:13 -0500217 @Override
218 public boolean isAvailable() {
219 return isVisible(mContext);
220 }
221
John Spurlockcd863ad2015-04-07 14:01:28 -0400222 private final OnSharedPreferenceChangeListener mPrefListener
223 = new OnSharedPreferenceChangeListener() {
224 @Override
Andrew Flynn82862572015-04-01 14:22:37 -0400225 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
226 @Prefs.Key String key) {
227 if (Prefs.Key.DND_TILE_COMBINED_ICON.equals(key) ||
228 Prefs.Key.DND_TILE_VISIBLE.equals(key)) {
John Spurlockcd863ad2015-04-07 14:01:28 -0400229 refreshState();
230 }
231 }
232 };
233
John Spurlock3c4076a2015-02-24 12:12:25 -0500234 private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
235 public void onZenChanged(int zen) {
236 refreshState(zen);
237 }
238 };
239
John Spurlock3c4076a2015-02-24 12:12:25 -0500240 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
241 @Override
242 public void onReceive(Context context, Intent intent) {
John Spurlockcd863ad2015-04-07 14:01:28 -0400243 final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
244 setVisible(mContext, visible);
John Spurlock3c4076a2015-02-24 12:12:25 -0500245 refreshState();
246 }
247 };
248
249 private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
250
251 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500252 public CharSequence getTitle() {
253 return mContext.getString(R.string.quick_settings_dnd_label);
John Spurlock3c4076a2015-02-24 12:12:25 -0500254 }
255
256 @Override
257 public Boolean getToggleState() {
258 return mState.value;
259 }
260
261 @Override
262 public Intent getSettingsIntent() {
263 return ZEN_SETTINGS;
264 }
265
266 @Override
267 public void setToggleState(boolean state) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500268 MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
John Spurlock3c4076a2015-02-24 12:12:25 -0500269 if (!state) {
John Spurlockb2278d62015-04-07 12:47:12 -0400270 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500271 showDetail(false);
272 }
273 }
274
275 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400276 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500277 return MetricsEvent.QS_DND_DETAILS;
Chris Wren457a21c2015-05-06 17:50:34 -0400278 }
279
280 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500281 public View createDetailView(Context context, View convertView, ViewGroup parent) {
282 final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
283 : (ZenModePanel) LayoutInflater.from(context).inflate(
284 R.layout.zen_mode_panel, parent, false);
285 if (convertView == null) {
286 zmp.init(mController);
John Spurlock3c4076a2015-02-24 12:12:25 -0500287 zmp.addOnAttachStateChangeListener(this);
John Spurlockd9c75db2015-04-28 11:19:13 -0400288 zmp.setCallback(mZenModePanelCallback);
John Spurlock3c4076a2015-02-24 12:12:25 -0500289 }
290 return zmp;
291 }
292
293 @Override
294 public void onViewAttachedToWindow(View v) {
295 mShowingDetail = true;
296 }
297
298 @Override
299 public void onViewDetachedFromWindow(View v) {
300 mShowingDetail = false;
301 }
302 }
John Spurlockd9c75db2015-04-28 11:19:13 -0400303
304 private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
305 @Override
306 public void onPrioritySettings() {
Jason Monkee43cdf2015-06-19 14:20:46 -0400307 mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
John Spurlockd9c75db2015-04-28 11:19:13 -0400308 }
309
310 @Override
311 public void onInteraction() {
312 // noop
313 }
314
315 @Override
316 public void onExpanded(boolean expanded) {
317 // noop
318 }
319 };
320
John Spurlock3c4076a2015-02-24 12:12:25 -0500321}