blob: c326feeb3d5226302b63a2f2cb8a084adb65183d [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
Wale Ogunwale68278562017-09-23 17:13:55 -070019import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
21import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
22import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
23
Jason Monk697b82a2017-04-19 18:41:06 -040024import android.app.ActivityManager;
Jason Monk324b8862017-02-16 17:19:12 -050025import android.app.ActivityManager.StackInfo;
Jason Monk697b82a2017-04-19 18:41:06 -040026import android.app.AlarmManager;
John Spurlock604a5ee2015-06-01 12:27:22 -040027import android.app.AlarmManager.AlarmClockInfo;
Jason Monk697b82a2017-04-19 18:41:06 -040028import android.app.AppGlobals;
29import android.app.Notification;
Jason Monk324b8862017-02-16 17:19:12 -050030import android.app.Notification.Action;
Jason Monk697b82a2017-04-19 18:41:06 -040031import android.app.NotificationManager;
32import android.app.PendingIntent;
33import android.app.SynchronousUserSwitchObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.content.BroadcastReceiver;
Jason Monk697b82a2017-04-19 18:41:06 -040035import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.content.Context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.Intent;
38import android.content.IntentFilter;
Jason Monk324b8862017-02-16 17:19:12 -050039import android.content.pm.ApplicationInfo;
40import android.content.pm.IPackageManager;
41import android.content.pm.PackageManager;
Jason Monk324b8862017-02-16 17:19:12 -050042import android.graphics.drawable.Icon;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.media.AudioManager;
Jason Monk324b8862017-02-16 17:19:12 -050044import android.net.Uri;
45import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.os.Handler;
Kenny Guy3094d4a2015-04-01 19:14:10 +010047import android.os.RemoteException;
Adrian Roosc42a1e12014-07-07 23:35:53 +020048import android.os.UserHandle;
Kenny Guy3094d4a2015-04-01 19:14:10 +010049import android.os.UserManager;
Jason Monk324b8862017-02-16 17:19:12 -050050import android.provider.Settings;
John Spurlockae641c92014-06-30 18:11:40 -040051import android.provider.Settings.Global;
Jason Monk324b8862017-02-16 17:19:12 -050052import android.service.notification.StatusBarNotification;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070053import android.telecom.TelecomManager;
Jason Monk324b8862017-02-16 17:19:12 -050054import android.util.ArraySet;
John Spurlockcd686b52013-06-05 10:13:46 -040055import android.util.Log;
Jason Monk324b8862017-02-16 17:19:12 -050056import android.util.Pair;
Jason Monk324b8862017-02-16 17:19:12 -050057import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Wink Savillea639b312012-07-10 12:37:54 -070058import com.android.internal.telephony.IccCardConstants;
Wink Saville04e71b32009-04-02 11:00:54 -070059import com.android.internal.telephony.TelephonyIntents;
Jason Monk9c7844c2017-01-18 15:21:53 -050060import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040061import com.android.systemui.DockedStackExistsListener;
Joe Onorato798ac4c2010-05-27 16:39:00 -040062import com.android.systemui.R;
Jason Monkaa573e92017-01-27 17:00:29 -050063import com.android.systemui.SysUiServiceProvider;
Jorim Jaggifabc7432017-05-15 02:40:05 +020064import com.android.systemui.UiOffloadThread;
John Spurlock3c4076a2015-02-24 12:12:25 -050065import com.android.systemui.qs.tiles.DndTile;
Jason Monk3e189872016-01-12 09:10:34 -050066import com.android.systemui.qs.tiles.RotationLockTile;
Winson Chungaa357452017-10-31 11:35:30 -070067import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
Winson Chung2cf6ad82017-11-09 17:36:59 -080068import com.android.systemui.shared.system.ActivityManagerWrapper;
Jason Monkaa573e92017-01-27 17:00:29 -050069import com.android.systemui.statusbar.CommandQueue;
70import com.android.systemui.statusbar.CommandQueue.Callbacks;
Jason Monk70364362015-08-06 16:32:18 -040071import com.android.systemui.statusbar.policy.BluetoothController;
72import com.android.systemui.statusbar.policy.BluetoothController.Callback;
John Spurlock96fe98d2014-08-27 09:36:02 -040073import com.android.systemui.statusbar.policy.CastController;
74import com.android.systemui.statusbar.policy.CastController.CastDevice;
Jason Monkf23aa992016-01-22 16:45:21 -050075import com.android.systemui.statusbar.policy.DataSaverController;
Jason Monkaa573e92017-01-27 17:00:29 -050076import com.android.systemui.statusbar.policy.DataSaverController.Listener;
77import com.android.systemui.statusbar.policy.DeviceProvisionedController;
78import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Jason Monk952d5d82014-10-27 15:28:22 -040079import com.android.systemui.statusbar.policy.HotspotController;
Jason Monkaa573e92017-01-27 17:00:29 -050080import com.android.systemui.statusbar.policy.KeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -040081import com.android.systemui.statusbar.policy.LocationController;
82import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
Juan Flores2ff37202015-04-30 13:44:23 +020083import com.android.systemui.statusbar.policy.NextAlarmController;
Jason Monk3e189872016-01-12 09:10:34 -050084import com.android.systemui.statusbar.policy.RotationLockController;
Jason Monkaa573e92017-01-27 17:00:29 -050085import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
Adrian Roos88b11932015-07-22 14:59:48 -070086import com.android.systemui.statusbar.policy.UserInfoController;
Jason Monkaa573e92017-01-27 17:00:29 -050087import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monk324b8862017-02-16 17:19:12 -050088import com.android.systemui.util.NotificationChannels;
89
Jason Monk697b82a2017-04-19 18:41:06 -040090import java.util.List;
91
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092/**
93 * This class contains all of the policy about which icons are installed in the status
Joe Onorato798ac4c2010-05-27 16:39:00 -040094 * bar at boot time. It goes through the normal API for icons, even though it probably
95 * strictly doesn't need to.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 */
Jason Monkaa573e92017-01-27 17:00:29 -050097public class PhoneStatusBarPolicy implements Callback, Callbacks,
Jason Monk359bb742017-04-13 10:40:40 -040098 RotationLockControllerCallback, Listener, LocationChangeCallback,
Jason Monkaa573e92017-01-27 17:00:29 -050099 ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
Joe Onoratofd52b182010-11-10 18:00:52 -0800100 private static final String TAG = "PhoneStatusBarPolicy";
John Spurlocka37e9c82014-07-08 09:40:31 -0400101 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -0700102
Jason Monk359bb742017-04-13 10:40:40 -0400103 public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
Jason Monk697b82a2017-04-19 18:41:06 -0400104 public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
Jason Monk359bb742017-04-13 10:40:40 -0400105
Jason Monk3e189872016-01-12 09:10:34 -0500106 private final String mSlotCast;
107 private final String mSlotHotspot;
108 private final String mSlotBluetooth;
109 private final String mSlotTty;
110 private final String mSlotZen;
111 private final String mSlotVolume;
112 private final String mSlotAlarmClock;
113 private final String mSlotManagedProfile;
114 private final String mSlotRotate;
115 private final String mSlotHeadset;
Jason Monkf23aa992016-01-22 16:45:21 -0500116 private final String mSlotDataSaver;
Jason Monk359bb742017-04-13 10:40:40 -0400117 private final String mSlotLocation;
John Spurlocka37e9c82014-07-08 09:40:31 -0400118
Dianne Hackborn4840e142009-03-24 22:40:29 -0700119 private final Context mContext;
Joe Onorato10523b4d2010-10-25 10:42:46 -0700120 private final Handler mHandler = new Handler();
John Spurlock96fe98d2014-08-27 09:36:02 -0400121 private final CastController mCast;
Jason Monk952d5d82014-10-27 15:28:22 -0400122 private final HotspotController mHotspot;
Juan Flores2ff37202015-04-30 13:44:23 +0200123 private final NextAlarmController mNextAlarm;
John Spurlock15782262015-05-29 15:35:53 -0400124 private final AlarmManager mAlarmManager;
Adrian Roos88b11932015-07-22 14:59:48 -0700125 private final UserInfoController mUserInfoController;
Rubin Xu1205fb12015-11-04 17:45:03 +0000126 private final UserManager mUserManager;
Jason Monk07473ce2016-01-05 14:59:19 -0500127 private final StatusBarIconController mIconController;
Jason Monk3e189872016-01-12 09:10:34 -0500128 private final RotationLockController mRotationLockController;
Jason Monkf23aa992016-01-22 16:45:21 -0500129 private final DataSaverController mDataSaver;
Jason Monkaa573e92017-01-27 17:00:29 -0500130 private final ZenModeController mZenController;
131 private final DeviceProvisionedController mProvisionedController;
132 private final KeyguardMonitor mKeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -0400133 private final LocationController mLocationController;
Jason Monk324b8862017-02-16 17:19:12 -0500134 private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200135 private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 // Assume it's all good unless we hear otherwise. We don't always seem
138 // to get broadcasts that it *is* there.
Wink Savillea639b312012-07-10 12:37:54 -0700139 IccCardConstants.State mSimState = IccCardConstants.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
John Spurlocka37e9c82014-07-08 09:40:31 -0400141 private boolean mZenVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 private boolean mVolumeVisible;
John Spurlock604a5ee2015-06-01 12:27:22 -0400143 private boolean mCurrentUserSetup;
Jason Monkf85fc962017-04-19 17:13:41 -0400144 private boolean mDockedStackExists;
Wink Saville04e71b32009-04-02 11:00:54 -0700145
Rubin Xu1205fb12015-11-04 17:45:03 +0000146 private boolean mManagedProfileIconVisible = false;
Kenny Guy3094d4a2015-04-01 19:14:10 +0100147
Jason Monk70364362015-08-06 16:32:18 -0400148 private BluetoothController mBluetooth;
Wink Savillee9b06d72009-05-18 21:47:50 -0700149
Jason Monk9c7844c2017-01-18 15:21:53 -0500150 public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 mContext = context;
Jason Monk07473ce2016-01-05 14:59:19 -0500152 mIconController = iconController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500153 mCast = Dependency.get(CastController.class);
154 mHotspot = Dependency.get(HotspotController.class);
155 mBluetooth = Dependency.get(BluetoothController.class);
Jason Monk9c7844c2017-01-18 15:21:53 -0500156 mNextAlarm = Dependency.get(NextAlarmController.class);
John Spurlock15782262015-05-29 15:35:53 -0400157 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500158 mUserInfoController = Dependency.get(UserInfoController.class);
Rubin Xu1205fb12015-11-04 17:45:03 +0000159 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500160 mRotationLockController = Dependency.get(RotationLockController.class);
161 mDataSaver = Dependency.get(DataSaverController.class);
Jason Monkaa573e92017-01-27 17:00:29 -0500162 mZenController = Dependency.get(ZenModeController.class);
163 mProvisionedController = Dependency.get(DeviceProvisionedController.class);
164 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
Jason Monk359bb742017-04-13 10:40:40 -0400165 mLocationController = Dependency.get(LocationController.class);
Jason Monk3e189872016-01-12 09:10:34 -0500166
167 mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
168 mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
169 mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth);
170 mSlotTty = context.getString(com.android.internal.R.string.status_bar_tty);
171 mSlotZen = context.getString(com.android.internal.R.string.status_bar_zen);
172 mSlotVolume = context.getString(com.android.internal.R.string.status_bar_volume);
173 mSlotAlarmClock = context.getString(com.android.internal.R.string.status_bar_alarm_clock);
174 mSlotManagedProfile = context.getString(
175 com.android.internal.R.string.status_bar_managed_profile);
176 mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
177 mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
Jason Monkf23aa992016-01-22 16:45:21 -0500178 mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
Jason Monk359bb742017-04-13 10:40:40 -0400179 mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400181 // listen for broadcasts
182 IntentFilter filter = new IntentFilter();
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400183 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
John Spurlockbcc10872014-11-28 15:29:21 -0500184 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
Jason Monk3e189872016-01-12 09:10:34 -0500185 filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400186 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700187 filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
Rubin Xue95057a2016-04-01 16:49:25 +0100188 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
189 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
Nicolas Prevot6c7b8742016-04-13 10:28:58 +0100190 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400191 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
192
Kenny Guy3094d4a2015-04-01 19:14:10 +0100193 // listen for user / profile change.
194 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800195 ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
Kenny Guy3094d4a2015-04-01 19:14:10 +0100196 } catch (RemoteException e) {
197 // Ignore
198 }
199
Wink Saville04e71b32009-04-02 11:00:54 -0700200 // TTY status
Hall Liu108ca202017-07-24 15:19:04 -0700201 updateTTY();
Wink Saville04e71b32009-04-02 11:00:54 -0700202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 // bluetooth status
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700204 updateBluetooth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 // Alarm clock
Jason Monk3e189872016-01-12 09:10:34 -0500207 mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
208 mIconController.setIconVisibility(mSlotAlarmClock, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209
John Spurlocka37e9c82014-07-08 09:40:31 -0400210 // zen
Jason Monk3e189872016-01-12 09:10:34 -0500211 mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
212 mIconController.setIconVisibility(mSlotZen, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 // volume
Jason Monk3e189872016-01-12 09:10:34 -0500215 mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);
216 mIconController.setIconVisibility(mSlotVolume, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400217 updateVolumeZen();
John Spurlock96fe98d2014-08-27 09:36:02 -0400218
219 // cast
Jason Monk3e189872016-01-12 09:10:34 -0500220 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
221 mIconController.setIconVisibility(mSlotCast, false);
Jason Monk952d5d82014-10-27 15:28:22 -0400222
223 // hotspot
Jason Monk3e189872016-01-12 09:10:34 -0500224 mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
Jason Monk08187a42015-06-09 14:33:51 -0400225 mContext.getString(R.string.accessibility_status_bar_hotspot));
Jason Monk3e189872016-01-12 09:10:34 -0500226 mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100227
228 // managed profile
Jason Monk3e189872016-01-12 09:10:34 -0500229 mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
Adrian Roos1b5eb972015-06-11 18:22:52 -0700230 mContext.getString(R.string.accessibility_managed_profile));
Jason Monk3e189872016-01-12 09:10:34 -0500231 mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);
Jason Monkf23aa992016-01-22 16:45:21 -0500232
233 // data saver
234 mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
235 context.getString(R.string.accessibility_data_saver_on));
236 mIconController.setIconVisibility(mSlotDataSaver, false);
Jason Monkaa573e92017-01-27 17:00:29 -0500237
238 mRotationLockController.addCallback(this);
239 mBluetooth.addCallback(this);
240 mProvisionedController.addCallback(this);
241 mZenController.addCallback(this);
242 mCast.addCallback(mCastCallback);
243 mHotspot.addCallback(mHotspotCallback);
244 mNextAlarm.addCallback(mNextAlarmCallback);
Jason Monk88529052016-11-04 13:29:58 -0400245 mDataSaver.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500246 mKeyguardMonitor.addCallback(this);
Jason Monk359bb742017-04-13 10:40:40 -0400247 mLocationController.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500248
249 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
Winson Chung2cf6ad82017-11-09 17:36:59 -0800250 ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
Jason Monk324b8862017-02-16 17:19:12 -0500251
252 // Clear out all old notifications on startup (only present in the case where sysui dies)
253 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
254 for (StatusBarNotification notification : noMan.getActiveNotifications()) {
255 if (notification.getId() == SystemMessage.NOTE_INSTANT_APPS) {
256 noMan.cancel(notification.getTag(), notification.getId());
257 }
258 }
Jason Monkf85fc962017-04-19 17:13:41 -0400259 DockedStackExistsListener.register(exists -> {
260 mDockedStackExists = exists;
261 updateForegroundInstantApps();
262 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 }
264
Jason Monkaa573e92017-01-27 17:00:29 -0500265 public void destroy() {
266 mRotationLockController.removeCallback(this);
267 mBluetooth.removeCallback(this);
268 mProvisionedController.removeCallback(this);
269 mZenController.removeCallback(this);
270 mCast.removeCallback(mCastCallback);
271 mHotspot.removeCallback(mHotspotCallback);
272 mNextAlarm.removeCallback(mNextAlarmCallback);
273 mDataSaver.removeCallback(this);
274 mKeyguardMonitor.removeCallback(this);
Jason Monk359bb742017-04-13 10:40:40 -0400275 mLocationController.removeCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500276 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
277 mContext.unregisterReceiver(mIntentReceiver);
Jason Monk324b8862017-02-16 17:19:12 -0500278
279 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
280 mCurrentNotifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
281 new UserHandle(v.second)));
Nicolas Prevot1dbbe7d2016-05-17 12:52:54 +0100282 }
283
Jason Monkaa573e92017-01-27 17:00:29 -0500284 @Override
285 public void onZenChanged(int zen) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400286 updateVolumeZen();
John Spurlockba2c6a02014-05-19 09:44:06 -0400287 }
288
Jason Monk359bb742017-04-13 10:40:40 -0400289 @Override
290 public void onLocationActiveChanged(boolean active) {
291 updateLocation();
292 }
293
294 // Updates the status view based on the current state of location requests.
295 private void updateLocation() {
296 if (mLocationController.isLocationActive()) {
297 mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
298 mContext.getString(R.string.accessibility_location_active));
299 } else {
300 mIconController.removeIcon(mSlotLocation);
301 }
302 }
303
Adrian Roosc42a1e12014-07-07 23:35:53 +0200304 private void updateAlarm() {
John Spurlock604a5ee2015-06-01 12:27:22 -0400305 final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
306 final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
Jason Monk20c0eb42017-03-02 17:35:49 -0500307 int zen = mZenController.getZen();
308 final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
Jason Monk3e189872016-01-12 09:10:34 -0500309 mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
Jason Monk07473ce2016-01-05 14:59:19 -0500310 : R.drawable.stat_sys_alarm, null);
Jason Monk3e189872016-01-12 09:10:34 -0500311 mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 }
313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 private final void updateSimState(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700315 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
316 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
317 mSimState = IccCardConstants.State.ABSENT;
Jason Monk07473ce2016-01-05 14:59:19 -0500318 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
Rakesh Pallerlaf099a5f2013-02-06 11:44:23 +0530319 mSimState = IccCardConstants.State.CARD_IO_ERROR;
Junda Liua2f6a672016-05-24 10:07:40 -0700320 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(stateExtra)) {
321 mSimState = IccCardConstants.State.CARD_RESTRICTED;
Jason Monk07473ce2016-01-05 14:59:19 -0500322 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700323 mSimState = IccCardConstants.State.READY;
Jason Monk07473ce2016-01-05 14:59:19 -0500324 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700325 final String lockedReason =
326 intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
327 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
328 mSimState = IccCardConstants.State.PIN_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500329 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700330 mSimState = IccCardConstants.State.PUK_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500331 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700332 mSimState = IccCardConstants.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 }
334 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700335 mSimState = IccCardConstants.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 }
338
John Spurlockbcc10872014-11-28 15:29:21 -0500339 private final void updateVolumeZen() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
John Spurlocka37e9c82014-07-08 09:40:31 -0400341
342 boolean zenVisible = false;
343 int zenIconId = 0;
344 String zenDescription = null;
345
346 boolean volumeVisible = false;
347 int volumeIconId = 0;
348 String volumeDescription = null;
Jason Monk20c0eb42017-03-02 17:35:49 -0500349 int zen = mZenController.getZen();
John Spurlocka37e9c82014-07-08 09:40:31 -0400350
John Spurlockf88d8082015-03-25 18:09:51 -0400351 if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
Jason Monk20c0eb42017-03-02 17:35:49 -0500352 zenVisible = zen != Global.ZEN_MODE_OFF;
353 zenIconId = zen == Global.ZEN_MODE_NO_INTERRUPTIONS
John Spurlock4ec8b602015-05-11 17:46:28 -0400354 ? R.drawable.stat_sys_dnd_total_silence : R.drawable.stat_sys_dnd;
John Spurlock3c4076a2015-02-24 12:12:25 -0500355 zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
Jason Monk20c0eb42017-03-02 17:35:49 -0500356 } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400357 zenVisible = true;
358 zenIconId = R.drawable.stat_sys_zen_none;
John Spurlockd9c75db2015-04-28 11:19:13 -0400359 zenDescription = mContext.getString(R.string.interruption_level_none);
Jason Monk20c0eb42017-03-02 17:35:49 -0500360 } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400361 zenVisible = true;
362 zenIconId = R.drawable.stat_sys_zen_important;
John Spurlockd9c75db2015-04-28 11:19:13 -0400363 zenDescription = mContext.getString(R.string.interruption_level_priority);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
John Spurlockd9c75db2015-04-28 11:19:13 -0400366 if (DndTile.isVisible(mContext) && !DndTile.isCombinedIcon(mContext)
John Spurlocka48d7792015-03-03 17:35:57 -0500367 && audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
368 volumeVisible = true;
369 volumeIconId = R.drawable.stat_sys_ringer_silent;
370 volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
Jason Monk20c0eb42017-03-02 17:35:49 -0500371 } else if (zen != Global.ZEN_MODE_NO_INTERRUPTIONS && zen != Global.ZEN_MODE_ALARMS &&
John Spurlock661f2cf2014-11-17 10:29:10 -0500372 audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400373 volumeVisible = true;
374 volumeIconId = R.drawable.stat_sys_ringer_vibrate;
375 volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 }
John Spurlocka37e9c82014-07-08 09:40:31 -0400377
378 if (zenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500379 mIconController.setIcon(mSlotZen, zenIconId, zenDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400380 }
381 if (zenVisible != mZenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500382 mIconController.setIconVisibility(mSlotZen, zenVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400383 mZenVisible = zenVisible;
384 }
385
386 if (volumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500387 mIconController.setIcon(mSlotVolume, volumeIconId, volumeDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400388 }
389 if (volumeVisible != mVolumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500390 mIconController.setIconVisibility(mSlotVolume, volumeVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400391 mVolumeVisible = volumeVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 }
John Spurlock15782262015-05-29 15:35:53 -0400393 updateAlarm();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 }
395
Jason Monk70364362015-08-06 16:32:18 -0400396 @Override
397 public void onBluetoothDevicesChanged() {
398 updateBluetooth();
399 }
400
401 @Override
402 public void onBluetoothStateChange(boolean enabled) {
403 updateBluetooth();
404 }
405
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700406 private final void updateBluetooth() {
Joe Onorato798ac4c2010-05-27 16:39:00 -0400407 int iconId = R.drawable.stat_sys_data_bluetooth;
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700408 String contentDescription =
Jason Monk1aa32822015-07-14 16:10:32 -0400409 mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500410 boolean bluetoothVisible = false;
Jason Monk70364362015-08-06 16:32:18 -0400411 if (mBluetooth != null) {
Jason Monk70364362015-08-06 16:32:18 -0400412 if (mBluetooth.isBluetoothConnected()) {
Jaikumar Ganeshd9bb6882010-09-27 17:05:24 -0700413 iconId = R.drawable.stat_sys_data_bluetooth_connected;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700414 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500415 bluetoothVisible = mBluetooth.isBluetoothEnabled();
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700418
Jason Monk3e189872016-01-12 09:10:34 -0500419 mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500420 mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422
Hall Liu108ca202017-07-24 15:19:04 -0700423 private final void updateTTY() {
424 TelecomManager telecomManager =
425 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
426 if (telecomManager == null) {
427 updateTTY(TelecomManager.TTY_MODE_OFF);
428 } else {
429 updateTTY(telecomManager.getCurrentTtyMode());
430 }
431 }
432
433 private final void updateTTY(int currentTtyMode) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700434 boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF;
Wink Saville04e71b32009-04-02 11:00:54 -0700435
John Spurlocka37e9c82014-07-08 09:40:31 -0400436 if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -0700437
438 if (enabled) {
439 // TTY is on
John Spurlocka37e9c82014-07-08 09:40:31 -0400440 if (DEBUG) Log.v(TAG, "updateTTY: set TTY on");
Jason Monk3e189872016-01-12 09:10:34 -0500441 mIconController.setIcon(mSlotTty, R.drawable.stat_sys_tty_mode,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700442 mContext.getString(R.string.accessibility_tty_enabled));
Jason Monk3e189872016-01-12 09:10:34 -0500443 mIconController.setIconVisibility(mSlotTty, true);
Wink Saville04e71b32009-04-02 11:00:54 -0700444 } else {
445 // TTY is off
John Spurlocka37e9c82014-07-08 09:40:31 -0400446 if (DEBUG) Log.v(TAG, "updateTTY: set TTY off");
Jason Monk3e189872016-01-12 09:10:34 -0500447 mIconController.setIconVisibility(mSlotTty, false);
Wink Saville04e71b32009-04-02 11:00:54 -0700448 }
449 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400450
451 private void updateCast() {
452 boolean isCasting = false;
453 for (CastDevice device : mCast.getCastDevices()) {
454 if (device.state == CastDevice.STATE_CONNECTING
455 || device.state == CastDevice.STATE_CONNECTED) {
456 isCasting = true;
457 break;
458 }
459 }
460 if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700461 mHandler.removeCallbacks(mRemoveCastIconRunnable);
John Spurlock96fe98d2014-08-27 09:36:02 -0400462 if (isCasting) {
Jason Monk3e189872016-01-12 09:10:34 -0500463 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast,
John Spurlock96fe98d2014-08-27 09:36:02 -0400464 mContext.getString(R.string.accessibility_casting));
Jason Monk3e189872016-01-12 09:10:34 -0500465 mIconController.setIconVisibility(mSlotCast, true);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700466 } else {
467 // don't turn off the screen-record icon for a few seconds, just to make sure the user
468 // has seen it
469 if (DEBUG) Log.v(TAG, "updateCast: hiding icon in 3 sec...");
470 mHandler.postDelayed(mRemoveCastIconRunnable, 3000);
John Spurlock96fe98d2014-08-27 09:36:02 -0400471 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400472 }
473
Kenny Guy3094d4a2015-04-01 19:14:10 +0100474 private void updateManagedProfile() {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200475 // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
476 // some cases. Since it doesn't really matter here whether it's updated in this frame
477 // or in the next one, we call this method from our UI offload thread.
478 mUiOffloadThread.submit(() -> {
479 final int userId;
480 try {
481 userId = ActivityManager.getService().getLastResumedActivityUserId();
482 boolean isManagedProfile = mUserManager.isManagedProfile(userId);
483 mHandler.post(() -> {
484 final boolean showIcon;
Pavel Grafov410d8082017-06-29 18:42:32 +0100485 if (isManagedProfile &&
486 (!mKeyguardMonitor.isShowing() || mKeyguardMonitor.isOccluded())) {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200487 showIcon = true;
488 mIconController.setIcon(mSlotManagedProfile,
489 R.drawable.stat_sys_managed_profile_status,
490 mContext.getString(R.string.accessibility_managed_profile));
Jorim Jaggifabc7432017-05-15 02:40:05 +0200491 } else {
492 showIcon = false;
493 }
494 if (mManagedProfileIconVisible != showIcon) {
495 mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
496 mManagedProfileIconVisible = showIcon;
497 }
498 });
499 } catch (RemoteException e) {
500 Log.w(TAG, "updateManagedProfile: ", e);
Tony Makec319ab2017-03-28 18:50:01 +0100501 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200502 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100503 }
504
Jason Monk324b8862017-02-16 17:19:12 -0500505 private void updateForegroundInstantApps() {
506 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
507 ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
508 IPackageManager pm = AppGlobals.getPackageManager();
509 mCurrentNotifs.clear();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200510 mUiOffloadThread.submit(() -> {
511 try {
Wale Ogunwale68278562017-09-23 17:13:55 -0700512 final StackInfo focusedStack = ActivityManager.getService().getFocusedStackInfo();
513 if (focusedStack != null) {
514 final int windowingMode =
515 focusedStack.configuration.windowConfiguration.getWindowingMode();
516 if (windowingMode == WINDOWING_MODE_FULLSCREEN
517 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
518 checkStack(focusedStack, notifs, noMan, pm);
519 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200520 }
521 if (mDockedStackExists) {
Wale Ogunwale68278562017-09-23 17:13:55 -0700522 checkStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED,
523 notifs, noMan, pm);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200524 }
525 } catch (RemoteException e) {
526 e.rethrowFromSystemServer();
Jason Monkf85fc962017-04-19 17:13:41 -0400527 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200528 // Cancel all the leftover notifications that don't have a foreground process anymore.
529 notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
530 new UserHandle(v.second)));
531 });
Jason Monk324b8862017-02-16 17:19:12 -0500532 }
533
Wale Ogunwale68278562017-09-23 17:13:55 -0700534 private void checkStack(int windowingMode, int activityType,
535 ArraySet<Pair<String, Integer>> notifs, NotificationManager noMan, IPackageManager pm) {
536 try {
537 final StackInfo info =
538 ActivityManager.getService().getStackInfo(windowingMode, activityType);
539 checkStack(info, notifs, noMan, pm);
540 } catch (RemoteException e) {
541 e.rethrowFromSystemServer();
542 }
543 }
544 private void checkStack(StackInfo info, ArraySet<Pair<String, Integer>> notifs,
Jason Monkf85fc962017-04-19 17:13:41 -0400545 NotificationManager noMan, IPackageManager pm) {
546 try {
Jason Monkf85fc962017-04-19 17:13:41 -0400547 if (info == null || info.topActivity == null) return;
548 String pkg = info.topActivity.getPackageName();
549 if (!hasNotif(notifs, pkg, info.userId)) {
550 // TODO: Optimize by not always needing to get application info.
551 // Maybe cache non-ephemeral packages?
552 ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
553 PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
554 if (appInfo.isInstantApp()) {
Jason Monk697b82a2017-04-19 18:41:06 -0400555 postEphemeralNotif(pkg, info.userId, appInfo, noMan, info.taskIds[info.taskIds.length - 1]);
Jason Monkf85fc962017-04-19 17:13:41 -0400556 }
557 }
558 } catch (RemoteException e) {
559 e.rethrowFromSystemServer();
560 }
561 }
562
Jason Monk324b8862017-02-16 17:19:12 -0500563 private void postEphemeralNotif(String pkg, int userId, ApplicationInfo appInfo,
Jason Monk697b82a2017-04-19 18:41:06 -0400564 NotificationManager noMan, int taskId) {
Jason Monk324b8862017-02-16 17:19:12 -0500565 final Bundle extras = new Bundle();
566 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
567 mContext.getString(R.string.instant_apps));
568 mCurrentNotifs.add(new Pair<>(pkg, userId));
569 String message = mContext.getString(R.string.instant_apps_message);
570 PendingIntent appInfoAction = PendingIntent.getActivity(mContext, 0,
571 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
572 .setData(Uri.fromParts("package", pkg, null)), 0);
Jason Monk324b8862017-02-16 17:19:12 -0500573 Action action = new Notification.Action.Builder(null, mContext.getString(R.string.app_info),
574 appInfoAction).build();
575
Jason Monk697b82a2017-04-19 18:41:06 -0400576 Intent browserIntent = getTaskIntent(taskId, userId);
577 Notification.Builder builder = new Notification.Builder(mContext, NotificationChannels.GENERAL);
Patrick Baumann531db462018-02-13 13:01:47 -0800578 if (browserIntent != null && browserIntent.isWebIntent()) {
Jesse Evansa2024a22017-04-20 14:44:49 -0700579 // Make sure that this doesn't resolve back to an instant app
580 browserIntent.setComponent(null)
581 .setPackage(null)
582 .addFlags(Intent.FLAG_IGNORE_EPHEMERAL)
583 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
584
Jason Monk697b82a2017-04-19 18:41:06 -0400585 PendingIntent pendingIntent = PendingIntent.getActivity(mContext,
586 0 /* requestCode */, browserIntent, 0 /* flags */);
Jason Monk697b82a2017-04-19 18:41:06 -0400587 ComponentName aiaComponent = null;
588 try {
589 aiaComponent = AppGlobals.getPackageManager().getInstantAppInstallerComponent();
590 } catch (RemoteException e) {
591 e.rethrowFromSystemServer();
592 }
593 Intent goToWebIntent = new Intent()
594 .setComponent(aiaComponent)
595 .setAction(Intent.ACTION_VIEW)
596 .addCategory(Intent.CATEGORY_BROWSABLE)
Jason Monk83c00512017-05-08 11:23:14 -0400597 .addCategory("unique:" + System.currentTimeMillis())
Jason Monk697b82a2017-04-19 18:41:06 -0400598 .putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName)
Dianne Hackborn3accca02013-09-20 09:32:11 -0700599 .putExtra(Intent.EXTRA_VERSION_CODE, (int) (appInfo.versionCode & 0x7fffffff))
Patrick Baumann531db462018-02-13 13:01:47 -0800600 .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.versionCode)
601 .putExtra(Intent.EXTRA_EPHEMERAL_FAILURE, pendingIntent)
602 .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent);
Jason Monk697b82a2017-04-19 18:41:06 -0400603
604 PendingIntent webPendingIntent = PendingIntent.getActivity(mContext, 0, goToWebIntent, 0);
605 Action webAction = new Notification.Action.Builder(null, mContext.getString(R.string.go_to_web),
606 webPendingIntent).build();
607 builder.addAction(webAction);
608 }
609
610 noMan.notifyAsUser(pkg, SystemMessage.NOTE_INSTANT_APPS, builder
Jason Monk324b8862017-02-16 17:19:12 -0500611 .addExtras(extras)
612 .addAction(action)
613 .setContentIntent(appInfoAction)
614 .setColor(mContext.getColor(R.color.instant_apps_color))
615 .setContentTitle(appInfo.loadLabel(mContext.getPackageManager()))
616 .setLargeIcon(Icon.createWithResource(pkg, appInfo.icon))
617 .setSmallIcon(Icon.createWithResource(mContext.getPackageName(),
618 R.drawable.instant_icon))
619 .setContentText(message)
620 .setOngoing(true)
621 .build(),
622 new UserHandle(userId));
623 }
624
Jason Monk697b82a2017-04-19 18:41:06 -0400625 private Intent getTaskIntent(int taskId, int userId) {
Winson Chung5fa39752017-10-04 14:50:15 -0700626 try {
627 final List<ActivityManager.RecentTaskInfo> tasks =
628 ActivityManager.getService().getRecentTasks(
629 NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId).getList();
630 for (int i = 0; i < tasks.size(); i++) {
631 if (tasks.get(i).id == taskId) {
632 return tasks.get(i).baseIntent;
633 }
Jason Monk697b82a2017-04-19 18:41:06 -0400634 }
Winson Chung5fa39752017-10-04 14:50:15 -0700635 } catch (RemoteException e) {
636 // Fall through
Jason Monk697b82a2017-04-19 18:41:06 -0400637 }
638 return null;
639 }
640
Jason Monk324b8862017-02-16 17:19:12 -0500641 private boolean hasNotif(ArraySet<Pair<String, Integer>> notifs, String pkg, int userId) {
642 Pair<String, Integer> key = new Pair<>(pkg, userId);
643 if (notifs.remove(key)) {
644 mCurrentNotifs.add(key);
645 return true;
646 }
647 return false;
648 }
649
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800650 private final SynchronousUserSwitchObserver mUserSwitchListener =
651 new SynchronousUserSwitchObserver() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100652 @Override
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800653 public void onUserSwitching(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100654 mHandler.post(() -> mUserInfoController.reloadUserInfo());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100655 }
656
657 @Override
658 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100659 mHandler.post(() -> {
660 updateAlarm();
Tony Makec319ab2017-03-28 18:50:01 +0100661 updateManagedProfile();
662 updateForegroundInstantApps();
Toni Barzice97f9232016-04-27 18:10:58 -0700663 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100664 }
665 };
666
Jason Monk952d5d82014-10-27 15:28:22 -0400667 private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
668 @Override
Rohan Shahe4071122018-01-22 15:16:09 -0800669 public void onHotspotChanged(boolean enabled, int numDevices) {
Jason Monk3e189872016-01-12 09:10:34 -0500670 mIconController.setIconVisibility(mSlotHotspot, enabled);
Jason Monk952d5d82014-10-27 15:28:22 -0400671 }
672 };
673
John Spurlock96fe98d2014-08-27 09:36:02 -0400674 private final CastController.Callback mCastCallback = new CastController.Callback() {
675 @Override
676 public void onCastDevicesChanged() {
677 updateCast();
678 }
679 };
Kenny Guy3094d4a2015-04-01 19:14:10 +0100680
Juan Flores2ff37202015-04-30 13:44:23 +0200681 private final NextAlarmController.NextAlarmChangeCallback mNextAlarmCallback =
682 new NextAlarmController.NextAlarmChangeCallback() {
Jason Monk324b8862017-02-16 17:19:12 -0500683 @Override
684 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
685 updateAlarm();
686 }
687 };
Juan Flores2ff37202015-04-30 13:44:23 +0200688
Jason Monkaa573e92017-01-27 17:00:29 -0500689 @Override
690 public void appTransitionStarting(long startTime, long duration, boolean forced) {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100691 updateManagedProfile();
Jason Monk324b8862017-02-16 17:19:12 -0500692 updateForegroundInstantApps();
Kenny Guy3094d4a2015-04-01 19:14:10 +0100693 }
694
Jason Monkaa573e92017-01-27 17:00:29 -0500695 @Override
696 public void onKeyguardShowingChanged() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100697 updateManagedProfile();
Jason Monk324b8862017-02-16 17:19:12 -0500698 updateForegroundInstantApps();
Kenny Guy3094d4a2015-04-01 19:14:10 +0100699 }
John Spurlock604a5ee2015-06-01 12:27:22 -0400700
Jason Monkaa573e92017-01-27 17:00:29 -0500701 @Override
702 public void onUserSetupChanged() {
703 boolean userSetup = mProvisionedController.isUserSetup(
704 mProvisionedController.getCurrentUser());
John Spurlock604a5ee2015-06-01 12:27:22 -0400705 if (mCurrentUserSetup == userSetup) return;
706 mCurrentUserSetup = userSetup;
707 updateAlarm();
708 }
Jason Monk3e189872016-01-12 09:10:34 -0500709
710 @Override
Jason Monk324b8862017-02-16 17:19:12 -0500711 public void preloadRecentApps() {
712 updateForegroundInstantApps();
713 }
714
715 @Override
Jason Monk3e189872016-01-12 09:10:34 -0500716 public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
717 boolean portrait = RotationLockTile.isCurrentOrientationLockPortrait(
718 mRotationLockController, mContext);
719 if (rotationLocked) {
720 if (portrait) {
721 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_portrait,
722 mContext.getString(R.string.accessibility_rotation_lock_on_portrait));
723 } else {
724 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape,
725 mContext.getString(R.string.accessibility_rotation_lock_on_landscape));
726 }
Jason Monk8816dff2016-02-09 21:50:36 -0500727 mIconController.setIconVisibility(mSlotRotate, true);
Jason Monk3e189872016-01-12 09:10:34 -0500728 } else {
Jason Monk8816dff2016-02-09 21:50:36 -0500729 mIconController.setIconVisibility(mSlotRotate, false);
Jason Monk3e189872016-01-12 09:10:34 -0500730 }
731 }
732
733 private void updateHeadsetPlug(Intent intent) {
734 boolean connected = intent.getIntExtra("state", 0) != 0;
735 boolean hasMic = intent.getIntExtra("microphone", 0) != 0;
736 if (connected) {
737 String contentDescription = mContext.getString(hasMic
738 ? R.string.accessibility_status_bar_headset
739 : R.string.accessibility_status_bar_headphones);
740 mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.ic_headset_mic
741 : R.drawable.ic_headset, contentDescription);
742 mIconController.setIconVisibility(mSlotHeadset, true);
743 } else {
744 mIconController.setIconVisibility(mSlotHeadset, false);
745 }
746 }
747
Jason Monkf23aa992016-01-22 16:45:21 -0500748 @Override
749 public void onDataSaverChanged(boolean isDataSaving) {
750 mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
751 }
752
Winson Chungaa357452017-10-31 11:35:30 -0700753 private final SysUiTaskStackChangeListener mTaskListener = new SysUiTaskStackChangeListener() {
Jason Monk324b8862017-02-16 17:19:12 -0500754 @Override
755 public void onTaskStackChanged() {
756 // Listen for changes to stacks and then check which instant apps are foreground.
757 updateForegroundInstantApps();
758 }
759 };
760
Jason Monk3e189872016-01-12 09:10:34 -0500761 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
762 @Override
763 public void onReceive(Context context, Intent intent) {
764 String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800765 switch (action) {
766 case AudioManager.RINGER_MODE_CHANGED_ACTION:
767 case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
768 updateVolumeZen();
769 break;
770 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
771 // Avoid rebroadcast because SysUI is direct boot aware.
772 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK,
773 false)) {
774 break;
775 }
776 updateSimState(intent);
777 break;
778 case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED:
779 updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
780 TelecomManager.TTY_MODE_OFF));
781 break;
782 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
783 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
784 case Intent.ACTION_MANAGED_PROFILE_REMOVED:
785 updateManagedProfile();
786 break;
787 case AudioManager.ACTION_HEADSET_PLUG:
788 updateHeadsetPlug(intent);
789 break;
Jason Monk3e189872016-01-12 09:10:34 -0500790 }
791 }
792 };
793
794 private Runnable mRemoveCastIconRunnable = new Runnable() {
795 @Override
796 public void run() {
797 if (DEBUG) Log.v(TAG, "updateCast: hiding icon NOW");
798 mIconController.setIconVisibility(mSlotCast, false);
799 }
800 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800801}