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 17 package com.android.systemui.statusbar.phone; 18 19 import android.app.ActivityManager; 20 import android.app.ActivityTaskManager; 21 import android.app.AlarmManager; 22 import android.app.AlarmManager.AlarmClockInfo; 23 import android.app.SynchronousUserSwitchObserver; 24 import android.content.BroadcastReceiver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.media.AudioManager; 29 import android.os.Handler; 30 import android.os.RemoteException; 31 import android.os.UserHandle; 32 import android.os.UserManager; 33 import android.provider.Settings.Global; 34 import android.service.notification.ZenModeConfig; 35 import android.telecom.TelecomManager; 36 import android.text.format.DateFormat; 37 import android.util.Log; 38 39 import com.android.internal.telephony.IccCardConstants; 40 import com.android.internal.telephony.TelephonyIntents; 41 import com.android.systemui.Dependency; 42 import com.android.systemui.R; 43 import com.android.systemui.SysUiServiceProvider; 44 import com.android.systemui.UiOffloadThread; 45 import com.android.systemui.qs.tiles.DndTile; 46 import com.android.systemui.qs.tiles.RotationLockTile; 47 import com.android.systemui.statusbar.CommandQueue; 48 import com.android.systemui.statusbar.policy.BluetoothController; 49 import com.android.systemui.statusbar.policy.CastController; 50 import com.android.systemui.statusbar.policy.CastController.CastDevice; 51 import com.android.systemui.statusbar.policy.DataSaverController; 52 import com.android.systemui.statusbar.policy.DataSaverController.Listener; 53 import com.android.systemui.statusbar.policy.DeviceProvisionedController; 54 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; 55 import com.android.systemui.statusbar.policy.HotspotController; 56 import com.android.systemui.statusbar.policy.KeyguardMonitor; 57 import com.android.systemui.statusbar.policy.LocationController; 58 import com.android.systemui.statusbar.policy.NextAlarmController; 59 import com.android.systemui.statusbar.policy.RotationLockController; 60 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback; 61 import com.android.systemui.statusbar.policy.SensorPrivacyController; 62 import com.android.systemui.statusbar.policy.UserInfoController; 63 import com.android.systemui.statusbar.policy.ZenModeController; 64 65 import java.util.Locale; 66 67 /** 68 * This class contains all of the policy about which icons are installed in the status bar at boot 69 * time. It goes through the normal API for icons, even though it probably strictly doesn't need to. 70 */ 71 public class PhoneStatusBarPolicy 72 implements BluetoothController.Callback, 73 CommandQueue.Callbacks, 74 RotationLockControllerCallback, 75 Listener, 76 ZenModeController.Callback, 77 DeviceProvisionedListener, 78 KeyguardMonitor.Callback, 79 LocationController.LocationChangeCallback { 80 private static final String TAG = "PhoneStatusBarPolicy"; 81 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 82 83 public static final int LOCATION_STATUS_ICON_ID = 84 com.android.internal.R.drawable.perm_group_location; 85 86 private final String mSlotCast; 87 private final String mSlotHotspot; 88 private final String mSlotBluetooth; 89 private final String mSlotTty; 90 private final String mSlotZen; 91 private final String mSlotVolume; 92 private final String mSlotAlarmClock; 93 private final String mSlotManagedProfile; 94 private final String mSlotRotate; 95 private final String mSlotHeadset; 96 private final String mSlotDataSaver; 97 private final String mSlotLocation; 98 private final String mSlotSensorsOff; 99 100 private final Context mContext; 101 private final Handler mHandler = new Handler(); 102 private final CastController mCast; 103 private final HotspotController mHotspot; 104 private final NextAlarmController mNextAlarmController; 105 private final AlarmManager mAlarmManager; 106 private final UserInfoController mUserInfoController; 107 private final UserManager mUserManager; 108 private final StatusBarIconController mIconController; 109 private final RotationLockController mRotationLockController; 110 private final DataSaverController mDataSaver; 111 private final ZenModeController mZenController; 112 private final DeviceProvisionedController mProvisionedController; 113 private final KeyguardMonitor mKeyguardMonitor; 114 private final LocationController mLocationController; 115 private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class); 116 private final SensorPrivacyController mSensorPrivacyController; 117 118 // Assume it's all good unless we hear otherwise. We don't always seem 119 // to get broadcasts that it *is* there. 120 IccCardConstants.State mSimState = IccCardConstants.State.READY; 121 122 private boolean mZenVisible; 123 private boolean mVolumeVisible; 124 private boolean mCurrentUserSetup; 125 126 private boolean mManagedProfileIconVisible = false; 127 128 private BluetoothController mBluetooth; 129 private AlarmManager.AlarmClockInfo mNextAlarm; 130 PhoneStatusBarPolicy(Context context, StatusBarIconController iconController)131 public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) { 132 mContext = context; 133 mIconController = iconController; 134 mCast = Dependency.get(CastController.class); 135 mHotspot = Dependency.get(HotspotController.class); 136 mBluetooth = Dependency.get(BluetoothController.class); 137 mNextAlarmController = Dependency.get(NextAlarmController.class); 138 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 139 mUserInfoController = Dependency.get(UserInfoController.class); 140 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 141 mRotationLockController = Dependency.get(RotationLockController.class); 142 mDataSaver = Dependency.get(DataSaverController.class); 143 mZenController = Dependency.get(ZenModeController.class); 144 mProvisionedController = Dependency.get(DeviceProvisionedController.class); 145 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class); 146 mLocationController = Dependency.get(LocationController.class); 147 mSensorPrivacyController = Dependency.get(SensorPrivacyController.class); 148 149 mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast); 150 mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot); 151 mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth); 152 mSlotTty = context.getString(com.android.internal.R.string.status_bar_tty); 153 mSlotZen = context.getString(com.android.internal.R.string.status_bar_zen); 154 mSlotVolume = context.getString(com.android.internal.R.string.status_bar_volume); 155 mSlotAlarmClock = context.getString(com.android.internal.R.string.status_bar_alarm_clock); 156 mSlotManagedProfile = context.getString( 157 com.android.internal.R.string.status_bar_managed_profile); 158 mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate); 159 mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset); 160 mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver); 161 mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location); 162 mSlotSensorsOff = context.getString(com.android.internal.R.string.status_bar_sensors_off); 163 164 // listen for broadcasts 165 IntentFilter filter = new IntentFilter(); 166 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 167 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); 168 filter.addAction(AudioManager.ACTION_HEADSET_PLUG); 169 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 170 filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED); 171 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); 172 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); 173 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); 174 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); 175 176 // listen for user / profile change. 177 try { 178 ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG); 179 } catch (RemoteException e) { 180 // Ignore 181 } 182 183 // TTY status 184 updateTTY(); 185 186 // bluetooth status 187 updateBluetooth(); 188 189 // Alarm clock 190 mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null); 191 mIconController.setIconVisibility(mSlotAlarmClock, false); 192 193 // zen 194 mIconController.setIcon(mSlotZen, R.drawable.stat_sys_dnd, null); 195 mIconController.setIconVisibility(mSlotZen, false); 196 197 // volume 198 mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null); 199 mIconController.setIconVisibility(mSlotVolume, false); 200 updateVolumeZen(); 201 202 // cast 203 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null); 204 mIconController.setIconVisibility(mSlotCast, false); 205 206 // hotspot 207 mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot, 208 mContext.getString(R.string.accessibility_status_bar_hotspot)); 209 mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled()); 210 211 // managed profile 212 mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status, 213 mContext.getString(R.string.accessibility_managed_profile)); 214 mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible); 215 216 // data saver 217 mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver, 218 context.getString(R.string.accessibility_data_saver_on)); 219 mIconController.setIconVisibility(mSlotDataSaver, false); 220 221 mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID, 222 mContext.getString(R.string.accessibility_location_active)); 223 mIconController.setIconVisibility(mSlotLocation, false); 224 225 // sensors off 226 mIconController.setIcon(mSlotSensorsOff, R.drawable.stat_sys_sensors_off, 227 mContext.getString(R.string.accessibility_sensors_off_active)); 228 mIconController.setIconVisibility(mSlotSensorsOff, 229 mSensorPrivacyController.isSensorPrivacyEnabled()); 230 231 mRotationLockController.addCallback(this); 232 mBluetooth.addCallback(this); 233 mProvisionedController.addCallback(this); 234 mZenController.addCallback(this); 235 mCast.addCallback(mCastCallback); 236 mHotspot.addCallback(mHotspotCallback); 237 mNextAlarmController.addCallback(mNextAlarmCallback); 238 mDataSaver.addCallback(this); 239 mKeyguardMonitor.addCallback(this); 240 mSensorPrivacyController.addCallback(mSensorPrivacyListener); 241 mLocationController.addCallback(this); 242 243 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this); 244 } 245 246 @Override onZenChanged(int zen)247 public void onZenChanged(int zen) { 248 updateVolumeZen(); 249 } 250 251 @Override onConfigChanged(ZenModeConfig config)252 public void onConfigChanged(ZenModeConfig config) { 253 updateVolumeZen(); 254 } 255 updateAlarm()256 private void updateAlarm() { 257 final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT); 258 final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0; 259 int zen = mZenController.getZen(); 260 final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS; 261 mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim 262 : R.drawable.stat_sys_alarm, buildAlarmContentDescription()); 263 mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm); 264 } 265 buildAlarmContentDescription()266 private String buildAlarmContentDescription() { 267 if (mNextAlarm == null) { 268 return mContext.getString(R.string.status_bar_alarm); 269 } 270 return formatNextAlarm(mNextAlarm, mContext); 271 } 272 formatNextAlarm(AlarmManager.AlarmClockInfo info, Context context)273 private static String formatNextAlarm(AlarmManager.AlarmClockInfo info, Context context) { 274 if (info == null) { 275 return ""; 276 } 277 String skeleton = DateFormat.is24HourFormat( 278 context, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma"; 279 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); 280 String dateString = DateFormat.format(pattern, info.getTriggerTime()).toString(); 281 282 return context.getString(R.string.accessibility_quick_settings_alarm, dateString); 283 } 284 updateSimState(Intent intent)285 private final void updateSimState(Intent intent) { 286 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 287 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { 288 mSimState = IccCardConstants.State.ABSENT; 289 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) { 290 mSimState = IccCardConstants.State.CARD_IO_ERROR; 291 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(stateExtra)) { 292 mSimState = IccCardConstants.State.CARD_RESTRICTED; 293 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { 294 mSimState = IccCardConstants.State.READY; 295 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { 296 final String lockedReason = 297 intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); 298 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { 299 mSimState = IccCardConstants.State.PIN_REQUIRED; 300 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { 301 mSimState = IccCardConstants.State.PUK_REQUIRED; 302 } else { 303 mSimState = IccCardConstants.State.NETWORK_LOCKED; 304 } 305 } else { 306 mSimState = IccCardConstants.State.UNKNOWN; 307 } 308 } 309 updateVolumeZen()310 private final void updateVolumeZen() { 311 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 312 313 boolean zenVisible = false; 314 int zenIconId = 0; 315 String zenDescription = null; 316 317 boolean volumeVisible = false; 318 int volumeIconId = 0; 319 String volumeDescription = null; 320 int zen = mZenController.getZen(); 321 322 if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) { 323 zenVisible = zen != Global.ZEN_MODE_OFF; 324 zenIconId = R.drawable.stat_sys_dnd; 325 zenDescription = mContext.getString(R.string.quick_settings_dnd_label); 326 } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) { 327 zenVisible = true; 328 zenIconId = R.drawable.stat_sys_dnd; 329 zenDescription = mContext.getString(R.string.interruption_level_none); 330 } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { 331 zenVisible = true; 332 zenIconId = R.drawable.stat_sys_dnd; 333 zenDescription = mContext.getString(R.string.interruption_level_priority); 334 } 335 336 if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConsolidatedPolicy())) { 337 if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) { 338 volumeVisible = true; 339 volumeIconId = R.drawable.stat_sys_ringer_vibrate; 340 volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate); 341 } else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) { 342 volumeVisible = true; 343 volumeIconId = R.drawable.stat_sys_ringer_silent; 344 volumeDescription = mContext.getString(R.string.accessibility_ringer_silent); 345 } 346 } 347 348 if (zenVisible) { 349 mIconController.setIcon(mSlotZen, zenIconId, zenDescription); 350 } 351 if (zenVisible != mZenVisible) { 352 mIconController.setIconVisibility(mSlotZen, zenVisible); 353 mZenVisible = zenVisible; 354 } 355 356 if (volumeVisible) { 357 mIconController.setIcon(mSlotVolume, volumeIconId, volumeDescription); 358 } 359 if (volumeVisible != mVolumeVisible) { 360 mIconController.setIconVisibility(mSlotVolume, volumeVisible); 361 mVolumeVisible = volumeVisible; 362 } 363 updateAlarm(); 364 } 365 366 @Override onBluetoothDevicesChanged()367 public void onBluetoothDevicesChanged() { 368 updateBluetooth(); 369 } 370 371 @Override onBluetoothStateChange(boolean enabled)372 public void onBluetoothStateChange(boolean enabled) { 373 updateBluetooth(); 374 } 375 updateBluetooth()376 private final void updateBluetooth() { 377 int iconId = R.drawable.stat_sys_data_bluetooth_connected; 378 String contentDescription = 379 mContext.getString(R.string.accessibility_quick_settings_bluetooth_on); 380 boolean bluetoothVisible = false; 381 if (mBluetooth != null) { 382 if (mBluetooth.isBluetoothConnected() 383 && (mBluetooth.isBluetoothAudioActive() 384 || !mBluetooth.isBluetoothAudioProfileOnly())) { 385 contentDescription = mContext.getString( 386 R.string.accessibility_bluetooth_connected); 387 bluetoothVisible = mBluetooth.isBluetoothEnabled(); 388 } 389 } 390 391 mIconController.setIcon(mSlotBluetooth, iconId, contentDescription); 392 mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible); 393 } 394 updateTTY()395 private final void updateTTY() { 396 TelecomManager telecomManager = 397 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 398 if (telecomManager == null) { 399 updateTTY(TelecomManager.TTY_MODE_OFF); 400 } else { 401 updateTTY(telecomManager.getCurrentTtyMode()); 402 } 403 } 404 updateTTY(int currentTtyMode)405 private final void updateTTY(int currentTtyMode) { 406 boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF; 407 408 if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled); 409 410 if (enabled) { 411 // TTY is on 412 if (DEBUG) Log.v(TAG, "updateTTY: set TTY on"); 413 mIconController.setIcon(mSlotTty, R.drawable.stat_sys_tty_mode, 414 mContext.getString(R.string.accessibility_tty_enabled)); 415 mIconController.setIconVisibility(mSlotTty, true); 416 } else { 417 // TTY is off 418 if (DEBUG) Log.v(TAG, "updateTTY: set TTY off"); 419 mIconController.setIconVisibility(mSlotTty, false); 420 } 421 } 422 updateCast()423 private void updateCast() { 424 boolean isCasting = false; 425 for (CastDevice device : mCast.getCastDevices()) { 426 if (device.state == CastDevice.STATE_CONNECTING 427 || device.state == CastDevice.STATE_CONNECTED) { 428 isCasting = true; 429 break; 430 } 431 } 432 if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting); 433 mHandler.removeCallbacks(mRemoveCastIconRunnable); 434 if (isCasting) { 435 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, 436 mContext.getString(R.string.accessibility_casting)); 437 mIconController.setIconVisibility(mSlotCast, true); 438 } else { 439 // don't turn off the screen-record icon for a few seconds, just to make sure the user 440 // has seen it 441 if (DEBUG) Log.v(TAG, "updateCast: hiding icon in 3 sec..."); 442 mHandler.postDelayed(mRemoveCastIconRunnable, 3000); 443 } 444 } 445 updateManagedProfile()446 private void updateManagedProfile() { 447 // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in 448 // some cases. Since it doesn't really matter here whether it's updated in this frame 449 // or in the next one, we call this method from our UI offload thread. 450 mUiOffloadThread.submit(() -> { 451 final int userId; 452 try { 453 userId = ActivityTaskManager.getService().getLastResumedActivityUserId(); 454 boolean isManagedProfile = mUserManager.isManagedProfile(userId); 455 mHandler.post(() -> { 456 final boolean showIcon; 457 if (isManagedProfile && 458 (!mKeyguardMonitor.isShowing() || mKeyguardMonitor.isOccluded())) { 459 showIcon = true; 460 mIconController.setIcon(mSlotManagedProfile, 461 R.drawable.stat_sys_managed_profile_status, 462 mContext.getString(R.string.accessibility_managed_profile)); 463 } else { 464 showIcon = false; 465 } 466 if (mManagedProfileIconVisible != showIcon) { 467 mIconController.setIconVisibility(mSlotManagedProfile, showIcon); 468 mManagedProfileIconVisible = showIcon; 469 } 470 }); 471 } catch (RemoteException e) { 472 Log.w(TAG, "updateManagedProfile: ", e); 473 } 474 }); 475 } 476 477 private final SynchronousUserSwitchObserver mUserSwitchListener = 478 new SynchronousUserSwitchObserver() { 479 @Override 480 public void onUserSwitching(int newUserId) throws RemoteException { 481 mHandler.post(() -> mUserInfoController.reloadUserInfo()); 482 } 483 484 @Override 485 public void onUserSwitchComplete(int newUserId) throws RemoteException { 486 mHandler.post(() -> { 487 updateAlarm(); 488 updateManagedProfile(); 489 }); 490 } 491 }; 492 493 private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() { 494 @Override 495 public void onHotspotChanged(boolean enabled, int numDevices) { 496 mIconController.setIconVisibility(mSlotHotspot, enabled); 497 } 498 }; 499 500 private final CastController.Callback mCastCallback = new CastController.Callback() { 501 @Override 502 public void onCastDevicesChanged() { 503 updateCast(); 504 } 505 }; 506 507 private final NextAlarmController.NextAlarmChangeCallback mNextAlarmCallback = 508 new NextAlarmController.NextAlarmChangeCallback() { 509 @Override 510 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) { 511 mNextAlarm = nextAlarm; 512 updateAlarm(); 513 } 514 }; 515 516 private final SensorPrivacyController.OnSensorPrivacyChangedListener mSensorPrivacyListener = 517 new SensorPrivacyController.OnSensorPrivacyChangedListener() { 518 @Override 519 public void onSensorPrivacyChanged(boolean enabled) { 520 mHandler.post(() -> { 521 mIconController.setIconVisibility(mSlotSensorsOff, enabled); 522 }); 523 } 524 }; 525 526 @Override appTransitionStarting(int displayId, long startTime, long duration, boolean forced)527 public void appTransitionStarting(int displayId, long startTime, long duration, 528 boolean forced) { 529 if (mContext.getDisplayId() == displayId) { 530 updateManagedProfile(); 531 } 532 } 533 534 @Override onKeyguardShowingChanged()535 public void onKeyguardShowingChanged() { 536 updateManagedProfile(); 537 } 538 539 @Override onUserSetupChanged()540 public void onUserSetupChanged() { 541 boolean userSetup = mProvisionedController.isUserSetup( 542 mProvisionedController.getCurrentUser()); 543 if (mCurrentUserSetup == userSetup) return; 544 mCurrentUserSetup = userSetup; 545 updateAlarm(); 546 } 547 548 @Override onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible)549 public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) { 550 boolean portrait = RotationLockTile.isCurrentOrientationLockPortrait( 551 mRotationLockController, mContext); 552 if (rotationLocked) { 553 if (portrait) { 554 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_portrait, 555 mContext.getString(R.string.accessibility_rotation_lock_on_portrait)); 556 } else { 557 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape, 558 mContext.getString(R.string.accessibility_rotation_lock_on_landscape)); 559 } 560 mIconController.setIconVisibility(mSlotRotate, true); 561 } else { 562 mIconController.setIconVisibility(mSlotRotate, false); 563 } 564 } 565 updateHeadsetPlug(Intent intent)566 private void updateHeadsetPlug(Intent intent) { 567 boolean connected = intent.getIntExtra("state", 0) != 0; 568 boolean hasMic = intent.getIntExtra("microphone", 0) != 0; 569 if (connected) { 570 String contentDescription = mContext.getString(hasMic 571 ? R.string.accessibility_status_bar_headset 572 : R.string.accessibility_status_bar_headphones); 573 mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.stat_sys_headset_mic 574 : R.drawable.stat_sys_headset, contentDescription); 575 mIconController.setIconVisibility(mSlotHeadset, true); 576 } else { 577 mIconController.setIconVisibility(mSlotHeadset, false); 578 } 579 } 580 581 @Override onDataSaverChanged(boolean isDataSaving)582 public void onDataSaverChanged(boolean isDataSaving) { 583 mIconController.setIconVisibility(mSlotDataSaver, isDataSaving); 584 } 585 586 @Override onLocationActiveChanged(boolean active)587 public void onLocationActiveChanged(boolean active) { 588 updateLocation(); 589 } 590 591 // Updates the status view based on the current state of location requests. updateLocation()592 private void updateLocation() { 593 if (mLocationController.isLocationActive()) { 594 mIconController.setIconVisibility(mSlotLocation, true); 595 } else { 596 mIconController.setIconVisibility(mSlotLocation, false); 597 } 598 } 599 600 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 601 @Override 602 public void onReceive(Context context, Intent intent) { 603 String action = intent.getAction(); 604 switch (action) { 605 case AudioManager.RINGER_MODE_CHANGED_ACTION: 606 case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION: 607 updateVolumeZen(); 608 break; 609 case TelephonyIntents.ACTION_SIM_STATE_CHANGED: 610 // Avoid rebroadcast because SysUI is direct boot aware. 611 if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) { 612 break; 613 } 614 updateSimState(intent); 615 break; 616 case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED: 617 updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE, 618 TelecomManager.TTY_MODE_OFF)); 619 break; 620 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE: 621 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE: 622 case Intent.ACTION_MANAGED_PROFILE_REMOVED: 623 updateManagedProfile(); 624 break; 625 case AudioManager.ACTION_HEADSET_PLUG: 626 updateHeadsetPlug(intent); 627 break; 628 } 629 } 630 }; 631 632 private Runnable mRemoveCastIconRunnable = new Runnable() { 633 @Override 634 public void run() { 635 if (DEBUG) Log.v(TAG, "updateCast: hiding icon NOW"); 636 mIconController.setIconVisibility(mSlotCast, false); 637 } 638 }; 639 } 640