• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.systemui.qs.tiles;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.SharedPreferences;
24 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
25 import android.os.UserManager;
26 import android.provider.Settings;
27 import android.provider.Settings.Global;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.View.OnAttachStateChangeListener;
31 import android.view.ViewGroup;
32 import android.widget.Switch;
33 import android.widget.Toast;
34 
35 import com.android.internal.logging.MetricsLogger;
36 import com.android.internal.logging.MetricsProto.MetricsEvent;
37 import com.android.systemui.Prefs;
38 import com.android.systemui.R;
39 import com.android.systemui.SysUIToast;
40 import com.android.systemui.qs.QSTile;
41 import com.android.systemui.statusbar.policy.ZenModeController;
42 import com.android.systemui.volume.ZenModePanel;
43 
44 /** Quick settings tile: Do not disturb **/
45 public class DndTile extends QSTile<QSTile.BooleanState> {
46 
47     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);
52 
53     private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
54     private static final String EXTRA_VISIBLE = "visible";
55 
56     private static final QSTile.Icon TOTAL_SILENCE =
57             ResourceIcon.get(R.drawable.ic_qs_dnd_on_total_silence);
58 
59     private final AnimationIcon mDisable =
60             new AnimationIcon(R.drawable.ic_dnd_disable_animation,
61                     R.drawable.ic_qs_dnd_off);
62     private final AnimationIcon mDisableTotalSilence =
63             new AnimationIcon(R.drawable.ic_dnd_total_silence_disable_animation,
64                     R.drawable.ic_qs_dnd_off);
65 
66     private final ZenModeController mController;
67     private final DndDetailAdapter mDetailAdapter;
68 
69     private boolean mListening;
70     private boolean mShowingDetail;
71 
DndTile(Host host)72     public DndTile(Host host) {
73         super(host);
74         mController = host.getZenModeController();
75         mDetailAdapter = new DndDetailAdapter();
76         mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
77     }
78 
setVisible(Context context, boolean visible)79     public static void setVisible(Context context, boolean visible) {
80         Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
81     }
82 
isVisible(Context context)83     public static boolean isVisible(Context context) {
84         return Prefs.getBoolean(context, Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */);
85     }
86 
setCombinedIcon(Context context, boolean combined)87     public static void setCombinedIcon(Context context, boolean combined) {
88         Prefs.putBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, combined);
89     }
90 
isCombinedIcon(Context context)91     public static boolean isCombinedIcon(Context context) {
92         return Prefs.getBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON,
93                 false /* defaultValue */);
94     }
95 
96     @Override
getDetailAdapter()97     public DetailAdapter getDetailAdapter() {
98         return mDetailAdapter;
99     }
100 
101     @Override
newTileState()102     public BooleanState newTileState() {
103         return new BooleanState();
104     }
105 
106     @Override
getLongClickIntent()107     public Intent getLongClickIntent() {
108         return ZEN_SETTINGS;
109     }
110 
111     @Override
handleClick()112     public void handleClick() {
113         if (mController.isVolumeRestricted()) {
114             // Collapse the panels, so the user can see the toast.
115             mHost.collapsePanels();
116             SysUIToast.makeText(mContext, mContext.getString(
117                     com.android.internal.R.string.error_message_change_not_allowed),
118                     Toast.LENGTH_LONG).show();
119             return;
120         }
121         MetricsLogger.action(mContext, getMetricsCategory(), !mState.value);
122         if (mState.value) {
123             mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
124         } else {
125             showDetail(true);
126             int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
127             mController.setZen(zen, null, TAG);
128         }
129     }
130 
131     @Override
getTileLabel()132     public CharSequence getTileLabel() {
133         return mContext.getString(R.string.quick_settings_dnd_label);
134     }
135 
136     @Override
handleUpdateState(BooleanState state, Object arg)137     protected void handleUpdateState(BooleanState state, Object arg) {
138         final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
139         final boolean newValue = zen != Global.ZEN_MODE_OFF;
140         final boolean valueChanged = state.value != newValue;
141         state.value = newValue;
142         checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
143         switch (zen) {
144             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
145                 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
146                 state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);
147                 state.contentDescription = mContext.getString(
148                         R.string.accessibility_quick_settings_dnd_priority_on);
149                 break;
150             case Global.ZEN_MODE_NO_INTERRUPTIONS:
151                 state.icon = TOTAL_SILENCE;
152                 state.label = mContext.getString(R.string.quick_settings_dnd_none_label);
153                 state.contentDescription = mContext.getString(
154                         R.string.accessibility_quick_settings_dnd_none_on);
155                 break;
156             case Global.ZEN_MODE_ALARMS:
157                 state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);
158                 state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);
159                 state.contentDescription = mContext.getString(
160                         R.string.accessibility_quick_settings_dnd_alarms_on);
161                 break;
162             default:
163                 state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;
164                 state.label = mContext.getString(R.string.quick_settings_dnd_label);
165                 state.contentDescription =  mContext.getString(
166                         R.string.accessibility_quick_settings_dnd);
167                 break;
168         }
169         if (mShowingDetail && !state.value) {
170             showDetail(false);
171         }
172         if (valueChanged) {
173             fireToggleStateChanged(state.value);
174         }
175         state.minimalAccessibilityClassName = state.expandedAccessibilityClassName
176                 = Switch.class.getName();
177     }
178 
179     @Override
getMetricsCategory()180     public int getMetricsCategory() {
181         return MetricsEvent.QS_DND;
182     }
183 
184     @Override
composeChangeAnnouncement()185     protected String composeChangeAnnouncement() {
186         if (mState.value) {
187             return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
188         } else {
189             return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_off);
190         }
191     }
192 
193     @Override
setListening(boolean listening)194     public void setListening(boolean listening) {
195         if (mListening == listening) return;
196         mListening = listening;
197         if (mListening) {
198             mController.addCallback(mZenCallback);
199             Prefs.registerListener(mContext, mPrefListener);
200         } else {
201             mController.removeCallback(mZenCallback);
202             Prefs.unregisterListener(mContext, mPrefListener);
203         }
204     }
205 
206     @Override
isAvailable()207     public boolean isAvailable() {
208         return isVisible(mContext);
209     }
210 
211     private final OnSharedPreferenceChangeListener mPrefListener
212             = new OnSharedPreferenceChangeListener() {
213         @Override
214         public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
215                 @Prefs.Key String key) {
216             if (Prefs.Key.DND_TILE_COMBINED_ICON.equals(key) ||
217                     Prefs.Key.DND_TILE_VISIBLE.equals(key)) {
218                 refreshState();
219             }
220         }
221     };
222 
223     private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
224         public void onZenChanged(int zen) {
225             refreshState(zen);
226         }
227     };
228 
229     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
230         @Override
231         public void onReceive(Context context, Intent intent) {
232             final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
233             setVisible(mContext, visible);
234             refreshState();
235         }
236     };
237 
238     private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
239 
240         @Override
getTitle()241         public CharSequence getTitle() {
242             return mContext.getString(R.string.quick_settings_dnd_label);
243         }
244 
245         @Override
getToggleState()246         public Boolean getToggleState() {
247             return mState.value;
248         }
249 
250         @Override
getSettingsIntent()251         public Intent getSettingsIntent() {
252             return ZEN_SETTINGS;
253         }
254 
255         @Override
setToggleState(boolean state)256         public void setToggleState(boolean state) {
257             MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
258             if (!state) {
259                 mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
260                 showDetail(false);
261             }
262         }
263 
264         @Override
getMetricsCategory()265         public int getMetricsCategory() {
266             return MetricsEvent.QS_DND_DETAILS;
267         }
268 
269         @Override
createDetailView(Context context, View convertView, ViewGroup parent)270         public View createDetailView(Context context, View convertView, ViewGroup parent) {
271             final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
272                     : (ZenModePanel) LayoutInflater.from(context).inflate(
273                             R.layout.zen_mode_panel, parent, false);
274             if (convertView == null) {
275                 zmp.init(mController);
276                 zmp.addOnAttachStateChangeListener(this);
277                 zmp.setCallback(mZenModePanelCallback);
278             }
279             return zmp;
280         }
281 
282         @Override
onViewAttachedToWindow(View v)283         public void onViewAttachedToWindow(View v) {
284             mShowingDetail = true;
285         }
286 
287         @Override
onViewDetachedFromWindow(View v)288         public void onViewDetachedFromWindow(View v) {
289             mShowingDetail = false;
290         }
291     }
292 
293     private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
294         @Override
295         public void onPrioritySettings() {
296             mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
297         }
298 
299         @Override
300         public void onInteraction() {
301             // noop
302         }
303 
304         @Override
305         public void onExpanded(boolean expanded) {
306             // noop
307         }
308     };
309 
310 }
311