PhoneStatusBarPolicy.java revision 661f2cf45860d2e10924e6b69966a9afe255f28b
1/* 2 * Copyright (C) 2008 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.statusbar.phone; 18 19import android.app.AlarmManager; 20import android.app.StatusBarManager; 21import android.bluetooth.BluetoothAdapter; 22import android.content.BroadcastReceiver; 23import android.content.Context; 24import android.content.Intent; 25import android.content.IntentFilter; 26import android.media.AudioManager; 27import android.os.Handler; 28import android.os.UserHandle; 29import android.provider.Settings.Global; 30import android.telecom.TelecomManager; 31import android.util.Log; 32 33import com.android.internal.telephony.IccCardConstants; 34import com.android.internal.telephony.TelephonyIntents; 35import com.android.systemui.R; 36import com.android.systemui.statusbar.policy.CastController; 37import com.android.systemui.statusbar.policy.CastController.CastDevice; 38import com.android.systemui.statusbar.policy.HotspotController; 39 40/** 41 * This class contains all of the policy about which icons are installed in the status 42 * bar at boot time. It goes through the normal API for icons, even though it probably 43 * strictly doesn't need to. 44 */ 45public class PhoneStatusBarPolicy { 46 private static final String TAG = "PhoneStatusBarPolicy"; 47 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 48 49 private static final boolean SHOW_SYNC_ICON = false; 50 51 private static final String SLOT_SYNC_ACTIVE = "sync_active"; 52 private static final String SLOT_CAST = "cast"; 53 private static final String SLOT_HOTSPOT = "hotspot"; 54 private static final String SLOT_BLUETOOTH = "bluetooth"; 55 private static final String SLOT_TTY = "tty"; 56 private static final String SLOT_ZEN = "zen"; 57 private static final String SLOT_VOLUME = "volume"; 58 private static final String SLOT_CDMA_ERI = "cdma_eri"; 59 private static final String SLOT_ALARM_CLOCK = "alarm_clock"; 60 61 private final Context mContext; 62 private final StatusBarManager mService; 63 private final Handler mHandler = new Handler(); 64 private final CastController mCast; 65 private final HotspotController mHotspot; 66 67 // Assume it's all good unless we hear otherwise. We don't always seem 68 // to get broadcasts that it *is* there. 69 IccCardConstants.State mSimState = IccCardConstants.State.READY; 70 71 private boolean mZenVisible; 72 private boolean mVolumeVisible; 73 74 private int mZen; 75 76 private boolean mBluetoothEnabled = false; 77 78 79 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 80 @Override 81 public void onReceive(Context context, Intent intent) { 82 String action = intent.getAction(); 83 if (action.equals(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED)) { 84 updateAlarm(); 85 } 86 else if (action.equals(Intent.ACTION_SYNC_STATE_CHANGED)) { 87 updateSyncState(intent); 88 } 89 else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) || 90 action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) { 91 updateBluetooth(); 92 } 93 else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { 94 updateVolumeZen(); 95 } 96 else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { 97 updateSimState(intent); 98 } 99 else if (action.equals(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED)) { 100 updateTTY(intent); 101 } 102 else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 103 updateAlarm(); 104 } 105 } 106 }; 107 108 public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot) { 109 mContext = context; 110 mCast = cast; 111 mHotspot = hotspot; 112 mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE); 113 114 // listen for broadcasts 115 IntentFilter filter = new IntentFilter(); 116 filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED); 117 filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED); 118 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 119 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 120 filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); 121 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 122 filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED); 123 filter.addAction(Intent.ACTION_USER_SWITCHED); 124 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); 125 126 // TTY status 127 mService.setIcon(SLOT_TTY, R.drawable.stat_sys_tty_mode, 0, null); 128 mService.setIconVisibility(SLOT_TTY, false); 129 130 // Cdma Roaming Indicator, ERI 131 mService.setIcon(SLOT_CDMA_ERI, R.drawable.stat_sys_roaming_cdma_0, 0, null); 132 mService.setIconVisibility(SLOT_CDMA_ERI, false); 133 134 // bluetooth status 135 updateBluetooth(); 136 137 // Alarm clock 138 mService.setIcon(SLOT_ALARM_CLOCK, R.drawable.stat_sys_alarm, 0, null); 139 mService.setIconVisibility(SLOT_ALARM_CLOCK, false); 140 141 // Sync state 142 mService.setIcon(SLOT_SYNC_ACTIVE, R.drawable.stat_sys_sync, 0, null); 143 mService.setIconVisibility(SLOT_SYNC_ACTIVE, false); 144 // "sync_failing" is obsolete: b/1297963 145 146 // zen 147 mService.setIcon(SLOT_ZEN, R.drawable.stat_sys_zen_important, 0, null); 148 mService.setIconVisibility(SLOT_ZEN, false); 149 150 // volume 151 mService.setIcon(SLOT_VOLUME, R.drawable.stat_sys_ringer_vibrate, 0, null); 152 mService.setIconVisibility(SLOT_VOLUME, false); 153 updateVolumeZen(); 154 155 // cast 156 mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, null); 157 mService.setIconVisibility(SLOT_CAST, false); 158 mCast.addCallback(mCastCallback); 159 160 // hotspot 161 mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0, null); 162 mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled()); 163 mHotspot.addCallback(mHotspotCallback); 164 } 165 166 public void setZenMode(int zen) { 167 mZen = zen; 168 updateVolumeZen(); 169 } 170 171 private void updateAlarm() { 172 AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 173 boolean alarmSet = alarmManager.getNextAlarmClock(UserHandle.USER_CURRENT) != null; 174 mService.setIconVisibility(SLOT_ALARM_CLOCK, alarmSet); 175 } 176 177 private final void updateSyncState(Intent intent) { 178 if (!SHOW_SYNC_ICON) return; 179 boolean isActive = intent.getBooleanExtra("active", false); 180 mService.setIconVisibility(SLOT_SYNC_ACTIVE, isActive); 181 } 182 183 private final void updateSimState(Intent intent) { 184 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 185 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { 186 mSimState = IccCardConstants.State.ABSENT; 187 } 188 else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) { 189 mSimState = IccCardConstants.State.CARD_IO_ERROR; 190 } 191 else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { 192 mSimState = IccCardConstants.State.READY; 193 } 194 else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { 195 final String lockedReason = 196 intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); 197 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { 198 mSimState = IccCardConstants.State.PIN_REQUIRED; 199 } 200 else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { 201 mSimState = IccCardConstants.State.PUK_REQUIRED; 202 } 203 else { 204 mSimState = IccCardConstants.State.NETWORK_LOCKED; 205 } 206 } else { 207 mSimState = IccCardConstants.State.UNKNOWN; 208 } 209 } 210 211 public final void updateVolumeZen() { 212 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 213 214 boolean zenVisible = false; 215 int zenIconId = 0; 216 String zenDescription = null; 217 218 boolean volumeVisible = false; 219 int volumeIconId = 0; 220 String volumeDescription = null; 221 222 if (mZen == Global.ZEN_MODE_NO_INTERRUPTIONS) { 223 zenVisible = true; 224 zenIconId = R.drawable.stat_sys_zen_none; 225 zenDescription = mContext.getString(R.string.zen_no_interruptions); 226 } else if (mZen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { 227 zenVisible = true; 228 zenIconId = R.drawable.stat_sys_zen_important; 229 zenDescription = mContext.getString(R.string.zen_important_interruptions); 230 } 231 232 if (mZen != Global.ZEN_MODE_NO_INTERRUPTIONS && 233 audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) { 234 volumeVisible = true; 235 volumeIconId = R.drawable.stat_sys_ringer_vibrate; 236 volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate); 237 } 238 239 if (zenVisible) { 240 mService.setIcon(SLOT_ZEN, zenIconId, 0, zenDescription); 241 } 242 if (zenVisible != mZenVisible) { 243 mService.setIconVisibility(SLOT_ZEN, zenVisible); 244 mZenVisible = zenVisible; 245 } 246 247 if (volumeVisible) { 248 mService.setIcon(SLOT_VOLUME, volumeIconId, 0, volumeDescription); 249 } 250 if (volumeVisible != mVolumeVisible) { 251 mService.setIconVisibility(SLOT_VOLUME, volumeVisible); 252 mVolumeVisible = volumeVisible; 253 } 254 } 255 256 private final void updateBluetooth() { 257 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 258 int iconId = R.drawable.stat_sys_data_bluetooth; 259 String contentDescription = 260 mContext.getString(R.string.accessibility_bluetooth_disconnected); 261 if (adapter != null) { 262 mBluetoothEnabled = (adapter.getState() == BluetoothAdapter.STATE_ON); 263 if (adapter.getConnectionState() == BluetoothAdapter.STATE_CONNECTED) { 264 iconId = R.drawable.stat_sys_data_bluetooth_connected; 265 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected); 266 } 267 } else { 268 mBluetoothEnabled = false; 269 } 270 271 mService.setIcon(SLOT_BLUETOOTH, iconId, 0, contentDescription); 272 mService.setIconVisibility(SLOT_BLUETOOTH, mBluetoothEnabled); 273 } 274 275 private final void updateTTY(Intent intent) { 276 int currentTtyMode = intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE, 277 TelecomManager.TTY_MODE_OFF); 278 boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF; 279 280 if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled); 281 282 if (enabled) { 283 // TTY is on 284 if (DEBUG) Log.v(TAG, "updateTTY: set TTY on"); 285 mService.setIcon(SLOT_TTY, R.drawable.stat_sys_tty_mode, 0, 286 mContext.getString(R.string.accessibility_tty_enabled)); 287 mService.setIconVisibility(SLOT_TTY, true); 288 } else { 289 // TTY is off 290 if (DEBUG) Log.v(TAG, "updateTTY: set TTY off"); 291 mService.setIconVisibility(SLOT_TTY, false); 292 } 293 } 294 295 private void updateCast() { 296 boolean isCasting = false; 297 for (CastDevice device : mCast.getCastDevices()) { 298 if (device.state == CastDevice.STATE_CONNECTING 299 || device.state == CastDevice.STATE_CONNECTED) { 300 isCasting = true; 301 break; 302 } 303 } 304 if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting); 305 if (isCasting) { 306 mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, 307 mContext.getString(R.string.accessibility_casting)); 308 } 309 mService.setIconVisibility(SLOT_CAST, isCasting); 310 } 311 312 private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() { 313 @Override 314 public void onHotspotChanged(boolean enabled) { 315 mService.setIconVisibility(SLOT_HOTSPOT, enabled); 316 } 317 }; 318 319 private final CastController.Callback mCastCallback = new CastController.Callback() { 320 @Override 321 public void onCastDevicesChanged() { 322 updateCast(); 323 } 324 }; 325} 326