blob: e0c5e59b73f36d7b02b52c73bbdb0af8544c0bb7 [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;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070026import android.app.ActivityTaskManager;
Jason Monk697b82a2017-04-19 18:41:06 -040027import android.app.AlarmManager;
John Spurlock604a5ee2015-06-01 12:27:22 -040028import android.app.AlarmManager.AlarmClockInfo;
Jason Monk697b82a2017-04-19 18:41:06 -040029import android.app.AppGlobals;
30import android.app.Notification;
Jason Monk324b8862017-02-16 17:19:12 -050031import android.app.Notification.Action;
Jason Monk697b82a2017-04-19 18:41:06 -040032import android.app.NotificationManager;
33import android.app.PendingIntent;
34import android.app.SynchronousUserSwitchObserver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.content.BroadcastReceiver;
Jason Monk697b82a2017-04-19 18:41:06 -040036import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.content.Context;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.content.Intent;
39import android.content.IntentFilter;
Jason Monk324b8862017-02-16 17:19:12 -050040import android.content.pm.ApplicationInfo;
41import android.content.pm.IPackageManager;
42import android.content.pm.PackageManager;
Jason Monk324b8862017-02-16 17:19:12 -050043import android.graphics.drawable.Icon;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.media.AudioManager;
Jason Monk324b8862017-02-16 17:19:12 -050045import android.net.Uri;
46import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.os.Handler;
Kenny Guy3094d4a2015-04-01 19:14:10 +010048import android.os.RemoteException;
Adrian Roosc42a1e12014-07-07 23:35:53 +020049import android.os.UserHandle;
Kenny Guy3094d4a2015-04-01 19:14:10 +010050import android.os.UserManager;
Jason Monk324b8862017-02-16 17:19:12 -050051import android.provider.Settings;
John Spurlockae641c92014-06-30 18:11:40 -040052import android.provider.Settings.Global;
Jason Monk324b8862017-02-16 17:19:12 -050053import android.service.notification.StatusBarNotification;
Beverlyb9826dd2018-04-12 15:02:45 -040054import android.service.notification.ZenModeConfig;
Tyler Gunnef9f6f92014-09-12 22:16:17 -070055import android.telecom.TelecomManager;
Evan Lairdbee3eb82018-05-16 15:58:49 -040056import android.text.format.DateFormat;
Jason Monk324b8862017-02-16 17:19:12 -050057import android.util.ArraySet;
John Spurlockcd686b52013-06-05 10:13:46 -040058import android.util.Log;
Jason Monk324b8862017-02-16 17:19:12 -050059import android.util.Pair;
Beverlyff2df9b2018-10-10 16:54:10 -040060
Jason Monk324b8862017-02-16 17:19:12 -050061import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Wink Savillea639b312012-07-10 12:37:54 -070062import com.android.internal.telephony.IccCardConstants;
Wink Saville04e71b32009-04-02 11:00:54 -070063import com.android.internal.telephony.TelephonyIntents;
Jason Monk9c7844c2017-01-18 15:21:53 -050064import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040065import com.android.systemui.DockedStackExistsListener;
Joe Onorato798ac4c2010-05-27 16:39:00 -040066import com.android.systemui.R;
Jason Monkaa573e92017-01-27 17:00:29 -050067import com.android.systemui.SysUiServiceProvider;
Jorim Jaggifabc7432017-05-15 02:40:05 +020068import com.android.systemui.UiOffloadThread;
Evan Lairdcf1a1032018-11-14 13:46:08 -050069import com.android.systemui.privacy.PrivacyItem;
70import com.android.systemui.privacy.PrivacyItemController;
John Spurlock3c4076a2015-02-24 12:12:25 -050071import com.android.systemui.qs.tiles.DndTile;
Jason Monk3e189872016-01-12 09:10:34 -050072import com.android.systemui.qs.tiles.RotationLockTile;
Winson Chung2cf6ad82017-11-09 17:36:59 -080073import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chung67f5c8b2018-09-24 12:09:19 -070074import com.android.systemui.shared.system.TaskStackChangeListener;
Jason Monkaa573e92017-01-27 17:00:29 -050075import com.android.systemui.statusbar.CommandQueue;
76import com.android.systemui.statusbar.CommandQueue.Callbacks;
Jason Monk70364362015-08-06 16:32:18 -040077import com.android.systemui.statusbar.policy.BluetoothController;
78import com.android.systemui.statusbar.policy.BluetoothController.Callback;
John Spurlock96fe98d2014-08-27 09:36:02 -040079import com.android.systemui.statusbar.policy.CastController;
80import com.android.systemui.statusbar.policy.CastController.CastDevice;
Jason Monkf23aa992016-01-22 16:45:21 -050081import com.android.systemui.statusbar.policy.DataSaverController;
Jason Monkaa573e92017-01-27 17:00:29 -050082import com.android.systemui.statusbar.policy.DataSaverController.Listener;
83import com.android.systemui.statusbar.policy.DeviceProvisionedController;
84import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
Jason Monk952d5d82014-10-27 15:28:22 -040085import com.android.systemui.statusbar.policy.HotspotController;
Jason Monkaa573e92017-01-27 17:00:29 -050086import com.android.systemui.statusbar.policy.KeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -040087import com.android.systemui.statusbar.policy.LocationController;
Juan Flores2ff37202015-04-30 13:44:23 +020088import com.android.systemui.statusbar.policy.NextAlarmController;
Jason Monk3e189872016-01-12 09:10:34 -050089import com.android.systemui.statusbar.policy.RotationLockController;
Jason Monkaa573e92017-01-27 17:00:29 -050090import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
Adrian Roos88b11932015-07-22 14:59:48 -070091import com.android.systemui.statusbar.policy.UserInfoController;
Jason Monkaa573e92017-01-27 17:00:29 -050092import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monk324b8862017-02-16 17:19:12 -050093import com.android.systemui.util.NotificationChannels;
94
Fabian Kozynskia6ff80b2019-02-12 11:32:44 -050095import java.io.PrintWriter;
96import java.io.StringWriter;
Jason Monk697b82a2017-04-19 18:41:06 -040097import java.util.List;
Evan Lairdbee3eb82018-05-16 15:58:49 -040098import java.util.Locale;
Jason Monk697b82a2017-04-19 18:41:06 -040099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100/**
101 * This class contains all of the policy about which icons are installed in the status
Joe Onorato798ac4c2010-05-27 16:39:00 -0400102 * bar at boot time. It goes through the normal API for icons, even though it probably
103 * strictly doesn't need to.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 */
Jason Monkaa573e92017-01-27 17:00:29 -0500105public class PhoneStatusBarPolicy implements Callback, Callbacks,
Fabian Kozynskied5dfd92018-12-20 15:00:48 -0500106 RotationLockControllerCallback, Listener, ZenModeController.Callback,
107 DeviceProvisionedListener, KeyguardMonitor.Callback, PrivacyItemController.Callback {
Joe Onoratofd52b182010-11-10 18:00:52 -0800108 private static final String TAG = "PhoneStatusBarPolicy";
John Spurlocka37e9c82014-07-08 09:40:31 -0400109 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
Robert Greenwaltd7085fc2010-09-08 15:24:47 -0700110
Jason Monk359bb742017-04-13 10:40:40 -0400111 public static final int LOCATION_STATUS_ICON_ID = R.drawable.stat_sys_location;
Jason Monk697b82a2017-04-19 18:41:06 -0400112 public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
Jason Monk359bb742017-04-13 10:40:40 -0400113
Jason Monk3e189872016-01-12 09:10:34 -0500114 private final String mSlotCast;
115 private final String mSlotHotspot;
116 private final String mSlotBluetooth;
117 private final String mSlotTty;
118 private final String mSlotZen;
119 private final String mSlotVolume;
120 private final String mSlotAlarmClock;
121 private final String mSlotManagedProfile;
122 private final String mSlotRotate;
123 private final String mSlotHeadset;
Jason Monkf23aa992016-01-22 16:45:21 -0500124 private final String mSlotDataSaver;
Jason Monk359bb742017-04-13 10:40:40 -0400125 private final String mSlotLocation;
Evan Lairdcf1a1032018-11-14 13:46:08 -0500126 private final String mSlotMicrophone;
127 private final String mSlotCamera;
John Spurlocka37e9c82014-07-08 09:40:31 -0400128
Dianne Hackborn4840e142009-03-24 22:40:29 -0700129 private final Context mContext;
Joe Onorato10523b4d2010-10-25 10:42:46 -0700130 private final Handler mHandler = new Handler();
John Spurlock96fe98d2014-08-27 09:36:02 -0400131 private final CastController mCast;
Jason Monk952d5d82014-10-27 15:28:22 -0400132 private final HotspotController mHotspot;
Evan Lairdbee3eb82018-05-16 15:58:49 -0400133 private final NextAlarmController mNextAlarmController;
John Spurlock15782262015-05-29 15:35:53 -0400134 private final AlarmManager mAlarmManager;
Adrian Roos88b11932015-07-22 14:59:48 -0700135 private final UserInfoController mUserInfoController;
Rubin Xu1205fb12015-11-04 17:45:03 +0000136 private final UserManager mUserManager;
Jason Monk07473ce2016-01-05 14:59:19 -0500137 private final StatusBarIconController mIconController;
Jason Monk3e189872016-01-12 09:10:34 -0500138 private final RotationLockController mRotationLockController;
Jason Monkf23aa992016-01-22 16:45:21 -0500139 private final DataSaverController mDataSaver;
Jason Monkaa573e92017-01-27 17:00:29 -0500140 private final ZenModeController mZenController;
141 private final DeviceProvisionedController mProvisionedController;
142 private final KeyguardMonitor mKeyguardMonitor;
Jason Monk359bb742017-04-13 10:40:40 -0400143 private final LocationController mLocationController;
Evan Lairdcf1a1032018-11-14 13:46:08 -0500144 private final PrivacyItemController mPrivacyItemController;
Jason Monk324b8862017-02-16 17:19:12 -0500145 private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200146 private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 // Assume it's all good unless we hear otherwise. We don't always seem
149 // to get broadcasts that it *is* there.
Wink Savillea639b312012-07-10 12:37:54 -0700150 IccCardConstants.State mSimState = IccCardConstants.State.READY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151
John Spurlocka37e9c82014-07-08 09:40:31 -0400152 private boolean mZenVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 private boolean mVolumeVisible;
John Spurlock604a5ee2015-06-01 12:27:22 -0400154 private boolean mCurrentUserSetup;
Jason Monkf85fc962017-04-19 17:13:41 -0400155 private boolean mDockedStackExists;
Wink Saville04e71b32009-04-02 11:00:54 -0700156
Rubin Xu1205fb12015-11-04 17:45:03 +0000157 private boolean mManagedProfileIconVisible = false;
Kenny Guy3094d4a2015-04-01 19:14:10 +0100158
Jason Monk70364362015-08-06 16:32:18 -0400159 private BluetoothController mBluetooth;
Evan Lairdbee3eb82018-05-16 15:58:49 -0400160 private AlarmManager.AlarmClockInfo mNextAlarm;
Wink Savillee9b06d72009-05-18 21:47:50 -0700161
Jason Monk9c7844c2017-01-18 15:21:53 -0500162 public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 mContext = context;
Jason Monk07473ce2016-01-05 14:59:19 -0500164 mIconController = iconController;
Jason Monk9c7844c2017-01-18 15:21:53 -0500165 mCast = Dependency.get(CastController.class);
166 mHotspot = Dependency.get(HotspotController.class);
167 mBluetooth = Dependency.get(BluetoothController.class);
Evan Lairdbee3eb82018-05-16 15:58:49 -0400168 mNextAlarmController = Dependency.get(NextAlarmController.class);
John Spurlock15782262015-05-29 15:35:53 -0400169 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500170 mUserInfoController = Dependency.get(UserInfoController.class);
Rubin Xu1205fb12015-11-04 17:45:03 +0000171 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Jason Monk9c7844c2017-01-18 15:21:53 -0500172 mRotationLockController = Dependency.get(RotationLockController.class);
173 mDataSaver = Dependency.get(DataSaverController.class);
Jason Monkaa573e92017-01-27 17:00:29 -0500174 mZenController = Dependency.get(ZenModeController.class);
175 mProvisionedController = Dependency.get(DeviceProvisionedController.class);
176 mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
Jason Monk359bb742017-04-13 10:40:40 -0400177 mLocationController = Dependency.get(LocationController.class);
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500178 mPrivacyItemController = Dependency.get(PrivacyItemController.class);
Jason Monk3e189872016-01-12 09:10:34 -0500179
180 mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
181 mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
182 mSlotBluetooth = context.getString(com.android.internal.R.string.status_bar_bluetooth);
183 mSlotTty = context.getString(com.android.internal.R.string.status_bar_tty);
184 mSlotZen = context.getString(com.android.internal.R.string.status_bar_zen);
185 mSlotVolume = context.getString(com.android.internal.R.string.status_bar_volume);
186 mSlotAlarmClock = context.getString(com.android.internal.R.string.status_bar_alarm_clock);
187 mSlotManagedProfile = context.getString(
188 com.android.internal.R.string.status_bar_managed_profile);
189 mSlotRotate = context.getString(com.android.internal.R.string.status_bar_rotate);
190 mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
Jason Monkf23aa992016-01-22 16:45:21 -0500191 mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
Jason Monk359bb742017-04-13 10:40:40 -0400192 mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
Evan Lairdcf1a1032018-11-14 13:46:08 -0500193 mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone);
194 mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400196 // listen for broadcasts
197 IntentFilter filter = new IntentFilter();
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400198 filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
John Spurlockbcc10872014-11-28 15:29:21 -0500199 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
Jason Monk3e189872016-01-12 09:10:34 -0500200 filter.addAction(AudioManager.ACTION_HEADSET_PLUG);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400201 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700202 filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
Rubin Xue95057a2016-04-01 16:49:25 +0100203 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
204 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
Nicolas Prevot6c7b8742016-04-13 10:28:58 +0100205 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
Daniel Sandlere3b7a2d2011-10-27 16:16:15 -0400206 mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
207
Kenny Guy3094d4a2015-04-01 19:14:10 +0100208 // listen for user / profile change.
209 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800210 ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
Kenny Guy3094d4a2015-04-01 19:14:10 +0100211 } catch (RemoteException e) {
212 // Ignore
213 }
214
Wink Saville04e71b32009-04-02 11:00:54 -0700215 // TTY status
Hall Liu108ca202017-07-24 15:19:04 -0700216 updateTTY();
Wink Saville04e71b32009-04-02 11:00:54 -0700217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 // bluetooth status
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700219 updateBluetooth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 // Alarm clock
Jason Monk3e189872016-01-12 09:10:34 -0500222 mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
223 mIconController.setIconVisibility(mSlotAlarmClock, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224
John Spurlocka37e9c82014-07-08 09:40:31 -0400225 // zen
Jason Monk3e189872016-01-12 09:10:34 -0500226 mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
227 mIconController.setIconVisibility(mSlotZen, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 // volume
Jason Monk3e189872016-01-12 09:10:34 -0500230 mIconController.setIcon(mSlotVolume, R.drawable.stat_sys_ringer_vibrate, null);
231 mIconController.setIconVisibility(mSlotVolume, false);
John Spurlocka37e9c82014-07-08 09:40:31 -0400232 updateVolumeZen();
John Spurlock96fe98d2014-08-27 09:36:02 -0400233
234 // cast
Jason Monk3e189872016-01-12 09:10:34 -0500235 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
236 mIconController.setIconVisibility(mSlotCast, false);
Jason Monk952d5d82014-10-27 15:28:22 -0400237
238 // hotspot
Jason Monk3e189872016-01-12 09:10:34 -0500239 mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
Jason Monk08187a42015-06-09 14:33:51 -0400240 mContext.getString(R.string.accessibility_status_bar_hotspot));
Jason Monk3e189872016-01-12 09:10:34 -0500241 mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100242
243 // managed profile
Jason Monk3e189872016-01-12 09:10:34 -0500244 mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
Adrian Roos1b5eb972015-06-11 18:22:52 -0700245 mContext.getString(R.string.accessibility_managed_profile));
Jason Monk3e189872016-01-12 09:10:34 -0500246 mIconController.setIconVisibility(mSlotManagedProfile, mManagedProfileIconVisible);
Jason Monkf23aa992016-01-22 16:45:21 -0500247
248 // data saver
249 mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
250 context.getString(R.string.accessibility_data_saver_on));
251 mIconController.setIconVisibility(mSlotDataSaver, false);
Jason Monkaa573e92017-01-27 17:00:29 -0500252
Evan Lairdcf1a1032018-11-14 13:46:08 -0500253 // privacy items
254 mIconController.setIcon(mSlotMicrophone, R.drawable.stat_sys_mic_none, null);
255 mIconController.setIconVisibility(mSlotMicrophone, false);
256 mIconController.setIcon(mSlotCamera, R.drawable.stat_sys_camera, null);
257 mIconController.setIconVisibility(mSlotCamera, false);
Fabian Kozynskied5dfd92018-12-20 15:00:48 -0500258 mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
259 mContext.getString(R.string.accessibility_location_active));
260 mIconController.setIconVisibility(mSlotLocation, false);
Evan Lairdcf1a1032018-11-14 13:46:08 -0500261
Jason Monkaa573e92017-01-27 17:00:29 -0500262 mRotationLockController.addCallback(this);
263 mBluetooth.addCallback(this);
264 mProvisionedController.addCallback(this);
265 mZenController.addCallback(this);
266 mCast.addCallback(mCastCallback);
267 mHotspot.addCallback(mHotspotCallback);
Evan Lairdbee3eb82018-05-16 15:58:49 -0400268 mNextAlarmController.addCallback(mNextAlarmCallback);
Jason Monk88529052016-11-04 13:29:58 -0400269 mDataSaver.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500270 mKeyguardMonitor.addCallback(this);
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500271 mPrivacyItemController.addCallback(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500272
Jason Monkd7c98552018-12-04 11:14:50 -0500273 SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
Winson Chung2cf6ad82017-11-09 17:36:59 -0800274 ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
Jason Monk324b8862017-02-16 17:19:12 -0500275
276 // Clear out all old notifications on startup (only present in the case where sysui dies)
277 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
278 for (StatusBarNotification notification : noMan.getActiveNotifications()) {
279 if (notification.getId() == SystemMessage.NOTE_INSTANT_APPS) {
280 noMan.cancel(notification.getTag(), notification.getId());
281 }
282 }
Jason Monkf85fc962017-04-19 17:13:41 -0400283 DockedStackExistsListener.register(exists -> {
284 mDockedStackExists = exists;
285 updateForegroundInstantApps();
286 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 }
288
Jason Monkaa573e92017-01-27 17:00:29 -0500289 @Override
290 public void onZenChanged(int zen) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400291 updateVolumeZen();
John Spurlockba2c6a02014-05-19 09:44:06 -0400292 }
293
Jason Monk359bb742017-04-13 10:40:40 -0400294 @Override
Beverlyb9826dd2018-04-12 15:02:45 -0400295 public void onConfigChanged(ZenModeConfig config) {
296 updateVolumeZen();
297 }
298
Adrian Roosc42a1e12014-07-07 23:35:53 +0200299 private void updateAlarm() {
John Spurlock604a5ee2015-06-01 12:27:22 -0400300 final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
301 final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
Jason Monk20c0eb42017-03-02 17:35:49 -0500302 int zen = mZenController.getZen();
303 final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
Jason Monk3e189872016-01-12 09:10:34 -0500304 mIconController.setIcon(mSlotAlarmClock, zenNone ? R.drawable.stat_sys_alarm_dim
Evan Lairdbee3eb82018-05-16 15:58:49 -0400305 : R.drawable.stat_sys_alarm, buildAlarmContentDescription());
Jason Monk3e189872016-01-12 09:10:34 -0500306 mIconController.setIconVisibility(mSlotAlarmClock, mCurrentUserSetup && hasAlarm);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 }
308
Evan Lairdbee3eb82018-05-16 15:58:49 -0400309 private String buildAlarmContentDescription() {
310 if (mNextAlarm == null) {
311 return mContext.getString(R.string.status_bar_alarm);
312 }
313 return formatNextAlarm(mNextAlarm, mContext);
314 }
315
316 private static String formatNextAlarm(AlarmManager.AlarmClockInfo info, Context context) {
317 if (info == null) {
318 return "";
319 }
320 String skeleton = DateFormat.is24HourFormat(
321 context, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma";
322 String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);
323 String dateString = DateFormat.format(pattern, info.getTriggerTime()).toString();
324
325 return context.getString(R.string.accessibility_quick_settings_alarm, dateString);
326 }
327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 private final void updateSimState(Intent intent) {
Wink Savillea639b312012-07-10 12:37:54 -0700329 String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
330 if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
331 mSimState = IccCardConstants.State.ABSENT;
Jason Monk07473ce2016-01-05 14:59:19 -0500332 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
Rakesh Pallerlaf099a5f2013-02-06 11:44:23 +0530333 mSimState = IccCardConstants.State.CARD_IO_ERROR;
Junda Liua2f6a672016-05-24 10:07:40 -0700334 } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED.equals(stateExtra)) {
335 mSimState = IccCardConstants.State.CARD_RESTRICTED;
Jason Monk07473ce2016-01-05 14:59:19 -0500336 } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700337 mSimState = IccCardConstants.State.READY;
Jason Monk07473ce2016-01-05 14:59:19 -0500338 } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
Wink Savillea639b312012-07-10 12:37:54 -0700339 final String lockedReason =
340 intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
341 if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
342 mSimState = IccCardConstants.State.PIN_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500343 } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
Wink Savillea639b312012-07-10 12:37:54 -0700344 mSimState = IccCardConstants.State.PUK_REQUIRED;
Jason Monk07473ce2016-01-05 14:59:19 -0500345 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700346 mSimState = IccCardConstants.State.NETWORK_LOCKED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 }
348 } else {
Wink Savillea639b312012-07-10 12:37:54 -0700349 mSimState = IccCardConstants.State.UNKNOWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 }
352
John Spurlockbcc10872014-11-28 15:29:21 -0500353 private final void updateVolumeZen() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
John Spurlocka37e9c82014-07-08 09:40:31 -0400355
356 boolean zenVisible = false;
357 int zenIconId = 0;
358 String zenDescription = null;
359
360 boolean volumeVisible = false;
361 int volumeIconId = 0;
362 String volumeDescription = null;
Jason Monk20c0eb42017-03-02 17:35:49 -0500363 int zen = mZenController.getZen();
John Spurlocka37e9c82014-07-08 09:40:31 -0400364
John Spurlockf88d8082015-03-25 18:09:51 -0400365 if (DndTile.isVisible(mContext) || DndTile.isCombinedIcon(mContext)) {
Jason Monk20c0eb42017-03-02 17:35:49 -0500366 zenVisible = zen != Global.ZEN_MODE_OFF;
Evan Lairda9adbd52018-05-16 11:32:08 -0400367 zenIconId = R.drawable.stat_sys_dnd;
John Spurlock3c4076a2015-02-24 12:12:25 -0500368 zenDescription = mContext.getString(R.string.quick_settings_dnd_label);
Jason Monk20c0eb42017-03-02 17:35:49 -0500369 } else if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400370 zenVisible = true;
371 zenIconId = R.drawable.stat_sys_zen_none;
John Spurlockd9c75db2015-04-28 11:19:13 -0400372 zenDescription = mContext.getString(R.string.interruption_level_none);
Jason Monk20c0eb42017-03-02 17:35:49 -0500373 } else if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
John Spurlocka37e9c82014-07-08 09:40:31 -0400374 zenVisible = true;
375 zenIconId = R.drawable.stat_sys_zen_important;
John Spurlockd9c75db2015-04-28 11:19:13 -0400376 zenDescription = mContext.getString(R.string.interruption_level_priority);
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700377 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378
Beverlyff2df9b2018-10-10 16:54:10 -0400379 if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConsolidatedPolicy())) {
Beverlyb9826dd2018-04-12 15:02:45 -0400380 if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
381 volumeVisible = true;
382 volumeIconId = R.drawable.stat_sys_ringer_vibrate;
383 volumeDescription = mContext.getString(R.string.accessibility_ringer_vibrate);
384 } else if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_SILENT) {
385 volumeVisible = true;
386 volumeIconId = R.drawable.stat_sys_ringer_silent;
387 volumeDescription = mContext.getString(R.string.accessibility_ringer_silent);
388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 }
John Spurlocka37e9c82014-07-08 09:40:31 -0400390
391 if (zenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500392 mIconController.setIcon(mSlotZen, zenIconId, zenDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400393 }
394 if (zenVisible != mZenVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500395 mIconController.setIconVisibility(mSlotZen, zenVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400396 mZenVisible = zenVisible;
397 }
398
399 if (volumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500400 mIconController.setIcon(mSlotVolume, volumeIconId, volumeDescription);
John Spurlocka37e9c82014-07-08 09:40:31 -0400401 }
402 if (volumeVisible != mVolumeVisible) {
Jason Monk3e189872016-01-12 09:10:34 -0500403 mIconController.setIconVisibility(mSlotVolume, volumeVisible);
John Spurlocka37e9c82014-07-08 09:40:31 -0400404 mVolumeVisible = volumeVisible;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 }
John Spurlock15782262015-05-29 15:35:53 -0400406 updateAlarm();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 }
408
Jason Monk70364362015-08-06 16:32:18 -0400409 @Override
410 public void onBluetoothDevicesChanged() {
411 updateBluetooth();
412 }
413
414 @Override
415 public void onBluetoothStateChange(boolean enabled) {
416 updateBluetooth();
417 }
418
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700419 private final void updateBluetooth() {
Joe Onorato798ac4c2010-05-27 16:39:00 -0400420 int iconId = R.drawable.stat_sys_data_bluetooth;
Jorim Jaggi2d75f9f2014-10-08 17:10:58 -0700421 String contentDescription =
Jason Monk1aa32822015-07-14 16:10:32 -0400422 mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500423 boolean bluetoothVisible = false;
Jason Monk70364362015-08-06 16:32:18 -0400424 if (mBluetooth != null) {
Jason Monk70364362015-08-06 16:32:18 -0400425 if (mBluetooth.isBluetoothConnected()) {
Jaikumar Ganeshd9bb6882010-09-27 17:05:24 -0700426 iconId = R.drawable.stat_sys_data_bluetooth_connected;
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700427 contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500428 bluetoothVisible = mBluetooth.isBluetoothEnabled();
Jaikumar Ganesh084c6652009-12-07 10:58:18 -0800429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 }
Wink Savillee9b06d72009-05-18 21:47:50 -0700431
Jason Monk3e189872016-01-12 09:10:34 -0500432 mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
Evan Laird3cdf47e2018-01-29 16:01:41 -0500433 mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 }
435
Hall Liu108ca202017-07-24 15:19:04 -0700436 private final void updateTTY() {
437 TelecomManager telecomManager =
438 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
439 if (telecomManager == null) {
440 updateTTY(TelecomManager.TTY_MODE_OFF);
441 } else {
442 updateTTY(telecomManager.getCurrentTtyMode());
443 }
444 }
445
446 private final void updateTTY(int currentTtyMode) {
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700447 boolean enabled = currentTtyMode != TelecomManager.TTY_MODE_OFF;
Wink Saville04e71b32009-04-02 11:00:54 -0700448
John Spurlocka37e9c82014-07-08 09:40:31 -0400449 if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled);
Wink Saville04e71b32009-04-02 11:00:54 -0700450
451 if (enabled) {
452 // TTY is on
John Spurlocka37e9c82014-07-08 09:40:31 -0400453 if (DEBUG) Log.v(TAG, "updateTTY: set TTY on");
Jason Monk3e189872016-01-12 09:10:34 -0500454 mIconController.setIcon(mSlotTty, R.drawable.stat_sys_tty_mode,
Svetoslav Ganov6179ea32011-06-28 01:12:41 -0700455 mContext.getString(R.string.accessibility_tty_enabled));
Jason Monk3e189872016-01-12 09:10:34 -0500456 mIconController.setIconVisibility(mSlotTty, true);
Wink Saville04e71b32009-04-02 11:00:54 -0700457 } else {
458 // TTY is off
John Spurlocka37e9c82014-07-08 09:40:31 -0400459 if (DEBUG) Log.v(TAG, "updateTTY: set TTY off");
Jason Monk3e189872016-01-12 09:10:34 -0500460 mIconController.setIconVisibility(mSlotTty, false);
Wink Saville04e71b32009-04-02 11:00:54 -0700461 }
462 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400463
464 private void updateCast() {
465 boolean isCasting = false;
466 for (CastDevice device : mCast.getCastDevices()) {
467 if (device.state == CastDevice.STATE_CONNECTING
468 || device.state == CastDevice.STATE_CONNECTED) {
469 isCasting = true;
470 break;
471 }
472 }
473 if (DEBUG) Log.v(TAG, "updateCast: isCasting: " + isCasting);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700474 mHandler.removeCallbacks(mRemoveCastIconRunnable);
John Spurlock96fe98d2014-08-27 09:36:02 -0400475 if (isCasting) {
Jason Monk3e189872016-01-12 09:10:34 -0500476 mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast,
John Spurlock96fe98d2014-08-27 09:36:02 -0400477 mContext.getString(R.string.accessibility_casting));
Jason Monk3e189872016-01-12 09:10:34 -0500478 mIconController.setIconVisibility(mSlotCast, true);
Dan Sandler8fd25bf2015-10-20 16:01:27 -0700479 } else {
480 // don't turn off the screen-record icon for a few seconds, just to make sure the user
481 // has seen it
482 if (DEBUG) Log.v(TAG, "updateCast: hiding icon in 3 sec...");
483 mHandler.postDelayed(mRemoveCastIconRunnable, 3000);
John Spurlock96fe98d2014-08-27 09:36:02 -0400484 }
John Spurlock96fe98d2014-08-27 09:36:02 -0400485 }
486
Kenny Guy3094d4a2015-04-01 19:14:10 +0100487 private void updateManagedProfile() {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200488 // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
489 // some cases. Since it doesn't really matter here whether it's updated in this frame
490 // or in the next one, we call this method from our UI offload thread.
491 mUiOffloadThread.submit(() -> {
492 final int userId;
493 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700494 userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200495 boolean isManagedProfile = mUserManager.isManagedProfile(userId);
496 mHandler.post(() -> {
497 final boolean showIcon;
Pavel Grafov410d8082017-06-29 18:42:32 +0100498 if (isManagedProfile &&
499 (!mKeyguardMonitor.isShowing() || mKeyguardMonitor.isOccluded())) {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200500 showIcon = true;
501 mIconController.setIcon(mSlotManagedProfile,
502 R.drawable.stat_sys_managed_profile_status,
503 mContext.getString(R.string.accessibility_managed_profile));
Jorim Jaggifabc7432017-05-15 02:40:05 +0200504 } else {
505 showIcon = false;
506 }
507 if (mManagedProfileIconVisible != showIcon) {
508 mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
509 mManagedProfileIconVisible = showIcon;
510 }
511 });
512 } catch (RemoteException e) {
513 Log.w(TAG, "updateManagedProfile: ", e);
Tony Makec319ab2017-03-28 18:50:01 +0100514 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200515 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100516 }
517
Jason Monk324b8862017-02-16 17:19:12 -0500518 private void updateForegroundInstantApps() {
519 NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
520 ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
521 IPackageManager pm = AppGlobals.getPackageManager();
522 mCurrentNotifs.clear();
Jorim Jaggifabc7432017-05-15 02:40:05 +0200523 mUiOffloadThread.submit(() -> {
524 try {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700525 final StackInfo focusedStack =
526 ActivityTaskManager.getService().getFocusedStackInfo();
Wale Ogunwale68278562017-09-23 17:13:55 -0700527 if (focusedStack != null) {
528 final int windowingMode =
529 focusedStack.configuration.windowConfiguration.getWindowingMode();
530 if (windowingMode == WINDOWING_MODE_FULLSCREEN
531 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
532 checkStack(focusedStack, notifs, noMan, pm);
533 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200534 }
535 if (mDockedStackExists) {
Wale Ogunwale68278562017-09-23 17:13:55 -0700536 checkStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED,
537 notifs, noMan, pm);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200538 }
539 } catch (RemoteException e) {
540 e.rethrowFromSystemServer();
Jason Monkf85fc962017-04-19 17:13:41 -0400541 }
Jorim Jaggifabc7432017-05-15 02:40:05 +0200542 // Cancel all the leftover notifications that don't have a foreground process anymore.
543 notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
544 new UserHandle(v.second)));
545 });
Jason Monk324b8862017-02-16 17:19:12 -0500546 }
547
Wale Ogunwale68278562017-09-23 17:13:55 -0700548 private void checkStack(int windowingMode, int activityType,
549 ArraySet<Pair<String, Integer>> notifs, NotificationManager noMan, IPackageManager pm) {
550 try {
551 final StackInfo info =
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700552 ActivityTaskManager.getService().getStackInfo(windowingMode, activityType);
Wale Ogunwale68278562017-09-23 17:13:55 -0700553 checkStack(info, notifs, noMan, pm);
554 } catch (RemoteException e) {
555 e.rethrowFromSystemServer();
556 }
557 }
558 private void checkStack(StackInfo info, ArraySet<Pair<String, Integer>> notifs,
Jason Monkf85fc962017-04-19 17:13:41 -0400559 NotificationManager noMan, IPackageManager pm) {
560 try {
Jason Monkf85fc962017-04-19 17:13:41 -0400561 if (info == null || info.topActivity == null) return;
562 String pkg = info.topActivity.getPackageName();
563 if (!hasNotif(notifs, pkg, info.userId)) {
564 // TODO: Optimize by not always needing to get application info.
565 // Maybe cache non-ephemeral packages?
566 ApplicationInfo appInfo = pm.getApplicationInfo(pkg,
567 PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
568 if (appInfo.isInstantApp()) {
Jason Monk697b82a2017-04-19 18:41:06 -0400569 postEphemeralNotif(pkg, info.userId, appInfo, noMan, info.taskIds[info.taskIds.length - 1]);
Jason Monkf85fc962017-04-19 17:13:41 -0400570 }
571 }
572 } catch (RemoteException e) {
573 e.rethrowFromSystemServer();
574 }
575 }
576
Jason Monk324b8862017-02-16 17:19:12 -0500577 private void postEphemeralNotif(String pkg, int userId, ApplicationInfo appInfo,
Jason Monk697b82a2017-04-19 18:41:06 -0400578 NotificationManager noMan, int taskId) {
Jason Monk324b8862017-02-16 17:19:12 -0500579 final Bundle extras = new Bundle();
580 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
581 mContext.getString(R.string.instant_apps));
582 mCurrentNotifs.add(new Pair<>(pkg, userId));
Gus Prevas71e15d12018-09-21 09:46:28 -0400583
584 String helpUrl = mContext.getString(R.string.instant_apps_help_url);
585 boolean hasHelpUrl = !helpUrl.isEmpty();
586 String message = mContext.getString(hasHelpUrl
587 ? R.string.instant_apps_message_with_help
588 : R.string.instant_apps_message);
589
Hai Zhang6102dfa2018-08-29 15:55:33 -0700590 UserHandle user = UserHandle.of(userId);
591 PendingIntent appInfoAction = PendingIntent.getActivityAsUser(mContext, 0,
Jason Monk324b8862017-02-16 17:19:12 -0500592 new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
Hai Zhang6102dfa2018-08-29 15:55:33 -0700593 .setData(Uri.fromParts("package", pkg, null)), 0, null, user);
Jason Monk324b8862017-02-16 17:19:12 -0500594 Action action = new Notification.Action.Builder(null, mContext.getString(R.string.app_info),
595 appInfoAction).build();
Gus Prevas71e15d12018-09-21 09:46:28 -0400596 PendingIntent helpCenterIntent = hasHelpUrl
597 ? PendingIntent.getActivityAsUser(mContext, 0,
598 new Intent(Intent.ACTION_VIEW).setData(Uri.parse(
599 helpUrl)),
600 0, null, user)
601 : null;
Jason Monk324b8862017-02-16 17:19:12 -0500602
Jason Monk697b82a2017-04-19 18:41:06 -0400603 Intent browserIntent = getTaskIntent(taskId, userId);
Gus Prevas71e15d12018-09-21 09:46:28 -0400604 Notification.Builder builder = new Notification.Builder(mContext,
605 NotificationChannels.GENERAL);
Patrick Baumann531db462018-02-13 13:01:47 -0800606 if (browserIntent != null && browserIntent.isWebIntent()) {
Jesse Evansa2024a22017-04-20 14:44:49 -0700607 // Make sure that this doesn't resolve back to an instant app
608 browserIntent.setComponent(null)
609 .setPackage(null)
610 .addFlags(Intent.FLAG_IGNORE_EPHEMERAL)
611 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
612
Hai Zhang6102dfa2018-08-29 15:55:33 -0700613 PendingIntent pendingIntent = PendingIntent.getActivityAsUser(mContext,
614 0 /* requestCode */, browserIntent, 0 /* flags */, null, user);
Jason Monk697b82a2017-04-19 18:41:06 -0400615 ComponentName aiaComponent = null;
616 try {
617 aiaComponent = AppGlobals.getPackageManager().getInstantAppInstallerComponent();
618 } catch (RemoteException e) {
619 e.rethrowFromSystemServer();
620 }
621 Intent goToWebIntent = new Intent()
622 .setComponent(aiaComponent)
623 .setAction(Intent.ACTION_VIEW)
624 .addCategory(Intent.CATEGORY_BROWSABLE)
Jason Monk83c00512017-05-08 11:23:14 -0400625 .addCategory("unique:" + System.currentTimeMillis())
Jason Monk697b82a2017-04-19 18:41:06 -0400626 .putExtra(Intent.EXTRA_PACKAGE_NAME, appInfo.packageName)
Dianne Hackborn3accca02013-09-20 09:32:11 -0700627 .putExtra(Intent.EXTRA_VERSION_CODE, (int) (appInfo.versionCode & 0x7fffffff))
Patrick Baumann531db462018-02-13 13:01:47 -0800628 .putExtra(Intent.EXTRA_LONG_VERSION_CODE, appInfo.versionCode)
Patrick Baumann531db462018-02-13 13:01:47 -0800629 .putExtra(Intent.EXTRA_INSTANT_APP_FAILURE, pendingIntent);
Jason Monk697b82a2017-04-19 18:41:06 -0400630
Hai Zhang6102dfa2018-08-29 15:55:33 -0700631 PendingIntent webPendingIntent = PendingIntent.getActivityAsUser(mContext, 0,
632 goToWebIntent, 0, null, user);
Gus Prevas71e15d12018-09-21 09:46:28 -0400633 Action webAction = new Notification.Action.Builder(null,
634 mContext.getString(R.string.go_to_web),
Jason Monk697b82a2017-04-19 18:41:06 -0400635 webPendingIntent).build();
636 builder.addAction(webAction);
637 }
638
639 noMan.notifyAsUser(pkg, SystemMessage.NOTE_INSTANT_APPS, builder
Jason Monk324b8862017-02-16 17:19:12 -0500640 .addExtras(extras)
641 .addAction(action)
Gus Prevas71e15d12018-09-21 09:46:28 -0400642 .setContentIntent(helpCenterIntent)
Jason Monk324b8862017-02-16 17:19:12 -0500643 .setColor(mContext.getColor(R.color.instant_apps_color))
Gus Prevas71e15d12018-09-21 09:46:28 -0400644 .setContentTitle(mContext.getString(R.string.instant_apps_title,
645 appInfo.loadLabel(mContext.getPackageManager())))
Jason Monk324b8862017-02-16 17:19:12 -0500646 .setLargeIcon(Icon.createWithResource(pkg, appInfo.icon))
647 .setSmallIcon(Icon.createWithResource(mContext.getPackageName(),
648 R.drawable.instant_icon))
649 .setContentText(message)
Gus Prevas71e15d12018-09-21 09:46:28 -0400650 .setStyle(new Notification.BigTextStyle().bigText(message))
Jason Monk324b8862017-02-16 17:19:12 -0500651 .setOngoing(true)
652 .build(),
653 new UserHandle(userId));
654 }
655
Jason Monk697b82a2017-04-19 18:41:06 -0400656 private Intent getTaskIntent(int taskId, int userId) {
Winson Chung5fa39752017-10-04 14:50:15 -0700657 try {
658 final List<ActivityManager.RecentTaskInfo> tasks =
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700659 ActivityTaskManager.getService().getRecentTasks(
Winson Chung5fa39752017-10-04 14:50:15 -0700660 NUM_TASKS_FOR_INSTANT_APP_INFO, 0, userId).getList();
661 for (int i = 0; i < tasks.size(); i++) {
662 if (tasks.get(i).id == taskId) {
663 return tasks.get(i).baseIntent;
664 }
Jason Monk697b82a2017-04-19 18:41:06 -0400665 }
Winson Chung5fa39752017-10-04 14:50:15 -0700666 } catch (RemoteException e) {
667 // Fall through
Jason Monk697b82a2017-04-19 18:41:06 -0400668 }
669 return null;
670 }
671
Jason Monk324b8862017-02-16 17:19:12 -0500672 private boolean hasNotif(ArraySet<Pair<String, Integer>> notifs, String pkg, int userId) {
673 Pair<String, Integer> key = new Pair<>(pkg, userId);
674 if (notifs.remove(key)) {
675 mCurrentNotifs.add(key);
676 return true;
677 }
678 return false;
679 }
680
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800681 private final SynchronousUserSwitchObserver mUserSwitchListener =
682 new SynchronousUserSwitchObserver() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100683 @Override
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -0800684 public void onUserSwitching(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100685 mHandler.post(() -> mUserInfoController.reloadUserInfo());
Kenny Guy3094d4a2015-04-01 19:14:10 +0100686 }
687
688 @Override
689 public void onUserSwitchComplete(int newUserId) throws RemoteException {
Tony Makec319ab2017-03-28 18:50:01 +0100690 mHandler.post(() -> {
691 updateAlarm();
Tony Makec319ab2017-03-28 18:50:01 +0100692 updateManagedProfile();
693 updateForegroundInstantApps();
Toni Barzice97f9232016-04-27 18:10:58 -0700694 });
Kenny Guy3094d4a2015-04-01 19:14:10 +0100695 }
696 };
697
Jason Monk952d5d82014-10-27 15:28:22 -0400698 private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
699 @Override
Rohan Shahe4071122018-01-22 15:16:09 -0800700 public void onHotspotChanged(boolean enabled, int numDevices) {
Jason Monk3e189872016-01-12 09:10:34 -0500701 mIconController.setIconVisibility(mSlotHotspot, enabled);
Jason Monk952d5d82014-10-27 15:28:22 -0400702 }
703 };
704
John Spurlock96fe98d2014-08-27 09:36:02 -0400705 private final CastController.Callback mCastCallback = new CastController.Callback() {
706 @Override
707 public void onCastDevicesChanged() {
708 updateCast();
709 }
710 };
Kenny Guy3094d4a2015-04-01 19:14:10 +0100711
Juan Flores2ff37202015-04-30 13:44:23 +0200712 private final NextAlarmController.NextAlarmChangeCallback mNextAlarmCallback =
713 new NextAlarmController.NextAlarmChangeCallback() {
Jason Monk324b8862017-02-16 17:19:12 -0500714 @Override
715 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
Evan Lairdbee3eb82018-05-16 15:58:49 -0400716 mNextAlarm = nextAlarm;
Jason Monk324b8862017-02-16 17:19:12 -0500717 updateAlarm();
718 }
719 };
Juan Flores2ff37202015-04-30 13:44:23 +0200720
Jason Monkaa573e92017-01-27 17:00:29 -0500721 @Override
Charles Chenf3d295c2018-11-30 18:15:21 +0800722 public void appTransitionStarting(int displayId, long startTime, long duration,
723 boolean forced) {
724 if (mContext.getDisplayId() == displayId) {
725 updateManagedProfile();
726 updateForegroundInstantApps();
727 }
Kenny Guy3094d4a2015-04-01 19:14:10 +0100728 }
729
Jason Monkaa573e92017-01-27 17:00:29 -0500730 @Override
731 public void onKeyguardShowingChanged() {
Kenny Guy3094d4a2015-04-01 19:14:10 +0100732 updateManagedProfile();
Jason Monk324b8862017-02-16 17:19:12 -0500733 updateForegroundInstantApps();
Kenny Guy3094d4a2015-04-01 19:14:10 +0100734 }
John Spurlock604a5ee2015-06-01 12:27:22 -0400735
Jason Monkaa573e92017-01-27 17:00:29 -0500736 @Override
737 public void onUserSetupChanged() {
738 boolean userSetup = mProvisionedController.isUserSetup(
739 mProvisionedController.getCurrentUser());
John Spurlock604a5ee2015-06-01 12:27:22 -0400740 if (mCurrentUserSetup == userSetup) return;
741 mCurrentUserSetup = userSetup;
742 updateAlarm();
743 }
Jason Monk3e189872016-01-12 09:10:34 -0500744
745 @Override
Jason Monk324b8862017-02-16 17:19:12 -0500746 public void preloadRecentApps() {
747 updateForegroundInstantApps();
748 }
749
750 @Override
Jason Monk3e189872016-01-12 09:10:34 -0500751 public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
752 boolean portrait = RotationLockTile.isCurrentOrientationLockPortrait(
753 mRotationLockController, mContext);
754 if (rotationLocked) {
755 if (portrait) {
756 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_portrait,
757 mContext.getString(R.string.accessibility_rotation_lock_on_portrait));
758 } else {
759 mIconController.setIcon(mSlotRotate, R.drawable.stat_sys_rotate_landscape,
760 mContext.getString(R.string.accessibility_rotation_lock_on_landscape));
761 }
Jason Monk8816dff2016-02-09 21:50:36 -0500762 mIconController.setIconVisibility(mSlotRotate, true);
Jason Monk3e189872016-01-12 09:10:34 -0500763 } else {
Jason Monk8816dff2016-02-09 21:50:36 -0500764 mIconController.setIconVisibility(mSlotRotate, false);
Jason Monk3e189872016-01-12 09:10:34 -0500765 }
766 }
767
768 private void updateHeadsetPlug(Intent intent) {
769 boolean connected = intent.getIntExtra("state", 0) != 0;
770 boolean hasMic = intent.getIntExtra("microphone", 0) != 0;
771 if (connected) {
772 String contentDescription = mContext.getString(hasMic
773 ? R.string.accessibility_status_bar_headset
774 : R.string.accessibility_status_bar_headphones);
775 mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.ic_headset_mic
776 : R.drawable.ic_headset, contentDescription);
777 mIconController.setIconVisibility(mSlotHeadset, true);
778 } else {
779 mIconController.setIconVisibility(mSlotHeadset, false);
780 }
781 }
782
Jason Monkf23aa992016-01-22 16:45:21 -0500783 @Override
784 public void onDataSaverChanged(boolean isDataSaving) {
785 mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
786 }
787
Evan Lairdcf1a1032018-11-14 13:46:08 -0500788 @Override // PrivacyItemController.Callback
789 public void privacyChanged(List<PrivacyItem> privacyItems) {
790 updatePrivacyItems(privacyItems);
791 }
792
793 private void updatePrivacyItems(List<PrivacyItem> items) {
794 boolean showCamera = false;
795 boolean showMicrophone = false;
796 boolean showLocation = false;
797 for (PrivacyItem item : items) {
Fabian Kozynskia6ff80b2019-02-12 11:32:44 -0500798 if (item == null /* b/124234367 */) {
799 if (DEBUG) {
800 Log.e(TAG, "updatePrivacyItems - null item found");
801 StringWriter out = new StringWriter();
802 mPrivacyItemController.dump(null, new PrintWriter(out), null);
803 Log.e(TAG, out.toString());
804 }
805 continue;
806 }
Evan Lairdcf1a1032018-11-14 13:46:08 -0500807 switch (item.getPrivacyType()) {
808 case TYPE_CAMERA:
809 showCamera = true;
810 break;
811 case TYPE_LOCATION:
812 showLocation = true;
813 break;
814 case TYPE_MICROPHONE:
815 showMicrophone = true;
816 break;
817 }
818 }
819
820 mIconController.setIconVisibility(mSlotCamera, showCamera);
821 mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
822 mIconController.setIconVisibility(mSlotLocation, showLocation);
823 }
824
Winson Chung67f5c8b2018-09-24 12:09:19 -0700825 private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
Jason Monk324b8862017-02-16 17:19:12 -0500826 @Override
827 public void onTaskStackChanged() {
828 // Listen for changes to stacks and then check which instant apps are foreground.
829 updateForegroundInstantApps();
830 }
831 };
832
Jason Monk3e189872016-01-12 09:10:34 -0500833 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
834 @Override
835 public void onReceive(Context context, Intent intent) {
836 String action = intent.getAction();
Lucas Dupin5e0f0d22018-02-26 13:32:16 -0800837 switch (action) {
838 case AudioManager.RINGER_MODE_CHANGED_ACTION:
839 case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
840 updateVolumeZen();
841 break;
842 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
843 // Avoid rebroadcast because SysUI is direct boot aware.
844 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK,
845 false)) {
846 break;
847 }
848 updateSimState(intent);
849 break;
850 case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED:
851 updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
852 TelecomManager.TTY_MODE_OFF));
853 break;
854 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
855 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
856 case Intent.ACTION_MANAGED_PROFILE_REMOVED:
857 updateManagedProfile();
858 break;
859 case AudioManager.ACTION_HEADSET_PLUG:
860 updateHeadsetPlug(intent);
861 break;
Jason Monk3e189872016-01-12 09:10:34 -0500862 }
863 }
864 };
865
866 private Runnable mRemoveCastIconRunnable = new Runnable() {
867 @Override
868 public void run() {
869 if (DEBUG) Log.v(TAG, "updateCast: hiding icon NOW");
870 mIconController.setIconVisibility(mSlotCast, false);
871 }
872 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873}