blob: 4a86484393a96e606683564e7acd30b05cc88272 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Joe Onoratofd52b182010-11-10 18:00:52 -080017package com.android.systemui.statusbar.phone;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Jason Monk697b82a2017-04-19 18:41:06 -040019import android.app.ActivityManager;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070020import android.app.ActivityTaskManager;
Jason Monk697b82a2017-04-19 18:41:06 -040021import android.app.AlarmManager;
John Spurlock604a5ee2015-06-01 12:27:22 -040022import android.app.AlarmManager.AlarmClockInfo;
Jason Monk697b82a2017-04-19 18:41:06 -040023import android.app.SynchronousUserSwitchObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.BroadcastReceiver;
25import android.content.Context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.content.Intent;
27import android.content.IntentFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.media.AudioManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.Handler;
Kenny Guy3094d4a2015-04-01 19:14:10 +010030import android.os.RemoteException;
Adrian Roosc42a1e12014-07-07 23:35:53 +020031import android.os.UserHandle;
Kenny Guy3094d4a2015-04-01 19:14:10 +010032import android.os.UserManager;
John Spurlockae641c92014-06-30 18:11:40 -040033import android.provider.Settings.Global;
Beverlyb9826dd2018-04-12 15:02:45 -040034import android.service.notification.ZenModeConfig;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070035import android.telecom.TelecomManager;
Evan Lairdbee3eb82018-05-16 15:58:49 -040036import android.text.format.DateFormat;
John Spurlockcd686b52013-06-05 10:13:46 -040037import android.util.Log;
Beverlyff2df9b2018-10-10 16:54:10 -040038
Wink Savillea639b312012-07-10 12:37:54 -070039import com.android.internal.telephony.IccCardConstants;
Wink Saville04e71b32009-04-02 11:00:54 -070040import com.android.internal.telephony.TelephonyIntents;
Jason Monk9c7844c2017-01-18 15:21:53 -050041import com.android.systemui.Dependency;
Joe Onorato798ac4c2010-05-27 16:39:00 -040042import com.android.systemui.R;
Jason Monkaa573e92017-01-27 17:00:29 -050043import com.android.systemui.SysUiServiceProvider;
Jorim Jaggifabc7432017-05-15 02:40:05 +020044import com.android.systemui.UiOffloadThread;
Evan Lairdcf1a1032018-11-14 13:46:08 -050045import com.android.systemui.privacy.PrivacyItem;
46import com.android.systemui.privacy.PrivacyItemController;
John Spurlock3c4076a2015-02-24 12:12:25 -050047import com.android.systemui.qs.tiles.DndTile;
Jason Monk3e189872016-01-12 09:10:34 -050048import com.android.systemui.qs.tiles.RotationLockTile;
Jason Monkaa573e92017-01-27 17:00:29 -050049import com.android.systemui.statusbar.CommandQueue;
Jason Monk70364362015-08-06 16:32:18 -040050import com.android.systemui.statusbar.policy.BluetoothController;
John Spurlock96fe98d2014-08-27 09:36:02 -040051import com.android.systemui.statusbar.policy.CastController;
52import com.android.systemui.statusbar.policy.CastController.CastDevice;
Jason Monkf23aa992016-01-22 16:45:21 -050053import com.android.systemui.statusbar.policy.DataSaverController;
Jason Monkaa573e92017-01-27 17:00:29 -050054import com.android.systemui.statusbar.policy.DataSaverController.Listener;
55import com.android.systemui.statusbar.policy.DeviceProvisionedController;
56import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Jason Monk952d5d82014-10-27 15:28:22 -040057import com.android.systemui.statusbar.policy.HotspotController;
Jason Monkaa573e92017-01-27 17:00:29 -050058import com.android.systemui.statusbar.policy.KeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -040059import com.android.systemui.statusbar.policy.LocationController;
Juan Flores2ff37202015-04-30 13:44:23 +020060import com.android.systemui.statusbar.policy.NextAlarmController;
Jason Monk3e189872016-01-12 09:10:34 -050061import com.android.systemui.statusbar.policy.RotationLockController;
Jason Monkaa573e92017-01-27 17:00:29 -050062import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
Adrian Roos88b11932015-07-22 14:59:48 -070063import com.android.systemui.statusbar.policy.UserInfoController;
Jason Monkaa573e92017-01-27 17:00:29 -050064import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monk324b8862017-02-16 17:19:12 -050065
Fabian Kozynskia6ff80b2019-02-12 11:32:44 -050066import java.io.PrintWriter;
67import java.io.StringWriter;
Jason Monk697b82a2017-04-19 18:41:06 -040068import java.util.List;
Evan Lairdbee3eb82018-05-16 15:58:49 -040069import java.util.Locale;
Jason Monk697b82a2017-04-19 18:41:06 -040070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071/**
yoshiki iguchi69d65852019-02-13 18:07:41 +090072 * This class contains all of the policy about which icons are installed in the status bar at boot
73 * time. It goes through the normal API for icons, even though it probably strictly doesn't need to.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 */
yoshiki iguchi69d65852019-02-13 18:07:41 +090075public class PhoneStatusBarPolicy
76 implements BluetoothController.Callback,
77 CommandQueue.Callbacks,
78 RotationLockControllerCallback,
79 Listener,
80 ZenModeController.Callback,
81 DeviceProvisionedListener,
82 KeyguardMonitor.Callback,
83 PrivacyItemController.Callback {
Joe Onoratofd52b182010-11-10 18:00:52 -080084 private static final String TAG = "PhoneStatusBarPolicy";
John Spurlocka37e9c82014-07-08 09:40:31 -040085 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -070086
Jason Monk359bb742017-04-13 10:40:40 -040087 public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
88
Jason Monk3e189872016-01-12 09:10:34 -050089 private final String mSlotCast;
90 private final String mSlotHotspot;
91 private final String mSlotBluetooth;
92 private final String mSlotTty;
93 private final String mSlotZen;
94 private final String mSlotVolume;
95 private final String mSlotAlarmClock;
96 private final String mSlotManagedProfile;
97 private final String mSlotRotate;
98 private final String mSlotHeadset;
Jason Monkf23aa992016-01-22 16:45:21 -050099 private final String mSlotDataSaver;
Jason Monk359bb742017-04-13 10:40:40 -0400100 private final String mSlotLocation;
Evan Lairdcf1a1032018-11-14 13:46:08 -0500101 private final String mSlotMicrophone;
102 private final String mSlotCamera;
John Spurlocka37e9c82014-07-08 09:40:31 -0400103
Dianne Hackborn4840e142009-03-24 22:40:29 -0700104 private final Context mContext;
Joe Onorato10523b4d2010-10-25 10:42:46 -0700105 private final Handler mHandler = new Handler();
John Spurlock96fe98d2014-08-27 09:36:02 -0400106 private final CastController mCast;
Jason Monk952d5d82014-10-27 15:28:22 -0400107 private final HotspotController mHotspot;
Evan Lairdbee3eb82018-05-16 15:58:49 -0400108 private final NextAlarmController mNextAlarmController;
John Spurlock15782262015-05-29 15:35:53 -0400109 private final AlarmManager mAlarmManager;
Adrian Roos88b11932015-07-22 14:59:48 -0700110 private final UserInfoController mUserInfoController;
Rubin Xu1205fb12015-11-04 17:45:03 +0000111 private final UserManager mUserManager;
Jason Monk07473ce2016-01-05 14:59:19 -0500112 private final StatusBarIconController mIconController;
Jason Monk3e189872016-01-12 09:10:34 -0500113 private final RotationLockController mRotationLockController;
Jason Monkf23aa992016-01-22 16:45:21 -0500114 private final DataSaverController mDataSaver;
Jason Monkaa573e92017-01-27 17:00:29 -0500115 private final ZenModeController mZenController;
116 private final DeviceProvisionedController mProvisionedController;
117 private final KeyguardMonitor mKeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -0400118 private final LocationController mLocationController;
Evan Lairdcf1a1032018-11-14 13:46:08 -0500119 private final PrivacyItemController mPrivacyItemController;
Jorim Jaggifabc7432017-05-15 02:40:05 +0200120 private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 // Assume it's all good unless we hear otherwise. We don't always seem
123 // to get broadcasts that it *is* there.
Wink Savillea639b312012-07-10 12:37:54 -0700124 IccCardConstants.State mSimState = IccCardConstants.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125
John Spurlocka37e9c82014-07-08 09:40:31 -0400126 private boolean mZenVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 private boolean mVolumeVisible;
John Spurlock604a5ee2015-06-01 12:27:22 -0400128 private boolean mCurrentUserSetup;
Wink Saville04e71b32009-04-02 11:00:54 -0700129
Rubin Xu1205fb12015-11-04 17:45:03 +0000130 private boolean mManagedProfileIconVisible = false;
Kenny Guy3094d4a2015-04-01 19:14:10 +0100131
Jason Monk70364362015-08-06 16:32:18 -0400132 private BluetoothController mBluetooth;
Evan Lairdbee3eb82018-05-16 15:58:49 -0400133 private AlarmManager.AlarmClockInfo mNextAlarm;
Wink Savillee9b06d72009-05-18 21:47:50 -0700134
Jason Monk9c7844c2017-01-18 15:21:53 -0500135 public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 mContext = context;
Jason Monk07473ce2016-01-05 14:59:19 -0500137 mIconController = iconController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500138 mCast = Dependency.get(CastController.class);
139 mHotspot = Dependency.get(HotspotController.class);
140 mBluetooth = Dependency.get(BluetoothController.class);
Evan Lairdbee3eb82018-05-16 15:58:49 -0400141 mNextAlarmController = Dependency.get(NextAlarmController.class);
John Spurlock15782262015-05-29 15:35:53 -0400142 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500143 mUserInfoController = Dependency.get(UserInfoController.class);
Rubin Xu1205fb12015-11-04 17:45:03 +0000144 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500145 mRotationLockController = Dependency.get(RotationLockController.class);
146 mDataSaver = Dependency.get(DataSaverController.class);
Jason Monkaa573e92017-01-27 17:00:29 -0500147 mZenController = Dependency.get(ZenModeController.class);
148 mProvisionedController = Dependency.get(DeviceProvisionedController.class);
149 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
Jason Monk359bb742017-04-13 10:40:40 -0400150 mLocationController = Dependency.get(LocationController.class);
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500151 mPrivacyItemController = Dependency.get(PrivacyItemController.class);
Jason Monk3e189872016-01-12 09:10:34 -0500152
153 mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
154 mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
155 mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth);
156 mSlotTty = context.getString(com.android.internal.R.string.status_bar_tty);
157 mSlotZen = context.getString(com.android.internal.R.string.status_bar_zen);
158 mSlotVolume = context.getString(com.android.internal.R.string.status_bar_volume);
159 mSlotAlarmClock = context.getString(com.android.internal.R.string.status_bar_alarm_clock);
160 mSlotManagedProfile = context.getString(
161 com.android.internal.R.string.status_bar_managed_profile);
162 mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
163 mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
Jason Monkf23aa992016-01-22 16:45:21 -0500164 mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
Jason Monk359bb742017-04-13 10:40:40 -0400165 mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
Evan Lairdcf1a1032018-11-14 13:46:08 -0500166 mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone);
167 mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400169 // listen for broadcasts
170 IntentFilter filter = new IntentFilter();
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400171 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
John Spurlockbcc10872014-11-28 15:29:21 -0500172 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
Jason Monk3e189872016-01-12 09:10:34 -0500173 filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400174 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700175 filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
Rubin Xue95057a2016-04-01 16:49:25 +0100176 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
177 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
Nicolas Prevot6c7b8742016-04-13 10:28:58 +0100178 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400179 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
180
Kenny Guy3094d4a2015-04-01 19:14:10 +0100181 // listen for user / profile change.
182 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800183 ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
Kenny Guy3094d4a2015-04-01 19:14:10 +0100184 } catch (RemoteException e) {
185 // Ignore
186 }
187
Wink Saville04e71b32009-04-02 11:00:54 -0700188 // TTY status
Hall Liu108ca202017-07-24 15:19:04 -0700189 updateTTY();
Wink Saville04e71b32009-04-02 11:00:54 -0700190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 // bluetooth status
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700192 updateBluetooth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 // Alarm clock
Jason Monk3e189872016-01-12 09:10:34 -0500195 mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
196 mIconController.setIconVisibility(mSlotAlarmClock, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197
John Spurlocka37e9c82014-07-08 09:40:31 -0400198 // zen
Jason Monk3e189872016-01-12 09:10:34 -0500199 mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
200 mIconController.setIconVisibility(mSlotZen, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 // volume
Jason Monk3e189872016-01-12 09:10:34 -0500203 mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);
204 mIconController.setIconVisibility(mSlotVolume, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400205 updateVolumeZen();
John Spurlock96fe98d2014-08-27 09:36:02 -0400206
207 // cast
Jason Monk3e189872016-01-12 09:10:34 -0500208 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
209 mIconController.setIconVisibility(mSlotCast, false);
Jason Monk952d5d82014-10-27 15:28:22 -0400210
211 // hotspot
Jason Monk3e189872016-01-12 09:10:34 -0500212 mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
Jason Monk08187a42015-06-09 14:33:51 -0400213 mContext.getString(R.string.accessibility_status_bar_hotspot));
Jason Monk3e189872016-01-12 09:10:34 -0500214 mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100215
216 // managed profile
Jason Monk3e189872016-01-12 09:10:34 -0500217 mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
Adrian Roos1b5eb972015-06-11 18:22:52 -0700218 mContext.getString(R.string.accessibility_managed_profile));
Jason Monk3e189872016-01-12 09:10:34 -0500219 mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);
Jason Monkf23aa992016-01-22 16:45:21 -0500220
221 // data saver
222 mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
223 context.getString(R.string.accessibility_data_saver_on));
224 mIconController.setIconVisibility(mSlotDataSaver, false);
Jason Monkaa573e92017-01-27 17:00:29 -0500225
Evan Lairdcf1a1032018-11-14 13:46:08 -0500226 // privacy items
227 mIconController.setIcon(mSlotMicrophone, R.drawable.stat_sys_mic_none, null);
228 mIconController.setIconVisibility(mSlotMicrophone, false);
229 mIconController.setIcon(mSlotCamera, R.drawable.stat_sys_camera, null);
230 mIconController.setIconVisibility(mSlotCamera, false);
Fabian Kozynskied5dfd92018-12-20 15:00:48 -0500231 mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
232 mContext.getString(R.string.accessibility_location_active));
233 mIconController.setIconVisibility(mSlotLocation, false);
Evan Lairdcf1a1032018-11-14 13:46:08 -0500234
Jason Monkaa573e92017-01-27 17:00:29 -0500235 mRotationLockController.addCallback(this);
236 mBluetooth.addCallback(this);
237 mProvisionedController.addCallback(this);
238 mZenController.addCallback(this);
239 mCast.addCallback(mCastCallback);
240 mHotspot.addCallback(mHotspotCallback);
Evan Lairdbee3eb82018-05-16 15:58:49 -0400241 mNextAlarmController.addCallback(mNextAlarmCallback);
Jason Monk88529052016-11-04 13:29:58 -0400242 mDataSaver.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500243 mKeyguardMonitor.addCallback(this);
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500244 mPrivacyItemController.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500245
Jason Monkd7c98552018-12-04 11:14:50 -0500246 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 }
248
Jason Monkaa573e92017-01-27 17:00:29 -0500249 @Override
250 public void onZenChanged(int zen) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400251 updateVolumeZen();
John Spurlockba2c6a02014-05-19 09:44:06 -0400252 }
253
Jason Monk359bb742017-04-13 10:40:40 -0400254 @Override
Beverlyb9826dd2018-04-12 15:02:45 -0400255 public void onConfigChanged(ZenModeConfig config) {
256 updateVolumeZen();
257 }
258
Adrian Roosc42a1e12014-07-07 23:35:53 +0200259 private void updateAlarm() {
John Spurlock604a5ee2015-06-01 12:27:22 -0400260 final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
261 final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
Jason Monk20c0eb42017-03-02 17:35:49 -0500262 int zen = mZenController.getZen();
263 final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
Jason Monk3e189872016-01-12 09:10:34 -0500264 mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
Evan Lairdbee3eb82018-05-16 15:58:49 -0400265 : R.drawable.stat_sys_alarm, buildAlarmContentDescription());
Jason Monk3e189872016-01-12 09:10:34 -0500266 mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 }
268
Evan Lairdbee3eb82018-05-16 15:58:49 -0400269 private String buildAlarmContentDescription() {
270 if (mNextAlarm == null) {
271 return mContext.getString(R.string.status_bar_alarm);
272 }
273 return formatNextAlarm(mNextAlarm, mContext);
274 }
275
276 private static String formatNextAlarm(AlarmManager.AlarmClockInfo info, Context context) {
277 if (info == null) {
278 return "";
279 }
280 String skeleton = DateFormat.is24HourFormat(
281 context, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma";
282 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
283 String dateString = DateFormat.format(pattern, info.getTriggerTime()).toString();
284
285 return context.getString(R.string.accessibility_quick_settings_alarm, dateString);
286 }
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 private final void updateSimState(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700289 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
290 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
291 mSimState = IccCardConstants.State.ABSENT;
Jason Monk07473ce2016-01-05 14:59:19 -0500292 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
Rakesh Pallerlaf099a5f2013-02-06 11:44:23 +0530293 mSimState = IccCardConstants.State.CARD_IO_ERROR;
Junda Liua2f6a672016-05-24 10:07:40 -0700294 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(stateExtra)) {
295 mSimState = IccCardConstants.State.CARD_RESTRICTED;
Jason Monk07473ce2016-01-05 14:59:19 -0500296 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700297 mSimState = IccCardConstants.State.READY;
Jason Monk07473ce2016-01-05 14:59:19 -0500298 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700299 final String lockedReason =
300 intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
301 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
302 mSimState = IccCardConstants.State.PIN_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500303 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700304 mSimState = IccCardConstants.State.PUK_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500305 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700306 mSimState = IccCardConstants.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 }
308 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700309 mSimState = IccCardConstants.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 }
312
John Spurlockbcc10872014-11-28 15:29:21 -0500313 private final void updateVolumeZen() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
John Spurlocka37e9c82014-07-08 09:40:31 -0400315
316 boolean zenVisible = false;
317 int zenIconId = 0;
318 String zenDescription = null;
319
320 boolean volumeVisible = false;
321 int volumeIconId = 0;
322 String volumeDescription = null;
Jason Monk20c0eb42017-03-02 17:35:49 -0500323 int zen = mZenController.getZen();
John Spurlocka37e9c82014-07-08 09:40:31 -0400324
John Spurlockf88d8082015-03-25 18:09:51 -0400325 if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
Jason Monk20c0eb42017-03-02 17:35:49 -0500326 zenVisible = zen != Global.ZEN_MODE_OFF;
Evan Lairda9adbd52018-05-16 11:32:08 -0400327 zenIconId = R.drawable.stat_sys_dnd;
John Spurlock3c4076a2015-02-24 12:12:25 -0500328 zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
Jason Monk20c0eb42017-03-02 17:35:49 -0500329 } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400330 zenVisible = true;
331 zenIconId = R.drawable.stat_sys_zen_none;
John Spurlockd9c75db2015-04-28 11:19:13 -0400332 zenDescription = mContext.getString(R.string.interruption_level_none);
Jason Monk20c0eb42017-03-02 17:35:49 -0500333 } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400334 zenVisible = true;
335 zenIconId = R.drawable.stat_sys_zen_important;
John Spurlockd9c75db2015-04-28 11:19:13 -0400336 zenDescription = mContext.getString(R.string.interruption_level_priority);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338
Beverlyff2df9b2018-10-10 16:54:10 -0400339 if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConsolidatedPolicy())) {
Beverlyb9826dd2018-04-12 15:02:45 -0400340 if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
341 volumeVisible = true;
342 volumeIconId = R.drawable.stat_sys_ringer_vibrate;
343 volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
344 } else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
345 volumeVisible = true;
346 volumeIconId = R.drawable.stat_sys_ringer_silent;
347 volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 }
John Spurlocka37e9c82014-07-08 09:40:31 -0400350
351 if (zenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500352 mIconController.setIcon(mSlotZen, zenIconId, zenDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400353 }
354 if (zenVisible != mZenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500355 mIconController.setIconVisibility(mSlotZen, zenVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400356 mZenVisible = zenVisible;
357 }
358
359 if (volumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500360 mIconController.setIcon(mSlotVolume, volumeIconId, volumeDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400361 }
362 if (volumeVisible != mVolumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500363 mIconController.setIconVisibility(mSlotVolume, volumeVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400364 mVolumeVisible = volumeVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 }
John Spurlock15782262015-05-29 15:35:53 -0400366 updateAlarm();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 }
368
Jason Monk70364362015-08-06 16:32:18 -0400369 @Override
370 public void onBluetoothDevicesChanged() {
371 updateBluetooth();
372 }
373
374 @Override
375 public void onBluetoothStateChange(boolean enabled) {
376 updateBluetooth();
377 }
378
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700379 private final void updateBluetooth() {
Joe Onorato798ac4c2010-05-27 16:39:00 -0400380 int iconId = R.drawable.stat_sys_data_bluetooth;
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700381 String contentDescription =
Jason Monk1aa32822015-07-14 16:10:32 -0400382 mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500383 boolean bluetoothVisible = false;
Jason Monk70364362015-08-06 16:32:18 -0400384 if (mBluetooth != null) {
Jason Monk70364362015-08-06 16:32:18 -0400385 if (mBluetooth.isBluetoothConnected()) {
Jaikumar Ganeshd9bb6882010-09-27 17:05:24 -0700386 iconId = R.drawable.stat_sys_data_bluetooth_connected;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700387 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500388 bluetoothVisible = mBluetooth.isBluetoothEnabled();
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700391
Jason Monk3e189872016-01-12 09:10:34 -0500392 mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500393 mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 }
395
Hall Liu108ca202017-07-24 15:19:04 -0700396 private final void updateTTY() {
397 TelecomManager telecomManager =
398 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
399 if (telecomManager == null) {
400 updateTTY(TelecomManager.TTY_MODE_OFF);
401 } else {
402 updateTTY(telecomManager.getCurrentTtyMode());
403 }
404 }
405
406 private final void updateTTY(int currentTtyMode) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700407 boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF;
Wink Saville04e71b32009-04-02 11:00:54 -0700408
John Spurlocka37e9c82014-07-08 09:40:31 -0400409 if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -0700410
411 if (enabled) {
412 // TTY is on
John Spurlocka37e9c82014-07-08 09:40:31 -0400413 if (DEBUG) Log.v(TAG, "updateTTY: set TTY on");
Jason Monk3e189872016-01-12 09:10:34 -0500414 mIconController.setIcon(mSlotTty, R.drawable.stat_sys_tty_mode,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700415 mContext.getString(R.string.accessibility_tty_enabled));
Jason Monk3e189872016-01-12 09:10:34 -0500416 mIconController.setIconVisibility(mSlotTty, true);
Wink Saville04e71b32009-04-02 11:00:54 -0700417 } else {
418 // TTY is off
John Spurlocka37e9c82014-07-08 09:40:31 -0400419 if (DEBUG) Log.v(TAG, "updateTTY: set TTY off");
Jason Monk3e189872016-01-12 09:10:34 -0500420 mIconController.setIconVisibility(mSlotTty, false);
Wink Saville04e71b32009-04-02 11:00:54 -0700421 }
422 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400423
424 private void updateCast() {
425 boolean isCasting = false;
426 for (CastDevice device : mCast.getCastDevices()) {
427 if (device.state == CastDevice.STATE_CONNECTING
428 || device.state == CastDevice.STATE_CONNECTED) {
429 isCasting = true;
430 break;
431 }
432 }
433 if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700434 mHandler.removeCallbacks(mRemoveCastIconRunnable);
John Spurlock96fe98d2014-08-27 09:36:02 -0400435 if (isCasting) {
Jason Monk3e189872016-01-12 09:10:34 -0500436 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast,
John Spurlock96fe98d2014-08-27 09:36:02 -0400437 mContext.getString(R.string.accessibility_casting));
Jason Monk3e189872016-01-12 09:10:34 -0500438 mIconController.setIconVisibility(mSlotCast, true);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700439 } else {
440 // don't turn off the screen-record icon for a few seconds, just to make sure the user
441 // has seen it
442 if (DEBUG) Log.v(TAG, "updateCast: hiding icon in 3 sec...");
443 mHandler.postDelayed(mRemoveCastIconRunnable, 3000);
John Spurlock96fe98d2014-08-27 09:36:02 -0400444 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400445 }
446
Kenny Guy3094d4a2015-04-01 19:14:10 +0100447 private void updateManagedProfile() {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200448 // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
449 // some cases. Since it doesn't really matter here whether it's updated in this frame
450 // or in the next one, we call this method from our UI offload thread.
451 mUiOffloadThread.submit(() -> {
452 final int userId;
453 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700454 userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200455 boolean isManagedProfile = mUserManager.isManagedProfile(userId);
456 mHandler.post(() -> {
457 final boolean showIcon;
Pavel Grafov410d8082017-06-29 18:42:32 +0100458 if (isManagedProfile &&
459 (!mKeyguardMonitor.isShowing() || mKeyguardMonitor.isOccluded())) {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200460 showIcon = true;
461 mIconController.setIcon(mSlotManagedProfile,
462 R.drawable.stat_sys_managed_profile_status,
463 mContext.getString(R.string.accessibility_managed_profile));
Jorim Jaggifabc7432017-05-15 02:40:05 +0200464 } else {
465 showIcon = false;
466 }
467 if (mManagedProfileIconVisible != showIcon) {
468 mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
469 mManagedProfileIconVisible = showIcon;
470 }
471 });
472 } catch (RemoteException e) {
473 Log.w(TAG, "updateManagedProfile: ", e);
Tony Makec319ab2017-03-28 18:50:01 +0100474 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200475 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100476 }
477
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800478 private final SynchronousUserSwitchObserver mUserSwitchListener =
479 new SynchronousUserSwitchObserver() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100480 @Override
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800481 public void onUserSwitching(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100482 mHandler.post(() -> mUserInfoController.reloadUserInfo());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100483 }
484
485 @Override
486 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100487 mHandler.post(() -> {
488 updateAlarm();
Tony Makec319ab2017-03-28 18:50:01 +0100489 updateManagedProfile();
Toni Barzice97f9232016-04-27 18:10:58 -0700490 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100491 }
492 };
493
Jason Monk952d5d82014-10-27 15:28:22 -0400494 private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
495 @Override
Rohan Shahe4071122018-01-22 15:16:09 -0800496 public void onHotspotChanged(boolean enabled, int numDevices) {
Jason Monk3e189872016-01-12 09:10:34 -0500497 mIconController.setIconVisibility(mSlotHotspot, enabled);
Jason Monk952d5d82014-10-27 15:28:22 -0400498 }
499 };
500
John Spurlock96fe98d2014-08-27 09:36:02 -0400501 private final CastController.Callback mCastCallback = new CastController.Callback() {
502 @Override
503 public void onCastDevicesChanged() {
504 updateCast();
505 }
506 };
Kenny Guy3094d4a2015-04-01 19:14:10 +0100507
Juan Flores2ff37202015-04-30 13:44:23 +0200508 private final NextAlarmController.NextAlarmChangeCallback mNextAlarmCallback =
509 new NextAlarmController.NextAlarmChangeCallback() {
Jason Monk324b8862017-02-16 17:19:12 -0500510 @Override
511 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
Evan Lairdbee3eb82018-05-16 15:58:49 -0400512 mNextAlarm = nextAlarm;
Jason Monk324b8862017-02-16 17:19:12 -0500513 updateAlarm();
514 }
515 };
Juan Flores2ff37202015-04-30 13:44:23 +0200516
Jason Monkaa573e92017-01-27 17:00:29 -0500517 @Override
Charles Chenf3d295c2018-11-30 18:15:21 +0800518 public void appTransitionStarting(int displayId, long startTime, long duration,
519 boolean forced) {
520 if (mContext.getDisplayId() == displayId) {
521 updateManagedProfile();
Charles Chenf3d295c2018-11-30 18:15:21 +0800522 }
Kenny Guy3094d4a2015-04-01 19:14:10 +0100523 }
524
Jason Monkaa573e92017-01-27 17:00:29 -0500525 @Override
526 public void onKeyguardShowingChanged() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100527 updateManagedProfile();
528 }
John Spurlock604a5ee2015-06-01 12:27:22 -0400529
Jason Monkaa573e92017-01-27 17:00:29 -0500530 @Override
531 public void onUserSetupChanged() {
532 boolean userSetup = mProvisionedController.isUserSetup(
533 mProvisionedController.getCurrentUser());
John Spurlock604a5ee2015-06-01 12:27:22 -0400534 if (mCurrentUserSetup == userSetup) return;
535 mCurrentUserSetup = userSetup;
536 updateAlarm();
537 }
Jason Monk3e189872016-01-12 09:10:34 -0500538
539 @Override
540 public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
541 boolean portrait = RotationLockTile.isCurrentOrientationLockPortrait(
542 mRotationLockController, mContext);
543 if (rotationLocked) {
544 if (portrait) {
545 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_portrait,
546 mContext.getString(R.string.accessibility_rotation_lock_on_portrait));
547 } else {
548 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape,
549 mContext.getString(R.string.accessibility_rotation_lock_on_landscape));
550 }
Jason Monk8816dff2016-02-09 21:50:36 -0500551 mIconController.setIconVisibility(mSlotRotate, true);
Jason Monk3e189872016-01-12 09:10:34 -0500552 } else {
Jason Monk8816dff2016-02-09 21:50:36 -0500553 mIconController.setIconVisibility(mSlotRotate, false);
Jason Monk3e189872016-01-12 09:10:34 -0500554 }
555 }
556
557 private void updateHeadsetPlug(Intent intent) {
558 boolean connected = intent.getIntExtra("state", 0) != 0;
559 boolean hasMic = intent.getIntExtra("microphone", 0) != 0;
560 if (connected) {
561 String contentDescription = mContext.getString(hasMic
562 ? R.string.accessibility_status_bar_headset
563 : R.string.accessibility_status_bar_headphones);
564 mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.ic_headset_mic
565 : R.drawable.ic_headset, contentDescription);
566 mIconController.setIconVisibility(mSlotHeadset, true);
567 } else {
568 mIconController.setIconVisibility(mSlotHeadset, false);
569 }
570 }
571
Jason Monkf23aa992016-01-22 16:45:21 -0500572 @Override
573 public void onDataSaverChanged(boolean isDataSaving) {
574 mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
575 }
576
Evan Lairdcf1a1032018-11-14 13:46:08 -0500577 @Override // PrivacyItemController.Callback
578 public void privacyChanged(List<PrivacyItem> privacyItems) {
579 updatePrivacyItems(privacyItems);
580 }
581
582 private void updatePrivacyItems(List<PrivacyItem> items) {
583 boolean showCamera = false;
584 boolean showMicrophone = false;
585 boolean showLocation = false;
586 for (PrivacyItem item : items) {
Fabian Kozynskia6ff80b2019-02-12 11:32:44 -0500587 if (item == null /* b/124234367 */) {
588 if (DEBUG) {
589 Log.e(TAG, "updatePrivacyItems - null item found");
590 StringWriter out = new StringWriter();
591 mPrivacyItemController.dump(null, new PrintWriter(out), null);
592 Log.e(TAG, out.toString());
593 }
594 continue;
595 }
Evan Lairdcf1a1032018-11-14 13:46:08 -0500596 switch (item.getPrivacyType()) {
597 case TYPE_CAMERA:
598 showCamera = true;
599 break;
600 case TYPE_LOCATION:
601 showLocation = true;
602 break;
603 case TYPE_MICROPHONE:
604 showMicrophone = true;
605 break;
606 }
607 }
608
609 mIconController.setIconVisibility(mSlotCamera, showCamera);
610 mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
611 mIconController.setIconVisibility(mSlotLocation, showLocation);
612 }
613
Jason Monk3e189872016-01-12 09:10:34 -0500614 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
615 @Override
616 public void onReceive(Context context, Intent intent) {
617 String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800618 switch (action) {
619 case AudioManager.RINGER_MODE_CHANGED_ACTION:
620 case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
621 updateVolumeZen();
622 break;
623 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
624 // Avoid rebroadcast because SysUI is direct boot aware.
625 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK,
626 false)) {
627 break;
628 }
629 updateSimState(intent);
630 break;
631 case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED:
632 updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
633 TelecomManager.TTY_MODE_OFF));
634 break;
635 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
636 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
637 case Intent.ACTION_MANAGED_PROFILE_REMOVED:
638 updateManagedProfile();
639 break;
640 case AudioManager.ACTION_HEADSET_PLUG:
641 updateHeadsetPlug(intent);
642 break;
Jason Monk3e189872016-01-12 09:10:34 -0500643 }
644 }
645 };
646
647 private Runnable mRemoveCastIconRunnable = new Runnable() {
648 @Override
649 public void run() {
650 if (DEBUG) Log.v(TAG, "updateCast: hiding icon NOW");
651 mIconController.setIconVisibility(mSlotCast, false);
652 }
653 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654}