blob: 8982b3e1de1394d1c1f708f4e3301984ca3c5df7 [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 =
59 new AnimationIcon(R.drawable.ic_dnd_disable_animation);
60 private final AnimationIcon mDisableTotalSilence =
61 new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation);
62
John Spurlock3c4076a2015-02-24 12:12:25 -050063 private final ZenModeController mController;
64 private final DndDetailAdapter mDetailAdapter;
65
66 private boolean mListening;
John Spurlock3c4076a2015-02-24 12:12:25 -050067 private boolean mShowingDetail;
68
69 public DndTile(Host host) {
70 super(host);
71 mController = host.getZenModeController();
72 mDetailAdapter = new DndDetailAdapter();
John Spurlock3c4076a2015-02-24 12:12:25 -050073 mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
74 }
75
76 public static void setVisible(Context context, boolean visible) {
Andrew Flynn82862572015-04-01 14:22:37 -040077 Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
John Spurlock3c4076a2015-02-24 12:12:25 -050078 }
79
80 public static boolean isVisible(Context context) {
Andrew Flynn82862572015-04-01 14:22:37 -040081 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */);
John Spurlock3c4076a2015-02-24 12:12:25 -050082 }
83
John Spurlockf88d8082015-03-25 18:09:51 -040084 public static void setCombinedIcon(Context context, boolean combined) {
Andrew Flynn82862572015-04-01 14:22:37 -040085 Prefs.putBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, combined);
John Spurlockf88d8082015-03-25 18:09:51 -040086 }
87
88 public static boolean isCombinedIcon(Context context) {
Andrew Flynn82862572015-04-01 14:22:37 -040089 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON,
90 false /* defaultValue */);
John Spurlockf88d8082015-03-25 18:09:51 -040091 }
92
John Spurlock3c4076a2015-02-24 12:12:25 -050093 @Override
94 public DetailAdapter getDetailAdapter() {
95 return mDetailAdapter;
96 }
97
98 @Override
Jason Monk62b63a02016-02-02 15:15:31 -050099 public BooleanState newTileState() {
John Spurlock3c4076a2015-02-24 12:12:25 -0500100 return new BooleanState();
101 }
102
103 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -0500104 public Intent getLongClickIntent() {
105 return ZEN_SETTINGS;
106 }
107
108 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500109 public void handleClick() {
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000110 if (mController.isVolumeRestricted()) {
111 // Collapse the panels, so the user can see the toast.
112 mHost.collapsePanels();
113 SysUIToast.makeText(mContext, mContext.getString(
114 com.android.internal.R.string.error_message_change_not_allowed),
115 Toast.LENGTH_LONG).show();
116 return;
117 }
Chris Wren9e7283f2015-05-08 17:23:47 -0400118 MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
John Spurlock3c4076a2015-02-24 12:12:25 -0500119 if (mState.value) {
John Spurlockb2278d62015-04-07 12:47:12 -0400120 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500121 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -0400122 int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
123 mController.setZen(zen, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500124 showDetail(true);
125 }
126 }
127
128 @Override
129 protected void handleUpdateState(BooleanState state, Object arg) {
130 final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
John Spurlockb1688f62015-05-12 15:52:38 -0400131 final boolean newValue = zen != Global.ZEN_MODE_OFF;
132 final boolean valueChanged = state.value != newValue;
133 state.value = newValue;
Sudheer Shankaa8fbbb32016-02-11 17:17:57 +0000134 checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
John Spurlock3c4076a2015-02-24 12:12:25 -0500135 switch (zen) {
136 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
137 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
138 state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);
139 state.contentDescription = mContext.getString(
140 R.string.accessibility_quick_settings_dnd_priority_on);
141 break;
142 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock036e7cb2015-06-15 13:49:57 -0400143 state.icon = TOTAL_SILENCE;
John Spurlock3c4076a2015-02-24 12:12:25 -0500144 state.label = mContext.getString(R.string.quick_settings_dnd_none_label);
145 state.contentDescription = mContext.getString(
146 R.string.accessibility_quick_settings_dnd_none_on);
147 break;
John Spurlock4f1163c2015-04-02 17:41:21 -0400148 case Global.ZEN_MODE_ALARMS:
149 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
150 state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);
151 state.contentDescription = mContext.getString(
152 R.string.accessibility_quick_settings_dnd_alarms_on);
153 break;
John Spurlock3c4076a2015-02-24 12:12:25 -0500154 default:
John Spurlock036e7cb2015-06-15 13:49:57 -0400155 state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;
John Spurlock3c4076a2015-02-24 12:12:25 -0500156 state.label = mContext.getString(R.string.quick_settings_dnd_label);
157 state.contentDescription = mContext.getString(
158 R.string.accessibility_quick_settings_dnd_off);
159 break;
160 }
161 if (mShowingDetail && !state.value) {
162 showDetail(false);
163 }
John Spurlockb1688f62015-05-12 15:52:38 -0400164 if (valueChanged) {
165 fireToggleStateChanged(state.value);
166 }
John Spurlock3c4076a2015-02-24 12:12:25 -0500167 }
168
169 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400170 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500171 return MetricsEvent.QS_DND;
Chris Wren457a21c2015-05-06 17:50:34 -0400172 }
173
174 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500175 protected String composeChangeAnnouncement() {
176 if (mState.value) {
177 return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
178 } else {
179 return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_off);
180 }
181 }
182
183 @Override
184 public void setListening(boolean listening) {
185 if (mListening == listening) return;
186 mListening = listening;
187 if (mListening) {
188 mController.addCallback(mZenCallback);
Andrew Flynn82862572015-04-01 14:22:37 -0400189 Prefs.registerListener(mContext, mPrefListener);
John Spurlock3c4076a2015-02-24 12:12:25 -0500190 } else {
191 mController.removeCallback(mZenCallback);
Andrew Flynn82862572015-04-01 14:22:37 -0400192 Prefs.unregisterListener(mContext, mPrefListener);
John Spurlock3c4076a2015-02-24 12:12:25 -0500193 }
194 }
195
Jason Monkc3f42c12016-02-05 12:33:13 -0500196 @Override
197 public boolean isAvailable() {
198 return isVisible(mContext);
199 }
200
John Spurlockcd863ad2015-04-07 14:01:28 -0400201 private final OnSharedPreferenceChangeListener mPrefListener
202 = new OnSharedPreferenceChangeListener() {
203 @Override
Andrew Flynn82862572015-04-01 14:22:37 -0400204 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
205 @Prefs.Key String key) {
206 if (Prefs.Key.DND_TILE_COMBINED_ICON.equals(key) ||
207 Prefs.Key.DND_TILE_VISIBLE.equals(key)) {
John Spurlockcd863ad2015-04-07 14:01:28 -0400208 refreshState();
209 }
210 }
211 };
212
John Spurlock3c4076a2015-02-24 12:12:25 -0500213 private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
214 public void onZenChanged(int zen) {
215 refreshState(zen);
216 }
217 };
218
John Spurlock3c4076a2015-02-24 12:12:25 -0500219 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
220 @Override
221 public void onReceive(Context context, Intent intent) {
John Spurlockcd863ad2015-04-07 14:01:28 -0400222 final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
223 setVisible(mContext, visible);
John Spurlock3c4076a2015-02-24 12:12:25 -0500224 refreshState();
225 }
226 };
227
228 private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
229
230 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500231 public CharSequence getTitle() {
232 return mContext.getString(R.string.quick_settings_dnd_label);
John Spurlock3c4076a2015-02-24 12:12:25 -0500233 }
234
235 @Override
236 public Boolean getToggleState() {
237 return mState.value;
238 }
239
240 @Override
241 public Intent getSettingsIntent() {
242 return ZEN_SETTINGS;
243 }
244
245 @Override
246 public void setToggleState(boolean state) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500247 MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
John Spurlock3c4076a2015-02-24 12:12:25 -0500248 if (!state) {
John Spurlockb2278d62015-04-07 12:47:12 -0400249 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
John Spurlock3c4076a2015-02-24 12:12:25 -0500250 showDetail(false);
251 }
252 }
253
254 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400255 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500256 return MetricsEvent.QS_DND_DETAILS;
Chris Wren457a21c2015-05-06 17:50:34 -0400257 }
258
259 @Override
John Spurlock3c4076a2015-02-24 12:12:25 -0500260 public View createDetailView(Context context, View convertView, ViewGroup parent) {
261 final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
262 : (ZenModePanel) LayoutInflater.from(context).inflate(
263 R.layout.zen_mode_panel, parent, false);
264 if (convertView == null) {
265 zmp.init(mController);
John Spurlock3c4076a2015-02-24 12:12:25 -0500266 zmp.addOnAttachStateChangeListener(this);
John Spurlockd9c75db2015-04-28 11:19:13 -0400267 zmp.setCallback(mZenModePanelCallback);
John Spurlock3c4076a2015-02-24 12:12:25 -0500268 }
269 return zmp;
270 }
271
272 @Override
273 public void onViewAttachedToWindow(View v) {
274 mShowingDetail = true;
275 }
276
277 @Override
278 public void onViewDetachedFromWindow(View v) {
279 mShowingDetail = false;
280 }
281 }
John Spurlockd9c75db2015-04-28 11:19:13 -0400282
283 private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
284 @Override
285 public void onPrioritySettings() {
Jason Monkee43cdf2015-06-19 14:20:46 -0400286 mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
John Spurlockd9c75db2015-04-28 11:19:13 -0400287 }
288
289 @Override
290 public void onInteraction() {
291 // noop
292 }
293
294 @Override
295 public void onExpanded(boolean expanded) {
296 // noop
297 }
298 };
299
John Spurlock3c4076a2015-02-24 12:12:25 -0500300}