blob: faf143e098fd5054e76ff87396aa48e11dc72f61 [file] [log] [blame]
Joe Onorato2314aab2010-04-08 16:41:23 -05001/*
2 * Copyright (C) 2010 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 Onorato79de0c52010-05-26 17:03:26 -040017package com.android.systemui.statusbar;
Joe Onorato2314aab2010-04-08 16:41:23 -050018
Dan Sandler4247a5c2014-07-23 15:58:08 -040019import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
Christopher Tate5e08af02012-09-21 17:17:22 -070021import android.app.ActivityManager;
Jorim Jaggie6e108e2016-03-28 13:38:45 -070022import android.app.ActivityManager.StackId;
Jorim Jaggie6e108e2016-03-28 13:38:45 -070023import android.app.ActivityOptions;
Geoffrey Pitsch4dd50062016-12-06 16:41:22 -050024import android.app.INotificationManager;
Ricky Wai7fa01712016-03-16 12:13:54 +000025import android.app.KeyguardManager;
Chris Wren51c75102013-07-16 20:49:17 -040026import android.app.Notification;
Chris Wrencd8f4f72014-08-27 18:48:13 -040027import android.app.NotificationManager;
Daniel Sandler6a858c32012-03-12 14:38:58 -040028import android.app.PendingIntent;
Adrian Roos497ab022015-02-10 20:49:33 +010029import android.app.RemoteInput;
Adam Powell0fc5b2b2012-07-18 18:20:29 -070030import android.app.TaskStackBuilder;
Adrian Roosbd3409c2014-08-12 18:21:09 +020031import android.app.admin.DevicePolicyManager;
Daniel Sandlerb9301c32012-08-14 15:08:24 -040032import android.content.BroadcastReceiver;
Christoph Studer60748e72014-05-22 16:51:41 +020033import android.content.ComponentName;
Joe Onorato808182d2010-07-09 18:52:06 -040034import android.content.Context;
Daniel Sandler6a858c32012-03-12 14:38:58 -040035import android.content.Intent;
Daniel Sandlerb9301c32012-08-14 15:08:24 -040036import android.content.IntentFilter;
Ricky Wai7fa01712016-03-16 12:13:54 +000037import android.content.IntentSender;
Daniel Sandler96fd7c12012-03-30 16:37:36 -040038import android.content.pm.ApplicationInfo;
Dan Sandlera5e0f412014-01-23 15:11:54 -050039import android.content.pm.PackageManager;
Daniel Sandler96fd7c12012-03-30 16:37:36 -040040import android.content.pm.PackageManager.NameNotFoundException;
Kenny Guy3a7c4a52014-03-03 18:24:03 +000041import android.content.pm.UserInfo;
John Spurlockde84f0e2013-06-12 12:41:00 -040042import android.content.res.Configuration;
Daniel Sandler26cda272012-05-22 15:44:08 -040043import android.database.ContentObserver;
Jorim Jaggi86905582016-02-09 21:36:09 -080044import android.graphics.Rect;
Jorim Jaggi8de4311c2014-08-11 22:36:20 +020045import android.os.AsyncTask;
Daniel Sandler96fd7c12012-03-30 16:37:36 -040046import android.os.Build;
Jorim Jaggi165ce062015-07-06 16:18:11 -070047import android.os.Bundle;
Michael Jurka7f2668c2012-03-27 07:49:52 -070048import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040049import android.os.IBinder;
Michael Jurka7f2668c2012-03-27 07:49:52 -070050import android.os.Message;
Chris Wren157026f2013-06-28 16:54:01 -040051import android.os.PowerManager;
Joe Onorato808182d2010-07-09 18:52:06 -040052import android.os.RemoteException;
53import android.os.ServiceManager;
Adrian Roos497ab022015-02-10 20:49:33 +010054import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070055import android.os.UserHandle;
Kenny Guy3a7c4a52014-03-03 18:24:03 +000056import android.os.UserManager;
Daniel Sandlerf7a19562012-04-04 14:04:21 -040057import android.provider.Settings;
Chris Wren157026f2013-06-28 16:54:01 -040058import android.service.dreams.DreamService;
59import android.service.dreams.IDreamManager;
Christoph Studer60748e72014-05-22 16:51:41 +020060import android.service.notification.NotificationListenerService;
Christoph Studerd0694b62014-06-04 16:36:01 +020061import android.service.notification.NotificationListenerService.RankingMap;
John Spurlockde84f0e2013-06-12 12:41:00 -040062import android.service.notification.StatusBarNotification;
Dan Sandlerdc34df52016-04-07 21:04:46 -040063import android.service.vr.IVrManager;
64import android.service.vr.IVrStateCallbacks;
Chris Wren0c8275b2012-05-08 13:36:48 -040065import android.text.TextUtils;
Selim Cinek2d79f632015-11-02 15:13:29 -080066import android.util.ArraySet;
Joe Onorato808182d2010-07-09 18:52:06 -040067import android.util.Log;
Dan Sandlere163a642015-03-01 22:58:32 -050068import android.util.Slog;
Kenny Guy3a7c4a52014-03-03 18:24:03 +000069import android.util.SparseArray;
Dan Sandlerfd16d562014-02-13 18:43:31 -080070import android.util.SparseBooleanArray;
Daniel Sandlerc638c1e2011-08-24 16:19:23 -070071import android.view.Display;
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -050072import android.view.IWindowManager;
Michael Jurka7f2668c2012-03-27 07:49:52 -070073import android.view.LayoutInflater;
74import android.view.MotionEvent;
Joe Onorato808182d2010-07-09 18:52:06 -040075import android.view.View;
Dan Sandler4247a5c2014-07-23 15:58:08 -040076import android.view.ViewAnimationUtils;
Daniel Sandler6a858c32012-03-12 14:38:58 -040077import android.view.ViewGroup;
Christoph Studer4da84cd2014-10-21 17:24:20 +020078import android.view.ViewParent;
Joe Onorato808182d2010-07-09 18:52:06 -040079import android.view.WindowManager;
Michael Jurka80343f62012-10-18 13:13:46 +020080import android.view.WindowManagerGlobal;
Selim Cineka8fefa52014-09-08 16:10:50 +020081import android.view.accessibility.AccessibilityManager;
Michael Jurkaa600fd92012-06-25 15:57:05 -070082import android.widget.RemoteViews;
Daniel Sandlerb9301c32012-08-14 15:08:24 -040083import android.widget.TextView;
Kenny Guydae30d52015-04-01 19:11:35 +010084import android.widget.Toast;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050085
Chris Wrenbd6b5fb2015-06-09 14:58:34 -040086import com.android.internal.logging.MetricsLogger;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010087import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Chris Wren5e6c0ff2017-01-05 12:57:06 -050088import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
John Spurlockde84f0e2013-06-12 12:41:00 -040089import com.android.internal.statusbar.IStatusBarService;
90import com.android.internal.statusbar.StatusBarIcon;
Chris Wrencd8f4f72014-08-27 18:48:13 -040091import com.android.internal.widget.LockPatternUtils;
Mady Mellor97c8df42016-03-22 18:09:39 -070092import com.android.keyguard.KeyguardHostView.OnDismissAction;
Selim Cinekfa760d42016-05-10 15:50:53 -040093import com.android.keyguard.KeyguardUpdateMonitor;
Jorim Jaggi5eb67c22015-08-19 19:50:49 -070094import com.android.systemui.DejankUtils;
Winsonc0d70582016-01-29 10:24:39 -080095import com.android.systemui.Interpolators;
John Spurlockde84f0e2013-06-12 12:41:00 -040096import com.android.systemui.R;
John Spurlockd08de372013-06-24 13:06:08 -040097import com.android.systemui.RecentsComponent;
Dan Sandler4247a5c2014-07-23 15:58:08 -040098import com.android.systemui.SwipeHelper;
John Spurlockde84f0e2013-06-12 12:41:00 -040099import com.android.systemui.SystemUI;
Jorim Jaggib835dd72015-06-08 12:28:42 -0700100import com.android.systemui.assist.AssistManager;
Jorim Jaggid61f2272014-12-19 20:35:35 +0100101import com.android.systemui.recents.Recents;
Christoph Studer37fe6932014-05-26 13:10:30 +0200102import com.android.systemui.statusbar.NotificationData.Entry;
Mady Mellor97c8df42016-03-22 18:09:39 -0700103import com.android.systemui.statusbar.NotificationGuts.OnGutsClosedListener;
Selim Cineka7d4f822016-12-06 14:34:47 -0800104import com.android.systemui.statusbar.notification.VisualStabilityManager;
Selim Cinek92d892c2014-09-11 15:11:00 +0200105import com.android.systemui.statusbar.phone.NavigationBarView;
Selim Cinek25fd4e2b2015-02-20 17:46:07 +0100106import com.android.systemui.statusbar.phone.NotificationGroupManager;
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200107import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700108import com.android.systemui.statusbar.policy.HeadsUpManager;
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200109import com.android.systemui.statusbar.policy.PreviewInflater;
Adrian Roos497ab022015-02-10 20:49:33 +0100110import com.android.systemui.statusbar.policy.RemoteInputView;
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100111import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Selim Cinekd84a5932015-12-15 11:45:36 -0800112import com.android.systemui.statusbar.stack.StackStateAnimator;
John Spurlockde84f0e2013-06-12 12:41:00 -0400113
Michael Jurkaa600fd92012-06-25 15:57:05 -0700114import java.util.ArrayList;
Julia Reynolds98a44862016-09-12 08:53:47 -0400115import java.util.Collections;
116import java.util.HashSet;
Dan Sandlerf4db75c2014-09-03 18:02:31 +0200117import java.util.List;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700118import java.util.Locale;
Julia Reynolds98a44862016-09-12 08:53:47 -0400119import java.util.Set;
Selim Cineka7d4f822016-12-06 14:34:47 -0800120import java.util.Stack;
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400121
Michael Jurka7f2668c2012-03-27 07:49:52 -0700122public abstract class BaseStatusBar extends SystemUI implements
Winson Chung9214eff2014-06-12 13:59:25 -0700123 CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
Selim Cinek570981d2015-12-01 11:37:01 -0800124 ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
dongwan0605.kimfc975d62017-01-05 10:01:11 +0900125 ExpandableNotificationRow.OnExpandClickListener {
Daniel Sandler198a0302012-08-17 16:04:31 -0400126 public static final String TAG = "StatusBar";
Jorim Jaggi86905582016-02-09 21:36:09 -0800127 public static final boolean DEBUG = false;
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400128 public static final boolean MULTIUSER_DEBUG = false;
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400129
Adrian Roos497ab022015-02-10 20:49:33 +0100130 public static final boolean ENABLE_REMOTE_INPUT =
Adrian Roos9531c9b2015-11-03 17:43:01 -0800131 SystemProperties.getBoolean("debug.enable_remote_input", true);
Selim Cinek40412492015-12-08 18:03:22 -0800132 public static final boolean ENABLE_CHILD_NOTIFICATIONS
133 = SystemProperties.getBoolean("debug.child_notifs", true);
Adrian Roosc0a579e2016-03-30 16:43:58 -0700134 public static final boolean FORCE_REMOTE_INPUT_HISTORY =
135 SystemProperties.getBoolean("debug.force_remoteinput_history", false);
Adrian Roosb27d7a52016-06-16 13:04:47 -0700136 private static boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
Adrian Roos497ab022015-02-10 20:49:33 +0100137
Winson Chung1e8d71b2014-05-16 17:05:22 -0700138 protected static final int MSG_SHOW_RECENT_APPS = 1019;
139 protected static final int MSG_HIDE_RECENT_APPS = 1020;
140 protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700141 protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
142 protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
Winson Chungb1f74992014-08-08 12:53:09 -0700143 protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
144 protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
Andrei Stingaceanuc22ab792016-01-07 12:39:38 +0000145 protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +0100146 protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
Chris Wren0c8275b2012-05-08 13:36:48 -0400147
Chris Wren157026f2013-06-28 16:54:01 -0400148 protected static final boolean ENABLE_HEADS_UP = true;
Chris Wren22ae46e2014-02-26 18:08:09 -0500149 protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
Chris Wren0c8275b2012-05-08 13:36:48 -0400150
Ricky Wai7fa01712016-03-16 12:13:54 +0000151 private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
152
Winsond8b1d632016-01-04 17:51:18 -0800153 // Should match the values in PhoneWindowManager
Michael Jurka56a57832012-05-14 13:24:43 -0700154 public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
Winsond8b1d632016-01-04 17:51:18 -0800155 public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
Michael Jurka56a57832012-05-14 13:24:43 -0700156
Chris Wrencd8f4f72014-08-27 18:48:13 -0400157 private static final String BANNER_ACTION_CANCEL =
158 "com.android.systemui.statusbar.banner_action_cancel";
159 private static final String BANNER_ACTION_SETUP =
160 "com.android.systemui.statusbar.banner_action_setup";
Robin Lee92b83c62016-08-31 13:27:51 +0100161 private static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
Ricky Wai7fa01712016-03-16 12:13:54 +0000162 = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
Chris Wrencd8f4f72014-08-27 18:48:13 -0400163
Joe Onorato808182d2010-07-09 18:52:06 -0400164 protected CommandQueue mCommandQueue;
165 protected IStatusBarService mBarService;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700166 protected H mHandler = createHandler();
167
Chris Wren0c8275b2012-05-08 13:36:48 -0400168 // all notifications
Christoph Studerc8db24b2014-07-25 17:50:30 +0200169 protected NotificationData mNotificationData;
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100170 protected NotificationStackScrollLayout mStackScroller;
Chris Wren0c8275b2012-05-08 13:36:48 -0400171
Selim Cinek25fd4e2b2015-02-20 17:46:07 +0100172 protected NotificationGroupManager mGroupManager = new NotificationGroupManager();
173
Adrian Roosb88b1a12015-12-09 18:51:05 -0800174 protected RemoteInputController mRemoteInputController;
175
Chris Wrena4ef6202014-06-09 18:07:30 -0400176 // for heads up notifications
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700177 protected HeadsUpManager mHeadsUpManager;
Chris Wren0c8275b2012-05-08 13:36:48 -0400178
Selim Cineka7d4f822016-12-06 14:34:47 -0800179 // handling reordering
180 protected VisualStabilityManager mVisualStabilityManager = new VisualStabilityManager();
181
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400182 protected int mCurrentUserId = 0;
Kenny Guy2a764942014-04-02 13:29:20 +0100183 final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400184
Daniel Sandler777dcde2013-09-30 10:21:45 -0400185 protected int mLayoutDirection = -1; // invalid
Selim Cineka8fefa52014-09-08 16:10:50 +0200186 protected AccessibilityManager mAccessibilityManager;
Selim Cinek92d892c2014-09-11 15:11:00 +0200187
Jorim Jaggi50ff3af2015-08-12 18:35:42 -0700188 protected boolean mDeviceInteractive;
Christoph Studere8e28652014-10-29 17:27:53 +0100189
190 protected boolean mVisible;
Selim Cinek2d79f632015-11-02 15:13:29 -0800191 protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>();
Adrian Roos18d099a2016-05-19 15:28:18 -0700192 protected ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>();
Christoph Studere8e28652014-10-29 17:27:53 +0100193
Adrian Roosc0a579e2016-03-30 16:43:58 -0700194 /**
195 * Notifications with keys in this set are not actually around anymore. We kept them around
196 * when they were canceled in response to a remote input interaction. This allows us to show
197 * what you replied and allows you to continue typing into it.
198 */
199 protected ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
200
Christoph Studere8e28652014-10-29 17:27:53 +0100201 // mScreenOnFromKeyguard && mVisible.
202 private boolean mVisibleToUser;
203
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700204 private Locale mLocale;
Dan Sandler539aad42014-08-04 00:43:39 -0400205 private float mFontScale;
206
Chris Wrenf6e83f42013-09-11 14:02:59 -0400207 protected boolean mUseHeadsUp = false;
Chris Wren22ae46e2014-02-26 18:08:09 -0500208 protected boolean mHeadsUpTicker = false;
Jason Monkf7019542014-07-31 12:42:25 -0400209 protected boolean mDisableNotificationAlerts = false;
Chris Wren157026f2013-06-28 16:54:01 -0400210
Adrian Roosbd3409c2014-08-12 18:21:09 +0200211 protected DevicePolicyManager mDevicePolicyManager;
Chris Wren157026f2013-06-28 16:54:01 -0400212 protected IDreamManager mDreamManager;
Julia Reynolds0971cb02016-01-26 17:00:22 -0500213 protected PowerManager mPowerManager;
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200214 protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Dan Sandlerfd16d562014-02-13 18:43:31 -0800215
216 // public mode, private notifications, etc
Robin Lee92b83c62016-08-31 13:27:51 +0100217 private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
Dan Sandlerfd16d562014-02-13 18:43:31 -0800218 private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
Julia Reynolds26fa8a52016-02-24 08:31:22 -0500219 private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700220
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000221 private UserManager mUserManager;
Selim Cinek01af3342016-02-09 19:25:31 -0800222 private int mDensity;
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000223
Robin Lee92b83c62016-08-31 13:27:51 +0100224 protected KeyguardManager mKeyguardManager;
Ricky Wai7fa01712016-03-16 12:13:54 +0000225 private LockPatternUtils mLockPatternUtils;
226
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500227 // UI-specific methods
Daniel Sandler6a858c32012-03-12 14:38:58 -0400228
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500229 /**
230 * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
231 * and add them to the window manager.
232 */
233 protected abstract void createAndAddWindows();
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400234
Jeff Brown98365d72012-08-19 20:30:52 -0700235 protected WindowManager mWindowManager;
236 protected IWindowManager mWindowManagerService;
Christoph Studer60748e72014-05-22 16:51:41 +0200237
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500238 protected Display mDisplay;
Jeff Brown98365d72012-08-19 20:30:52 -0700239
Daniel Sandler26cda272012-05-22 15:44:08 -0400240 private boolean mDeviceProvisioned = false;
Daniel Sandler6a858c32012-03-12 14:38:58 -0400241
Jorim Jaggi75b25972015-10-21 14:51:10 +0200242 protected RecentsComponent mRecents;
John Spurlockd08de372013-06-24 13:06:08 -0400243
John Spurlocke677d712014-02-13 12:52:19 -0500244 protected int mZenMode;
245
Dan Sandler4247a5c2014-07-23 15:58:08 -0400246 // which notification is currently being longpress-examined by the user
Selim Cinek024ca592014-09-01 15:11:28 +0200247 private NotificationGuts mNotificationGutsExposed;
Dan Sandler4247a5c2014-07-23 15:58:08 -0400248
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +0100249 private KeyboardShortcuts mKeyboardShortcuts;
250
Jorim Jaggiecbab362014-04-23 16:13:15 +0200251 /**
252 * The {@link StatusBarState} of the status bar.
253 */
254 protected int mState;
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200255 protected boolean mBouncerShowing;
John Spurlock4b3bda22014-05-22 14:32:20 -0400256 protected boolean mShowLockscreenNotifications;
Adrian Roos3aec6382016-02-05 14:19:01 -0800257 protected boolean mAllowLockscreenRemoteInput;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200258
Selim Cinek281c2022016-10-13 19:14:43 -0700259 protected NotificationShelf mNotificationShelf;
Dan Sandlereceda3d2014-07-21 15:35:01 -0400260 protected DismissView mDismissView;
Jorim Jaggia2052ea2014-08-05 16:22:30 +0200261 protected EmptyShadeView mEmptyShadeView;
Jorim Jaggi649b7082014-04-03 13:15:18 +0200262
Chris Wren42d5dd42015-05-01 10:39:26 -0400263 private NotificationClicker mNotificationClicker = new NotificationClicker();
264
Jorim Jaggib835dd72015-06-08 12:28:42 -0700265 protected AssistManager mAssistManager;
266
Dan Sandlerdc34df52016-04-07 21:04:46 -0400267 protected boolean mVrMode;
268
Julia Reynolds98a44862016-09-12 08:53:47 -0400269 private Set<String> mNonBlockablePkgs;
270
Christoph Studerc8db24b2014-07-25 17:50:30 +0200271 @Override // NotificationData.Environment
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400272 public boolean isDeviceProvisioned() {
Daniel Sandler26cda272012-05-22 15:44:08 -0400273 return mDeviceProvisioned;
274 }
275
Dan Sandlerdc34df52016-04-07 21:04:46 -0400276 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
277 @Override
278 public void onVrStateChanged(boolean enabled) {
279 mVrMode = enabled;
280 }
281 };
282
283 public boolean isDeviceInVrMode() {
284 return mVrMode;
285 }
286
John Spurlocke677d712014-02-13 12:52:19 -0500287 protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
Daniel Sandler26cda272012-05-22 15:44:08 -0400288 @Override
289 public void onChange(boolean selfChange) {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700290 final boolean provisioned = 0 != Settings.Global.getInt(
291 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
Daniel Sandler26cda272012-05-22 15:44:08 -0400292 if (provisioned != mDeviceProvisioned) {
293 mDeviceProvisioned = provisioned;
Christoph Studer37fe6932014-05-26 13:10:30 +0200294 updateNotifications();
Daniel Sandler26cda272012-05-22 15:44:08 -0400295 }
John Spurlocke677d712014-02-13 12:52:19 -0500296 final int mode = Settings.Global.getInt(mContext.getContentResolver(),
297 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
298 setZenMode(mode);
Dan Sandler52e5701e2014-07-22 23:14:54 -0400299
300 updateLockscreenNotificationSetting();
Daniel Sandler26cda272012-05-22 15:44:08 -0400301 }
302 };
303
Dan Sandlerfd16d562014-02-13 18:43:31 -0800304 private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
305 @Override
306 public void onChange(boolean selfChange) {
Daniel U57454872016-03-29 20:28:21 +0100307 // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
308 // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
Dan Sandlerfd16d562014-02-13 18:43:31 -0800309 mUsersAllowingPrivateNotifications.clear();
Daniel U57454872016-03-29 20:28:21 +0100310 mUsersAllowingNotifications.clear();
Dan Sandlerfd16d562014-02-13 18:43:31 -0800311 // ... and refresh all the notifications
Robin Lee9c5799c2016-08-26 15:12:22 +0100312 updateLockscreenNotificationSetting();
Christoph Studer37fe6932014-05-26 13:10:30 +0200313 updateNotifications();
Dan Sandlerfd16d562014-02-13 18:43:31 -0800314 }
315 };
316
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700317 private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
318 @Override
Adrian Roos7d7090d2014-05-21 13:10:23 +0200319 public boolean onClickHandler(
320 final View view, final PendingIntent pendingIntent, final Intent fillInIntent) {
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800321 if (handleRemoteInput(view, pendingIntent, fillInIntent)) {
322 return true;
323 }
324
Daniel Sandler198a0302012-08-17 16:04:31 -0400325 if (DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -0400326 Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
Daniel Sandler198a0302012-08-17 16:04:31 -0400327 }
Christoph Studer4da84cd2014-10-21 17:24:20 +0200328 logActionClick(view);
Jorim Jaggi89f7f282014-10-17 19:54:15 +0200329 // The intent we are sending is for the application, which
330 // won't have permission to immediately start an activity after
331 // the user switches to home. We know it is safe to do at this
332 // point, so make sure new activity switches are now allowed.
333 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800334 ActivityManager.getService().resumeAppSwitches();
Jorim Jaggi89f7f282014-10-17 19:54:15 +0200335 } catch (RemoteException e) {
336 }
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700337 final boolean isActivity = pendingIntent.isActivity();
338 if (isActivity) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200339 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200340 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
341 mContext, pendingIntent.getIntent(), mCurrentUserId);
Adrian Roos4314f6d2014-05-28 14:10:27 +0200342 dismissKeyguardThenExecute(new OnDismissAction() {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200343 @Override
344 public boolean onDismiss() {
Jorim Jaggife762342016-10-13 14:33:27 +0200345 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800346 ActivityManager.getService().resumeAppSwitches();
Jorim Jaggife762342016-10-13 14:33:27 +0200347 } catch (RemoteException e) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200348 }
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700349
Adrian Roos7d7090d2014-05-21 13:10:23 +0200350 boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700351
Adrian Roos7d7090d2014-05-21 13:10:23 +0200352 // close the shade if it was open
353 if (handled) {
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +0100354 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
355 true /* force */);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200356 visibilityChanged(false);
Jorim Jaggi91617a72015-06-25 15:01:29 -0700357 mAssistManager.hideAssist();
Adrian Roos7d7090d2014-05-21 13:10:23 +0200358 }
Jorim Jaggi91617a72015-06-25 15:01:29 -0700359
Adrian Roos4314f6d2014-05-28 14:10:27 +0200360 // Wait for activity start.
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200361 return handled;
Adrian Roos7d7090d2014-05-21 13:10:23 +0200362 }
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200363 }, afterKeyguardGone);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200364 return true;
365 } else {
Jorim Jaggie6e108e2016-03-28 13:38:45 -0700366 return superOnClickHandler(view, pendingIntent, fillInIntent);
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700367 }
Adrian Roos7d7090d2014-05-21 13:10:23 +0200368 }
369
Christoph Studer4da84cd2014-10-21 17:24:20 +0200370 private void logActionClick(View view) {
371 ViewParent parent = view.getParent();
372 String key = getNotificationKeyForParent(parent);
373 if (key == null) {
374 Log.w(TAG, "Couldn't determine notification for click.");
375 return;
376 }
377 int index = -1;
378 // If this is a default template, determine the index of the button.
379 if (view.getId() == com.android.internal.R.id.action0 &&
380 parent != null && parent instanceof ViewGroup) {
381 ViewGroup actionGroup = (ViewGroup) parent;
382 index = actionGroup.indexOfChild(view);
383 }
384 try {
385 mBarService.onNotificationActionClick(key, index);
386 } catch (RemoteException e) {
387 // Ignore
388 }
389 }
390
391 private String getNotificationKeyForParent(ViewParent parent) {
392 while (parent != null) {
393 if (parent instanceof ExpandableNotificationRow) {
394 return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey();
395 }
396 parent = parent.getParent();
397 }
398 return null;
399 }
400
Adrian Roos7d7090d2014-05-21 13:10:23 +0200401 private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
402 Intent fillInIntent) {
Jorim Jaggie6e108e2016-03-28 13:38:45 -0700403 return super.onClickHandler(view, pendingIntent, fillInIntent,
404 StackId.FULLSCREEN_WORKSPACE_STACK_ID);
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700405 }
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800406
407 private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) {
408 Object tag = view.getTag(com.android.internal.R.id.remote_input_tag);
409 RemoteInput[] inputs = null;
410 if (tag instanceof RemoteInput[]) {
411 inputs = (RemoteInput[]) tag;
412 }
413
414 if (inputs == null) {
415 return false;
416 }
417
418 RemoteInput input = null;
419
420 for (RemoteInput i : inputs) {
421 if (i.getAllowFreeFormInput()) {
422 input = i;
423 }
424 }
425
426 if (input == null) {
427 return false;
428 }
429
430 ViewParent p = view.getParent();
431 RemoteInputView riv = null;
432 while (p != null) {
433 if (p instanceof View) {
434 View pv = (View) p;
435 if (pv.isRootNamespace()) {
436 riv = (RemoteInputView) pv.findViewWithTag(RemoteInputView.VIEW_TAG);
437 break;
438 }
439 }
440 p = p.getParent();
441 }
Adrian Roos3aec6382016-02-05 14:19:01 -0800442 ExpandableNotificationRow row = null;
443 while (p != null) {
444 if (p instanceof ExpandableNotificationRow) {
445 row = (ExpandableNotificationRow) p;
446 break;
447 }
448 p = p.getParent();
449 }
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800450
Adrian Roos3aec6382016-02-05 14:19:01 -0800451 if (riv == null || row == null) {
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800452 return false;
453 }
454
Adrian Roos3aec6382016-02-05 14:19:01 -0800455 row.setUserExpanded(true);
456
Ricky Waicd35def2016-05-03 11:07:07 +0100457 if (!mAllowLockscreenRemoteInput) {
Robin Lee92b83c62016-08-31 13:27:51 +0100458 final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
459 if (isLockscreenPublicMode(userId)) {
Ricky Waicd35def2016-05-03 11:07:07 +0100460 onLockedRemoteInput(row, view);
461 return true;
462 }
Ricky Waicd35def2016-05-03 11:07:07 +0100463 if (mUserManager.getUserInfo(userId).isManagedProfile()
464 && mKeyguardManager.isDeviceLocked(userId)) {
465 onLockedWorkRemoteInput(userId, row, view);
466 return true;
467 }
Adrian Roos3aec6382016-02-05 14:19:01 -0800468 }
469
Adrian Roosaf06bf22016-07-15 12:26:49 -0700470 int width = view.getWidth();
471 if (view instanceof TextView) {
472 // Center the reveal on the text which might be off-center from the TextView
473 TextView tv = (TextView) view;
474 if (tv.getLayout() != null) {
475 int innerWidth = (int) tv.getLayout().getLineWidth(0);
476 innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
477 width = Math.min(width, innerWidth);
478 }
479 }
480 int cx = view.getLeft() + width / 2;
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800481 int cy = view.getTop() + view.getHeight() / 2;
482 int w = riv.getWidth();
483 int h = riv.getHeight();
484 int r = Math.max(
485 Math.max(cx + cy, cx + (h - cy)),
486 Math.max((w - cx) + cy, (w - cx) + (h - cy)));
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800487
Adrian Roosaf06bf22016-07-15 12:26:49 -0700488 riv.setRevealParameters(cx, cy, r);
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800489 riv.setPendingIntent(pendingIntent);
490 riv.setRemoteInput(inputs, input);
Adrian Roosaf06bf22016-07-15 12:26:49 -0700491 riv.focusAnimated();
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800492
493 return true;
494 }
495
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700496 };
497
John Spurlock5c454122013-06-17 07:35:46 -0400498 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
499 @Override
500 public void onReceive(Context context, Intent intent) {
501 String action = intent.getAction();
502 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
503 mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Kenny Guy2a764942014-04-02 13:29:20 +0100504 updateCurrentProfilesCache();
John Spurlock5c454122013-06-17 07:35:46 -0400505 if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
Dan Sandler52e5701e2014-07-22 23:14:54 -0400506
507 updateLockscreenNotificationSetting();
508
John Spurlock5c454122013-06-17 07:35:46 -0400509 userSwitched(mCurrentUserId);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000510 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
Kenny Guy2a764942014-04-02 13:29:20 +0100511 updateCurrentProfilesCache();
Kenny Guydae30d52015-04-01 19:11:35 +0100512 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
513 List<ActivityManager.RecentTaskInfo> recentTask = null;
514 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800515 recentTask = ActivityManager.getService().getRecentTasks(1,
Kenny Guydae30d52015-04-01 19:11:35 +0100516 ActivityManager.RECENT_WITH_EXCLUDED
517 | ActivityManager.RECENT_INCLUDE_PROFILES,
Jeff Sharkey479212c2016-06-29 16:00:55 -0600518 mCurrentUserId).getList();
Kenny Guydae30d52015-04-01 19:11:35 +0100519 } catch (RemoteException e) {
520 // Abandon hope activity manager not running.
521 }
522 if (recentTask != null && recentTask.size() > 0) {
523 UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId);
524 if (user != null && user.isManagedProfile()) {
Kenny Guy63bf8ac2015-06-18 15:09:09 +0100525 Toast toast = Toast.makeText(mContext,
526 R.string.managed_profile_foreground_toast,
527 Toast.LENGTH_SHORT);
528 TextView text = (TextView) toast.getView().findViewById(
529 android.R.id.message);
530 text.setCompoundDrawablesRelativeWithIntrinsicBounds(
531 R.drawable.stat_sys_managed_profile_status, 0, 0, 0);
532 int paddingPx = mContext.getResources().getDimensionPixelSize(
533 R.dimen.managed_profile_toast_padding);
534 text.setCompoundDrawablePadding(paddingPx);
Kenny Guy540f7d22015-06-08 20:24:23 +0100535 toast.show();
Kenny Guydae30d52015-04-01 19:11:35 +0100536 }
537 }
Chris Wrencd8f4f72014-08-27 18:48:13 -0400538 } else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
539 NotificationManager noMan = (NotificationManager)
540 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500541 noMan.cancel(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400542
543 Settings.Secure.putInt(mContext.getContentResolver(),
544 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
545 if (BANNER_ACTION_SETUP.equals(action)) {
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +0100546 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
547 true /* force */);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400548 mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
549 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
550
551 );
552 }
Robin Lee92b83c62016-08-31 13:27:51 +0100553 } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
Tony Mak646fe992016-04-21 16:43:08 +0100554 final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
Ricky Wai7fa01712016-03-16 12:13:54 +0000555 final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
Ricky Waicd35def2016-05-03 11:07:07 +0100556 if (intentSender != null) {
557 try {
558 mContext.startIntentSender(intentSender, null, 0, 0, 0);
559 } catch (IntentSender.SendIntentException e) {
560 /* ignore */
561 }
Ricky Wai7fa01712016-03-16 12:13:54 +0000562 }
Ricky Waicd35def2016-05-03 11:07:07 +0100563 if (notificationKey != null) {
564 try {
565 mBarService.onNotificationClick(notificationKey);
566 } catch (RemoteException e) {
567 /* ignore */
568 }
Ricky Wai7fa01712016-03-16 12:13:54 +0000569 }
John Spurlock5c454122013-06-17 07:35:46 -0400570 }
571 }
572 };
573
Kenny Guy0b7dd1e2015-03-12 17:14:38 +0000574 private final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
575 @Override
576 public void onReceive(Context context, Intent intent) {
Robin Lee92b83c62016-08-31 13:27:51 +0100577 final String action = intent.getAction();
578 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
579
Kenny Guy0b7dd1e2015-03-12 17:14:38 +0000580 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
581 isCurrentProfile(getSendingUserId())) {
582 mUsersAllowingPrivateNotifications.clear();
583 updateLockscreenNotificationSetting();
584 updateNotifications();
Robin Lee92b83c62016-08-31 13:27:51 +0100585 } else if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) {
586 if (userId != mCurrentUserId && isCurrentProfile(userId)) {
587 onWorkChallengeChanged();
588 }
Kenny Guy0b7dd1e2015-03-12 17:14:38 +0000589 }
590 }
591 };
592
Christoph Studer60748e72014-05-22 16:51:41 +0200593 private final NotificationListenerService mNotificationListener =
594 new NotificationListenerService() {
595 @Override
596 public void onListenerConnected() {
597 if (DEBUG) Log.d(TAG, "onListenerConnected");
598 final StatusBarNotification[] notifications = getActiveNotifications();
Kent Persson185e9c22014-12-10 16:40:13 +0100599 if (notifications == null) {
600 Log.w(TAG, "onListenerConnected unable to get active notifications.");
601 return;
602 }
Christoph Studerd0694b62014-06-04 16:36:01 +0200603 final RankingMap currentRanking = getCurrentRanking();
Christoph Studer60748e72014-05-22 16:51:41 +0200604 mHandler.post(new Runnable() {
605 @Override
606 public void run() {
607 for (StatusBarNotification sbn : notifications) {
Selim Cinek379ff8f2015-02-20 17:03:16 +0100608 addNotification(sbn, currentRanking, null /* oldEntry */);
Christoph Studer60748e72014-05-22 16:51:41 +0200609 }
610 }
611 });
612 }
613
614 @Override
Christoph Studerd0694b62014-06-04 16:36:01 +0200615 public void onNotificationPosted(final StatusBarNotification sbn,
616 final RankingMap rankingMap) {
Christoph Studer60748e72014-05-22 16:51:41 +0200617 if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
Chris Wren56919552015-02-24 15:56:34 -0500618 if (sbn != null) {
619 mHandler.post(new Runnable() {
620 @Override
621 public void run() {
Adrian Roos497ab022015-02-10 20:49:33 +0100622 processForRemoteInput(sbn.getNotification());
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700623 String key = sbn.getKey();
Adrian Roosc0a579e2016-03-30 16:43:58 -0700624 mKeysKeptForRemoteInput.remove(key);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700625 boolean isUpdate = mNotificationData.get(key) != null;
Selim Cinekb5605e52015-02-20 18:21:41 +0100626 // In case we don't allow child notifications, we ignore children of
627 // notifications that have a summary, since we're not going to show them
628 // anyway. This is true also when the summary is canceled,
Chris Wren56919552015-02-24 15:56:34 -0500629 // because children are automatically canceled by NoMan in that case.
Selim Cinekb5605e52015-02-20 18:21:41 +0100630 if (!ENABLE_CHILD_NOTIFICATIONS
631 && mGroupManager.isChildInGroupWithSummary(sbn)) {
Chris Wren56919552015-02-24 15:56:34 -0500632 if (DEBUG) {
633 Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
634 }
635
636 // Remove existing notification to avoid stale data.
637 if (isUpdate) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700638 removeNotification(key, rankingMap);
Chris Wren56919552015-02-24 15:56:34 -0500639 } else {
640 mNotificationData.updateRanking(rankingMap);
641 }
642 return;
Christoph Studerd722f272014-09-02 11:49:19 +0200643 }
Christoph Studerd722f272014-09-02 11:49:19 +0200644 if (isUpdate) {
Chris Wren56919552015-02-24 15:56:34 -0500645 updateNotification(sbn, rankingMap);
Christoph Studerd722f272014-09-02 11:49:19 +0200646 } else {
Selim Cinek379ff8f2015-02-20 17:03:16 +0100647 addNotification(sbn, rankingMap, null /* oldEntry */);
Christoph Studerd722f272014-09-02 11:49:19 +0200648 }
Christoph Studerd722f272014-09-02 11:49:19 +0200649 }
Chris Wren56919552015-02-24 15:56:34 -0500650 });
651 }
Christoph Studer60748e72014-05-22 16:51:41 +0200652 }
653
654 @Override
Chris Wren56919552015-02-24 15:56:34 -0500655 public void onNotificationRemoved(StatusBarNotification sbn,
Christoph Studerd0694b62014-06-04 16:36:01 +0200656 final RankingMap rankingMap) {
Christoph Studer60748e72014-05-22 16:51:41 +0200657 if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
Chris Wren56919552015-02-24 15:56:34 -0500658 if (sbn != null) {
659 final String key = sbn.getKey();
660 mHandler.post(new Runnable() {
661 @Override
662 public void run() {
663 removeNotification(key, rankingMap);
664 }
665 });
666 }
Christoph Studer37fe6932014-05-26 13:10:30 +0200667 }
668
669 @Override
Christoph Studerd0694b62014-06-04 16:36:01 +0200670 public void onNotificationRankingUpdate(final RankingMap rankingMap) {
Christoph Studer37fe6932014-05-26 13:10:30 +0200671 if (DEBUG) Log.d(TAG, "onRankingUpdate");
Chris Wren56919552015-02-24 15:56:34 -0500672 if (rankingMap != null) {
Christoph Studer37fe6932014-05-26 13:10:30 +0200673 mHandler.post(new Runnable() {
674 @Override
675 public void run() {
Christoph Studere71fefc2014-06-24 16:16:49 +0200676 updateNotificationRanking(rankingMap);
Christoph Studer60748e72014-05-22 16:51:41 +0200677 }
678 });
Chris Wren56919552015-02-24 15:56:34 -0500679 } }
Christoph Studer5b638262014-07-07 11:21:49 +0200680
Christoph Studer60748e72014-05-22 16:51:41 +0200681 };
682
Kenny Guy2a764942014-04-02 13:29:20 +0100683 private void updateCurrentProfilesCache() {
684 synchronized (mCurrentProfiles) {
685 mCurrentProfiles.clear();
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000686 if (mUserManager != null) {
Kenny Guy2a764942014-04-02 13:29:20 +0100687 for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
688 mCurrentProfiles.put(user.id, user);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000689 }
690 }
691 }
692 }
693
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400694 public void start() {
Jeff Brown98365d72012-08-19 20:30:52 -0700695 mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
696 mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
697 mDisplay = mWindowManager.getDefaultDisplay();
Adrian Roosbd3409c2014-08-12 18:21:09 +0200698 mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
699 Context.DEVICE_POLICY_SERVICE);
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500700
Christoph Studerc8db24b2014-07-25 17:50:30 +0200701 mNotificationData = new NotificationData(this);
702
Selim Cineka8fefa52014-09-08 16:10:50 +0200703 mAccessibilityManager = (AccessibilityManager)
704 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
705
Chris Wren157026f2013-06-28 16:54:01 -0400706 mDreamManager = IDreamManager.Stub.asInterface(
707 ServiceManager.checkService(DreamService.DREAM_SERVICE));
Chris Wren157026f2013-06-28 16:54:01 -0400708 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
709
Daniel Sandler26cda272012-05-22 15:44:08 -0400710 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700711 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
John Spurlocke677d712014-02-13 12:52:19 -0500712 mSettingsObserver);
713 mContext.getContentResolver().registerContentObserver(
714 Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
715 mSettingsObserver);
John Spurlock4b3bda22014-05-22 14:32:20 -0400716 mContext.getContentResolver().registerContentObserver(
Dan Sandler52e5701e2014-07-22 23:14:54 -0400717 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
Robin Lee9c5799c2016-08-26 15:12:22 +0100718 mLockscreenSettingsObserver,
Dan Sandler52e5701e2014-07-22 23:14:54 -0400719 UserHandle.USER_ALL);
Adrian Roosb27d7a52016-06-16 13:04:47 -0700720 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
721 mContext.getContentResolver().registerContentObserver(
722 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
723 false,
724 mSettingsObserver,
725 UserHandle.USER_ALL);
726 }
Daniel Sandler26cda272012-05-22 15:44:08 -0400727
Dan Sandlerfd16d562014-02-13 18:43:31 -0800728 mContext.getContentResolver().registerContentObserver(
729 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
730 true,
731 mLockscreenSettingsObserver,
732 UserHandle.USER_ALL);
733
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500734 mBarService = IStatusBarService.Stub.asInterface(
735 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400736
Jorim Jaggid61f2272014-12-19 20:35:35 +0100737 mRecents = getComponent(Recents.class);
John Spurlockd08de372013-06-24 13:06:08 -0400738
Dan Sandler539aad42014-08-04 00:43:39 -0400739 final Configuration currentConfig = mContext.getResources().getConfiguration();
740 mLocale = currentConfig.locale;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700741 mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
Dan Sandler539aad42014-08-04 00:43:39 -0400742 mFontScale = currentConfig.fontScale;
Selim Cinek01af3342016-02-09 19:25:31 -0800743 mDensity = currentConfig.densityDpi;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700744
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000745 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Ricky Wai7fa01712016-03-16 12:13:54 +0000746 mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
747 mLockPatternUtils = new LockPatternUtils(mContext);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000748
Joe Onorato2314aab2010-04-08 16:41:23 -0500749 // Connect in to the status bar manager service
Jason Monkb5b092012017-01-05 11:35:34 -0500750 mCommandQueue = getComponent(CommandQueue.class);
751 mCommandQueue.addCallbacks(this);
Daniel Sandler6a858c32012-03-12 14:38:58 -0400752
Jorim Jaggi86905582016-02-09 21:36:09 -0800753 int[] switches = new int[9];
satokcd7cd292010-11-20 15:46:23 +0900754 ArrayList<IBinder> binders = new ArrayList<IBinder>();
Jason Monk07473ce2016-01-05 14:59:19 -0500755 ArrayList<String> iconSlots = new ArrayList<>();
756 ArrayList<StatusBarIcon> icons = new ArrayList<>();
Jorim Jaggi86905582016-02-09 21:36:09 -0800757 Rect fullscreenStackBounds = new Rect();
758 Rect dockedStackBounds = new Rect();
Joe Onorato2314aab2010-04-08 16:41:23 -0500759 try {
Jorim Jaggi86905582016-02-09 21:36:09 -0800760 mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
761 fullscreenStackBounds, dockedStackBounds);
Joe Onorato2314aab2010-04-08 16:41:23 -0500762 } catch (RemoteException ex) {
763 // If the system process isn't there we're doomed anyway.
764 }
Daniel Sandler6a858c32012-03-12 14:38:58 -0400765
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500766 createAndAddWindows();
Joe Onorato0cbda992010-05-02 16:28:15 -0700767
Jorim Jaggi66ac1332015-01-21 19:22:26 +0100768 mSettingsObserver.onChange(false); // set up
Benjamin Franzcde0a2a2015-04-23 17:19:48 +0100769 disable(switches[0], switches[6], false /* animate */);
Jorim Jaggi86905582016-02-09 21:36:09 -0800770 setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff,
771 fullscreenStackBounds, dockedStackBounds);
Dianne Hackborn7d049322011-06-14 15:00:32 -0700772 topAppWindowChanged(switches[2] != 0);
satokcd7cd292010-11-20 15:46:23 +0900773 // StatusBarManagerService has a back up of IME token and it's restored here.
Michael Wright665366a2014-08-07 15:44:40 -0700774 setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0);
Joe Onorato93056472010-09-10 10:30:46 -0400775
Joe Onorato0cbda992010-05-02 16:28:15 -0700776 // Set up the initial icon state
Jason Monk07473ce2016-01-05 14:59:19 -0500777 int N = iconSlots.size();
Joe Onorato0cbda992010-05-02 16:28:15 -0700778 int viewIndex = 0;
Jason Monk07473ce2016-01-05 14:59:19 -0500779 for (int i=0; i < N; i++) {
780 setIcon(iconSlots.get(i), icons.get(i));
Joe Onorato0cbda992010-05-02 16:28:15 -0700781 }
782
Christoph Studer71f18fd2014-05-20 17:02:04 +0200783 // Set up the initial notification state.
Christoph Studere71fefc2014-06-24 16:16:49 +0200784 try {
Christoph Studer4600f9b2014-07-22 22:44:43 +0200785 mNotificationListener.registerAsSystemService(mContext,
Christoph Studere71fefc2014-06-24 16:16:49 +0200786 new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
787 UserHandle.USER_ALL);
788 } catch (RemoteException e) {
789 Log.e(TAG, "Unable to register notification listener", e);
Joe Onorato75199e32010-05-29 17:22:51 -0400790 }
791
Christoph Studer60748e72014-05-22 16:51:41 +0200792
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500793 if (DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -0400794 Log.d(TAG, String.format(
Daniel Sandler6a858c32012-03-12 14:38:58 -0400795 "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
Jason Monk07473ce2016-01-05 14:59:19 -0500796 icons.size(),
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500797 switches[0],
798 switches[1],
799 switches[2],
800 switches[3]
801 ));
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400802 }
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400803
Christopher Tate5e08af02012-09-21 17:17:22 -0700804 mCurrentUserId = ActivityManager.getCurrentUser();
Chris Wrena6d4fb62014-11-20 14:46:23 -0500805 setHeadsUpUser(mCurrentUserId);
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400806
807 IntentFilter filter = new IntentFilter();
808 filter.addAction(Intent.ACTION_USER_SWITCHED);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000809 filter.addAction(Intent.ACTION_USER_ADDED);
Kenny Guydae30d52015-04-01 19:11:35 +0100810 filter.addAction(Intent.ACTION_USER_PRESENT);
John Spurlock5c454122013-06-17 07:35:46 -0400811 mContext.registerReceiver(mBroadcastReceiver, filter);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000812
Ricky Wai7fa01712016-03-16 12:13:54 +0000813 IntentFilter internalFilter = new IntentFilter();
Robin Lee92b83c62016-08-31 13:27:51 +0100814 internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
Ricky Wai7fa01712016-03-16 12:13:54 +0000815 internalFilter.addAction(BANNER_ACTION_CANCEL);
816 internalFilter.addAction(BANNER_ACTION_SETUP);
817 mContext.registerReceiver(mBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
818
Kenny Guy0b7dd1e2015-03-12 17:14:38 +0000819 IntentFilter allUsersFilter = new IntentFilter();
820 allUsersFilter.addAction(
821 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
Robin Lee92b83c62016-08-31 13:27:51 +0100822 allUsersFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED);
Kenny Guy0b7dd1e2015-03-12 17:14:38 +0000823 mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
824 null, null);
Kenny Guy2a764942014-04-02 13:29:20 +0100825 updateCurrentProfilesCache();
Dan Sandlerdc34df52016-04-07 21:04:46 -0400826
827 IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
828 try {
829 vrManager.registerListener(mVrStateCallbacks);
830 } catch (RemoteException e) {
831 Slog.e(TAG, "Failed to register VR mode state listener: " + e);
832 }
833
Julia Reynolds98a44862016-09-12 08:53:47 -0400834 mNonBlockablePkgs = new HashSet<String>();
835 Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
836 com.android.internal.R.array.config_nonBlockableNotificationPackages));
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400837 }
838
Chris Wrencd8f4f72014-08-27 18:48:13 -0400839 protected void notifyUserAboutHiddenNotifications() {
840 if (0 != Settings.Secure.getInt(mContext.getContentResolver(),
841 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) {
842 Log.d(TAG, "user hasn't seen notification about hidden notifications");
Ricky Wai7fa01712016-03-16 12:13:54 +0000843 if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
Chris Wrencd8f4f72014-08-27 18:48:13 -0400844 Log.d(TAG, "insecure lockscreen, skipping notification");
845 Settings.Secure.putInt(mContext.getContentResolver(),
846 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
847 return;
848 }
849 Log.d(TAG, "disabling lockecreen notifications and alerting the user");
850 // disable lockscreen notifications until user acts on the banner.
851 Settings.Secure.putInt(mContext.getContentResolver(),
852 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
Adrian Roosaee70462014-09-03 16:27:39 +0200853 Settings.Secure.putInt(mContext.getContentResolver(),
854 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400855
856 final String packageName = mContext.getPackageName();
857 PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0,
858 new Intent(BANNER_ACTION_CANCEL).setPackage(packageName),
859 PendingIntent.FLAG_CANCEL_CURRENT);
860 PendingIntent setupIntent = PendingIntent.getBroadcast(mContext, 0,
861 new Intent(BANNER_ACTION_SETUP).setPackage(packageName),
862 PendingIntent.FLAG_CANCEL_CURRENT);
863
Chris Wrencd8f4f72014-08-27 18:48:13 -0400864 final int colorRes = com.android.internal.R.color.system_notification_accent_color;
865 Notification.Builder note = new Notification.Builder(mContext)
866 .setSmallIcon(R.drawable.ic_android)
867 .setContentTitle(mContext.getString(R.string.hidden_notifications_title))
868 .setContentText(mContext.getString(R.string.hidden_notifications_text))
869 .setPriority(Notification.PRIORITY_HIGH)
870 .setOngoing(true)
Alan Viverette4a357cd2015-03-18 18:37:18 -0700871 .setColor(mContext.getColor(colorRes))
Chris Wrencd8f4f72014-08-27 18:48:13 -0400872 .setContentIntent(setupIntent)
873 .addAction(R.drawable.ic_close,
874 mContext.getString(R.string.hidden_notifications_cancel),
875 cancelIntent)
876 .addAction(R.drawable.ic_settings,
877 mContext.getString(R.string.hidden_notifications_setup),
878 setupIntent);
Adrian Roose25c18d2016-06-17 15:59:49 -0700879 overrideNotificationAppName(mContext, note);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400880
881 NotificationManager noMan =
882 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500883 noMan.notify(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS, note.build());
Chris Wrencd8f4f72014-08-27 18:48:13 -0400884 }
885 }
886
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400887 public void userSwitched(int newUserId) {
Chris Wrena6d4fb62014-11-20 14:46:23 -0500888 setHeadsUpUser(newUserId);
889 }
890
Selim Cinek29fa89b2015-04-17 10:39:11 -0700891 protected abstract void setHeadsUpUser(int newUserId);
Chris Wrend04f6ce2014-06-11 17:37:28 -0400892
Christoph Studerc8db24b2014-07-25 17:50:30 +0200893 @Override // NotificationData.Environment
894 public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400895 final int thisUserId = mCurrentUserId;
896 final int notificationUserId = n.getUserId();
897 if (DEBUG && MULTIUSER_DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -0400898 Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400899 n, thisUserId, notificationUserId));
900 }
Dan Sandlere63ba4b2014-12-05 00:26:24 -0500901 return isCurrentProfile(notificationUserId);
Joe Onorato2314aab2010-04-08 16:41:23 -0500902 }
Daniel Sandler6a858c32012-03-12 14:38:58 -0400903
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700904 protected void setNotificationShown(StatusBarNotification n) {
Chris Wren26505582015-07-22 17:03:17 -0400905 setNotificationsShown(new String[]{n.getKey()});
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700906 }
907
908 protected void setNotificationsShown(String[] keys) {
Chris Wren26505582015-07-22 17:03:17 -0400909 try {
910 mNotificationListener.setNotificationsShown(keys);
911 } catch (RuntimeException e) {
912 Log.d(TAG, "failed setNotificationsShown: ", e);
913 }
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700914 }
915
Kenny Guy44fc65f2014-11-28 22:18:14 +0000916 protected boolean isCurrentProfile(int userId) {
917 synchronized (mCurrentProfiles) {
Dan Sandlere63ba4b2014-12-05 00:26:24 -0500918 return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
Kenny Guy44fc65f2014-11-28 22:18:14 +0000919 }
920 }
921
Christoph Studer2e731b52014-08-22 16:01:51 +0200922 @Override
923 public String getCurrentMediaNotificationKey() {
924 return null;
925 }
926
Selim Cinek25fd4e2b2015-02-20 17:46:07 +0100927 @Override
928 public NotificationGroupManager getGroupManager() {
929 return mGroupManager;
930 }
931
Adrian Roos7d7090d2014-05-21 13:10:23 +0200932 /**
933 * Takes the necessary steps to prepare the status bar for starting an activity, then starts it.
934 * @param action A dismiss action that is called if it's safe to start the activity.
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200935 * @param afterKeyguardGone Whether the action should be executed after the Keyguard is gone.
Adrian Roos7d7090d2014-05-21 13:10:23 +0200936 */
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200937 protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200938 action.onDismiss();
939 }
940
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700941 @Override
942 protected void onConfigurationChanged(Configuration newConfig) {
Dan Sandler539aad42014-08-04 00:43:39 -0400943 final float fontScale = newConfig.fontScale;
Selim Cinek01af3342016-02-09 19:25:31 -0800944 final int density = newConfig.densityDpi;
945 if (density != mDensity || mFontScale != fontScale) {
Selim Cinek3e7592d2016-04-11 09:35:54 +0800946 onDensityOrFontScaleChanged();
Selim Cinek01af3342016-02-09 19:25:31 -0800947 mDensity = density;
948 mFontScale = fontScale;
949 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700950 }
951
Selim Cinek3e7592d2016-04-11 09:35:54 +0800952 protected void onDensityOrFontScaleChanged() {
Selim Cinek01af3342016-02-09 19:25:31 -0800953 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
954 for (int i = 0; i < activeNotifications.size(); i++) {
955 Entry entry = activeNotifications.get(i);
956 boolean exposedGuts = entry.row.getGuts() == mNotificationGutsExposed;
957 entry.row.reInflateViews();
958 if (exposedGuts) {
959 mNotificationGutsExposed = entry.row.getGuts();
960 bindGuts(entry.row);
961 }
Selim Cinek01af3342016-02-09 19:25:31 -0800962 inflateViews(entry, mStackScroller);
963 }
964 }
965
Selim Cineke9079112016-12-14 14:41:01 -0800966 protected void bindDismissRunnable(final ExpandableNotificationRow row) {
967 row.setOnDismissRunnable(() -> performRemoveNotification(row.getStatusBarNotification()));
Winson Chungc57ccf02011-10-13 15:04:59 -0700968 }
Daniel Sandler6a858c32012-03-12 14:38:58 -0400969
Selim Cinekd47401412016-12-15 14:44:36 -0800970 protected void performRemoveNotification(StatusBarNotification n) {
Selim Cinek36b02232016-05-11 23:07:05 -0400971 final String pkg = n.getPackageName();
972 final String tag = n.getTag();
973 final int id = n.getId();
974 final int userId = n.getUserId();
975 try {
976 mBarService.onNotificationClear(pkg, tag, id, userId);
977 if (FORCE_REMOTE_INPUT_HISTORY
978 && mKeysKeptForRemoteInput.contains(n.getKey())) {
979 mKeysKeptForRemoteInput.remove(n.getKey());
Selim Cinek36b02232016-05-11 23:07:05 -0400980 }
Selim Cinekd47401412016-12-15 14:44:36 -0800981 removeNotification(n.getKey(), null);
Selim Cinek36b02232016-05-11 23:07:05 -0400982
983 } catch (RemoteException ex) {
984 // system process is dead if we're here.
985 }
986 }
987
Daniel Sandler96fd7c12012-03-30 16:37:36 -0400988
Christoph Studer13b895122014-08-26 15:42:12 +0200989 protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
Jorim Jaggi46739852014-04-15 09:58:24 +0200990 NotificationData.Entry entry) {
Dan Sandlerfe266a32014-05-15 22:28:06 -0400991
Selim Cinek684a4422015-04-15 16:18:39 -0700992 if (entry.getContentView().getId()
993 != com.android.internal.R.id.status_bar_latest_event_content) {
Dan Sandlerfe266a32014-05-15 22:28:06 -0400994 // Using custom RemoteViews
Jorim Jaggia1eeade2014-09-08 22:34:39 +0200995 if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
Dianne Hackborn955d8d62014-10-07 20:17:19 -0700996 && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
Selim Cinek697178b2014-07-02 19:40:30 +0200997 entry.row.setShowingLegacyBackground(true);
Jorim Jaggi36b15232014-06-10 17:24:20 +0200998 entry.legacy = true;
Daniel Sandler96fd7c12012-03-30 16:37:36 -0400999 }
1000 }
Christoph Studer13b895122014-08-26 15:42:12 +02001001
Selim Cinek281c2022016-10-13 19:14:43 -07001002 entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
Daniel Sandler96fd7c12012-03-30 16:37:36 -04001003 }
1004
Dan Sandler16128f42014-05-21 12:48:22 -04001005 public boolean isMediaNotification(NotificationData.Entry entry) {
Dan Sandler842dd772014-05-15 09:36:47 -04001006 // TODO: confirm that there's a valid media key
Selim Cinek684a4422015-04-15 16:18:39 -07001007 return entry.getExpandedContentView() != null &&
1008 entry.getExpandedContentView()
1009 .findViewById(com.android.internal.R.id.media_actions) != null;
Dan Sandler842dd772014-05-15 09:36:47 -04001010 }
1011
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001012 // The (i) button in the guts that links to the system notification settings for that app
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001013 private void startAppNotificationSettingsActivity(String packageName, final int appUid) {
1014 final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
Dan Sandlere9a4e902014-07-31 01:06:43 -04001015 intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
1016 intent.putExtra(Settings.EXTRA_APP_UID, appUid);
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001017 startNotificationGutsIntent(intent, appUid);
1018 }
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001019
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001020 private void startNotificationGutsIntent(final Intent intent, final int appUid) {
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001021 dismissKeyguardThenExecute(new OnDismissAction() {
1022 @Override
1023 public boolean onDismiss() {
1024 AsyncTask.execute(new Runnable() {
1025 public void run() {
Jorim Jaggife762342016-10-13 14:33:27 +02001026 TaskStackBuilder.create(mContext)
1027 .addNextIntentWithParentStack(intent)
1028 .startActivities(getActivityOptions(),
1029 new UserHandle(UserHandle.getUserId(appUid)));
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001030 }
1031 });
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +01001032 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001033 return true;
1034 }
Jorim Jaggi746f7fa2014-08-27 17:52:46 +02001035 }, false /* afterKeyguardGone */);
Dan Sandler4247a5c2014-07-23 15:58:08 -04001036 }
1037
Mady Mellorb53bc272016-02-11 18:28:23 -08001038 private void bindGuts(final ExpandableNotificationRow row) {
Selim Cinekab29aeb2015-02-20 18:18:32 +01001039 row.inflateGuts();
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001040 final StatusBarNotification sbn = row.getStatusBarNotification();
Selim Cinekeef84282015-10-30 16:28:00 -07001041 PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001042 row.setTag(sbn.getPackageName());
Julia Reynoldsa07af882015-12-17 08:32:48 -05001043 final NotificationGuts guts = row.getGuts();
dongwan0605.kimfc975d62017-01-05 10:01:11 +09001044 guts.setClosedListener((NotificationGuts g) -> {
1045 if (!row.isRemoved()) {
1046 mStackScroller.onHeightChanged(row, !isPanelFullyCollapsed() /* needsAnimation */);
1047 }
1048 mNotificationGutsExposed = null;
1049 });
Geoffrey Pitsch4dd50062016-12-06 16:41:22 -05001050
1051 final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
1052 ServiceManager.getService(Context.NOTIFICATION_SERVICE));
1053
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001054 final String pkg = sbn.getPackageName();
Geoffrey Pitsch4dd50062016-12-06 16:41:22 -05001055 final NotificationGuts.OnSettingsClickListener onSettingsClick =
1056 (View v, int appUid) -> {
Chris Wrenf6e9228b2016-01-26 18:04:35 -05001057 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
Mady Mellor97c8df42016-03-22 18:09:39 -07001058 guts.resetFalsingCheck();
Geoffrey Pitsch4dd50062016-12-06 16:41:22 -05001059 startAppNotificationSettingsActivity(pkg, appUid);
1060 };
1061 final View.OnClickListener onDoneClick =
1062 (View v) -> {
1063 // If the user has security enabled, show challenge if the setting is changed.
1064 if (guts.hasImportanceChanged()
1065 && isLockscreenPublicMode(sbn.getUser().getIdentifier())
1066 && (mState == StatusBarState.KEYGUARD
1067 || mState == StatusBarState.SHADE_LOCKED)) {
1068 OnDismissAction dismissAction = new OnDismissAction() {
1069 @Override
1070 public boolean onDismiss() {
1071 closeControls(row, guts, v);
1072 return true;
1073 }
1074 };
1075 onLockedNotificationImportanceChange(dismissAction);
1076 } else {
1077 closeControls(row, guts, v);
1078 }
1079 };
1080 guts.bindNotification(pmUser, iNotificationManager, sbn, onSettingsClick, onDoneClick,
1081 mNonBlockablePkgs);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001082 }
1083
Geoffrey Pitsch4dd50062016-12-06 16:41:22 -05001084 private void closeControls(
Mady Mellor8e8a69e2016-03-14 12:30:10 -07001085 ExpandableNotificationRow row, NotificationGuts guts, View done) {
Mady Mellor97c8df42016-03-22 18:09:39 -07001086 guts.resetFalsingCheck();
Mady Mellor8e8a69e2016-03-14 12:30:10 -07001087
1088 int[] rowLocation = new int[2];
1089 int[] doneLocation = new int[2];
1090 row.getLocationOnScreen(rowLocation);
1091 done.getLocationOnScreen(doneLocation);
1092
1093 final int centerX = done.getWidth() / 2;
1094 final int centerY = done.getHeight() / 2;
1095 final int x = doneLocation[0] - rowLocation[0] + centerX;
1096 final int y = doneLocation[1] - rowLocation[1] + centerY;
1097 dismissPopups(x, y);
1098 }
1099
Dan Sandler4247a5c2014-07-23 15:58:08 -04001100 protected SwipeHelper.LongPressListener getNotificationLongClicker() {
1101 return new SwipeHelper.LongPressListener() {
Daniel Sandlerf7a19562012-04-04 14:04:21 -04001102 @Override
Selim Cinekd84a5932015-12-15 11:45:36 -08001103 public boolean onLongPress(View v, final int x, final int y) {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001104 if (!(v instanceof ExpandableNotificationRow)) {
1105 return false;
1106 }
Selim Cinekabdc5a02014-09-02 13:46:00 +02001107 if (v.getWindowToken() == null) {
1108 Log.e(TAG, "Trying to show notification guts, but not attached to window");
1109 return false;
1110 }
Dan Sandler4247a5c2014-07-23 15:58:08 -04001111
Mady Mellor4b80b102016-01-22 08:03:58 -08001112 final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
Selim Cinekab29aeb2015-02-20 18:18:32 +01001113 bindGuts(row);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001114
Dan Sandler4247a5c2014-07-23 15:58:08 -04001115 // Assume we are a status_bar_notification_row
Selim Cinekab29aeb2015-02-20 18:18:32 +01001116 final NotificationGuts guts = row.getGuts();
Selim Cinekbdefcdf2014-09-11 12:41:47 +02001117 if (guts == null) {
1118 // This view has no guts. Examples are the more card or the dismiss all view
1119 return false;
1120 }
Dan Sandler4247a5c2014-07-23 15:58:08 -04001121
1122 // Already showing?
Selim Cinekabdc5a02014-09-02 13:46:00 +02001123 if (guts.getVisibility() == View.VISIBLE) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001124 dismissPopups(x, y);
Selim Cinekabdc5a02014-09-02 13:46:00 +02001125 return false;
1126 }
Dan Sandler4247a5c2014-07-23 15:58:08 -04001127
Chris Wrenf6e9228b2016-01-26 18:04:35 -05001128 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
Julia Reynoldsead00aa2015-12-07 08:23:48 -05001129
Julia Reynolds40779452016-02-23 13:43:32 -05001130 // ensure that it's laid but not visible until actually laid out
Selim Cinekd84a5932015-12-15 11:45:36 -08001131 guts.setVisibility(View.INVISIBLE);
Julia Reynolds40779452016-02-23 13:43:32 -05001132 // Post to ensure the the guts are properly laid out.
Selim Cinekd84a5932015-12-15 11:45:36 -08001133 guts.post(new Runnable() {
1134 public void run() {
Selim Cinek97244312017-01-13 17:40:50 -08001135 if (row.getWindowToken() == null) {
1136 Log.e(TAG, "Trying to show notification guts, but not attached to "
1137 + "window");
1138 return;
1139 }
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001140 dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
1141 false /* animate */);
Selim Cinekd84a5932015-12-15 11:45:36 -08001142 guts.setVisibility(View.VISIBLE);
1143 final double horz = Math.max(guts.getWidth() - x, x);
1144 final double vert = Math.max(guts.getHeight() - y, y);
1145 final float r = (float) Math.hypot(horz, vert);
1146 final Animator a
1147 = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r);
1148 a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
Selim Cinekc18010f2016-01-20 13:41:30 -08001149 a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
Mady Mellor4b80b102016-01-22 08:03:58 -08001150 a.addListener(new AnimatorListenerAdapter() {
1151 @Override
1152 public void onAnimationEnd(Animator animation) {
1153 super.onAnimationEnd(animation);
1154 // Move the notification view back over the gear
1155 row.resetTranslation();
1156 }
1157 });
Selim Cinekd84a5932015-12-15 11:45:36 -08001158 a.start();
Mady Mellor97c8df42016-03-22 18:09:39 -07001159 guts.setExposed(true /* exposed */,
1160 mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
Adrian Roos0bd8a4b2016-03-14 16:21:44 -07001161 row.closeRemoteInput();
dongwan0605.kimfc975d62017-01-05 10:01:11 +09001162 mStackScroller.onHeightChanged(row, true /* needsAnimation */);
Selim Cinekd84a5932015-12-15 11:45:36 -08001163 mNotificationGutsExposed = guts;
1164 }
1165 });
Daniel Sandlerf7a19562012-04-04 14:04:21 -04001166 return true;
1167 }
1168 };
1169 }
1170
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001171 /**
1172 * Returns the exposed NotificationGuts or null if none are exposed.
1173 */
1174 public NotificationGuts getExposedGuts() {
1175 return mNotificationGutsExposed;
Mady Mellor4b80b102016-01-22 08:03:58 -08001176 }
1177
Daniel Sandler469e96e2012-05-04 15:56:19 -04001178 public void dismissPopups() {
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001179 dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
Selim Cinekd84a5932015-12-15 11:45:36 -08001180 }
1181
1182 private void dismissPopups(int x, int y) {
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001183 dismissPopups(x, y, true /* resetGear */, false /* animate */);
Mady Mellorb53bc272016-02-11 18:28:23 -08001184 }
1185
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001186 public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
Dan Sandler4247a5c2014-07-23 15:58:08 -04001187 if (mNotificationGutsExposed != null) {
Geoffrey Pitsch4dd50062016-12-06 16:41:22 -05001188 mNotificationGutsExposed.closeControls(x, y, true /* save */);
Daniel Sandler469e96e2012-05-04 15:56:19 -04001189 }
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001190 if (resetGear) {
1191 mStackScroller.resetExposedGearView(animate, true /* force */);
Mady Mellor4b80b102016-01-22 08:03:58 -08001192 }
Daniel Sandler469e96e2012-05-04 15:56:19 -04001193 }
1194
Michael Jurka7f2668c2012-03-27 07:49:52 -07001195 @Override
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001196 public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001197 int msg = MSG_SHOW_RECENT_APPS;
1198 mHandler.removeMessages(msg);
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001199 mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0).sendToTarget();
Winson Chung1e8d71b2014-05-16 17:05:22 -07001200 }
1201
1202 @Override
Winson Chungcdcd4872014-08-05 18:00:13 -07001203 public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001204 int msg = MSG_HIDE_RECENT_APPS;
1205 mHandler.removeMessages(msg);
Winson Chungcdcd4872014-08-05 18:00:13 -07001206 mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0,
1207 triggeredFromHomeKey ? 1 : 0).sendToTarget();
Winson Chung1e8d71b2014-05-16 17:05:22 -07001208 }
1209
1210 @Override
Michael Jurka7f2668c2012-03-27 07:49:52 -07001211 public void toggleRecentApps() {
Jorim Jaggi900fb482015-06-02 15:07:33 -07001212 toggleRecents();
Michael Jurka7f2668c2012-03-27 07:49:52 -07001213 }
1214
1215 @Override
Phil Weaver315c34e2016-02-19 15:12:29 -08001216 public void toggleSplitScreen() {
Jorim Jaggi29379ec2016-04-11 23:43:42 -07001217 toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
Phil Weaver315c34e2016-02-19 15:12:29 -08001218 }
1219
1220 @Override
Michael Jurka7f2668c2012-03-27 07:49:52 -07001221 public void preloadRecentApps() {
1222 int msg = MSG_PRELOAD_RECENT_APPS;
1223 mHandler.removeMessages(msg);
1224 mHandler.sendEmptyMessage(msg);
1225 }
1226
1227 @Override
1228 public void cancelPreloadRecentApps() {
1229 int msg = MSG_CANCEL_PRELOAD_RECENT_APPS;
1230 mHandler.removeMessages(msg);
1231 mHandler.sendEmptyMessage(msg);
1232 }
1233
Clara Bayarrif2debb12015-07-10 14:47:17 +01001234 @Override
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +01001235 public void dismissKeyboardShortcutsMenu() {
1236 int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU;
1237 mHandler.removeMessages(msg);
1238 mHandler.sendEmptyMessage(msg);
1239 }
1240
1241 @Override
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001242 public void toggleKeyboardShortcutsMenu(int deviceId) {
Andrei Stingaceanuc22ab792016-01-07 12:39:38 +00001243 int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
Clara Bayarrif2debb12015-07-10 14:47:17 +01001244 mHandler.removeMessages(msg);
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001245 mHandler.obtainMessage(msg, deviceId, 0).sendToTarget();
Clara Bayarrif2debb12015-07-10 14:47:17 +01001246 }
1247
Winson Chungb1f74992014-08-08 12:53:09 -07001248 /** Jumps to the next affiliated task in the group. */
1249 public void showNextAffiliatedTask() {
1250 int msg = MSG_SHOW_NEXT_AFFILIATED_TASK;
1251 mHandler.removeMessages(msg);
1252 mHandler.sendEmptyMessage(msg);
1253 }
1254
1255 /** Jumps to the previous affiliated task in the group. */
1256 public void showPreviousAffiliatedTask() {
1257 int msg = MSG_SHOW_PREV_AFFILIATED_TASK;
1258 mHandler.removeMessages(msg);
1259 mHandler.sendEmptyMessage(msg);
1260 }
1261
Michael Jurkaecc395a2012-03-30 05:31:46 -07001262 protected H createHandler() {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001263 return new H();
1264 }
1265
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +01001266 protected void sendCloseSystemWindows(String reason) {
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07001267 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001268 ActivityManager.getService().closeSystemDialogs(reason);
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07001269 } catch (RemoteException e) {
Michael Jurka56a57832012-05-14 13:24:43 -07001270 }
1271 }
1272
Michael Jurkacb2522c2012-04-13 09:32:47 -07001273 protected abstract View getStatusBarView();
1274
Phil Weaver315c34e2016-02-19 15:12:29 -08001275 /**
1276 * Toggle docking the app window
1277 *
Jorim Jaggi29379ec2016-04-11 23:43:42 -07001278 * @param metricsDockAction the action to log when docking is successful, or -1 to not log
1279 * anything on successful docking
1280 * @param metricsUndockAction the action to log when undocking, or -1 to not log anything when
1281 * undocking
Matthew Ng8d372882016-12-20 11:06:49 -08001282 * @return true if toggle split screen was successful
Phil Weaver315c34e2016-02-19 15:12:29 -08001283 */
Matthew Ng8d372882016-12-20 11:06:49 -08001284 protected abstract boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction);
Phil Weaver315c34e2016-02-19 15:12:29 -08001285
Winson Chung1e8d71b2014-05-16 17:05:22 -07001286 /** Proxy for RecentsComponent */
1287
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001288 protected void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001289 if (mRecents != null) {
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +01001290 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
Jorim Jaggidb21bbd2016-04-18 15:32:07 -07001291 mRecents.showRecents(triggeredFromAltTab, fromHome);
Winson Chung1e8d71b2014-05-16 17:05:22 -07001292 }
1293 }
1294
Winson Chungcdcd4872014-08-05 18:00:13 -07001295 protected void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001296 if (mRecents != null) {
Winson Chungcdcd4872014-08-05 18:00:13 -07001297 mRecents.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
Winson Chung1e8d71b2014-05-16 17:05:22 -07001298 }
1299 }
1300
1301 protected void toggleRecents() {
John Spurlockd08de372013-06-24 13:06:08 -04001302 if (mRecents != null) {
Jorim Jaggidb21bbd2016-04-18 15:32:07 -07001303 mRecents.toggleRecents(mDisplay);
John Spurlockd08de372013-06-24 13:06:08 -04001304 }
1305 }
Michael Jurka80343f62012-10-18 13:13:46 +02001306
Winson Chung1e8d71b2014-05-16 17:05:22 -07001307 protected void preloadRecents() {
John Spurlockd08de372013-06-24 13:06:08 -04001308 if (mRecents != null) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001309 mRecents.preloadRecents();
John Spurlockd08de372013-06-24 13:06:08 -04001310 }
Michael Jurka80343f62012-10-18 13:13:46 +02001311 }
1312
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001313 protected void toggleKeyboardShortcuts(int deviceId) {
Andrei Stingaceanuf86bc972016-04-12 15:29:25 +01001314 KeyboardShortcuts.toggle(mContext, deviceId);
Clara Bayarrif2debb12015-07-10 14:47:17 +01001315 }
1316
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +01001317 protected void dismissKeyboardShortcuts() {
1318 KeyboardShortcuts.dismiss();
1319 }
1320
Winson Chung1e8d71b2014-05-16 17:05:22 -07001321 protected void cancelPreloadingRecents() {
John Spurlockd08de372013-06-24 13:06:08 -04001322 if (mRecents != null) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001323 mRecents.cancelPreloadingRecents();
John Spurlockd08de372013-06-24 13:06:08 -04001324 }
Michael Jurka80343f62012-10-18 13:13:46 +02001325 }
1326
Winson Chungb1f74992014-08-08 12:53:09 -07001327 protected void showRecentsNextAffiliatedTask() {
1328 if (mRecents != null) {
1329 mRecents.showNextAffiliatedTask();
1330 }
1331 }
1332
1333 protected void showRecentsPreviousAffiliatedTask() {
1334 if (mRecents != null) {
1335 mRecents.showPrevAffiliatedTask();
1336 }
1337 }
1338
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001339 /**
Selim Cinek684a4422015-04-15 16:18:39 -07001340 * If there is an active heads-up notification and it has a fullscreen intent, fire it now.
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001341 */
Selim Cinek684a4422015-04-15 16:18:39 -07001342 public abstract void maybeEscalateHeadsUp();
Chris Wrena4ef6202014-06-09 18:07:30 -04001343
Dan Sandlerfd16d562014-02-13 18:43:31 -08001344 /**
1345 * Save the current "public" (locked and secure) state of the lockscreen.
1346 */
Robin Lee92b83c62016-08-31 13:27:51 +01001347 public void setLockscreenPublicMode(boolean publicMode, int userId) {
1348 mLockscreenPublicMode.put(userId, publicMode);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001349 }
1350
Robin Lee92b83c62016-08-31 13:27:51 +01001351 public boolean isLockscreenPublicMode(int userId) {
1352 return mLockscreenPublicMode.get(userId, false);
Dan Sandlerfd16d562014-02-13 18:43:31 -08001353 }
1354
Robin Lee92b83c62016-08-31 13:27:51 +01001355 protected void onWorkChallengeChanged() {}
Ricky Waicd35def2016-05-03 11:07:07 +01001356
Dan Sandlerfd16d562014-02-13 18:43:31 -08001357 /**
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001358 * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
1359 * "public" (secure & locked) mode?
1360 */
1361 public boolean userAllowsNotificationsInPublic(int userHandle) {
1362 if (userHandle == UserHandle.USER_ALL) {
1363 return true;
1364 }
1365
1366 if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
1367 final boolean allowed = 0 != Settings.Secure.getIntForUser(
1368 mContext.getContentResolver(),
1369 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
1370 mUsersAllowingNotifications.append(userHandle, allowed);
1371 return allowed;
1372 }
1373
1374 return mUsersAllowingNotifications.get(userHandle);
1375 }
1376
1377 /**
Dan Sandlerfd16d562014-02-13 18:43:31 -08001378 * Has the given user chosen to allow their private (full) notifications to be shown even
1379 * when the lockscreen is in "public" (secure & locked) mode?
1380 */
1381 public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
1382 if (userHandle == UserHandle.USER_ALL) {
1383 return true;
1384 }
1385
1386 if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
Kenny Guyb0d3ab22015-02-10 16:13:11 +00001387 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
Dan Sandlerfd16d562014-02-13 18:43:31 -08001388 mContext.getContentResolver(),
1389 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00001390 final boolean allowedByDpm = adminAllowsUnredactedNotifications(userHandle);
Kenny Guyb0d3ab22015-02-10 16:13:11 +00001391 final boolean allowed = allowedByUser && allowedByDpm;
1392 mUsersAllowingPrivateNotifications.append(userHandle, allowed);
Dan Sandlerfd16d562014-02-13 18:43:31 -08001393 return allowed;
1394 }
1395
1396 return mUsersAllowingPrivateNotifications.get(userHandle);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001397 }
1398
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00001399 private boolean adminAllowsUnredactedNotifications(int userHandle) {
1400 if (userHandle == UserHandle.USER_ALL) {
1401 return true;
1402 }
1403 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */,
1404 userHandle);
1405 return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
1406 }
1407
Christoph Studerc8db24b2014-07-25 17:50:30 +02001408 /**
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001409 * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
1410 * If so, notifications should be hidden.
Christoph Studerc8db24b2014-07-25 17:50:30 +02001411 */
1412 @Override // NotificationData.Environment
Robin Lee92b83c62016-08-31 13:27:51 +01001413 public boolean shouldHideNotifications(int userId) {
Robin Lee50a9ad22016-11-28 15:11:51 +00001414 return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
Robin Lee92b83c62016-08-31 13:27:51 +01001415 || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId));
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001416 }
1417
1418 /**
1419 * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
1420 * package-specific override.
1421 */
1422 @Override // NotificationDate.Environment
1423 public boolean shouldHideNotifications(String key) {
Robin Lee92b83c62016-08-31 13:27:51 +01001424 return isLockscreenPublicMode(mCurrentUserId)
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001425 && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
1426 }
1427
1428 /**
1429 * Returns true if we're on a secure lockscreen.
1430 */
1431 @Override // NotificationData.Environment
Robin Lee92b83c62016-08-31 13:27:51 +01001432 public boolean isSecurelyLocked(int userId) {
1433 return isLockscreenPublicMode(userId);
Christoph Studerc8db24b2014-07-25 17:50:30 +02001434 }
1435
Chris Wrena4ef6202014-06-09 18:07:30 -04001436 public void onNotificationClear(StatusBarNotification notification) {
1437 try {
1438 mBarService.onNotificationClear(
1439 notification.getPackageName(),
1440 notification.getTag(),
1441 notification.getId(),
1442 notification.getUserId());
1443 } catch (android.os.RemoteException ex) {
1444 // oh well
1445 }
1446 }
1447
Selim Cinek5f71bee2015-11-18 10:25:23 -08001448 /**
Selim Cinek5fbc6322016-01-15 17:17:58 -08001449 * Called when the notification panel layouts
Selim Cinek5f71bee2015-11-18 10:25:23 -08001450 */
Selim Cinek5fbc6322016-01-15 17:17:58 -08001451 public void onPanelLaidOut() {
Selim Cinek5f71bee2015-11-18 10:25:23 -08001452 if (mState == StatusBarState.KEYGUARD) {
1453 // Since the number of notifications is determined based on the height of the view, we
1454 // need to update them.
Selim Cinek5fbc6322016-01-15 17:17:58 -08001455 int maxBefore = getMaxKeyguardNotifications(false /* recompute */);
1456 int maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
1457 if (maxBefore != maxNotifications) {
1458 updateRowStates();
1459 }
Selim Cinek5f71bee2015-11-18 10:25:23 -08001460 }
1461 }
1462
Mady Mellor8e8a69e2016-03-14 12:30:10 -07001463 protected void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {}
1464
Adrian Roos3aec6382016-02-05 14:19:01 -08001465 protected void onLockedRemoteInput(ExpandableNotificationRow row, View clickedView) {}
1466
Ricky Waicd35def2016-05-03 11:07:07 +01001467 protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
1468 View clicked) {}
1469
Selim Cinek570981d2015-12-01 11:37:01 -08001470 @Override
Selim Cinek31aada42015-12-18 17:51:15 -08001471 public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
Selim Cinek570981d2015-12-01 11:37:01 -08001472 }
1473
Michael Jurka7f2668c2012-03-27 07:49:52 -07001474 protected class H extends Handler {
1475 public void handleMessage(Message m) {
1476 switch (m.what) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001477 case MSG_SHOW_RECENT_APPS:
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001478 showRecents(m.arg1 > 0, m.arg2 != 0);
Michael Jurkacb2522c2012-04-13 09:32:47 -07001479 break;
Winson Chung1e8d71b2014-05-16 17:05:22 -07001480 case MSG_HIDE_RECENT_APPS:
Winson Chungcdcd4872014-08-05 18:00:13 -07001481 hideRecents(m.arg1 > 0, m.arg2 > 0);
Winson Chung1e8d71b2014-05-16 17:05:22 -07001482 break;
1483 case MSG_TOGGLE_RECENTS_APPS:
1484 toggleRecents();
Michael Jurkacb2522c2012-04-13 09:32:47 -07001485 break;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001486 case MSG_PRELOAD_RECENT_APPS:
Winson Chung1e8d71b2014-05-16 17:05:22 -07001487 preloadRecents();
Michael Jurka7f2668c2012-03-27 07:49:52 -07001488 break;
1489 case MSG_CANCEL_PRELOAD_RECENT_APPS:
Winson Chung1e8d71b2014-05-16 17:05:22 -07001490 cancelPreloadingRecents();
Michael Jurka7f2668c2012-03-27 07:49:52 -07001491 break;
Winson Chungb1f74992014-08-08 12:53:09 -07001492 case MSG_SHOW_NEXT_AFFILIATED_TASK:
1493 showRecentsNextAffiliatedTask();
1494 break;
1495 case MSG_SHOW_PREV_AFFILIATED_TASK:
1496 showRecentsPreviousAffiliatedTask();
1497 break;
Andrei Stingaceanuc22ab792016-01-07 12:39:38 +00001498 case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001499 toggleKeyboardShortcuts(m.arg1);
Clara Bayarrif2debb12015-07-10 14:47:17 +01001500 break;
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +01001501 case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU:
1502 dismissKeyboardShortcuts();
1503 break;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001504 }
1505 }
1506 }
1507
Daniel Sandler6a858c32012-03-12 14:38:58 -04001508 protected void workAroundBadLayerDrawableOpacity(View v) {
1509 }
1510
Selim Cinek8d490d42015-04-10 00:05:50 -07001511 protected boolean inflateViews(Entry entry, ViewGroup parent) {
Selim Cinekeef84282015-10-30 16:28:00 -07001512 PackageManager pmUser = getPackageManagerForUser(mContext,
Dan Sandlere9a4e902014-07-31 01:06:43 -04001513 entry.notification.getUser().getIdentifier());
1514
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001515 final StatusBarNotification sbn = entry.notification;
Adrian Roos95f8bea2016-07-27 15:49:03 -07001516 try {
1517 entry.cacheContentViews(mContext, null);
1518 } catch (RuntimeException e) {
1519 Log.e(TAG, "Unable to get notification remote views", e);
1520 return false;
1521 }
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001522
1523 final RemoteViews contentView = entry.cachedContentView;
1524 final RemoteViews bigContentView = entry.cachedBigContentView;
1525 final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
1526 final RemoteViews publicContentView = entry.cachedPublicContentView;
Adrian Roos0aac04f2016-12-08 15:59:29 -08001527 final RemoteViews ambientContentView = entry.cachedAmbientContentView;
Chris Wren8fd39ec2014-02-27 17:43:26 -05001528
Chris Wren574a55e2013-07-15 18:48:37 -04001529 if (contentView == null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001530 Log.v(TAG, "no contentView for: " + sbn.getNotification());
Daniel Sandler6a858c32012-03-12 14:38:58 -04001531 return false;
1532 }
1533
Dan Sandlerf68448e2014-04-24 15:54:16 -04001534 if (DEBUG) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001535 Log.v(TAG, "publicContentView: " + publicContentView);
Dan Sandlerf68448e2014-04-24 15:54:16 -04001536 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05001537
Christoph Studera7fe6312014-06-27 19:32:44 +02001538 ExpandableNotificationRow row;
1539
1540 // Stash away previous user expansion state so we can restore it at
1541 // the end.
1542 boolean hasUserChangedExpansion = false;
1543 boolean userExpanded = false;
1544 boolean userLocked = false;
1545
1546 if (entry.row != null) {
1547 row = entry.row;
1548 hasUserChangedExpansion = row.hasUserChangedExpansion();
1549 userExpanded = row.isUserExpanded();
1550 userLocked = row.isUserLocked();
Christoph Studer22f2ee52014-07-29 22:57:21 +02001551 entry.reset();
Christoph Studera7fe6312014-06-27 19:32:44 +02001552 if (hasUserChangedExpansion) {
1553 row.setUserExpanded(userExpanded);
1554 }
1555 } else {
1556 // create the row view
1557 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
1558 Context.LAYOUT_INFLATER_SERVICE);
1559 row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
1560 parent, false);
Chris Wren78403d72014-07-28 10:23:24 +01001561 row.setExpansionLogger(this, entry.notification.getKey());
Selim Cinekb5605e52015-02-20 18:21:41 +01001562 row.setGroupManager(mGroupManager);
Selim Cinek31aada42015-12-18 17:51:15 -08001563 row.setHeadsUpManager(mHeadsUpManager);
Adrian Roosb88b1a12015-12-09 18:51:05 -08001564 row.setRemoteInputController(mRemoteInputController);
Selim Cinek570981d2015-12-01 11:37:01 -08001565 row.setOnExpandClickListener(this);
Mady Mellor3fd273e2016-03-15 21:08:14 -07001566
Dan Sandler732bd6c2016-04-12 14:20:32 -04001567 // Get the app name.
1568 // Note that Notification.Builder#bindHeaderAppName has similar logic
1569 // but since this field is used in the guts, it must be accurate.
1570 // Therefore we will only show the application label, or, failing that, the
1571 // package name. No substitutions.
Mady Mellor3fd273e2016-03-15 21:08:14 -07001572 final String pkg = sbn.getPackageName();
1573 String appname = pkg;
1574 try {
1575 final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07001576 PackageManager.MATCH_UNINSTALLED_PACKAGES
1577 | PackageManager.MATCH_DISABLED_COMPONENTS);
Mady Mellor3fd273e2016-03-15 21:08:14 -07001578 if (info != null) {
1579 appname = String.valueOf(pmUser.getApplicationLabel(info));
1580 }
1581 } catch (NameNotFoundException e) {
1582 // Do nothing
1583 }
1584 row.setAppName(appname);
Christoph Studera7fe6312014-06-27 19:32:44 +02001585 }
Daniel Sandlerbc5559f2012-04-19 01:08:15 -04001586
Daniel Sandler6a858c32012-03-12 14:38:58 -04001587 workAroundBadLayerDrawableOpacity(row);
Selim Cineke9079112016-12-14 14:41:01 -08001588 bindDismissRunnable(row);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001589
1590 // NB: the large icon is now handled entirely by the template
1591
1592 // bind the click event to the content area
Selim Cinek8d490d42015-04-10 00:05:50 -07001593 NotificationContentView contentContainer = row.getPrivateLayout();
1594 NotificationContentView contentContainerPublic = row.getPublicLayout();
Daniel Sandlerbc5559f2012-04-19 01:08:15 -04001595
Jorim Jaggife40f7d2014-04-28 15:20:04 +02001596 row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
Adrian Roos497ab022015-02-10 20:49:33 +01001597 if (ENABLE_REMOTE_INPUT) {
1598 row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
1599 }
Daniel Sandlerbc5559f2012-04-19 01:08:15 -04001600
Chris Wren42d5dd42015-05-01 10:39:26 -04001601 mNotificationClicker.register(row, sbn);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001602
Dan Sandlera5e0f412014-01-23 15:11:54 -05001603 // set up the adaptive layout
Chris Wren574a55e2013-07-15 18:48:37 -04001604 View contentViewLocal = null;
1605 View bigContentViewLocal = null;
Selim Cinek8d490d42015-04-10 00:05:50 -07001606 View headsUpContentViewLocal = null;
Selim Cinek624c02db2015-12-14 21:00:02 -08001607 View publicViewLocal = null;
Adrian Roos0aac04f2016-12-08 15:59:29 -08001608 View ambientViewLocal = null;
Daniel Sandler6a858c32012-03-12 14:38:58 -04001609 try {
Dan Sandler68079d52015-07-22 10:45:30 -04001610 contentViewLocal = contentView.apply(
1611 sbn.getPackageContext(mContext),
1612 contentContainer,
Jorim Jaggi39fa59f2014-02-25 15:38:45 +01001613 mOnClickHandler);
Chris Wren574a55e2013-07-15 18:48:37 -04001614 if (bigContentView != null) {
Dan Sandler68079d52015-07-22 10:45:30 -04001615 bigContentViewLocal = bigContentView.apply(
1616 sbn.getPackageContext(mContext),
1617 contentContainer,
Selim Cinek8d490d42015-04-10 00:05:50 -07001618 mOnClickHandler);
1619 }
1620 if (headsUpContentView != null) {
Dan Sandler68079d52015-07-22 10:45:30 -04001621 headsUpContentViewLocal = headsUpContentView.apply(
1622 sbn.getPackageContext(mContext),
1623 contentContainer,
Jorim Jaggi39fa59f2014-02-25 15:38:45 +01001624 mOnClickHandler);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001625 }
Selim Cinek624c02db2015-12-14 21:00:02 -08001626 if (publicContentView != null) {
1627 publicViewLocal = publicContentView.apply(
1628 sbn.getPackageContext(mContext),
1629 contentContainerPublic, mOnClickHandler);
1630 }
Adrian Roos0aac04f2016-12-08 15:59:29 -08001631 if (ambientContentView != null) {
1632 ambientViewLocal = ambientContentView.apply(
1633 sbn.getPackageContext(mContext),
1634 contentContainer, mOnClickHandler);
1635 }
dooyoung.hwang78c41142016-10-04 18:55:31 +09001636
1637 if (contentViewLocal != null) {
1638 contentViewLocal.setIsRootNamespace(true);
1639 contentContainer.setContractedChild(contentViewLocal);
1640 }
1641 if (bigContentViewLocal != null) {
1642 bigContentViewLocal.setIsRootNamespace(true);
1643 contentContainer.setExpandedChild(bigContentViewLocal);
1644 }
1645 if (headsUpContentViewLocal != null) {
1646 headsUpContentViewLocal.setIsRootNamespace(true);
1647 contentContainer.setHeadsUpChild(headsUpContentViewLocal);
1648 }
1649 if (publicViewLocal != null) {
1650 publicViewLocal.setIsRootNamespace(true);
1651 contentContainerPublic.setContractedChild(publicViewLocal);
1652 }
Adrian Roos0aac04f2016-12-08 15:59:29 -08001653
1654 if (ambientViewLocal != null) {
1655 ambientViewLocal.setIsRootNamespace(true);
1656 contentContainer.setAmbientChild(ambientViewLocal);
1657 }
Daniel Sandler6a858c32012-03-12 14:38:58 -04001658 }
1659 catch (RuntimeException e) {
Daniel Sandler4f91efd2013-04-25 16:38:41 -04001660 final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
John Spurlockcd686b52013-06-05 10:13:46 -04001661 Log.e(TAG, "couldn't inflate view for notification " + ident, e);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001662 return false;
Daniel Sandler6a858c32012-03-12 14:38:58 -04001663 }
1664
Jorim Jaggia1eeade2014-09-08 22:34:39 +02001665 // Extract target SDK version.
1666 try {
1667 ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
1668 entry.targetSdk = info.targetSdkVersion;
1669 } catch (NameNotFoundException ex) {
1670 Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
1671 }
Selim Cinek624c02db2015-12-14 21:00:02 -08001672 entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001673
Daniel Sandler6a858c32012-03-12 14:38:58 -04001674 entry.row = row;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +02001675 entry.row.setOnActivatedListener(this);
Selim Cinek684a4422015-04-15 16:18:39 -07001676 entry.row.setExpandable(bigContentViewLocal != null);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001677
Christoph Studer13b895122014-08-26 15:42:12 +02001678 applyColorsAndBackgrounds(sbn, entry);
Jorim Jaggi46739852014-04-15 09:58:24 +02001679
Christoph Studera7fe6312014-06-27 19:32:44 +02001680 // Restore previous flags.
1681 if (hasUserChangedExpansion) {
1682 // Note: setUserExpanded() conveniently ignores calls with
1683 // userExpanded=true if !isExpandable().
1684 row.setUserExpanded(userExpanded);
1685 }
1686 row.setUserLocked(userLocked);
Selim Cinekda42d652015-12-04 15:51:16 -08001687 row.onNotificationUpdated(entry);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001688 return true;
1689 }
1690
Adrian Roos497ab022015-02-10 20:49:33 +01001691 /**
1692 * Adds RemoteInput actions from the WearableExtender; to be removed once more apps support this
1693 * via first-class API.
1694 *
1695 * TODO: Remove once enough apps specify remote inputs on their own.
1696 */
1697 private void processForRemoteInput(Notification n) {
1698 if (!ENABLE_REMOTE_INPUT) return;
1699
1700 if (n.extras != null && n.extras.containsKey("android.wearable.EXTENSIONS") &&
1701 (n.actions == null || n.actions.length == 0)) {
1702 Notification.Action viableAction = null;
1703 Notification.WearableExtender we = new Notification.WearableExtender(n);
1704
1705 List<Notification.Action> actions = we.getActions();
1706 final int numActions = actions.size();
1707
1708 for (int i = 0; i < numActions; i++) {
1709 Notification.Action action = actions.get(i);
Adrian Roosa3539cb2015-12-16 16:47:02 -08001710 if (action == null) {
1711 continue;
1712 }
Adrian Roos497ab022015-02-10 20:49:33 +01001713 RemoteInput[] remoteInputs = action.getRemoteInputs();
Adrian Roosa3539cb2015-12-16 16:47:02 -08001714 if (remoteInputs == null) {
1715 continue;
1716 }
1717 for (RemoteInput ri : remoteInputs) {
Adrian Roos497ab022015-02-10 20:49:33 +01001718 if (ri.getAllowFreeFormInput()) {
1719 viableAction = action;
1720 break;
1721 }
1722 }
1723 if (viableAction != null) {
1724 break;
1725 }
1726 }
1727
1728 if (viableAction != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001729 Notification.Builder rebuilder = Notification.Builder.recoverBuilder(mContext, n);
1730 rebuilder.setActions(viableAction);
1731 rebuilder.build(); // will rewrite n
Adrian Roos497ab022015-02-10 20:49:33 +01001732 }
1733 }
1734 }
1735
Adrian Roos62692b22015-09-11 17:46:23 -07001736 public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
1737 if (!isDeviceProvisioned()) return;
1738
1739 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
1740 final boolean afterKeyguardGone = intent.isActivity()
1741 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
1742 mCurrentUserId);
1743 dismissKeyguardThenExecute(new OnDismissAction() {
1744 public boolean onDismiss() {
1745 new Thread() {
1746 @Override
1747 public void run() {
1748 try {
Adrian Roos62692b22015-09-11 17:46:23 -07001749 // The intent we are sending is for the application, which
1750 // won't have permission to immediately start an activity after
1751 // the user switches to home. We know it is safe to do at this
1752 // point, so make sure new activity switches are now allowed.
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001753 ActivityManager.getService().resumeAppSwitches();
Adrian Roos62692b22015-09-11 17:46:23 -07001754 } catch (RemoteException e) {
1755 }
Adrian Roos62692b22015-09-11 17:46:23 -07001756 try {
Jorim Jaggie6e108e2016-03-28 13:38:45 -07001757 intent.send(null, 0, null, null, null, null, getActivityOptions());
Adrian Roos62692b22015-09-11 17:46:23 -07001758 } catch (PendingIntent.CanceledException e) {
1759 // the stack trace isn't very helpful here.
1760 // Just log the exception message.
1761 Log.w(TAG, "Sending intent failed: " + e);
1762
1763 // TODO: Dismiss Keyguard.
1764 }
1765 if (intent.isActivity()) {
1766 mAssistManager.hideAssist();
Adrian Roos62692b22015-09-11 17:46:23 -07001767 }
1768 }
1769 }.start();
1770
1771 // close the shade if it was open
1772 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
1773 true /* force */, true /* delayed */);
1774 visibilityChanged(false);
1775
1776 return true;
1777 }
1778 }, afterKeyguardGone);
1779 }
1780
Selim Cinek36b02232016-05-11 23:07:05 -04001781 public void addPostCollapseAction(Runnable r) {
1782 }
1783
1784 public boolean isCollapsing() {
1785 return false;
1786 }
1787
Chris Wren42d5dd42015-05-01 10:39:26 -04001788 private final class NotificationClicker implements View.OnClickListener {
Adrian Roos7d7090d2014-05-21 13:10:23 +02001789 public void onClick(final View v) {
Chris Wren42d5dd42015-05-01 10:39:26 -04001790 if (!(v instanceof ExpandableNotificationRow)) {
1791 Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
1792 return;
1793 }
1794
1795 final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
1796 final StatusBarNotification sbn = row.getStatusBarNotification();
1797 if (sbn == null) {
1798 Log.e(TAG, "NotificationClicker called on an unclickable notification,");
1799 return;
1800 }
1801
Mady Mellorf0625802016-02-11 18:03:48 -08001802 // Check if the notification is displaying the gear, if so slide notification back
1803 if (row.getSettingsRow() != null && row.getSettingsRow().isVisible()) {
1804 row.animateTranslateNotification(0);
1805 return;
1806 }
1807
Selim Cinekc6dd5212015-11-02 14:51:54 -08001808 Notification notification = sbn.getNotification();
1809 final PendingIntent intent = notification.contentIntent != null
1810 ? notification.contentIntent
1811 : notification.fullScreenIntent;
Chris Wren42d5dd42015-05-01 10:39:26 -04001812 final String notificationKey = sbn.getKey();
1813
Jorim Jaggi5eb67c22015-08-19 19:50:49 -07001814 // Mark notification for one frame.
1815 row.setJustClicked(true);
1816 DejankUtils.postAfterTraversal(new Runnable() {
1817 @Override
1818 public void run() {
1819 row.setJustClicked(false);
1820 }
1821 });
1822
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001823 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Chris Wren42d5dd42015-05-01 10:39:26 -04001824 final boolean afterKeyguardGone = intent.isActivity()
1825 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02001826 mCurrentUserId);
Adrian Roos4314f6d2014-05-28 14:10:27 +02001827 dismissKeyguardThenExecute(new OnDismissAction() {
Adrian Roos7d7090d2014-05-21 13:10:23 +02001828 public boolean onDismiss() {
Chris Wren42d5dd42015-05-01 10:39:26 -04001829 if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
Christoph Studerc6a656c2015-01-22 15:02:49 +01001830 // Release the HUN notification to the shade.
Selim Cinekf55f1bc2016-05-27 11:19:11 -07001831
1832 if (isPanelFullyCollapsed()) {
1833 HeadsUpManager.setIsClickedNotification(row, true);
1834 }
Christoph Studerc6a656c2015-01-22 15:02:49 +01001835 //
1836 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
1837 // become canceled shortly by NoMan, but we can't assume that.
Chris Wren42d5dd42015-05-01 10:39:26 -04001838 mHeadsUpManager.releaseImmediately(notificationKey);
Adrian Roos7d7090d2014-05-21 13:10:23 +02001839 }
Selim Cinek36b02232016-05-11 23:07:05 -04001840 StatusBarNotification parentToCancel = null;
1841 if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
1842 StatusBarNotification summarySbn = mGroupManager.getLogicalGroupSummary(sbn)
1843 .getStatusBarNotification();
1844 if (shouldAutoCancel(summarySbn)) {
1845 parentToCancel = summarySbn;
1846 }
1847 }
1848 final StatusBarNotification parentToCancelFinal = parentToCancel;
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001849 new Thread() {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001850 @Override
1851 public void run() {
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001852 try {
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001853 // The intent we are sending is for the application, which
1854 // won't have permission to immediately start an activity after
1855 // the user switches to home. We know it is safe to do at this
1856 // point, so make sure new activity switches are now allowed.
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001857 ActivityManager.getService().resumeAppSwitches();
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001858 } catch (RemoteException e) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001859 }
Chris Wren42d5dd42015-05-01 10:39:26 -04001860 if (intent != null) {
Ricky Wai7fa01712016-03-16 12:13:54 +00001861 // If we are launching a work activity and require to launch
1862 // separate work challenge, we defer the activity action and cancel
1863 // notification until work challenge is unlocked.
1864 if (intent.isActivity()) {
1865 final int userId = intent.getCreatorUserHandle()
1866 .getIdentifier();
1867 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
1868 && mKeyguardManager.isDeviceLocked(userId)) {
Rubin Xu89927b32016-07-28 14:34:26 +01001869 boolean canBypass = false;
1870 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001871 canBypass = ActivityManager.getService()
Rubin Xu89927b32016-07-28 14:34:26 +01001872 .canBypassWorkChallenge(intent);
1873 } catch (RemoteException e) {
1874 }
1875 // For direct-boot aware activities, they can be shown when
1876 // the device is still locked without triggering the work
1877 // challenge.
1878 if ((!canBypass) && startWorkChallengeIfNecessary(userId,
1879 intent.getIntentSender(), notificationKey)) {
1880 // Show work challenge, do not run PendingIntent and
Ricky Waia8c37a12016-04-05 17:10:04 +01001881 // remove notification
1882 return;
1883 }
Ricky Wai7fa01712016-03-16 12:13:54 +00001884 }
1885 }
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001886 try {
Jorim Jaggie6e108e2016-03-28 13:38:45 -07001887 intent.send(null, 0, null, null, null, null,
1888 getActivityOptions());
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001889 } catch (PendingIntent.CanceledException e) {
1890 // the stack trace isn't very helpful here.
1891 // Just log the exception message.
1892 Log.w(TAG, "Sending contentIntent failed: " + e);
Adrian Roos7d7090d2014-05-21 13:10:23 +02001893
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001894 // TODO: Dismiss Keyguard.
1895 }
Chris Wren42d5dd42015-05-01 10:39:26 -04001896 if (intent.isActivity()) {
Jorim Jaggib835dd72015-06-08 12:28:42 -07001897 mAssistManager.hideAssist();
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001898 }
1899 }
1900
1901 try {
Chris Wren42d5dd42015-05-01 10:39:26 -04001902 mBarService.onNotificationClick(notificationKey);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001903 } catch (RemoteException ex) {
1904 // system process is dead if we're here.
1905 }
Selim Cinek36b02232016-05-11 23:07:05 -04001906 if (parentToCancelFinal != null) {
1907 // We have to post it to the UI thread for synchronization
1908 mHandler.post(new Runnable() {
1909 @Override
1910 public void run() {
1911 Runnable removeRunnable = new Runnable() {
1912 @Override
1913 public void run() {
Selim Cinekd47401412016-12-15 14:44:36 -08001914 performRemoveNotification(parentToCancelFinal);
Selim Cinek36b02232016-05-11 23:07:05 -04001915 }
1916 };
1917 if (isCollapsing()) {
1918 // To avoid lags we're only performing the remove
1919 // after the shade was collapsed
1920 addPostCollapseAction(removeRunnable);
1921 } else {
1922 removeRunnable.run();
1923 }
1924 }
1925 });
1926 }
Adrian Roos7d7090d2014-05-21 13:10:23 +02001927 }
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001928 }.start();
Adrian Roos7d7090d2014-05-21 13:10:23 +02001929
1930 // close the shade if it was open
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +01001931 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
Jorim Jaggi27c9b742015-04-09 10:34:49 -07001932 true /* force */, true /* delayed */);
Adrian Roos7d7090d2014-05-21 13:10:23 +02001933 visibilityChanged(false);
1934
Jorim Jaggi8972c2a2015-06-05 16:05:54 -07001935 return true;
Daniel Sandler6a858c32012-03-12 14:38:58 -04001936 }
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02001937 }, afterKeyguardGone);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001938 }
Chris Wren42d5dd42015-05-01 10:39:26 -04001939
Selim Cinek36b02232016-05-11 23:07:05 -04001940 private boolean shouldAutoCancel(StatusBarNotification sbn) {
1941 int flags = sbn.getNotification().flags;
1942 if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
1943 return false;
1944 }
1945 if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
1946 return false;
1947 }
1948 return true;
1949 }
1950
Chris Wren42d5dd42015-05-01 10:39:26 -04001951 public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
Selim Cinekc6dd5212015-11-02 14:51:54 -08001952 Notification notification = sbn.getNotification();
1953 if (notification.contentIntent != null || notification.fullScreenIntent != null) {
Chris Wren42d5dd42015-05-01 10:39:26 -04001954 row.setOnClickListener(this);
1955 } else {
1956 row.setOnClickListener(null);
1957 }
1958 }
Daniel Sandler6a858c32012-03-12 14:38:58 -04001959 }
Chris Wrenf29c3b42013-11-27 16:30:30 -05001960
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001961 public void animateCollapsePanels(int flags, boolean force) {
1962 }
1963
Jorim Jaggi27c9b742015-04-09 10:34:49 -07001964 public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
1965 }
1966
Ricky Waicd35def2016-05-03 11:07:07 +01001967 protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
1968 String notificationKey) {
1969 final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
1970 null, userId);
1971 if (newIntent == null) {
1972 return false;
1973 }
Robin Lee92b83c62016-08-31 13:27:51 +01001974 final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
Ricky Waicd35def2016-05-03 11:07:07 +01001975 callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
1976 callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
1977 callBackIntent.setPackage(mContext.getPackageName());
1978
1979 PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
1980 mContext,
1981 0,
1982 callBackIntent,
1983 PendingIntent.FLAG_CANCEL_CURRENT |
1984 PendingIntent.FLAG_ONE_SHOT |
1985 PendingIntent.FLAG_IMMUTABLE);
1986 newIntent.putExtra(
1987 Intent.EXTRA_INTENT,
1988 callBackPendingIntent.getIntentSender());
1989 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001990 ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent);
Ricky Waicd35def2016-05-03 11:07:07 +01001991 } catch (RemoteException ex) {
1992 // ignore
1993 }
1994 return true;
1995 }
1996
Jorim Jaggie6e108e2016-03-28 13:38:45 -07001997 protected Bundle getActivityOptions() {
1998 // Anything launched from the notification shade should always go into the
1999 // fullscreen stack.
2000 ActivityOptions options = ActivityOptions.makeBasic();
2001 options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID);
2002 return options.toBundle();
2003 }
2004
Christoph Studere8e28652014-10-29 17:27:53 +01002005 protected void visibilityChanged(boolean visible) {
2006 if (mVisible != visible) {
2007 mVisible = visible;
2008 if (!visible) {
2009 dismissPopups();
2010 }
2011 }
2012 updateVisibleToUser();
2013 }
2014
2015 protected void updateVisibleToUser() {
2016 boolean oldVisibleToUser = mVisibleToUser;
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07002017 mVisibleToUser = mVisible && mDeviceInteractive;
Christoph Studere8e28652014-10-29 17:27:53 +01002018
2019 if (oldVisibleToUser != mVisibleToUser) {
2020 handleVisibleToUserChanged(mVisibleToUser);
2021 }
2022 }
2023
Daniel Sandler6a858c32012-03-12 14:38:58 -04002024 /**
Christoph Studere8e28652014-10-29 17:27:53 +01002025 * The LEDs are turned off when the notification panel is shown, even just a little bit.
Adrian Roos18d099a2016-05-19 15:28:18 -07002026 * See also PhoneStatusBar.setPanelExpanded for another place where we attempt to do this.
Daniel Sandler6a858c32012-03-12 14:38:58 -04002027 */
Christoph Studere8e28652014-10-29 17:27:53 +01002028 protected void handleVisibleToUserChanged(boolean visibleToUser) {
2029 try {
2030 if (visibleToUser) {
Selim Cinek6577cae2015-08-31 16:15:49 -07002031 boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
2032 boolean clearNotificationEffects =
Dan Sandlercb012892016-03-01 00:45:06 -05002033 !isPanelFullyCollapsed() &&
2034 (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
Chris Wrenb659c4f2015-06-25 17:12:27 -04002035 int notificationLoad = mNotificationData.getActiveNotifications().size();
Selim Cinek6577cae2015-08-31 16:15:49 -07002036 if (pinnedHeadsUp && isPanelFullyCollapsed()) {
Chris Wrenb659c4f2015-06-25 17:12:27 -04002037 notificationLoad = 1;
2038 } else {
2039 MetricsLogger.histogram(mContext, "note_load", notificationLoad);
2040 }
2041 mBarService.onPanelRevealed(clearNotificationEffects, notificationLoad);
Christoph Studere8e28652014-10-29 17:27:53 +01002042 } else {
2043 mBarService.onPanelHidden();
Dan Sandler4247a5c2014-07-23 15:58:08 -04002044 }
Christoph Studere8e28652014-10-29 17:27:53 +01002045 } catch (RemoteException ex) {
2046 // Won't fail unless the world has ended.
Daniel Sandler6a858c32012-03-12 14:38:58 -04002047 }
2048 }
2049
Chris Wren0c8275b2012-05-08 13:36:48 -04002050 /**
Chris Wren16895942015-06-23 11:22:20 -04002051 * Clear Buzz/Beep/Blink.
2052 */
2053 public void clearNotificationEffects() {
2054 try {
2055 mBarService.clearNotificationEffects();
2056 } catch (RemoteException e) {
2057 // Won't fail unless the world has ended.
2058 }
2059 }
2060
Yorke Leee4ea6ab2016-03-03 14:51:49 -08002061 public abstract boolean isPanelFullyCollapsed();
Chris Wren16895942015-06-23 11:22:20 -04002062
2063 /**
Chris Wren0c8275b2012-05-08 13:36:48 -04002064 * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
2065 * about the failure.
2066 *
2067 * WARNING: this will call back into us. Don't hold any locks.
2068 */
Christoph Studer71f18fd2014-05-20 17:02:04 +02002069 void handleNotificationError(StatusBarNotification n, String message) {
Christoph Studere71fefc2014-06-24 16:16:49 +02002070 removeNotification(n.getKey(), null);
Chris Wren0c8275b2012-05-08 13:36:48 -04002071 try {
Kenny Guy3a7c4a52014-03-03 18:24:03 +00002072 mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
2073 n.getInitialPid(), message, n.getUserId());
Chris Wren0c8275b2012-05-08 13:36:48 -04002074 } catch (RemoteException ex) {
2075 // The end is nigh.
2076 }
2077 }
2078
Christoph Studerd0694b62014-06-04 16:36:01 +02002079 protected StatusBarNotification removeNotificationViews(String key, RankingMap ranking) {
Christoph Studer37fe6932014-05-26 13:10:30 +02002080 NotificationData.Entry entry = mNotificationData.remove(key, ranking);
Chris Wren0c8275b2012-05-08 13:36:48 -04002081 if (entry == null) {
John Spurlockcd686b52013-06-05 10:13:46 -04002082 Log.w(TAG, "removeNotification for unknown key: " + key);
Chris Wren0c8275b2012-05-08 13:36:48 -04002083 return null;
2084 }
Christoph Studer37fe6932014-05-26 13:10:30 +02002085 updateNotifications();
Chris Wren0c8275b2012-05-08 13:36:48 -04002086 return entry.notification;
2087 }
2088
Selim Cinek8d490d42015-04-10 00:05:50 -07002089 protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn) {
Chris Wren0c8275b2012-05-08 13:36:48 -04002090 if (DEBUG) {
Christoph Studera0506e72014-07-31 20:27:39 +02002091 Log.d(TAG, "createNotificationViews(notification=" + sbn);
Chris Wren0c8275b2012-05-08 13:36:48 -04002092 }
Selim Cinek281c2022016-10-13 19:14:43 -07002093 NotificationData.Entry entry = new NotificationData.Entry(sbn);
2094 try {
2095 entry.createIcons(mContext, sbn);
2096 } catch (NotificationData.IconException exception) {
2097 handleNotificationError(sbn, exception.getMessage());
Selim Cinek379ff8f2015-02-20 17:03:16 +01002098 }
2099
2100 // Construct the expanded view.
Selim Cinek8d490d42015-04-10 00:05:50 -07002101 if (!inflateViews(entry, mStackScroller)) {
Selim Cinek379ff8f2015-02-20 17:03:16 +01002102 handleNotificationError(sbn, "Couldn't expand RemoteViews for: " + sbn);
2103 return null;
2104 }
2105 return entry;
2106 }
2107
Christoph Studerd0694b62014-06-04 16:36:01 +02002108 protected void addNotificationViews(Entry entry, RankingMap ranking) {
Raju Yadav5f330262014-03-24 10:44:00 +01002109 if (entry == null) {
2110 return;
2111 }
Chris Wren0c8275b2012-05-08 13:36:48 -04002112 // Add the expanded view and icon.
Christoph Studer37fe6932014-05-26 13:10:30 +02002113 mNotificationData.add(entry, ranking);
2114 updateNotifications();
Selim Cinek8efa6dd2014-05-19 16:27:37 +02002115 }
2116
Jorim Jaggi251957d2014-04-09 04:24:09 +02002117 /**
Selim Cinek5f71bee2015-11-18 10:25:23 -08002118 * @param recompute wheter the number should be recomputed
Jorim Jaggid4a57442014-04-10 02:45:55 +02002119 * @return The number of notifications we show on Keyguard.
2120 */
Selim Cinek5f71bee2015-11-18 10:25:23 -08002121 protected abstract int getMaxKeyguardNotifications(boolean recompute);
Jorim Jaggid4a57442014-04-10 02:45:55 +02002122
2123 /**
Jorim Jaggi251957d2014-04-09 04:24:09 +02002124 * Updates expanded, dimmed and locked states of notification rows.
2125 */
2126 protected void updateRowStates() {
Selim Cineka7d4f822016-12-06 14:34:47 -08002127 final int N = mStackScroller.getChildCount();
Christoph Studerc8db24b2014-07-25 17:50:30 +02002128
Jorim Jaggif6411742014-08-05 17:10:43 +00002129 int visibleNotifications = 0;
Jorim Jaggiecbab362014-04-23 16:13:15 +02002130 boolean onKeyguard = mState == StatusBarState.KEYGUARD;
Selim Cinekad7fac02016-10-18 17:09:15 -07002131 int maxNotifications = -1;
Selim Cinek5f71bee2015-11-18 10:25:23 -08002132 if (onKeyguard) {
2133 maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
2134 }
Selim Cinekad7fac02016-10-18 17:09:15 -07002135 mStackScroller.setMaxDisplayedNotifications(maxNotifications);
Selim Cineka7d4f822016-12-06 14:34:47 -08002136 Stack<ExpandableNotificationRow> stack = new Stack<>();
2137 for (int i = N - 1; i >= 0; i--) {
2138 View child = mStackScroller.getChildAt(i);
2139 if (!(child instanceof ExpandableNotificationRow)) {
2140 continue;
2141 }
2142 stack.push((ExpandableNotificationRow) child);
2143 }
2144 while(!stack.isEmpty()) {
2145 ExpandableNotificationRow row = stack.pop();
2146 NotificationData.Entry entry = row.getEntry();
Selim Cinek2a739342016-03-17 10:28:55 -07002147 boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification);
Jorim Jaggiecbab362014-04-23 16:13:15 +02002148 if (onKeyguard) {
Selim Cineka7d4f822016-12-06 14:34:47 -08002149 row.setOnKeyguard(true);
Chris Wren3ddab0d2012-08-02 16:52:21 -04002150 } else {
Selim Cineka7d4f822016-12-06 14:34:47 -08002151 row.setOnKeyguard(false);
2152 row.setSystemExpanded(visibleNotifications == 0 && !childNotification);
Chris Wren8fd12652012-05-09 21:25:57 -04002153 }
Adrian Roos0aac04f2016-12-08 15:59:29 -08002154 entry.row.setShowAmbient(isDozing());
Robin Lee92b83c62016-08-31 13:27:51 +01002155 int userId = entry.notification.getUserId();
Selim Cinek3f19f602016-05-02 18:01:56 -07002156 boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
2157 entry.notification) && !entry.row.isRemoved();
Jorim Jaggif6411742014-08-05 17:10:43 +00002158 boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
Robin Lee92b83c62016-08-31 13:27:51 +01002159 if (suppressedSummary
2160 || (isLockscreenPublicMode(userId) && !mShowLockscreenNotifications)
Selim Cinekad7fac02016-10-18 17:09:15 -07002161 || (onKeyguard && !showOnKeyguard)) {
Jorim Jaggif6411742014-08-05 17:10:43 +00002162 entry.row.setVisibility(View.GONE);
Jorim Jaggif6411742014-08-05 17:10:43 +00002163 } else {
2164 boolean wasGone = entry.row.getVisibility() == View.GONE;
Selim Cinek01ee2cd52016-12-21 18:23:11 +01002165 if (wasGone) {
2166 entry.row.setVisibility(View.VISIBLE);
2167 }
Selim Cinekfa760d42016-05-10 15:50:53 -04002168 if (!childNotification && !entry.row.isRemoved()) {
Selim Cinekb5605e52015-02-20 18:21:41 +01002169 if (wasGone) {
2170 // notify the scroller of a child addition
Selim Cinek2a739342016-03-17 10:28:55 -07002171 mStackScroller.generateAddAnimation(entry.row,
2172 !showOnKeyguard /* fromMoreCard */);
Selim Cinekb5605e52015-02-20 18:21:41 +01002173 }
2174 visibleNotifications++;
Jorim Jaggif6411742014-08-05 17:10:43 +00002175 }
Jorim Jaggif6411742014-08-05 17:10:43 +00002176 }
Selim Cineka7d4f822016-12-06 14:34:47 -08002177 if (row.isSummaryWithChildren()) {
2178 List<ExpandableNotificationRow> notificationChildren =
2179 row.getNotificationChildren();
2180 int size = notificationChildren.size();
2181 for (int i = size - 1; i >= 0; i--) {
2182 stack.push(notificationChildren.get(i));
2183 }
2184 }
Chris Wren8fd12652012-05-09 21:25:57 -04002185 }
Jorim Jaggif6411742014-08-05 17:10:43 +00002186
Selim Cinek0cce5312015-05-20 22:13:55 -07002187 mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
2188 mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
Selim Cinek25b52912016-11-02 16:12:56 -07002189 mStackScroller.changeViewPosition(mNotificationShelf, mStackScroller.getChildCount() - 3);
Jorim Jaggif6411742014-08-05 17:10:43 +00002190 }
2191
Adrian Roos0aac04f2016-12-08 15:59:29 -08002192 public boolean isDozing() {
2193 return false;
2194 }
2195
Selim Cinekfa760d42016-05-10 15:50:53 -04002196 public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
Jorim Jaggif6411742014-08-05 17:10:43 +00002197 return mShowLockscreenNotifications && !mNotificationData.isAmbient(sbn.getKey());
Chris Wren8fd12652012-05-09 21:25:57 -04002198 }
2199
John Spurlocke677d712014-02-13 12:52:19 -05002200 protected void setZenMode(int mode) {
John Spurlock110e5b12014-02-27 13:09:35 -05002201 if (!isDeviceProvisioned()) return;
John Spurlocke677d712014-02-13 12:52:19 -05002202 mZenMode = mode;
Christoph Studer37fe6932014-05-26 13:10:30 +02002203 updateNotifications();
John Spurlocke677d712014-02-13 12:52:19 -05002204 }
2205
Dan Sandler52e5701e2014-07-22 23:14:54 -04002206 // extended in PhoneStatusBar
2207 protected void setShowLockscreenNotifications(boolean show) {
2208 mShowLockscreenNotifications = show;
2209 }
2210
Adrian Roos3aec6382016-02-05 14:19:01 -08002211 protected void setLockScreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
2212 mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
2213 }
2214
Dan Sandler52e5701e2014-07-22 23:14:54 -04002215 private void updateLockscreenNotificationSetting() {
2216 final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
2217 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
2218 1,
2219 mCurrentUserId) != 0;
Adrian Roosbd3409c2014-08-12 18:21:09 +02002220 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
2221 null /* admin */, mCurrentUserId);
2222 final boolean allowedByDpm = (dpmFlags
2223 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
Adrian Roos3aec6382016-02-05 14:19:01 -08002224
Adrian Roosbd3409c2014-08-12 18:21:09 +02002225 setShowLockscreenNotifications(show && allowedByDpm);
Adrian Roosb27d7a52016-06-16 13:04:47 -07002226
2227 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
2228 final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
2229 Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
2230 0,
2231 mCurrentUserId) != 0;
2232 final boolean remoteInputDpm =
2233 (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
2234
2235 setLockScreenAllowRemoteInput(remoteInput && remoteInputDpm);
2236 } else {
2237 setLockScreenAllowRemoteInput(false);
2238 }
Dan Sandler52e5701e2014-07-22 23:14:54 -04002239 }
2240
Chris Wren0c8275b2012-05-08 13:36:48 -04002241 protected abstract void setAreThereNotifications();
Christoph Studer37fe6932014-05-26 13:10:30 +02002242 protected abstract void updateNotifications();
Chris Wren0c8275b2012-05-08 13:36:48 -04002243
Christoph Studere71fefc2014-06-24 16:16:49 +02002244 public abstract void addNotification(StatusBarNotification notification,
Selim Cinek379ff8f2015-02-20 17:03:16 +01002245 RankingMap ranking, Entry oldEntry);
Christoph Studere71fefc2014-06-24 16:16:49 +02002246 protected abstract void updateNotificationRanking(RankingMap ranking);
2247 public abstract void removeNotification(String key, RankingMap ranking);
Christoph Studera7fe6312014-06-27 19:32:44 +02002248
Christoph Studere71fefc2014-06-24 16:16:49 +02002249 public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
Christoph Studer71f18fd2014-05-20 17:02:04 +02002250 if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
Chris Wren0c8275b2012-05-08 13:36:48 -04002251
Chris Wrend04f6ce2014-06-11 17:37:28 -04002252 final String key = notification.getKey();
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002253 Entry entry = mNotificationData.get(key);
2254 if (entry == null) {
Chris Wren0c8275b2012-05-08 13:36:48 -04002255 return;
Adrian Roos18d099a2016-05-19 15:28:18 -07002256 } else {
Selim Cinek2d79f632015-11-02 15:13:29 -08002257 mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
Adrian Roos18d099a2016-05-19 15:28:18 -07002258 mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
Chris Wren0c8275b2012-05-08 13:36:48 -04002259 }
2260
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002261 Notification n = notification.getNotification();
Julia Reynoldsf612869ae2015-11-05 16:48:55 -05002262 mNotificationData.updateRanking(ranking);
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002263
Adrian Roos95f8bea2016-07-27 15:49:03 -07002264 boolean applyInPlace;
2265 try {
2266 applyInPlace = entry.cacheContentViews(mContext, notification.getNotification());
2267 } catch (RuntimeException e) {
2268 Log.e(TAG, "Unable to get notification remote views", e);
2269 applyInPlace = false;
2270 }
Chris Wrenbdf33762015-12-04 15:50:51 -05002271 boolean shouldPeek = shouldPeek(entry, notification);
Selim Cinek684a4422015-04-15 16:18:39 -07002272 boolean alertAgain = alertAgain(entry, n);
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002273 if (DEBUG) {
2274 Log.d(TAG, "applyInPlace=" + applyInPlace
Chris Wrenbdf33762015-12-04 15:50:51 -05002275 + " shouldPeek=" + shouldPeek
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002276 + " alertAgain=" + alertAgain);
2277 }
Chris Wren0c8275b2012-05-08 13:36:48 -04002278
Dan Sandler24813b02016-01-14 15:49:36 -05002279 final StatusBarNotification oldNotification = entry.notification;
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002280 entry.notification = notification;
Dan Sandler24813b02016-01-14 15:49:36 -05002281 mGroupManager.onEntryUpdated(entry, oldNotification);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002282
2283 boolean updateSuccessful = false;
Selim Cinek281c2022016-10-13 19:14:43 -07002284 try {
2285 if (applyInPlace) {
2286 if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
2287 try {
2288 entry.updateIcons(mContext, n);
2289 updateNotificationViews(entry, notification);
2290 updateSuccessful = true;
2291 } catch (RuntimeException e) {
2292 // It failed to apply cleanly.
2293 Log.w(TAG, "Couldn't reapply views for package " +
2294 notification.getPackageName(), e);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002295 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002296 }
Selim Cinek281c2022016-10-13 19:14:43 -07002297 if (!updateSuccessful) {
2298 entry.updateIcons(mContext, n);
2299 if (!inflateViews(entry, mStackScroller)) {
2300 handleNotificationError(notification, "Couldn't update remote views for: "
2301 + notification);
2302 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002303 }
Selim Cinek281c2022016-10-13 19:14:43 -07002304 } catch (NotificationData.IconException e) {
2305 handleNotificationError(notification, e.getMessage());
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002306 }
Chris Wrenbdf33762015-12-04 15:50:51 -05002307 updateHeadsUp(key, entry, shouldPeek, alertAgain);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002308 updateNotifications();
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002309
dongwan0605.kim30637e42016-03-02 17:16:47 +09002310 if (!notification.isClearable()) {
2311 // The user may have performed a dismiss action on the notification, since it's
2312 // not clearable we should snap it back.
2313 mStackScroller.snapViewIfNeeded(entry.row);
2314 }
2315
Selim Cinek684a4422015-04-15 16:18:39 -07002316 if (DEBUG) {
2317 // Is this for you?
2318 boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
2319 Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
2320 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002321
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002322 setAreThereNotifications();
2323 }
2324
Chris Wrenbdf33762015-12-04 15:50:51 -05002325 protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
Selim Cinek29fa89b2015-04-17 10:39:11 -07002326 boolean alertAgain);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002327
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002328 private void updateNotificationViews(Entry entry, StatusBarNotification sbn) {
2329 final RemoteViews contentView = entry.cachedContentView;
2330 final RemoteViews bigContentView = entry.cachedBigContentView;
2331 final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
2332 final RemoteViews publicContentView = entry.cachedPublicContentView;
Dan Sandlera5e0f412014-01-23 15:11:54 -05002333
Chris Wrene03f4e12013-08-08 16:48:48 -04002334 // Reapply the RemoteViews
Selim Cinek684a4422015-04-15 16:18:39 -07002335 contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
2336 if (bigContentView != null && entry.getExpandedContentView() != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002337 bigContentView.reapply(sbn.getPackageContext(mContext),
Dan Sandler68079d52015-07-22 10:45:30 -04002338 entry.getExpandedContentView(),
Jorim Jaggi39fa59f2014-02-25 15:38:45 +01002339 mOnClickHandler);
Chris Wrene03f4e12013-08-08 16:48:48 -04002340 }
Selim Cinek684a4422015-04-15 16:18:39 -07002341 View headsUpChild = entry.getHeadsUpContentView();
Selim Cinek8d490d42015-04-10 00:05:50 -07002342 if (headsUpContentView != null && headsUpChild != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002343 headsUpContentView.reapply(sbn.getPackageContext(mContext),
Dan Sandler68079d52015-07-22 10:45:30 -04002344 headsUpChild, mOnClickHandler);
Selim Cinek8d490d42015-04-10 00:05:50 -07002345 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05002346 if (publicContentView != null && entry.getPublicContentView() != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002347 publicContentView.reapply(sbn.getPackageContext(mContext),
Dan Sandler68079d52015-07-22 10:45:30 -04002348 entry.getPublicContentView(), mOnClickHandler);
Dan Sandlera5e0f412014-01-23 15:11:54 -05002349 }
Chris Wrene03f4e12013-08-08 16:48:48 -04002350 // update the contentIntent
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002351 mNotificationClicker.register(entry.row, sbn);
Chris Wren42d5dd42015-05-01 10:39:26 -04002352
Selim Cinekda42d652015-12-04 15:51:16 -08002353 entry.row.onNotificationUpdated(entry);
Selim Cinek51ae05d2014-09-09 15:51:38 +02002354 entry.row.resetHeight();
Chris Wren0c8275b2012-05-08 13:36:48 -04002355 }
John Spurlock36231282012-06-23 17:11:27 -04002356
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00002357 protected void updatePublicContentView(Entry entry,
2358 StatusBarNotification sbn) {
2359 final RemoteViews publicContentView = entry.cachedPublicContentView;
Selim Cineke4c068d2016-02-19 13:46:55 -08002360 View inflatedView = entry.getPublicContentView();
2361 if (entry.autoRedacted && publicContentView != null && inflatedView != null) {
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00002362 final boolean disabledByPolicy =
2363 !adminAllowsUnredactedNotifications(entry.notification.getUserId());
Selim Cineke4c068d2016-02-19 13:46:55 -08002364 String notificationHiddenText = mContext.getString(disabledByPolicy
2365 ? com.android.internal.R.string.notification_hidden_by_policy_text
2366 : com.android.internal.R.string.notification_hidden_text);
2367 TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
2368 if (titleView != null
2369 && !titleView.getText().toString().equals(notificationHiddenText)) {
2370 publicContentView.setTextViewText(android.R.id.title, notificationHiddenText);
2371 publicContentView.reapply(sbn.getPackageContext(mContext),
2372 inflatedView, mOnClickHandler);
2373 entry.row.onNotificationUpdated(entry);
2374 }
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00002375 }
2376 }
2377
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002378 protected void notifyHeadsUpScreenOff() {
Selim Cinek684a4422015-04-15 16:18:39 -07002379 maybeEscalateHeadsUp();
Chris Wrene97f90b2013-08-07 17:39:35 -04002380 }
2381
Chris Wrend93d5ad2014-09-08 16:34:03 -04002382 private boolean alertAgain(Entry oldEntry, Notification newNotification) {
2383 return oldEntry == null || !oldEntry.hasInterrupted()
2384 || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
Chris Wrend04f6ce2014-06-11 17:37:28 -04002385 }
2386
Chris Wrenbdf33762015-12-04 15:50:51 -05002387 protected boolean shouldPeek(Entry entry) {
2388 return shouldPeek(entry, entry.notification);
Chris Wren0c274b12015-07-17 10:34:53 -04002389 }
2390
Chris Wrenbdf33762015-12-04 15:50:51 -05002391 protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
Adrian Roosf6967e062016-06-21 16:12:48 -07002392 if (!mUseHeadsUp || isDeviceInVrMode()) {
Dan Sandlerdc34df52016-04-07 21:04:46 -04002393 return false;
2394 }
2395
Christoph Studer2f9dbba2014-09-03 17:35:54 +02002396 if (mNotificationData.shouldFilterOut(sbn)) {
Chris Wrenbdf33762015-12-04 15:50:51 -05002397 if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
Christoph Studer2f9dbba2014-09-03 17:35:54 +02002398 return false;
2399 }
2400
Selim Cinek01ee2cd52016-12-21 18:23:11 +01002401 boolean inUse = mPowerManager.isScreenOn();
Selim Cinekd5921912016-02-09 10:33:01 -08002402 try {
2403 inUse = inUse && !mDreamManager.isDreaming();
2404 } catch (RemoteException e) {
2405 Log.d(TAG, "failed to query dream manager", e);
2406 }
2407
Adrian Roos4b820e42017-01-13 17:40:43 -08002408 if (!inUse && !isDozing()) {
Selim Cinekd5921912016-02-09 10:33:01 -08002409 if (DEBUG) {
2410 Log.d(TAG, "No peeking: not in use: " + sbn.getKey());
2411 }
2412 return false;
2413 }
2414
2415 if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
2416 if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
Chris Wrena6d4fb62014-11-20 14:46:23 -05002417 return false;
2418 }
2419
Chris Wrenbdf33762015-12-04 15:50:51 -05002420 if (entry.hasJustLaunchedFullScreenIntent()) {
2421 if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
2422 return false;
2423 }
2424
Julia Reynoldsf0f629f2016-02-25 09:34:04 -05002425 if (isSnoozedPackage(sbn)) {
2426 if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
2427 return false;
2428 }
2429
Julia Reynolds85769912016-10-25 09:08:57 -04002430 if (mNotificationData.getImportance(sbn.getKey()) < NotificationManager.IMPORTANCE_HIGH) {
Julia Reynoldsf0f629f2016-02-25 09:34:04 -05002431 if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
2432 return false;
2433 }
2434
Selim Cinekd5921912016-02-09 10:33:01 -08002435 if (sbn.getNotification().fullScreenIntent != null) {
2436 if (mAccessibilityManager.isTouchExplorationEnabled()) {
2437 if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
2438 return false;
2439 } else {
Selim Cinek01ee2cd52016-12-21 18:23:11 +01002440 // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
2441 return !mStatusBarKeyguardViewManager.isShowing()
2442 || mStatusBarKeyguardViewManager.isOccluded();
Selim Cinekd5921912016-02-09 10:33:01 -08002443 }
Chris Wrenbdf33762015-12-04 15:50:51 -05002444 }
2445
Selim Cinekd5921912016-02-09 10:33:01 -08002446 return true;
Chris Wren157026f2013-06-28 16:54:01 -04002447 }
2448
Selim Cinek29fa89b2015-04-17 10:39:11 -07002449 protected abstract boolean isSnoozedPackage(StatusBarNotification sbn);
2450
John Spurlockcfc359a2013-09-05 10:42:03 -04002451 public void setInteracting(int barWindow, boolean interacting) {
John Spurlockad3e6cb2013-04-30 08:47:43 -04002452 // hook for subclasses
2453 }
John Spurlock5c454122013-06-17 07:35:46 -04002454
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02002455 public void setBouncerShowing(boolean bouncerShowing) {
2456 mBouncerShowing = bouncerShowing;
2457 }
2458
2459 /**
2460 * @return Whether the security bouncer from Keyguard is showing.
2461 */
2462 public boolean isBouncerShowing() {
2463 return mBouncerShowing;
2464 }
2465
John Spurlock5c454122013-06-17 07:35:46 -04002466 public void destroy() {
John Spurlock5c454122013-06-17 07:35:46 -04002467 mContext.unregisterReceiver(mBroadcastReceiver);
Christoph Studere71fefc2014-06-24 16:16:49 +02002468 try {
2469 mNotificationListener.unregisterAsSystemService();
2470 } catch (RemoteException e) {
2471 // Ignore.
Christoph Studer37fe6932014-05-26 13:10:30 +02002472 }
John Spurlock5c454122013-06-17 07:35:46 -04002473 }
Kenny Guy4dcb0dc2014-07-15 12:41:24 +01002474
2475 /**
2476 * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then
2477 * return PackageManager for mContext
2478 */
Selim Cinekeef84282015-10-30 16:28:00 -07002479 public static PackageManager getPackageManagerForUser(Context context, int userId) {
2480 Context contextForUser = context;
Kenny Guy4dcb0dc2014-07-15 12:41:24 +01002481 // UserHandle defines special userId as negative values, e.g. USER_ALL
2482 if (userId >= 0) {
2483 try {
2484 // Create a context for the correct user so if a package isn't installed
2485 // for user 0 we can still load information about the package.
2486 contextForUser =
Selim Cinekeef84282015-10-30 16:28:00 -07002487 context.createPackageContextAsUser(context.getPackageName(),
Kenny Guy4dcb0dc2014-07-15 12:41:24 +01002488 Context.CONTEXT_RESTRICTED,
2489 new UserHandle(userId));
2490 } catch (NameNotFoundException e) {
2491 // Shouldn't fail to find the package name for system ui.
2492 }
2493 }
2494 return contextForUser.getPackageManager();
2495 }
Chris Wren78403d72014-07-28 10:23:24 +01002496
2497 @Override
2498 public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
2499 try {
2500 mBarService.onNotificationExpansionChanged(key, userAction, expanded);
2501 } catch (RemoteException e) {
2502 // Ignore.
2503 }
2504 }
Jim Millerab954542014-10-10 18:21:49 -07002505
2506 public boolean isKeyguardSecure() {
Dan Sandlere163a642015-03-01 22:58:32 -05002507 if (mStatusBarKeyguardViewManager == null) {
2508 // startKeyguard() hasn't been called yet, so we don't know.
2509 // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
2510 // value onVisibilityChanged().
2511 Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
2512 new Throwable());
2513 return false;
2514 }
Jim Millerab954542014-10-10 18:21:49 -07002515 return mStatusBarKeyguardViewManager.isSecure();
2516 }
Adrian Roos4f43dc02015-06-17 16:43:38 -07002517
2518 @Override
2519 public void showAssistDisclosure() {
2520 if (mAssistManager != null) {
2521 mAssistManager.showDisclosure();
2522 }
2523 }
Jorim Jaggi165ce062015-07-06 16:18:11 -07002524
2525 @Override
2526 public void startAssist(Bundle args) {
2527 if (mAssistManager != null) {
2528 mAssistManager.startAssist(args);
2529 }
2530 }
Joe Onorato2314aab2010-04-08 16:41:23 -05002531}