DndTile.java revision 76c67aa361f65dfb2f5e03d06cc1ccebce9cecd9
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; 32import android.widget.Toast; 33 34import com.android.internal.logging.MetricsLogger; 35import com.android.internal.logging.MetricsProto.MetricsEvent; 36import com.android.systemui.Prefs; 37import com.android.systemui.R; 38import com.android.systemui.SysUIToast; 39import 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> { 45 46 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); 51 52 private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE"; 53 private static final String EXTRA_VISIBLE = "visible"; 54 55 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 63 private final ZenModeController mController; 64 private final DndDetailAdapter mDetailAdapter; 65 66 private boolean mListening; 67 private boolean mShowingDetail; 68 69 public DndTile(Host host) { 70 super(host); 71 mController = host.getZenModeController(); 72 mDetailAdapter = new DndDetailAdapter(); 73 mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE)); 74 } 75 76 public static void setVisible(Context context, boolean visible) { 77 Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible); 78 } 79 80 public static boolean isVisible(Context context) { 81 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_VISIBLE, false /* defaultValue */); 82 } 83 84 public static void setCombinedIcon(Context context, boolean combined) { 85 Prefs.putBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, combined); 86 } 87 88 public static boolean isCombinedIcon(Context context) { 89 return Prefs.getBoolean(context, Prefs.Key.DND_TILE_COMBINED_ICON, 90 false /* defaultValue */); 91 } 92 93 @Override 94 public DetailAdapter getDetailAdapter() { 95 return mDetailAdapter; 96 } 97 98 @Override 99 public BooleanState newTileState() { 100 return new BooleanState(); 101 } 102 103 @Override 104 public Intent getLongClickIntent() { 105 return ZEN_SETTINGS; 106 } 107 108 @Override 109 public void handleClick() { 110 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 } 118 MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); 119 if (mState.value) { 120 mController.setZen(Global.ZEN_MODE_OFF, null, TAG); 121 } else { 122 int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS); 123 mController.setZen(zen, null, TAG); 124 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(); 131 final boolean newValue = zen != Global.ZEN_MODE_OFF; 132 final boolean valueChanged = state.value != newValue; 133 state.value = newValue; 134 checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME); 135 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: 143 state.icon = TOTAL_SILENCE; 144 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; 148 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; 154 default: 155 state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable; 156 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 } 164 if (valueChanged) { 165 fireToggleStateChanged(state.value); 166 } 167 } 168 169 @Override 170 public int getMetricsCategory() { 171 return MetricsEvent.QS_DND; 172 } 173 174 @Override 175 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); 189 Prefs.registerListener(mContext, mPrefListener); 190 } else { 191 mController.removeCallback(mZenCallback); 192 Prefs.unregisterListener(mContext, mPrefListener); 193 } 194 } 195 196 @Override 197 public boolean isAvailable() { 198 return isVisible(mContext); 199 } 200 201 private final OnSharedPreferenceChangeListener mPrefListener 202 = new OnSharedPreferenceChangeListener() { 203 @Override 204 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)) { 208 refreshState(); 209 } 210 } 211 }; 212 213 private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() { 214 public void onZenChanged(int zen) { 215 refreshState(zen); 216 } 217 }; 218 219 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 220 @Override 221 public void onReceive(Context context, Intent intent) { 222 final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false); 223 setVisible(mContext, visible); 224 refreshState(); 225 } 226 }; 227 228 private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener { 229 230 @Override 231 public CharSequence getTitle() { 232 return mContext.getString(R.string.quick_settings_dnd_label); 233 } 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) { 247 MetricsLogger.action(mContext, MetricsEvent.QS_DND_TOGGLE, state); 248 if (!state) { 249 mController.setZen(Global.ZEN_MODE_OFF, null, TAG); 250 showDetail(false); 251 } 252 } 253 254 @Override 255 public int getMetricsCategory() { 256 return MetricsEvent.QS_DND_DETAILS; 257 } 258 259 @Override 260 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); 266 zmp.addOnAttachStateChangeListener(this); 267 zmp.setCallback(mZenModePanelCallback); 268 } 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 } 282 283 private final ZenModePanel.Callback mZenModePanelCallback = new ZenModePanel.Callback() { 284 @Override 285 public void onPrioritySettings() { 286 mHost.startActivityDismissingKeyguard(ZEN_PRIORITY_SETTINGS); 287 } 288 289 @Override 290 public void onInteraction() { 291 // noop 292 } 293 294 @Override 295 public void onExpanded(boolean expanded) { 296 // noop 297 } 298 }; 299 300} 301