blob: e0c734281092b336370d79d66b93245f75fab226 [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;
Beverlyb9826dd2018-04-12 15:02:45 -040053import android.service.notification.ZenModeConfig;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070054import android.telecom.TelecomManager;
Evan Lairdbee3eb82018-05-16 15:58:49 -040055import android.text.format.DateFormat;
Jason Monk324b8862017-02-16 17:19:12 -050056import android.util.ArraySet;
John Spurlockcd686b52013-06-05 10:13:46 -040057import android.util.Log;
Jason Monk324b8862017-02-16 17:19:12 -050058import android.util.Pair;
Jason Monk324b8862017-02-16 17:19:12 -050059import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Wink Savillea639b312012-07-10 12:37:54 -070060import com.android.internal.telephony.IccCardConstants;
Wink Saville04e71b32009-04-02 11:00:54 -070061import com.android.internal.telephony.TelephonyIntents;
Jason Monk9c7844c2017-01-18 15:21:53 -050062import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040063import com.android.systemui.DockedStackExistsListener;
Joe Onorato798ac4c2010-05-27 16:39:00 -040064import com.android.systemui.R;
Jason Monkaa573e92017-01-27 17:00:29 -050065import com.android.systemui.SysUiServiceProvider;
Jorim Jaggifabc7432017-05-15 02:40:05 +020066import com.android.systemui.UiOffloadThread;
John Spurlock3c4076a2015-02-24 12:12:25 -050067import com.android.systemui.qs.tiles.DndTile;
Jason Monk3e189872016-01-12 09:10:34 -050068import com.android.systemui.qs.tiles.RotationLockTile;
Winson Chungaa357452017-10-31 11:35:30 -070069import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
Winson Chung2cf6ad82017-11-09 17:36:59 -080070import com.android.systemui.shared.system.ActivityManagerWrapper;
Jason Monkaa573e92017-01-27 17:00:29 -050071import com.android.systemui.statusbar.CommandQueue;
72import com.android.systemui.statusbar.CommandQueue.Callbacks;
Jason Monk70364362015-08-06 16:32:18 -040073import com.android.systemui.statusbar.policy.BluetoothController;
74import com.android.systemui.statusbar.policy.BluetoothController.Callback;
John Spurlock96fe98d2014-08-27 09:36:02 -040075import com.android.systemui.statusbar.policy.CastController;
76import com.android.systemui.statusbar.policy.CastController.CastDevice;
Jason Monkf23aa992016-01-22 16:45:21 -050077import com.android.systemui.statusbar.policy.DataSaverController;
Jason Monkaa573e92017-01-27 17:00:29 -050078import com.android.systemui.statusbar.policy.DataSaverController.Listener;
79import com.android.systemui.statusbar.policy.DeviceProvisionedController;
80import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Jason Monk952d5d82014-10-27 15:28:22 -040081import com.android.systemui.statusbar.policy.HotspotController;
Jason Monkaa573e92017-01-27 17:00:29 -050082import com.android.systemui.statusbar.policy.KeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -040083import com.android.systemui.statusbar.policy.LocationController;
84import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
Juan Flores2ff37202015-04-30 13:44:23 +020085import com.android.systemui.statusbar.policy.NextAlarmController;
Jason Monk3e189872016-01-12 09:10:34 -050086import com.android.systemui.statusbar.policy.RotationLockController;
Jason Monkaa573e92017-01-27 17:00:29 -050087import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
Adrian Roos88b11932015-07-22 14:59:48 -070088import com.android.systemui.statusbar.policy.UserInfoController;
Jason Monkaa573e92017-01-27 17:00:29 -050089import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monk324b8862017-02-16 17:19:12 -050090import com.android.systemui.util.NotificationChannels;
91
Jason Monk697b82a2017-04-19 18:41:06 -040092import java.util.List;
Evan Lairdbee3eb82018-05-16 15:58:49 -040093import java.util.Locale;
Jason Monk697b82a2017-04-19 18:41:06 -040094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095/**
96 * This class contains all of the policy about which icons are installed in the status
Joe Onorato798ac4c2010-05-27 16:39:00 -040097 * bar at boot time. It goes through the normal API for icons, even though it probably
98 * strictly doesn't need to.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 */
Jason Monkaa573e92017-01-27 17:00:29 -0500100public class PhoneStatusBarPolicy implements Callback, Callbacks,
Jason Monk359bb742017-04-13 10:40:40 -0400101 RotationLockControllerCallback, Listener, LocationChangeCallback,
Jason Monkaa573e92017-01-27 17:00:29 -0500102 ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
Joe Onoratofd52b182010-11-10 18:00:52 -0800103 private static final String TAG = "PhoneStatusBarPolicy";
John Spurlocka37e9c82014-07-08 09:40:31 -0400104 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -0700105
Jason Monk359bb742017-04-13 10:40:40 -0400106 public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
Jason Monk697b82a2017-04-19 18:41:06 -0400107 public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
Jason Monk359bb742017-04-13 10:40:40 -0400108
Jason Monk3e189872016-01-12 09:10:34 -0500109 private final String mSlotCast;
110 private final String mSlotHotspot;
111 private final String mSlotBluetooth;
112 private final String mSlotTty;
113 private final String mSlotZen;
114 private final String mSlotVolume;
115 private final String mSlotAlarmClock;
116 private final String mSlotManagedProfile;
117 private final String mSlotRotate;
118 private final String mSlotHeadset;
Jason Monkf23aa992016-01-22 16:45:21 -0500119 private final String mSlotDataSaver;
Jason Monk359bb742017-04-13 10:40:40 -0400120 private final String mSlotLocation;
John Spurlocka37e9c82014-07-08 09:40:31 -0400121
Dianne Hackborn4840e142009-03-24 22:40:29 -0700122 private final Context mContext;
Joe Onorato10523b4d2010-10-25 10:42:46 -0700123 private final Handler mHandler = new Handler();
John Spurlock96fe98d2014-08-27 09:36:02 -0400124 private final CastController mCast;
Jason Monk952d5d82014-10-27 15:28:22 -0400125 private final HotspotController mHotspot;
Evan Lairdbee3eb82018-05-16 15:58:49 -0400126 private final NextAlarmController mNextAlarmController;
John Spurlock15782262015-05-29 15:35:53 -0400127 private final AlarmManager mAlarmManager;
Adrian Roos88b11932015-07-22 14:59:48 -0700128 private final UserInfoController mUserInfoController;
Rubin Xu1205fb12015-11-04 17:45:03 +0000129 private final UserManager mUserManager;
Jason Monk07473ce2016-01-05 14:59:19 -0500130 private final StatusBarIconController mIconController;
Jason Monk3e189872016-01-12 09:10:34 -0500131 private final RotationLockController mRotationLockController;
Jason Monkf23aa992016-01-22 16:45:21 -0500132 private final DataSaverController mDataSaver;
Jason Monkaa573e92017-01-27 17:00:29 -0500133 private final ZenModeController mZenController;
134 private final DeviceProvisionedController mProvisionedController;
135 private final KeyguardMonitor mKeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -0400136 private final LocationController mLocationController;
Jason Monk324b8862017-02-16 17:19:12 -0500137 private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200138 private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 // Assume it's all good unless we hear otherwise. We don't always seem
141 // to get broadcasts that it *is* there.
Wink Savillea639b312012-07-10 12:37:54 -0700142 IccCardConstants.State mSimState = IccCardConstants.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143
John Spurlocka37e9c82014-07-08 09:40:31 -0400144 private boolean mZenVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 private boolean mVolumeVisible;
John Spurlock604a5ee2015-06-01 12:27:22 -0400146 private boolean mCurrentUserSetup;
Jason Monkf85fc962017-04-19 17:13:41 -0400147 private boolean mDockedStackExists;
Wink Saville04e71b32009-04-02 11:00:54 -0700148
Rubin Xu1205fb12015-11-04 17:45:03 +0000149 private boolean mManagedProfileIconVisible = false;
Kenny Guy3094d4a2015-04-01 19:14:10 +0100150
Jason Monk70364362015-08-06 16:32:18 -0400151 private BluetoothController mBluetooth;
Evan Lairdbee3eb82018-05-16 15:58:49 -0400152 private AlarmManager.AlarmClockInfo mNextAlarm;
Wink Savillee9b06d72009-05-18 21:47:50 -0700153
Jason Monk9c7844c2017-01-18 15:21:53 -0500154 public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 mContext = context;
Jason Monk07473ce2016-01-05 14:59:19 -0500156 mIconController = iconController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500157 mCast = Dependency.get(CastController.class);
158 mHotspot = Dependency.get(HotspotController.class);
159 mBluetooth = Dependency.get(BluetoothController.class);
Evan Lairdbee3eb82018-05-16 15:58:49 -0400160 mNextAlarmController = Dependency.get(NextAlarmController.class);
John Spurlock15782262015-05-29 15:35:53 -0400161 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500162 mUserInfoController = Dependency.get(UserInfoController.class);
Rubin Xu1205fb12015-11-04 17:45:03 +0000163 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500164 mRotationLockController = Dependency.get(RotationLockController.class);
165 mDataSaver = Dependency.get(DataSaverController.class);
Jason Monkaa573e92017-01-27 17:00:29 -0500166 mZenController = Dependency.get(ZenModeController.class);
167 mProvisionedController = Dependency.get(DeviceProvisionedController.class);
168 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
Jason Monk359bb742017-04-13 10:40:40 -0400169 mLocationController = Dependency.get(LocationController.class);
Jason Monk3e189872016-01-12 09:10:34 -0500170
171 mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
172 mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
173 mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth);
174 mSlotTty = context.getString(com.android.internal.R.string.status_bar_tty);
175 mSlotZen = context.getString(com.android.internal.R.string.status_bar_zen);
176 mSlotVolume = context.getString(com.android.internal.R.string.status_bar_volume);
177 mSlotAlarmClock = context.getString(com.android.internal.R.string.status_bar_alarm_clock);
178 mSlotManagedProfile = context.getString(
179 com.android.internal.R.string.status_bar_managed_profile);
180 mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
181 mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
Jason Monkf23aa992016-01-22 16:45:21 -0500182 mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
Jason Monk359bb742017-04-13 10:40:40 -0400183 mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400185 // listen for broadcasts
186 IntentFilter filter = new IntentFilter();
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400187 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
John Spurlockbcc10872014-11-28 15:29:21 -0500188 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
Jason Monk3e189872016-01-12 09:10:34 -0500189 filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400190 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700191 filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
Rubin Xue95057a2016-04-01 16:49:25 +0100192 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
193 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
Nicolas Prevot6c7b8742016-04-13 10:28:58 +0100194 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400195 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
196
Kenny Guy3094d4a2015-04-01 19:14:10 +0100197 // listen for user / profile change.
198 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800199 ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
Kenny Guy3094d4a2015-04-01 19:14:10 +0100200 } catch (RemoteException e) {
201 // Ignore
202 }
203
Wink Saville04e71b32009-04-02 11:00:54 -0700204 // TTY status
Hall Liu108ca202017-07-24 15:19:04 -0700205 updateTTY();
Wink Saville04e71b32009-04-02 11:00:54 -0700206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 // bluetooth status
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700208 updateBluetooth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 // Alarm clock
Jason Monk3e189872016-01-12 09:10:34 -0500211 mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
212 mIconController.setIconVisibility(mSlotAlarmClock, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213
John Spurlocka37e9c82014-07-08 09:40:31 -0400214 // zen
Jason Monk3e189872016-01-12 09:10:34 -0500215 mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
216 mIconController.setIconVisibility(mSlotZen, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 // volume
Jason Monk3e189872016-01-12 09:10:34 -0500219 mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);
220 mIconController.setIconVisibility(mSlotVolume, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400221 updateVolumeZen();
John Spurlock96fe98d2014-08-27 09:36:02 -0400222
223 // cast
Jason Monk3e189872016-01-12 09:10:34 -0500224 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
225 mIconController.setIconVisibility(mSlotCast, false);
Jason Monk952d5d82014-10-27 15:28:22 -0400226
227 // hotspot
Jason Monk3e189872016-01-12 09:10:34 -0500228 mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
Jason Monk08187a42015-06-09 14:33:51 -0400229 mContext.getString(R.string.accessibility_status_bar_hotspot));
Jason Monk3e189872016-01-12 09:10:34 -0500230 mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100231
232 // managed profile
Jason Monk3e189872016-01-12 09:10:34 -0500233 mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
Adrian Roos1b5eb972015-06-11 18:22:52 -0700234 mContext.getString(R.string.accessibility_managed_profile));
Jason Monk3e189872016-01-12 09:10:34 -0500235 mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);
Jason Monkf23aa992016-01-22 16:45:21 -0500236
237 // data saver
238 mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
239 context.getString(R.string.accessibility_data_saver_on));
240 mIconController.setIconVisibility(mSlotDataSaver, false);
Jason Monkaa573e92017-01-27 17:00:29 -0500241
242 mRotationLockController.addCallback(this);
243 mBluetooth.addCallback(this);
244 mProvisionedController.addCallback(this);
245 mZenController.addCallback(this);
246 mCast.addCallback(mCastCallback);
247 mHotspot.addCallback(mHotspotCallback);
Evan Lairdbee3eb82018-05-16 15:58:49 -0400248 mNextAlarmController.addCallback(mNextAlarmCallback);
Jason Monk88529052016-11-04 13:29:58 -0400249 mDataSaver.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500250 mKeyguardMonitor.addCallback(this);
Jason Monk359bb742017-04-13 10:40:40 -0400251 mLocationController.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500252
253 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
Winson Chung2cf6ad82017-11-09 17:36:59 -0800254 ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
Jason Monk324b8862017-02-16 17:19:12 -0500255
256 // Clear out all old notifications on startup (only present in the case where sysui dies)
257 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
258 for (StatusBarNotification notification : noMan.getActiveNotifications()) {
259 if (notification.getId() == SystemMessage.NOTE_INSTANT_APPS) {
260 noMan.cancel(notification.getTag(), notification.getId());
261 }
262 }
Jason Monkf85fc962017-04-19 17:13:41 -0400263 DockedStackExistsListener.register(exists -> {
264 mDockedStackExists = exists;
265 updateForegroundInstantApps();
266 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 }
268
Jason Monkaa573e92017-01-27 17:00:29 -0500269 public void destroy() {
270 mRotationLockController.removeCallback(this);
271 mBluetooth.removeCallback(this);
272 mProvisionedController.removeCallback(this);
273 mZenController.removeCallback(this);
274 mCast.removeCallback(mCastCallback);
275 mHotspot.removeCallback(mHotspotCallback);
Evan Lairdbee3eb82018-05-16 15:58:49 -0400276 mNextAlarmController.removeCallback(mNextAlarmCallback);
Jason Monkaa573e92017-01-27 17:00:29 -0500277 mDataSaver.removeCallback(this);
278 mKeyguardMonitor.removeCallback(this);
Jason Monk359bb742017-04-13 10:40:40 -0400279 mLocationController.removeCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500280 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
281 mContext.unregisterReceiver(mIntentReceiver);
Jason Monk324b8862017-02-16 17:19:12 -0500282
283 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
284 mCurrentNotifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
285 new UserHandle(v.second)));
Nicolas Prevot1dbbe7d2016-05-17 12:52:54 +0100286 }
287
Jason Monkaa573e92017-01-27 17:00:29 -0500288 @Override
289 public void onZenChanged(int zen) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400290 updateVolumeZen();
John Spurlockba2c6a02014-05-19 09:44:06 -0400291 }
292
Jason Monk359bb742017-04-13 10:40:40 -0400293 @Override
Beverlyb9826dd2018-04-12 15:02:45 -0400294 public void onConfigChanged(ZenModeConfig config) {
295 updateVolumeZen();
296 }
297
298 @Override
Jason Monk359bb742017-04-13 10:40:40 -0400299 public void onLocationActiveChanged(boolean active) {
300 updateLocation();
301 }
302
303 // Updates the status view based on the current state of location requests.
304 private void updateLocation() {
305 if (mLocationController.isLocationActive()) {
306 mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
307 mContext.getString(R.string.accessibility_location_active));
308 } else {
Evan Lairde1d13c92018-03-20 16:58:01 -0400309 mIconController.removeAllIconsForSlot(mSlotLocation);
Jason Monk359bb742017-04-13 10:40:40 -0400310 }
311 }
312
Adrian Roosc42a1e12014-07-07 23:35:53 +0200313 private void updateAlarm() {
John Spurlock604a5ee2015-06-01 12:27:22 -0400314 final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
315 final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
Jason Monk20c0eb42017-03-02 17:35:49 -0500316 int zen = mZenController.getZen();
317 final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
Jason Monk3e189872016-01-12 09:10:34 -0500318 mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
Evan Lairdbee3eb82018-05-16 15:58:49 -0400319 : R.drawable.stat_sys_alarm, buildAlarmContentDescription());
Jason Monk3e189872016-01-12 09:10:34 -0500320 mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
322
Evan Lairdbee3eb82018-05-16 15:58:49 -0400323 private String buildAlarmContentDescription() {
324 if (mNextAlarm == null) {
325 return mContext.getString(R.string.status_bar_alarm);
326 }
327 return formatNextAlarm(mNextAlarm, mContext);
328 }
329
330 private static String formatNextAlarm(AlarmManager.AlarmClockInfo info, Context context) {
331 if (info == null) {
332 return "";
333 }
334 String skeleton = DateFormat.is24HourFormat(
335 context, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma";
336 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
337 String dateString = DateFormat.format(pattern, info.getTriggerTime()).toString();
338
339 return context.getString(R.string.accessibility_quick_settings_alarm, dateString);
340 }
341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 private final void updateSimState(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700343 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
344 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
345 mSimState = IccCardConstants.State.ABSENT;
Jason Monk07473ce2016-01-05 14:59:19 -0500346 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
Rakesh Pallerlaf099a5f2013-02-06 11:44:23 +0530347 mSimState = IccCardConstants.State.CARD_IO_ERROR;
Junda Liua2f6a672016-05-24 10:07:40 -0700348 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(stateExtra)) {
349 mSimState = IccCardConstants.State.CARD_RESTRICTED;
Jason Monk07473ce2016-01-05 14:59:19 -0500350 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700351 mSimState = IccCardConstants.State.READY;
Jason Monk07473ce2016-01-05 14:59:19 -0500352 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700353 final String lockedReason =
354 intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
355 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
356 mSimState = IccCardConstants.State.PIN_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500357 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700358 mSimState = IccCardConstants.State.PUK_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500359 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700360 mSimState = IccCardConstants.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 }
362 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700363 mSimState = IccCardConstants.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 }
366
John Spurlockbcc10872014-11-28 15:29:21 -0500367 private final void updateVolumeZen() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
John Spurlocka37e9c82014-07-08 09:40:31 -0400369
370 boolean zenVisible = false;
371 int zenIconId = 0;
372 String zenDescription = null;
373
374 boolean volumeVisible = false;
375 int volumeIconId = 0;
376 String volumeDescription = null;
Jason Monk20c0eb42017-03-02 17:35:49 -0500377 int zen = mZenController.getZen();
John Spurlocka37e9c82014-07-08 09:40:31 -0400378
John Spurlockf88d8082015-03-25 18:09:51 -0400379 if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
Jason Monk20c0eb42017-03-02 17:35:49 -0500380 zenVisible = zen != Global.ZEN_MODE_OFF;
Evan Lairda9adbd52018-05-16 11:32:08 -0400381 zenIconId = R.drawable.stat_sys_dnd;
John Spurlock3c4076a2015-02-24 12:12:25 -0500382 zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
Jason Monk20c0eb42017-03-02 17:35:49 -0500383 } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400384 zenVisible = true;
385 zenIconId = R.drawable.stat_sys_zen_none;
John Spurlockd9c75db2015-04-28 11:19:13 -0400386 zenDescription = mContext.getString(R.string.interruption_level_none);
Jason Monk20c0eb42017-03-02 17:35:49 -0500387 } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400388 zenVisible = true;
389 zenIconId = R.drawable.stat_sys_zen_important;
John Spurlockd9c75db2015-04-28 11:19:13 -0400390 zenDescription = mContext.getString(R.string.interruption_level_priority);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392
Beverlyb9826dd2018-04-12 15:02:45 -0400393 if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConfig())) {
394 if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
395 volumeVisible = true;
396 volumeIconId = R.drawable.stat_sys_ringer_vibrate;
397 volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
398 } else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
399 volumeVisible = true;
400 volumeIconId = R.drawable.stat_sys_ringer_silent;
401 volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 }
John Spurlocka37e9c82014-07-08 09:40:31 -0400404
405 if (zenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500406 mIconController.setIcon(mSlotZen, zenIconId, zenDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400407 }
408 if (zenVisible != mZenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500409 mIconController.setIconVisibility(mSlotZen, zenVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400410 mZenVisible = zenVisible;
411 }
412
413 if (volumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500414 mIconController.setIcon(mSlotVolume, volumeIconId, volumeDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400415 }
416 if (volumeVisible != mVolumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500417 mIconController.setIconVisibility(mSlotVolume, volumeVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400418 mVolumeVisible = volumeVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 }
John Spurlock15782262015-05-29 15:35:53 -0400420 updateAlarm();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422
Jason Monk70364362015-08-06 16:32:18 -0400423 @Override
424 public void onBluetoothDevicesChanged() {
425 updateBluetooth();
426 }
427
428 @Override
429 public void onBluetoothStateChange(boolean enabled) {
430 updateBluetooth();
431 }
432
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700433 private final void updateBluetooth() {
Joe Onorato798ac4c2010-05-27 16:39:00 -0400434 int iconId = R.drawable.stat_sys_data_bluetooth;
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700435 String contentDescription =
Jason Monk1aa32822015-07-14 16:10:32 -0400436 mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500437 boolean bluetoothVisible = false;
Jason Monk70364362015-08-06 16:32:18 -0400438 if (mBluetooth != null) {
Jason Monk70364362015-08-06 16:32:18 -0400439 if (mBluetooth.isBluetoothConnected()) {
Jaikumar Ganeshd9bb6882010-09-27 17:05:24 -0700440 iconId = R.drawable.stat_sys_data_bluetooth_connected;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700441 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500442 bluetoothVisible = mBluetooth.isBluetoothEnabled();
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800443 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700445
Jason Monk3e189872016-01-12 09:10:34 -0500446 mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500447 mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 }
449
Hall Liu108ca202017-07-24 15:19:04 -0700450 private final void updateTTY() {
451 TelecomManager telecomManager =
452 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
453 if (telecomManager == null) {
454 updateTTY(TelecomManager.TTY_MODE_OFF);
455 } else {
456 updateTTY(telecomManager.getCurrentTtyMode());
457 }
458 }
459
460 private final void updateTTY(int currentTtyMode) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700461 boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF;
Wink Saville04e71b32009-04-02 11:00:54 -0700462
John Spurlocka37e9c82014-07-08 09:40:31 -0400463 if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -0700464
465 if (enabled) {
466 // TTY is on
John Spurlocka37e9c82014-07-08 09:40:31 -0400467 if (DEBUG) Log.v(TAG, "updateTTY: set TTY on");
Jason Monk3e189872016-01-12 09:10:34 -0500468 mIconController.setIcon(mSlotTty, R.drawable.stat_sys_tty_mode,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700469 mContext.getString(R.string.accessibility_tty_enabled));
Jason Monk3e189872016-01-12 09:10:34 -0500470 mIconController.setIconVisibility(mSlotTty, true);
Wink Saville04e71b32009-04-02 11:00:54 -0700471 } else {
472 // TTY is off
John Spurlocka37e9c82014-07-08 09:40:31 -0400473 if (DEBUG) Log.v(TAG, "updateTTY: set TTY off");
Jason Monk3e189872016-01-12 09:10:34 -0500474 mIconController.setIconVisibility(mSlotTty, false);
Wink Saville04e71b32009-04-02 11:00:54 -0700475 }
476 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400477
478 private void updateCast() {
479 boolean isCasting = false;
480 for (CastDevice device : mCast.getCastDevices()) {
481 if (device.state == CastDevice.STATE_CONNECTING
482 || device.state == CastDevice.STATE_CONNECTED) {
483 isCasting = true;
484 break;
485 }
486 }
487 if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700488 mHandler.removeCallbacks(mRemoveCastIconRunnable);
John Spurlock96fe98d2014-08-27 09:36:02 -0400489 if (isCasting) {
Jason Monk3e189872016-01-12 09:10:34 -0500490 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast,
John Spurlock96fe98d2014-08-27 09:36:02 -0400491 mContext.getString(R.string.accessibility_casting));
Jason Monk3e189872016-01-12 09:10:34 -0500492 mIconController.setIconVisibility(mSlotCast, true);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700493 } else {
494 // don't turn off the screen-record icon for a few seconds, just to make sure the user
495 // has seen it
496 if (DEBUG) Log.v(TAG, "updateCast: hiding icon in 3 sec...");
497 mHandler.postDelayed(mRemoveCastIconRunnable, 3000);
John Spurlock96fe98d2014-08-27 09:36:02 -0400498 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400499 }
500
Kenny Guy3094d4a2015-04-01 19:14:10 +0100501 private void updateManagedProfile() {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200502 // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
503 // some cases. Since it doesn't really matter here whether it's updated in this frame
504 // or in the next one, we call this method from our UI offload thread.
505 mUiOffloadThread.submit(() -> {
506 final int userId;
507 try {
508 userId = ActivityManager.getService().getLastResumedActivityUserId();
509 boolean isManagedProfile = mUserManager.isManagedProfile(userId);
510 mHandler.post(() -> {
511 final boolean showIcon;
Pavel Grafov410d8082017-06-29 18:42:32 +0100512 if (isManagedProfile &&
513 (!mKeyguardMonitor.isShowing() || mKeyguardMonitor.isOccluded())) {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200514 showIcon = true;
515 mIconController.setIcon(mSlotManagedProfile,
516 R.drawable.stat_sys_managed_profile_status,
517 mContext.getString(R.string.accessibility_managed_profile));
Jorim Jaggifabc7432017-05-15 02:40:05 +0200518 } else {
519 showIcon = false;
520 }
521 if (mManagedProfileIconVisible != showIcon) {
522 mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
523 mManagedProfileIconVisible = showIcon;
524 }
525 });
526 } catch (RemoteException e) {
527 Log.w(TAG, "updateManagedProfile: ", e);
Tony Makec319ab2017-03-28 18:50:01 +0100528 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200529 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100530 }
531
Jason Monk324b8862017-02-16 17:19:12 -0500532 private void updateForegroundInstantApps() {
533 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
534 ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
535 IPackageManager pm = AppGlobals.getPackageManager();
536 mCurrentNotifs.clear();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200537 mUiOffloadThread.submit(() -> {
538 try {
Wale Ogunwale68278562017-09-23 17:13:55 -0700539 final StackInfo focusedStack = ActivityManager.getService().getFocusedStackInfo();
540 if (focusedStack != null) {
541 final int windowingMode =
542 focusedStack.configuration.windowConfiguration.getWindowingMode();
543 if (windowingMode == WINDOWING_MODE_FULLSCREEN
544 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
545 checkStack(focusedStack, notifs, noMan, pm);
546 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200547 }
548 if (mDockedStackExists) {
Wale Ogunwale68278562017-09-23 17:13:55 -0700549 checkStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED,
550 notifs, noMan, pm);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200551 }
552 } catch (RemoteException e) {
553 e.rethrowFromSystemServer();
Jason Monkf85fc962017-04-19 17:13:41 -0400554 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200555 // Cancel all the leftover notifications that don't have a foreground process anymore.
556 notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
557 new UserHandle(v.second)));
558 });
Jason Monk324b8862017-02-16 17:19:12 -0500559 }
560
Wale Ogunwale68278562017-09-23 17:13:55 -0700561 private void checkStack(int windowingMode, int activityType,
562 ArraySet<Pair<String, Integer>> notifs, NotificationManager noMan, IPackageManager pm) {
563 try {
564 final StackInfo info =
565 ActivityManager.getService().getStackInfo(windowingMode, activityType);
566 checkStack(info, notifs, noMan, pm);
567 } catch (RemoteException e) {
568 e.rethrowFromSystemServer();
569 }
570 }
571 private void checkStack(StackInfo info, ArraySet<Pair<String, Integer>> notifs,
Jason Monkf85fc962017-04-19 17:13:41 -0400572 NotificationManager noMan, IPackageManager pm) {
573 try {
Jason Monkf85fc962017-04-19 17:13:41 -0400574 if (info == null || info.topActivity == null) return;
575 String pkg = info.topActivity.getPackageName();
576 if (!hasNotif(notifs, pkg, info.userId)) {
577 // TODO: Optimize by not always needing to get application info.
578 // Maybe cache non-ephemeral packages?
579 ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
580 PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
581 if (appInfo.isInstantApp()) {
Jason Monk697b82a2017-04-19 18:41:06 -0400582 postEphemeralNotif(pkg, info.userId, appInfo, noMan, info.taskIds[info.taskIds.length - 1]);
Jason Monkf85fc962017-04-19 17:13:41 -0400583 }
584 }
585 } catch (RemoteException e) {
586 e.rethrowFromSystemServer();
587 }
588 }
589
Jason Monk324b8862017-02-16 17:19:12 -0500590 private void postEphemeralNotif(String pkg, int userId, ApplicationInfo appInfo,
Jason Monk697b82a2017-04-19 18:41:06 -0400591 NotificationManager noMan, int taskId) {
Jason Monk324b8862017-02-16 17:19:12 -0500592 final Bundle extras = new Bundle();
593 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
594 mContext.getString(R.string.instant_apps));
595 mCurrentNotifs.add(new Pair<>(pkg, userId));
596 String message = mContext.getString(R.string.instant_apps_message);
597 PendingIntent appInfoAction = PendingIntent.getActivity(mContext, 0,
598 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
599 .setData(Uri.fromParts("package", pkg, null)), 0);
Jason Monk324b8862017-02-16 17:19:12 -0500600 Action action = new Notification.Action.Builder(null, mContext.getString(R.string.app_info),
601 appInfoAction).build();
602
Jason Monk697b82a2017-04-19 18:41:06 -0400603 Intent browserIntent = getTaskIntent(taskId, userId);
604 Notification.Builder builder = new Notification.Builder(mContext, NotificationChannels.GENERAL);
Patrick Baumann531db462018-02-13 13:01:47 -0800605 if (browserIntent != null && browserIntent.isWebIntent()) {
Jesse Evansa2024a22017-04-20 14:44:49 -0700606 // Make sure that this doesn't resolve back to an instant app
607 browserIntent.setComponent(null)
608 .setPackage(null)
609 .addFlags(Intent.FLAG_IGNORE_EPHEMERAL)
610 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
611
Jason Monk697b82a2017-04-19 18:41:06 -0400612 PendingIntent pendingIntent = PendingIntent.getActivity(mContext,
613 0 /* requestCode */, browserIntent, 0 /* flags */);
Jason Monk697b82a2017-04-19 18:41:06 -0400614 ComponentName aiaComponent = null;
615 try {
616 aiaComponent = AppGlobals.getPackageManager().getInstantAppInstallerComponent();
617 } catch (RemoteException e) {
618 e.rethrowFromSystemServer();
619 }
620 Intent goToWebIntent = new Intent()
621 .setComponent(aiaComponent)
622 .setAction(Intent.ACTION_VIEW)
623 .addCategory(Intent.CATEGORY_BROWSABLE)
Jason Monk83c00512017-05-08 11:23:14 -0400624 .addCategory("unique:" + System.currentTimeMillis())
Jason Monk697b82a2017-04-19 18:41:06 -0400625 .putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName)
Dianne Hackborn3accca02013-09-20 09:32:11 -0700626 .putExtra(Intent.EXTRA_VERSION_CODE, (int) (appInfo.versionCode & 0x7fffffff))
Patrick Baumann531db462018-02-13 13:01:47 -0800627 .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.versionCode)
Patrick Baumann531db462018-02-13 13:01:47 -0800628 .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent);
Jason Monk697b82a2017-04-19 18:41:06 -0400629
630 PendingIntent webPendingIntent = PendingIntent.getActivity(mContext, 0, goToWebIntent, 0);
631 Action webAction = new Notification.Action.Builder(null, mContext.getString(R.string.go_to_web),
632 webPendingIntent).build();
633 builder.addAction(webAction);
634 }
635
636 noMan.notifyAsUser(pkg, SystemMessage.NOTE_INSTANT_APPS, builder
Jason Monk324b8862017-02-16 17:19:12 -0500637 .addExtras(extras)
638 .addAction(action)
639 .setContentIntent(appInfoAction)
640 .setColor(mContext.getColor(R.color.instant_apps_color))
641 .setContentTitle(appInfo.loadLabel(mContext.getPackageManager()))
642 .setLargeIcon(Icon.createWithResource(pkg, appInfo.icon))
643 .setSmallIcon(Icon.createWithResource(mContext.getPackageName(),
644 R.drawable.instant_icon))
645 .setContentText(message)
646 .setOngoing(true)
647 .build(),
648 new UserHandle(userId));
649 }
650
Jason Monk697b82a2017-04-19 18:41:06 -0400651 private Intent getTaskIntent(int taskId, int userId) {
Winson Chung5fa39752017-10-04 14:50:15 -0700652 try {
653 final List<ActivityManager.RecentTaskInfo> tasks =
654 ActivityManager.getService().getRecentTasks(
655 NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId).getList();
656 for (int i = 0; i < tasks.size(); i++) {
657 if (tasks.get(i).id == taskId) {
658 return tasks.get(i).baseIntent;
659 }
Jason Monk697b82a2017-04-19 18:41:06 -0400660 }
Winson Chung5fa39752017-10-04 14:50:15 -0700661 } catch (RemoteException e) {
662 // Fall through
Jason Monk697b82a2017-04-19 18:41:06 -0400663 }
664 return null;
665 }
666
Jason Monk324b8862017-02-16 17:19:12 -0500667 private boolean hasNotif(ArraySet<Pair<String, Integer>> notifs, String pkg, int userId) {
668 Pair<String, Integer> key = new Pair<>(pkg, userId);
669 if (notifs.remove(key)) {
670 mCurrentNotifs.add(key);
671 return true;
672 }
673 return false;
674 }
675
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800676 private final SynchronousUserSwitchObserver mUserSwitchListener =
677 new SynchronousUserSwitchObserver() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100678 @Override
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800679 public void onUserSwitching(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100680 mHandler.post(() -> mUserInfoController.reloadUserInfo());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100681 }
682
683 @Override
684 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100685 mHandler.post(() -> {
686 updateAlarm();
Tony Makec319ab2017-03-28 18:50:01 +0100687 updateManagedProfile();
688 updateForegroundInstantApps();
Toni Barzice97f9232016-04-27 18:10:58 -0700689 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100690 }
691 };
692
Jason Monk952d5d82014-10-27 15:28:22 -0400693 private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
694 @Override
Rohan Shahe4071122018-01-22 15:16:09 -0800695 public void onHotspotChanged(boolean enabled, int numDevices) {
Jason Monk3e189872016-01-12 09:10:34 -0500696 mIconController.setIconVisibility(mSlotHotspot, enabled);
Jason Monk952d5d82014-10-27 15:28:22 -0400697 }
698 };
699
John Spurlock96fe98d2014-08-27 09:36:02 -0400700 private final CastController.Callback mCastCallback = new CastController.Callback() {
701 @Override
702 public void onCastDevicesChanged() {
703 updateCast();
704 }
705 };
Kenny Guy3094d4a2015-04-01 19:14:10 +0100706
Juan Flores2ff37202015-04-30 13:44:23 +0200707 private final NextAlarmController.NextAlarmChangeCallback mNextAlarmCallback =
708 new NextAlarmController.NextAlarmChangeCallback() {
Jason Monk324b8862017-02-16 17:19:12 -0500709 @Override
710 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
Evan Lairdbee3eb82018-05-16 15:58:49 -0400711 mNextAlarm = nextAlarm;
Jason Monk324b8862017-02-16 17:19:12 -0500712 updateAlarm();
713 }
714 };
Juan Flores2ff37202015-04-30 13:44:23 +0200715
Jason Monkaa573e92017-01-27 17:00:29 -0500716 @Override
717 public void appTransitionStarting(long startTime, long duration, boolean forced) {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100718 updateManagedProfile();
Jason Monk324b8862017-02-16 17:19:12 -0500719 updateForegroundInstantApps();
Kenny Guy3094d4a2015-04-01 19:14:10 +0100720 }
721
Jason Monkaa573e92017-01-27 17:00:29 -0500722 @Override
723 public void onKeyguardShowingChanged() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100724 updateManagedProfile();
Jason Monk324b8862017-02-16 17:19:12 -0500725 updateForegroundInstantApps();
Kenny Guy3094d4a2015-04-01 19:14:10 +0100726 }
John Spurlock604a5ee2015-06-01 12:27:22 -0400727
Jason Monkaa573e92017-01-27 17:00:29 -0500728 @Override
729 public void onUserSetupChanged() {
730 boolean userSetup = mProvisionedController.isUserSetup(
731 mProvisionedController.getCurrentUser());
John Spurlock604a5ee2015-06-01 12:27:22 -0400732 if (mCurrentUserSetup == userSetup) return;
733 mCurrentUserSetup = userSetup;
734 updateAlarm();
735 }
Jason Monk3e189872016-01-12 09:10:34 -0500736
737 @Override
Jason Monk324b8862017-02-16 17:19:12 -0500738 public void preloadRecentApps() {
739 updateForegroundInstantApps();
740 }
741
742 @Override
Jason Monk3e189872016-01-12 09:10:34 -0500743 public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
744 boolean portrait = RotationLockTile.isCurrentOrientationLockPortrait(
745 mRotationLockController, mContext);
746 if (rotationLocked) {
747 if (portrait) {
748 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_portrait,
749 mContext.getString(R.string.accessibility_rotation_lock_on_portrait));
750 } else {
751 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape,
752 mContext.getString(R.string.accessibility_rotation_lock_on_landscape));
753 }
Jason Monk8816dff2016-02-09 21:50:36 -0500754 mIconController.setIconVisibility(mSlotRotate, true);
Jason Monk3e189872016-01-12 09:10:34 -0500755 } else {
Jason Monk8816dff2016-02-09 21:50:36 -0500756 mIconController.setIconVisibility(mSlotRotate, false);
Jason Monk3e189872016-01-12 09:10:34 -0500757 }
758 }
759
760 private void updateHeadsetPlug(Intent intent) {
761 boolean connected = intent.getIntExtra("state", 0) != 0;
762 boolean hasMic = intent.getIntExtra("microphone", 0) != 0;
763 if (connected) {
764 String contentDescription = mContext.getString(hasMic
765 ? R.string.accessibility_status_bar_headset
766 : R.string.accessibility_status_bar_headphones);
767 mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.ic_headset_mic
768 : R.drawable.ic_headset, contentDescription);
769 mIconController.setIconVisibility(mSlotHeadset, true);
770 } else {
771 mIconController.setIconVisibility(mSlotHeadset, false);
772 }
773 }
774
Jason Monkf23aa992016-01-22 16:45:21 -0500775 @Override
776 public void onDataSaverChanged(boolean isDataSaving) {
777 mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
778 }
779
Winson Chungaa357452017-10-31 11:35:30 -0700780 private final SysUiTaskStackChangeListener mTaskListener = new SysUiTaskStackChangeListener() {
Jason Monk324b8862017-02-16 17:19:12 -0500781 @Override
782 public void onTaskStackChanged() {
783 // Listen for changes to stacks and then check which instant apps are foreground.
784 updateForegroundInstantApps();
785 }
786 };
787
Jason Monk3e189872016-01-12 09:10:34 -0500788 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
789 @Override
790 public void onReceive(Context context, Intent intent) {
791 String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800792 switch (action) {
793 case AudioManager.RINGER_MODE_CHANGED_ACTION:
794 case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
795 updateVolumeZen();
796 break;
797 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
798 // Avoid rebroadcast because SysUI is direct boot aware.
799 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK,
800 false)) {
801 break;
802 }
803 updateSimState(intent);
804 break;
805 case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED:
806 updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
807 TelecomManager.TTY_MODE_OFF));
808 break;
809 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
810 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
811 case Intent.ACTION_MANAGED_PROFILE_REMOVED:
812 updateManagedProfile();
813 break;
814 case AudioManager.ACTION_HEADSET_PLUG:
815 updateHeadsetPlug(intent);
816 break;
Jason Monk3e189872016-01-12 09:10:34 -0500817 }
818 }
819 };
820
821 private Runnable mRemoveCastIconRunnable = new Runnable() {
822 @Override
823 public void run() {
824 if (DEBUG) Log.v(TAG, "updateCast: hiding icon NOW");
825 mIconController.setIconVisibility(mSlotCast, false);
826 }
827 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828}