DndTile.java revision c3f42c102422f70f5bbe67105e16515ce9c306a3
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    @Override
183    public boolean isAvailable() {
184        return isVisible(mContext);
185    }
186
187    private final OnSharedPreferenceChangeListener mPrefListener
188            = new OnSharedPreferenceChangeListener() {
189        @Override
190        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
191                @Prefs.Key String key) {
192            if (Prefs.Key.DND_TILE_COMBINED_ICON.equals(key) ||
193                    Prefs.Key.DND_TILE_VISIBLE.equals(key)) {
194                refreshState();
195            }
196        }
197    };
198
199    private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
200        public void onZenChanged(int zen) {
201            refreshState(zen);
202        }
203    };
204
205    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
206        @Override
207        public void onReceive(Context context, Intent intent) {
208            final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
209            setVisible(mContext, visible);
210            refreshState();
211        }
212    };
213
214    private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
215
216        @Override
217        public CharSequence getTitle() {
218            return mContext.getString(R.string.quick_settings_dnd_label);
219        }
220
221        @Override
222        public Boolean getToggleState() {
223            return mState.value;
224        }
225
226        @Override
227        public Intent getSettingsIntent() {
228            return ZEN_SETTINGS;
229        }
230
231        @Override
232        public void setToggleState(boolean state) {
233            MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state);
234            if (!state) {
235                mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
236                showDetail(false);
237            }
238        }
239
240        @Override
241        public int getMetricsCategory() {
242            return MetricsEvent.QS_DND_DETAILS;
243        }
244
245        @Override
246        public View createDetailView(Context context, View convertView, ViewGroup parent) {
247            final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
248                    : (ZenModePanel) LayoutInflater.from(context).inflate(
249                            R.layout.zen_mode_panel, parent, false);
250            if (convertView == null) {
251                zmp.init(mController);
252                zmp.addOnAttachStateChangeListener(this);
253                zmp.setCallback(mZenModePanelCallback);
254            }
255            return zmp;
256        }
257
258        @Override
259        public void onViewAttachedToWindow(View v) {
260            mShowingDetail = true;
261        }
262
263        @Override
264        public void onViewDetachedFromWindow(View v) {
265            mShowingDetail = false;
266        }
267    }
268
269    private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() {
270        @Override
271        public void onPrioritySettings() {
272            mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS);
273        }
274
275        @Override
276        public void onInteraction() {
277            // noop
278        }
279
280        @Override
281        public void onExpanded(boolean expanded) {
282            // noop
283        }
284    };
285
286}
287