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