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