blob: 7d3d8e8449918433915d0e3ecf16f7860d8d7f31 [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;
Daniel Sandler6a858c32012-03-12 14:38:58 -040023import android.app.ActivityManagerNative;
Jorim Jaggie6e108e2016-03-28 13:38:45 -070024import android.app.ActivityOptions;
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 Jaggi39fa59f2014-02-25 15:38:45 +010045import android.graphics.drawable.Drawable;
Dan Sandler33439812015-08-10 15:49:56 -040046import android.graphics.drawable.Icon;
Jorim Jaggi8de4311c2014-08-11 22:36:20 +020047import android.os.AsyncTask;
Daniel Sandler96fd7c12012-03-30 16:37:36 -040048import android.os.Build;
Jorim Jaggi165ce062015-07-06 16:18:11 -070049import android.os.Bundle;
Michael Jurka7f2668c2012-03-27 07:49:52 -070050import android.os.Handler;
Joe Onorato808182d2010-07-09 18:52:06 -040051import android.os.IBinder;
Michael Jurka7f2668c2012-03-27 07:49:52 -070052import android.os.Message;
Chris Wren157026f2013-06-28 16:54:01 -040053import android.os.PowerManager;
Joe Onorato808182d2010-07-09 18:52:06 -040054import android.os.RemoteException;
55import android.os.ServiceManager;
Adrian Roos497ab022015-02-10 20:49:33 +010056import android.os.SystemProperties;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070057import android.os.UserHandle;
Kenny Guy3a7c4a52014-03-03 18:24:03 +000058import android.os.UserManager;
Daniel Sandlerf7a19562012-04-04 14:04:21 -040059import android.provider.Settings;
Chris Wren157026f2013-06-28 16:54:01 -040060import android.service.dreams.DreamService;
61import android.service.dreams.IDreamManager;
Christoph Studer60748e72014-05-22 16:51:41 +020062import android.service.notification.NotificationListenerService;
Christoph Studerd0694b62014-06-04 16:36:01 +020063import android.service.notification.NotificationListenerService.RankingMap;
John Spurlockde84f0e2013-06-12 12:41:00 -040064import android.service.notification.StatusBarNotification;
Dan Sandlerdc34df52016-04-07 21:04:46 -040065import android.service.vr.IVrManager;
66import android.service.vr.IVrStateCallbacks;
Chris Wren0c8275b2012-05-08 13:36:48 -040067import android.text.TextUtils;
Selim Cinek2d79f632015-11-02 15:13:29 -080068import android.util.ArraySet;
Joe Onorato808182d2010-07-09 18:52:06 -040069import android.util.Log;
Dan Sandlere163a642015-03-01 22:58:32 -050070import android.util.Slog;
Kenny Guy3a7c4a52014-03-03 18:24:03 +000071import android.util.SparseArray;
Dan Sandlerfd16d562014-02-13 18:43:31 -080072import android.util.SparseBooleanArray;
Daniel Sandlerc638c1e2011-08-24 16:19:23 -070073import android.view.Display;
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -050074import android.view.IWindowManager;
Michael Jurka7f2668c2012-03-27 07:49:52 -070075import android.view.LayoutInflater;
76import android.view.MotionEvent;
Joe Onorato808182d2010-07-09 18:52:06 -040077import android.view.View;
Dan Sandler4247a5c2014-07-23 15:58:08 -040078import android.view.ViewAnimationUtils;
Daniel Sandler6a858c32012-03-12 14:38:58 -040079import android.view.ViewGroup;
Christoph Studer4da84cd2014-10-21 17:24:20 +020080import android.view.ViewParent;
Joe Onorato808182d2010-07-09 18:52:06 -040081import android.view.WindowManager;
Michael Jurka80343f62012-10-18 13:13:46 +020082import android.view.WindowManagerGlobal;
Selim Cineka8fefa52014-09-08 16:10:50 +020083import android.view.accessibility.AccessibilityManager;
Chris Wren0c8275b2012-05-08 13:36:48 -040084import android.widget.ImageView;
Michael Jurkaa600fd92012-06-25 15:57:05 -070085import android.widget.RemoteViews;
Daniel Sandlerb9301c32012-08-14 15:08:24 -040086import android.widget.TextView;
Kenny Guydae30d52015-04-01 19:11:35 +010087import android.widget.Toast;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050088
Chris Wrenbd6b5fb2015-06-09 14:58:34 -040089import com.android.internal.logging.MetricsLogger;
Tamas Berghammercbd3f0c2016-06-22 15:21:38 +010090import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
John Spurlockde84f0e2013-06-12 12:41:00 -040091import com.android.internal.statusbar.IStatusBarService;
92import com.android.internal.statusbar.StatusBarIcon;
Chris Wrencd8f4f72014-08-27 18:48:13 -040093import com.android.internal.widget.LockPatternUtils;
Mady Mellor97c8df42016-03-22 18:09:39 -070094import com.android.keyguard.KeyguardHostView.OnDismissAction;
Selim Cinekfa760d42016-05-10 15:50:53 -040095import com.android.keyguard.KeyguardUpdateMonitor;
Jorim Jaggi5eb67c22015-08-19 19:50:49 -070096import com.android.systemui.DejankUtils;
Winsonc0d70582016-01-29 10:24:39 -080097import com.android.systemui.Interpolators;
John Spurlockde84f0e2013-06-12 12:41:00 -040098import com.android.systemui.R;
John Spurlockd08de372013-06-24 13:06:08 -040099import com.android.systemui.RecentsComponent;
Dan Sandler4247a5c2014-07-23 15:58:08 -0400100import com.android.systemui.SwipeHelper;
John Spurlockde84f0e2013-06-12 12:41:00 -0400101import com.android.systemui.SystemUI;
Jorim Jaggib835dd72015-06-08 12:28:42 -0700102import com.android.systemui.assist.AssistManager;
Jorim Jaggid61f2272014-12-19 20:35:35 +0100103import com.android.systemui.recents.Recents;
Christoph Studer37fe6932014-05-26 13:10:30 +0200104import com.android.systemui.statusbar.NotificationData.Entry;
Mady Mellor97c8df42016-03-22 18:09:39 -0700105import com.android.systemui.statusbar.NotificationGuts.OnGutsClosedListener;
Selim Cinek92d892c2014-09-11 15:11:00 +0200106import com.android.systemui.statusbar.phone.NavigationBarView;
Selim Cinek25fd4e2b2015-02-20 17:46:07 +0100107import com.android.systemui.statusbar.phone.NotificationGroupManager;
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200108import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700109import com.android.systemui.statusbar.policy.HeadsUpManager;
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200110import com.android.systemui.statusbar.policy.PreviewInflater;
Adrian Roos497ab022015-02-10 20:49:33 +0100111import com.android.systemui.statusbar.policy.RemoteInputView;
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100112import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Selim Cinekd84a5932015-12-15 11:45:36 -0800113import com.android.systemui.statusbar.stack.StackStateAnimator;
John Spurlockde84f0e2013-06-12 12:41:00 -0400114
Michael Jurkaa600fd92012-06-25 15:57:05 -0700115import java.util.ArrayList;
Julia Reynolds98a44862016-09-12 08:53:47 -0400116import java.util.Collections;
117import java.util.HashSet;
Dan Sandlerf4db75c2014-09-03 18:02:31 +0200118import java.util.List;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700119import java.util.Locale;
Julia Reynolds98a44862016-09-12 08:53:47 -0400120import java.util.Set;
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400121
Julia Reynoldsf0f629f2016-02-25 09:34:04 -0500122import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
Adrian Roos7d7090d2014-05-21 13:10:23 +0200123
Michael Jurka7f2668c2012-03-27 07:49:52 -0700124public abstract class BaseStatusBar extends SystemUI implements
Winson Chung9214eff2014-06-12 13:59:25 -0700125 CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
Selim Cinek570981d2015-12-01 11:37:01 -0800126 ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
Mady Mellor97c8df42016-03-22 18:09:39 -0700127 ExpandableNotificationRow.OnExpandClickListener,
128 OnGutsClosedListener {
Daniel Sandler198a0302012-08-17 16:04:31 -0400129 public static final String TAG = "StatusBar";
Jorim Jaggi86905582016-02-09 21:36:09 -0800130 public static final boolean DEBUG = false;
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400131 public static final boolean MULTIUSER_DEBUG = false;
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400132
Adrian Roos497ab022015-02-10 20:49:33 +0100133 public static final boolean ENABLE_REMOTE_INPUT =
Adrian Roos9531c9b2015-11-03 17:43:01 -0800134 SystemProperties.getBoolean("debug.enable_remote_input", true);
Selim Cinek40412492015-12-08 18:03:22 -0800135 public static final boolean ENABLE_CHILD_NOTIFICATIONS
136 = SystemProperties.getBoolean("debug.child_notifs", true);
Adrian Roosc0a579e2016-03-30 16:43:58 -0700137 public static final boolean FORCE_REMOTE_INPUT_HISTORY =
138 SystemProperties.getBoolean("debug.force_remoteinput_history", false);
Adrian Roosb27d7a52016-06-16 13:04:47 -0700139 private static boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
Adrian Roos497ab022015-02-10 20:49:33 +0100140
Winson Chung1e8d71b2014-05-16 17:05:22 -0700141 protected static final int MSG_SHOW_RECENT_APPS = 1019;
142 protected static final int MSG_HIDE_RECENT_APPS = 1020;
143 protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700144 protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
145 protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
Winson Chungb1f74992014-08-08 12:53:09 -0700146 protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
147 protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
Andrei Stingaceanuc22ab792016-01-07 12:39:38 +0000148 protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +0100149 protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
Chris Wren0c8275b2012-05-08 13:36:48 -0400150
Chris Wren157026f2013-06-28 16:54:01 -0400151 protected static final boolean ENABLE_HEADS_UP = true;
Chris Wren22ae46e2014-02-26 18:08:09 -0500152 protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
Chris Wren0c8275b2012-05-08 13:36:48 -0400153
Ricky Wai7fa01712016-03-16 12:13:54 +0000154 private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
155
Winsond8b1d632016-01-04 17:51:18 -0800156 // Should match the values in PhoneWindowManager
Michael Jurka56a57832012-05-14 13:24:43 -0700157 public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
Winsond8b1d632016-01-04 17:51:18 -0800158 public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
Michael Jurka56a57832012-05-14 13:24:43 -0700159
Chris Wrencd8f4f72014-08-27 18:48:13 -0400160 private static final String BANNER_ACTION_CANCEL =
161 "com.android.systemui.statusbar.banner_action_cancel";
162 private static final String BANNER_ACTION_SETUP =
163 "com.android.systemui.statusbar.banner_action_setup";
Ricky Wai7fa01712016-03-16 12:13:54 +0000164 private static final String WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION
165 = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
Chris Wrencd8f4f72014-08-27 18:48:13 -0400166
Joe Onorato808182d2010-07-09 18:52:06 -0400167 protected CommandQueue mCommandQueue;
168 protected IStatusBarService mBarService;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700169 protected H mHandler = createHandler();
170
Chris Wren0c8275b2012-05-08 13:36:48 -0400171 // all notifications
Christoph Studerc8db24b2014-07-25 17:50:30 +0200172 protected NotificationData mNotificationData;
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100173 protected NotificationStackScrollLayout mStackScroller;
Chris Wren0c8275b2012-05-08 13:36:48 -0400174
Selim Cinek25fd4e2b2015-02-20 17:46:07 +0100175 protected NotificationGroupManager mGroupManager = new NotificationGroupManager();
176
Adrian Roosb88b1a12015-12-09 18:51:05 -0800177 protected RemoteInputController mRemoteInputController;
178
Chris Wrena4ef6202014-06-09 18:07:30 -0400179 // for heads up notifications
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700180 protected HeadsUpManager mHeadsUpManager;
Chris Wren0c8275b2012-05-08 13:36:48 -0400181
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
188 // on-screen navigation buttons
189 protected NavigationBarView mNavigationBarView = null;
Christoph Studere8e28652014-10-29 17:27:53 +0100190
Jorim Jaggi50ff3af2015-08-12 18:35:42 -0700191 protected boolean mDeviceInteractive;
Christoph Studere8e28652014-10-29 17:27:53 +0100192
193 protected boolean mVisible;
Selim Cinek2d79f632015-11-02 15:13:29 -0800194 protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>();
Adrian Roos18d099a2016-05-19 15:28:18 -0700195 protected ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>();
Christoph Studere8e28652014-10-29 17:27:53 +0100196
Adrian Roosc0a579e2016-03-30 16:43:58 -0700197 /**
198 * Notifications with keys in this set are not actually around anymore. We kept them around
199 * when they were canceled in response to a remote input interaction. This allows us to show
200 * what you replied and allows you to continue typing into it.
201 */
202 protected ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
203
Christoph Studere8e28652014-10-29 17:27:53 +0100204 // mScreenOnFromKeyguard && mVisible.
205 private boolean mVisibleToUser;
206
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700207 private Locale mLocale;
Dan Sandler539aad42014-08-04 00:43:39 -0400208 private float mFontScale;
209
Chris Wrenf6e83f42013-09-11 14:02:59 -0400210 protected boolean mUseHeadsUp = false;
Chris Wren22ae46e2014-02-26 18:08:09 -0500211 protected boolean mHeadsUpTicker = false;
Jason Monkf7019542014-07-31 12:42:25 -0400212 protected boolean mDisableNotificationAlerts = false;
Chris Wren157026f2013-06-28 16:54:01 -0400213
Adrian Roosbd3409c2014-08-12 18:21:09 +0200214 protected DevicePolicyManager mDevicePolicyManager;
Chris Wren157026f2013-06-28 16:54:01 -0400215 protected IDreamManager mDreamManager;
Julia Reynolds0971cb02016-01-26 17:00:22 -0500216 protected PowerManager mPowerManager;
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200217 protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Dan Sandlerfd16d562014-02-13 18:43:31 -0800218
219 // public mode, private notifications, etc
220 private boolean mLockscreenPublicMode = false;
221 private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
Julia Reynolds26fa8a52016-02-24 08:31:22 -0500222 private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700223
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000224 private UserManager mUserManager;
Selim Cinek01af3342016-02-09 19:25:31 -0800225 private int mDensity;
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000226
Ricky Wai7fa01712016-03-16 12:13:54 +0000227 private KeyguardManager mKeyguardManager;
228 private LockPatternUtils mLockPatternUtils;
229
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500230 // UI-specific methods
Daniel Sandler6a858c32012-03-12 14:38:58 -0400231
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500232 /**
233 * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
234 * and add them to the window manager.
235 */
236 protected abstract void createAndAddWindows();
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400237
Jeff Brown98365d72012-08-19 20:30:52 -0700238 protected WindowManager mWindowManager;
239 protected IWindowManager mWindowManagerService;
Christoph Studer60748e72014-05-22 16:51:41 +0200240
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700241 protected abstract void refreshLayout(int layoutDirection);
242
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500243 protected Display mDisplay;
Jeff Brown98365d72012-08-19 20:30:52 -0700244
Daniel Sandler26cda272012-05-22 15:44:08 -0400245 private boolean mDeviceProvisioned = false;
Daniel Sandler6a858c32012-03-12 14:38:58 -0400246
Jorim Jaggi75b25972015-10-21 14:51:10 +0200247 protected RecentsComponent mRecents;
John Spurlockd08de372013-06-24 13:06:08 -0400248
John Spurlocke677d712014-02-13 12:52:19 -0500249 protected int mZenMode;
250
Dan Sandler4247a5c2014-07-23 15:58:08 -0400251 // which notification is currently being longpress-examined by the user
Selim Cinek024ca592014-09-01 15:11:28 +0200252 private NotificationGuts mNotificationGutsExposed;
Dan Sandler4247a5c2014-07-23 15:58:08 -0400253
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +0100254 private KeyboardShortcuts mKeyboardShortcuts;
255
Jorim Jaggiecbab362014-04-23 16:13:15 +0200256 /**
257 * The {@link StatusBarState} of the status bar.
258 */
259 protected int mState;
Jorim Jaggi4222d9a2014-04-23 16:13:15 +0200260 protected boolean mBouncerShowing;
John Spurlock4b3bda22014-05-22 14:32:20 -0400261 protected boolean mShowLockscreenNotifications;
Adrian Roos3aec6382016-02-05 14:19:01 -0800262 protected boolean mAllowLockscreenRemoteInput;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200263
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200264 protected NotificationOverflowContainer mKeyguardIconOverflowContainer;
Dan Sandlereceda3d2014-07-21 15:35:01 -0400265 protected DismissView mDismissView;
Jorim Jaggia2052ea2014-08-05 16:22:30 +0200266 protected EmptyShadeView mEmptyShadeView;
Jorim Jaggi649b7082014-04-03 13:15:18 +0200267
Chris Wren42d5dd42015-05-01 10:39:26 -0400268 private NotificationClicker mNotificationClicker = new NotificationClicker();
269
Jorim Jaggib835dd72015-06-08 12:28:42 -0700270 protected AssistManager mAssistManager;
271
Dan Sandlerdc34df52016-04-07 21:04:46 -0400272 protected boolean mVrMode;
273
Julia Reynolds98a44862016-09-12 08:53:47 -0400274 private Set<String> mNonBlockablePkgs;
275
Christoph Studerc8db24b2014-07-25 17:50:30 +0200276 @Override // NotificationData.Environment
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400277 public boolean isDeviceProvisioned() {
Daniel Sandler26cda272012-05-22 15:44:08 -0400278 return mDeviceProvisioned;
279 }
280
Dan Sandlerdc34df52016-04-07 21:04:46 -0400281 private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
282 @Override
283 public void onVrStateChanged(boolean enabled) {
284 mVrMode = enabled;
285 }
286 };
287
288 public boolean isDeviceInVrMode() {
289 return mVrMode;
290 }
291
John Spurlocke677d712014-02-13 12:52:19 -0500292 protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
Daniel Sandler26cda272012-05-22 15:44:08 -0400293 @Override
294 public void onChange(boolean selfChange) {
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700295 final boolean provisioned = 0 != Settings.Global.getInt(
296 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0);
Daniel Sandler26cda272012-05-22 15:44:08 -0400297 if (provisioned != mDeviceProvisioned) {
298 mDeviceProvisioned = provisioned;
Christoph Studer37fe6932014-05-26 13:10:30 +0200299 updateNotifications();
Daniel Sandler26cda272012-05-22 15:44:08 -0400300 }
John Spurlocke677d712014-02-13 12:52:19 -0500301 final int mode = Settings.Global.getInt(mContext.getContentResolver(),
302 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
303 setZenMode(mode);
Dan Sandler52e5701e2014-07-22 23:14:54 -0400304
305 updateLockscreenNotificationSetting();
Daniel Sandler26cda272012-05-22 15:44:08 -0400306 }
307 };
308
Dan Sandlerfd16d562014-02-13 18:43:31 -0800309 private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
310 @Override
311 public void onChange(boolean selfChange) {
Daniel U57454872016-03-29 20:28:21 +0100312 // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
313 // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
Dan Sandlerfd16d562014-02-13 18:43:31 -0800314 mUsersAllowingPrivateNotifications.clear();
Daniel U57454872016-03-29 20:28:21 +0100315 mUsersAllowingNotifications.clear();
Dan Sandlerfd16d562014-02-13 18:43:31 -0800316 // ... and refresh all the notifications
Christoph Studer37fe6932014-05-26 13:10:30 +0200317 updateNotifications();
Dan Sandlerfd16d562014-02-13 18:43:31 -0800318 }
319 };
320
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700321 private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
322 @Override
Adrian Roos7d7090d2014-05-21 13:10:23 +0200323 public boolean onClickHandler(
324 final View view, final PendingIntent pendingIntent, final Intent fillInIntent) {
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800325 if (handleRemoteInput(view, pendingIntent, fillInIntent)) {
326 return true;
327 }
328
Daniel Sandler198a0302012-08-17 16:04:31 -0400329 if (DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -0400330 Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
Daniel Sandler198a0302012-08-17 16:04:31 -0400331 }
Christoph Studer4da84cd2014-10-21 17:24:20 +0200332 logActionClick(view);
Jorim Jaggi89f7f282014-10-17 19:54:15 +0200333 // The intent we are sending is for the application, which
334 // won't have permission to immediately start an activity after
335 // the user switches to home. We know it is safe to do at this
336 // point, so make sure new activity switches are now allowed.
337 try {
338 ActivityManagerNative.getDefault().resumeAppSwitches();
339 } catch (RemoteException e) {
340 }
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700341 final boolean isActivity = pendingIntent.isActivity();
342 if (isActivity) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200343 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200344 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
345 mContext, pendingIntent.getIntent(), mCurrentUserId);
Adrian Roos4314f6d2014-05-28 14:10:27 +0200346 dismissKeyguardThenExecute(new OnDismissAction() {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200347 @Override
348 public boolean onDismiss() {
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200349 if (keyguardShowing && !afterKeyguardGone) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200350 try {
351 ActivityManagerNative.getDefault()
352 .keyguardWaitingForActivityDrawn();
Jorim Jaggi91617a72015-06-25 15:01:29 -0700353 ActivityManagerNative.getDefault().resumeAppSwitches();
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200354 } catch (RemoteException e) {
355 }
Adrian Roos7d7090d2014-05-21 13:10:23 +0200356 }
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700357
Adrian Roos7d7090d2014-05-21 13:10:23 +0200358 boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200359 overrideActivityPendingAppTransition(keyguardShowing && !afterKeyguardGone);
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700360
Adrian Roos7d7090d2014-05-21 13:10:23 +0200361 // close the shade if it was open
362 if (handled) {
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +0100363 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
364 true /* force */);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200365 visibilityChanged(false);
Jorim Jaggi91617a72015-06-25 15:01:29 -0700366 mAssistManager.hideAssist();
Adrian Roos7d7090d2014-05-21 13:10:23 +0200367 }
Jorim Jaggi91617a72015-06-25 15:01:29 -0700368
Adrian Roos4314f6d2014-05-28 14:10:27 +0200369 // Wait for activity start.
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200370 return handled;
Adrian Roos7d7090d2014-05-21 13:10:23 +0200371 }
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200372 }, afterKeyguardGone);
Adrian Roos7d7090d2014-05-21 13:10:23 +0200373 return true;
374 } else {
Jorim Jaggie6e108e2016-03-28 13:38:45 -0700375 return superOnClickHandler(view, pendingIntent, fillInIntent);
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700376 }
Adrian Roos7d7090d2014-05-21 13:10:23 +0200377 }
378
Christoph Studer4da84cd2014-10-21 17:24:20 +0200379 private void logActionClick(View view) {
380 ViewParent parent = view.getParent();
381 String key = getNotificationKeyForParent(parent);
382 if (key == null) {
383 Log.w(TAG, "Couldn't determine notification for click.");
384 return;
385 }
386 int index = -1;
387 // If this is a default template, determine the index of the button.
388 if (view.getId() == com.android.internal.R.id.action0 &&
389 parent != null && parent instanceof ViewGroup) {
390 ViewGroup actionGroup = (ViewGroup) parent;
391 index = actionGroup.indexOfChild(view);
392 }
393 try {
394 mBarService.onNotificationActionClick(key, index);
395 } catch (RemoteException e) {
396 // Ignore
397 }
398 }
399
400 private String getNotificationKeyForParent(ViewParent parent) {
401 while (parent != null) {
402 if (parent instanceof ExpandableNotificationRow) {
403 return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey();
404 }
405 parent = parent.getParent();
406 }
407 return null;
408 }
409
Adrian Roos7d7090d2014-05-21 13:10:23 +0200410 private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
411 Intent fillInIntent) {
Jorim Jaggie6e108e2016-03-28 13:38:45 -0700412 return super.onClickHandler(view, pendingIntent, fillInIntent,
413 StackId.FULLSCREEN_WORKSPACE_STACK_ID);
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700414 }
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800415
416 private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) {
417 Object tag = view.getTag(com.android.internal.R.id.remote_input_tag);
418 RemoteInput[] inputs = null;
419 if (tag instanceof RemoteInput[]) {
420 inputs = (RemoteInput[]) tag;
421 }
422
423 if (inputs == null) {
424 return false;
425 }
426
427 RemoteInput input = null;
428
429 for (RemoteInput i : inputs) {
430 if (i.getAllowFreeFormInput()) {
431 input = i;
432 }
433 }
434
435 if (input == null) {
436 return false;
437 }
438
439 ViewParent p = view.getParent();
440 RemoteInputView riv = null;
441 while (p != null) {
442 if (p instanceof View) {
443 View pv = (View) p;
444 if (pv.isRootNamespace()) {
445 riv = (RemoteInputView) pv.findViewWithTag(RemoteInputView.VIEW_TAG);
446 break;
447 }
448 }
449 p = p.getParent();
450 }
Adrian Roos3aec6382016-02-05 14:19:01 -0800451 ExpandableNotificationRow row = null;
452 while (p != null) {
453 if (p instanceof ExpandableNotificationRow) {
454 row = (ExpandableNotificationRow) p;
455 break;
456 }
457 p = p.getParent();
458 }
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800459
Adrian Roos3aec6382016-02-05 14:19:01 -0800460 if (riv == null || row == null) {
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800461 return false;
462 }
463
Adrian Roos3aec6382016-02-05 14:19:01 -0800464 row.setUserExpanded(true);
465
Ricky Waicd35def2016-05-03 11:07:07 +0100466 if (!mAllowLockscreenRemoteInput) {
467 if (isLockscreenPublicMode()) {
468 onLockedRemoteInput(row, view);
469 return true;
470 }
471 final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
472 if (mUserManager.getUserInfo(userId).isManagedProfile()
473 && mKeyguardManager.isDeviceLocked(userId)) {
474 onLockedWorkRemoteInput(userId, row, view);
475 return true;
476 }
Adrian Roos3aec6382016-02-05 14:19:01 -0800477 }
478
Adrian Roosaf06bf22016-07-15 12:26:49 -0700479 int width = view.getWidth();
480 if (view instanceof TextView) {
481 // Center the reveal on the text which might be off-center from the TextView
482 TextView tv = (TextView) view;
483 if (tv.getLayout() != null) {
484 int innerWidth = (int) tv.getLayout().getLineWidth(0);
485 innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
486 width = Math.min(width, innerWidth);
487 }
488 }
489 int cx = view.getLeft() + width / 2;
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800490 int cy = view.getTop() + view.getHeight() / 2;
491 int w = riv.getWidth();
492 int h = riv.getHeight();
493 int r = Math.max(
494 Math.max(cx + cy, cx + (h - cy)),
495 Math.max((w - cx) + cy, (w - cx) + (h - cy)));
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800496
Adrian Roosaf06bf22016-07-15 12:26:49 -0700497 riv.setRevealParameters(cx, cy, r);
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800498 riv.setPendingIntent(pendingIntent);
499 riv.setRemoteInput(inputs, input);
Adrian Roosaf06bf22016-07-15 12:26:49 -0700500 riv.focusAnimated();
Adrian Roosfe84e1f2015-11-04 15:55:39 -0800501
502 return true;
503 }
504
Dianne Hackborn1927ae82012-06-22 15:21:36 -0700505 };
506
John Spurlock5c454122013-06-17 07:35:46 -0400507 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
508 @Override
509 public void onReceive(Context context, Intent intent) {
510 String action = intent.getAction();
511 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
512 mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Kenny Guy2a764942014-04-02 13:29:20 +0100513 updateCurrentProfilesCache();
John Spurlock5c454122013-06-17 07:35:46 -0400514 if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
Dan Sandler52e5701e2014-07-22 23:14:54 -0400515
516 updateLockscreenNotificationSetting();
517
John Spurlock5c454122013-06-17 07:35:46 -0400518 userSwitched(mCurrentUserId);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000519 } else if (Intent.ACTION_USER_ADDED.equals(action)) {
Kenny Guy2a764942014-04-02 13:29:20 +0100520 updateCurrentProfilesCache();
Kenny Guydae30d52015-04-01 19:11:35 +0100521 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
522 List<ActivityManager.RecentTaskInfo> recentTask = null;
523 try {
524 recentTask = ActivityManagerNative.getDefault().getRecentTasks(1,
525 ActivityManager.RECENT_WITH_EXCLUDED
526 | ActivityManager.RECENT_INCLUDE_PROFILES,
Jeff Sharkey479212c2016-06-29 16:00:55 -0600527 mCurrentUserId).getList();
Kenny Guydae30d52015-04-01 19:11:35 +0100528 } catch (RemoteException e) {
529 // Abandon hope activity manager not running.
530 }
531 if (recentTask != null && recentTask.size() > 0) {
532 UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId);
533 if (user != null && user.isManagedProfile()) {
Kenny Guy63bf8ac2015-06-18 15:09:09 +0100534 Toast toast = Toast.makeText(mContext,
535 R.string.managed_profile_foreground_toast,
536 Toast.LENGTH_SHORT);
537 TextView text = (TextView) toast.getView().findViewById(
538 android.R.id.message);
539 text.setCompoundDrawablesRelativeWithIntrinsicBounds(
540 R.drawable.stat_sys_managed_profile_status, 0, 0, 0);
541 int paddingPx = mContext.getResources().getDimensionPixelSize(
542 R.dimen.managed_profile_toast_padding);
543 text.setCompoundDrawablePadding(paddingPx);
Kenny Guy540f7d22015-06-08 20:24:23 +0100544 toast.show();
Kenny Guydae30d52015-04-01 19:11:35 +0100545 }
546 }
Chris Wrencd8f4f72014-08-27 18:48:13 -0400547 } else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
548 NotificationManager noMan = (NotificationManager)
549 mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Chris Wrend8775102015-01-16 16:16:43 -0500550 noMan.cancel(R.id.notification_hidden);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400551
552 Settings.Secure.putInt(mContext.getContentResolver(),
553 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
554 if (BANNER_ACTION_SETUP.equals(action)) {
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +0100555 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
556 true /* force */);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400557 mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
558 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
559
560 );
561 }
Ricky Wai7fa01712016-03-16 12:13:54 +0000562 } else if (WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION.equals(action)) {
Tony Mak646fe992016-04-21 16:43:08 +0100563 final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
Ricky Wai7fa01712016-03-16 12:13:54 +0000564 final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
Ricky Waicd35def2016-05-03 11:07:07 +0100565 if (intentSender != null) {
566 try {
567 mContext.startIntentSender(intentSender, null, 0, 0, 0);
568 } catch (IntentSender.SendIntentException e) {
569 /* ignore */
570 }
Ricky Wai7fa01712016-03-16 12:13:54 +0000571 }
Ricky Waicd35def2016-05-03 11:07:07 +0100572 if (notificationKey != null) {
573 try {
574 mBarService.onNotificationClick(notificationKey);
575 } catch (RemoteException e) {
576 /* ignore */
577 }
Ricky Wai7fa01712016-03-16 12:13:54 +0000578 }
Ricky Waicd35def2016-05-03 11:07:07 +0100579 onWorkChallengeUnlocked();
John Spurlock5c454122013-06-17 07:35:46 -0400580 }
581 }
582 };
583
Kenny Guy0b7dd1e2015-03-12 17:14:38 +0000584 private final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
585 @Override
586 public void onReceive(Context context, Intent intent) {
587 String action = intent.getAction();
588 if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
589 isCurrentProfile(getSendingUserId())) {
590 mUsersAllowingPrivateNotifications.clear();
591 updateLockscreenNotificationSetting();
592 updateNotifications();
593 }
594 }
595 };
596
Christoph Studer60748e72014-05-22 16:51:41 +0200597 private final NotificationListenerService mNotificationListener =
598 new NotificationListenerService() {
599 @Override
600 public void onListenerConnected() {
601 if (DEBUG) Log.d(TAG, "onListenerConnected");
602 final StatusBarNotification[] notifications = getActiveNotifications();
Kent Persson185e9c22014-12-10 16:40:13 +0100603 if (notifications == null) {
604 Log.w(TAG, "onListenerConnected unable to get active notifications.");
605 return;
606 }
Christoph Studerd0694b62014-06-04 16:36:01 +0200607 final RankingMap currentRanking = getCurrentRanking();
Christoph Studer60748e72014-05-22 16:51:41 +0200608 mHandler.post(new Runnable() {
609 @Override
610 public void run() {
611 for (StatusBarNotification sbn : notifications) {
Selim Cinek379ff8f2015-02-20 17:03:16 +0100612 addNotification(sbn, currentRanking, null /* oldEntry */);
Christoph Studer60748e72014-05-22 16:51:41 +0200613 }
614 }
615 });
616 }
617
618 @Override
Christoph Studerd0694b62014-06-04 16:36:01 +0200619 public void onNotificationPosted(final StatusBarNotification sbn,
620 final RankingMap rankingMap) {
Christoph Studer60748e72014-05-22 16:51:41 +0200621 if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
Chris Wren56919552015-02-24 15:56:34 -0500622 if (sbn != null) {
623 mHandler.post(new Runnable() {
624 @Override
625 public void run() {
Adrian Roos497ab022015-02-10 20:49:33 +0100626 processForRemoteInput(sbn.getNotification());
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700627 String key = sbn.getKey();
Adrian Roosc0a579e2016-03-30 16:43:58 -0700628 mKeysKeptForRemoteInput.remove(key);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700629 boolean isUpdate = mNotificationData.get(key) != null;
Selim Cinekb5605e52015-02-20 18:21:41 +0100630 // In case we don't allow child notifications, we ignore children of
631 // notifications that have a summary, since we're not going to show them
632 // anyway. This is true also when the summary is canceled,
Chris Wren56919552015-02-24 15:56:34 -0500633 // because children are automatically canceled by NoMan in that case.
Selim Cinekb5605e52015-02-20 18:21:41 +0100634 if (!ENABLE_CHILD_NOTIFICATIONS
635 && mGroupManager.isChildInGroupWithSummary(sbn)) {
Chris Wren56919552015-02-24 15:56:34 -0500636 if (DEBUG) {
637 Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
638 }
639
640 // Remove existing notification to avoid stale data.
641 if (isUpdate) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700642 removeNotification(key, rankingMap);
Chris Wren56919552015-02-24 15:56:34 -0500643 } else {
644 mNotificationData.updateRanking(rankingMap);
645 }
646 return;
Christoph Studerd722f272014-09-02 11:49:19 +0200647 }
Christoph Studerd722f272014-09-02 11:49:19 +0200648 if (isUpdate) {
Chris Wren56919552015-02-24 15:56:34 -0500649 updateNotification(sbn, rankingMap);
Christoph Studerd722f272014-09-02 11:49:19 +0200650 } else {
Selim Cinek379ff8f2015-02-20 17:03:16 +0100651 addNotification(sbn, rankingMap, null /* oldEntry */);
Christoph Studerd722f272014-09-02 11:49:19 +0200652 }
Christoph Studerd722f272014-09-02 11:49:19 +0200653 }
Chris Wren56919552015-02-24 15:56:34 -0500654 });
655 }
Christoph Studer60748e72014-05-22 16:51:41 +0200656 }
657
658 @Override
Chris Wren56919552015-02-24 15:56:34 -0500659 public void onNotificationRemoved(StatusBarNotification sbn,
Christoph Studerd0694b62014-06-04 16:36:01 +0200660 final RankingMap rankingMap) {
Christoph Studer60748e72014-05-22 16:51:41 +0200661 if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
Chris Wren56919552015-02-24 15:56:34 -0500662 if (sbn != null) {
663 final String key = sbn.getKey();
664 mHandler.post(new Runnable() {
665 @Override
666 public void run() {
667 removeNotification(key, rankingMap);
668 }
669 });
670 }
Christoph Studer37fe6932014-05-26 13:10:30 +0200671 }
672
673 @Override
Christoph Studerd0694b62014-06-04 16:36:01 +0200674 public void onNotificationRankingUpdate(final RankingMap rankingMap) {
Christoph Studer37fe6932014-05-26 13:10:30 +0200675 if (DEBUG) Log.d(TAG, "onRankingUpdate");
Chris Wren56919552015-02-24 15:56:34 -0500676 if (rankingMap != null) {
Christoph Studer37fe6932014-05-26 13:10:30 +0200677 mHandler.post(new Runnable() {
678 @Override
679 public void run() {
Christoph Studere71fefc2014-06-24 16:16:49 +0200680 updateNotificationRanking(rankingMap);
Christoph Studer60748e72014-05-22 16:51:41 +0200681 }
682 });
Chris Wren56919552015-02-24 15:56:34 -0500683 } }
Christoph Studer5b638262014-07-07 11:21:49 +0200684
Christoph Studer60748e72014-05-22 16:51:41 +0200685 };
686
Kenny Guy2a764942014-04-02 13:29:20 +0100687 private void updateCurrentProfilesCache() {
688 synchronized (mCurrentProfiles) {
689 mCurrentProfiles.clear();
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000690 if (mUserManager != null) {
Kenny Guy2a764942014-04-02 13:29:20 +0100691 for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
692 mCurrentProfiles.put(user.id, user);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000693 }
694 }
695 }
696 }
697
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400698 public void start() {
Jeff Brown98365d72012-08-19 20:30:52 -0700699 mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
700 mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
701 mDisplay = mWindowManager.getDefaultDisplay();
Adrian Roosbd3409c2014-08-12 18:21:09 +0200702 mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
703 Context.DEVICE_POLICY_SERVICE);
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500704
Christoph Studerc8db24b2014-07-25 17:50:30 +0200705 mNotificationData = new NotificationData(this);
706
Selim Cineka8fefa52014-09-08 16:10:50 +0200707 mAccessibilityManager = (AccessibilityManager)
708 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
709
Chris Wren157026f2013-06-28 16:54:01 -0400710 mDreamManager = IDreamManager.Stub.asInterface(
711 ServiceManager.checkService(DreamService.DREAM_SERVICE));
Chris Wren157026f2013-06-28 16:54:01 -0400712 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
713
Daniel Sandler26cda272012-05-22 15:44:08 -0400714 mContext.getContentResolver().registerContentObserver(
Jeff Brownbf6f6f92012-09-25 15:03:20 -0700715 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), true,
John Spurlocke677d712014-02-13 12:52:19 -0500716 mSettingsObserver);
717 mContext.getContentResolver().registerContentObserver(
718 Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
719 mSettingsObserver);
John Spurlock4b3bda22014-05-22 14:32:20 -0400720 mContext.getContentResolver().registerContentObserver(
Dan Sandler52e5701e2014-07-22 23:14:54 -0400721 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
722 mSettingsObserver,
723 UserHandle.USER_ALL);
Adrian Roosb27d7a52016-06-16 13:04:47 -0700724 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
725 mContext.getContentResolver().registerContentObserver(
726 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
727 false,
728 mSettingsObserver,
729 UserHandle.USER_ALL);
730 }
Daniel Sandler26cda272012-05-22 15:44:08 -0400731
Dan Sandlerfd16d562014-02-13 18:43:31 -0800732 mContext.getContentResolver().registerContentObserver(
733 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
734 true,
735 mLockscreenSettingsObserver,
736 UserHandle.USER_ALL);
737
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500738 mBarService = IStatusBarService.Stub.asInterface(
739 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400740
Jorim Jaggid61f2272014-12-19 20:35:35 +0100741 mRecents = getComponent(Recents.class);
John Spurlockd08de372013-06-24 13:06:08 -0400742
Dan Sandler539aad42014-08-04 00:43:39 -0400743 final Configuration currentConfig = mContext.getResources().getConfiguration();
744 mLocale = currentConfig.locale;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700745 mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
Dan Sandler539aad42014-08-04 00:43:39 -0400746 mFontScale = currentConfig.fontScale;
Selim Cinek01af3342016-02-09 19:25:31 -0800747 mDensity = currentConfig.densityDpi;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700748
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000749 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Ricky Wai7fa01712016-03-16 12:13:54 +0000750 mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
751 mLockPatternUtils = new LockPatternUtils(mContext);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000752
Joe Onorato2314aab2010-04-08 16:41:23 -0500753 // Connect in to the status bar manager service
Jason Monk07473ce2016-01-05 14:59:19 -0500754 mCommandQueue = new CommandQueue(this);
Daniel Sandler6a858c32012-03-12 14:38:58 -0400755
Jorim Jaggi86905582016-02-09 21:36:09 -0800756 int[] switches = new int[9];
satokcd7cd292010-11-20 15:46:23 +0900757 ArrayList<IBinder> binders = new ArrayList<IBinder>();
Jason Monk07473ce2016-01-05 14:59:19 -0500758 ArrayList<String> iconSlots = new ArrayList<>();
759 ArrayList<StatusBarIcon> icons = new ArrayList<>();
Jorim Jaggi86905582016-02-09 21:36:09 -0800760 Rect fullscreenStackBounds = new Rect();
761 Rect dockedStackBounds = new Rect();
Joe Onorato2314aab2010-04-08 16:41:23 -0500762 try {
Jorim Jaggi86905582016-02-09 21:36:09 -0800763 mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
764 fullscreenStackBounds, dockedStackBounds);
Joe Onorato2314aab2010-04-08 16:41:23 -0500765 } catch (RemoteException ex) {
766 // If the system process isn't there we're doomed anyway.
767 }
Daniel Sandler6a858c32012-03-12 14:38:58 -0400768
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500769 createAndAddWindows();
Joe Onorato0cbda992010-05-02 16:28:15 -0700770
Jorim Jaggi66ac1332015-01-21 19:22:26 +0100771 mSettingsObserver.onChange(false); // set up
Benjamin Franzcde0a2a2015-04-23 17:19:48 +0100772 disable(switches[0], switches[6], false /* animate */);
Jorim Jaggi86905582016-02-09 21:36:09 -0800773 setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff,
774 fullscreenStackBounds, dockedStackBounds);
Dianne Hackborn7d049322011-06-14 15:00:32 -0700775 topAppWindowChanged(switches[2] != 0);
satokcd7cd292010-11-20 15:46:23 +0900776 // StatusBarManagerService has a back up of IME token and it's restored here.
Michael Wright665366a2014-08-07 15:44:40 -0700777 setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0);
Joe Onorato93056472010-09-10 10:30:46 -0400778
Joe Onorato0cbda992010-05-02 16:28:15 -0700779 // Set up the initial icon state
Jason Monk07473ce2016-01-05 14:59:19 -0500780 int N = iconSlots.size();
Joe Onorato0cbda992010-05-02 16:28:15 -0700781 int viewIndex = 0;
Jason Monk07473ce2016-01-05 14:59:19 -0500782 for (int i=0; i < N; i++) {
783 setIcon(iconSlots.get(i), icons.get(i));
Joe Onorato0cbda992010-05-02 16:28:15 -0700784 }
785
Christoph Studer71f18fd2014-05-20 17:02:04 +0200786 // Set up the initial notification state.
Christoph Studere71fefc2014-06-24 16:16:49 +0200787 try {
Christoph Studer4600f9b2014-07-22 22:44:43 +0200788 mNotificationListener.registerAsSystemService(mContext,
Christoph Studere71fefc2014-06-24 16:16:49 +0200789 new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
790 UserHandle.USER_ALL);
791 } catch (RemoteException e) {
792 Log.e(TAG, "Unable to register notification listener", e);
Joe Onorato75199e32010-05-29 17:22:51 -0400793 }
794
Christoph Studer60748e72014-05-22 16:51:41 +0200795
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500796 if (DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -0400797 Log.d(TAG, String.format(
Daniel Sandler6a858c32012-03-12 14:38:58 -0400798 "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
Jason Monk07473ce2016-01-05 14:59:19 -0500799 icons.size(),
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500800 switches[0],
801 switches[1],
802 switches[2],
803 switches[3]
804 ));
Joe Onorato1c95ecb2010-06-28 17:19:12 -0400805 }
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400806
Christopher Tate5e08af02012-09-21 17:17:22 -0700807 mCurrentUserId = ActivityManager.getCurrentUser();
Chris Wrena6d4fb62014-11-20 14:46:23 -0500808 setHeadsUpUser(mCurrentUserId);
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400809
810 IntentFilter filter = new IntentFilter();
811 filter.addAction(Intent.ACTION_USER_SWITCHED);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000812 filter.addAction(Intent.ACTION_USER_ADDED);
Kenny Guydae30d52015-04-01 19:11:35 +0100813 filter.addAction(Intent.ACTION_USER_PRESENT);
John Spurlock5c454122013-06-17 07:35:46 -0400814 mContext.registerReceiver(mBroadcastReceiver, filter);
Kenny Guy3a7c4a52014-03-03 18:24:03 +0000815
Ricky Wai7fa01712016-03-16 12:13:54 +0000816 IntentFilter internalFilter = new IntentFilter();
817 internalFilter.addAction(WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
818 internalFilter.addAction(BANNER_ACTION_CANCEL);
819 internalFilter.addAction(BANNER_ACTION_SETUP);
820 mContext.registerReceiver(mBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
821
Kenny Guy0b7dd1e2015-03-12 17:14:38 +0000822 IntentFilter allUsersFilter = new IntentFilter();
823 allUsersFilter.addAction(
824 DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
825 mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
826 null, null);
Kenny Guy2a764942014-04-02 13:29:20 +0100827 updateCurrentProfilesCache();
Dan Sandlerdc34df52016-04-07 21:04:46 -0400828
829 IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
830 try {
831 vrManager.registerListener(mVrStateCallbacks);
832 } catch (RemoteException e) {
833 Slog.e(TAG, "Failed to register VR mode state listener: " + e);
834 }
835
Dan Sandler028a60f2016-10-04 15:01:22 -0400836 mNonBlockablePkgs = new ArraySet<String>();
Julia Reynolds98a44862016-09-12 08:53:47 -0400837 Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
838 com.android.internal.R.array.config_nonBlockableNotificationPackages));
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400839 }
840
Chris Wrencd8f4f72014-08-27 18:48:13 -0400841 protected void notifyUserAboutHiddenNotifications() {
842 if (0 != Settings.Secure.getInt(mContext.getContentResolver(),
843 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) {
844 Log.d(TAG, "user hasn't seen notification about hidden notifications");
Ricky Wai7fa01712016-03-16 12:13:54 +0000845 if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
Chris Wrencd8f4f72014-08-27 18:48:13 -0400846 Log.d(TAG, "insecure lockscreen, skipping notification");
847 Settings.Secure.putInt(mContext.getContentResolver(),
848 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
849 return;
850 }
851 Log.d(TAG, "disabling lockecreen notifications and alerting the user");
852 // disable lockscreen notifications until user acts on the banner.
853 Settings.Secure.putInt(mContext.getContentResolver(),
854 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
Adrian Roosaee70462014-09-03 16:27:39 +0200855 Settings.Secure.putInt(mContext.getContentResolver(),
856 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400857
858 final String packageName = mContext.getPackageName();
859 PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0,
860 new Intent(BANNER_ACTION_CANCEL).setPackage(packageName),
861 PendingIntent.FLAG_CANCEL_CURRENT);
862 PendingIntent setupIntent = PendingIntent.getBroadcast(mContext, 0,
863 new Intent(BANNER_ACTION_SETUP).setPackage(packageName),
864 PendingIntent.FLAG_CANCEL_CURRENT);
865
Chris Wrencd8f4f72014-08-27 18:48:13 -0400866 final int colorRes = com.android.internal.R.color.system_notification_accent_color;
867 Notification.Builder note = new Notification.Builder(mContext)
868 .setSmallIcon(R.drawable.ic_android)
869 .setContentTitle(mContext.getString(R.string.hidden_notifications_title))
870 .setContentText(mContext.getString(R.string.hidden_notifications_text))
871 .setPriority(Notification.PRIORITY_HIGH)
872 .setOngoing(true)
Alan Viverette4a357cd2015-03-18 18:37:18 -0700873 .setColor(mContext.getColor(colorRes))
Chris Wrencd8f4f72014-08-27 18:48:13 -0400874 .setContentIntent(setupIntent)
875 .addAction(R.drawable.ic_close,
876 mContext.getString(R.string.hidden_notifications_cancel),
877 cancelIntent)
878 .addAction(R.drawable.ic_settings,
879 mContext.getString(R.string.hidden_notifications_setup),
880 setupIntent);
Adrian Roose25c18d2016-06-17 15:59:49 -0700881 overrideNotificationAppName(mContext, note);
Chris Wrencd8f4f72014-08-27 18:48:13 -0400882
883 NotificationManager noMan =
884 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Chris Wrend8775102015-01-16 16:16:43 -0500885 noMan.notify(R.id.notification_hidden, note.build());
Chris Wrencd8f4f72014-08-27 18:48:13 -0400886 }
887 }
888
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400889 public void userSwitched(int newUserId) {
Chris Wrena6d4fb62014-11-20 14:46:23 -0500890 setHeadsUpUser(newUserId);
891 }
892
Selim Cinek29fa89b2015-04-17 10:39:11 -0700893 protected abstract void setHeadsUpUser(int newUserId);
Chris Wrend04f6ce2014-06-11 17:37:28 -0400894
Christoph Studerc8db24b2014-07-25 17:50:30 +0200895 @Override // NotificationData.Environment
896 public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400897 final int thisUserId = mCurrentUserId;
898 final int notificationUserId = n.getUserId();
899 if (DEBUG && MULTIUSER_DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -0400900 Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400901 n, thisUserId, notificationUserId));
902 }
Dan Sandlere63ba4b2014-12-05 00:26:24 -0500903 return isCurrentProfile(notificationUserId);
Joe Onorato2314aab2010-04-08 16:41:23 -0500904 }
Daniel Sandler6a858c32012-03-12 14:38:58 -0400905
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700906 protected void setNotificationShown(StatusBarNotification n) {
Chris Wren26505582015-07-22 17:03:17 -0400907 setNotificationsShown(new String[]{n.getKey()});
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700908 }
909
910 protected void setNotificationsShown(String[] keys) {
Chris Wren26505582015-07-22 17:03:17 -0400911 try {
912 mNotificationListener.setNotificationsShown(keys);
913 } catch (RuntimeException e) {
914 Log.d(TAG, "failed setNotificationsShown: ", e);
915 }
Amith Yamasanif47e51e2015-04-17 10:02:15 -0700916 }
917
Kenny Guy44fc65f2014-11-28 22:18:14 +0000918 protected boolean isCurrentProfile(int userId) {
919 synchronized (mCurrentProfiles) {
Dan Sandlere63ba4b2014-12-05 00:26:24 -0500920 return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
Kenny Guy44fc65f2014-11-28 22:18:14 +0000921 }
922 }
923
Christoph Studer2e731b52014-08-22 16:01:51 +0200924 @Override
925 public String getCurrentMediaNotificationKey() {
926 return null;
927 }
928
Selim Cinek25fd4e2b2015-02-20 17:46:07 +0100929 @Override
930 public NotificationGroupManager getGroupManager() {
931 return mGroupManager;
932 }
933
Adrian Roos7d7090d2014-05-21 13:10:23 +0200934 /**
935 * Takes the necessary steps to prepare the status bar for starting an activity, then starts it.
936 * @param action A dismiss action that is called if it's safe to start the activity.
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200937 * @param afterKeyguardGone Whether the action should be executed after the Keyguard is gone.
Adrian Roos7d7090d2014-05-21 13:10:23 +0200938 */
Jorim Jaggi746f7fa2014-08-27 17:52:46 +0200939 protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
Adrian Roos7d7090d2014-05-21 13:10:23 +0200940 action.onDismiss();
941 }
942
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700943 @Override
944 protected void onConfigurationChanged(Configuration newConfig) {
Daniel Sandler777dcde2013-09-30 10:21:45 -0400945 final Locale locale = mContext.getResources().getConfiguration().locale;
946 final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
Dan Sandler539aad42014-08-04 00:43:39 -0400947 final float fontScale = newConfig.fontScale;
Selim Cinek01af3342016-02-09 19:25:31 -0800948 final int density = newConfig.densityDpi;
949 if (density != mDensity || mFontScale != fontScale) {
Selim Cinek3e7592d2016-04-11 09:35:54 +0800950 onDensityOrFontScaleChanged();
Selim Cinek01af3342016-02-09 19:25:31 -0800951 mDensity = density;
952 mFontScale = fontScale;
953 }
954 if (! locale.equals(mLocale) || ld != mLayoutDirection) {
Daniel Sandler777dcde2013-09-30 10:21:45 -0400955 if (DEBUG) {
956 Log.v(TAG, String.format(
957 "config changed locale/LD: %s (%d) -> %s (%d)", mLocale, mLayoutDirection,
958 locale, ld));
959 }
960 mLocale = locale;
961 mLayoutDirection = ld;
962 refreshLayout(ld);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700963 }
964 }
965
Selim Cinek3e7592d2016-04-11 09:35:54 +0800966 protected void onDensityOrFontScaleChanged() {
Selim Cinek01af3342016-02-09 19:25:31 -0800967 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
968 for (int i = 0; i < activeNotifications.size(); i++) {
969 Entry entry = activeNotifications.get(i);
970 boolean exposedGuts = entry.row.getGuts() == mNotificationGutsExposed;
971 entry.row.reInflateViews();
972 if (exposedGuts) {
973 mNotificationGutsExposed = entry.row.getGuts();
974 bindGuts(entry.row);
975 }
Selim Cinek01af3342016-02-09 19:25:31 -0800976 inflateViews(entry, mStackScroller);
977 }
978 }
979
Selim Cinek9e624e72016-07-20 13:46:49 -0700980 protected void bindDismissListener(final ExpandableNotificationRow row) {
981 row.setOnDismissListener(new View.OnClickListener() {
Selim Cinek757d8792016-01-28 16:21:08 -0800982 public void onClick(View v) {
983 // Accessibility feedback
984 v.announceForAccessibility(
985 mContext.getString(R.string.accessibility_notification_dismissed));
Selim Cinek9e624e72016-07-20 13:46:49 -0700986 performRemoveNotification(row.getStatusBarNotification(), false /* removeView */);
Selim Cinek757d8792016-01-28 16:21:08 -0800987 }
988 });
Winson Chungc57ccf02011-10-13 15:04:59 -0700989 }
Daniel Sandler6a858c32012-03-12 14:38:58 -0400990
Adrian Roos18d099a2016-05-19 15:28:18 -0700991 protected void performRemoveNotification(StatusBarNotification n, boolean removeView) {
Selim Cinek36b02232016-05-11 23:07:05 -0400992 final String pkg = n.getPackageName();
993 final String tag = n.getTag();
994 final int id = n.getId();
995 final int userId = n.getUserId();
996 try {
997 mBarService.onNotificationClear(pkg, tag, id, userId);
998 if (FORCE_REMOTE_INPUT_HISTORY
999 && mKeysKeptForRemoteInput.contains(n.getKey())) {
1000 mKeysKeptForRemoteInput.remove(n.getKey());
1001 removeView = true;
1002 }
Adrian Roos18d099a2016-05-19 15:28:18 -07001003 if (mRemoteInputEntriesToRemoveOnCollapse.remove(mNotificationData.get(n.getKey()))) {
1004 removeView = true;
1005 }
Selim Cinek36b02232016-05-11 23:07:05 -04001006 if (removeView) {
1007 removeNotification(n.getKey(), null);
1008 }
1009
1010 } catch (RemoteException ex) {
1011 // system process is dead if we're here.
1012 }
1013 }
1014
Daniel Sandler96fd7c12012-03-30 16:37:36 -04001015
Christoph Studer13b895122014-08-26 15:42:12 +02001016 protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
Jorim Jaggi46739852014-04-15 09:58:24 +02001017 NotificationData.Entry entry) {
Dan Sandlerfe266a32014-05-15 22:28:06 -04001018
Selim Cinek684a4422015-04-15 16:18:39 -07001019 if (entry.getContentView().getId()
1020 != com.android.internal.R.id.status_bar_latest_event_content) {
Dan Sandlerfe266a32014-05-15 22:28:06 -04001021 // Using custom RemoteViews
Jorim Jaggia1eeade2014-09-08 22:34:39 +02001022 if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
Dianne Hackborn955d8d62014-10-07 20:17:19 -07001023 && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
Selim Cinek697178b2014-07-02 19:40:30 +02001024 entry.row.setShowingLegacyBackground(true);
Jorim Jaggi36b15232014-06-10 17:24:20 +02001025 entry.legacy = true;
Daniel Sandler96fd7c12012-03-30 16:37:36 -04001026 }
1027 }
Christoph Studer13b895122014-08-26 15:42:12 +02001028
1029 if (entry.icon != null) {
Jorim Jaggidd0107a2015-01-21 22:23:48 +01001030 entry.icon.setTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
Christoph Studer13b895122014-08-26 15:42:12 +02001031 }
Daniel Sandler96fd7c12012-03-30 16:37:36 -04001032 }
1033
Dan Sandler16128f42014-05-21 12:48:22 -04001034 public boolean isMediaNotification(NotificationData.Entry entry) {
Dan Sandler842dd772014-05-15 09:36:47 -04001035 // TODO: confirm that there's a valid media key
Selim Cinek684a4422015-04-15 16:18:39 -07001036 return entry.getExpandedContentView() != null &&
1037 entry.getExpandedContentView()
1038 .findViewById(com.android.internal.R.id.media_actions) != null;
Dan Sandler842dd772014-05-15 09:36:47 -04001039 }
1040
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001041 // The (i) button in the guts that links to the system notification settings for that app
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001042 private void startAppNotificationSettingsActivity(String packageName, final int appUid) {
1043 final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
Dan Sandlere9a4e902014-07-31 01:06:43 -04001044 intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
1045 intent.putExtra(Settings.EXTRA_APP_UID, appUid);
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001046 startNotificationGutsIntent(intent, appUid);
1047 }
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001048
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001049 private void startNotificationGutsIntent(final Intent intent, final int appUid) {
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001050 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
1051 dismissKeyguardThenExecute(new OnDismissAction() {
1052 @Override
1053 public boolean onDismiss() {
1054 AsyncTask.execute(new Runnable() {
1055 public void run() {
1056 try {
1057 if (keyguardShowing) {
1058 ActivityManagerNative.getDefault()
1059 .keyguardWaitingForActivityDrawn();
1060 }
1061 TaskStackBuilder.create(mContext)
1062 .addNextIntentWithParentStack(intent)
Jorim Jaggie6e108e2016-03-28 13:38:45 -07001063 .startActivities(getActivityOptions(),
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001064 new UserHandle(UserHandle.getUserId(appUid)));
1065 overrideActivityPendingAppTransition(keyguardShowing);
1066 } catch (RemoteException e) {
1067 }
1068 }
1069 });
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +01001070 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
Jorim Jaggifb28c0e2014-08-22 16:28:42 +02001071 return true;
1072 }
Jorim Jaggi746f7fa2014-08-27 17:52:46 +02001073 }, false /* afterKeyguardGone */);
Dan Sandler4247a5c2014-07-23 15:58:08 -04001074 }
1075
Mady Mellorb53bc272016-02-11 18:28:23 -08001076 private void bindGuts(final ExpandableNotificationRow row) {
Selim Cinekab29aeb2015-02-20 18:18:32 +01001077 row.inflateGuts();
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001078 final StatusBarNotification sbn = row.getStatusBarNotification();
Selim Cinekeef84282015-10-30 16:28:00 -07001079 PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001080 row.setTag(sbn.getPackageName());
Julia Reynoldsa07af882015-12-17 08:32:48 -05001081 final NotificationGuts guts = row.getGuts();
Mady Mellor97c8df42016-03-22 18:09:39 -07001082 guts.setClosedListener(this);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001083 final String pkg = sbn.getPackageName();
1084 String appname = pkg;
1085 Drawable pkgicon = null;
1086 int appUid = -1;
1087 try {
1088 final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
1089 PackageManager.GET_UNINSTALLED_PACKAGES
1090 | PackageManager.GET_DISABLED_COMPONENTS);
1091 if (info != null) {
1092 appname = String.valueOf(pmUser.getApplicationLabel(info));
1093 pkgicon = pmUser.getApplicationIcon(info);
1094 appUid = info.uid;
1095 }
1096 } catch (NameNotFoundException e) {
1097 // app is gone, just show package name and generic icon
1098 pkgicon = pmUser.getDefaultActivityIcon();
1099 }
Julia Reynoldsead00aa2015-12-07 08:23:48 -05001100
Min Yun175559a2016-06-17 11:59:24 -07001101 ((ImageView) guts.findViewById(R.id.app_icon)).setImageDrawable(pkgicon);
1102 ((TextView) guts.findViewById(R.id.pkgname)).setText(appname);
Julia Reynoldsead00aa2015-12-07 08:23:48 -05001103
Min Yunde383c72016-06-24 11:05:03 -07001104 final TextView settingsButton = (TextView) guts.findViewById(R.id.more_settings);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001105 if (appUid >= 0) {
1106 final int appUidF = appUid;
1107 settingsButton.setOnClickListener(new View.OnClickListener() {
1108 public void onClick(View v) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -05001109 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
Mady Mellor97c8df42016-03-22 18:09:39 -07001110 guts.resetFalsingCheck();
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001111 startAppNotificationSettingsActivity(pkg, appUidF);
1112 }
1113 });
Min Yunde383c72016-06-24 11:05:03 -07001114 settingsButton.setText(R.string.notification_more_settings);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001115 } else {
1116 settingsButton.setVisibility(View.GONE);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001117 }
1118
Julia Reynolds98a44862016-09-12 08:53:47 -04001119 guts.bindImportance(pmUser, sbn, mNonBlockablePkgs,
1120 mNotificationData.getImportance(sbn.getKey()));
Min Yun175559a2016-06-17 11:59:24 -07001121
Min Yunde383c72016-06-24 11:05:03 -07001122 final TextView doneButton = (TextView) guts.findViewById(R.id.done);
1123 doneButton.setText(R.string.notification_done);
1124 doneButton.setOnClickListener(new View.OnClickListener() {
Julia Reynolds56821922016-01-04 15:24:01 -05001125 @Override
1126 public void onClick(View v) {
Mady Mellor8e8a69e2016-03-14 12:30:10 -07001127 // If the user has security enabled, show challenge if the setting is changed.
1128 if (guts.hasImportanceChanged() && isLockscreenPublicMode() &&
1129 (mState == StatusBarState.KEYGUARD
1130 || mState == StatusBarState.SHADE_LOCKED)) {
1131 OnDismissAction dismissAction = new OnDismissAction() {
1132 @Override
1133 public boolean onDismiss() {
1134 saveImportanceCloseControls(sbn, row, guts, v);
1135 return true;
1136 }
1137 };
1138 onLockedNotificationImportanceChange(dismissAction);
1139 } else {
1140 saveImportanceCloseControls(sbn, row, guts, v);
1141 }
Julia Reynolds56821922016-01-04 15:24:01 -05001142 }
1143 });
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001144 }
1145
Mady Mellor8e8a69e2016-03-14 12:30:10 -07001146 private void saveImportanceCloseControls(StatusBarNotification sbn,
1147 ExpandableNotificationRow row, NotificationGuts guts, View done) {
Mady Mellor97c8df42016-03-22 18:09:39 -07001148 guts.resetFalsingCheck();
Mady Mellor8e8a69e2016-03-14 12:30:10 -07001149 guts.saveImportance(sbn);
1150
1151 int[] rowLocation = new int[2];
1152 int[] doneLocation = new int[2];
1153 row.getLocationOnScreen(rowLocation);
1154 done.getLocationOnScreen(doneLocation);
1155
1156 final int centerX = done.getWidth() / 2;
1157 final int centerY = done.getHeight() / 2;
1158 final int x = doneLocation[0] - rowLocation[0] + centerX;
1159 final int y = doneLocation[1] - rowLocation[1] + centerY;
1160 dismissPopups(x, y);
1161 }
1162
Dan Sandler4247a5c2014-07-23 15:58:08 -04001163 protected SwipeHelper.LongPressListener getNotificationLongClicker() {
1164 return new SwipeHelper.LongPressListener() {
Daniel Sandlerf7a19562012-04-04 14:04:21 -04001165 @Override
Selim Cinekd84a5932015-12-15 11:45:36 -08001166 public boolean onLongPress(View v, final int x, final int y) {
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001167 if (!(v instanceof ExpandableNotificationRow)) {
1168 return false;
1169 }
Selim Cinekabdc5a02014-09-02 13:46:00 +02001170 if (v.getWindowToken() == null) {
1171 Log.e(TAG, "Trying to show notification guts, but not attached to window");
1172 return false;
1173 }
Dan Sandler4247a5c2014-07-23 15:58:08 -04001174
Mady Mellor4b80b102016-01-22 08:03:58 -08001175 final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
Selim Cinekab29aeb2015-02-20 18:18:32 +01001176 bindGuts(row);
Jorim Jaggib1cd3c12014-09-08 19:55:17 +02001177
Dan Sandler4247a5c2014-07-23 15:58:08 -04001178 // Assume we are a status_bar_notification_row
Selim Cinekab29aeb2015-02-20 18:18:32 +01001179 final NotificationGuts guts = row.getGuts();
Selim Cinekbdefcdf2014-09-11 12:41:47 +02001180 if (guts == null) {
1181 // This view has no guts. Examples are the more card or the dismiss all view
1182 return false;
1183 }
Dan Sandler4247a5c2014-07-23 15:58:08 -04001184
1185 // Already showing?
Selim Cinekabdc5a02014-09-02 13:46:00 +02001186 if (guts.getVisibility() == View.VISIBLE) {
Selim Cinekd84a5932015-12-15 11:45:36 -08001187 dismissPopups(x, y);
Selim Cinekabdc5a02014-09-02 13:46:00 +02001188 return false;
1189 }
Dan Sandler4247a5c2014-07-23 15:58:08 -04001190
Chris Wrenf6e9228b2016-01-26 18:04:35 -05001191 MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
Julia Reynoldsead00aa2015-12-07 08:23:48 -05001192
Julia Reynolds40779452016-02-23 13:43:32 -05001193 // ensure that it's laid but not visible until actually laid out
Selim Cinekd84a5932015-12-15 11:45:36 -08001194 guts.setVisibility(View.INVISIBLE);
Julia Reynolds40779452016-02-23 13:43:32 -05001195 // Post to ensure the the guts are properly laid out.
Selim Cinekd84a5932015-12-15 11:45:36 -08001196 guts.post(new Runnable() {
1197 public void run() {
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001198 dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
1199 false /* animate */);
Selim Cinekd84a5932015-12-15 11:45:36 -08001200 guts.setVisibility(View.VISIBLE);
1201 final double horz = Math.max(guts.getWidth() - x, x);
1202 final double vert = Math.max(guts.getHeight() - y, y);
1203 final float r = (float) Math.hypot(horz, vert);
1204 final Animator a
1205 = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r);
1206 a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
Selim Cinekc18010f2016-01-20 13:41:30 -08001207 a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
Mady Mellor4b80b102016-01-22 08:03:58 -08001208 a.addListener(new AnimatorListenerAdapter() {
1209 @Override
1210 public void onAnimationEnd(Animator animation) {
1211 super.onAnimationEnd(animation);
1212 // Move the notification view back over the gear
1213 row.resetTranslation();
1214 }
1215 });
Selim Cinekd84a5932015-12-15 11:45:36 -08001216 a.start();
Mady Mellor97c8df42016-03-22 18:09:39 -07001217 guts.setExposed(true /* exposed */,
1218 mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
Adrian Roos0bd8a4b2016-03-14 16:21:44 -07001219 row.closeRemoteInput();
Selim Cinekd84a5932015-12-15 11:45:36 -08001220 mStackScroller.onHeightChanged(null, true /* needsAnimation */);
1221 mNotificationGutsExposed = guts;
1222 }
1223 });
Daniel Sandlerf7a19562012-04-04 14:04:21 -04001224 return true;
1225 }
1226 };
1227 }
1228
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001229 /**
1230 * Returns the exposed NotificationGuts or null if none are exposed.
1231 */
1232 public NotificationGuts getExposedGuts() {
1233 return mNotificationGutsExposed;
Mady Mellor4b80b102016-01-22 08:03:58 -08001234 }
1235
Daniel Sandler469e96e2012-05-04 15:56:19 -04001236 public void dismissPopups() {
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001237 dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
Selim Cinekd84a5932015-12-15 11:45:36 -08001238 }
1239
1240 private void dismissPopups(int x, int y) {
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001241 dismissPopups(x, y, true /* resetGear */, false /* animate */);
Mady Mellorb53bc272016-02-11 18:28:23 -08001242 }
1243
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001244 public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
Dan Sandler4247a5c2014-07-23 15:58:08 -04001245 if (mNotificationGutsExposed != null) {
Mady Mellor97c8df42016-03-22 18:09:39 -07001246 mNotificationGutsExposed.closeControls(x, y, true /* notify */);
Daniel Sandler469e96e2012-05-04 15:56:19 -04001247 }
Mady Mellor7a9b2a62016-03-23 07:41:47 -07001248 if (resetGear) {
1249 mStackScroller.resetExposedGearView(animate, true /* force */);
Mady Mellor4b80b102016-01-22 08:03:58 -08001250 }
Daniel Sandler469e96e2012-05-04 15:56:19 -04001251 }
1252
Michael Jurka7f2668c2012-03-27 07:49:52 -07001253 @Override
Mady Mellor97c8df42016-03-22 18:09:39 -07001254 public void onGutsClosed(NotificationGuts guts) {
1255 mStackScroller.onHeightChanged(null, true /* needsAnimation */);
1256 mNotificationGutsExposed = null;
1257 }
1258
1259 @Override
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001260 public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001261 int msg = MSG_SHOW_RECENT_APPS;
1262 mHandler.removeMessages(msg);
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001263 mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0).sendToTarget();
Winson Chung1e8d71b2014-05-16 17:05:22 -07001264 }
1265
1266 @Override
Winson Chungcdcd4872014-08-05 18:00:13 -07001267 public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001268 int msg = MSG_HIDE_RECENT_APPS;
1269 mHandler.removeMessages(msg);
Winson Chungcdcd4872014-08-05 18:00:13 -07001270 mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0,
1271 triggeredFromHomeKey ? 1 : 0).sendToTarget();
Winson Chung1e8d71b2014-05-16 17:05:22 -07001272 }
1273
1274 @Override
Michael Jurka7f2668c2012-03-27 07:49:52 -07001275 public void toggleRecentApps() {
Jorim Jaggi900fb482015-06-02 15:07:33 -07001276 toggleRecents();
Michael Jurka7f2668c2012-03-27 07:49:52 -07001277 }
1278
1279 @Override
Phil Weaver315c34e2016-02-19 15:12:29 -08001280 public void toggleSplitScreen() {
Jorim Jaggi29379ec2016-04-11 23:43:42 -07001281 toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
Phil Weaver315c34e2016-02-19 15:12:29 -08001282 }
1283
1284 @Override
Michael Jurka7f2668c2012-03-27 07:49:52 -07001285 public void preloadRecentApps() {
1286 int msg = MSG_PRELOAD_RECENT_APPS;
1287 mHandler.removeMessages(msg);
1288 mHandler.sendEmptyMessage(msg);
1289 }
1290
1291 @Override
1292 public void cancelPreloadRecentApps() {
1293 int msg = MSG_CANCEL_PRELOAD_RECENT_APPS;
1294 mHandler.removeMessages(msg);
1295 mHandler.sendEmptyMessage(msg);
1296 }
1297
Clara Bayarrif2debb12015-07-10 14:47:17 +01001298 @Override
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +01001299 public void dismissKeyboardShortcutsMenu() {
1300 int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU;
1301 mHandler.removeMessages(msg);
1302 mHandler.sendEmptyMessage(msg);
1303 }
1304
1305 @Override
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001306 public void toggleKeyboardShortcutsMenu(int deviceId) {
Andrei Stingaceanuc22ab792016-01-07 12:39:38 +00001307 int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
Clara Bayarrif2debb12015-07-10 14:47:17 +01001308 mHandler.removeMessages(msg);
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001309 mHandler.obtainMessage(msg, deviceId, 0).sendToTarget();
Clara Bayarrif2debb12015-07-10 14:47:17 +01001310 }
1311
Winson Chungb1f74992014-08-08 12:53:09 -07001312 /** Jumps to the next affiliated task in the group. */
1313 public void showNextAffiliatedTask() {
1314 int msg = MSG_SHOW_NEXT_AFFILIATED_TASK;
1315 mHandler.removeMessages(msg);
1316 mHandler.sendEmptyMessage(msg);
1317 }
1318
1319 /** Jumps to the previous affiliated task in the group. */
1320 public void showPreviousAffiliatedTask() {
1321 int msg = MSG_SHOW_PREV_AFFILIATED_TASK;
1322 mHandler.removeMessages(msg);
1323 mHandler.sendEmptyMessage(msg);
1324 }
1325
Michael Jurkaecc395a2012-03-30 05:31:46 -07001326 protected H createHandler() {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001327 return new H();
1328 }
1329
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +01001330 protected void sendCloseSystemWindows(String reason) {
Michael Jurka56a57832012-05-14 13:24:43 -07001331 if (ActivityManagerNative.isSystemReady()) {
1332 try {
1333 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
1334 } catch (RemoteException e) {
1335 }
1336 }
1337 }
1338
Michael Jurkacb2522c2012-04-13 09:32:47 -07001339 protected abstract View getStatusBarView();
1340
Michael Jurka80343f62012-10-18 13:13:46 +02001341 protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
1342 // additional optimization when we have software system buttons - start loading the recent
1343 // tasks on touch down
1344 @Override
1345 public boolean onTouch(View v, MotionEvent event) {
1346 int action = event.getAction() & MotionEvent.ACTION_MASK;
1347 if (action == MotionEvent.ACTION_DOWN) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001348 preloadRecents();
Michael Jurka80343f62012-10-18 13:13:46 +02001349 } else if (action == MotionEvent.ACTION_CANCEL) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001350 cancelPreloadingRecents();
Michael Jurka80343f62012-10-18 13:13:46 +02001351 } else if (action == MotionEvent.ACTION_UP) {
1352 if (!v.isPressed()) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001353 cancelPreloadingRecents();
Michael Jurka80343f62012-10-18 13:13:46 +02001354 }
1355
1356 }
1357 return false;
1358 }
1359 };
1360
Phil Weaver315c34e2016-02-19 15:12:29 -08001361 /**
1362 * Toggle docking the app window
1363 *
Jorim Jaggi29379ec2016-04-11 23:43:42 -07001364 * @param metricsDockAction the action to log when docking is successful, or -1 to not log
1365 * anything on successful docking
1366 * @param metricsUndockAction the action to log when undocking, or -1 to not log anything when
1367 * undocking
Phil Weaver315c34e2016-02-19 15:12:29 -08001368 */
Jorim Jaggi29379ec2016-04-11 23:43:42 -07001369 protected abstract void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction);
Phil Weaver315c34e2016-02-19 15:12:29 -08001370
Winson Chung1e8d71b2014-05-16 17:05:22 -07001371 /** Proxy for RecentsComponent */
1372
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001373 protected void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001374 if (mRecents != null) {
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +01001375 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
Jorim Jaggidb21bbd2016-04-18 15:32:07 -07001376 mRecents.showRecents(triggeredFromAltTab, fromHome);
Winson Chung1e8d71b2014-05-16 17:05:22 -07001377 }
1378 }
1379
Winson Chungcdcd4872014-08-05 18:00:13 -07001380 protected void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001381 if (mRecents != null) {
Winson Chungcdcd4872014-08-05 18:00:13 -07001382 mRecents.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
Winson Chung1e8d71b2014-05-16 17:05:22 -07001383 }
1384 }
1385
1386 protected void toggleRecents() {
John Spurlockd08de372013-06-24 13:06:08 -04001387 if (mRecents != null) {
Jorim Jaggidb21bbd2016-04-18 15:32:07 -07001388 mRecents.toggleRecents(mDisplay);
John Spurlockd08de372013-06-24 13:06:08 -04001389 }
1390 }
Michael Jurka80343f62012-10-18 13:13:46 +02001391
Winson Chung1e8d71b2014-05-16 17:05:22 -07001392 protected void preloadRecents() {
John Spurlockd08de372013-06-24 13:06:08 -04001393 if (mRecents != null) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001394 mRecents.preloadRecents();
John Spurlockd08de372013-06-24 13:06:08 -04001395 }
Michael Jurka80343f62012-10-18 13:13:46 +02001396 }
1397
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001398 protected void toggleKeyboardShortcuts(int deviceId) {
Andrei Stingaceanuf86bc972016-04-12 15:29:25 +01001399 KeyboardShortcuts.toggle(mContext, deviceId);
Clara Bayarrif2debb12015-07-10 14:47:17 +01001400 }
1401
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +01001402 protected void dismissKeyboardShortcuts() {
1403 KeyboardShortcuts.dismiss();
1404 }
1405
Winson Chung1e8d71b2014-05-16 17:05:22 -07001406 protected void cancelPreloadingRecents() {
John Spurlockd08de372013-06-24 13:06:08 -04001407 if (mRecents != null) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001408 mRecents.cancelPreloadingRecents();
John Spurlockd08de372013-06-24 13:06:08 -04001409 }
Michael Jurka80343f62012-10-18 13:13:46 +02001410 }
1411
Winson Chungb1f74992014-08-08 12:53:09 -07001412 protected void showRecentsNextAffiliatedTask() {
1413 if (mRecents != null) {
1414 mRecents.showNextAffiliatedTask();
1415 }
1416 }
1417
1418 protected void showRecentsPreviousAffiliatedTask() {
1419 if (mRecents != null) {
1420 mRecents.showPrevAffiliatedTask();
1421 }
1422 }
1423
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001424 /**
Selim Cinek684a4422015-04-15 16:18:39 -07001425 * If there is an active heads-up notification and it has a fullscreen intent, fire it now.
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001426 */
Selim Cinek684a4422015-04-15 16:18:39 -07001427 public abstract void maybeEscalateHeadsUp();
Chris Wrena4ef6202014-06-09 18:07:30 -04001428
Dan Sandlerfd16d562014-02-13 18:43:31 -08001429 /**
1430 * Save the current "public" (locked and secure) state of the lockscreen.
1431 */
1432 public void setLockscreenPublicMode(boolean publicMode) {
1433 mLockscreenPublicMode = publicMode;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001434 }
1435
Dan Sandlerfd16d562014-02-13 18:43:31 -08001436 public boolean isLockscreenPublicMode() {
1437 return mLockscreenPublicMode;
1438 }
1439
Ricky Waicd35def2016-05-03 11:07:07 +01001440 protected void onWorkChallengeUnlocked() {}
1441
Dan Sandlerfd16d562014-02-13 18:43:31 -08001442 /**
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001443 * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
1444 * "public" (secure & locked) mode?
1445 */
1446 public boolean userAllowsNotificationsInPublic(int userHandle) {
1447 if (userHandle == UserHandle.USER_ALL) {
1448 return true;
1449 }
1450
1451 if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
1452 final boolean allowed = 0 != Settings.Secure.getIntForUser(
1453 mContext.getContentResolver(),
1454 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
1455 mUsersAllowingNotifications.append(userHandle, allowed);
1456 return allowed;
1457 }
1458
1459 return mUsersAllowingNotifications.get(userHandle);
1460 }
1461
1462 /**
Dan Sandlerfd16d562014-02-13 18:43:31 -08001463 * Has the given user chosen to allow their private (full) notifications to be shown even
1464 * when the lockscreen is in "public" (secure & locked) mode?
1465 */
1466 public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
1467 if (userHandle == UserHandle.USER_ALL) {
1468 return true;
1469 }
1470
1471 if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
Kenny Guyb0d3ab22015-02-10 16:13:11 +00001472 final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
Dan Sandlerfd16d562014-02-13 18:43:31 -08001473 mContext.getContentResolver(),
1474 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00001475 final boolean allowedByDpm = adminAllowsUnredactedNotifications(userHandle);
Kenny Guyb0d3ab22015-02-10 16:13:11 +00001476 final boolean allowed = allowedByUser && allowedByDpm;
1477 mUsersAllowingPrivateNotifications.append(userHandle, allowed);
Dan Sandlerfd16d562014-02-13 18:43:31 -08001478 return allowed;
1479 }
1480
1481 return mUsersAllowingPrivateNotifications.get(userHandle);
Dan Sandlera5e0f412014-01-23 15:11:54 -05001482 }
1483
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00001484 private boolean adminAllowsUnredactedNotifications(int userHandle) {
1485 if (userHandle == UserHandle.USER_ALL) {
1486 return true;
1487 }
1488 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */,
1489 userHandle);
1490 return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
1491 }
1492
Christoph Studerc8db24b2014-07-25 17:50:30 +02001493 /**
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001494 * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
1495 * If so, notifications should be hidden.
Christoph Studerc8db24b2014-07-25 17:50:30 +02001496 */
1497 @Override // NotificationData.Environment
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001498 public boolean shouldHideNotifications(int userid) {
1499 return isLockscreenPublicMode() && !userAllowsNotificationsInPublic(userid);
1500 }
1501
1502 /**
1503 * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
1504 * package-specific override.
1505 */
1506 @Override // NotificationDate.Environment
1507 public boolean shouldHideNotifications(String key) {
1508 return isLockscreenPublicMode()
1509 && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
1510 }
1511
1512 /**
1513 * Returns true if we're on a secure lockscreen.
1514 */
1515 @Override // NotificationData.Environment
1516 public boolean onSecureLockScreen() {
1517 return isLockscreenPublicMode();
Christoph Studerc8db24b2014-07-25 17:50:30 +02001518 }
1519
Chris Wrena4ef6202014-06-09 18:07:30 -04001520 public void onNotificationClear(StatusBarNotification notification) {
1521 try {
1522 mBarService.onNotificationClear(
1523 notification.getPackageName(),
1524 notification.getTag(),
1525 notification.getId(),
1526 notification.getUserId());
1527 } catch (android.os.RemoteException ex) {
1528 // oh well
1529 }
1530 }
1531
Selim Cinek5f71bee2015-11-18 10:25:23 -08001532 /**
Selim Cinek5fbc6322016-01-15 17:17:58 -08001533 * Called when the notification panel layouts
Selim Cinek5f71bee2015-11-18 10:25:23 -08001534 */
Selim Cinek5fbc6322016-01-15 17:17:58 -08001535 public void onPanelLaidOut() {
Selim Cinek5f71bee2015-11-18 10:25:23 -08001536 if (mState == StatusBarState.KEYGUARD) {
1537 // Since the number of notifications is determined based on the height of the view, we
1538 // need to update them.
Selim Cinek5fbc6322016-01-15 17:17:58 -08001539 int maxBefore = getMaxKeyguardNotifications(false /* recompute */);
1540 int maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
1541 if (maxBefore != maxNotifications) {
1542 updateRowStates();
1543 }
Selim Cinek5f71bee2015-11-18 10:25:23 -08001544 }
1545 }
1546
Mady Mellor8e8a69e2016-03-14 12:30:10 -07001547 protected void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {}
1548
Adrian Roos3aec6382016-02-05 14:19:01 -08001549 protected void onLockedRemoteInput(ExpandableNotificationRow row, View clickedView) {}
1550
Ricky Waicd35def2016-05-03 11:07:07 +01001551 protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
1552 View clicked) {}
1553
Selim Cinek570981d2015-12-01 11:37:01 -08001554 @Override
Selim Cinek31aada42015-12-18 17:51:15 -08001555 public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
Selim Cinek570981d2015-12-01 11:37:01 -08001556 }
1557
Michael Jurka7f2668c2012-03-27 07:49:52 -07001558 protected class H extends Handler {
1559 public void handleMessage(Message m) {
1560 switch (m.what) {
Winson Chung1e8d71b2014-05-16 17:05:22 -07001561 case MSG_SHOW_RECENT_APPS:
Jorim Jaggi681fc7b2016-04-14 22:02:39 -07001562 showRecents(m.arg1 > 0, m.arg2 != 0);
Michael Jurkacb2522c2012-04-13 09:32:47 -07001563 break;
Winson Chung1e8d71b2014-05-16 17:05:22 -07001564 case MSG_HIDE_RECENT_APPS:
Winson Chungcdcd4872014-08-05 18:00:13 -07001565 hideRecents(m.arg1 > 0, m.arg2 > 0);
Winson Chung1e8d71b2014-05-16 17:05:22 -07001566 break;
1567 case MSG_TOGGLE_RECENTS_APPS:
1568 toggleRecents();
Michael Jurkacb2522c2012-04-13 09:32:47 -07001569 break;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001570 case MSG_PRELOAD_RECENT_APPS:
Winson Chung1e8d71b2014-05-16 17:05:22 -07001571 preloadRecents();
Michael Jurka7f2668c2012-03-27 07:49:52 -07001572 break;
1573 case MSG_CANCEL_PRELOAD_RECENT_APPS:
Winson Chung1e8d71b2014-05-16 17:05:22 -07001574 cancelPreloadingRecents();
Michael Jurka7f2668c2012-03-27 07:49:52 -07001575 break;
Winson Chungb1f74992014-08-08 12:53:09 -07001576 case MSG_SHOW_NEXT_AFFILIATED_TASK:
1577 showRecentsNextAffiliatedTask();
1578 break;
1579 case MSG_SHOW_PREV_AFFILIATED_TASK:
1580 showRecentsPreviousAffiliatedTask();
1581 break;
Andrei Stingaceanuc22ab792016-01-07 12:39:38 +00001582 case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
Clara Bayarri4e850ff2016-03-02 11:12:32 -08001583 toggleKeyboardShortcuts(m.arg1);
Clara Bayarrif2debb12015-07-10 14:47:17 +01001584 break;
Andrei Stingaceanu0bf096f2016-04-14 18:11:57 +01001585 case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU:
1586 dismissKeyboardShortcuts();
1587 break;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001588 }
1589 }
1590 }
1591
Daniel Sandler6a858c32012-03-12 14:38:58 -04001592 protected void workAroundBadLayerDrawableOpacity(View v) {
1593 }
1594
Selim Cinek8d490d42015-04-10 00:05:50 -07001595 protected boolean inflateViews(Entry entry, ViewGroup parent) {
Selim Cinekeef84282015-10-30 16:28:00 -07001596 PackageManager pmUser = getPackageManagerForUser(mContext,
Dan Sandlere9a4e902014-07-31 01:06:43 -04001597 entry.notification.getUser().getIdentifier());
1598
Dan Sandlerf4db75c2014-09-03 18:02:31 +02001599 final StatusBarNotification sbn = entry.notification;
Adrian Roos95f8bea2016-07-27 15:49:03 -07001600 try {
1601 entry.cacheContentViews(mContext, null);
1602 } catch (RuntimeException e) {
1603 Log.e(TAG, "Unable to get notification remote views", e);
1604 return false;
1605 }
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001606
1607 final RemoteViews contentView = entry.cachedContentView;
1608 final RemoteViews bigContentView = entry.cachedBigContentView;
1609 final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
1610 final RemoteViews publicContentView = entry.cachedPublicContentView;
Chris Wren8fd39ec2014-02-27 17:43:26 -05001611
Chris Wren574a55e2013-07-15 18:48:37 -04001612 if (contentView == null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001613 Log.v(TAG, "no contentView for: " + sbn.getNotification());
Daniel Sandler6a858c32012-03-12 14:38:58 -04001614 return false;
1615 }
1616
Dan Sandlerf68448e2014-04-24 15:54:16 -04001617 if (DEBUG) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001618 Log.v(TAG, "publicContentView: " + publicContentView);
Dan Sandlerf68448e2014-04-24 15:54:16 -04001619 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05001620
Christoph Studera7fe6312014-06-27 19:32:44 +02001621 ExpandableNotificationRow row;
1622
1623 // Stash away previous user expansion state so we can restore it at
1624 // the end.
1625 boolean hasUserChangedExpansion = false;
1626 boolean userExpanded = false;
1627 boolean userLocked = false;
1628
1629 if (entry.row != null) {
1630 row = entry.row;
1631 hasUserChangedExpansion = row.hasUserChangedExpansion();
1632 userExpanded = row.isUserExpanded();
1633 userLocked = row.isUserLocked();
Christoph Studer22f2ee52014-07-29 22:57:21 +02001634 entry.reset();
Christoph Studera7fe6312014-06-27 19:32:44 +02001635 if (hasUserChangedExpansion) {
1636 row.setUserExpanded(userExpanded);
1637 }
1638 } else {
1639 // create the row view
1640 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
1641 Context.LAYOUT_INFLATER_SERVICE);
1642 row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
1643 parent, false);
Chris Wren78403d72014-07-28 10:23:24 +01001644 row.setExpansionLogger(this, entry.notification.getKey());
Selim Cinekb5605e52015-02-20 18:21:41 +01001645 row.setGroupManager(mGroupManager);
Selim Cinek31aada42015-12-18 17:51:15 -08001646 row.setHeadsUpManager(mHeadsUpManager);
Adrian Roosb88b1a12015-12-09 18:51:05 -08001647 row.setRemoteInputController(mRemoteInputController);
Selim Cinek570981d2015-12-01 11:37:01 -08001648 row.setOnExpandClickListener(this);
Mady Mellor3fd273e2016-03-15 21:08:14 -07001649
Dan Sandler732bd6c2016-04-12 14:20:32 -04001650 // Get the app name.
1651 // Note that Notification.Builder#bindHeaderAppName has similar logic
1652 // but since this field is used in the guts, it must be accurate.
1653 // Therefore we will only show the application label, or, failing that, the
1654 // package name. No substitutions.
Mady Mellor3fd273e2016-03-15 21:08:14 -07001655 final String pkg = sbn.getPackageName();
1656 String appname = pkg;
1657 try {
1658 final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
1659 PackageManager.GET_UNINSTALLED_PACKAGES
1660 | PackageManager.GET_DISABLED_COMPONENTS);
1661 if (info != null) {
1662 appname = String.valueOf(pmUser.getApplicationLabel(info));
1663 }
1664 } catch (NameNotFoundException e) {
1665 // Do nothing
1666 }
1667 row.setAppName(appname);
Christoph Studera7fe6312014-06-27 19:32:44 +02001668 }
Daniel Sandlerbc5559f2012-04-19 01:08:15 -04001669
Daniel Sandler6a858c32012-03-12 14:38:58 -04001670 workAroundBadLayerDrawableOpacity(row);
Selim Cinek9e624e72016-07-20 13:46:49 -07001671 bindDismissListener(row);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001672
1673 // NB: the large icon is now handled entirely by the template
1674
1675 // bind the click event to the content area
Selim Cinek8d490d42015-04-10 00:05:50 -07001676 NotificationContentView contentContainer = row.getPrivateLayout();
1677 NotificationContentView contentContainerPublic = row.getPublicLayout();
Daniel Sandlerbc5559f2012-04-19 01:08:15 -04001678
Jorim Jaggife40f7d2014-04-28 15:20:04 +02001679 row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
Adrian Roos497ab022015-02-10 20:49:33 +01001680 if (ENABLE_REMOTE_INPUT) {
1681 row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
1682 }
Daniel Sandlerbc5559f2012-04-19 01:08:15 -04001683
Chris Wren42d5dd42015-05-01 10:39:26 -04001684 mNotificationClicker.register(row, sbn);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001685
Dan Sandlera5e0f412014-01-23 15:11:54 -05001686 // set up the adaptive layout
Chris Wren574a55e2013-07-15 18:48:37 -04001687 View contentViewLocal = null;
1688 View bigContentViewLocal = null;
Selim Cinek8d490d42015-04-10 00:05:50 -07001689 View headsUpContentViewLocal = null;
Selim Cinek624c02db2015-12-14 21:00:02 -08001690 View publicViewLocal = null;
Daniel Sandler6a858c32012-03-12 14:38:58 -04001691 try {
Dan Sandler68079d52015-07-22 10:45:30 -04001692 contentViewLocal = contentView.apply(
1693 sbn.getPackageContext(mContext),
1694 contentContainer,
Jorim Jaggi39fa59f2014-02-25 15:38:45 +01001695 mOnClickHandler);
Chris Wren574a55e2013-07-15 18:48:37 -04001696 if (bigContentView != null) {
Dan Sandler68079d52015-07-22 10:45:30 -04001697 bigContentViewLocal = bigContentView.apply(
1698 sbn.getPackageContext(mContext),
1699 contentContainer,
Selim Cinek8d490d42015-04-10 00:05:50 -07001700 mOnClickHandler);
1701 }
1702 if (headsUpContentView != null) {
Dan Sandler68079d52015-07-22 10:45:30 -04001703 headsUpContentViewLocal = headsUpContentView.apply(
1704 sbn.getPackageContext(mContext),
1705 contentContainer,
Jorim Jaggi39fa59f2014-02-25 15:38:45 +01001706 mOnClickHandler);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001707 }
Selim Cinek624c02db2015-12-14 21:00:02 -08001708 if (publicContentView != null) {
1709 publicViewLocal = publicContentView.apply(
1710 sbn.getPackageContext(mContext),
1711 contentContainerPublic, mOnClickHandler);
1712 }
dooyoung.hwang78c41142016-10-04 18:55:31 +09001713
1714 if (contentViewLocal != null) {
1715 contentViewLocal.setIsRootNamespace(true);
1716 contentContainer.setContractedChild(contentViewLocal);
1717 }
1718 if (bigContentViewLocal != null) {
1719 bigContentViewLocal.setIsRootNamespace(true);
1720 contentContainer.setExpandedChild(bigContentViewLocal);
1721 }
1722 if (headsUpContentViewLocal != null) {
1723 headsUpContentViewLocal.setIsRootNamespace(true);
1724 contentContainer.setHeadsUpChild(headsUpContentViewLocal);
1725 }
1726 if (publicViewLocal != null) {
1727 publicViewLocal.setIsRootNamespace(true);
1728 contentContainerPublic.setContractedChild(publicViewLocal);
1729 }
Daniel Sandler6a858c32012-03-12 14:38:58 -04001730 }
1731 catch (RuntimeException e) {
Daniel Sandler4f91efd2013-04-25 16:38:41 -04001732 final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
John Spurlockcd686b52013-06-05 10:13:46 -04001733 Log.e(TAG, "couldn't inflate view for notification " + ident, e);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001734 return false;
Daniel Sandler6a858c32012-03-12 14:38:58 -04001735 }
1736
Jorim Jaggia1eeade2014-09-08 22:34:39 +02001737 // Extract target SDK version.
1738 try {
1739 ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
1740 entry.targetSdk = info.targetSdkVersion;
1741 } catch (NameNotFoundException ex) {
1742 Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
1743 }
Selim Cinek624c02db2015-12-14 21:00:02 -08001744 entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
Dan Sandlera5e0f412014-01-23 15:11:54 -05001745
Daniel Sandlerb9301c32012-08-14 15:08:24 -04001746 if (MULTIUSER_DEBUG) {
1747 TextView debug = (TextView) row.findViewById(R.id.debug_info);
1748 if (debug != null) {
1749 debug.setVisibility(View.VISIBLE);
Kenny Guy3a7c4a52014-03-03 18:24:03 +00001750 debug.setText("CU " + mCurrentUserId +" NU " + entry.notification.getUserId());
Daniel Sandlerb9301c32012-08-14 15:08:24 -04001751 }
1752 }
Daniel Sandler6a858c32012-03-12 14:38:58 -04001753 entry.row = row;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +02001754 entry.row.setOnActivatedListener(this);
Selim Cinek684a4422015-04-15 16:18:39 -07001755 entry.row.setExpandable(bigContentViewLocal != null);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001756
Christoph Studer13b895122014-08-26 15:42:12 +02001757 applyColorsAndBackgrounds(sbn, entry);
Jorim Jaggi46739852014-04-15 09:58:24 +02001758
Christoph Studera7fe6312014-06-27 19:32:44 +02001759 // Restore previous flags.
1760 if (hasUserChangedExpansion) {
1761 // Note: setUserExpanded() conveniently ignores calls with
1762 // userExpanded=true if !isExpandable().
1763 row.setUserExpanded(userExpanded);
1764 }
1765 row.setUserLocked(userLocked);
Selim Cinekda42d652015-12-04 15:51:16 -08001766 row.onNotificationUpdated(entry);
Daniel Sandler6a858c32012-03-12 14:38:58 -04001767 return true;
1768 }
1769
Adrian Roos497ab022015-02-10 20:49:33 +01001770 /**
1771 * Adds RemoteInput actions from the WearableExtender; to be removed once more apps support this
1772 * via first-class API.
1773 *
1774 * TODO: Remove once enough apps specify remote inputs on their own.
1775 */
1776 private void processForRemoteInput(Notification n) {
1777 if (!ENABLE_REMOTE_INPUT) return;
1778
1779 if (n.extras != null && n.extras.containsKey("android.wearable.EXTENSIONS") &&
1780 (n.actions == null || n.actions.length == 0)) {
1781 Notification.Action viableAction = null;
1782 Notification.WearableExtender we = new Notification.WearableExtender(n);
1783
1784 List<Notification.Action> actions = we.getActions();
1785 final int numActions = actions.size();
1786
1787 for (int i = 0; i < numActions; i++) {
1788 Notification.Action action = actions.get(i);
Adrian Roosa3539cb2015-12-16 16:47:02 -08001789 if (action == null) {
1790 continue;
1791 }
Adrian Roos497ab022015-02-10 20:49:33 +01001792 RemoteInput[] remoteInputs = action.getRemoteInputs();
Adrian Roosa3539cb2015-12-16 16:47:02 -08001793 if (remoteInputs == null) {
1794 continue;
1795 }
1796 for (RemoteInput ri : remoteInputs) {
Adrian Roos497ab022015-02-10 20:49:33 +01001797 if (ri.getAllowFreeFormInput()) {
1798 viableAction = action;
1799 break;
1800 }
1801 }
1802 if (viableAction != null) {
1803 break;
1804 }
1805 }
1806
1807 if (viableAction != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04001808 Notification.Builder rebuilder = Notification.Builder.recoverBuilder(mContext, n);
1809 rebuilder.setActions(viableAction);
1810 rebuilder.build(); // will rewrite n
Adrian Roos497ab022015-02-10 20:49:33 +01001811 }
1812 }
1813 }
1814
Adrian Roos62692b22015-09-11 17:46:23 -07001815 public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
1816 if (!isDeviceProvisioned()) return;
1817
1818 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
1819 final boolean afterKeyguardGone = intent.isActivity()
1820 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
1821 mCurrentUserId);
1822 dismissKeyguardThenExecute(new OnDismissAction() {
1823 public boolean onDismiss() {
1824 new Thread() {
1825 @Override
1826 public void run() {
1827 try {
1828 if (keyguardShowing && !afterKeyguardGone) {
1829 ActivityManagerNative.getDefault()
1830 .keyguardWaitingForActivityDrawn();
1831 }
1832
1833 // The intent we are sending is for the application, which
1834 // won't have permission to immediately start an activity after
1835 // the user switches to home. We know it is safe to do at this
1836 // point, so make sure new activity switches are now allowed.
1837 ActivityManagerNative.getDefault().resumeAppSwitches();
1838 } catch (RemoteException e) {
1839 }
Adrian Roos62692b22015-09-11 17:46:23 -07001840 try {
Jorim Jaggie6e108e2016-03-28 13:38:45 -07001841 intent.send(null, 0, null, null, null, null, getActivityOptions());
Adrian Roos62692b22015-09-11 17:46:23 -07001842 } catch (PendingIntent.CanceledException e) {
1843 // the stack trace isn't very helpful here.
1844 // Just log the exception message.
1845 Log.w(TAG, "Sending intent failed: " + e);
1846
1847 // TODO: Dismiss Keyguard.
1848 }
1849 if (intent.isActivity()) {
1850 mAssistManager.hideAssist();
1851 overrideActivityPendingAppTransition(keyguardShowing
1852 && !afterKeyguardGone);
1853 }
1854 }
1855 }.start();
1856
1857 // close the shade if it was open
1858 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
1859 true /* force */, true /* delayed */);
1860 visibilityChanged(false);
1861
1862 return true;
1863 }
1864 }, afterKeyguardGone);
1865 }
1866
Selim Cinek36b02232016-05-11 23:07:05 -04001867 public void addPostCollapseAction(Runnable r) {
1868 }
1869
1870 public boolean isCollapsing() {
1871 return false;
1872 }
1873
Chris Wren42d5dd42015-05-01 10:39:26 -04001874 private final class NotificationClicker implements View.OnClickListener {
Adrian Roos7d7090d2014-05-21 13:10:23 +02001875 public void onClick(final View v) {
Chris Wren42d5dd42015-05-01 10:39:26 -04001876 if (!(v instanceof ExpandableNotificationRow)) {
1877 Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
1878 return;
1879 }
1880
1881 final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
1882 final StatusBarNotification sbn = row.getStatusBarNotification();
1883 if (sbn == null) {
1884 Log.e(TAG, "NotificationClicker called on an unclickable notification,");
1885 return;
1886 }
1887
Mady Mellorf0625802016-02-11 18:03:48 -08001888 // Check if the notification is displaying the gear, if so slide notification back
1889 if (row.getSettingsRow() != null && row.getSettingsRow().isVisible()) {
1890 row.animateTranslateNotification(0);
1891 return;
1892 }
1893
Selim Cinekc6dd5212015-11-02 14:51:54 -08001894 Notification notification = sbn.getNotification();
1895 final PendingIntent intent = notification.contentIntent != null
1896 ? notification.contentIntent
1897 : notification.fullScreenIntent;
Chris Wren42d5dd42015-05-01 10:39:26 -04001898 final String notificationKey = sbn.getKey();
1899
Jorim Jaggi5eb67c22015-08-19 19:50:49 -07001900 // Mark notification for one frame.
1901 row.setJustClicked(true);
1902 DejankUtils.postAfterTraversal(new Runnable() {
1903 @Override
1904 public void run() {
1905 row.setJustClicked(false);
1906 }
1907 });
1908
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001909 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Chris Wren42d5dd42015-05-01 10:39:26 -04001910 final boolean afterKeyguardGone = intent.isActivity()
1911 && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02001912 mCurrentUserId);
Adrian Roos4314f6d2014-05-28 14:10:27 +02001913 dismissKeyguardThenExecute(new OnDismissAction() {
Adrian Roos7d7090d2014-05-21 13:10:23 +02001914 public boolean onDismiss() {
Chris Wren42d5dd42015-05-01 10:39:26 -04001915 if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
Christoph Studerc6a656c2015-01-22 15:02:49 +01001916 // Release the HUN notification to the shade.
Selim Cinekf55f1bc2016-05-27 11:19:11 -07001917
1918 if (isPanelFullyCollapsed()) {
1919 HeadsUpManager.setIsClickedNotification(row, true);
1920 }
Christoph Studerc6a656c2015-01-22 15:02:49 +01001921 //
1922 // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
1923 // become canceled shortly by NoMan, but we can't assume that.
Chris Wren42d5dd42015-05-01 10:39:26 -04001924 mHeadsUpManager.releaseImmediately(notificationKey);
Adrian Roos7d7090d2014-05-21 13:10:23 +02001925 }
Selim Cinek36b02232016-05-11 23:07:05 -04001926 StatusBarNotification parentToCancel = null;
1927 if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
1928 StatusBarNotification summarySbn = mGroupManager.getLogicalGroupSummary(sbn)
1929 .getStatusBarNotification();
1930 if (shouldAutoCancel(summarySbn)) {
1931 parentToCancel = summarySbn;
1932 }
1933 }
1934 final StatusBarNotification parentToCancelFinal = parentToCancel;
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001935 new Thread() {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001936 @Override
1937 public void run() {
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001938 try {
1939 if (keyguardShowing && !afterKeyguardGone) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001940 ActivityManagerNative.getDefault()
1941 .keyguardWaitingForActivityDrawn();
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001942 }
Jorim Jaggi89f7f282014-10-17 19:54:15 +02001943
1944 // The intent we are sending is for the application, which
1945 // won't have permission to immediately start an activity after
1946 // the user switches to home. We know it is safe to do at this
1947 // point, so make sure new activity switches are now allowed.
1948 ActivityManagerNative.getDefault().resumeAppSwitches();
1949 } catch (RemoteException e) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001950 }
Chris Wren42d5dd42015-05-01 10:39:26 -04001951 if (intent != null) {
Ricky Wai7fa01712016-03-16 12:13:54 +00001952 // If we are launching a work activity and require to launch
1953 // separate work challenge, we defer the activity action and cancel
1954 // notification until work challenge is unlocked.
1955 if (intent.isActivity()) {
1956 final int userId = intent.getCreatorUserHandle()
1957 .getIdentifier();
1958 if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
1959 && mKeyguardManager.isDeviceLocked(userId)) {
Rubin Xu89927b32016-07-28 14:34:26 +01001960 boolean canBypass = false;
1961 try {
1962 canBypass = ActivityManagerNative.getDefault()
1963 .canBypassWorkChallenge(intent);
1964 } catch (RemoteException e) {
1965 }
1966 // For direct-boot aware activities, they can be shown when
1967 // the device is still locked without triggering the work
1968 // challenge.
1969 if ((!canBypass) && startWorkChallengeIfNecessary(userId,
1970 intent.getIntentSender(), notificationKey)) {
1971 // Show work challenge, do not run PendingIntent and
Ricky Waia8c37a12016-04-05 17:10:04 +01001972 // remove notification
1973 return;
1974 }
Ricky Wai7fa01712016-03-16 12:13:54 +00001975 }
1976 }
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001977 try {
Jorim Jaggie6e108e2016-03-28 13:38:45 -07001978 intent.send(null, 0, null, null, null, null,
1979 getActivityOptions());
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001980 } catch (PendingIntent.CanceledException e) {
1981 // the stack trace isn't very helpful here.
1982 // Just log the exception message.
1983 Log.w(TAG, "Sending contentIntent failed: " + e);
Adrian Roos7d7090d2014-05-21 13:10:23 +02001984
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001985 // TODO: Dismiss Keyguard.
1986 }
Chris Wren42d5dd42015-05-01 10:39:26 -04001987 if (intent.isActivity()) {
Jorim Jaggib835dd72015-06-08 12:28:42 -07001988 mAssistManager.hideAssist();
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02001989 overrideActivityPendingAppTransition(keyguardShowing
1990 && !afterKeyguardGone);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001991 }
1992 }
1993
1994 try {
Chris Wren42d5dd42015-05-01 10:39:26 -04001995 mBarService.onNotificationClick(notificationKey);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001996 } catch (RemoteException ex) {
1997 // system process is dead if we're here.
1998 }
Selim Cinek36b02232016-05-11 23:07:05 -04001999 if (parentToCancelFinal != null) {
2000 // We have to post it to the UI thread for synchronization
2001 mHandler.post(new Runnable() {
2002 @Override
2003 public void run() {
2004 Runnable removeRunnable = new Runnable() {
2005 @Override
2006 public void run() {
2007 performRemoveNotification(parentToCancelFinal,
2008 true);
2009 }
2010 };
2011 if (isCollapsing()) {
2012 // To avoid lags we're only performing the remove
2013 // after the shade was collapsed
2014 addPostCollapseAction(removeRunnable);
2015 } else {
2016 removeRunnable.run();
2017 }
2018 }
2019 });
2020 }
Adrian Roos7d7090d2014-05-21 13:10:23 +02002021 }
Jorim Jaggi89f7f282014-10-17 19:54:15 +02002022 }.start();
Adrian Roos7d7090d2014-05-21 13:10:23 +02002023
2024 // close the shade if it was open
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +01002025 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
Jorim Jaggi27c9b742015-04-09 10:34:49 -07002026 true /* force */, true /* delayed */);
Adrian Roos7d7090d2014-05-21 13:10:23 +02002027 visibilityChanged(false);
2028
Jorim Jaggi8972c2a2015-06-05 16:05:54 -07002029 return true;
Daniel Sandler6a858c32012-03-12 14:38:58 -04002030 }
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02002031 }, afterKeyguardGone);
Daniel Sandler6a858c32012-03-12 14:38:58 -04002032 }
Chris Wren42d5dd42015-05-01 10:39:26 -04002033
Selim Cinek36b02232016-05-11 23:07:05 -04002034 private boolean shouldAutoCancel(StatusBarNotification sbn) {
2035 int flags = sbn.getNotification().flags;
2036 if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
2037 return false;
2038 }
2039 if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
2040 return false;
2041 }
2042 return true;
2043 }
2044
Chris Wren42d5dd42015-05-01 10:39:26 -04002045 public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
Selim Cinekc6dd5212015-11-02 14:51:54 -08002046 Notification notification = sbn.getNotification();
2047 if (notification.contentIntent != null || notification.fullScreenIntent != null) {
Chris Wren42d5dd42015-05-01 10:39:26 -04002048 row.setOnClickListener(this);
2049 } else {
2050 row.setOnClickListener(null);
2051 }
2052 }
Daniel Sandler6a858c32012-03-12 14:38:58 -04002053 }
Chris Wrenf29c3b42013-11-27 16:30:30 -05002054
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02002055 public void animateCollapsePanels(int flags, boolean force) {
2056 }
2057
Jorim Jaggi27c9b742015-04-09 10:34:49 -07002058 public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
2059 }
2060
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02002061 public void overrideActivityPendingAppTransition(boolean keyguardShowing) {
2062 if (keyguardShowing) {
2063 try {
2064 mWindowManagerService.overridePendingAppTransition(null, 0, 0, null);
2065 } catch (RemoteException e) {
2066 Log.w(TAG, "Error overriding app transition: " + e);
2067 }
2068 }
2069 }
2070
Ricky Waicd35def2016-05-03 11:07:07 +01002071 protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
2072 String notificationKey) {
2073 final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
2074 null, userId);
2075 if (newIntent == null) {
2076 return false;
2077 }
2078 final Intent callBackIntent = new Intent(
2079 WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION);
2080 callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
2081 callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
2082 callBackIntent.setPackage(mContext.getPackageName());
2083
2084 PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
2085 mContext,
2086 0,
2087 callBackIntent,
2088 PendingIntent.FLAG_CANCEL_CURRENT |
2089 PendingIntent.FLAG_ONE_SHOT |
2090 PendingIntent.FLAG_IMMUTABLE);
2091 newIntent.putExtra(
2092 Intent.EXTRA_INTENT,
2093 callBackPendingIntent.getIntentSender());
2094 try {
2095 ActivityManagerNative.getDefault().startConfirmDeviceCredentialIntent(newIntent);
2096 } catch (RemoteException ex) {
2097 // ignore
2098 }
2099 return true;
2100 }
2101
Jorim Jaggie6e108e2016-03-28 13:38:45 -07002102 protected Bundle getActivityOptions() {
2103 // Anything launched from the notification shade should always go into the
2104 // fullscreen stack.
2105 ActivityOptions options = ActivityOptions.makeBasic();
2106 options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID);
2107 return options.toBundle();
2108 }
2109
Christoph Studere8e28652014-10-29 17:27:53 +01002110 protected void visibilityChanged(boolean visible) {
2111 if (mVisible != visible) {
2112 mVisible = visible;
2113 if (!visible) {
2114 dismissPopups();
2115 }
2116 }
2117 updateVisibleToUser();
2118 }
2119
2120 protected void updateVisibleToUser() {
2121 boolean oldVisibleToUser = mVisibleToUser;
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07002122 mVisibleToUser = mVisible && mDeviceInteractive;
Christoph Studere8e28652014-10-29 17:27:53 +01002123
2124 if (oldVisibleToUser != mVisibleToUser) {
2125 handleVisibleToUserChanged(mVisibleToUser);
2126 }
2127 }
2128
Daniel Sandler6a858c32012-03-12 14:38:58 -04002129 /**
Christoph Studere8e28652014-10-29 17:27:53 +01002130 * The LEDs are turned off when the notification panel is shown, even just a little bit.
Adrian Roos18d099a2016-05-19 15:28:18 -07002131 * See also PhoneStatusBar.setPanelExpanded for another place where we attempt to do this.
Daniel Sandler6a858c32012-03-12 14:38:58 -04002132 */
Christoph Studere8e28652014-10-29 17:27:53 +01002133 protected void handleVisibleToUserChanged(boolean visibleToUser) {
2134 try {
2135 if (visibleToUser) {
Selim Cinek6577cae2015-08-31 16:15:49 -07002136 boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
2137 boolean clearNotificationEffects =
Dan Sandlercb012892016-03-01 00:45:06 -05002138 !isPanelFullyCollapsed() &&
2139 (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
Chris Wrenb659c4f2015-06-25 17:12:27 -04002140 int notificationLoad = mNotificationData.getActiveNotifications().size();
Selim Cinek6577cae2015-08-31 16:15:49 -07002141 if (pinnedHeadsUp && isPanelFullyCollapsed()) {
Chris Wrenb659c4f2015-06-25 17:12:27 -04002142 notificationLoad = 1;
2143 } else {
2144 MetricsLogger.histogram(mContext, "note_load", notificationLoad);
2145 }
2146 mBarService.onPanelRevealed(clearNotificationEffects, notificationLoad);
Christoph Studere8e28652014-10-29 17:27:53 +01002147 } else {
2148 mBarService.onPanelHidden();
Dan Sandler4247a5c2014-07-23 15:58:08 -04002149 }
Christoph Studere8e28652014-10-29 17:27:53 +01002150 } catch (RemoteException ex) {
2151 // Won't fail unless the world has ended.
Daniel Sandler6a858c32012-03-12 14:38:58 -04002152 }
2153 }
2154
Chris Wren0c8275b2012-05-08 13:36:48 -04002155 /**
Chris Wren16895942015-06-23 11:22:20 -04002156 * Clear Buzz/Beep/Blink.
2157 */
2158 public void clearNotificationEffects() {
2159 try {
2160 mBarService.clearNotificationEffects();
2161 } catch (RemoteException e) {
2162 // Won't fail unless the world has ended.
2163 }
2164 }
2165
Yorke Leee4ea6ab2016-03-03 14:51:49 -08002166 public abstract boolean isPanelFullyCollapsed();
Chris Wren16895942015-06-23 11:22:20 -04002167
2168 /**
Chris Wren0c8275b2012-05-08 13:36:48 -04002169 * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
2170 * about the failure.
2171 *
2172 * WARNING: this will call back into us. Don't hold any locks.
2173 */
Christoph Studer71f18fd2014-05-20 17:02:04 +02002174 void handleNotificationError(StatusBarNotification n, String message) {
Christoph Studere71fefc2014-06-24 16:16:49 +02002175 removeNotification(n.getKey(), null);
Chris Wren0c8275b2012-05-08 13:36:48 -04002176 try {
Kenny Guy3a7c4a52014-03-03 18:24:03 +00002177 mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
2178 n.getInitialPid(), message, n.getUserId());
Chris Wren0c8275b2012-05-08 13:36:48 -04002179 } catch (RemoteException ex) {
2180 // The end is nigh.
2181 }
2182 }
2183
Christoph Studerd0694b62014-06-04 16:36:01 +02002184 protected StatusBarNotification removeNotificationViews(String key, RankingMap ranking) {
Christoph Studer37fe6932014-05-26 13:10:30 +02002185 NotificationData.Entry entry = mNotificationData.remove(key, ranking);
Chris Wren0c8275b2012-05-08 13:36:48 -04002186 if (entry == null) {
John Spurlockcd686b52013-06-05 10:13:46 -04002187 Log.w(TAG, "removeNotification for unknown key: " + key);
Chris Wren0c8275b2012-05-08 13:36:48 -04002188 return null;
2189 }
Christoph Studer37fe6932014-05-26 13:10:30 +02002190 updateNotifications();
Chris Wren0c8275b2012-05-08 13:36:48 -04002191 return entry.notification;
2192 }
2193
Selim Cinek8d490d42015-04-10 00:05:50 -07002194 protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn) {
Chris Wren0c8275b2012-05-08 13:36:48 -04002195 if (DEBUG) {
Christoph Studera0506e72014-07-31 20:27:39 +02002196 Log.d(TAG, "createNotificationViews(notification=" + sbn);
Chris Wren0c8275b2012-05-08 13:36:48 -04002197 }
Selim Cinek379ff8f2015-02-20 17:03:16 +01002198 final StatusBarIconView iconView = createIcon(sbn);
2199 if (iconView == null) {
2200 return null;
2201 }
2202
2203 // Construct the expanded view.
2204 NotificationData.Entry entry = new NotificationData.Entry(sbn, iconView);
Selim Cinek8d490d42015-04-10 00:05:50 -07002205 if (!inflateViews(entry, mStackScroller)) {
Selim Cinek379ff8f2015-02-20 17:03:16 +01002206 handleNotificationError(sbn, "Couldn't expand RemoteViews for: " + sbn);
2207 return null;
2208 }
2209 return entry;
2210 }
2211
Xiaohui Chene90c2c52016-02-24 16:08:00 -08002212 public StatusBarIconView createIcon(StatusBarNotification sbn) {
Chris Wren0c8275b2012-05-08 13:36:48 -04002213 // Construct the icon.
Christoph Studera0506e72014-07-31 20:27:39 +02002214 Notification n = sbn.getNotification();
Chris Wren0c8275b2012-05-08 13:36:48 -04002215 final StatusBarIconView iconView = new StatusBarIconView(mContext,
Christoph Studera0506e72014-07-31 20:27:39 +02002216 sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
Chris Wren0c8275b2012-05-08 13:36:48 -04002217 iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
2218
Dan Sandler33439812015-08-10 15:49:56 -04002219 final Icon smallIcon = n.getSmallIcon();
2220 if (smallIcon == null) {
2221 handleNotificationError(sbn,
2222 "No small icon in notification from " + sbn.getPackageName());
2223 return null;
2224 }
Dan Sandlerd63f9322015-05-06 15:18:49 -04002225 final StatusBarIcon ic = new StatusBarIcon(
Christoph Studera0506e72014-07-31 20:27:39 +02002226 sbn.getUser(),
Dan Sandler4e787062015-06-17 15:09:48 -04002227 sbn.getPackageName(),
Dan Sandler33439812015-08-10 15:49:56 -04002228 smallIcon,
Dan Sandler4e787062015-06-17 15:09:48 -04002229 n.iconLevel,
2230 n.number,
Adrian Rooseba05822016-04-22 17:09:27 -07002231 StatusBarIconView.contentDescForNotification(mContext, n));
Chris Wren0c8275b2012-05-08 13:36:48 -04002232 if (!iconView.set(ic)) {
Christoph Studera0506e72014-07-31 20:27:39 +02002233 handleNotificationError(sbn, "Couldn't create icon: " + ic);
Chris Wren0c8275b2012-05-08 13:36:48 -04002234 return null;
2235 }
Selim Cinek379ff8f2015-02-20 17:03:16 +01002236 return iconView;
Chris Wrenf0048ce2013-08-07 16:43:43 -04002237 }
Chris Wren0c8275b2012-05-08 13:36:48 -04002238
Christoph Studerd0694b62014-06-04 16:36:01 +02002239 protected void addNotificationViews(Entry entry, RankingMap ranking) {
Raju Yadav5f330262014-03-24 10:44:00 +01002240 if (entry == null) {
2241 return;
2242 }
Chris Wren0c8275b2012-05-08 13:36:48 -04002243 // Add the expanded view and icon.
Christoph Studer37fe6932014-05-26 13:10:30 +02002244 mNotificationData.add(entry, ranking);
2245 updateNotifications();
Selim Cinek8efa6dd2014-05-19 16:27:37 +02002246 }
2247
Jorim Jaggi251957d2014-04-09 04:24:09 +02002248 /**
Selim Cinek5f71bee2015-11-18 10:25:23 -08002249 * @param recompute wheter the number should be recomputed
Jorim Jaggid4a57442014-04-10 02:45:55 +02002250 * @return The number of notifications we show on Keyguard.
2251 */
Selim Cinek5f71bee2015-11-18 10:25:23 -08002252 protected abstract int getMaxKeyguardNotifications(boolean recompute);
Jorim Jaggid4a57442014-04-10 02:45:55 +02002253
2254 /**
Jorim Jaggi251957d2014-04-09 04:24:09 +02002255 * Updates expanded, dimmed and locked states of notification rows.
2256 */
2257 protected void updateRowStates() {
Jorim Jaggif6411742014-08-05 17:10:43 +00002258 mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
2259
Christoph Studerc8db24b2014-07-25 17:50:30 +02002260 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
2261 final int N = activeNotifications.size();
2262
Jorim Jaggif6411742014-08-05 17:10:43 +00002263 int visibleNotifications = 0;
Jorim Jaggiecbab362014-04-23 16:13:15 +02002264 boolean onKeyguard = mState == StatusBarState.KEYGUARD;
Selim Cinek5f71bee2015-11-18 10:25:23 -08002265 int maxNotifications = 0;
2266 if (onKeyguard) {
2267 maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
2268 }
Christoph Studer37fe6932014-05-26 13:10:30 +02002269 for (int i = 0; i < N; i++) {
Christoph Studerc8db24b2014-07-25 17:50:30 +02002270 NotificationData.Entry entry = activeNotifications.get(i);
Selim Cinek2a739342016-03-17 10:28:55 -07002271 boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification);
Jorim Jaggiecbab362014-04-23 16:13:15 +02002272 if (onKeyguard) {
Selim Cinek83bc7832015-10-22 13:26:54 -07002273 entry.row.setOnKeyguard(true);
Chris Wren3ddab0d2012-08-02 16:52:21 -04002274 } else {
Selim Cinek83bc7832015-10-22 13:26:54 -07002275 entry.row.setOnKeyguard(false);
Selim Cinek2a739342016-03-17 10:28:55 -07002276 entry.row.setSystemExpanded(visibleNotifications == 0 && !childNotification);
Chris Wren8fd12652012-05-09 21:25:57 -04002277 }
Selim Cinek3f19f602016-05-02 18:01:56 -07002278 boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
2279 entry.notification) && !entry.row.isRemoved();
Selim Cinek83bc7832015-10-22 13:26:54 -07002280 boolean childWithVisibleSummary = childNotification
2281 && mGroupManager.getGroupSummary(entry.notification).getVisibility()
2282 == View.VISIBLE;
Jorim Jaggif6411742014-08-05 17:10:43 +00002283 boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
Selim Cinek2a739342016-03-17 10:28:55 -07002284 if (suppressedSummary || (isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
Selim Cinek06416b92016-05-09 16:36:10 -04002285 (onKeyguard && !childWithVisibleSummary
2286 && (visibleNotifications >= maxNotifications || !showOnKeyguard))) {
Jorim Jaggif6411742014-08-05 17:10:43 +00002287 entry.row.setVisibility(View.GONE);
Selim Cinek2a739342016-03-17 10:28:55 -07002288 if (onKeyguard && showOnKeyguard && !childNotification && !suppressedSummary) {
Jorim Jaggif6411742014-08-05 17:10:43 +00002289 mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
2290 }
2291 } else {
2292 boolean wasGone = entry.row.getVisibility() == View.GONE;
2293 entry.row.setVisibility(View.VISIBLE);
Selim Cinekfa760d42016-05-10 15:50:53 -04002294 if (!childNotification && !entry.row.isRemoved()) {
Selim Cinekb5605e52015-02-20 18:21:41 +01002295 if (wasGone) {
2296 // notify the scroller of a child addition
Selim Cinek2a739342016-03-17 10:28:55 -07002297 mStackScroller.generateAddAnimation(entry.row,
2298 !showOnKeyguard /* fromMoreCard */);
Selim Cinekb5605e52015-02-20 18:21:41 +01002299 }
2300 visibleNotifications++;
Jorim Jaggif6411742014-08-05 17:10:43 +00002301 }
Jorim Jaggif6411742014-08-05 17:10:43 +00002302 }
Chris Wren8fd12652012-05-09 21:25:57 -04002303 }
Jorim Jaggif6411742014-08-05 17:10:43 +00002304
Selim Cinek2cd45df2015-06-09 18:00:07 -07002305 mStackScroller.updateOverflowContainerVisibility(onKeyguard
2306 && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0);
Jorim Jaggif6411742014-08-05 17:10:43 +00002307
Selim Cinek0cce5312015-05-20 22:13:55 -07002308 mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
2309 mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
Jorim Jaggif6411742014-08-05 17:10:43 +00002310 mStackScroller.changeViewPosition(mKeyguardIconOverflowContainer,
2311 mStackScroller.getChildCount() - 3);
Jorim Jaggif6411742014-08-05 17:10:43 +00002312 }
2313
Selim Cinekfa760d42016-05-10 15:50:53 -04002314 public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
Jorim Jaggif6411742014-08-05 17:10:43 +00002315 return mShowLockscreenNotifications && !mNotificationData.isAmbient(sbn.getKey());
Chris Wren8fd12652012-05-09 21:25:57 -04002316 }
2317
John Spurlocke677d712014-02-13 12:52:19 -05002318 protected void setZenMode(int mode) {
John Spurlock110e5b12014-02-27 13:09:35 -05002319 if (!isDeviceProvisioned()) return;
John Spurlocke677d712014-02-13 12:52:19 -05002320 mZenMode = mode;
Christoph Studer37fe6932014-05-26 13:10:30 +02002321 updateNotifications();
John Spurlocke677d712014-02-13 12:52:19 -05002322 }
2323
Dan Sandler52e5701e2014-07-22 23:14:54 -04002324 // extended in PhoneStatusBar
2325 protected void setShowLockscreenNotifications(boolean show) {
2326 mShowLockscreenNotifications = show;
2327 }
2328
Adrian Roos3aec6382016-02-05 14:19:01 -08002329 protected void setLockScreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
2330 mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
2331 }
2332
Dan Sandler52e5701e2014-07-22 23:14:54 -04002333 private void updateLockscreenNotificationSetting() {
2334 final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
2335 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
2336 1,
2337 mCurrentUserId) != 0;
Adrian Roosbd3409c2014-08-12 18:21:09 +02002338 final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
2339 null /* admin */, mCurrentUserId);
2340 final boolean allowedByDpm = (dpmFlags
2341 & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
Adrian Roos3aec6382016-02-05 14:19:01 -08002342
Adrian Roosbd3409c2014-08-12 18:21:09 +02002343 setShowLockscreenNotifications(show && allowedByDpm);
Adrian Roosb27d7a52016-06-16 13:04:47 -07002344
2345 if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
2346 final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
2347 Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
2348 0,
2349 mCurrentUserId) != 0;
2350 final boolean remoteInputDpm =
2351 (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
2352
2353 setLockScreenAllowRemoteInput(remoteInput && remoteInputDpm);
2354 } else {
2355 setLockScreenAllowRemoteInput(false);
2356 }
Dan Sandler52e5701e2014-07-22 23:14:54 -04002357 }
2358
Chris Wren0c8275b2012-05-08 13:36:48 -04002359 protected abstract void setAreThereNotifications();
Christoph Studer37fe6932014-05-26 13:10:30 +02002360 protected abstract void updateNotifications();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07002361 public abstract boolean shouldDisableNavbarGestures();
Chris Wren0c8275b2012-05-08 13:36:48 -04002362
Christoph Studere71fefc2014-06-24 16:16:49 +02002363 public abstract void addNotification(StatusBarNotification notification,
Selim Cinek379ff8f2015-02-20 17:03:16 +01002364 RankingMap ranking, Entry oldEntry);
Christoph Studere71fefc2014-06-24 16:16:49 +02002365 protected abstract void updateNotificationRanking(RankingMap ranking);
2366 public abstract void removeNotification(String key, RankingMap ranking);
Christoph Studera7fe6312014-06-27 19:32:44 +02002367
Christoph Studere71fefc2014-06-24 16:16:49 +02002368 public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
Christoph Studer71f18fd2014-05-20 17:02:04 +02002369 if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
Chris Wren0c8275b2012-05-08 13:36:48 -04002370
Chris Wrend04f6ce2014-06-11 17:37:28 -04002371 final String key = notification.getKey();
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002372 Entry entry = mNotificationData.get(key);
2373 if (entry == null) {
Chris Wren0c8275b2012-05-08 13:36:48 -04002374 return;
Adrian Roos18d099a2016-05-19 15:28:18 -07002375 } else {
Selim Cinek2d79f632015-11-02 15:13:29 -08002376 mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
Adrian Roos18d099a2016-05-19 15:28:18 -07002377 mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
Chris Wren0c8275b2012-05-08 13:36:48 -04002378 }
2379
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002380 Notification n = notification.getNotification();
Julia Reynoldsf612869ae2015-11-05 16:48:55 -05002381 mNotificationData.updateRanking(ranking);
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002382
Adrian Roos95f8bea2016-07-27 15:49:03 -07002383 boolean applyInPlace;
2384 try {
2385 applyInPlace = entry.cacheContentViews(mContext, notification.getNotification());
2386 } catch (RuntimeException e) {
2387 Log.e(TAG, "Unable to get notification remote views", e);
2388 applyInPlace = false;
2389 }
Chris Wrenbdf33762015-12-04 15:50:51 -05002390 boolean shouldPeek = shouldPeek(entry, notification);
Selim Cinek684a4422015-04-15 16:18:39 -07002391 boolean alertAgain = alertAgain(entry, n);
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002392 if (DEBUG) {
2393 Log.d(TAG, "applyInPlace=" + applyInPlace
Chris Wrenbdf33762015-12-04 15:50:51 -05002394 + " shouldPeek=" + shouldPeek
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002395 + " alertAgain=" + alertAgain);
2396 }
Chris Wren0c8275b2012-05-08 13:36:48 -04002397
Dan Sandler24813b02016-01-14 15:49:36 -05002398 final StatusBarNotification oldNotification = entry.notification;
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002399 entry.notification = notification;
Dan Sandler24813b02016-01-14 15:49:36 -05002400 mGroupManager.onEntryUpdated(entry, oldNotification);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002401
2402 boolean updateSuccessful = false;
2403 if (applyInPlace) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002404 if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
2405 try {
2406 if (entry.icon != null) {
2407 // Update the icon
Dan Sandlerd63f9322015-05-06 15:18:49 -04002408 final StatusBarIcon ic = new StatusBarIcon(
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002409 notification.getUser(),
Dan Sandler4e787062015-06-17 15:09:48 -04002410 notification.getPackageName(),
Dan Sandlerd63f9322015-05-06 15:18:49 -04002411 n.getSmallIcon(),
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002412 n.iconLevel,
2413 n.number,
Adrian Rooseba05822016-04-22 17:09:27 -07002414 StatusBarIconView.contentDescForNotification(mContext, n));
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002415 entry.icon.setNotification(n);
2416 if (!entry.icon.set(ic)) {
2417 handleNotificationError(notification, "Couldn't update icon: " + ic);
2418 return;
2419 }
2420 }
Selim Cinek8d490d42015-04-10 00:05:50 -07002421 updateNotificationViews(entry, notification);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002422 updateSuccessful = true;
2423 }
2424 catch (RuntimeException e) {
Selim Cinek684a4422015-04-15 16:18:39 -07002425 // It failed to apply cleanly.
Adrian Roose458aa82015-12-08 16:17:19 -08002426 Log.w(TAG, "Couldn't reapply views for package " +
2427 notification.getPackageName(), e);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002428 }
2429 }
2430 if (!updateSuccessful) {
2431 if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
Dan Sandlerd63f9322015-05-06 15:18:49 -04002432 final StatusBarIcon ic = new StatusBarIcon(
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002433 notification.getUser(),
Dan Sandler4e787062015-06-17 15:09:48 -04002434 notification.getPackageName(),
Dan Sandlerd63f9322015-05-06 15:18:49 -04002435 n.getSmallIcon(),
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002436 n.iconLevel,
2437 n.number,
Adrian Rooseba05822016-04-22 17:09:27 -07002438 StatusBarIconView.contentDescForNotification(mContext, n));
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002439 entry.icon.setNotification(n);
2440 entry.icon.set(ic);
Adrian Roos95f8bea2016-07-27 15:49:03 -07002441 if (!inflateViews(entry, mStackScroller)) {
2442 handleNotificationError(notification, "Couldn't update remote views for: "
2443 + notification);
2444 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002445 }
Chris Wrenbdf33762015-12-04 15:50:51 -05002446 updateHeadsUp(key, entry, shouldPeek, alertAgain);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002447 updateNotifications();
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002448
dongwan0605.kim30637e42016-03-02 17:16:47 +09002449 if (!notification.isClearable()) {
2450 // The user may have performed a dismiss action on the notification, since it's
2451 // not clearable we should snap it back.
2452 mStackScroller.snapViewIfNeeded(entry.row);
2453 }
2454
Selim Cinek684a4422015-04-15 16:18:39 -07002455 if (DEBUG) {
2456 // Is this for you?
2457 boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
2458 Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
2459 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002460
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002461 setAreThereNotifications();
2462 }
2463
Chris Wrenbdf33762015-12-04 15:50:51 -05002464 protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
Selim Cinek29fa89b2015-04-17 10:39:11 -07002465 boolean alertAgain);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002466
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002467 private void updateNotificationViews(Entry entry, StatusBarNotification sbn) {
2468 final RemoteViews contentView = entry.cachedContentView;
2469 final RemoteViews bigContentView = entry.cachedBigContentView;
2470 final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
2471 final RemoteViews publicContentView = entry.cachedPublicContentView;
Dan Sandlera5e0f412014-01-23 15:11:54 -05002472
Chris Wrene03f4e12013-08-08 16:48:48 -04002473 // Reapply the RemoteViews
Selim Cinek684a4422015-04-15 16:18:39 -07002474 contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
2475 if (bigContentView != null && entry.getExpandedContentView() != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002476 bigContentView.reapply(sbn.getPackageContext(mContext),
Dan Sandler68079d52015-07-22 10:45:30 -04002477 entry.getExpandedContentView(),
Jorim Jaggi39fa59f2014-02-25 15:38:45 +01002478 mOnClickHandler);
Chris Wrene03f4e12013-08-08 16:48:48 -04002479 }
Selim Cinek684a4422015-04-15 16:18:39 -07002480 View headsUpChild = entry.getHeadsUpContentView();
Selim Cinek8d490d42015-04-10 00:05:50 -07002481 if (headsUpContentView != null && headsUpChild != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002482 headsUpContentView.reapply(sbn.getPackageContext(mContext),
Dan Sandler68079d52015-07-22 10:45:30 -04002483 headsUpChild, mOnClickHandler);
Selim Cinek8d490d42015-04-10 00:05:50 -07002484 }
Dan Sandlera5e0f412014-01-23 15:11:54 -05002485 if (publicContentView != null && entry.getPublicContentView() != null) {
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002486 publicContentView.reapply(sbn.getPackageContext(mContext),
Dan Sandler68079d52015-07-22 10:45:30 -04002487 entry.getPublicContentView(), mOnClickHandler);
Dan Sandlera5e0f412014-01-23 15:11:54 -05002488 }
Chris Wrene03f4e12013-08-08 16:48:48 -04002489 // update the contentIntent
Julia Reynoldsd9228f12015-10-20 10:37:27 -04002490 mNotificationClicker.register(entry.row, sbn);
Chris Wren42d5dd42015-05-01 10:39:26 -04002491
Selim Cinekda42d652015-12-04 15:51:16 -08002492 entry.row.onNotificationUpdated(entry);
Selim Cinek51ae05d2014-09-09 15:51:38 +02002493 entry.row.resetHeight();
Chris Wren0c8275b2012-05-08 13:36:48 -04002494 }
John Spurlock36231282012-06-23 17:11:27 -04002495
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00002496 protected void updatePublicContentView(Entry entry,
2497 StatusBarNotification sbn) {
2498 final RemoteViews publicContentView = entry.cachedPublicContentView;
Selim Cineke4c068d2016-02-19 13:46:55 -08002499 View inflatedView = entry.getPublicContentView();
2500 if (entry.autoRedacted && publicContentView != null && inflatedView != null) {
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00002501 final boolean disabledByPolicy =
2502 !adminAllowsUnredactedNotifications(entry.notification.getUserId());
Selim Cineke4c068d2016-02-19 13:46:55 -08002503 String notificationHiddenText = mContext.getString(disabledByPolicy
2504 ? com.android.internal.R.string.notification_hidden_by_policy_text
2505 : com.android.internal.R.string.notification_hidden_text);
2506 TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
2507 if (titleView != null
2508 && !titleView.getText().toString().equals(notificationHiddenText)) {
2509 publicContentView.setTextViewText(android.R.id.title, notificationHiddenText);
2510 publicContentView.reapply(sbn.getPackageContext(mContext),
2511 inflatedView, mOnClickHandler);
2512 entry.row.onNotificationUpdated(entry);
2513 }
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00002514 }
2515 }
2516
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002517 protected void notifyHeadsUpScreenOff() {
Selim Cinek684a4422015-04-15 16:18:39 -07002518 maybeEscalateHeadsUp();
Chris Wrene97f90b2013-08-07 17:39:35 -04002519 }
2520
Chris Wrend93d5ad2014-09-08 16:34:03 -04002521 private boolean alertAgain(Entry oldEntry, Notification newNotification) {
2522 return oldEntry == null || !oldEntry.hasInterrupted()
2523 || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
Chris Wrend04f6ce2014-06-11 17:37:28 -04002524 }
2525
Chris Wrenbdf33762015-12-04 15:50:51 -05002526 protected boolean shouldPeek(Entry entry) {
2527 return shouldPeek(entry, entry.notification);
Chris Wren0c274b12015-07-17 10:34:53 -04002528 }
2529
Chris Wrenbdf33762015-12-04 15:50:51 -05002530 protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
Adrian Roosf6967e062016-06-21 16:12:48 -07002531 if (!mUseHeadsUp || isDeviceInVrMode()) {
Dan Sandlerdc34df52016-04-07 21:04:46 -04002532 return false;
2533 }
2534
Christoph Studer2f9dbba2014-09-03 17:35:54 +02002535 if (mNotificationData.shouldFilterOut(sbn)) {
Chris Wrenbdf33762015-12-04 15:50:51 -05002536 if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
Christoph Studer2f9dbba2014-09-03 17:35:54 +02002537 return false;
2538 }
2539
Selim Cinekd5921912016-02-09 10:33:01 -08002540 boolean inUse = mPowerManager.isScreenOn()
2541 && (!mStatusBarKeyguardViewManager.isShowing()
Selim Cinek2dabc822016-08-09 16:28:17 -07002542 || mStatusBarKeyguardViewManager.isOccluded());
Selim Cinekd5921912016-02-09 10:33:01 -08002543 try {
2544 inUse = inUse && !mDreamManager.isDreaming();
2545 } catch (RemoteException e) {
2546 Log.d(TAG, "failed to query dream manager", e);
2547 }
2548
2549 if (!inUse) {
2550 if (DEBUG) {
2551 Log.d(TAG, "No peeking: not in use: " + sbn.getKey());
2552 }
2553 return false;
2554 }
2555
2556 if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
2557 if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
Chris Wrena6d4fb62014-11-20 14:46:23 -05002558 return false;
2559 }
2560
Chris Wrenbdf33762015-12-04 15:50:51 -05002561 if (entry.hasJustLaunchedFullScreenIntent()) {
2562 if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
2563 return false;
2564 }
2565
Julia Reynoldsf0f629f2016-02-25 09:34:04 -05002566 if (isSnoozedPackage(sbn)) {
2567 if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
2568 return false;
2569 }
2570
2571 if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_HIGH) {
2572 if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
2573 return false;
2574 }
2575
Selim Cinekd5921912016-02-09 10:33:01 -08002576 if (sbn.getNotification().fullScreenIntent != null) {
2577 if (mAccessibilityManager.isTouchExplorationEnabled()) {
2578 if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
2579 return false;
2580 } else {
2581 return true;
2582 }
Chris Wrenbdf33762015-12-04 15:50:51 -05002583 }
2584
Selim Cinekd5921912016-02-09 10:33:01 -08002585 return true;
Chris Wren157026f2013-06-28 16:54:01 -04002586 }
2587
Selim Cinek29fa89b2015-04-17 10:39:11 -07002588 protected abstract boolean isSnoozedPackage(StatusBarNotification sbn);
2589
John Spurlockcfc359a2013-09-05 10:42:03 -04002590 public void setInteracting(int barWindow, boolean interacting) {
John Spurlockad3e6cb2013-04-30 08:47:43 -04002591 // hook for subclasses
2592 }
John Spurlock5c454122013-06-17 07:35:46 -04002593
Jorim Jaggi4222d9a2014-04-23 16:13:15 +02002594 public void setBouncerShowing(boolean bouncerShowing) {
2595 mBouncerShowing = bouncerShowing;
2596 }
2597
2598 /**
2599 * @return Whether the security bouncer from Keyguard is showing.
2600 */
2601 public boolean isBouncerShowing() {
2602 return mBouncerShowing;
2603 }
2604
John Spurlock5c454122013-06-17 07:35:46 -04002605 public void destroy() {
John Spurlock5c454122013-06-17 07:35:46 -04002606 mContext.unregisterReceiver(mBroadcastReceiver);
Christoph Studere71fefc2014-06-24 16:16:49 +02002607 try {
2608 mNotificationListener.unregisterAsSystemService();
2609 } catch (RemoteException e) {
2610 // Ignore.
Christoph Studer37fe6932014-05-26 13:10:30 +02002611 }
John Spurlock5c454122013-06-17 07:35:46 -04002612 }
Kenny Guy4dcb0dc2014-07-15 12:41:24 +01002613
2614 /**
2615 * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then
2616 * return PackageManager for mContext
2617 */
Selim Cinekeef84282015-10-30 16:28:00 -07002618 public static PackageManager getPackageManagerForUser(Context context, int userId) {
2619 Context contextForUser = context;
Kenny Guy4dcb0dc2014-07-15 12:41:24 +01002620 // UserHandle defines special userId as negative values, e.g. USER_ALL
2621 if (userId >= 0) {
2622 try {
2623 // Create a context for the correct user so if a package isn't installed
2624 // for user 0 we can still load information about the package.
2625 contextForUser =
Selim Cinekeef84282015-10-30 16:28:00 -07002626 context.createPackageContextAsUser(context.getPackageName(),
Kenny Guy4dcb0dc2014-07-15 12:41:24 +01002627 Context.CONTEXT_RESTRICTED,
2628 new UserHandle(userId));
2629 } catch (NameNotFoundException e) {
2630 // Shouldn't fail to find the package name for system ui.
2631 }
2632 }
2633 return contextForUser.getPackageManager();
2634 }
Chris Wren78403d72014-07-28 10:23:24 +01002635
2636 @Override
2637 public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
2638 try {
2639 mBarService.onNotificationExpansionChanged(key, userAction, expanded);
2640 } catch (RemoteException e) {
2641 // Ignore.
2642 }
2643 }
Jim Millerab954542014-10-10 18:21:49 -07002644
2645 public boolean isKeyguardSecure() {
Dan Sandlere163a642015-03-01 22:58:32 -05002646 if (mStatusBarKeyguardViewManager == null) {
2647 // startKeyguard() hasn't been called yet, so we don't know.
2648 // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
2649 // value onVisibilityChanged().
2650 Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
2651 new Throwable());
2652 return false;
2653 }
Jim Millerab954542014-10-10 18:21:49 -07002654 return mStatusBarKeyguardViewManager.isSecure();
2655 }
Adrian Roos4f43dc02015-06-17 16:43:38 -07002656
2657 @Override
2658 public void showAssistDisclosure() {
2659 if (mAssistManager != null) {
2660 mAssistManager.showDisclosure();
2661 }
2662 }
Jorim Jaggi165ce062015-07-06 16:18:11 -07002663
2664 @Override
2665 public void startAssist(Bundle args) {
2666 if (mAssistManager != null) {
2667 mAssistManager.startAssist(args);
2668 }
2669 }
Joe Onorato2314aab2010-04-08 16:41:23 -05002670}