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