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