blob: 8b228684297149d00a599dac923e57d07ebc85ab [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;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +000032import android.widget.Toast;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050033
Chris Wren457a21c2015-05-06 17:50:34 -040034import com.android.internal.logging.MetricsLogger;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050035import com.android.internal.logging.MetricsProto.MetricsEvent;
Andrew Flynn82862572015-04-01 14:22:37 -040036import com.android.systemui.Prefs;
John Spurlock3c4076a2015-02-24 12:12:25 -050037import com.android.systemui.R;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +000038import com.android.systemui.SysUIToast;
John Spurlock3c4076a2015-02-24 12:12:25 -050039import com.android.systemui.qs.QSTile;
40import com.android.systemui.statusbar.policy.ZenModeController;
41import com.android.systemui.volume.ZenModePanel;
42
43/** Quick settings tile: Do not disturb **/
44public class DndTile extends QSTile<QSTile.BooleanState> {
John Spurlock036e7cb2015-06-15 13:49:57 -040045
John Spurlockd9c75db2015-04-28 11:19:13 -040046 private static final Intent ZEN_SETTINGS =
47 new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
48
49 private static final Intent ZEN_PRIORITY_SETTINGS =
50 new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
John Spurlock3c4076a2015-02-24 12:12:25 -050051
52 private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
53 private static final String EXTRA_VISIBLE = "visible";
John Spurlock3c4076a2015-02-24 12:12:25 -050054
John Spurlock036e7cb2015-06-15 13:49:57 -040055 private static final QSTile.Icon TOTAL_SILENCE =
56 ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
57
58 private final AnimationIcon mDisable =
Jason Monk1aec93f2016-03-01 09:39:30 -050059 new AnimationIcon(R.drawable.ic_dnd_disable_animation,
60 R.drawable.ic_qs_dnd_off);
John Spurlock036e7cb2015-06-15 13:49:57 -040061 private final AnimationIcon mDisableTotalSilence =
Jason Monk1aec93f2016-03-01 09:39:30 -050062 new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation,
63 R.drawable.ic_qs_dnd_off);
John Spurlock036e7cb2015-06-15 13:49:57 -040064
John Spurlock3c4076a2015-02-24 12:12:25 -050065 private final ZenModeController mController;
66 private final DndDetailAdapter mDetailAdapter;
67
68 private boolean mListening;
John Spurlock3c4076a2015-02-24 12:12:25 -050069 private boolean mShowingDetail;
70
71 public DndTile(Host host) {
72 super(host);
73 mController = host.getZenModeController();
74 mDetailAdapter = new DndDetailAdapter();
John Spurlock3c4076a2015-02-24 12:12:25 -050075 mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
76 }
77
78 public static void setVisible(Context context, boolean visible) {
Andrew Flynn82862572015-04-01 14:22:37 -040079 Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
John Spurlock3c4076a2015-02-24 12:12:25 -050080 }
81
82 public static boolean isVisible(Context context) {
Andrew Flynn82862572015-04-01 14:22:37 -040083 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */);
John Spurlock3c4076a2015-02-24 12:12:25 -050084 }
85
John Spurlockf88d8082015-03-25 18:09:51 -040086 public static void setCombinedIcon(Context context, boolean combined) {
Andrew Flynn82862572015-04-01 14:22:37 -040087 Prefs.putBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, combined);
John Spurlockf88d8082015-03-25 18:09:51 -040088 }
89
90 public static boolean isCombinedIcon(Context context) {
Andrew Flynn82862572015-04-01 14:22:37 -040091 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON,
92 false /* defaultValue */);
John Spurlockf88d8082015-03-25 18:09:51 -040093 }
94
John Spurlock3c4076a2015-02-24 12:12:25 -050095 @Override
96 public DetailAdapter getDetailAdapter() {
97 return mDetailAdapter;
98 }
99
100 @Override
Jason Monk62b63a02016-02-02 15:15:31 -0500101 public BooleanState newTileState() {
John Spurlock3c4076a2015-02-24 12:12:25 -0500102 return new BooleanState();
103 }
104
105 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -0500106 public Intent getLongClickIntent() {
107 return ZEN_SETTINGS;
108 }
109
110 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500111 public void handleClick() {
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000112 if (mController.isVolumeRestricted()) {
113 // Collapse the panels, so the user can see the toast.
114 mHost.collapsePanels();
115 SysUIToast.makeText(mContext, mContext.getString(
116 com.android.internal.R.string.error_message_change_not_allowed),
117 Toast.LENGTH_LONG).show();
118 return;
119 }
Chris Wren9e7283f2015-05-08 17:23:47 -0400120 MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
John Spurlock3c4076a2015-02-24 12:12:25 -0500121 if (mState.value) {
John Spurlockb2278d62015-04-07 12:47:12 -0400122 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500123 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -0400124 int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
125 mController.setZen(zen, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500126 showDetail(true);
127 }
128 }
129
130 @Override
131 protected void handleUpdateState(BooleanState state, Object arg) {
132 final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
John Spurlockb1688f62015-05-12 15:52:38 -0400133 final boolean newValue = zen != Global.ZEN_MODE_OFF;
134 final boolean valueChanged = state.value != newValue;
135 state.value = newValue;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000136 checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
John Spurlock3c4076a2015-02-24 12:12:25 -0500137 switch (zen) {
138 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
139 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
140 state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);
141 state.contentDescription = mContext.getString(
142 R.string.accessibility_quick_settings_dnd_priority_on);
143 break;
144 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock036e7cb2015-06-15 13:49:57 -0400145 state.icon = TOTAL_SILENCE;
John Spurlock3c4076a2015-02-24 12:12:25 -0500146 state.label = mContext.getString(R.string.quick_settings_dnd_none_label);
147 state.contentDescription = mContext.getString(
148 R.string.accessibility_quick_settings_dnd_none_on);
149 break;
John Spurlock4f1163c2015-04-02 17:41:21 -0400150 case Global.ZEN_MODE_ALARMS:
151 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
152 state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);
153 state.contentDescription = mContext.getString(
154 R.string.accessibility_quick_settings_dnd_alarms_on);
155 break;
John Spurlock3c4076a2015-02-24 12:12:25 -0500156 default:
John Spurlock036e7cb2015-06-15 13:49:57 -0400157 state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;
John Spurlock3c4076a2015-02-24 12:12:25 -0500158 state.label = mContext.getString(R.string.quick_settings_dnd_label);
159 state.contentDescription = mContext.getString(
160 R.string.accessibility_quick_settings_dnd_off);
161 break;
162 }
163 if (mShowingDetail && !state.value) {
164 showDetail(false);
165 }
John Spurlockb1688f62015-05-12 15:52:38 -0400166 if (valueChanged) {
167 fireToggleStateChanged(state.value);
168 }
John Spurlock3c4076a2015-02-24 12:12:25 -0500169 }
170
171 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400172 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500173 return MetricsEvent.QS_DND;
Chris Wren457a21c2015-05-06 17:50:34 -0400174 }
175
176 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500177 protected String composeChangeAnnouncement() {
178 if (mState.value) {
179 return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
180 } else {
181 return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_off);
182 }
183 }
184
185 @Override
186 public void setListening(boolean listening) {
187 if (mListening == listening) return;
188 mListening = listening;
189 if (mListening) {
190 mController.addCallback(mZenCallback);
Andrew Flynn82862572015-04-01 14:22:37 -0400191 Prefs.registerListener(mContext, mPrefListener);
John Spurlock3c4076a2015-02-24 12:12:25 -0500192 } else {
193 mController.removeCallback(mZenCallback);
Andrew Flynn82862572015-04-01 14:22:37 -0400194 Prefs.unregisterListener(mContext, mPrefListener);
John Spurlock3c4076a2015-02-24 12:12:25 -0500195 }
196 }
197
Jason Monkc3f42c12016-02-05 12:33:13 -0500198 @Override
199 public boolean isAvailable() {
200 return isVisible(mContext);
201 }
202
John Spurlockcd863ad2015-04-07 14:01:28 -0400203 private final OnSharedPreferenceChangeListener mPrefListener
204 = new OnSharedPreferenceChangeListener() {
205 @Override
Andrew Flynn82862572015-04-01 14:22:37 -0400206 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
207 @Prefs.Key String key) {
208 if (Prefs.Key.DND_TILE_COMBINED_ICON.equals(key) ||
209 Prefs.Key.DND_TILE_VISIBLE.equals(key)) {
John Spurlockcd863ad2015-04-07 14:01:28 -0400210 refreshState();
211 }
212 }
213 };
214
John Spurlock3c4076a2015-02-24 12:12:25 -0500215 private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
216 public void onZenChanged(int zen) {
217 refreshState(zen);
218 }
219 };
220
John Spurlock3c4076a2015-02-24 12:12:25 -0500221 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
222 @Override
223 public void onReceive(Context context, Intent intent) {
John Spurlockcd863ad2015-04-07 14:01:28 -0400224 final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
225 setVisible(mContext, visible);
John Spurlock3c4076a2015-02-24 12:12:25 -0500226 refreshState();
227 }
228 };
229
230 private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
231
232 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500233 public CharSequence getTitle() {
234 return mContext.getString(R.string.quick_settings_dnd_label);
John Spurlock3c4076a2015-02-24 12:12:25 -0500235 }
236
237 @Override
238 public Boolean getToggleState() {
239 return mState.value;
240 }
241
242 @Override
243 public Intent getSettingsIntent() {
244 return ZEN_SETTINGS;
245 }
246
247 @Override
248 public void setToggleState(boolean state) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500249 MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
John Spurlock3c4076a2015-02-24 12:12:25 -0500250 if (!state) {
John Spurlockb2278d62015-04-07 12:47:12 -0400251 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500252 showDetail(false);
253 }
254 }
255
256 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400257 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500258 return MetricsEvent.QS_DND_DETAILS;
Chris Wren457a21c2015-05-06 17:50:34 -0400259 }
260
261 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500262 public View createDetailView(Context context, View convertView, ViewGroup parent) {
263 final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
264 : (ZenModePanel) LayoutInflater.from(context).inflate(
265 R.layout.zen_mode_panel, parent, false);
266 if (convertView == null) {
267 zmp.init(mController);
John Spurlock3c4076a2015-02-24 12:12:25 -0500268 zmp.addOnAttachStateChangeListener(this);
John Spurlockd9c75db2015-04-28 11:19:13 -0400269 zmp.setCallback(mZenModePanelCallback);
John Spurlock3c4076a2015-02-24 12:12:25 -0500270 }
271 return zmp;
272 }
273
274 @Override
275 public void onViewAttachedToWindow(View v) {
276 mShowingDetail = true;
277 }
278
279 @Override
280 public void onViewDetachedFromWindow(View v) {
281 mShowingDetail = false;
282 }
283 }
John Spurlockd9c75db2015-04-28 11:19:13 -0400284
285 private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
286 @Override
287 public void onPrioritySettings() {
Jason Monkee43cdf2015-06-19 14:20:46 -0400288 mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
John Spurlockd9c75db2015-04-28 11:19:13 -0400289 }
290
291 @Override
292 public void onInteraction() {
293 // noop
294 }
295
296 @Override
297 public void onExpanded(boolean expanded) {
298 // noop
299 }
300 };
301
John Spurlock3c4076a2015-02-24 12:12:25 -0500302}