blob: 7ae87e7e834f7da2f782d1bdc253d76f49733774 [file] [log] [blame]
Joe Onorato808182d2010-07-09 18:52:06 -04001/*
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 Onoratofd52b182010-11-10 18:00:52 -080017package com.android.systemui.statusbar.phone;
Joe Onorato808182d2010-07-09 18:52:06 -040018
Jorim Jaggicff0acb2014-03-31 16:35:15 +020019
Daniel Sandlerd7e96862012-04-26 01:10:29 -040020import android.animation.Animator;
21import android.animation.AnimatorListenerAdapter;
Jeff Brown4d69e222014-09-18 15:27:50 -070022import android.annotation.NonNull;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070023import android.app.ActivityManager;
Joe Onorato808182d2010-07-09 18:52:06 -040024import android.app.ActivityManagerNative;
Jason Monk62515be2014-05-21 16:06:19 -040025import android.app.IActivityManager;
Joe Onorato808182d2010-07-09 18:52:06 -040026import android.app.Notification;
27import android.app.PendingIntent;
Joe Onorato808182d2010-07-09 18:52:06 -040028import android.app.StatusBarManager;
29import android.content.BroadcastReceiver;
Jorim Jaggi786afcb2014-09-25 02:41:29 +020030import android.content.ComponentCallbacks2;
Jason Monk7e53f202016-01-28 10:40:20 -050031import android.content.ComponentName;
Joe Onorato808182d2010-07-09 18:52:06 -040032import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
Adrian Roos21d2a252015-06-01 13:59:59 -070035import android.content.pm.IPackageManager;
Vladislav Kaznacheev38f426c2015-10-28 15:48:12 -070036import android.content.pm.PackageManager;
Daniel Sandler777dcde2013-09-30 10:21:45 -040037import android.content.res.Configuration;
Michael Jurka7f2668c2012-03-27 07:49:52 -070038import android.content.res.Resources;
John Spurlock919adac2012-10-02 16:41:12 -040039import android.database.ContentObserver;
Dan Sandler16128f42014-05-21 12:48:22 -040040import android.graphics.Bitmap;
Romain Guy648342f2012-05-25 10:44:45 -070041import android.graphics.Canvas;
42import android.graphics.ColorFilter;
Joe Onorato808182d2010-07-09 18:52:06 -040043import android.graphics.PixelFormat;
Daniel Sandlere680f542012-09-28 12:22:27 -040044import android.graphics.Point;
Jorim Jaggi2a5e4522014-11-24 21:45:20 +010045import android.graphics.PointF;
Romain Guy648342f2012-05-25 10:44:45 -070046import android.graphics.PorterDuff;
Selim Cineka0fad3b2014-09-19 17:20:05 +020047import android.graphics.PorterDuffXfermode;
Joe Onorato808182d2010-07-09 18:52:06 -040048import android.graphics.Rect;
Dan Sandler16128f42014-05-21 12:48:22 -040049import android.graphics.drawable.ColorDrawable;
Romain Guy648342f2012-05-25 10:44:45 -070050import android.graphics.drawable.Drawable;
Michael Jurka7f2668c2012-03-27 07:49:52 -070051import android.inputmethodservice.InputMethodService;
John Spurlock7b414672014-07-18 13:02:39 -040052import android.media.AudioAttributes;
Dan Sandler16128f42014-05-21 12:48:22 -040053import android.media.MediaMetadata;
54import android.media.session.MediaController;
55import android.media.session.MediaSession;
56import android.media.session.MediaSessionManager;
57import android.media.session.PlaybackState;
Selim Cinekbaa23272014-07-08 18:01:07 +020058import android.os.AsyncTask;
John Spurlock3c875662013-08-31 15:07:25 -040059import android.os.Bundle;
John Spurlock919adac2012-10-02 16:41:12 -040060import android.os.Handler;
Jason Monk4ae97d32014-12-17 10:14:33 -050061import android.os.HandlerThread;
Joe Onorato808182d2010-07-09 18:52:06 -040062import android.os.IBinder;
Joe Onorato808182d2010-07-09 18:52:06 -040063import android.os.Message;
John Spurlock56d007b2013-10-28 18:40:56 -040064import android.os.PowerManager;
Jason Monk4ae97d32014-12-17 10:14:33 -050065import android.os.Process;
Michael Jurka7f2668c2012-03-27 07:49:52 -070066import android.os.RemoteException;
Adrian Roos21d2a252015-06-01 13:59:59 -070067import android.os.ServiceManager;
Joe Onorato808182d2010-07-09 18:52:06 -040068import android.os.SystemClock;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070069import android.os.UserHandle;
Adrian Roos2b154a92014-11-17 15:18:39 +010070import android.os.UserManager;
Selim Cinek69ff8af2015-08-25 19:03:48 -070071import android.os.Vibrator;
Daniel Sandlerd3090562011-08-09 00:28:44 -040072import android.provider.Settings;
Chris Wren3ad4e3a2014-09-02 17:23:51 -040073import android.service.notification.NotificationListenerService;
Christoph Studerd0694b62014-06-04 16:36:01 +020074import android.service.notification.NotificationListenerService.RankingMap;
John Spurlockde84f0e2013-06-12 12:41:00 -040075import android.service.notification.StatusBarNotification;
Christoph Studer92b389d2014-04-01 18:44:40 +020076import android.util.ArraySet;
Daniel Sandler36412a72011-08-04 09:35:13 -040077import android.util.DisplayMetrics;
Chris Wren64161cc2012-12-17 16:49:30 -050078import android.util.EventLog;
Joe Onorato808182d2010-07-09 18:52:06 -040079import android.util.Log;
80import android.view.Display;
Jorim Jaggidf993512014-05-13 23:06:35 +020081import android.view.KeyEvent;
Jorim Jaggid4a57442014-04-10 02:45:55 +020082import android.view.LayoutInflater;
Joe Onorato808182d2010-07-09 18:52:06 -040083import android.view.MotionEvent;
Chris Craik2507c342015-05-04 14:36:49 -070084import android.view.ThreadedRenderer;
Joe Onorato808182d2010-07-09 18:52:06 -040085import android.view.View;
Xiyuan Xia1b30f792016-01-06 08:50:30 -080086import android.view.ViewGroup;
Jim Millerf2a16b22011-07-06 17:32:48 -070087import android.view.ViewGroup.LayoutParams;
Dan Sandler44c0dfd2014-06-09 11:26:16 -040088import android.view.ViewStub;
Joe Onorato808182d2010-07-09 18:52:06 -040089import android.view.WindowManager;
Jorim Jaggi786afcb2014-09-25 02:41:29 +020090import android.view.WindowManagerGlobal;
Daniel Sandlerd7e96862012-04-26 01:10:29 -040091import android.view.animation.AccelerateInterpolator;
Jorim Jaggib13d36d2014-06-06 18:03:52 +020092import android.view.animation.Interpolator;
Dan Sandler16128f42014-05-21 12:48:22 -040093import android.widget.ImageView;
Joe Onorato808182d2010-07-09 18:52:06 -040094import android.widget.TextView;
Chris Wren9763d422015-04-30 15:24:05 -040095import com.android.internal.logging.MetricsLogger;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050096import com.android.internal.logging.MetricsProto.MetricsEvent;
Chris Wrend1dbc922015-06-19 17:51:16 -040097import com.android.internal.statusbar.NotificationVisibility;
Joe Onorato808182d2010-07-09 18:52:06 -040098import com.android.internal.statusbar.StatusBarIcon;
Jorim Jaggi6b88cdf2014-12-22 20:56:50 +010099import com.android.keyguard.KeyguardHostView.OnDismissAction;
Jason Monkab525272015-07-13 17:02:49 -0400100import com.android.keyguard.KeyguardUpdateMonitor;
Jorim Jaggi007f0e82015-08-14 13:56:01 -0700101import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200102import com.android.keyguard.ViewMediatorCallback;
Jorim Jaggi708f7722014-08-20 17:30:38 +0200103import com.android.systemui.BatteryMeterView;
John Spurlock3c875662013-08-31 15:07:25 -0400104import com.android.systemui.DemoMode;
Jason Monk46dbfb42016-02-25 14:59:20 -0500105import com.android.systemui.DensityContainer;
106import com.android.systemui.DensityContainer.InflateListener;
Christoph Studerb0183992014-12-22 21:02:26 +0100107import com.android.systemui.EventLogConstants;
Chris Wren64161cc2012-12-17 16:49:30 -0500108import com.android.systemui.EventLogTags;
Winsonc0d70582016-01-29 10:24:39 -0800109import com.android.systemui.Interpolators;
Andrew Flynn82862572015-04-01 14:22:37 -0400110import com.android.systemui.Prefs;
Joe Onorato808182d2010-07-09 18:52:06 -0400111import com.android.systemui.R;
Xiaohui Chen5da71352016-02-22 10:04:41 -0800112import com.android.systemui.SystemUIFactory;
Selim Cineke70d6532015-04-24 16:46:13 -0700113import com.android.systemui.assist.AssistManager;
Adrian Roos401caae2016-03-04 13:35:21 -0800114import com.android.systemui.classifier.FalsingLog;
Selim Cinek5f71bee2015-11-18 10:25:23 -0800115import com.android.systemui.classifier.FalsingManager;
Jeff Brown4d69e222014-09-18 15:27:50 -0700116import com.android.systemui.doze.DozeHost;
John Spurlock813552c2014-09-19 08:30:21 -0400117import com.android.systemui.doze.DozeLog;
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200118import com.android.systemui.keyguard.KeyguardViewMediator;
Jason Monk162011e2016-02-19 08:11:55 -0500119import com.android.systemui.qs.QSContainer;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400120import com.android.systemui.qs.QSPanel;
Jorim Jaggid61f2272014-12-19 20:35:35 +0100121import com.android.systemui.recents.ScreenPinningRequest;
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800122import com.android.systemui.recents.events.EventBus;
Jorim Jaggi2adba072016-03-03 13:43:39 +0100123import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800124import com.android.systemui.recents.events.activity.UndockingTaskEvent;
Jorim Jaggidd98d412015-11-18 15:57:38 -0800125import com.android.systemui.stackdivider.Divider;
Jorim Jaggiea4a19f2016-02-03 21:31:27 -0800126import com.android.systemui.stackdivider.WindowManagerProxy;
Selim Cineka32ab602014-06-11 15:06:01 +0200127import com.android.systemui.statusbar.ActivatableNotificationView;
Selim Cineka0fad3b2014-09-19 17:20:05 +0200128import com.android.systemui.statusbar.BackDropView;
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500129import com.android.systemui.statusbar.BaseStatusBar;
Michael Jurkaa600fd92012-06-25 15:57:05 -0700130import com.android.systemui.statusbar.CommandQueue;
Dan Sandlereceda3d2014-07-21 15:35:01 -0400131import com.android.systemui.statusbar.DismissView;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200132import com.android.systemui.statusbar.DragDownHelper;
Jorim Jaggia2052ea2014-08-05 16:22:30 +0200133import com.android.systemui.statusbar.EmptyShadeView;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200134import com.android.systemui.statusbar.ExpandableNotificationRow;
Daniel Sandler33805342012-07-23 15:45:12 -0400135import com.android.systemui.statusbar.GestureRecorder;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200136import com.android.systemui.statusbar.KeyguardIndicationController;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700137import com.android.systemui.statusbar.NotificationData;
Daniel Sandler58b173b2012-05-03 11:25:29 -0400138import com.android.systemui.statusbar.NotificationData.Entry;
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200139import com.android.systemui.statusbar.NotificationOverflowContainer;
Adrian Roos1c0ca502015-10-07 12:20:42 -0700140import com.android.systemui.statusbar.RemoteInputController;
Selim Cineka0fad3b2014-09-19 17:20:05 +0200141import com.android.systemui.statusbar.ScrimView;
Christian Robertson2e347422011-08-11 14:01:04 -0700142import com.android.systemui.statusbar.SignalClusterView;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200143import com.android.systemui.statusbar.StatusBarState;
Christoph Studer2231c6e2014-12-19 12:40:13 +0100144import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200145import com.android.systemui.statusbar.policy.AccessibilityController;
Daniel Sandler2b697352011-07-22 16:23:09 -0400146import com.android.systemui.statusbar.policy.BatteryController;
John Spurlock0ff62e02014-07-22 16:15:08 -0400147import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400148import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
Adrian Roos5fd872e2014-08-12 17:28:58 +0200149import com.android.systemui.statusbar.policy.BrightnessMirrorController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400150import com.android.systemui.statusbar.policy.CastControllerImpl;
Adrian Roosb83777b2014-06-30 15:11:53 +0200151import com.android.systemui.statusbar.policy.FlashlightController;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700152import com.android.systemui.statusbar.policy.HeadsUpManager;
Jason Monk3d5f5512014-07-25 11:17:28 -0400153import com.android.systemui.statusbar.policy.HotspotControllerImpl;
John Spurlock657c62c2014-07-22 12:18:09 -0400154import com.android.systemui.statusbar.policy.KeyguardMonitor;
Adrian Roos8ddb2da2014-06-16 18:56:22 -0700155import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400156import com.android.systemui.statusbar.policy.LocationControllerImpl;
157import com.android.systemui.statusbar.policy.NetworkControllerImpl;
Jason Monk3d5f5512014-07-25 11:17:28 -0400158import com.android.systemui.statusbar.policy.NextAlarmController;
Jorim Jaggi85dc23c2014-09-08 14:42:29 +0200159import com.android.systemui.statusbar.policy.PreviewInflater;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400160import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
Jason Monk3d5f5512014-07-25 11:17:28 -0400161import com.android.systemui.statusbar.policy.SecurityControllerImpl;
162import com.android.systemui.statusbar.policy.UserInfoController;
Adrian Roos00a0b1f2014-07-16 16:44:49 +0200163import com.android.systemui.statusbar.policy.UserSwitcherController;
John Spurlock86005342014-05-23 11:58:00 -0400164import com.android.systemui.statusbar.policy.ZenModeController;
Selim Cinek67b22602014-03-10 15:40:16 +0100165import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Christoph Studer92b389d2014-04-01 18:44:40 +0200166import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
Jorim Jaggi37c11802015-08-18 20:27:54 -0700167import com.android.systemui.statusbar.stack.StackStateAnimator;
Selim Cinekb036ca42015-02-20 15:56:28 +0100168import com.android.systemui.statusbar.stack.StackViewState;
John Spurlock86005342014-05-23 11:58:00 -0400169import com.android.systemui.volume.VolumeComponent;
Selim Cinek67b22602014-03-10 15:40:16 +0100170
Daniel Sandler6a858c32012-03-12 14:38:58 -0400171import java.io.FileDescriptor;
172import java.io.PrintWriter;
173import java.util.ArrayList;
Christoph Studer92b389d2014-04-01 18:44:40 +0200174import java.util.Collection;
175import java.util.Collections;
Selim Cinekb5605e52015-02-20 18:21:41 +0100176import java.util.HashMap;
Dan Sandler16128f42014-05-21 12:48:22 -0400177import java.util.List;
John Spurlock7bbb9f62014-10-21 12:15:28 -0400178import java.util.Map;
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700179
180import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
181import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
182import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
183import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
184import static android.app.StatusBarManager.windowStateToString;
185import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
186import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
187import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
188import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
189import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
190import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
191import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
Daniel Sandler6a858c32012-03-12 14:38:58 -0400192
Jorim Jaggiecbab362014-04-23 16:13:15 +0200193public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Selim Cinek8d490d42015-04-10 00:05:50 -0700194 DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
195 HeadsUpManager.OnHeadsUpChangedListener {
Joe Onoratofd52b182010-11-10 18:00:52 -0800196 static final String TAG = "PhoneStatusBar";
Daniel Sandler198a0302012-08-17 16:04:31 -0400197 public static final boolean DEBUG = BaseStatusBar.DEBUG;
Chris Wren6d15a362013-08-20 18:46:29 -0400198 public static final boolean SPEW = false;
Daniel Sandler7579bca2011-08-18 15:47:26 -0400199 public static final boolean DUMPTRUCK = true; // extra dumpsys info
Daniel Sandlerfa027f52013-04-11 22:01:47 -0400200 public static final boolean DEBUG_GESTURES = false;
Dan Sandler16128f42014-05-21 12:48:22 -0400201 public static final boolean DEBUG_MEDIA = false;
202 public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
Joe Onorato808182d2010-07-09 18:52:06 -0400203
John Spurlock342cad72013-10-08 09:36:50 -0400204 public static final boolean DEBUG_WINDOW_STATE = false;
Daniel Sandlerb17a7262012-10-05 14:32:50 -0400205
Daniel Sandler96e61c3c82011-08-04 22:49:06 -0400206 // additional instrumentation for testing purposes; intended to be left on during development
Daniel Sandler7c351742011-10-17 10:48:06 -0400207 public static final boolean CHATTY = DEBUG;
Daniel Sandler96e61c3c82011-08-04 22:49:06 -0400208
Dan Sandler16128f42014-05-21 12:48:22 -0400209 public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
210
Adrian Roos8e3e8362015-07-16 19:42:22 -0700211 public static final String ACTION_FAKE_ARTWORK = "fake_artwork";
212
Daniel Sandler8ba33c92011-10-04 21:49:30 -0400213 private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
Daniel Sandler11cf1782012-09-27 14:03:08 -0400214 private static final int MSG_CLOSE_PANELS = 1001;
215 private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
Jorim Jaggi826730a2014-12-08 21:05:13 +0100216 private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003;
Winson Chungb1f74992014-08-08 12:53:09 -0700217 // 1020-1040 reserved for BaseStatusBar
Joe Onorato808182d2010-07-09 18:52:06 -0400218
Jorim Jaggi826730a2014-12-08 21:05:13 +0100219 // Time after we abort the launch transition.
220 private static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000;
221
Daniel Sandler8cc36e52011-10-17 14:18:46 -0400222 private static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
223
John Spurlocke1f366f2013-08-05 12:22:40 -0400224 private static final int STATUS_OR_NAV_TRANSIENT =
225 View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
John Spurlock32beb2c2013-03-11 10:16:47 -0400226 private static final long AUTOHIDE_TIMEOUT_MS = 3000;
John Spurlocke1f366f2013-08-05 12:22:40 -0400227
Christoph Studer92b389d2014-04-01 18:44:40 +0200228 /** The minimum delay in ms between reports of notification visibility. */
229 private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
230
Jorim Jaggi93a2bb22014-06-02 19:57:28 +0200231 /**
232 * The delay to reset the hint text when the hint animation is finished running.
233 */
234 private static final int HINT_RESET_DELAY_MS = 1200;
235
John Spurlock7b414672014-07-18 13:02:39 -0400236 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
237 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
238 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
239 .build();
240
Selim Cinekbaa23272014-07-08 18:01:07 +0200241 public static final int FADE_KEYGUARD_START_DELAY = 100;
242 public static final int FADE_KEYGUARD_DURATION = 300;
Jorim Jaggi90978852015-08-18 19:55:53 -0700243 public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
Selim Cinekbaa23272014-07-08 18:01:07 +0200244
Jason Monk815e0572014-08-12 17:26:36 -0400245 /** Allow some time inbetween the long press for back and recents. */
246 private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
247
Adrian Roos2f2bd9a2015-06-04 18:11:14 -0700248 /** If true, the system is in the half-boot-to-decryption-screen state.
249 * Prudently disable QS and notifications. */
Adrian Roos21d2a252015-06-01 13:59:59 -0700250 private static final boolean ONLY_CORE_APPS;
251
Adrian Roos52738322016-01-29 08:49:21 -0800252 /** If true, the lockscreen will show a distinct wallpaper */
Adrian Roose381c162016-02-11 15:26:42 -0800253 private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
Adrian Roos52738322016-01-29 08:49:21 -0800254
Vladislav Kaznacheev38f426c2015-10-28 15:48:12 -0700255 /* If true, the device supports freeform window management.
256 * This affects the status bar UI. */
257 private static final boolean FREEFORM_WINDOW_MANAGEMENT;
258
Adrian Roos21d2a252015-06-01 13:59:59 -0700259 static {
260 boolean onlyCoreApps;
Vladislav Kaznacheev38f426c2015-10-28 15:48:12 -0700261 boolean freeformWindowManagement;
Adrian Roos21d2a252015-06-01 13:59:59 -0700262 try {
Vladislav Kaznacheev38f426c2015-10-28 15:48:12 -0700263 IPackageManager packageManager =
264 IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
265 onlyCoreApps = packageManager.isOnlyCoreApps();
266 freeformWindowManagement = packageManager.hasSystemFeature(
Jeff Sharkey115d2c12016-02-15 17:25:57 -0700267 PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT, 0);
Adrian Roos21d2a252015-06-01 13:59:59 -0700268 } catch (RemoteException e) {
269 onlyCoreApps = false;
Vladislav Kaznacheev38f426c2015-10-28 15:48:12 -0700270 freeformWindowManagement = false;
Adrian Roos21d2a252015-06-01 13:59:59 -0700271 }
272 ONLY_CORE_APPS = onlyCoreApps;
Vladislav Kaznacheev38f426c2015-10-28 15:48:12 -0700273 FREEFORM_WINDOW_MANAGEMENT = freeformWindowManagement;
Adrian Roos21d2a252015-06-01 13:59:59 -0700274 }
275
Joe Onoratofd52b182010-11-10 18:00:52 -0800276 PhoneStatusBarPolicy mIconPolicy;
Joe Onorato808182d2010-07-09 18:52:06 -0400277
Daniel Sandler2b697352011-07-22 16:23:09 -0400278 // These are no longer handled by the policy, because we need custom strategies for them
John Spurlockaf8d6c42014-05-07 17:49:08 -0400279 BluetoothControllerImpl mBluetoothController;
Jason Monk3d5f5512014-07-25 11:17:28 -0400280 SecurityControllerImpl mSecurityController;
Xiaohui Chen8bdcd1f2016-01-19 13:52:07 -0800281 protected BatteryController mBatteryController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400282 LocationControllerImpl mLocationController;
283 NetworkControllerImpl mNetworkController;
Jason Monk51e4dc02014-07-22 12:00:47 -0400284 HotspotControllerImpl mHotspotController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400285 RotationLockControllerImpl mRotationLockController;
Jorim Jaggi3d878be2014-05-10 03:22:32 +0200286 UserInfoController mUserInfoController;
John Spurlock86005342014-05-23 11:58:00 -0400287 ZenModeController mZenModeController;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400288 CastControllerImpl mCastController;
John Spurlock86005342014-05-23 11:58:00 -0400289 VolumeComponent mVolumeComponent;
Adrian Roos8ddb2da2014-06-16 18:56:22 -0700290 KeyguardUserSwitcher mKeyguardUserSwitcher;
Adrian Roosb83777b2014-06-30 15:11:53 +0200291 FlashlightController mFlashlightController;
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800292 protected UserSwitcherController mUserSwitcherController;
Jorim Jaggic7dea6e2014-07-26 14:36:57 +0200293 NextAlarmController mNextAlarmController;
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800294 protected KeyguardMonitor mKeyguardMonitor;
Adrian Roos5fd872e2014-08-12 17:28:58 +0200295 BrightnessMirrorController mBrightnessMirrorController;
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200296 AccessibilityController mAccessibilityController;
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -0700297 FingerprintUnlockController mFingerprintUnlockController;
Jorim Jaggi86905582016-02-09 21:36:09 -0800298 LightStatusBarController mLightStatusBarController;
Vadim Tryshev12a30e82016-02-12 15:39:28 -0800299 protected LockscreenWallpaper mLockscreenWallpaper;
Jim Miller5e6af442011-12-02 18:24:26 -0800300
Daniel Sandler7c3e39d2011-07-29 16:30:49 -0400301 int mNaturalBarHeight = -1;
Jorim Jaggi66ac1332015-01-21 19:22:26 +0100302
Joe Onorato808182d2010-07-09 18:52:06 -0400303 Display mDisplay;
Daniel Sandlere680f542012-09-28 12:22:27 -0400304 Point mCurrentDisplaySize = new Point();
Joe Onorato808182d2010-07-09 18:52:06 -0400305
Xiaohui Chend839d1a2016-01-21 13:05:02 -0800306 protected StatusBarWindowView mStatusBarWindow;
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700307 protected PhoneStatusBarView mStatusBarView;
John Spurlockd4e65752013-08-28 14:17:09 -0400308 private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800309 protected StatusBarWindowManager mStatusBarWindowManager;
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200310 private UnlockMethodCache mUnlockMethodCache;
John Spurlockbf370992014-06-17 13:58:31 -0400311 private DozeServiceHost mDozeServiceHost;
Jorim Jaggi50ff3af2015-08-12 18:35:42 -0700312 private boolean mWakeUpComingFromTouch;
313 private PointF mWakeUpTouchLocation;
Selim Cinek1b6f8192015-09-03 16:01:53 -0700314 private boolean mScreenTurningOn;
Daniel Sandlera310af82012-04-24 01:20:13 -0400315
Joe Onorato808182d2010-07-09 18:52:06 -0400316 int mPixelFormat;
Joe Onorato808182d2010-07-09 18:52:06 -0400317 Object mQueueLock = new Object();
318
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700319 protected StatusBarIconController mIconController;
Joe Onorato808182d2010-07-09 18:52:06 -0400320
321 // expanded notifications
Xiaohui Chenea4b6ba2016-02-18 10:53:17 -0800322 protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
Joe Onorato808182d2010-07-09 18:52:06 -0400323 View mExpandedContents;
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400324 TextView mNotificationPanelDebugText;
Daniel Sandler21b274e2012-05-02 15:07:51 -0400325
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400326 // settings
John Spurlockaf8d6c42014-05-07 17:49:08 -0400327 private QSPanel mQSPanel;
Daniel Sandler8e72c9e2012-08-15 00:09:26 -0400328
Joe Onorato808182d2010-07-09 18:52:06 -0400329 // top bar
Jason Monk0e1101d2015-10-07 13:06:09 -0400330 BaseStatusBarHeader mHeader;
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700331 protected KeyguardStatusBarView mKeyguardStatusBar;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200332 View mKeyguardStatusView;
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200333 KeyguardBottomAreaView mKeyguardBottomArea;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200334 boolean mLeaveOpenOnKeyguardHide;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200335 KeyguardIndicationController mKeyguardIndicationController;
Jorim Jaggie70d31f2014-04-24 22:08:30 +0200336
Adrian Roos46df1ca2015-09-11 12:38:43 -0700337 // Keyguard is going away soon.
338 private boolean mKeyguardGoingAway;
339 // Keyguard is actually fading away now.
Jorim Jaggi44cf9192014-06-17 19:16:00 -0700340 private boolean mKeyguardFadingAway;
341 private long mKeyguardFadingAwayDelay;
342 private long mKeyguardFadingAwayDuration;
343
Adrian Roos3aec6382016-02-05 14:19:01 -0800344 // RemoteInputView to be activated after unlock
345 private View mPendingRemoteInputView;
346
Selim Cinek5f71bee2015-11-18 10:25:23 -0800347 int mMaxAllowedKeyguardNotifications;
Daniel Sandlerd3090562011-08-09 00:28:44 -0400348
Joe Onorato808182d2010-07-09 18:52:06 -0400349 boolean mExpandedVisible;
350
John Spurlockd4e65752013-08-28 14:17:09 -0400351 private int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400352
Joe Onorato808182d2010-07-09 18:52:06 -0400353 // the tracker view
Joe Onorato808182d2010-07-09 18:52:06 -0400354 int mTrackingPosition; // the position of the top of the tracking view.
Joe Onorato808182d2010-07-09 18:52:06 -0400355
Joe Onorato808182d2010-07-09 18:52:06 -0400356 // Tracking finger for opening/closing.
Joe Onorato808182d2010-07-09 18:52:06 -0400357 boolean mTracking;
Joe Onorato808182d2010-07-09 18:52:06 -0400358
Joe Onorato808182d2010-07-09 18:52:06 -0400359 int[] mAbsPos = new int[2];
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200360 ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>();
Chet Haase2f2022a2011-10-11 06:41:59 -0700361
Joe Onorato808182d2010-07-09 18:52:06 -0400362 // for disabling the status bar
Benjamin Franzcde0a2a2015-04-23 17:19:48 +0100363 int mDisabled1 = 0;
364 int mDisabled2 = 0;
Joe Onorato808182d2010-07-09 18:52:06 -0400365
Daniel Sandler60ee2562011-07-22 12:34:33 -0400366 // tracking calls to View.setSystemUiVisibility()
367 int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
Jorim Jaggi86905582016-02-09 21:36:09 -0800368 private final Rect mLastFullscreenStackBounds = new Rect();
369 private final Rect mLastDockedStackBounds = new Rect();
Daniel Sandler60ee2562011-07-22 12:34:33 -0400370
Adrian Roos389beec2015-05-12 13:33:25 -0700371 // last value sent to window manager
372 private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
373
Daniel Sandler36412a72011-08-04 09:35:13 -0400374 DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Dianne Hackborn1dacf272011-08-02 15:01:22 -0700375
Daniel Sandler33805342012-07-23 15:45:12 -0400376 // XXX: gesture research
Daniel Sandler151f00d2012-10-02 22:33:08 -0400377 private final GestureRecorder mGestureRec = DEBUG_GESTURES
John Spurlock209bede2013-07-17 12:23:27 -0400378 ? new GestureRecorder("/sdcard/statusbar_gestures.dat")
Daniel Sandler151f00d2012-10-02 22:33:08 -0400379 : null;
Daniel Sandler33805342012-07-23 15:45:12 -0400380
Jason Monk18f99d92014-09-11 13:36:42 -0400381 private ScreenPinningRequest mScreenPinningRequest;
382
Daniel Sandler328310c2011-09-23 15:56:52 -0400383 private int mNavigationIconHints = 0;
Jason Monk4ae97d32014-12-17 10:14:33 -0500384 private HandlerThread mHandlerThread;
Daniel Sandler328310c2011-09-23 15:56:52 -0400385
John Spurlock919adac2012-10-02 16:41:12 -0400386 // ensure quick settings is disabled until the current user makes it through the setup wizard
387 private boolean mUserSetup = false;
388 private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
389 @Override
390 public void onChange(boolean selfChange) {
391 final boolean userSetup = 0 != Settings.Secure.getIntForUser(
392 mContext.getContentResolver(),
393 Settings.Secure.USER_SETUP_COMPLETE,
394 0 /*default */,
395 mCurrentUserId);
John Spurlockcd686b52013-06-05 10:13:46 -0400396 if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " +
John Spurlocke4e8c562012-10-04 09:55:01 -0400397 "selfChange=%s userSetup=%s mUserSetup=%s",
398 selfChange, userSetup, mUserSetup));
John Spurlock73203eb2014-04-15 16:14:46 -0400399
John Spurlock919adac2012-10-02 16:41:12 -0400400 if (userSetup != mUserSetup) {
401 mUserSetup = userSetup;
John Spurlock919adac2012-10-02 16:41:12 -0400402 if (!mUserSetup && mStatusBarView != null)
403 animateCollapseQuickSettings();
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700404 if (mKeyguardBottomArea != null) {
405 mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
406 }
John Spurlock919adac2012-10-02 16:41:12 -0400407 }
John Spurlock604a5ee2015-06-01 12:27:22 -0400408 if (mIconPolicy != null) {
409 mIconPolicy.setCurrentUserSetup(mUserSetup);
410 }
John Spurlock919adac2012-10-02 16:41:12 -0400411 }
412 };
413
Chris Wrenf6e83f42013-09-11 14:02:59 -0400414 final private ContentObserver mHeadsUpObserver = new ContentObserver(mHandler) {
415 @Override
416 public void onChange(boolean selfChange) {
417 boolean wasUsing = mUseHeadsUp;
Jason Monkf7019542014-07-31 12:42:25 -0400418 mUseHeadsUp = ENABLE_HEADS_UP && !mDisableNotificationAlerts
419 && Settings.Global.HEADS_UP_OFF != Settings.Global.getInt(
Chris Wren10d82df2014-03-01 10:34:51 -0500420 mContext.getContentResolver(), Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
Chris Wren7bd241232014-02-28 16:25:05 -0500421 Settings.Global.HEADS_UP_OFF);
Chris Wren22ae46e2014-02-26 18:08:09 -0500422 mHeadsUpTicker = mUseHeadsUp && 0 != Settings.Global.getInt(
423 mContext.getContentResolver(), SETTING_HEADS_UP_TICKER, 0);
Chris Wrenf6e83f42013-09-11 14:02:59 -0400424 Log.d(TAG, "heads up is " + (mUseHeadsUp ? "enabled" : "disabled"));
425 if (wasUsing != mUseHeadsUp) {
426 if (!mUseHeadsUp) {
427 Log.d(TAG, "dismissing any existing heads up notification on disable event");
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700428 mHeadsUpManager.releaseAllImmediately();
Chris Wrenf6e83f42013-09-11 14:02:59 -0400429 }
430 }
431 }
432 };
433
John Spurlockcfc359a2013-09-05 10:42:03 -0400434 private int mInteractingWindows;
John Spurlock32beb2c2013-03-11 10:16:47 -0400435 private boolean mAutohideSuspended;
John Spurlockd4e65752013-08-28 14:17:09 -0400436 private int mStatusBarMode;
437 private int mNavigationBarMode;
Selim Cinek5f71bee2015-11-18 10:25:23 -0800438 private int mMaxKeyguardNotifications;
Jorim Jaggid41083a2014-09-12 02:54:40 +0200439
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200440 private ViewMediatorCallback mKeyguardViewMediatorCallback;
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800441 protected ScrimController mScrimController;
442 protected DozeScrimController mDozeScrimController;
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200443
John Spurlock32beb2c2013-03-11 10:16:47 -0400444 private final Runnable mAutohide = new Runnable() {
445 @Override
446 public void run() {
John Spurlocke1f366f2013-08-05 12:22:40 -0400447 int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT;
John Spurlock9deaa282013-07-25 13:03:47 -0400448 if (mSystemUiVisibility != requested) {
449 notifyUiVisibilityChanged(requested);
450 }
John Spurlock32beb2c2013-03-11 10:16:47 -0400451 }};
452
Jorim Jaggi44cf9192014-06-17 19:16:00 -0700453 private boolean mWaitingForKeyguardExit;
John Spurlockbf370992014-06-17 13:58:31 -0400454 private boolean mDozing;
Jorim Jaggi83969702015-06-05 14:59:24 -0700455 private boolean mDozingRequested;
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800456 protected boolean mScrimSrcModeEnabled;
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100457
Selim Cinekc18010f2016-01-20 13:41:30 -0800458 public static final Interpolator ALPHA_IN = Interpolators.ALPHA_IN;
459 public static final Interpolator ALPHA_OUT = Interpolators.ALPHA_OUT;
Jorim Jaggib13d36d2014-06-06 18:03:52 +0200460
Selim Cineka0fad3b2014-09-19 17:20:05 +0200461 private BackDropView mBackdrop;
Dan Sandler16128f42014-05-21 12:48:22 -0400462 private ImageView mBackdropFront, mBackdropBack;
Selim Cineka0fad3b2014-09-19 17:20:05 +0200463 private PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
464 private PorterDuffXfermode mSrcOverXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER);
Dan Sandler16128f42014-05-21 12:48:22 -0400465
466 private MediaSessionManager mMediaSessionManager;
467 private MediaController mMediaController;
468 private String mMediaNotificationKey;
469 private MediaMetadata mMediaMetadata;
470 private MediaController.Callback mMediaListener
471 = new MediaController.Callback() {
472 @Override
473 public void onPlaybackStateChanged(PlaybackState state) {
474 super.onPlaybackStateChanged(state);
475 if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state);
Julia Reynoldsd30e42d2015-07-20 17:02:14 -0400476 if (state != null) {
477 if (!isPlaybackActive(state.getState())) {
478 clearCurrentMediaNotification();
Adrian Roos52738322016-01-29 08:49:21 -0800479 updateMediaMetaData(true, true);
Julia Reynoldsd30e42d2015-07-20 17:02:14 -0400480 }
481 }
Dan Sandler16128f42014-05-21 12:48:22 -0400482 }
483
484 @Override
485 public void onMetadataChanged(MediaMetadata metadata) {
486 super.onMetadataChanged(metadata);
487 if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata);
488 mMediaMetadata = metadata;
Adrian Roos52738322016-01-29 08:49:21 -0800489 updateMediaMetaData(true, true);
Dan Sandler16128f42014-05-21 12:48:22 -0400490 }
491 };
492
493 private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
494 new OnChildLocationsChangedListener() {
495 @Override
496 public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout) {
497 userActivity();
498 }
499 };
500
Benjamin Franzcde0a2a2015-04-23 17:19:48 +0100501 private int mDisabledUnmodified1;
502 private int mDisabledUnmodified2;
Jorim Jaggib13d36d2014-06-06 18:03:52 +0200503
Christoph Studer92b389d2014-04-01 18:44:40 +0200504 /** Keys of notifications currently visible to the user. */
Chris Wrend1dbc922015-06-19 17:51:16 -0400505 private final ArraySet<NotificationVisibility> mCurrentlyVisibleNotifications =
506 new ArraySet<>();
Christoph Studer92b389d2014-04-01 18:44:40 +0200507 private long mLastVisibilityReportUptimeMs;
508
John Spurlockbf370992014-06-17 13:58:31 -0400509 private final ShadeUpdates mShadeUpdates = new ShadeUpdates();
510
Selim Cinekbaa23272014-07-08 18:01:07 +0200511 private Runnable mLaunchTransitionEndRunnable;
512 private boolean mLaunchTransitionFadingAway;
Jorim Jaggidbc3dce2014-08-01 01:16:36 +0200513 private ExpandableNotificationRow mDraggedDownRow;
Selim Cinek372d1bd2015-08-14 13:19:37 -0700514 private boolean mLaunchCameraOnScreenTurningOn;
Jorim Jaggi18f18ae2015-09-10 15:48:21 -0700515 private boolean mLaunchCameraOnFinishedGoingToSleep;
Jorim Jaggi40aa8812015-09-23 12:59:22 -0700516 private int mLastCameraLaunchSource;
Selim Cinek372d1bd2015-08-14 13:19:37 -0700517 private PowerManager.WakeLock mGestureWakeLock;
Selim Cinek69ff8af2015-08-25 19:03:48 -0700518 private Vibrator mVibrator;
Jorim Jaggi362dd6d2014-07-09 19:04:07 +0200519
Christoph Studer2231c6e2014-12-19 12:40:13 +0100520 // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
521 private int mLastLoggedStateFingerprint;
522
Jorim Jaggi18f18ae2015-09-10 15:48:21 -0700523 /**
524 * If set, the device has started going to sleep but isn't fully non-interactive yet.
525 */
526 protected boolean mStartedGoingToSleep;
527
Selim Cinek3776fe02016-02-04 13:32:43 -0800528 private static final int VISIBLE_LOCATIONS = StackViewState.LOCATION_FIRST_HUN
Chris Wren35a7c922015-06-22 16:31:01 -0400529 | StackViewState.LOCATION_MAIN_AREA;
Christoph Studer92b389d2014-04-01 18:44:40 +0200530
531 private final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
532 new OnChildLocationsChangedListener() {
533 @Override
534 public void onChildLocationsChanged(
535 NotificationStackScrollLayout stackScrollLayout) {
536 if (mHandler.hasCallbacks(mVisibilityReporter)) {
537 // Visibilities will be reported when the existing
538 // callback is executed.
539 return;
540 }
541 // Calculate when we're allowed to run the visibility
542 // reporter. Note that this timestamp might already have
543 // passed. That's OK, the callback will just be executed
544 // ASAP.
545 long nextReportUptimeMs =
546 mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS;
547 mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs);
548 }
549 };
550
551 // Tracks notifications currently visible in mNotificationStackScroller and
552 // emits visibility events via NoMan on changes.
553 private final Runnable mVisibilityReporter = new Runnable() {
Chris Wrend1dbc922015-06-19 17:51:16 -0400554 private final ArraySet<NotificationVisibility> mTmpNewlyVisibleNotifications =
555 new ArraySet<>();
556 private final ArraySet<NotificationVisibility> mTmpCurrentlyVisibleNotifications =
557 new ArraySet<>();
558 private final ArraySet<NotificationVisibility> mTmpNoLongerVisibleNotifications =
559 new ArraySet<>();
Christoph Studer92b389d2014-04-01 18:44:40 +0200560
561 @Override
562 public void run() {
563 mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
Chris Wrend1dbc922015-06-19 17:51:16 -0400564 final String mediaKey = getCurrentMediaNotificationKey();
Christoph Studer92b389d2014-04-01 18:44:40 +0200565
566 // 1. Loop over mNotificationData entries:
567 // A. Keep list of visible notifications.
568 // B. Keep list of previously hidden, now visible notifications.
569 // 2. Compute no-longer visible notifications by removing currently
570 // visible notifications from the set of previously visible
571 // notifications.
572 // 3. Report newly visible and no-longer visible notifications.
573 // 4. Keep currently visible notifications for next report.
Christoph Studerc8db24b2014-07-25 17:50:30 +0200574 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
575 int N = activeNotifications.size();
Christoph Studer92b389d2014-04-01 18:44:40 +0200576 for (int i = 0; i < N; i++) {
Christoph Studerc8db24b2014-07-25 17:50:30 +0200577 Entry entry = activeNotifications.get(i);
Christoph Studer92b389d2014-04-01 18:44:40 +0200578 String key = entry.notification.getKey();
Chris Wrend1dbc922015-06-19 17:51:16 -0400579 boolean isVisible =
Christoph Studer92b389d2014-04-01 18:44:40 +0200580 (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0;
Chris Wrend1dbc922015-06-19 17:51:16 -0400581 NotificationVisibility visObj = NotificationVisibility.obtain(key, i, isVisible);
582 boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(visObj);
583 if (isVisible) {
Christoph Studer92b389d2014-04-01 18:44:40 +0200584 // Build new set of visible notifications.
Chris Wrend1dbc922015-06-19 17:51:16 -0400585 mTmpCurrentlyVisibleNotifications.add(visObj);
586 if (!previouslyVisible) {
587 mTmpNewlyVisibleNotifications.add(visObj);
588 }
589 } else {
590 // release object
591 visObj.recycle();
Christoph Studer92b389d2014-04-01 18:44:40 +0200592 }
593 }
Chris Wrend1dbc922015-06-19 17:51:16 -0400594 mTmpNoLongerVisibleNotifications.addAll(mCurrentlyVisibleNotifications);
595 mTmpNoLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
Christoph Studer92b389d2014-04-01 18:44:40 +0200596
597 logNotificationVisibilityChanges(
Chris Wrend1dbc922015-06-19 17:51:16 -0400598 mTmpNewlyVisibleNotifications, mTmpNoLongerVisibleNotifications);
Christoph Studer92b389d2014-04-01 18:44:40 +0200599
Chris Wrend1dbc922015-06-19 17:51:16 -0400600 recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
Christoph Studer92b389d2014-04-01 18:44:40 +0200601 mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
602
Chris Wrend1dbc922015-06-19 17:51:16 -0400603 recycleAllVisibilityObjects(mTmpNoLongerVisibleNotifications);
Christoph Studer92b389d2014-04-01 18:44:40 +0200604 mTmpCurrentlyVisibleNotifications.clear();
Chris Wrend1dbc922015-06-19 17:51:16 -0400605 mTmpNewlyVisibleNotifications.clear();
606 mTmpNoLongerVisibleNotifications.clear();
Christoph Studer92b389d2014-04-01 18:44:40 +0200607 }
608 };
609
Chris Wrend1dbc922015-06-19 17:51:16 -0400610 private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
611 final int N = array.size();
612 for (int i = 0 ; i < N; i++) {
613 array.valueAt(i).recycle();
614 }
615 array.clear();
616 }
617
Jorim Jaggiecbab362014-04-23 16:13:15 +0200618 private final View.OnClickListener mOverflowClickListener = new View.OnClickListener() {
619 @Override
620 public void onClick(View v) {
621 goToLockedShade(null);
622 }
623 };
Selim Cinekb5605e52015-02-20 18:21:41 +0100624 private HashMap<ExpandableNotificationRow, List<ExpandableNotificationRow>> mTmpChildOrderMap
625 = new HashMap<>();
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700626 private RankingMap mLatestRankingMap;
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -0700627 private boolean mNoAnimationOnNextBarModeChange;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700628 private FalsingManager mFalsingManager;
Jorim Jaggiecbab362014-04-23 16:13:15 +0200629
Joe Onorato808182d2010-07-09 18:52:06 -0400630 @Override
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400631 public void start() {
632 mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
633 .getDefaultDisplay();
Daniel Sandler7e8ae502013-10-10 23:38:19 -0400634 updateDisplaySize();
Jorim Jaggi0e664392014-09-27 01:30:22 +0200635 mScrimSrcModeEnabled = mContext.getResources().getBoolean(
636 R.bool.config_status_bar_scrim_behind_use_src);
Adrian Roos75fa3852015-01-27 20:21:44 +0100637
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -0500638 super.start(); // calls createAndAddWindows()
Joe Onorato808182d2010-07-09 18:52:06 -0400639
Dan Sandler16128f42014-05-21 12:48:22 -0400640 mMediaSessionManager
641 = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
642 // TODO: use MediaSessionManager.SessionListener to hook us up to future updates
643 // in session state
644
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400645 addNavigationBar();
646
Joe Onorato808182d2010-07-09 18:52:06 -0400647 // Lastly, call to the icon policy to install/update all the icons.
Jason Monk07473ce2016-01-05 14:59:19 -0500648 mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController, mCastController,
Jason Monk3e189872016-01-12 09:10:34 -0500649 mHotspotController, mUserInfoController, mBluetoothController,
Jason Monkf23aa992016-01-22 16:45:21 -0500650 mRotationLockController, mNetworkController.getDataSaverController());
John Spurlock604a5ee2015-06-01 12:27:22 -0400651 mIconPolicy.setCurrentUserSetup(mUserSetup);
John Spurlocke677d712014-02-13 12:52:19 -0500652 mSettingsObserver.onChange(false); // set up
Chris Wrenf6e83f42013-09-11 14:02:59 -0400653
654 mHeadsUpObserver.onChange(true); // set up
655 if (ENABLE_HEADS_UP) {
656 mContext.getContentResolver().registerContentObserver(
Chris Wren10d82df2014-03-01 10:34:51 -0500657 Settings.Global.getUriFor(Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED), true,
Chris Wrenf6e83f42013-09-11 14:02:59 -0400658 mHeadsUpObserver);
Chris Wren22ae46e2014-02-26 18:08:09 -0500659 mContext.getContentResolver().registerContentObserver(
660 Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
661 mHeadsUpObserver);
Chris Wrenf6e83f42013-09-11 14:02:59 -0400662 }
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +0200663 mUnlockMethodCache = UnlockMethodCache.getInstance(mContext);
Christoph Studer2231c6e2014-12-19 12:40:13 +0100664 mUnlockMethodCache.addListener(this);
Jorim Jaggi5cf17872014-03-26 18:31:48 +0100665 startKeyguard();
John Spurlockbf370992014-06-17 13:58:31 -0400666
667 mDozeServiceHost = new DozeServiceHost();
Jorim Jaggi007f0e82015-08-14 13:56:01 -0700668 KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mDozeServiceHost);
Jeff Brown4d69e222014-09-18 15:27:50 -0700669 putComponent(DozeHost.class, mDozeServiceHost);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +0200670 putComponent(PhoneStatusBar.class, this);
John Spurlock89f060a2014-07-16 21:03:15 -0400671
672 setControllerUsers();
Chris Wrencd8f4f72014-08-27 18:48:13 -0400673
674 notifyUserAboutHiddenNotifications();
Jason Monk18f99d92014-09-11 13:36:42 -0400675
676 mScreenPinningRequest = new ScreenPinningRequest(mContext);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -0700677 mFalsingManager = FalsingManager.getInstance(mContext);
Joe Onorato808182d2010-07-09 18:52:06 -0400678 }
679
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700680 protected void createIconController() {
681 mIconController = new StatusBarIconController(
682 mContext, mStatusBarView, mKeyguardStatusBar, this);
683 }
684
Joe Onorato808182d2010-07-09 18:52:06 -0400685 // ================================================================================
686 // Constructing the view
687 // ================================================================================
Jim Millere898ac52012-04-06 17:10:57 -0700688 protected PhoneStatusBarView makeStatusBarView() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -0400689 final Context context = mContext;
Joe Onorato808182d2010-07-09 18:52:06 -0400690
Daniel Sandler6e8db882011-10-26 15:40:51 -0400691 updateDisplaySize(); // populates mDisplayMetrics
Jorim Jaggi2e115c52014-07-01 21:27:58 +0200692 updateResources();
Joe Onorato808182d2010-07-09 18:52:06 -0400693
Xiaohui Chend839d1a2016-01-21 13:05:02 -0800694 inflateStatusBarWindow(context);
Selim Cinek4e6b2d32015-06-25 20:15:33 -0400695 mStatusBarWindow.setService(this);
Daniel Sandler21b274e2012-05-02 15:07:51 -0400696 mStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {
697 @Override
698 public boolean onTouch(View v, MotionEvent event) {
John Spurlock9deaa282013-07-25 13:03:47 -0400699 checkUserAutohide(v, event);
Daniel Sandler21b274e2012-05-02 15:07:51 -0400700 if (event.getAction() == MotionEvent.ACTION_DOWN) {
Daniel Sandler37a38aa2013-02-13 17:15:57 -0500701 if (mExpandedVisible) {
Daniel Sandler11cf1782012-09-27 14:03:08 -0400702 animateCollapsePanels();
Daniel Sandler21b274e2012-05-02 15:07:51 -0400703 }
704 }
Chris Wren5de6e942012-05-16 14:22:21 -0400705 return mStatusBarWindow.onTouchEvent(event);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700706 }
707 });
Daniel Sandler21b274e2012-05-02 15:07:51 -0400708
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100709 mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
710 R.id.notification_panel);
Daniel Sandler040c2e42012-10-17 00:56:33 -0400711 mNotificationPanel.setStatusBar(this);
Selim Cinek53f8e7d2016-03-25 02:28:01 -0700712 mNotificationPanel.setGroupManager(mGroupManager);
Joe Onorato808182d2010-07-09 18:52:06 -0400713
Xiaohui Chen9f967112016-01-07 14:14:06 -0800714 mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
715 mStatusBarView.setBar(this);
716 mStatusBarView.setPanel(mNotificationPanel);
717
Jeff Brown98365d72012-08-19 20:30:52 -0700718 if (!ActivityManager.isHighEndGfx()) {
Romain Guy328b3582012-05-08 15:30:57 -0700719 mStatusBarWindow.setBackground(null);
Alan Viverette4a357cd2015-03-18 18:37:18 -0700720 mNotificationPanel.setBackground(new FastColorDrawable(context.getColor(
Romain Guy648342f2012-05-25 10:44:45 -0700721 R.color.notification_panel_solid_background)));
Romain Guy328b3582012-05-08 15:30:57 -0700722 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700723
Selim Cinek83bc7832015-10-22 13:26:54 -0700724 mHeadsUpManager = new HeadsUpManager(context, mStatusBarWindow, mGroupManager);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700725 mHeadsUpManager.setBar(this);
726 mHeadsUpManager.addListener(this);
727 mHeadsUpManager.addListener(mNotificationPanel);
Selim Cinekef5127e2015-12-21 16:55:58 -0800728 mHeadsUpManager.addListener(mGroupManager);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700729 mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
Selim Cinekfbe9a442015-04-13 16:09:49 -0700730 mNotificationData.setHeadsUpManager(mHeadsUpManager);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700731
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400732 if (MULTIUSER_DEBUG) {
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100733 mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
734 R.id.header_debug_info);
Daniel Sandlerb9301c32012-08-14 15:08:24 -0400735 mNotificationPanelDebugText.setVisibility(View.VISIBLE);
736 }
Joe Onorato808182d2010-07-09 18:52:06 -0400737
Daniel Sandler0129b312011-05-11 11:54:11 -0400738 try {
Jeff Brown98365d72012-08-19 20:30:52 -0700739 boolean showNav = mWindowManagerService.hasNavigationBar();
John Spurlockcd686b52013-06-05 10:13:46 -0400740 if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
Daniel Sandler0129b312011-05-11 11:54:11 -0400741 if (showNav) {
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800742 createNavigationBarView(context);
Daniel Sandler0129b312011-05-11 11:54:11 -0400743 }
Daniel Sandler0c4ccff2011-10-19 16:39:14 -0400744 } catch (RemoteException ex) {
745 // no window manager? good luck with that
Daniel Sandler0129b312011-05-11 11:54:11 -0400746 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400747
Selim Cineke70d6532015-04-24 16:46:13 -0700748 mAssistManager = new AssistManager(this, context);
749
Joe Onorato808182d2010-07-09 18:52:06 -0400750 // figure out which pixel-format to use for the status bar.
Daniel Sandlerf733c2a2011-09-25 15:03:40 -0400751 mPixelFormat = PixelFormat.OPAQUE;
Daniel Sandler173bae22012-09-25 14:37:42 -0400752
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100753 mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
754 R.id.notification_stack_scroller);
755 mStackScroller.setLongPressListener(getNotificationLongClicker());
Mady Mellor4b80b102016-01-22 08:03:58 -0800756 mStackScroller.setGearDisplayedListener(getGearDisplayedListener());
Selim Cinek19c8c702014-08-25 22:09:19 +0200757 mStackScroller.setPhoneStatusBar(this);
Selim Cinekb5605e52015-02-20 18:21:41 +0100758 mStackScroller.setGroupManager(mGroupManager);
Selim Cinekb8f09cf2015-03-16 17:09:28 -0700759 mStackScroller.setHeadsUpManager(mHeadsUpManager);
Selim Cinekb5605e52015-02-20 18:21:41 +0100760 mGroupManager.setOnGroupChangeListener(mStackScroller);
Selim Cinek80a14e52014-03-27 16:58:04 +0100761
Jorim Jaggic5dc0d02014-04-15 15:42:55 +0200762 mKeyguardIconOverflowContainer =
763 (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
764 R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
765 mKeyguardIconOverflowContainer.setOnActivatedListener(this);
Jorim Jaggie96fcd12014-05-07 21:10:35 +0200766 mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
Selim Cinek2cd45df2015-06-09 18:00:07 -0700767 mStackScroller.setOverflowContainer(mKeyguardIconOverflowContainer);
Jorim Jaggid4a57442014-04-10 02:45:55 +0200768
Selim Cinek4fd5dfc2016-01-19 15:16:15 -0800769
Selim Cinek01af3342016-02-09 19:25:31 -0800770 inflateEmptyShadeView();
771 inflateDismissView();
Selim Cinekb6d85eb2014-03-28 20:21:01 +0100772 mExpandedContents = mStackScroller;
Selim Cinek67b22602014-03-10 15:40:16 +0100773
Selim Cineka0fad3b2014-09-19 17:20:05 +0200774 mBackdrop = (BackDropView) mStatusBarWindow.findViewById(R.id.backdrop);
775 mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
776 mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
777
778 ScrimView scrimBehind = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_behind);
779 ScrimView scrimInFront = (ScrimView) mStatusBarWindow.findViewById(R.id.scrim_in_front);
Selim Cinekaac93252015-04-14 20:04:12 -0700780 View headsUpScrim = mStatusBarWindow.findViewById(R.id.heads_up_scrim);
Xiaohui Chen5da71352016-02-22 10:04:41 -0800781 mScrimController = SystemUIFactory.getInstance().createScrimController(
Selim Cinek25503252016-03-03 15:31:43 -0800782 scrimBehind, scrimInFront, headsUpScrim);
783 if (mScrimSrcModeEnabled) {
784 Runnable runnable = new Runnable() {
785 @Override
786 public void run() {
787 boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE;
788 mScrimController.setDrawBehindAsSrc(asSrc);
789 mStackScroller.setDrawBackgroundAsSrc(asSrc);
790 }
791 };
792 mBackdrop.setOnVisibilityChangedRunnable(runnable);
793 runnable.run();
794 }
Selim Cinekaac93252015-04-14 20:04:12 -0700795 mHeadsUpManager.addListener(mScrimController);
796 mStackScroller.setScrimController(mScrimController);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200797 mStatusBarView.setScrimController(mScrimController);
Jorim Jaggi048af1f2014-11-11 22:51:10 +0100798 mDozeScrimController = new DozeScrimController(mScrimController, context);
Jorim Jaggiecc798e2014-05-26 18:14:37 +0200799
Jorim Jaggi4538027d2014-07-30 15:43:13 +0200800 mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
Jorim Jaggi03c701e2014-04-02 12:39:51 +0200801 mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
Jorim Jaggi97b63c42014-05-02 23:03:34 +0200802 mKeyguardBottomArea =
803 (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
804 mKeyguardBottomArea.setActivityStarter(this);
Selim Cineke70d6532015-04-24 16:46:13 -0700805 mKeyguardBottomArea.setAssistManager(mAssistManager);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200806 mKeyguardIndicationController = new KeyguardIndicationController(mContext,
807 (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700808 R.id.keyguard_indication_text),
809 mKeyguardBottomArea.getLockIcon());
Adrian Roos4ebcdfd2014-08-12 23:33:49 +0200810 mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
Daniel Sandlere111ad32012-10-13 15:17:45 -0400811
Adrian Roose381c162016-02-11 15:26:42 -0800812 if (ENABLE_LOCKSCREEN_WALLPAPER) {
813 mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
814 }
815
Xiaohui Chenf43491f2016-02-01 12:19:35 -0800816 // set the initial view visibility
Joe Onorato808182d2010-07-09 18:52:06 -0400817 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -0400818
Xiaohui Cheneb04a992016-03-22 14:58:03 -0700819 createIconController();
Jorim Jaggi66ac1332015-01-21 19:22:26 +0100820
Jason Monk4ae97d32014-12-17 10:14:33 -0500821 // Background thread for any controllers that need it.
822 mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
823 mHandlerThread.start();
824
Daniel Sandler2b697352011-07-22 16:23:09 -0400825 // Other icons
Jason Monk05b86bc2015-05-19 14:21:28 -0400826 mLocationController = new LocationControllerImpl(mContext,
827 mHandlerThread.getLooper()); // will post a notification
Daniel Sandler2b697352011-07-22 16:23:09 -0400828 mBatteryController = new BatteryController(mContext);
John Spurlock0ff62e02014-07-22 16:15:08 -0400829 mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() {
830 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500831 public void onPowerSaveChanged(boolean isPowerSave) {
John Spurlock0ff62e02014-07-22 16:15:08 -0400832 mHandler.post(mCheckBarModes);
John Spurlockd96179e2014-08-21 16:43:45 -0400833 if (mDozeServiceHost != null) {
Jason Monkc06fbb12016-01-08 14:12:18 -0500834 mDozeServiceHost.firePowerSaveChanged(isPowerSave);
John Spurlockd96179e2014-08-21 16:43:45 -0400835 }
John Spurlock0ff62e02014-07-22 16:15:08 -0400836 }
837 @Override
838 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
839 // noop
840 }
841 });
Jason Monk30d80042015-05-08 16:54:18 -0400842 mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
Jason Monk51e4dc02014-07-22 12:00:47 -0400843 mHotspotController = new HotspotControllerImpl(mContext);
Jason Monk4ae97d32014-12-17 10:14:33 -0500844 mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());
Jason Monk3d5f5512014-07-25 11:17:28 -0400845 mSecurityController = new SecurityControllerImpl(mContext);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400846 if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)) {
847 mRotationLockController = new RotationLockControllerImpl(mContext);
John Spurlock8ab172e2013-12-19 16:39:23 -0500848 }
Jorim Jaggi3d878be2014-05-10 03:22:32 +0200849 mUserInfoController = new UserInfoController(mContext);
John Spurlock86005342014-05-23 11:58:00 -0400850 mVolumeComponent = getComponent(VolumeComponent.class);
John Spurlockf2565a82014-10-23 20:16:22 -0400851 if (mVolumeComponent != null) {
852 mZenModeController = mVolumeComponent.getZenController();
853 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400854 mCastController = new CastControllerImpl(mContext);
Xiaohui Chen10942302015-12-16 16:38:13 -0800855
856 initSignalCluster(mStatusBarView);
857 initSignalCluster(mKeyguardStatusBar);
Daniel Sandlerdd4ef492012-07-27 11:19:52 -0400858
Adrian Roosb83777b2014-06-30 15:11:53 +0200859 mFlashlightController = new FlashlightController(mContext);
Adrian Roos1e1d6ac2014-07-22 17:18:55 +0200860 mKeyguardBottomArea.setFlashlightController(mFlashlightController);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200861 mKeyguardBottomArea.setPhoneStatusBar(this);
Adrian Roosa4eba9f2015-07-22 18:13:04 -0700862 mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
Jorim Jaggib2e104f2014-08-15 18:12:36 +0200863 mAccessibilityController = new AccessibilityController(mContext);
864 mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
Jorim Jaggic7dea6e2014-07-26 14:36:57 +0200865 mNextAlarmController = new NextAlarmController(mContext);
Jorim Jaggi86905582016-02-09 21:36:09 -0800866 mLightStatusBarController = new LightStatusBarController(mIconController,
867 mBatteryController);
Jason Monk8a3a9642015-06-05 11:01:30 -0400868 mKeyguardMonitor = new KeyguardMonitor(mContext);
Fyodor Kupolovcd86ebf2015-09-29 17:06:50 -0700869 if (UserManager.get(mContext).isUserSwitcherEnabled()) {
Adrian Roos88b11932015-07-22 14:59:48 -0700870 mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor,
Sudheer Shanka1c7cda82015-12-31 14:46:02 +0000871 mHandler, this);
Rakesh Iyer2790a372016-01-22 15:33:39 -0800872 createUserSwitcher();
Adrian Roos2b154a92014-11-17 15:18:39 +0100873 }
Adrian Roos723632e2014-07-23 21:13:21 +0200874
John Spurlockaf8d6c42014-05-07 17:49:08 -0400875 // Set up the quick settings tile panel
Jason Monk46dbfb42016-02-25 14:59:20 -0500876 DensityContainer container = (DensityContainer) mStatusBarWindow.findViewById(
877 R.id.qs_density_container);
878 if (container != null) {
John Spurlockaf8d6c42014-05-07 17:49:08 -0400879 final QSTileHost qsh = new QSTileHost(mContext, this,
880 mBluetoothController, mLocationController, mRotationLockController,
Jason Monk51e4dc02014-07-22 12:00:47 -0400881 mNetworkController, mZenModeController, mHotspotController,
John Spurlock657c62c2014-07-22 12:18:09 -0400882 mCastController, mFlashlightController,
Jason Monkabe19742015-09-29 09:47:06 -0400883 mUserSwitcherController, mUserInfoController, mKeyguardMonitor,
Jason Monk46dbfb42016-02-25 14:59:20 -0500884 mSecurityController, mBatteryController, mIconController,
885 mNextAlarmController);
Adrian Roos5fd872e2014-08-12 17:28:58 +0200886 mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow);
Jason Monk46dbfb42016-02-25 14:59:20 -0500887 container.addInflateListener(new InflateListener() {
John Spurlockbceed062014-08-10 18:04:16 -0400888 @Override
Jason Monk46dbfb42016-02-25 14:59:20 -0500889 public void onInflated(View v) {
890 QSContainer qsContainer = (QSContainer) v.findViewById(
891 R.id.quick_settings_container);
892 qsContainer.setHost(qsh);
893 mQSPanel = qsContainer.getQsPanel();
894 mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
895 mHeader = qsContainer.getHeader();
896 initSignalCluster(mHeader);
897 mHeader.setActivityStarter(PhoneStatusBar.this);
John Spurlockbceed062014-08-10 18:04:16 -0400898 }
899 });
Siva Velusamy537421b2012-09-14 14:45:02 -0700900 }
901
Jorim Jaggi3d878be2014-05-10 03:22:32 +0200902 // User info. Trigger first load.
Jorim Jaggi4538027d2014-07-30 15:43:13 +0200903 mKeyguardStatusBar.setUserInfoController(mUserInfoController);
Adrian Roosffc90972015-06-09 18:09:49 -0700904 mKeyguardStatusBar.setUserSwitcherController(mUserSwitcherController);
Jorim Jaggi3d878be2014-05-10 03:22:32 +0200905 mUserInfoController.reloadUserInfo();
906
Jorim Jaggi708f7722014-08-20 17:30:38 +0200907 ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)).setBatteryController(
908 mBatteryController);
Jorim Jaggi4538027d2014-07-30 15:43:13 +0200909 mKeyguardStatusBar.setBatteryController(mBatteryController);
Jorim Jaggi853b0702014-07-05 04:31:14 +0200910
John Spurlock56d007b2013-10-28 18:40:56 -0400911 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
912 mBroadcastReceiver.onReceive(mContext,
913 new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
Selim Cinek372d1bd2015-08-14 13:19:37 -0700914 mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
915 "GestureWakeLock");
Selim Cinek69ff8af2015-08-25 19:03:48 -0700916 mVibrator = mContext.getSystemService(Vibrator.class);
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -0700917
Joe Onorato808182d2010-07-09 18:52:06 -0400918 // receive broadcasts
919 IntentFilter filter = new IntentFilter();
Joe Onorato808182d2010-07-09 18:52:06 -0400920 filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
921 filter.addAction(Intent.ACTION_SCREEN_OFF);
Daniel Sandler7f3cf952012-08-31 14:57:09 -0400922 filter.addAction(Intent.ACTION_SCREEN_ON);
Kenny Guy44fc65f2014-11-28 22:18:14 +0000923 context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
Joe Onorato808182d2010-07-09 18:52:06 -0400924
Adrian Roos8e3e8362015-07-16 19:42:22 -0700925 IntentFilter demoFilter = new IntentFilter();
926 if (DEBUG_MEDIA_FAKE_ARTWORK) {
927 demoFilter.addAction(ACTION_FAKE_ARTWORK);
928 }
929 demoFilter.addAction(ACTION_DEMO);
930 context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
931 android.Manifest.permission.DUMP, null);
932
John Spurlock919adac2012-10-02 16:41:12 -0400933 // listen for USER_SETUP_COMPLETE setting (per-user)
934 resetUserSetupObserver();
935
Chris Craik2507c342015-05-04 14:36:49 -0700936 // disable profiling bars, since they overlap and clutter the output on app windows
937 ThreadedRenderer.overrideProperty("disableProfileBars", "true");
938
939 // Private API call to make the shadows look better for Recents
940 ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
941
Daniel Sandlera310af82012-04-24 01:20:13 -0400942 return mStatusBarView;
Joe Onorato808182d2010-07-09 18:52:06 -0400943 }
944
Selim Cinek01af3342016-02-09 19:25:31 -0800945 @Override
946 protected void reInflateViews() {
947 super.reInflateViews();
948 inflateDismissView();
949 updateClearAll();
950 inflateEmptyShadeView();
951 updateEmptyShadeView();
952 }
953
954 private void inflateEmptyShadeView() {
955 mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate(
956 R.layout.status_bar_no_notifications, mStackScroller, false);
957 mStackScroller.setEmptyShadeView(mEmptyShadeView);
958 }
959
960 private void inflateDismissView() {
961 mDismissView = (DismissView) LayoutInflater.from(mContext).inflate(
962 R.layout.status_bar_notification_dismiss_all, mStackScroller, false);
963 mDismissView.setOnButtonClickListener(new View.OnClickListener() {
964 @Override
965 public void onClick(View v) {
966 MetricsLogger.action(mContext, MetricsEvent.ACTION_DISMISS_ALL_NOTES);
967 clearAllNotifications();
968 }
969 });
970 mStackScroller.setDismissView(mDismissView);
971 }
972
Rakesh Iyer2790a372016-01-22 15:33:39 -0800973 protected void createUserSwitcher() {
974 mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
975 (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),
976 mKeyguardStatusBar, mNotificationPanel, mUserSwitcherController);
977 }
978
Xiaohui Chend839d1a2016-01-21 13:05:02 -0800979 protected void inflateStatusBarWindow(Context context) {
980 mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
981 R.layout.super_status_bar, null);
982 }
983
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800984 protected void createNavigationBarView(Context context) {
Xiaohui Chen8bdcd1f2016-01-19 13:52:07 -0800985 inflateNavigationBarView(context);
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800986 mNavigationBarView.setDisabledFlags(mDisabled1);
987 mNavigationBarView.setComponents(mRecents, getComponent(Divider.class));
988 mNavigationBarView.setOnVerticalChangedListener(
989 new NavigationBarView.OnVerticalChangedListener() {
990 @Override
991 public void onVerticalChanged(boolean isVertical) {
992 if (mAssistManager != null) {
993 mAssistManager.onConfigurationChanged();
994 }
995 mNotificationPanel.setQsScrimEnabled(!isVertical);
996 }
997 });
998 mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {
999 @Override
1000 public boolean onTouch(View v, MotionEvent event) {
1001 checkUserAutohide(v, event);
1002 return false;
1003 }});
1004 }
1005
Xiaohui Chen8bdcd1f2016-01-19 13:52:07 -08001006 protected void inflateNavigationBarView(Context context) {
Jason Monk4f878ef2016-01-23 14:37:38 -05001007 mNavigationBarView = (NavigationBarView) View.inflate(
1008 context, R.layout.navigation_bar, null);
Xiaohui Chen8bdcd1f2016-01-19 13:52:07 -08001009 }
1010
1011 protected void initSignalCluster(View containerView) {
Xiaohui Chen10942302015-12-16 16:38:13 -08001012 SignalClusterView signalCluster =
1013 (SignalClusterView) containerView.findViewById(R.id.signal_cluster);
1014 if (signalCluster != null) {
Xiaohui Chen10942302015-12-16 16:38:13 -08001015 signalCluster.setSecurityController(mSecurityController);
1016 signalCluster.setNetworkController(mNetworkController);
1017 }
1018 }
1019
Muyuan Lic510b5e2016-03-09 17:15:05 -08001020 public void clearAllNotifications() {
Dan Sandlereceda3d2014-07-21 15:35:01 -04001021
1022 // animate-swipe all dismissable notifications, then animate the shade closed
1023 int numChildren = mStackScroller.getChildCount();
1024
1025 final ArrayList<View> viewsToHide = new ArrayList<View>(numChildren);
1026 for (int i = 0; i < numChildren; i++) {
1027 final View child = mStackScroller.getChildAt(i);
Selim Cinekb5605e52015-02-20 18:21:41 +01001028 if (child instanceof ExpandableNotificationRow) {
1029 if (mStackScroller.canChildBeDismissed(child)) {
1030 if (child.getVisibility() == View.VISIBLE) {
1031 viewsToHide.add(child);
1032 }
1033 }
1034 ExpandableNotificationRow row = (ExpandableNotificationRow) child;
1035 List<ExpandableNotificationRow> children = row.getNotificationChildren();
1036 if (row.areChildrenExpanded() && children != null) {
1037 for (ExpandableNotificationRow childRow : children) {
1038 if (childRow.getVisibility() == View.VISIBLE) {
1039 viewsToHide.add(childRow);
1040 }
1041 }
Dan Sandlereceda3d2014-07-21 15:35:01 -04001042 }
1043 }
1044 }
1045 if (viewsToHide.isEmpty()) {
1046 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
1047 return;
1048 }
1049
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001050 addPostCollapseAction(new Runnable() {
Dan Sandlereceda3d2014-07-21 15:35:01 -04001051 @Override
1052 public void run() {
Selim Cinek9c17b772015-07-07 20:37:09 -07001053 mStackScroller.setDismissAllInProgress(false);
Dan Sandlereceda3d2014-07-21 15:35:01 -04001054 try {
1055 mBarService.onClearAllNotifications(mCurrentUserId);
1056 } catch (Exception ex) { }
1057 }
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001058 });
Dan Sandlereceda3d2014-07-21 15:35:01 -04001059
1060 performDismissAllAnimations(viewsToHide);
1061
1062 }
1063
1064 private void performDismissAllAnimations(ArrayList<View> hideAnimatedList) {
1065 Runnable animationFinishAction = new Runnable() {
1066 @Override
1067 public void run() {
Dan Sandlereceda3d2014-07-21 15:35:01 -04001068 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
1069 }
1070 };
1071
1072 // let's disable our normal animations
1073 mStackScroller.setDismissAllInProgress(true);
1074
1075 // Decrease the delay for every row we animate to give the sense of
1076 // accelerating the swipes
1077 int rowDelayDecrement = 10;
1078 int currentDelay = 140;
Selim Cinek7d5f3742014-11-07 18:07:49 +01001079 int totalDelay = 180;
Dan Sandlereceda3d2014-07-21 15:35:01 -04001080 int numItems = hideAnimatedList.size();
Selim Cinek7d5f3742014-11-07 18:07:49 +01001081 for (int i = numItems - 1; i >= 0; i--) {
Dan Sandlereceda3d2014-07-21 15:35:01 -04001082 View view = hideAnimatedList.get(i);
1083 Runnable endRunnable = null;
Selim Cinek7d5f3742014-11-07 18:07:49 +01001084 if (i == 0) {
Dan Sandlereceda3d2014-07-21 15:35:01 -04001085 endRunnable = animationFinishAction;
1086 }
1087 mStackScroller.dismissViewAnimated(view, endRunnable, totalDelay, 260);
1088 currentDelay = Math.max(50, currentDelay - rowDelayDecrement);
1089 totalDelay += currentDelay;
1090 }
1091 }
1092
John Spurlockae641c92014-06-30 18:11:40 -04001093 @Override
1094 protected void setZenMode(int mode) {
1095 super.setZenMode(mode);
1096 if (mIconPolicy != null) {
1097 mIconPolicy.setZenMode(mode);
1098 }
1099 }
1100
Xiyuan Xia1b30f792016-01-06 08:50:30 -08001101 protected void startKeyguard() {
Jorim Jaggi03c701e2014-04-02 12:39:51 +02001102 KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07001103 mFingerprintUnlockController = new FingerprintUnlockController(mContext,
1104 mStatusBarWindowManager, mDozeScrimController, keyguardViewMediator,
1105 mScrimController, this);
Jorim Jaggi03c701e2014-04-02 12:39:51 +02001106 mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
Xiyuan Xia1b30f792016-01-06 08:50:30 -08001107 getBouncerContainer(), mStatusBarWindowManager, mScrimController,
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07001108 mFingerprintUnlockController);
Selim Cinekcfafe4e2015-08-11 14:58:44 -07001109 mKeyguardIndicationController.setStatusBarKeyguardViewManager(
1110 mStatusBarKeyguardViewManager);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07001111 mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
Adrian Roosd28ccd72016-01-06 15:23:14 +01001112 mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
Jorim Jaggi03c701e2014-04-02 12:39:51 +02001113 mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
Jorim Jaggi86905582016-02-09 21:36:09 -08001114 mLightStatusBarController.setFingerprintUnlockController(mFingerprintUnlockController);
Jorim Jaggi5cf17872014-03-26 18:31:48 +01001115 }
1116
Michael Jurka7f2668c2012-03-27 07:49:52 -07001117 @Override
Michael Jurkacb2522c2012-04-13 09:32:47 -07001118 protected View getStatusBarView() {
1119 return mStatusBarView;
1120 }
1121
Jorim Jaggi0a27be82014-06-11 03:22:39 +02001122 public StatusBarWindowView getStatusBarWindow() {
1123 return mStatusBarWindow;
1124 }
1125
Xiyuan Xia1b30f792016-01-06 08:50:30 -08001126 protected ViewGroup getBouncerContainer() {
1127 return mStatusBarWindow;
1128 }
1129
Joe Onoratodc100302011-01-11 17:07:41 -08001130 public int getStatusBarHeight() {
Daniel Sandlera310af82012-04-24 01:20:13 -04001131 if (mNaturalBarHeight < 0) {
1132 final Resources res = mContext.getResources();
Jim Millera073e572012-05-23 17:03:27 -07001133 mNaturalBarHeight =
Daniel Sandlera310af82012-04-24 01:20:13 -04001134 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
1135 }
1136 return mNaturalBarHeight;
Joe Onoratodc100302011-01-11 17:07:41 -08001137 }
1138
Daniel Sandler5c8da942011-06-28 00:29:04 -04001139 private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
1140 public void onClick(View v) {
John Spurlockc8b46ca2013-04-08 12:59:26 -04001141 awakenDreams();
Daniel Sandler5c8da942011-06-28 00:29:04 -04001142 toggleRecentApps();
1143 }
1144 };
Chris Wren0c8275b2012-05-08 13:36:48 -04001145
Jorim Jaggi75b25972015-10-21 14:51:10 +02001146 private View.OnLongClickListener mLongPressBackListener = new View.OnLongClickListener() {
Jason Monk62515be2014-05-21 16:06:19 -04001147 @Override
1148 public boolean onLongClick(View v) {
Jorim Jaggi75b25972015-10-21 14:51:10 +02001149 return handleLongPressBack();
1150 }
1151 };
1152
1153 private View.OnLongClickListener mRecentsLongClickListener = new View.OnLongClickListener() {
1154
1155 @Override
1156 public boolean onLongClick(View v) {
Winsonc694a502016-03-10 16:35:03 -08001157 if (mRecents == null || !ActivityManager.supportsMultiWindow()) {
Phil Weaver315c34e2016-02-19 15:12:29 -08001158 return false;
1159 }
Winsonc694a502016-03-10 16:35:03 -08001160
Phil Weaver315c34e2016-02-19 15:12:29 -08001161 boolean initiallyDocked = WindowManagerProxy.getInstance().getDockSide()
1162 == WindowManager.DOCKED_INVALID;
1163 boolean dockedAtEnd = toggleSplitScreenMode();
1164 if (dockedAtEnd != initiallyDocked) {
1165 int logAction = dockedAtEnd ? MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS
1166 : MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS;
1167 MetricsLogger.action(mContext, logAction);
1168 return true;
Jorim Jaggi75b25972015-10-21 14:51:10 +02001169 }
1170 return false;
Jason Monk62515be2014-05-21 16:06:19 -04001171 }
1172 };
1173
Phil Weaver315c34e2016-02-19 15:12:29 -08001174 @Override
1175 protected boolean toggleSplitScreenMode() {
1176 if (mRecents == null) {
1177 return false;
1178 }
1179 int dockSide = WindowManagerProxy.getInstance().getDockSide();
1180 if (dockSide == WindowManager.DOCKED_INVALID) {
Phil Weaver315c34e2016-02-19 15:12:29 -08001181 return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
Muyuan Lia2129992016-03-03 18:30:39 -08001182 ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null);
Phil Weaver315c34e2016-02-19 15:12:29 -08001183 } else {
1184 EventBus.getDefault().send(new UndockingTaskEvent());
1185 return false;
1186 }
1187 }
1188
Jorim Jaggi7e6571f2015-06-25 11:52:48 -07001189 private final View.OnLongClickListener mLongPressHomeListener
1190 = new View.OnLongClickListener() {
1191 @Override
1192 public boolean onLongClick(View v) {
1193 if (shouldDisableNavbarGestures()) {
1194 return false;
1195 }
Chris Wrenf6e9228b2016-01-26 18:04:35 -05001196 MetricsLogger.action(mContext, MetricsEvent.ACTION_ASSIST_LONG_PRESS);
Jorim Jaggi165ce062015-07-06 16:18:11 -07001197 mAssistManager.startAssist(new Bundle() /* args */);
Daniel Sandlera2fbe532012-08-10 01:19:03 -04001198 awakenDreams();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07001199 if (mNavigationBarView != null) {
Xiyuan Xiaee7dd052015-05-15 09:46:27 -07001200 mNavigationBarView.abortCurrentGesture();
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07001201 }
Jorim Jaggi7e6571f2015-06-25 11:52:48 -07001202 return true;
Jim Miller9a720f52012-05-30 03:19:43 -07001203 }
1204 };
1205
Jorim Jaggi7e6571f2015-06-25 11:52:48 -07001206 private final View.OnTouchListener mHomeActionListener = new View.OnTouchListener() {
Jim Millere898ac52012-04-06 17:10:57 -07001207 public boolean onTouch(View v, MotionEvent event) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07001208 switch (event.getAction()) {
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07001209 case MotionEvent.ACTION_UP:
1210 case MotionEvent.ACTION_CANCEL:
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07001211 awakenDreams();
1212 break;
1213 }
1214 return false;
Jim Millere898ac52012-04-06 17:10:57 -07001215 }
1216 };
Daniel Sandler5c8da942011-06-28 00:29:04 -04001217
Daniel Sandlera2fbe532012-08-10 01:19:03 -04001218 private void awakenDreams() {
1219 if (mDreamManager != null) {
1220 try {
1221 mDreamManager.awaken();
1222 } catch (RemoteException e) {
1223 // fine, stay asleep then
1224 }
1225 }
1226 }
1227
Michael Jurka412cba82011-10-17 09:05:00 -07001228 private void prepareNavigationBarView() {
1229 mNavigationBarView.reorient();
1230
Jason Monka2081822016-01-18 14:41:03 -05001231 ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
1232 recentsButton.setOnClickListener(mRecentsClickListener);
1233 recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
1234 recentsButton.setLongClickable(true);
1235 recentsButton.setOnLongClickListener(mRecentsLongClickListener);
Anthony Chenada13042016-01-19 16:57:20 -08001236
Jason Monka2081822016-01-18 14:41:03 -05001237 ButtonDispatcher backButton = mNavigationBarView.getBackButton();
1238 backButton.setLongClickable(true);
1239 backButton.setOnLongClickListener(mLongPressBackListener);
Anthony Chenada13042016-01-19 16:57:20 -08001240
Jason Monka2081822016-01-18 14:41:03 -05001241 ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
1242 homeButton.setOnTouchListener(mHomeActionListener);
1243 homeButton.setOnLongClickListener(mLongPressHomeListener);
Anthony Chenada13042016-01-19 16:57:20 -08001244
Selim Cineke70d6532015-04-24 16:46:13 -07001245 mAssistManager.onConfigurationChanged();
Michael Jurka412cba82011-10-17 09:05:00 -07001246 }
1247
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001248 // For small-screen devices (read: phones) that lack hardware navigation buttons
Rakesh Iyer1186faa2015-12-07 16:48:46 -08001249 protected void addNavigationBar() {
John Spurlockcd686b52013-06-05 10:13:46 -04001250 if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
Daniel Sandler0129b312011-05-11 11:54:11 -04001251 if (mNavigationBarView == null) return;
Jim Miller17dfec72011-07-08 19:09:55 -07001252
Michael Jurka412cba82011-10-17 09:05:00 -07001253 prepareNavigationBarView();
Daniel Sandler5c8da942011-06-28 00:29:04 -04001254
Jeff Brown98365d72012-08-19 20:30:52 -07001255 mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001256 }
1257
Victor Chanecdb8b02016-01-07 18:32:43 -08001258 protected void repositionNavigationBar() {
John Spurlock56d007b2013-10-28 18:40:56 -04001259 if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return;
Jim Miller17dfec72011-07-08 19:09:55 -07001260
Michael Jurka412cba82011-10-17 09:05:00 -07001261 prepareNavigationBarView();
Daniel Sandler5c8da942011-06-28 00:29:04 -04001262
Jeff Brown98365d72012-08-19 20:30:52 -07001263 mWindowManager.updateViewLayout(mNavigationBarView, getNavigationBarLayoutParams());
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001264 }
1265
John Spurlock1bbd49d2012-10-19 11:09:32 -04001266 private void notifyNavigationBarScreenOn(boolean screenOn) {
1267 if (mNavigationBarView == null) return;
1268 mNavigationBarView.notifyScreenOn(screenOn);
1269 }
1270
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001271 private WindowManager.LayoutParams getNavigationBarLayoutParams() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001272 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001273 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001274 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
1275 0
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001276 | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
1277 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
Dianne Hackborndf89e652011-10-06 22:35:11 -07001278 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
Daniel Sandlerc26185b2012-08-29 15:49:53 -04001279 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
Jim Millerd99e7fd2012-05-08 16:30:42 -07001280 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
John Spurlockad3e6cb2013-04-30 08:47:43 -04001281 PixelFormat.TRANSLUCENT);
Daniel Sandlerc638c1e2011-08-24 16:19:23 -07001282 // this will allow the navbar to run in an overlay on devices that support this
Jeff Brown98365d72012-08-19 20:30:52 -07001283 if (ActivityManager.isHighEndGfx()) {
Daniel Sandlerc638c1e2011-08-24 16:19:23 -07001284 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
1285 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001286
1287 lp.setTitle("NavigationBar");
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001288 lp.windowAnimations = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001289 return lp;
1290 }
1291
Jason Monk07473ce2016-01-05 14:59:19 -05001292 @Override
1293 public void setIcon(String slot, StatusBarIcon icon) {
1294 mIconController.setIcon(slot, icon);
Joe Onorato808182d2010-07-09 18:52:06 -04001295 }
1296
Jason Monk07473ce2016-01-05 14:59:19 -05001297 @Override
1298 public void removeIcon(String slot) {
1299 mIconController.removeIcon(slot);
Joe Onorato808182d2010-07-09 18:52:06 -04001300 }
1301
John Spurlockbf20eab2014-04-09 16:40:39 -04001302 public UserHandle getCurrentUserHandle() {
1303 return new UserHandle(mCurrentUserId);
1304 }
1305
Christoph Studer71f18fd2014-05-20 17:02:04 +02001306 @Override
Selim Cinek379ff8f2015-02-20 17:03:16 +01001307 public void addNotification(StatusBarNotification notification, RankingMap ranking,
1308 Entry oldEntry) {
Chris Wrenaaa58d12014-06-03 14:29:12 -04001309 if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
Chris Wrend4db6cb2013-08-07 16:05:23 -04001310
Julia Reynoldsf612869ae2015-11-05 16:48:55 -05001311 mNotificationData.updateRanking(ranking);
Selim Cinek8d490d42015-04-10 00:05:50 -07001312 Entry shadeEntry = createNotificationViews(notification);
Chris Wrena4ef6202014-06-09 18:07:30 -04001313 if (shadeEntry == null) {
1314 return;
1315 }
Chris Wrenbdf33762015-12-04 15:50:51 -05001316 boolean isHeadsUped = mUseHeadsUp && shouldPeek(shadeEntry);
Selim Cinek31d9ef72015-04-15 19:29:49 -07001317 if (isHeadsUped) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001318 mHeadsUpManager.showNotification(shadeEntry);
Amith Yamasanif47e51e2015-04-17 10:02:15 -07001319 // Mark as seen immediately
1320 setNotificationShown(notification);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001321 }
Chris Wrena4ef6202014-06-09 18:07:30 -04001322
Selim Cinek31d9ef72015-04-15 19:29:49 -07001323 if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) {
Julia Reynoldsd5607292016-02-05 15:25:58 -05001324 if (shouldSuppressFullScreenIntent(notification.getKey())) {
Julia Reynolds61721582016-01-05 08:35:25 -05001325 if (DEBUG) {
1326 Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
1327 }
Julia Reynoldsf0f629f2016-02-25 09:34:04 -05001328 } else if (mNotificationData.getImportance(notification.getKey())
1329 < NotificationListenerService.Ranking.IMPORTANCE_MAX) {
1330 if (DEBUG) {
1331 Log.d(TAG, "No Fullscreen intent: not important enough: "
1332 + notification.getKey());
1333 }
Julia Reynolds61721582016-01-05 08:35:25 -05001334 } else {
1335 // Stop screensaver if the notification has a full-screen intent.
1336 // (like an incoming phone call)
1337 awakenDreams();
Daniel Sandlerc9ce0ab2012-09-04 13:27:09 -04001338
Julia Reynolds61721582016-01-05 08:35:25 -05001339 // not immersive & a full-screen alert should be shown
1340 if (DEBUG)
1341 Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
1342 try {
1343 EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
1344 notification.getKey());
1345 notification.getNotification().fullScreenIntent.send();
1346 shadeEntry.notifyFullScreenIntentLaunched();
1347 MetricsLogger.count(mContext, "note_fullscreen", 1);
1348 } catch (PendingIntent.CanceledException e) {
1349 }
John Spurlockbf20eab2014-04-09 16:40:39 -04001350 }
Joe Onorato808182d2010-07-09 18:52:06 -04001351 }
Christoph Studer37fe6932014-05-26 13:10:30 +02001352 addNotificationViews(shadeEntry, ranking);
Joe Onorato808182d2010-07-09 18:52:06 -04001353 // Recalculate the position of the sliding windows and the titles.
1354 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -04001355 }
1356
Julia Reynoldsd5607292016-02-05 15:25:58 -05001357 private boolean shouldSuppressFullScreenIntent(String key) {
Julia Reynolds0971cb02016-01-26 17:00:22 -05001358 if (mPowerManager.isInteractive()) {
Julia Reynolds0971cb02016-01-26 17:00:22 -05001359 return mNotificationData.shouldSuppressScreenOn(key);
Julia Reynoldsd5607292016-02-05 15:25:58 -05001360 } else {
1361 return mNotificationData.shouldSuppressScreenOff(key);
Julia Reynolds0971cb02016-01-26 17:00:22 -05001362 }
1363 }
1364
Chris Wren51c75102013-07-16 20:49:17 -04001365 @Override
Christoph Studere71fefc2014-06-24 16:16:49 +02001366 protected void updateNotificationRanking(RankingMap ranking) {
Chris Wren333a61c2014-05-28 16:40:57 -04001367 mNotificationData.updateRanking(ranking);
Chris Wren333a61c2014-05-28 16:40:57 -04001368 updateNotifications();
1369 }
1370
1371 @Override
Christoph Studere71fefc2014-06-24 16:16:49 +02001372 public void removeNotification(String key, RankingMap ranking) {
Selim Cinek684a4422015-04-15 16:18:39 -07001373 boolean deferRemoval = false;
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001374 if (mHeadsUpManager.isHeadsUp(key)) {
Selim Cinek684a4422015-04-15 16:18:39 -07001375 deferRemoval = !mHeadsUpManager.removeNotification(key);
Chris Wrena4ef6202014-06-09 18:07:30 -04001376 }
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001377 if (key.equals(mMediaNotificationKey)) {
1378 clearCurrentMediaNotification();
Adrian Roos52738322016-01-29 08:49:21 -08001379 updateMediaMetaData(true, true);
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001380 }
Selim Cinek684a4422015-04-15 16:18:39 -07001381 if (deferRemoval) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -07001382 mLatestRankingMap = ranking;
1383 mHeadsUpEntriesToRemoveOnSwitch.add(mHeadsUpManager.getEntry(key));
1384 return;
1385 }
Christoph Studer37fe6932014-05-26 13:10:30 +02001386 StatusBarNotification old = removeNotificationViews(key, ranking);
John Spurlockcd686b52013-06-05 10:13:46 -04001387 if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
Joe Onorato808182d2010-07-09 18:52:06 -04001388
1389 if (old != null) {
Christoph Studerc8db24b2014-07-25 17:50:30 +02001390 if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
Jorim Jaggiba94f882014-08-20 19:23:55 +02001391 && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) {
Jorim Jaggi48bc36a2014-07-25 23:16:04 +02001392 if (mState == StatusBarState.SHADE) {
1393 animateCollapsePanels();
1394 } else if (mState == StatusBarState.SHADE_LOCKED) {
1395 goToKeyguard();
1396 }
Daniel Sandler8cc36e52011-10-17 14:18:46 -04001397 }
Joe Onorato808182d2010-07-09 18:52:06 -04001398 }
Daniel Sandler0761e4c2011-08-11 00:19:49 -04001399 setAreThereNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -04001400 }
1401
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -07001402 @Override
1403 protected void refreshLayout(int layoutDirection) {
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -07001404 if (mNavigationBarView != null) {
1405 mNavigationBarView.setLayoutDirection(layoutDirection);
1406 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -07001407 }
1408
Christoph Studer37fe6932014-05-26 13:10:30 +02001409 private void updateNotificationShade() {
Selim Cinekb6d85eb2014-03-28 20:21:01 +01001410 if (mStackScroller == null) return;
Daniel Sandler26cda272012-05-22 15:44:08 -04001411
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02001412 // Do not modify the notifications during collapse.
1413 if (isCollapsing()) {
1414 addPostCollapseAction(new Runnable() {
1415 @Override
1416 public void run() {
1417 updateNotificationShade();
1418 }
1419 });
1420 return;
1421 }
1422
Christoph Studerc8db24b2014-07-25 17:50:30 +02001423 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
Jorim Jaggif6411742014-08-05 17:10:43 +00001424 ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size());
Christoph Studerc8db24b2014-07-25 17:50:30 +02001425 final int N = activeNotifications.size();
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001426 for (int i=0; i<N; i++) {
Christoph Studerc8db24b2014-07-25 17:50:30 +02001427 Entry ent = activeNotifications.get(i);
1428 int vis = ent.notification.getNotification().visibility;
Kenny Guy3a7c4a52014-03-03 18:24:03 +00001429
Christoph Studerc8db24b2014-07-25 17:50:30 +02001430 // Display public version of the notification if we need to redact.
Jorim Jaggiae441282014-08-01 02:45:18 +02001431 final boolean hideSensitive =
1432 !userAllowsPrivateNotificationsInPublic(ent.notification.getUserId());
Chris Wren3ad4e3a2014-09-02 17:23:51 -04001433 boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE;
1434 boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey());
1435 boolean sensitive = (sensitiveNote && hideSensitive) || sensitivePackage;
1436 boolean showingPublic = sensitive && isLockscreenPublicMode();
Sudheer Shankaf5b850e2016-01-25 19:58:59 +00001437 if (showingPublic) {
1438 updatePublicContentView(ent, ent.notification);
1439 }
Selim Cinek3c76d502016-02-19 15:16:33 -08001440 ent.row.setSensitive(sensitive, hideSensitive);
Dan Sandler1b718782014-07-18 12:43:45 -04001441 if (ent.autoRedacted && ent.legacy) {
Jorim Jaggiae441282014-08-01 02:45:18 +02001442 // TODO: Also fade this? Or, maybe easier (and better), provide a dark redacted form
1443 // for legacy auto redacted notifications.
Dan Sandler1b718782014-07-18 12:43:45 -04001444 if (showingPublic) {
1445 ent.row.setShowingLegacyBackground(false);
1446 } else {
1447 ent.row.setShowingLegacyBackground(true);
1448 }
1449 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001450 if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) {
1451 ExpandableNotificationRow summary = mGroupManager.getGroupSummary(
1452 ent.row.getStatusBarNotification());
1453 List<ExpandableNotificationRow> orderedChildren =
1454 mTmpChildOrderMap.get(summary);
1455 if (orderedChildren == null) {
1456 orderedChildren = new ArrayList<>();
1457 mTmpChildOrderMap.put(summary, orderedChildren);
1458 }
1459 orderedChildren.add(ent.row);
1460 } else {
1461 toShow.add(ent.row);
1462 }
1463
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001464 }
1465
Selim Cinekef5127e2015-12-21 16:55:58 -08001466 ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>();
Selim Cinekb6d85eb2014-03-28 20:21:01 +01001467 for (int i=0; i< mStackScroller.getChildCount(); i++) {
1468 View child = mStackScroller.getChildAt(i);
Jorim Jaggif6411742014-08-05 17:10:43 +00001469 if (!toShow.contains(child) && child instanceof ExpandableNotificationRow) {
Selim Cinekef5127e2015-12-21 16:55:58 -08001470 toRemove.add((ExpandableNotificationRow) child);
Joe Onorato808182d2010-07-09 18:52:06 -04001471 }
1472 }
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001473
Selim Cinekef5127e2015-12-21 16:55:58 -08001474 for (ExpandableNotificationRow remove : toRemove) {
1475 if (mGroupManager.isChildInGroupWithSummary(remove.getStatusBarNotification())) {
1476 // we are only transfering this notification to its parent, don't generate an animation
1477 mStackScroller.setChildTransferInProgress(true);
1478 }
Selim Cinekb6d85eb2014-03-28 20:21:01 +01001479 mStackScroller.removeView(remove);
Selim Cinekef5127e2015-12-21 16:55:58 -08001480 mStackScroller.setChildTransferInProgress(false);
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001481 }
Selim Cinek2b542422016-03-04 18:10:37 -08001482
1483 removeNotificationChildren();
1484
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001485 for (int i=0; i<toShow.size(); i++) {
1486 View v = toShow.get(i);
1487 if (v.getParent() == null) {
Christoph Studer37fe6932014-05-26 13:10:30 +02001488 mStackScroller.addView(v);
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001489 }
1490 }
Daniel Sandler26cda272012-05-22 15:44:08 -04001491
Selim Cinek2b542422016-03-04 18:10:37 -08001492 addNotificationChildrenAndSort();
1493
Christoph Studer37fe6932014-05-26 13:10:30 +02001494 // So after all this work notifications still aren't sorted correctly.
1495 // Let's do that now by advancing through toShow and mStackScroller in
1496 // lock-step, making sure mStackScroller matches what we see in toShow.
1497 int j = 0;
1498 for (int i = 0; i < mStackScroller.getChildCount(); i++) {
1499 View child = mStackScroller.getChildAt(i);
1500 if (!(child instanceof ExpandableNotificationRow)) {
1501 // We don't care about non-notification views.
1502 continue;
1503 }
1504
Selim Cinekb5605e52015-02-20 18:21:41 +01001505 ExpandableNotificationRow targetChild = toShow.get(j);
1506 if (child != targetChild) {
1507 // Oops, wrong notification at this position. Put the right one
1508 // here and advance both lists.
1509 mStackScroller.changeViewPosition(targetChild, i);
Christoph Studer37fe6932014-05-26 13:10:30 +02001510 }
Christoph Studer37fe6932014-05-26 13:10:30 +02001511 j++;
Selim Cinekb5605e52015-02-20 18:21:41 +01001512
Christoph Studer37fe6932014-05-26 13:10:30 +02001513 }
Selim Cinekb5605e52015-02-20 18:21:41 +01001514
Selim Cinekb5605e52015-02-20 18:21:41 +01001515 // clear the map again for the next usage
1516 mTmpChildOrderMap.clear();
1517
Christoph Studer37fe6932014-05-26 13:10:30 +02001518 updateRowStates();
Jorim Jaggif6411742014-08-05 17:10:43 +00001519 updateSpeedbump();
Dan Sandlereceda3d2014-07-21 15:35:01 -04001520 updateClearAll();
Jorim Jaggia2052ea2014-08-05 16:22:30 +02001521 updateEmptyShadeView();
Dan Sandlereceda3d2014-07-21 15:35:01 -04001522
Benjamin Franz27cf1462015-04-23 19:36:42 +01001523 updateQsExpansionEnabled();
1524 mShadeUpdates.check();
1525 }
1526
1527 /**
1528 * Disable QS if device not provisioned.
1529 * If the user switcher is simple then disable QS during setup because
1530 * the user intends to use the lock screen user switcher, QS in not needed.
1531 */
1532 private void updateQsExpansionEnabled() {
Jason Monk3ad242d2014-09-15 11:13:35 -04001533 mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned()
Adrian Roos2b154a92014-11-17 15:18:39 +01001534 && (mUserSetup || mUserSwitcherController == null
Benjamin Franz27cf1462015-04-23 19:36:42 +01001535 || !mUserSwitcherController.isSimpleUserSwitcher())
Adrian Roos21d2a252015-06-01 13:59:59 -07001536 && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
1537 && !ONLY_CORE_APPS);
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001538 }
1539
Selim Cinek2b542422016-03-04 18:10:37 -08001540 private void addNotificationChildrenAndSort() {
Selim Cinek322ec7e2016-02-11 14:47:06 -08001541 // Let's now add all notification children which are missing
1542 boolean orderChanged = false;
1543 for (int i = 0; i < mStackScroller.getChildCount(); i++) {
1544 View view = mStackScroller.getChildAt(i);
1545 if (!(view instanceof ExpandableNotificationRow)) {
1546 // We don't care about non-notification views.
1547 continue;
1548 }
1549
1550 ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
1551 List<ExpandableNotificationRow> children = parent.getNotificationChildren();
1552 List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent);
1553
Selim Cinekb5605e52015-02-20 18:21:41 +01001554 for (int childIndex = 0; orderedChildren != null && childIndex < orderedChildren.size();
1555 childIndex++) {
1556 ExpandableNotificationRow childView = orderedChildren.get(childIndex);
1557 if (children == null || !children.contains(childView)) {
1558 parent.addChildNotification(childView, childIndex);
1559 mStackScroller.notifyGroupChildAdded(childView);
1560 }
1561 }
1562
1563 // Finally after removing and adding has been beformed we can apply the order.
1564 orderChanged |= parent.applyChildOrder(orderedChildren);
1565 }
1566 if (orderChanged) {
1567 mStackScroller.generateChildOrderChangedEvent();
1568 }
1569 }
1570
Selim Cinek2b542422016-03-04 18:10:37 -08001571 private void removeNotificationChildren() {
1572 // First let's remove all children which don't belong in the parents
1573 ArrayList<ExpandableNotificationRow> toRemove = new ArrayList<>();
1574 for (int i = 0; i < mStackScroller.getChildCount(); i++) {
1575 View view = mStackScroller.getChildAt(i);
1576 if (!(view instanceof ExpandableNotificationRow)) {
1577 // We don't care about non-notification views.
1578 continue;
1579 }
1580
1581 ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
1582 List<ExpandableNotificationRow> children = parent.getNotificationChildren();
1583 List<ExpandableNotificationRow> orderedChildren = mTmpChildOrderMap.get(parent);
1584
1585 if (children != null) {
1586 toRemove.clear();
1587 for (ExpandableNotificationRow childRow : children) {
1588 if (orderedChildren == null || !orderedChildren.contains(childRow)) {
1589 toRemove.add(childRow);
1590 }
1591 }
1592 for (ExpandableNotificationRow remove : toRemove) {
1593 parent.removeChildNotification(remove);
1594 if (mNotificationData.get(remove.getStatusBarNotification().getKey()) == null) {
1595 // We only want to add an animation if the view is completely removed
1596 // otherwise it's just a transfer
1597 mStackScroller.notifyGroupChildRemoved(remove);
1598 }
1599 }
1600 }
1601 }
1602 }
1603
Jason Monk7e53f202016-01-28 10:40:20 -05001604 @Override
1605 public void addQsTile(ComponentName tile) {
1606 mQSPanel.getHost().addTile(tile);
1607 }
1608
1609 @Override
1610 public void remQsTile(ComponentName tile) {
1611 mQSPanel.getHost().removeTile(tile);
1612 }
1613
1614 @Override
1615 public void clickTile(ComponentName tile) {
1616 mQSPanel.clickTile(tile);
1617 }
1618
Chris Wren3ad4e3a2014-09-02 17:23:51 -04001619 private boolean packageHasVisibilityOverride(String key) {
Julia Reynolds26fa8a52016-02-24 08:31:22 -05001620 return mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_PRIVATE;
Chris Wren3ad4e3a2014-09-02 17:23:51 -04001621 }
1622
Dan Sandlereceda3d2014-07-21 15:35:01 -04001623 private void updateClearAll() {
Christoph Studerc8db24b2014-07-25 17:50:30 +02001624 boolean showDismissView =
1625 mState != StatusBarState.KEYGUARD &&
1626 mNotificationData.hasActiveClearableNotifications();
Dan Sandlereceda3d2014-07-21 15:35:01 -04001627 mStackScroller.updateDismissView(showDismissView);
1628 }
1629
Jorim Jaggia2052ea2014-08-05 16:22:30 +02001630 private void updateEmptyShadeView() {
1631 boolean showEmptyShade =
1632 mState != StatusBarState.KEYGUARD &&
1633 mNotificationData.getActiveNotifications().size() == 0;
1634 mNotificationPanel.setShadeEmpty(showEmptyShade);
1635 }
1636
Jorim Jaggif6411742014-08-05 17:10:43 +00001637 private void updateSpeedbump() {
1638 int speedbumpIndex = -1;
1639 int currentIndex = 0;
Selim Cinek2a739342016-03-17 10:28:55 -07001640 final int N = mStackScroller.getChildCount();
Jorim Jaggif6411742014-08-05 17:10:43 +00001641 for (int i = 0; i < N; i++) {
Selim Cinek2a739342016-03-17 10:28:55 -07001642 View view = mStackScroller.getChildAt(i);
1643 if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) {
Selim Cinekb5605e52015-02-20 18:21:41 +01001644 continue;
1645 }
Selim Cinek2a739342016-03-17 10:28:55 -07001646 ExpandableNotificationRow row = (ExpandableNotificationRow) view;
1647 if (mNotificationData.isAmbient(row.getStatusBarNotification().getKey())) {
Jorim Jaggif6411742014-08-05 17:10:43 +00001648 speedbumpIndex = currentIndex;
1649 break;
1650 }
1651 currentIndex++;
1652 }
1653 mStackScroller.updateSpeedBumpIndex(speedbumpIndex);
1654 }
1655
Selim Cinekb5605e52015-02-20 18:21:41 +01001656 public static boolean isTopLevelChild(Entry entry) {
1657 return entry.row.getParent() instanceof NotificationStackScrollLayout;
1658 }
1659
Chris Wren0c8275b2012-05-08 13:36:48 -04001660 @Override
Christoph Studer37fe6932014-05-26 13:10:30 +02001661 protected void updateNotifications() {
Christoph Studerc8db24b2014-07-25 17:50:30 +02001662 mNotificationData.filterAndSort();
1663
Christoph Studer37fe6932014-05-26 13:10:30 +02001664 updateNotificationShade();
Jorim Jaggi66ac1332015-01-21 19:22:26 +01001665 mIconController.updateNotificationIcons(mNotificationData);
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04001666 }
1667
Selim Cinekef5127e2015-12-21 16:55:58 -08001668 public void requestNotificationUpdate() {
1669 updateNotifications();
1670 }
1671
Jorim Jaggi54045422014-07-03 18:30:40 +02001672 @Override
Chris Wren0c8275b2012-05-08 13:36:48 -04001673 protected void setAreThereNotifications() {
Daniel Sandler0761e4c2011-08-11 00:19:49 -04001674
Chris Wren6d15a362013-08-20 18:46:29 -04001675 if (SPEW) {
Christoph Studerc8db24b2014-07-25 17:50:30 +02001676 final boolean clearable = hasActiveNotifications() &&
1677 mNotificationData.hasActiveClearableNotifications();
1678 Log.d(TAG, "setAreThereNotifications: N=" +
1679 mNotificationData.getActiveNotifications().size() + " any=" +
1680 hasActiveNotifications() + " clearable=" + clearable);
Daniel Sandler0761e4c2011-08-11 00:19:49 -04001681 }
1682
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001683 final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
Christoph Studerc8db24b2014-07-25 17:50:30 +02001684 final boolean showDot = hasActiveNotifications() && !areLightsOn();
Daniel Sandlerd7e96862012-04-26 01:10:29 -04001685 if (showDot != (nlo.getAlpha() == 1.0f)) {
1686 if (showDot) {
1687 nlo.setAlpha(0f);
1688 nlo.setVisibility(View.VISIBLE);
1689 }
1690 nlo.animate()
1691 .alpha(showDot?1:0)
1692 .setDuration(showDot?750:250)
1693 .setInterpolator(new AccelerateInterpolator(2.0f))
1694 .setListener(showDot ? null : new AnimatorListenerAdapter() {
1695 @Override
1696 public void onAnimationEnd(Animator _a) {
1697 nlo.setVisibility(View.GONE);
1698 }
1699 })
1700 .start();
1701 }
Daniel Sandler3d32a242012-06-05 13:44:14 -04001702
Dan Sandler16128f42014-05-21 12:48:22 -04001703 findAndUpdateMediaNotifications();
Joe Onorato808182d2010-07-09 18:52:06 -04001704 }
1705
Dan Sandler16128f42014-05-21 12:48:22 -04001706 public void findAndUpdateMediaNotifications() {
1707 boolean metaDataChanged = false;
1708
1709 synchronized (mNotificationData) {
Christoph Studerc8db24b2014-07-25 17:50:30 +02001710 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
1711 final int N = activeNotifications.size();
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001712
1713 // Promote the media notification with a controller in 'playing' state, if any.
Dan Sandler16128f42014-05-21 12:48:22 -04001714 Entry mediaNotification = null;
1715 MediaController controller = null;
Christoph Studerc8db24b2014-07-25 17:50:30 +02001716 for (int i = 0; i < N; i++) {
1717 final Entry entry = activeNotifications.get(i);
Dan Sandler16128f42014-05-21 12:48:22 -04001718 if (isMediaNotification(entry)) {
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001719 final MediaSession.Token token =
1720 entry.notification.getNotification().extras
Dan Sandler16128f42014-05-21 12:48:22 -04001721 .getParcelable(Notification.EXTRA_MEDIA_SESSION);
1722 if (token != null) {
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001723 MediaController aController = new MediaController(mContext, token);
1724 if (PlaybackState.STATE_PLAYING ==
1725 getMediaControllerPlaybackState(aController)) {
1726 if (DEBUG_MEDIA) {
1727 Log.v(TAG, "DEBUG_MEDIA: found mediastyle controller matching "
1728 + entry.notification.getKey());
1729 }
Dan Sandler16128f42014-05-21 12:48:22 -04001730 mediaNotification = entry;
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001731 controller = aController;
1732 break;
Dan Sandler16128f42014-05-21 12:48:22 -04001733 }
1734 }
1735 }
1736 }
Dan Sandler16128f42014-05-21 12:48:22 -04001737 if (mediaNotification == null) {
1738 // Still nothing? OK, let's just look for live media sessions and see if they match
1739 // one of our notifications. This will catch apps that aren't (yet!) using media
1740 // notifications.
1741
1742 if (mMediaSessionManager != null) {
1743 final List<MediaController> sessions
1744 = mMediaSessionManager.getActiveSessionsForUser(
1745 null,
1746 UserHandle.USER_ALL);
1747
1748 for (MediaController aController : sessions) {
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001749 if (PlaybackState.STATE_PLAYING ==
1750 getMediaControllerPlaybackState(aController)) {
1751 // now to see if we have one like this
1752 final String pkg = aController.getPackageName();
Dan Sandler16128f42014-05-21 12:48:22 -04001753
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001754 for (int i = 0; i < N; i++) {
1755 final Entry entry = activeNotifications.get(i);
1756 if (entry.notification.getPackageName().equals(pkg)) {
1757 if (DEBUG_MEDIA) {
1758 Log.v(TAG, "DEBUG_MEDIA: found controller matching "
1759 + entry.notification.getKey());
Dan Sandler16128f42014-05-21 12:48:22 -04001760 }
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001761 controller = aController;
1762 mediaNotification = entry;
1763 break;
Dan Sandler16128f42014-05-21 12:48:22 -04001764 }
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001765 }
Dan Sandler16128f42014-05-21 12:48:22 -04001766 }
1767 }
1768 }
1769 }
1770
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001771 if (controller != null && !sameSessions(mMediaController, controller)) {
Dan Sandler16128f42014-05-21 12:48:22 -04001772 // We have a new media session
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001773 clearCurrentMediaNotification();
Dan Sandler16128f42014-05-21 12:48:22 -04001774 mMediaController = controller;
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001775 mMediaController.registerCallback(mMediaListener);
1776 mMediaMetadata = mMediaController.getMetadata();
Dan Sandler16128f42014-05-21 12:48:22 -04001777 if (DEBUG_MEDIA) {
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001778 Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: "
1779 + mMediaMetadata);
Dan Sandler16128f42014-05-21 12:48:22 -04001780 }
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001781
1782 if (mediaNotification != null) {
1783 mMediaNotificationKey = mediaNotification.notification.getKey();
1784 if (DEBUG_MEDIA) {
1785 Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
1786 + mMediaNotificationKey + " controller=" + mMediaController);
1787 }
1788 }
1789 metaDataChanged = true;
Dan Sandler16128f42014-05-21 12:48:22 -04001790 }
1791 }
1792
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001793 if (metaDataChanged) {
1794 updateNotifications();
1795 }
Adrian Roos52738322016-01-29 08:49:21 -08001796 updateMediaMetaData(metaDataChanged, true);
Dan Sandler16128f42014-05-21 12:48:22 -04001797 }
1798
Julia Reynoldsd30e42d2015-07-20 17:02:14 -04001799 private int getMediaControllerPlaybackState(MediaController controller) {
1800 if (controller != null) {
1801 final PlaybackState playbackState = controller.getPlaybackState();
1802 if (playbackState != null) {
1803 return playbackState.getState();
1804 }
1805 }
1806 return PlaybackState.STATE_NONE;
1807 }
1808
1809 private boolean isPlaybackActive(int state) {
1810 if (state != PlaybackState.STATE_STOPPED
1811 && state != PlaybackState.STATE_ERROR
1812 && state != PlaybackState.STATE_NONE) {
1813 return true;
1814 }
1815 return false;
1816 }
1817
1818 private void clearCurrentMediaNotification() {
1819 mMediaNotificationKey = null;
1820 mMediaMetadata = null;
1821 if (mMediaController != null) {
1822 if (DEBUG_MEDIA) {
1823 Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
1824 + mMediaController.getPackageName());
1825 }
1826 mMediaController.unregisterCallback(mMediaListener);
1827 }
1828 mMediaController = null;
1829 }
1830
Christoph Studerb5245d82014-09-19 16:54:36 +02001831 private boolean sameSessions(MediaController a, MediaController b) {
1832 if (a == b) return true;
1833 if (a == null) return false;
1834 return a.controlsSameSession(b);
1835 }
1836
Dan Sandler16128f42014-05-21 12:48:22 -04001837 /**
Dan Sandler7dea0ee2014-07-21 21:07:15 -04001838 * Hide the album artwork that is fading out and release its bitmap.
Dan Sandler16128f42014-05-21 12:48:22 -04001839 */
1840 private Runnable mHideBackdropFront = new Runnable() {
1841 @Override
1842 public void run() {
1843 if (DEBUG_MEDIA) {
1844 Log.v(TAG, "DEBUG_MEDIA: removing fade layer");
1845 }
1846 mBackdropFront.setVisibility(View.INVISIBLE);
Dan Sandler7dea0ee2014-07-21 21:07:15 -04001847 mBackdropFront.animate().cancel();
1848 mBackdropFront.setImageDrawable(null);
Dan Sandler16128f42014-05-21 12:48:22 -04001849 }
1850 };
1851
1852 /**
Adrian Roose381c162016-02-11 15:26:42 -08001853 * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
Dan Sandler16128f42014-05-21 12:48:22 -04001854 */
Adrian Roos52738322016-01-29 08:49:21 -08001855 public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
Dan Sandler16128f42014-05-21 12:48:22 -04001856 if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) return;
1857
1858 if (mBackdrop == null) return; // called too early
1859
Selim Cinek37c110f2015-05-22 12:38:44 -07001860 if (mLaunchTransitionFadingAway) {
1861 mBackdrop.setVisibility(View.INVISIBLE);
1862 return;
1863 }
1864
Dan Sandler16128f42014-05-21 12:48:22 -04001865 if (DEBUG_MEDIA) {
1866 Log.v(TAG, "DEBUG_MEDIA: updating album art for notification " + mMediaNotificationKey
Selim Cinek131c1e22015-05-11 19:04:49 -07001867 + " metadata=" + mMediaMetadata
1868 + " metaDataChanged=" + metaDataChanged
1869 + " state=" + mState);
Dan Sandler16128f42014-05-21 12:48:22 -04001870 }
1871
1872 Bitmap artworkBitmap = null;
1873 if (mMediaMetadata != null) {
1874 artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
1875 if (artworkBitmap == null) {
1876 artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
1877 // might still be null
1878 }
1879 }
Adrian Roos52738322016-01-29 08:49:21 -08001880 if (ENABLE_LOCKSCREEN_WALLPAPER && artworkBitmap == null) {
Adrian Roose381c162016-02-11 15:26:42 -08001881 artworkBitmap = mLockscreenWallpaper.getBitmap();
Adrian Roos52738322016-01-29 08:49:21 -08001882 }
Dan Sandler16128f42014-05-21 12:48:22 -04001883
1884 final boolean hasArtwork = artworkBitmap != null;
1885
Jorim Jaggi95d16bf2015-08-24 17:42:02 -07001886 if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && mState != StatusBarState.SHADE
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001887 && mFingerprintUnlockController.getMode()
1888 != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
Dan Sandler16128f42014-05-21 12:48:22 -04001889 // time to show some art!
1890 if (mBackdrop.getVisibility() != View.VISIBLE) {
1891 mBackdrop.setVisibility(View.VISIBLE);
Adrian Roos52738322016-01-29 08:49:21 -08001892 if (allowEnterAnimation) {
Adrian Roosd5c2db62016-03-08 16:11:31 -08001893 mBackdrop.animate().alpha(1f).withEndAction(new Runnable() {
1894 @Override
1895 public void run() {
1896 mStatusBarWindowManager.setBackdropShowing(true);
1897 }
1898 });
Adrian Roos52738322016-01-29 08:49:21 -08001899 } else {
1900 mBackdrop.animate().cancel();
1901 mBackdrop.setAlpha(1f);
Adrian Roosd5c2db62016-03-08 16:11:31 -08001902 mStatusBarWindowManager.setBackdropShowing(true);
Adrian Roos52738322016-01-29 08:49:21 -08001903 }
Dan Sandler16128f42014-05-21 12:48:22 -04001904 metaDataChanged = true;
1905 if (DEBUG_MEDIA) {
1906 Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
1907 }
1908 }
1909 if (metaDataChanged) {
1910 if (mBackdropBack.getDrawable() != null) {
Julia Reynolds4b9658a2015-07-22 17:07:42 -04001911 Drawable drawable =
1912 mBackdropBack.getDrawable().getConstantState().newDrawable().mutate();
Selim Cineka0fad3b2014-09-19 17:20:05 +02001913 mBackdropFront.setImageDrawable(drawable);
Jorim Jaggi0e664392014-09-27 01:30:22 +02001914 if (mScrimSrcModeEnabled) {
1915 mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode);
1916 }
Dan Sandler16128f42014-05-21 12:48:22 -04001917 mBackdropFront.setAlpha(1f);
1918 mBackdropFront.setVisibility(View.VISIBLE);
1919 } else {
1920 mBackdropFront.setVisibility(View.INVISIBLE);
1921 }
1922
1923 if (DEBUG_MEDIA_FAKE_ARTWORK) {
1924 final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF);
1925 Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c));
1926 mBackdropBack.setBackgroundColor(0xFFFFFFFF);
1927 mBackdropBack.setImageDrawable(new ColorDrawable(c));
1928 } else {
1929 mBackdropBack.setImageBitmap(artworkBitmap);
1930 }
Jorim Jaggi0e664392014-09-27 01:30:22 +02001931 if (mScrimSrcModeEnabled) {
1932 mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode);
1933 }
Dan Sandler16128f42014-05-21 12:48:22 -04001934
1935 if (mBackdropFront.getVisibility() == View.VISIBLE) {
1936 if (DEBUG_MEDIA) {
1937 Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from "
1938 + mBackdropFront.getDrawable()
1939 + " to "
1940 + mBackdropBack.getDrawable());
1941 }
Jorim Jaggi4e0880e2014-07-25 14:51:50 +02001942 mBackdropFront.animate()
Dan Sandler16128f42014-05-21 12:48:22 -04001943 .setDuration(250)
1944 .alpha(0f).withEndAction(mHideBackdropFront);
1945 }
1946 }
1947 } else {
1948 // need to hide the album art, either because we are unlocked or because
1949 // the metadata isn't there to support it
1950 if (mBackdrop.getVisibility() != View.GONE) {
1951 if (DEBUG_MEDIA) {
1952 Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
1953 }
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001954 if (mFingerprintUnlockController.getMode()
1955 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) {
Jorim Jaggi4e0880e2014-07-25 14:51:50 +02001956
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001957 // We are unlocking directly - no animation!
1958 mBackdrop.setVisibility(View.GONE);
Vadim Trysheve7d7d572016-03-09 16:44:30 -08001959 mBackdropBack.setImageDrawable(null);
Adrian Roosd5c2db62016-03-08 16:11:31 -08001960 mStatusBarWindowManager.setBackdropShowing(false);
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001961 } else {
Adrian Roosd5c2db62016-03-08 16:11:31 -08001962 mStatusBarWindowManager.setBackdropShowing(false);
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001963 mBackdrop.animate()
1964 // Never let the alpha become zero - otherwise the RenderNode
1965 // won't draw anything and uninitialized memory will show through
1966 // if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
1967 // libhwui.
1968 .alpha(0.002f)
Selim Cinekc18010f2016-01-20 13:41:30 -08001969 .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001970 .setDuration(300)
1971 .setStartDelay(0)
1972 .withEndAction(new Runnable() {
1973 @Override
1974 public void run() {
1975 mBackdrop.setVisibility(View.GONE);
1976 mBackdropFront.animate().cancel();
Vadim Trysheve7d7d572016-03-09 16:44:30 -08001977 mBackdropBack.setImageDrawable(null);
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001978 mHandler.post(mHideBackdropFront);
1979 }
1980 });
1981 if (mKeyguardFadingAway) {
1982 mBackdrop.animate()
1983
1984 // Make it disappear faster, as the focus should be on the activity
1985 // behind.
1986 .setDuration(mKeyguardFadingAwayDuration / 2)
1987 .setStartDelay(mKeyguardFadingAwayDelay)
Selim Cinekc18010f2016-01-20 13:41:30 -08001988 .setInterpolator(Interpolators.LINEAR)
Jorim Jaggid94d3a22015-08-21 16:52:55 -07001989 .start();
1990 }
Jorim Jaggi4e0880e2014-07-25 14:51:50 +02001991 }
Dan Sandler16128f42014-05-21 12:48:22 -04001992 }
1993 }
1994 }
1995
Xiaohui Cheneb04a992016-03-22 14:58:03 -07001996 protected int adjustDisableFlags(int state) {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -07001997 if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway
Selim Cinekbaa23272014-07-08 18:01:07 +02001998 && (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) {
Jorim Jaggib13d36d2014-06-06 18:03:52 +02001999 state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
2000 state |= StatusBarManager.DISABLE_SYSTEM_INFO;
2001 }
2002 return state;
2003 }
2004
Joe Onorato808182d2010-07-09 18:52:06 -04002005 /**
2006 * State is one or more of the DISABLE constants from StatusBarManager.
2007 */
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002008 public void disable(int state1, int state2, boolean animate) {
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002009 animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002010 mDisabledUnmodified1 = state1;
2011 mDisabledUnmodified2 = state2;
2012 state1 = adjustDisableFlags(state1);
2013 final int old1 = mDisabled1;
2014 final int diff1 = state1 ^ old1;
2015 mDisabled1 = state1;
2016
2017 final int old2 = mDisabled2;
2018 final int diff2 = state2 ^ old2;
2019 mDisabled2 = state2;
Joe Onorato808182d2010-07-09 18:52:06 -04002020
Daniel Sandlere21f2882011-08-18 10:14:59 -04002021 if (DEBUG) {
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002022 Log.d(TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)",
2023 old1, state1, diff1));
2024 Log.d(TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)",
2025 old2, state2, diff2));
Daniel Sandlere21f2882011-08-18 10:14:59 -04002026 }
2027
Daniel Sandler6da2b762011-09-14 16:04:59 -04002028 StringBuilder flagdbg = new StringBuilder();
2029 flagdbg.append("disable: < ");
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002030 flagdbg.append(((state1 & StatusBarManager.DISABLE_EXPAND) != 0) ? "EXPAND" : "expand");
2031 flagdbg.append(((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) ? "* " : " ");
2032 flagdbg.append(((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "ICONS" : "icons");
2033 flagdbg.append(((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " ");
2034 flagdbg.append(((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts");
2035 flagdbg.append(((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " ");
2036 flagdbg.append(((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info");
2037 flagdbg.append(((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " ");
2038 flagdbg.append(((state1 & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back");
2039 flagdbg.append(((diff1 & StatusBarManager.DISABLE_BACK) != 0) ? "* " : " ");
2040 flagdbg.append(((state1 & StatusBarManager.DISABLE_HOME) != 0) ? "HOME" : "home");
2041 flagdbg.append(((diff1 & StatusBarManager.DISABLE_HOME) != 0) ? "* " : " ");
2042 flagdbg.append(((state1 & StatusBarManager.DISABLE_RECENT) != 0) ? "RECENT" : "recent");
2043 flagdbg.append(((diff1 & StatusBarManager.DISABLE_RECENT) != 0) ? "* " : " ");
2044 flagdbg.append(((state1 & StatusBarManager.DISABLE_CLOCK) != 0) ? "CLOCK" : "clock");
2045 flagdbg.append(((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) ? "* " : " ");
2046 flagdbg.append(((state1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "SEARCH" : "search");
2047 flagdbg.append(((diff1 & StatusBarManager.DISABLE_SEARCH) != 0) ? "* " : " ");
Benjamin Franz27cf1462015-04-23 19:36:42 +01002048 flagdbg.append(((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "QUICK_SETTINGS"
2049 : "quick_settings");
2050 flagdbg.append(((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) ? "* " : " ");
Daniel Sandler6da2b762011-09-14 16:04:59 -04002051 flagdbg.append(">");
John Spurlockcd686b52013-06-05 10:13:46 -04002052 Log.d(TAG, flagdbg.toString());
Jim Millera073e572012-05-23 17:03:27 -07002053
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002054 if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
2055 if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
Jorim Jaggi66ac1332015-01-21 19:22:26 +01002056 mIconController.hideSystemIconArea(animate);
Daniel Sandler8e18dc72012-05-17 00:44:59 -04002057 } else {
Jorim Jaggi66ac1332015-01-21 19:22:26 +01002058 mIconController.showSystemIconArea(animate);
Daniel Sandler8e18dc72012-05-17 00:44:59 -04002059 }
2060 }
Daniel Sandler6da2b762011-09-14 16:04:59 -04002061
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002062 if ((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) {
2063 boolean visible = (state1 & StatusBarManager.DISABLE_CLOCK) == 0;
Jorim Jaggi66ac1332015-01-21 19:22:26 +01002064 mIconController.setClockVisibility(visible);
Jeff Sharkeyf52c70b2011-08-30 22:05:47 -07002065 }
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002066 if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
2067 if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {
Daniel Sandler11cf1782012-09-27 14:03:08 -04002068 animateCollapsePanels();
Joe Onorato808182d2010-07-09 18:52:06 -04002069 }
2070 }
Daniel Sandlere21f2882011-08-18 10:14:59 -04002071
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002072 if ((diff1 & (StatusBarManager.DISABLE_HOME
Jim Miller5e6af442011-12-02 18:24:26 -08002073 | StatusBarManager.DISABLE_RECENT
Daniel Sandlerd5483c32012-10-19 16:44:15 -04002074 | StatusBarManager.DISABLE_BACK
2075 | StatusBarManager.DISABLE_SEARCH)) != 0) {
Daniel Sandlerdba93562011-10-06 16:39:58 -04002076 // the nav bar will take care of these
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002077 if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1);
Daniel Sandler6da2b762011-09-14 16:04:59 -04002078
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002079 if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) {
Daniel Sandler6da2b762011-09-14 16:04:59 -04002080 // close recents if it's visible
Winson Chung1e8d71b2014-05-16 17:05:22 -07002081 mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
2082 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
Daniel Sandler6da2b762011-09-14 16:04:59 -04002083 }
Daniel Sandlere21f2882011-08-18 10:14:59 -04002084 }
2085
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002086 if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
2087 if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
Jorim Jaggi66ac1332015-01-21 19:22:26 +01002088 mIconController.hideNotificationIconArea(animate);
Joe Onorato808182d2010-07-09 18:52:06 -04002089 } else {
Jorim Jaggi66ac1332015-01-21 19:22:26 +01002090 mIconController.showNotificationIconArea(animate);
Joe Onorato808182d2010-07-09 18:52:06 -04002091 }
Joe Onorato808182d2010-07-09 18:52:06 -04002092 }
Jason Monkf7019542014-07-31 12:42:25 -04002093
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002094 if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
Jason Monkf7019542014-07-31 12:42:25 -04002095 mDisableNotificationAlerts =
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002096 (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
Jason Monkf7019542014-07-31 12:42:25 -04002097 mHeadsUpObserver.onChange(true);
2098 }
Benjamin Franz27cf1462015-04-23 19:36:42 +01002099
2100 if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) {
2101 updateQsExpansionEnabled();
2102 }
Joe Onorato808182d2010-07-09 18:52:06 -04002103 }
2104
Michael Jurka7f2668c2012-03-27 07:49:52 -07002105 @Override
Michael Jurkaecc395a2012-03-30 05:31:46 -07002106 protected BaseStatusBar.H createHandler() {
Michael Jurka7f2668c2012-03-27 07:49:52 -07002107 return new PhoneStatusBar.H();
2108 }
2109
Jorim Jaggi97b63c42014-05-02 23:03:34 +02002110 @Override
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02002111 public void startActivity(Intent intent, boolean dismissShade) {
2112 startActivityDismissingKeyguard(intent, false, dismissShade);
Jorim Jaggi97b63c42014-05-02 23:03:34 +02002113 }
2114
Selim Cineke70d6532015-04-24 16:46:13 -07002115 @Override
Jorim Jaggid9449862015-05-29 14:49:08 -07002116 public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
2117 startActivityDismissingKeyguard(intent, false, dismissShade, callback);
2118 }
2119
2120 @Override
Selim Cineke70d6532015-04-24 16:46:13 -07002121 public void preventNextAnimation() {
2122 overrideActivityPendingAppTransition(true /* keyguardShowing */);
2123 }
2124
Jorim Jaggib690f0d2014-07-03 23:25:44 +02002125 public void setQsExpanded(boolean expanded) {
2126 mStatusBarWindowManager.setQsExpanded(expanded);
Adrian Roos4c7d9602015-06-10 13:44:48 -07002127 mKeyguardStatusView.setImportantForAccessibility(expanded
2128 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
2129 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
Jorim Jaggib690f0d2014-07-03 23:25:44 +02002130 }
2131
Jorim Jaggi84a3e7a2014-08-13 17:58:58 +02002132 public boolean isGoingToNotificationShade() {
2133 return mLeaveOpenOnKeyguardHide;
2134 }
2135
Jorim Jaggid692dd02014-08-14 20:57:42 +02002136 public boolean isQsExpanded() {
2137 return mNotificationPanel.isQsExpanded();
2138 }
2139
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07002140 public boolean isWakeUpComingFromTouch() {
2141 return mWakeUpComingFromTouch;
Selim Cinek29ed3c92014-09-23 20:44:35 +02002142 }
2143
Selim Cinek19c8c702014-08-25 22:09:19 +02002144 public boolean isFalsingThresholdNeeded() {
Selim Cinek9db71052015-04-24 18:54:30 -07002145 return getBarState() == StatusBarState.KEYGUARD;
Selim Cinek19c8c702014-08-25 22:09:19 +02002146 }
2147
John Spurlock0b99ea92014-10-01 15:32:22 -04002148 public boolean isDozing() {
2149 return mDozing;
2150 }
2151
Christoph Studer2e731b52014-08-22 16:01:51 +02002152 @Override // NotificationData.Environment
2153 public String getCurrentMediaNotificationKey() {
2154 return mMediaNotificationKey;
2155 }
2156
Jorim Jaggi0e664392014-09-27 01:30:22 +02002157 public boolean isScrimSrcModeEnabled() {
2158 return mScrimSrcModeEnabled;
2159 }
2160
Joe Onorato808182d2010-07-09 18:52:06 -04002161 /**
Christoph Studer2231c6e2014-12-19 12:40:13 +01002162 * To be called when there's a state change in StatusBarKeyguardViewManager.
2163 */
2164 public void onKeyguardViewManagerStatesUpdated() {
2165 logStateToEventlog();
2166 }
2167
2168 @Override // UnlockMethodCache.OnUnlockMethodChangedListener
2169 public void onUnlockMethodStateChanged() {
2170 logStateToEventlog();
2171 }
2172
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002173 @Override
John Spurlockb349af572015-04-29 12:24:19 -04002174 public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
Selim Cinek684a4422015-04-15 16:18:39 -07002175 if (inPinnedMode) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002176 mStatusBarWindowManager.setHeadsUpShowing(true);
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002177 mStatusBarWindowManager.setForceStatusBarVisible(true);
Selim Cinek131c1e22015-05-11 19:04:49 -07002178 if (mNotificationPanel.isFullyCollapsed()) {
2179 // We need to ensure that the touchable region is updated before the window will be
2180 // resized, in order to not catch any touches. A layout will ensure that
2181 // onComputeInternalInsets will be called and after that we can resize the layout. Let's
2182 // make sure that the window stays small for one frame until the touchableRegion is set.
2183 mNotificationPanel.requestLayout();
2184 mStatusBarWindowManager.setForceWindowCollapsed(true);
2185 mNotificationPanel.post(new Runnable() {
2186 @Override
2187 public void run() {
2188 mStatusBarWindowManager.setForceWindowCollapsed(false);
2189 }
2190 });
2191 }
Selim Cinek737bff32015-05-08 16:08:35 -07002192 } else {
Selim Cinek131c1e22015-05-11 19:04:49 -07002193 if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()) {
2194 // We are currently tracking or is open and the shade doesn't need to be kept
2195 // open artificially.
Selim Cinek737bff32015-05-08 16:08:35 -07002196 mStatusBarWindowManager.setHeadsUpShowing(false);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002197 } else {
Selim Cinek131c1e22015-05-11 19:04:49 -07002198 // we need to keep the panel open artificially, let's wait until the animation
2199 // is finished.
Selim Cinek737bff32015-05-08 16:08:35 -07002200 mHeadsUpManager.setHeadsUpGoingAway(true);
2201 mStackScroller.runAfterAnimationFinished(new Runnable() {
2202 @Override
2203 public void run() {
2204 if (!mHeadsUpManager.hasPinnedHeadsUp()) {
2205 mStatusBarWindowManager.setHeadsUpShowing(false);
2206 mHeadsUpManager.setHeadsUpGoingAway(false);
2207 }
2208 }
2209 });
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002210 }
2211 }
2212 }
2213
2214 @Override
Selim Cinek684a4422015-04-15 16:18:39 -07002215 public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
John Spurlockb349af572015-04-29 12:24:19 -04002216 dismissVolumeDialog();
Selim Cinek1f3f5442015-04-10 17:54:46 -07002217 }
2218
2219 @Override
Selim Cinek684a4422015-04-15 16:18:39 -07002220 public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
2221 }
2222
2223 @Override
2224 public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002225 if (!isHeadsUp && mHeadsUpEntriesToRemoveOnSwitch.contains(entry)) {
2226 removeNotification(entry.key, mLatestRankingMap);
2227 mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
2228 if (mHeadsUpEntriesToRemoveOnSwitch.isEmpty()) {
2229 mLatestRankingMap = null;
2230 }
Selim Cinekfbe9a442015-04-13 16:09:49 -07002231 } else {
2232 updateNotificationRanking(null);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002233 }
Selim Cinekfbe9a442015-04-13 16:09:49 -07002234
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002235 }
2236
Chris Wrenbdf33762015-12-04 15:50:51 -05002237 protected void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
Selim Cinek29fa89b2015-04-17 10:39:11 -07002238 boolean alertAgain) {
2239 final boolean wasHeadsUp = isHeadsUp(key);
2240 if (wasHeadsUp) {
Chris Wrenbdf33762015-12-04 15:50:51 -05002241 if (!shouldPeek) {
Selim Cinek29fa89b2015-04-17 10:39:11 -07002242 // We don't want this to be interrupting anymore, lets remove it
2243 mHeadsUpManager.removeNotification(key);
Selim Cinek684a4422015-04-15 16:18:39 -07002244 } else {
2245 mHeadsUpManager.updateNotification(entry, alertAgain);
Selim Cinek29fa89b2015-04-17 10:39:11 -07002246 }
Chris Wrenbdf33762015-12-04 15:50:51 -05002247 } else if (shouldPeek && alertAgain) {
Selim Cinek29fa89b2015-04-17 10:39:11 -07002248 // This notification was updated to be a heads-up, show it!
2249 mHeadsUpManager.showNotification(entry);
2250 }
2251 }
2252
2253 protected void setHeadsUpUser(int newUserId) {
2254 if (mHeadsUpManager != null) {
2255 mHeadsUpManager.setUser(newUserId);
2256 }
2257 }
2258
2259 public boolean isHeadsUp(String key) {
2260 return mHeadsUpManager.isHeadsUp(key);
2261 }
2262
2263 protected boolean isSnoozedPackage(StatusBarNotification sbn) {
2264 return mHeadsUpManager.isSnoozed(sbn.getPackageName());
2265 }
2266
Selim Cineke70d6532015-04-24 16:46:13 -07002267 public boolean isKeyguardCurrentlySecure() {
Selim Cineke8bae622015-07-15 13:24:06 -07002268 return !mUnlockMethodCache.canSkipBouncer();
Selim Cineke70d6532015-04-24 16:46:13 -07002269 }
2270
Selim Cinek4a21a7f2015-05-19 11:00:38 -07002271 public void setPanelExpanded(boolean isExpanded) {
2272 mStatusBarWindowManager.setPanelExpanded(isExpanded);
2273 }
2274
Adrian Roos401caae2016-03-04 13:35:21 -08002275 public void onScreenTurnedOff() {
2276 mFalsingManager.onScreenOff();
2277 }
2278
Christoph Studer2231c6e2014-12-19 12:40:13 +01002279 /**
Joe Onorato808182d2010-07-09 18:52:06 -04002280 * All changes to the status bar and notifications funnel through here and are batched.
2281 */
Michael Jurka7f2668c2012-03-27 07:49:52 -07002282 private class H extends BaseStatusBar.H {
Joe Onorato808182d2010-07-09 18:52:06 -04002283 public void handleMessage(Message m) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07002284 super.handleMessage(m);
Joe Onorato808182d2010-07-09 18:52:06 -04002285 switch (m.what) {
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002286 case MSG_OPEN_NOTIFICATION_PANEL:
Daniel Sandler11cf1782012-09-27 14:03:08 -04002287 animateExpandNotificationsPanel();
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002288 break;
Daniel Sandler11cf1782012-09-27 14:03:08 -04002289 case MSG_OPEN_SETTINGS_PANEL:
Jason Monka9927322015-12-13 16:22:37 -05002290 animateExpandSettingsPanel((String) m.obj);
Daniel Sandler11cf1782012-09-27 14:03:08 -04002291 break;
2292 case MSG_CLOSE_PANELS:
2293 animateCollapsePanels();
Daniel Sandler8ba33c92011-10-04 21:49:30 -04002294 break;
Jorim Jaggi826730a2014-12-08 21:05:13 +01002295 case MSG_LAUNCH_TRANSITION_TIMEOUT:
2296 onLaunchTransitionTimeout();
2297 break;
Chris Wrene97f90b2013-08-07 17:39:35 -04002298 }
2299 }
2300 }
2301
Chris Wren930ecca2014-11-12 17:43:41 -05002302 @Override
Selim Cinek684a4422015-04-15 16:18:39 -07002303 public void maybeEscalateHeadsUp() {
Selim Cinek3362c132016-02-11 15:43:03 -08002304 Collection<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getAllEntries();
Selim Cineka59ecc32015-04-07 10:51:49 -07002305 for (HeadsUpManager.HeadsUpEntry entry : entries) {
2306 final StatusBarNotification sbn = entry.entry.notification;
Chris Wrene97f90b2013-08-07 17:39:35 -04002307 final Notification notification = sbn.getNotification();
2308 if (notification.fullScreenIntent != null) {
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002309 if (DEBUG) {
Chris Wrene97f90b2013-08-07 17:39:35 -04002310 Log.d(TAG, "converting a heads up to fullScreen");
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002311 }
Chris Wrene97f90b2013-08-07 17:39:35 -04002312 try {
Chris Wren223c66b62014-11-10 16:00:09 -05002313 EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
2314 sbn.getKey());
Chris Wrene97f90b2013-08-07 17:39:35 -04002315 notification.fullScreenIntent.send();
Selim Cinekb18a20f2015-06-04 17:08:35 +02002316 entry.entry.notifyFullScreenIntentLaunched();
Chris Wrene97f90b2013-08-07 17:39:35 -04002317 } catch (PendingIntent.CanceledException e) {
2318 }
Joe Onorato808182d2010-07-09 18:52:06 -04002319 }
2320 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002321 mHeadsUpManager.releaseAllImmediately();
Joe Onorato808182d2010-07-09 18:52:06 -04002322 }
2323
John Spurlock97642182013-07-29 17:58:39 -04002324 boolean panelsEnabled() {
Adrian Roos21d2a252015-06-01 13:59:59 -07002325 return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && !ONLY_CORE_APPS;
John Spurlock97642182013-07-29 17:58:39 -04002326 }
2327
Jorim Jaggifa505a72014-04-28 20:04:11 +02002328 void makeExpandedVisible(boolean force) {
John Spurlockcd686b52013-06-05 10:13:46 -04002329 if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
Jorim Jaggifa505a72014-04-28 20:04:11 +02002330 if (!force && (mExpandedVisible || !panelsEnabled())) {
Joe Onorato808182d2010-07-09 18:52:06 -04002331 return;
2332 }
Jim Millera073e572012-05-23 17:03:27 -07002333
Joe Onorato808182d2010-07-09 18:52:06 -04002334 mExpandedVisible = true;
John Spurlockd5ef5462012-06-13 11:19:51 -04002335 if (mNavigationBarView != null)
2336 mNavigationBarView.setSlippery(true);
Joe Onorato808182d2010-07-09 18:52:06 -04002337
Daniel Sandlera310af82012-04-24 01:20:13 -04002338 // Expand the window to encompass the full screen in anticipation of the drag.
2339 // This is only possible to do atomically because the status bar is at the top of the screen!
Selim Cinek4a21a7f2015-05-19 11:00:38 -07002340 mStatusBarWindowManager.setPanelVisible(true);
Jorim Jaggi380ecb82014-03-14 17:25:20 +01002341
2342 visibilityChanged(true);
Jorim Jaggi44cf9192014-06-17 19:16:00 -07002343 mWaitingForKeyguardExit = false;
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002344 disable(mDisabledUnmodified1, mDisabledUnmodified2, !force /* animate */);
Jorim Jaggi380ecb82014-03-14 17:25:20 +01002345 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
2346 }
2347
Daniel Sandler11cf1782012-09-27 14:03:08 -04002348 public void animateCollapsePanels() {
2349 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
Michael Jurka3b1fc472011-06-13 10:54:40 -07002350 }
2351
John Spurlockaf8d6c42014-05-07 17:49:08 -04002352 private final Runnable mAnimateCollapsePanels = new Runnable() {
2353 @Override
2354 public void run() {
2355 animateCollapsePanels();
2356 }
2357 };
2358
2359 public void postAnimateCollapsePanels() {
2360 mHandler.post(mAnimateCollapsePanels);
2361 }
2362
Jason Monkba2318e2015-12-08 09:04:23 -05002363 public void postAnimateOpenPanels() {
2364 mHandler.sendEmptyMessage(MSG_OPEN_SETTINGS_PANEL);
2365 }
2366
Daniel Sandler11cf1782012-09-27 14:03:08 -04002367 public void animateCollapsePanels(int flags) {
Jorim Jaggif3b3bee2015-04-16 14:57:34 -07002368 animateCollapsePanels(flags, false /* force */, false /* delayed */,
2369 1.0f /* speedUpFactor */);
Jorim Jaggi34250762014-07-03 23:51:19 +02002370 }
2371
2372 public void animateCollapsePanels(int flags, boolean force) {
Jorim Jaggif3b3bee2015-04-16 14:57:34 -07002373 animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */);
Jorim Jaggi27c9b742015-04-09 10:34:49 -07002374 }
2375
2376 public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
Jorim Jaggif3b3bee2015-04-16 14:57:34 -07002377 animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */);
2378 }
2379
2380 public void animateCollapsePanels(int flags, boolean force, boolean delayed,
2381 float speedUpFactor) {
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -07002382 if (!force && mState != StatusBarState.SHADE) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02002383 runPostCollapseRunnables();
Jorim Jaggic1cf1ae2014-05-02 21:19:17 +02002384 return;
2385 }
Joe Onorato808182d2010-07-09 18:52:06 -04002386 if (SPEW) {
John Spurlockcd686b52013-06-05 10:13:46 -04002387 Log.d(TAG, "animateCollapse():"
Joe Onorato808182d2010-07-09 18:52:06 -04002388 + " mExpandedVisible=" + mExpandedVisible
Jim Miller9a720f52012-05-30 03:19:43 -07002389 + " flags=" + flags);
Joe Onorato808182d2010-07-09 18:52:06 -04002390 }
2391
Jim Miller9a720f52012-05-30 03:19:43 -07002392 if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
Winson Chungcdcd4872014-08-05 18:00:13 -07002393 if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) {
2394 mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
2395 mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS);
2396 }
Michael Jurka3b1fc472011-06-13 10:54:40 -07002397 }
Jim Miller9a720f52012-05-30 03:19:43 -07002398
Jorim Jaggi5cf17872014-03-26 18:31:48 +01002399 if (mStatusBarWindow != null) {
Jorim Jaggi03c701e2014-04-02 12:39:51 +02002400 // release focus immediately to kick off focus change transition
2401 mStatusBarWindowManager.setStatusBarFocusable(false);
2402
John Spurlockab847cf2014-01-15 14:13:59 -05002403 mStatusBarWindow.cancelExpandHelper();
Xiaohui Chen9f967112016-01-07 14:14:06 -08002404 mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
John Spurlockab847cf2014-01-15 14:13:59 -05002405 }
Joe Onorato808182d2010-07-09 18:52:06 -04002406 }
2407
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02002408 private void runPostCollapseRunnables() {
Selim Cinekae77f8e2015-07-07 18:43:59 -07002409 ArrayList<Runnable> clonedList = new ArrayList<>(mPostCollapseRunnables);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02002410 mPostCollapseRunnables.clear();
Selim Cinekae77f8e2015-07-07 18:43:59 -07002411 int size = clonedList.size();
2412 for (int i = 0; i < size; i++) {
2413 clonedList.get(i).run();
2414 }
2415
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02002416 }
2417
Daniel Sandler08d05e32012-08-08 16:39:54 -04002418 @Override
Daniel Sandler11cf1782012-09-27 14:03:08 -04002419 public void animateExpandNotificationsPanel() {
John Spurlockcd686b52013-06-05 10:13:46 -04002420 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
John Spurlock97642182013-07-29 17:58:39 -04002421 if (!panelsEnabled()) {
Joe Onorato808182d2010-07-09 18:52:06 -04002422 return ;
2423 }
Joe Onorato808182d2010-07-09 18:52:06 -04002424
Oren Blasberg8d3fea12015-07-10 14:21:44 -07002425 mNotificationPanel.expand(true /* animate */);
Joe Onorato808182d2010-07-09 18:52:06 -04002426
2427 if (false) postStartTracing();
2428 }
2429
Svetoslav Ganove20a1772012-09-25 16:07:46 -07002430 @Override
Jason Monka9927322015-12-13 16:22:37 -05002431 public void animateExpandSettingsPanel(String subPanel) {
John Spurlockcd686b52013-06-05 10:13:46 -04002432 if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
John Spurlock97642182013-07-29 17:58:39 -04002433 if (!panelsEnabled()) {
Svetoslav Ganove20a1772012-09-25 16:07:46 -07002434 return;
2435 }
2436
Daniel Sandlera8ef3b02012-11-29 15:52:39 -05002437 // Settings are not available in setup
2438 if (!mUserSetup) return;
2439
Jason Monka9927322015-12-13 16:22:37 -05002440
2441 if (subPanel != null) {
2442 mQSPanel.openDetails(subPanel);
2443 }
Jason Monk3c68ca22015-01-30 11:30:29 -05002444 mNotificationPanel.expandWithQs();
Svetoslav Ganove20a1772012-09-25 16:07:46 -07002445
2446 if (false) postStartTracing();
2447 }
2448
2449 public void animateCollapseQuickSettings() {
Jorim Jaggi449981b2014-10-03 14:24:55 -07002450 if (mState == StatusBarState.SHADE) {
Xiaohui Chen9f967112016-01-07 14:14:06 -08002451 mStatusBarView.collapsePanel(true, false /* delayed */, 1.0f /* speedUpFactor */);
Jorim Jaggi449981b2014-10-03 14:24:55 -07002452 }
Svetoslav Ganove20a1772012-09-25 16:07:46 -07002453 }
2454
Daniel Sandler08d05e32012-08-08 16:39:54 -04002455 void makeExpandedInvisible() {
John Spurlockcd686b52013-06-05 10:13:46 -04002456 if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
Joe Onorato808182d2010-07-09 18:52:06 -04002457 + " mExpandedVisible=" + mExpandedVisible);
2458
Jorim Jaggi5cf17872014-03-26 18:31:48 +01002459 if (!mExpandedVisible || mStatusBarWindow == null) {
Joe Onorato808182d2010-07-09 18:52:06 -04002460 return;
2461 }
Daniel Sandlered930e52012-07-03 14:31:22 -04002462
Daniel Sandlerc38bbc32012-10-05 12:21:38 -04002463 // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
Xiaohui Chen9f967112016-01-07 14:14:06 -08002464 mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/,
Jorim Jaggif3b3bee2015-04-16 14:57:34 -07002465 1.0f /* speedUpFactor */);
Daniel Sandlered930e52012-07-03 14:31:22 -04002466
Jorim Jaggid7daab72014-05-06 22:22:20 +02002467 mNotificationPanel.closeQs();
Daniel Sandler040c2e42012-10-17 00:56:33 -04002468
Joe Onorato808182d2010-07-09 18:52:06 -04002469 mExpandedVisible = false;
John Spurlockd5ef5462012-06-13 11:19:51 -04002470 if (mNavigationBarView != null)
2471 mNavigationBarView.setSlippery(false);
Joe Onorato808182d2010-07-09 18:52:06 -04002472 visibilityChanged(false);
Daniel Sandlera310af82012-04-24 01:20:13 -04002473
2474 // Shrink the window to the size of the status bar only
Selim Cinek4a21a7f2015-05-19 11:00:38 -07002475 mStatusBarWindowManager.setPanelVisible(false);
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002476 mStatusBarWindowManager.setForceStatusBarVisible(false);
Joe Onorato808182d2010-07-09 18:52:06 -04002477
Daniel Sandler469e96e2012-05-04 15:56:19 -04002478 // Close any "App info" popups that might have snuck on-screen
2479 dismissPopups();
2480
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02002481 runPostCollapseRunnables();
John Spurlockcfc359a2013-09-05 10:42:03 -04002482 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
Jorim Jaggi03c701e2014-04-02 12:39:51 +02002483 showBouncer();
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002484 disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */);
Jorim Jaggi786afcb2014-09-25 02:41:29 +02002485
2486 // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
2487 // the bouncer appear animation.
2488 if (!mStatusBarKeyguardViewManager.isShowing()) {
2489 WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
2490 }
Joe Onorato808182d2010-07-09 18:52:06 -04002491 }
2492
Daniel Sandlerb17a7262012-10-05 14:32:50 -04002493 public boolean interceptTouchEvent(MotionEvent event) {
Chris Wren64161cc2012-12-17 16:49:30 -05002494 if (DEBUG_GESTURES) {
2495 if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
2496 EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH,
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002497 event.getActionMasked(), (int) event.getX(), (int) event.getY(),
2498 mDisabled1, mDisabled2);
Chris Wren64161cc2012-12-17 16:49:30 -05002499 }
2500
2501 }
2502
Joe Onorato808182d2010-07-09 18:52:06 -04002503 if (SPEW) {
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002504 Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1="
2505 + mDisabled1 + " mDisabled2=" + mDisabled2 + " mTracking=" + mTracking);
Daniel Sandler96e61c3c82011-08-04 22:49:06 -04002506 } else if (CHATTY) {
Daniel Sandlerfe172cc2011-09-12 13:47:25 -04002507 if (event.getAction() != MotionEvent.ACTION_MOVE) {
John Spurlockcd686b52013-06-05 10:13:46 -04002508 Log.d(TAG, String.format(
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002509 "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x",
Daniel Sandlerfe172cc2011-09-12 13:47:25 -04002510 MotionEvent.actionToString(event.getAction()),
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01002511 event.getRawX(), event.getRawY(), mDisabled1, mDisabled2));
Daniel Sandler96e61c3c82011-08-04 22:49:06 -04002512 }
Joe Onorato808182d2010-07-09 18:52:06 -04002513 }
2514
Daniel Sandler151f00d2012-10-02 22:33:08 -04002515 if (DEBUG_GESTURES) {
2516 mGestureRec.add(event);
2517 }
Daniel Sandler33805342012-07-23 15:45:12 -04002518
John Spurlock686820a2013-09-03 14:44:16 -04002519 if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
John Spurlock5fee8362013-09-12 10:34:33 -04002520 final boolean upOrCancel =
2521 event.getAction() == MotionEvent.ACTION_UP ||
2522 event.getAction() == MotionEvent.ACTION_CANCEL;
2523 if (upOrCancel && !mExpandedVisible) {
2524 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
2525 } else {
2526 setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
2527 }
John Spurlock686820a2013-09-03 14:44:16 -04002528 }
Joe Onorato808182d2010-07-09 18:52:06 -04002529 return false;
2530 }
2531
Daniel Sandler08d05e32012-08-08 16:39:54 -04002532 public GestureRecorder getGestureRecorder() {
2533 return mGestureRec;
Jeff Brown911fe302011-09-12 14:21:17 -07002534 }
2535
John Spurlock56d007b2013-10-28 18:40:56 -04002536 private void setNavigationIconHints(int hints) {
Daniel Sandler328310c2011-09-23 15:56:52 -04002537 if (hints == mNavigationIconHints) return;
2538
2539 mNavigationIconHints = hints;
2540
2541 if (mNavigationBarView != null) {
2542 mNavigationBarView.setNavigationIconHints(hints);
2543 }
John Spurlockd4e65752013-08-28 14:17:09 -04002544 checkBarModes();
Daniel Sandler328310c2011-09-23 15:56:52 -04002545 }
2546
2547 @Override // CommandQueue
John Spurlock97642182013-07-29 17:58:39 -04002548 public void setWindowState(int window, int state) {
John Spurlockd4e65752013-08-28 14:17:09 -04002549 boolean showing = state == WINDOW_STATE_SHOWING;
John Spurlock97642182013-07-29 17:58:39 -04002550 if (mStatusBarWindow != null
2551 && window == StatusBarManager.WINDOW_STATUS_BAR
2552 && mStatusBarWindowState != state) {
2553 mStatusBarWindowState = state;
John Spurlock0ec64c62013-08-26 15:37:58 -04002554 if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state));
Jorim Jaggi449981b2014-10-03 14:24:55 -07002555 if (!showing && mState == StatusBarState.SHADE) {
Xiaohui Chen9f967112016-01-07 14:14:06 -08002556 mStatusBarView.collapsePanel(false /* animate */, false /* delayed */,
Jorim Jaggif3b3bee2015-04-16 14:57:34 -07002557 1.0f /* speedUpFactor */);
John Spurlock97642182013-07-29 17:58:39 -04002558 }
2559 }
2560 if (mNavigationBarView != null
2561 && window == StatusBarManager.WINDOW_NAVIGATION_BAR
2562 && mNavigationBarWindowState != state) {
2563 mNavigationBarWindowState = state;
John Spurlock0ec64c62013-08-26 15:37:58 -04002564 if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state));
John Spurlock97642182013-07-29 17:58:39 -04002565 }
2566 }
2567
John Spurlock97642182013-07-29 17:58:39 -04002568 @Override // CommandQueue
John Spurlockcad57682014-07-26 17:09:56 -04002569 public void buzzBeepBlinked() {
2570 if (mDozeServiceHost != null) {
2571 mDozeServiceHost.fireBuzzBeepBlinked();
2572 }
2573 }
2574
John Spurlockcb566aa2014-08-03 22:58:28 -04002575 @Override
2576 public void notificationLightOff() {
2577 if (mDozeServiceHost != null) {
2578 mDozeServiceHost.fireNotificationLight(false);
2579 }
2580 }
2581
2582 @Override
2583 public void notificationLightPulse(int argb, int onMillis, int offMillis) {
2584 if (mDozeServiceHost != null) {
2585 mDozeServiceHost.fireNotificationLight(true);
2586 }
2587 }
2588
John Spurlockcad57682014-07-26 17:09:56 -04002589 @Override // CommandQueue
Jorim Jaggi86905582016-02-09 21:36:09 -08002590 public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
2591 int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002592 final int oldVal = mSystemUiVisibility;
2593 final int newVal = (oldVal&~mask) | (vis&mask);
2594 final int diff = newVal ^ oldVal;
John Spurlockcd686b52013-06-05 10:13:46 -04002595 if (DEBUG) Log.d(TAG, String.format(
John Spurlockdcf4f212013-05-21 17:19:53 -04002596 "setSystemUiVisibility vis=%s mask=%s oldVal=%s newVal=%s diff=%s",
2597 Integer.toHexString(vis), Integer.toHexString(mask),
2598 Integer.toHexString(oldVal), Integer.toHexString(newVal),
2599 Integer.toHexString(diff)));
Jorim Jaggi86905582016-02-09 21:36:09 -08002600 boolean sbModeChanged = false;
Daniel Sandlere137a1e2011-08-17 16:47:19 -04002601 if (diff != 0) {
Winson Chung9214eff2014-06-12 13:59:25 -07002602 // we never set the recents bit via this method, so save the prior state to prevent
2603 // clobbering the bit below
2604 final boolean wasRecentsVisible = (mSystemUiVisibility & View.RECENT_APPS_VISIBLE) > 0;
2605
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002606 mSystemUiVisibility = newVal;
Daniel Sandler60ee2562011-07-22 12:34:33 -04002607
John Spurlocke1f366f2013-08-05 12:22:40 -04002608 // update low profile
2609 if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) {
2610 final boolean lightsOut = (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0;
Daniel Sandlere137a1e2011-08-17 16:47:19 -04002611 if (lightsOut) {
Daniel Sandler11cf1782012-09-27 14:03:08 -04002612 animateCollapsePanels();
Daniel Sandlere137a1e2011-08-17 16:47:19 -04002613 }
Jim Millera073e572012-05-23 17:03:27 -07002614
John Spurlock7edfbca2013-09-14 11:58:55 -04002615 setAreThereNotifications();
Daniel Sandler60ee2562011-07-22 12:34:33 -04002616 }
2617
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002618 // ready to unhide
2619 if ((vis & View.STATUS_BAR_UNHIDE) != 0) {
2620 mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE;
2621 mNoAnimationOnNextBarModeChange = true;
2622 }
2623
John Spurlocke1f366f2013-08-05 12:22:40 -04002624 // update status bar mode
John Spurlockd4e65752013-08-28 14:17:09 -04002625 final int sbMode = computeBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),
Jorim Jaggi4fa78922015-11-30 17:13:56 -08002626 View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT,
2627 View.STATUS_BAR_TRANSPARENT);
John Spurlocke1f366f2013-08-05 12:22:40 -04002628
2629 // update navigation bar mode
John Spurlockd4e65752013-08-28 14:17:09 -04002630 final int nbMode = mNavigationBarView == null ? -1 : computeBarMode(
John Spurlockf6b63972013-08-27 16:08:28 -04002631 oldVal, newVal, mNavigationBarView.getBarTransitions(),
Jorim Jaggi4fa78922015-11-30 17:13:56 -08002632 View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
2633 View.NAVIGATION_BAR_TRANSPARENT);
Jorim Jaggi86905582016-02-09 21:36:09 -08002634 sbModeChanged = sbMode != -1;
John Spurlockd4e65752013-08-28 14:17:09 -04002635 final boolean nbModeChanged = nbMode != -1;
2636 boolean checkBarModes = false;
2637 if (sbModeChanged && sbMode != mStatusBarMode) {
2638 mStatusBarMode = sbMode;
2639 checkBarModes = true;
2640 }
2641 if (nbModeChanged && nbMode != mNavigationBarMode) {
2642 mNavigationBarMode = nbMode;
2643 checkBarModes = true;
2644 }
2645 if (checkBarModes) {
2646 checkBarModes();
2647 }
2648 if (sbModeChanged || nbModeChanged) {
John Spurlocke1f366f2013-08-05 12:22:40 -04002649 // update transient bar autohide
John Spurlockc6d1c602014-01-17 15:22:06 -05002650 if (mStatusBarMode == MODE_SEMI_TRANSPARENT || mNavigationBarMode == MODE_SEMI_TRANSPARENT) {
John Spurlock32beb2c2013-03-11 10:16:47 -04002651 scheduleAutohide();
2652 } else {
John Spurlock32beb2c2013-03-11 10:16:47 -04002653 cancelAutohide();
2654 }
2655 }
John Spurlocke1f366f2013-08-05 12:22:40 -04002656
John Spurlock5b9145b2013-08-20 15:13:47 -04002657 if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) {
2658 mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE;
2659 }
2660
Winson Chung9214eff2014-06-12 13:59:25 -07002661 // restore the recents bit
2662 if (wasRecentsVisible) {
2663 mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
2664 }
2665
John Spurlocke1f366f2013-08-05 12:22:40 -04002666 // send updated sysui visibility to window manager
John Spurlock32beb2c2013-03-11 10:16:47 -04002667 notifyUiVisibilityChanged(mSystemUiVisibility);
Joe Onorato93056472010-09-10 10:30:46 -04002668 }
Jorim Jaggi86905582016-02-09 21:36:09 -08002669
2670 mLightStatusBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis,
2671 mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -04002672 }
2673
John Spurlockd4e65752013-08-28 14:17:09 -04002674 private int computeBarMode(int oldVis, int newVis, BarTransitions transitions,
Jorim Jaggi4fa78922015-11-30 17:13:56 -08002675 int transientFlag, int translucentFlag, int transparentFlag) {
2676 final int oldMode = barMode(oldVis, transientFlag, translucentFlag, transparentFlag);
2677 final int newMode = barMode(newVis, transientFlag, translucentFlag, transparentFlag);
John Spurlocke1f366f2013-08-05 12:22:40 -04002678 if (oldMode == newMode) {
2679 return -1; // no mode change
2680 }
John Spurlocke1f366f2013-08-05 12:22:40 -04002681 return newMode;
2682 }
2683
Jorim Jaggi4fa78922015-11-30 17:13:56 -08002684 private int barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag) {
2685 int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | transparentFlag;
John Spurlock89835dd2013-08-16 15:06:51 -04002686 return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
John Spurlockbd957402013-10-03 11:38:39 -04002687 : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT
Adrian Roosc0f0a742014-10-28 16:39:56 +01002688 : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT
Jorim Jaggi4fa78922015-11-30 17:13:56 -08002689 : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT
John Spurlock7edfbca2013-09-14 11:58:55 -04002690 : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT
John Spurlock3b139a92013-08-17 17:18:08 -04002691 : MODE_OPAQUE;
John Spurlocke1f366f2013-08-05 12:22:40 -04002692 }
2693
John Spurlockd4e65752013-08-28 14:17:09 -04002694 private void checkBarModes() {
John Spurlock3c875662013-08-31 15:07:25 -04002695 if (mDemoMode) return;
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002696 checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarView.getBarTransitions(),
2697 mNoAnimationOnNextBarModeChange);
John Spurlockd4e65752013-08-28 14:17:09 -04002698 if (mNavigationBarView != null) {
2699 checkBarMode(mNavigationBarMode,
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002700 mNavigationBarWindowState, mNavigationBarView.getBarTransitions(),
2701 mNoAnimationOnNextBarModeChange);
John Spurlockd4e65752013-08-28 14:17:09 -04002702 }
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002703 mNoAnimationOnNextBarModeChange = false;
John Spurlockd4e65752013-08-28 14:17:09 -04002704 }
2705
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002706 private void checkBarMode(int mode, int windowState, BarTransitions transitions,
2707 boolean noAnimation) {
John Spurlock0ff62e02014-07-22 16:15:08 -04002708 final boolean powerSave = mBatteryController.isPowerSave();
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07002709 final boolean anim = !noAnimation && mDeviceInteractive
Selim Cinek4a4a2bddc2015-05-07 12:50:19 -07002710 && windowState != WINDOW_STATE_HIDDEN && !powerSave;
John Spurlock1bb480a2014-08-02 17:12:43 -04002711 if (powerSave && getBarState() == StatusBarState.SHADE) {
John Spurlock0ff62e02014-07-22 16:15:08 -04002712 mode = MODE_WARNING;
2713 }
John Spurlockc68d5772013-10-08 11:47:58 -04002714 transitions.transitionTo(mode, anim);
John Spurlockd4e65752013-08-28 14:17:09 -04002715 }
2716
John Spurlock42197262013-10-21 09:32:25 -04002717 private void finishBarAnimations() {
2718 mStatusBarView.getBarTransitions().finishAnimations();
2719 if (mNavigationBarView != null) {
2720 mNavigationBarView.getBarTransitions().finishAnimations();
2721 }
2722 }
2723
John Spurlockd4e65752013-08-28 14:17:09 -04002724 private final Runnable mCheckBarModes = new Runnable() {
John Spurlock5b9145b2013-08-20 15:13:47 -04002725 @Override
2726 public void run() {
John Spurlockd4e65752013-08-28 14:17:09 -04002727 checkBarModes();
John Spurlock0ff62e02014-07-22 16:15:08 -04002728 }
2729 };
John Spurlock5b9145b2013-08-20 15:13:47 -04002730
John Spurlockad3e6cb2013-04-30 08:47:43 -04002731 @Override
John Spurlockcfc359a2013-09-05 10:42:03 -04002732 public void setInteracting(int barWindow, boolean interacting) {
John Spurlock7fbf5732014-11-18 11:40:22 -05002733 final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting;
John Spurlockcfc359a2013-09-05 10:42:03 -04002734 mInteractingWindows = interacting
2735 ? (mInteractingWindows | barWindow)
2736 : (mInteractingWindows & ~barWindow);
2737 if (mInteractingWindows != 0) {
John Spurlockd4e65752013-08-28 14:17:09 -04002738 suspendAutohide();
2739 } else {
2740 resumeSuspendedAutohide();
2741 }
John Spurlock7fbf5732014-11-18 11:40:22 -05002742 // manually dismiss the volume panel when interacting with the nav bar
2743 if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) {
John Spurlockb349af572015-04-29 12:24:19 -04002744 dismissVolumeDialog();
John Spurlock7fbf5732014-11-18 11:40:22 -05002745 }
John Spurlockd4e65752013-08-28 14:17:09 -04002746 checkBarModes();
2747 }
2748
John Spurlockb349af572015-04-29 12:24:19 -04002749 private void dismissVolumeDialog() {
2750 if (mVolumeComponent != null) {
2751 mVolumeComponent.dismissNow();
2752 }
2753 }
2754
John Spurlockd4e65752013-08-28 14:17:09 -04002755 private void resumeSuspendedAutohide() {
John Spurlockad3e6cb2013-04-30 08:47:43 -04002756 if (mAutohideSuspended) {
2757 scheduleAutohide();
John Spurlockd4e65752013-08-28 14:17:09 -04002758 mHandler.postDelayed(mCheckBarModes, 500); // longer than home -> launcher
John Spurlock3b139a92013-08-17 17:18:08 -04002759 }
2760 }
2761
John Spurlockd4e65752013-08-28 14:17:09 -04002762 private void suspendAutohide() {
John Spurlock32beb2c2013-03-11 10:16:47 -04002763 mHandler.removeCallbacks(mAutohide);
John Spurlockd4e65752013-08-28 14:17:09 -04002764 mHandler.removeCallbacks(mCheckBarModes);
John Spurlock5b9145b2013-08-20 15:13:47 -04002765 mAutohideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0;
John Spurlock32beb2c2013-03-11 10:16:47 -04002766 }
2767
2768 private void cancelAutohide() {
2769 mAutohideSuspended = false;
2770 mHandler.removeCallbacks(mAutohide);
2771 }
2772
2773 private void scheduleAutohide() {
2774 cancelAutohide();
2775 mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS);
2776 }
2777
John Spurlock9deaa282013-07-25 13:03:47 -04002778 private void checkUserAutohide(View v, MotionEvent event) {
John Spurlocke1f366f2013-08-05 12:22:40 -04002779 if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed
John Spurlock9deaa282013-07-25 13:03:47 -04002780 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar
2781 && event.getX() == 0 && event.getY() == 0 // a touch outside both bars
2782 ) {
2783 userAutohide();
2784 }
2785 }
2786
2787 private void userAutohide() {
2788 cancelAutohide();
John Spurlock5b9145b2013-08-20 15:13:47 -04002789 mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear
John Spurlock9deaa282013-07-25 13:03:47 -04002790 }
2791
Daniel Sandlerd7e96862012-04-26 01:10:29 -04002792 private boolean areLightsOn() {
2793 return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE);
2794 }
Jim Millera073e572012-05-23 17:03:27 -07002795
Daniel Sandler60ee2562011-07-22 12:34:33 -04002796 public void setLightsOn(boolean on) {
2797 Log.v(TAG, "setLightsOn(" + on + ")");
2798 if (on) {
Jorim Jaggi86905582016-02-09 21:36:09 -08002799 setSystemUiVisibility(0, 0, 0, View.SYSTEM_UI_FLAG_LOW_PROFILE,
2800 mLastFullscreenStackBounds, mLastDockedStackBounds);
Daniel Sandler60ee2562011-07-22 12:34:33 -04002801 } else {
Jorim Jaggi86905582016-02-09 21:36:09 -08002802 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, 0, 0,
2803 View.SYSTEM_UI_FLAG_LOW_PROFILE, mLastFullscreenStackBounds,
2804 mLastDockedStackBounds);
Daniel Sandler60ee2562011-07-22 12:34:33 -04002805 }
2806 }
2807
John Spurlock32beb2c2013-03-11 10:16:47 -04002808 private void notifyUiVisibilityChanged(int vis) {
Daniel Sandler1d4d30a2011-04-28 12:35:29 -04002809 try {
Adrian Roos389beec2015-05-12 13:33:25 -07002810 if (mLastDispatchedSystemUiVisibility != vis) {
2811 mWindowManagerService.statusBarVisibilityChanged(vis);
2812 mLastDispatchedSystemUiVisibility = vis;
2813 }
Daniel Sandler1d4d30a2011-04-28 12:35:29 -04002814 } catch (RemoteException ex) {
2815 }
Joe Onorato93056472010-09-10 10:30:46 -04002816 }
2817
Daniel Sandler5c8da942011-06-28 00:29:04 -04002818 public void topAppWindowChanged(boolean showMenu) {
2819 if (DEBUG) {
John Spurlockcd686b52013-06-05 10:13:46 -04002820 Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
Daniel Sandler5c8da942011-06-28 00:29:04 -04002821 }
2822 if (mNavigationBarView != null) {
Daniel Sandlerf1ebcee2011-09-15 16:02:56 -04002823 mNavigationBarView.setMenuVisibility(showMenu);
Daniel Sandler5c8da942011-06-28 00:29:04 -04002824 }
2825
2826 // See above re: lights-out policy for legacy apps.
2827 if (showMenu) setLightsOn(true);
2828 }
2829
Daniel Sandler328310c2011-09-23 15:56:52 -04002830 @Override
Jason Monkb605fec2014-05-02 17:04:10 -04002831 public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
2832 boolean showImeSwitcher) {
Jason Monkf1ff2092014-04-29 16:50:53 -04002833 boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
2834 int flags = mNavigationIconHints;
2835 if ((backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS) || imeShown) {
2836 flags |= NAVIGATION_HINT_BACK_ALT;
2837 } else {
2838 flags &= ~NAVIGATION_HINT_BACK_ALT;
2839 }
Jason Monkb605fec2014-05-02 17:04:10 -04002840 if (showImeSwitcher) {
Jason Monkf1ff2092014-04-29 16:50:53 -04002841 flags |= NAVIGATION_HINT_IME_SHOWN;
2842 } else {
2843 flags &= ~NAVIGATION_HINT_IME_SHOWN;
2844 }
Daniel Sandler328310c2011-09-23 15:56:52 -04002845
Jason Monkf1ff2092014-04-29 16:50:53 -04002846 setNavigationIconHints(flags);
Daniel Sandler328310c2011-09-23 15:56:52 -04002847 }
2848
Daniel Sandler48852952011-12-01 14:34:23 -05002849 public static String viewInfo(View v) {
2850 return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
2851 + ") " + v.getWidth() + "x" + v.getHeight() + "]";
Joe Onorato808182d2010-07-09 18:52:06 -04002852 }
2853
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04002854 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Joe Onorato808182d2010-07-09 18:52:06 -04002855 synchronized (mQueueLock) {
2856 pw.println("Current Status Bar state:");
Daniel Sandlere7237fc2012-08-14 16:08:27 -04002857 pw.println(" mExpandedVisible=" + mExpandedVisible
Daniel Sandlerfdbac772012-07-03 14:30:10 -04002858 + ", mTrackingPosition=" + mTrackingPosition);
Joe Onorato808182d2010-07-09 18:52:06 -04002859 pw.println(" mTracking=" + mTracking);
Daniel Sandler36412a72011-08-04 09:35:13 -04002860 pw.println(" mDisplayMetrics=" + mDisplayMetrics);
Selim Cinekb6d85eb2014-03-28 20:21:01 +01002861 pw.println(" mStackScroller: " + viewInfo(mStackScroller));
Selim Cinekb6d85eb2014-03-28 20:21:01 +01002862 pw.println(" mStackScroller: " + viewInfo(mStackScroller)
2863 + " scroll " + mStackScroller.getScrollX()
2864 + "," + mStackScroller.getScrollY());
Joe Onorato808182d2010-07-09 18:52:06 -04002865 }
Joe Onorato808182d2010-07-09 18:52:06 -04002866
John Spurlockcfc359a2013-09-05 10:42:03 -04002867 pw.print(" mInteractingWindows="); pw.println(mInteractingWindows);
John Spurlock0ec64c62013-08-26 15:37:58 -04002868 pw.print(" mStatusBarWindowState=");
2869 pw.println(windowStateToString(mStatusBarWindowState));
John Spurlockd4e65752013-08-28 14:17:09 -04002870 pw.print(" mStatusBarMode=");
2871 pw.println(BarTransitions.modeToString(mStatusBarMode));
John Spurlockbf370992014-06-17 13:58:31 -04002872 pw.print(" mDozing="); pw.println(mDozing);
John Spurlocke677d712014-02-13 12:52:19 -05002873 pw.print(" mZenMode=");
2874 pw.println(Settings.Global.zenModeToString(mZenMode));
Chris Wren3b6745b2014-03-07 14:34:35 -05002875 pw.print(" mUseHeadsUp=");
2876 pw.println(mUseHeadsUp);
John Spurlock0ec64c62013-08-26 15:37:58 -04002877 dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions());
2878 if (mNavigationBarView != null) {
2879 pw.print(" mNavigationBarWindowState=");
2880 pw.println(windowStateToString(mNavigationBarWindowState));
John Spurlockd4e65752013-08-28 14:17:09 -04002881 pw.print(" mNavigationBarMode=");
2882 pw.println(BarTransitions.modeToString(mNavigationBarMode));
John Spurlock0ec64c62013-08-26 15:37:58 -04002883 dumpBarTransitions(pw, "mNavigationBarView", mNavigationBarView.getBarTransitions());
2884 }
2885
Daniel Sandler48852952011-12-01 14:34:23 -05002886 pw.print(" mNavigationBarView=");
2887 if (mNavigationBarView == null) {
2888 pw.println("null");
2889 } else {
2890 mNavigationBarView.dump(fd, pw, args);
2891 }
2892
Dan Sandler16128f42014-05-21 12:48:22 -04002893 pw.print(" mMediaSessionManager=");
2894 pw.println(mMediaSessionManager);
2895 pw.print(" mMediaNotificationKey=");
2896 pw.println(mMediaNotificationKey);
2897 pw.print(" mMediaController=");
2898 pw.print(mMediaController);
2899 if (mMediaController != null) {
2900 pw.print(" state=" + mMediaController.getPlaybackState());
2901 }
2902 pw.println();
2903 pw.print(" mMediaMetadata=");
2904 pw.print(mMediaMetadata);
2905 if (mMediaMetadata != null) {
RoboErik75847b92014-07-29 13:10:17 -07002906 pw.print(" title=" + mMediaMetadata.getText(MediaMetadata.METADATA_KEY_TITLE));
Dan Sandler16128f42014-05-21 12:48:22 -04002907 }
2908 pw.println();
2909
Daniel Sandler37a38aa2013-02-13 17:15:57 -05002910 pw.println(" Panels: ");
2911 if (mNotificationPanel != null) {
2912 pw.println(" mNotificationPanel=" +
2913 mNotificationPanel + " params=" + mNotificationPanel.getLayoutParams().debug(""));
2914 pw.print (" ");
2915 mNotificationPanel.dump(fd, pw, args);
2916 }
Daniel Sandler37a38aa2013-02-13 17:15:57 -05002917
John Spurlock813552c2014-09-19 08:30:21 -04002918 DozeLog.dump(pw);
2919
Daniel Sandler7579bca2011-08-18 15:47:26 -04002920 if (DUMPTRUCK) {
2921 synchronized (mNotificationData) {
Christoph Studerc8db24b2014-07-25 17:50:30 +02002922 mNotificationData.dump(pw, " ");
Daniel Sandler7579bca2011-08-18 15:47:26 -04002923 }
2924
Jorim Jaggi66ac1332015-01-21 19:22:26 +01002925 mIconController.dump(pw);
Jim Miller5e6af442011-12-02 18:24:26 -08002926
Daniel Sandler89d97132011-09-08 15:31:57 -04002927 if (false) {
2928 pw.println("see the logcat for a dump of the views we have created.");
2929 // must happen on ui thread
2930 mHandler.post(new Runnable() {
2931 public void run() {
2932 mStatusBarView.getLocationOnScreen(mAbsPos);
John Spurlockcd686b52013-06-05 10:13:46 -04002933 Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
Daniel Sandler89d97132011-09-08 15:31:57 -04002934 + ") " + mStatusBarView.getWidth() + "x"
Daniel Sandlera310af82012-04-24 01:20:13 -04002935 + getStatusBarHeight());
Daniel Sandler89d97132011-09-08 15:31:57 -04002936 mStatusBarView.debug();
Daniel Sandler89d97132011-09-08 15:31:57 -04002937 }
2938 });
2939 }
Joe Onorato808182d2010-07-09 18:52:06 -04002940 }
Daniel Sandler89d97132011-09-08 15:31:57 -04002941
Daniel Sandler151f00d2012-10-02 22:33:08 -04002942 if (DEBUG_GESTURES) {
2943 pw.print(" status bar gestures: ");
2944 mGestureRec.dump(fd, pw, args);
2945 }
Selim Cinek7025f262015-07-13 16:22:48 -07002946 if (mStatusBarWindowManager != null) {
2947 mStatusBarWindowManager.dump(fd, pw, args);
2948 }
John Spurlock486b78e2014-07-07 08:37:56 -04002949 if (mNetworkController != null) {
2950 mNetworkController.dump(fd, pw, args);
2951 }
2952 if (mBluetoothController != null) {
2953 mBluetoothController.dump(fd, pw, args);
2954 }
Jason Monkdd5bdc62015-07-20 12:18:38 -04002955 if (mHotspotController != null) {
2956 mHotspotController.dump(fd, pw, args);
2957 }
John Spurlock1e6eb172014-07-13 11:59:50 -04002958 if (mCastController != null) {
2959 mCastController.dump(fd, pw, args);
2960 }
Adrian Roos00a0b1f2014-07-16 16:44:49 +02002961 if (mUserSwitcherController != null) {
2962 mUserSwitcherController.dump(fd, pw, args);
2963 }
John Spurlock0ff62e02014-07-22 16:15:08 -04002964 if (mBatteryController != null) {
2965 mBatteryController.dump(fd, pw, args);
2966 }
Jorim Jaggic7dea6e2014-07-26 14:36:57 +02002967 if (mNextAlarmController != null) {
2968 mNextAlarmController.dump(fd, pw, args);
2969 }
Jason Monk3d5f5512014-07-25 11:17:28 -04002970 if (mSecurityController != null) {
2971 mSecurityController.dump(fd, pw, args);
2972 }
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002973 if (mHeadsUpManager != null) {
2974 mHeadsUpManager.dump(fd, pw, args);
Chris Wren428c6b62014-12-05 16:07:06 -05002975 } else {
Selim Cinekb8f09cf2015-03-16 17:09:28 -07002976 pw.println(" mHeadsUpManager: null");
Chris Wren428c6b62014-12-05 16:07:06 -05002977 }
Jason Monkab525272015-07-13 17:02:49 -04002978 if (KeyguardUpdateMonitor.getInstance(mContext) != null) {
2979 KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
2980 }
Chris Wren428c6b62014-12-05 16:07:06 -05002981
Adrian Roos401caae2016-03-04 13:35:21 -08002982 FalsingManager.getInstance(mContext).dump(pw);
2983 FalsingLog.dump(pw);
2984
John Spurlock7bbb9f62014-10-21 12:15:28 -04002985 pw.println("SharedPreferences:");
Andrew Flynn82862572015-04-01 14:22:37 -04002986 for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
John Spurlock7bbb9f62014-10-21 12:15:28 -04002987 pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
2988 }
Joe Onorato808182d2010-07-09 18:52:06 -04002989 }
2990
John Spurlock0ec64c62013-08-26 15:37:58 -04002991 private static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) {
2992 pw.print(" "); pw.print(var); pw.print(".BarTransitions.mMode=");
2993 pw.println(BarTransitions.modeToString(transitions.getMode()));
2994 }
2995
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05002996 @Override
2997 public void createAndAddWindows() {
2998 addStatusBarWindow();
Joe Onorato808182d2010-07-09 18:52:06 -04002999 }
Jim Millere898ac52012-04-06 17:10:57 -07003000
Daniel Sandlerc6d29fc2012-02-25 00:33:12 -05003001 private void addStatusBarWindow() {
Daniel Sandlera310af82012-04-24 01:20:13 -04003002 makeStatusBarView();
Jorim Jaggi5cf17872014-03-26 18:31:48 +01003003 mStatusBarWindowManager = new StatusBarWindowManager(mContext);
Adrian Roos1c0ca502015-10-07 12:20:42 -07003004 mRemoteInputController = new RemoteInputController(mStatusBarWindowManager,
3005 mHeadsUpManager);
Jorim Jaggi5cf17872014-03-26 18:31:48 +01003006 mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
Joe Onorato808182d2010-07-09 18:52:06 -04003007 }
3008
Daniel Sandler747a9e92012-08-10 16:39:19 -04003009 // called by makeStatusbar and also by PhoneStatusBarView
Dianne Hackborn1dacf272011-08-02 15:01:22 -07003010 void updateDisplaySize() {
Daniel Sandler36412a72011-08-04 09:35:13 -04003011 mDisplay.getMetrics(mDisplayMetrics);
Daniel Sandler7e8ae502013-10-10 23:38:19 -04003012 mDisplay.getSize(mCurrentDisplaySize);
Daniel Sandler151f00d2012-10-02 22:33:08 -04003013 if (DEBUG_GESTURES) {
John Spurlock209bede2013-07-17 12:23:27 -04003014 mGestureRec.tag("display",
Daniel Sandler151f00d2012-10-02 22:33:08 -04003015 String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
3016 }
Dianne Hackborn1dacf272011-08-02 15:01:22 -07003017 }
3018
Christoph Studerb0183992014-12-22 21:02:26 +01003019 float getDisplayDensity() {
3020 return mDisplayMetrics.density;
3021 }
3022
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02003023 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
Jorim Jaggid9449862015-05-29 14:49:08 -07003024 boolean dismissShade) {
3025 startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */);
3026 }
3027
3028 public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
3029 final boolean dismissShade, final Callback callback) {
Daniel Sandler3679bf52012-10-16 21:30:28 -04003030 if (onlyProvisioned && !isDeviceProvisioned()) return;
Adrian Roos4314f6d2014-05-28 14:10:27 +02003031
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02003032 final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
3033 mContext, intent, mCurrentUserId);
Jorim Jaggic7dea6e2014-07-26 14:36:57 +02003034 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Selim Cineke70d6532015-04-24 16:46:13 -07003035 Runnable runnable = new Runnable() {
3036 public void run() {
Jorim Jaggib835dd72015-06-08 12:28:42 -07003037 mAssistManager.hideAssist();
Selim Cineke70d6532015-04-24 16:46:13 -07003038 intent.setFlags(
3039 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Jorim Jaggid9449862015-05-29 14:49:08 -07003040 int result = ActivityManager.START_CANCELED;
3041 try {
3042 result = ActivityManagerNative.getDefault().startActivityAsUser(
3043 null, mContext.getBasePackageName(),
3044 intent,
3045 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
3046 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null,
3047 UserHandle.CURRENT.getIdentifier());
3048 } catch (RemoteException e) {
3049 Log.w(TAG, "Unable to start activity", e);
3050 }
Selim Cineke70d6532015-04-24 16:46:13 -07003051 overrideActivityPendingAppTransition(
3052 keyguardShowing && !afterKeyguardGone);
Jorim Jaggid9449862015-05-29 14:49:08 -07003053 if (callback != null) {
3054 callback.onActivityStarted(result);
3055 }
Selim Cineke70d6532015-04-24 16:46:13 -07003056 }
3057 };
Jorim Jaggid9449862015-05-29 14:49:08 -07003058 Runnable cancelRunnable = new Runnable() {
3059 @Override
3060 public void run() {
Jorim Jaggi5cc86592015-06-08 14:48:28 -07003061 if (callback != null) {
3062 callback.onActivityStarted(ActivityManager.START_CANCELED);
3063 }
Jorim Jaggid9449862015-05-29 14:49:08 -07003064 }
3065 };
Jorim Jaggib835dd72015-06-08 12:28:42 -07003066 executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade,
3067 afterKeyguardGone);
Selim Cineke70d6532015-04-24 16:46:13 -07003068 }
3069
3070 public void executeRunnableDismissingKeyguard(final Runnable runnable,
Jorim Jaggid9449862015-05-29 14:49:08 -07003071 final Runnable cancelAction,
Selim Cineke70d6532015-04-24 16:46:13 -07003072 final boolean dismissShade,
3073 final boolean afterKeyguardGone) {
3074 final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Adrian Roos4314f6d2014-05-28 14:10:27 +02003075 dismissKeyguardThenExecute(new OnDismissAction() {
3076 @Override
3077 public boolean onDismiss() {
Selim Cinekbaa23272014-07-08 18:01:07 +02003078 AsyncTask.execute(new Runnable() {
3079 public void run() {
3080 try {
Jorim Jaggi746f7fa2014-08-27 17:52:46 +02003081 if (keyguardShowing && !afterKeyguardGone) {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02003082 ActivityManagerNative.getDefault()
3083 .keyguardWaitingForActivityDrawn();
3084 }
Selim Cineke70d6532015-04-24 16:46:13 -07003085 if (runnable != null) {
3086 runnable.run();
3087 }
Selim Cinekbaa23272014-07-08 18:01:07 +02003088 } catch (RemoteException e) {
3089 }
3090 }
3091 });
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02003092 if (dismissShade) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -07003093 animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
3094 true /* delayed*/);
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02003095 }
3096 return true;
Adrian Roos4314f6d2014-05-28 14:10:27 +02003097 }
Jorim Jaggid9449862015-05-29 14:49:08 -07003098 }, cancelAction, afterKeyguardGone);
Daniel Sandler3679bf52012-10-16 21:30:28 -04003099 }
3100
Joe Onorato808182d2010-07-09 18:52:06 -04003101 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
3102 public void onReceive(Context context, Intent intent) {
John Spurlockcd686b52013-06-05 10:13:46 -04003103 if (DEBUG) Log.v(TAG, "onReceive: " + intent);
Joe Onorato808182d2010-07-09 18:52:06 -04003104 String action = intent.getAction();
Daniel Sandlered930e52012-07-03 14:31:22 -04003105 if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +01003106 getKeyboardShortcuts().dismissKeyboardShortcutsDialog();
Kenny Guy44fc65f2014-11-28 22:18:14 +00003107 if (isCurrentProfile(getSendingUserId())) {
3108 int flags = CommandQueue.FLAG_EXCLUDE_NONE;
3109 String reason = intent.getStringExtra("reason");
3110 if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
3111 flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
3112 }
3113 animateCollapsePanels(flags);
Michael Jurka3b1fc472011-06-13 10:54:40 -07003114 }
Joe Onorato808182d2010-07-09 18:52:06 -04003115 }
Daniel Sandlered930e52012-07-03 14:31:22 -04003116 else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
John Spurlock1bbd49d2012-10-19 11:09:32 -04003117 notifyNavigationBarScreenOn(false);
Selim Cinekb8f09cf2015-03-16 17:09:28 -07003118 notifyHeadsUpScreenOff();
John Spurlock42197262013-10-21 09:32:25 -04003119 finishBarAnimations();
Selim Cinekccd14fb2014-08-12 18:53:24 +02003120 resetUserExpandedStates();
Daniel Sandlered930e52012-07-03 14:31:22 -04003121 }
Daniel Sandler7f3cf952012-08-31 14:57:09 -04003122 else if (Intent.ACTION_SCREEN_ON.equals(action)) {
John Spurlock1bbd49d2012-10-19 11:09:32 -04003123 notifyNavigationBarScreenOn(true);
Joe Onorato808182d2010-07-09 18:52:06 -04003124 }
Adrian Roos8e3e8362015-07-16 19:42:22 -07003125 }
3126 };
3127
3128 private BroadcastReceiver mDemoReceiver = new BroadcastReceiver() {
3129 public void onReceive(Context context, Intent intent) {
3130 if (DEBUG) Log.v(TAG, "onReceive: " + intent);
3131 String action = intent.getAction();
3132 if (ACTION_DEMO.equals(action)) {
John Spurlock3c875662013-08-31 15:07:25 -04003133 Bundle bundle = intent.getExtras();
3134 if (bundle != null) {
3135 String command = bundle.getString("command", "").trim().toLowerCase();
3136 if (command.length() > 0) {
3137 try {
3138 dispatchDemoCommand(command, bundle);
3139 } catch (Throwable t) {
3140 Log.w(TAG, "Error running demo command, intent=" + intent, t);
3141 }
3142 }
3143 }
Adrian Roos8e3e8362015-07-16 19:42:22 -07003144 } else if (ACTION_FAKE_ARTWORK.equals(action)) {
Dan Sandler16128f42014-05-21 12:48:22 -04003145 if (DEBUG_MEDIA_FAKE_ARTWORK) {
Adrian Roos52738322016-01-29 08:49:21 -08003146 updateMediaMetaData(true, true);
Dan Sandler16128f42014-05-21 12:48:22 -04003147 }
John Spurlock3c875662013-08-31 15:07:25 -04003148 }
Joe Onorato808182d2010-07-09 18:52:06 -04003149 }
3150 };
3151
Selim Cinek78f40082016-03-10 18:06:27 -08003152 public void resetUserExpandedStates() {
Selim Cinekccd14fb2014-08-12 18:53:24 +02003153 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
3154 final int notificationCount = activeNotifications.size();
3155 for (int i = 0; i < notificationCount; i++) {
3156 NotificationData.Entry entry = activeNotifications.get(i);
3157 if (entry.row != null) {
3158 entry.row.resetUserExpansion();
3159 }
3160 }
3161 }
3162
Adrian Roos7d7090d2014-05-21 13:10:23 +02003163 @Override
Jorim Jaggid9449862015-05-29 14:49:08 -07003164 protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
3165 dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
3166 }
3167
Jason Monkabe19742015-09-29 09:47:06 -04003168 public void dismissKeyguard() {
3169 mStatusBarKeyguardViewManager.dismiss();
3170 }
3171
Jorim Jaggid9449862015-05-29 14:49:08 -07003172 private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
Jorim Jaggi746f7fa2014-08-27 17:52:46 +02003173 boolean afterKeyguardGone) {
Adrian Roos7d7090d2014-05-21 13:10:23 +02003174 if (mStatusBarKeyguardViewManager.isShowing()) {
Jorim Jaggid9449862015-05-29 14:49:08 -07003175 mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
3176 afterKeyguardGone);
Adrian Roos7d7090d2014-05-21 13:10:23 +02003177 } else {
3178 action.onDismiss();
3179 }
3180 }
3181
Daniel Sandler777dcde2013-09-30 10:21:45 -04003182 // SystemUIService notifies SystemBars of configuration changes, which then calls down here
3183 @Override
3184 protected void onConfigurationChanged(Configuration newConfig) {
3185 super.onConfigurationChanged(newConfig); // calls refreshLayout
3186
3187 if (DEBUG) {
3188 Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
3189 }
Daniel Sandler7e8ae502013-10-10 23:38:19 -04003190 updateDisplaySize(); // populates mDisplayMetrics
Daniel Sandler777dcde2013-09-30 10:21:45 -04003191
3192 updateResources();
3193 repositionNavigationBar();
Jorim Jaggif6411742014-08-05 17:10:43 +00003194 updateRowStates();
Jorim Jaggi66ac1332015-01-21 19:22:26 +01003195 mIconController.updateResources();
Jason Monk18f99d92014-09-11 13:36:42 -04003196 mScreenPinningRequest.onConfigurationChanged();
Jason Monk1c040db2015-07-20 09:45:54 -04003197 mNetworkController.onConfigurationChanged();
Daniel Sandler777dcde2013-09-30 10:21:45 -04003198 }
3199
Daniel Sandlerb9301c32012-08-14 15:08:24 -04003200 @Override
3201 public void userSwitched(int newUserId) {
Chris Wrena6d4fb62014-11-20 14:46:23 -05003202 super.userSwitched(newUserId);
Daniel Sandlerb9301c32012-08-14 15:08:24 -04003203 if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
Daniel Sandler11cf1782012-09-27 14:03:08 -04003204 animateCollapsePanels();
Adrian Roos31b844b2014-11-21 13:55:09 +01003205 updatePublicMode();
Christoph Studer37fe6932014-05-26 13:10:30 +02003206 updateNotifications();
John Spurlock919adac2012-10-02 16:41:12 -04003207 resetUserSetupObserver();
John Spurlock89f060a2014-07-16 21:03:15 -04003208 setControllerUsers();
Julia Reynolds86ef8e22015-09-09 16:42:38 -04003209 clearCurrentMediaNotification();
Vadim Tryshev12a30e82016-02-12 15:39:28 -08003210 mLockscreenWallpaper.setCurrentUser(newUserId);
Adrian Roos52738322016-01-29 08:49:21 -08003211 updateMediaMetaData(true, false);
John Spurlock89f060a2014-07-16 21:03:15 -04003212 }
3213
3214 private void setControllerUsers() {
3215 if (mZenModeController != null) {
3216 mZenModeController.setUserId(mCurrentUserId);
3217 }
Robin Lee63204ee2015-06-04 01:53:01 +01003218 if (mSecurityController != null) {
3219 mSecurityController.onUserSwitched(mCurrentUserId);
3220 }
Daniel Sandlerb9301c32012-08-14 15:08:24 -04003221 }
John Spurlock919adac2012-10-02 16:41:12 -04003222
3223 private void resetUserSetupObserver() {
3224 mContext.getContentResolver().unregisterContentObserver(mUserSetupObserver);
3225 mUserSetupObserver.onChange(false);
3226 mContext.getContentResolver().registerContentObserver(
3227 Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), true,
Jorim Jaggi66ac1332015-01-21 19:22:26 +01003228 mUserSetupObserver, mCurrentUserId);
John Spurlock919adac2012-10-02 16:41:12 -04003229 }
3230
Joe Onorato808182d2010-07-09 18:52:06 -04003231 /**
3232 * Reload some of our resources when the configuration changes.
3233 *
3234 * We don't reload everything when the configuration changes -- we probably
3235 * should, but getting that smooth is tough. Someday we'll fix that. In the
3236 * meantime, just update the things that we know change.
3237 */
3238 void updateResources() {
John Spurlockaf8d6c42014-05-07 17:49:08 -04003239 // Update the quick setting tiles
John Spurlock7e6809a2014-08-06 16:03:14 -04003240 if (mQSPanel != null) {
3241 mQSPanel.updateResources();
3242 }
Winson Chungd63c59782012-09-05 17:34:41 -07003243
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04003244 loadDimens();
John Spurlock7e6809a2014-08-06 16:03:14 -04003245
3246 if (mNotificationPanel != null) {
3247 mNotificationPanel.updateResources();
3248 }
Adrian Roos5fd872e2014-08-12 17:28:58 +02003249 if (mBrightnessMirrorController != null) {
3250 mBrightnessMirrorController.updateResources();
3251 }
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04003252 }
Jim Miller5e6af442011-12-02 18:24:26 -08003253
Daniel Sandler7c3e39d2011-07-29 16:30:49 -04003254 protected void loadDimens() {
3255 final Resources res = mContext.getResources();
3256
3257 mNaturalBarHeight = res.getDimensionPixelSize(
3258 com.android.internal.R.dimen.status_bar_height);
3259
Selim Cinek5f71bee2015-11-18 10:25:23 -08003260 mMaxAllowedKeyguardNotifications = res.getInteger(R.integer.keyguard_max_notification_count);
Jorim Jaggid4a57442014-04-10 02:45:55 +02003261
John Spurlock7e6809a2014-08-06 16:03:14 -04003262 if (DEBUG) Log.v(TAG, "updateResources");
John Spurlock804df702012-06-01 15:34:27 -04003263 }
3264
Christoph Studer92b389d2014-04-01 18:44:40 +02003265 // Visibility reporting
3266
3267 @Override
Christoph Studere8e28652014-10-29 17:27:53 +01003268 protected void handleVisibleToUserChanged(boolean visibleToUser) {
3269 if (visibleToUser) {
3270 super.handleVisibleToUserChanged(visibleToUser);
3271 startNotificationLogging();
Christoph Studer92b389d2014-04-01 18:44:40 +02003272 } else {
Christoph Studer037e34c2014-04-30 20:06:04 +02003273 stopNotificationLogging();
Christoph Studere8e28652014-10-29 17:27:53 +01003274 super.handleVisibleToUserChanged(visibleToUser);
Christoph Studer92b389d2014-04-01 18:44:40 +02003275 }
Christoph Studer92b389d2014-04-01 18:44:40 +02003276 }
3277
Christoph Studer037e34c2014-04-30 20:06:04 +02003278 private void stopNotificationLogging() {
3279 // Report all notifications as invisible and turn down the
3280 // reporter.
3281 if (!mCurrentlyVisibleNotifications.isEmpty()) {
Chris Wrend1dbc922015-06-19 17:51:16 -04003282 logNotificationVisibilityChanges(Collections.<NotificationVisibility>emptyList(),
3283 mCurrentlyVisibleNotifications);
3284 recycleAllVisibilityObjects(mCurrentlyVisibleNotifications);
Christoph Studer037e34c2014-04-30 20:06:04 +02003285 }
3286 mHandler.removeCallbacks(mVisibilityReporter);
3287 mStackScroller.setChildLocationsChangedListener(null);
3288 }
3289
Christoph Studere8e28652014-10-29 17:27:53 +01003290 private void startNotificationLogging() {
3291 mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
3292 // Some transitions like mVisibleToUser=false -> mVisibleToUser=true don't
3293 // cause the scroller to emit child location events. Hence generate
3294 // one ourselves to guarantee that we're reporting visible
3295 // notifications.
3296 // (Note that in cases where the scroller does emit events, this
3297 // additional event doesn't break anything.)
3298 mNotificationLocationsChangedListener.onChildLocationsChanged(mStackScroller);
Christoph Studer037e34c2014-04-30 20:06:04 +02003299 }
3300
Christoph Studer92b389d2014-04-01 18:44:40 +02003301 private void logNotificationVisibilityChanges(
Chris Wrend1dbc922015-06-19 17:51:16 -04003302 Collection<NotificationVisibility> newlyVisible,
3303 Collection<NotificationVisibility> noLongerVisible) {
Christoph Studer92b389d2014-04-01 18:44:40 +02003304 if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
3305 return;
3306 }
Chris Wrend1dbc922015-06-19 17:51:16 -04003307 NotificationVisibility[] newlyVisibleAr =
3308 newlyVisible.toArray(new NotificationVisibility[newlyVisible.size()]);
3309 NotificationVisibility[] noLongerVisibleAr =
3310 noLongerVisible.toArray(new NotificationVisibility[noLongerVisible.size()]);
Christoph Studer92b389d2014-04-01 18:44:40 +02003311 try {
3312 mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
3313 } catch (RemoteException e) {
3314 // Ignore.
3315 }
Chris Wrend1dbc922015-06-19 17:51:16 -04003316
3317 final int N = newlyVisible.size();
Amith Yamasani76495672015-07-07 15:22:54 -07003318 if (N > 0) {
3319 String[] newlyVisibleKeyAr = new String[N];
3320 for (int i = 0; i < N; i++) {
3321 newlyVisibleKeyAr[i] = newlyVisibleAr[i].key;
3322 }
3323
3324 setNotificationsShown(newlyVisibleKeyAr);
Chris Wrend1dbc922015-06-19 17:51:16 -04003325 }
Christoph Studer92b389d2014-04-01 18:44:40 +02003326 }
3327
Christoph Studer2231c6e2014-12-19 12:40:13 +01003328 // State logging
3329
3330 private void logStateToEventlog() {
3331 boolean isShowing = mStatusBarKeyguardViewManager.isShowing();
3332 boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded();
3333 boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
3334 boolean isSecure = mUnlockMethodCache.isMethodSecure();
Selim Cineke8bae622015-07-15 13:24:06 -07003335 boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer();
Christoph Studer2231c6e2014-12-19 12:40:13 +01003336 int stateFingerprint = getLoggingFingerprint(mState,
3337 isShowing,
3338 isOccluded,
3339 isBouncerShowing,
3340 isSecure,
Selim Cineke8bae622015-07-15 13:24:06 -07003341 canSkipBouncer);
Christoph Studer2231c6e2014-12-19 12:40:13 +01003342 if (stateFingerprint != mLastLoggedStateFingerprint) {
3343 EventLogTags.writeSysuiStatusBarState(mState,
3344 isShowing ? 1 : 0,
3345 isOccluded ? 1 : 0,
3346 isBouncerShowing ? 1 : 0,
3347 isSecure ? 1 : 0,
Selim Cineke8bae622015-07-15 13:24:06 -07003348 canSkipBouncer ? 1 : 0);
Christoph Studer2231c6e2014-12-19 12:40:13 +01003349 mLastLoggedStateFingerprint = stateFingerprint;
3350 }
3351 }
3352
3353 /**
3354 * Returns a fingerprint of fields logged to eventlog
3355 */
3356 private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing,
3357 boolean keyguardOccluded, boolean bouncerShowing, boolean secure,
3358 boolean currentlyInsecure) {
3359 // Reserve 8 bits for statusBarState. We'll never go higher than
3360 // that, right? Riiiight.
3361 return (statusBarState & 0xFF)
3362 | ((keyguardShowing ? 1 : 0) << 8)
3363 | ((keyguardOccluded ? 1 : 0) << 9)
3364 | ((bouncerShowing ? 1 : 0) << 10)
3365 | ((secure ? 1 : 0) << 11)
3366 | ((currentlyInsecure ? 1 : 0) << 12);
3367 }
3368
Joe Onorato808182d2010-07-09 18:52:06 -04003369 //
3370 // tracing
3371 //
3372
3373 void postStartTracing() {
3374 mHandler.postDelayed(mStartTracing, 3000);
3375 }
3376
3377 void vibrate() {
Joe Onoratof3c3c4f2010-10-21 11:09:02 -04003378 android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService(
3379 Context.VIBRATOR_SERVICE);
John Spurlock7b414672014-07-18 13:02:39 -04003380 vib.vibrate(250, VIBRATION_ATTRIBUTES);
Joe Onorato808182d2010-07-09 18:52:06 -04003381 }
3382
3383 Runnable mStartTracing = new Runnable() {
3384 public void run() {
3385 vibrate();
3386 SystemClock.sleep(250);
John Spurlockcd686b52013-06-05 10:13:46 -04003387 Log.d(TAG, "startTracing");
Joe Onorato808182d2010-07-09 18:52:06 -04003388 android.os.Debug.startMethodTracing("/data/statusbar-traces/trace");
3389 mHandler.postDelayed(mStopTracing, 10000);
3390 }
3391 };
3392
3393 Runnable mStopTracing = new Runnable() {
3394 public void run() {
3395 android.os.Debug.stopMethodTracing();
John Spurlockcd686b52013-06-05 10:13:46 -04003396 Log.d(TAG, "stopTracing");
Joe Onorato808182d2010-07-09 18:52:06 -04003397 vibrate();
3398 }
3399 };
Chris Wren0c8275b2012-05-08 13:36:48 -04003400
3401 @Override
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -07003402 public boolean shouldDisableNavbarGestures() {
Jorim Jaggi18976a52015-07-24 13:18:19 -07003403 return !isDeviceProvisioned() || (mDisabled1 & StatusBarManager.DISABLE_SEARCH) != 0;
Jim Miller670d9dd2012-05-12 13:28:26 -07003404 }
Joe Onorato808182d2010-07-09 18:52:06 -04003405
Jason Monkba2318e2015-12-08 09:04:23 -05003406 public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
3407 mHandler.post(new Runnable() {
3408 @Override
3409 public void run() {
3410 mLeaveOpenOnKeyguardHide = true;
3411 executeRunnableDismissingKeyguard(runnable, null, false, true);
3412 }
3413 });
3414 }
3415
Adrian Roos62692b22015-09-11 17:46:23 -07003416 public void postStartActivityDismissingKeyguard(final PendingIntent intent) {
3417 mHandler.post(new Runnable() {
3418 @Override
3419 public void run() {
3420 startPendingIntentDismissingKeyguard(intent);
3421 }
3422 });
3423 }
3424
Jason Monkee43cdf2015-06-19 14:20:46 -04003425 public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
John Spurlockd47a3f32014-05-18 19:14:14 -04003426 mHandler.postDelayed(new Runnable() {
John Spurlockaf8d6c42014-05-07 17:49:08 -04003427 @Override
3428 public void run() {
Jason Monkee43cdf2015-06-19 14:20:46 -04003429 handleStartActivityDismissingKeyguard(intent, true /*onlyProvisioned*/);
John Spurlockaf8d6c42014-05-07 17:49:08 -04003430 }
John Spurlockd47a3f32014-05-18 19:14:14 -04003431 }, delay);
John Spurlockaf8d6c42014-05-07 17:49:08 -04003432 }
3433
Jason Monkee43cdf2015-06-19 14:20:46 -04003434 private void handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) {
Jorim Jaggi85dc23c2014-09-08 14:42:29 +02003435 startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */);
John Spurlockde547002014-02-28 17:50:39 -05003436 }
3437
Romain Guy648342f2012-05-25 10:44:45 -07003438 private static class FastColorDrawable extends Drawable {
3439 private final int mColor;
3440
3441 public FastColorDrawable(int color) {
3442 mColor = 0xff000000 | color;
3443 }
3444
3445 @Override
3446 public void draw(Canvas canvas) {
3447 canvas.drawColor(mColor, PorterDuff.Mode.SRC);
3448 }
3449
3450 @Override
3451 public void setAlpha(int alpha) {
3452 }
3453
3454 @Override
Chris Craikbd3bfc52015-03-02 10:43:29 -08003455 public void setColorFilter(ColorFilter colorFilter) {
Romain Guy648342f2012-05-25 10:44:45 -07003456 }
3457
3458 @Override
3459 public int getOpacity() {
3460 return PixelFormat.OPAQUE;
3461 }
3462
3463 @Override
3464 public void setBounds(int left, int top, int right, int bottom) {
3465 }
3466
3467 @Override
3468 public void setBounds(Rect bounds) {
3469 }
3470 }
John Spurlock5c454122013-06-17 07:35:46 -04003471
3472 @Override
3473 public void destroy() {
3474 super.destroy();
3475 if (mStatusBarWindow != null) {
3476 mWindowManager.removeViewImmediate(mStatusBarWindow);
John Spurlockab847cf2014-01-15 14:13:59 -05003477 mStatusBarWindow = null;
John Spurlock5c454122013-06-17 07:35:46 -04003478 }
3479 if (mNavigationBarView != null) {
3480 mWindowManager.removeViewImmediate(mNavigationBarView);
John Spurlockab847cf2014-01-15 14:13:59 -05003481 mNavigationBarView = null;
John Spurlock5c454122013-06-17 07:35:46 -04003482 }
Jason Monk4ae97d32014-12-17 10:14:33 -05003483 if (mHandlerThread != null) {
3484 mHandlerThread.quitSafely();
3485 mHandlerThread = null;
3486 }
John Spurlock5c454122013-06-17 07:35:46 -04003487 mContext.unregisterReceiver(mBroadcastReceiver);
Adrian Roos8e3e8362015-07-16 19:42:22 -07003488 mContext.unregisterReceiver(mDemoReceiver);
Selim Cineke70d6532015-04-24 16:46:13 -07003489 mAssistManager.destroy();
Jason Monk07b75fe2015-05-14 16:47:03 -04003490
3491 final SignalClusterView signalCluster =
3492 (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
3493 final SignalClusterView signalClusterKeyguard =
3494 (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
3495 final SignalClusterView signalClusterQs =
3496 (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
Jason Monk5e745172015-06-02 19:14:44 -04003497 mNetworkController.removeSignalCallback(signalCluster);
3498 mNetworkController.removeSignalCallback(signalClusterKeyguard);
3499 mNetworkController.removeSignalCallback(signalClusterQs);
3500 if (mQSPanel != null && mQSPanel.getHost() != null) {
3501 mQSPanel.getHost().destroy();
3502 }
John Spurlock5c454122013-06-17 07:35:46 -04003503 }
John Spurlock3c875662013-08-31 15:07:25 -04003504
3505 private boolean mDemoModeAllowed;
3506 private boolean mDemoMode;
John Spurlock3c875662013-08-31 15:07:25 -04003507
3508 @Override
3509 public void dispatchDemoCommand(String command, Bundle args) {
3510 if (!mDemoModeAllowed) {
3511 mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(),
Jason Monk431ad732015-07-16 08:58:15 -04003512 DEMO_MODE_ALLOWED, 0) != 0;
John Spurlock3c875662013-08-31 15:07:25 -04003513 }
3514 if (!mDemoModeAllowed) return;
3515 if (command.equals(COMMAND_ENTER)) {
3516 mDemoMode = true;
3517 } else if (command.equals(COMMAND_EXIT)) {
3518 mDemoMode = false;
3519 checkBarModes();
3520 } else if (!mDemoMode) {
3521 // automatically enter demo mode on first demo command
3522 dispatchDemoCommand(COMMAND_ENTER, new Bundle());
3523 }
3524 boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT);
John Spurlockbb4a7022014-11-08 12:40:19 -05003525 if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) {
3526 mVolumeComponent.dispatchDemoCommand(command, args);
3527 }
John Spurlock3c875662013-08-31 15:07:25 -04003528 if (modeChange || command.equals(COMMAND_CLOCK)) {
3529 dispatchDemoCommandToView(command, args, R.id.clock);
3530 }
3531 if (modeChange || command.equals(COMMAND_BATTERY)) {
3532 dispatchDemoCommandToView(command, args, R.id.battery);
3533 }
3534 if (modeChange || command.equals(COMMAND_STATUS)) {
Jorim Jaggi66ac1332015-01-21 19:22:26 +01003535 mIconController.dispatchDemoCommand(command, args);
3536
John Spurlock3c875662013-08-31 15:07:25 -04003537 }
3538 if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) {
3539 mNetworkController.dispatchDemoCommand(command, args);
3540 }
John Spurlock7f42fc52014-01-14 16:20:39 -05003541 if (modeChange || command.equals(COMMAND_NOTIFICATIONS)) {
3542 View notifications = mStatusBarView == null ? null
3543 : mStatusBarView.findViewById(R.id.notification_icon_area);
3544 if (notifications != null) {
3545 String visible = args.getString("visible");
3546 int vis = mDemoMode && "false".equals(visible) ? View.INVISIBLE : View.VISIBLE;
3547 notifications.setVisibility(vis);
3548 }
3549 }
John Spurlock3c875662013-08-31 15:07:25 -04003550 if (command.equals(COMMAND_BARS)) {
3551 String mode = args.getString("mode");
3552 int barMode = "opaque".equals(mode) ? MODE_OPAQUE :
John Spurlockbd957402013-10-03 11:38:39 -04003553 "translucent".equals(mode) ? MODE_TRANSLUCENT :
John Spurlock3c875662013-08-31 15:07:25 -04003554 "semi-transparent".equals(mode) ? MODE_SEMI_TRANSPARENT :
John Spurlock0ff62e02014-07-22 16:15:08 -04003555 "transparent".equals(mode) ? MODE_TRANSPARENT :
3556 "warning".equals(mode) ? MODE_WARNING :
John Spurlock3c875662013-08-31 15:07:25 -04003557 -1;
3558 if (barMode != -1) {
3559 boolean animate = true;
3560 if (mStatusBarView != null) {
3561 mStatusBarView.getBarTransitions().transitionTo(barMode, animate);
3562 }
3563 if (mNavigationBarView != null) {
3564 mNavigationBarView.getBarTransitions().transitionTo(barMode, animate);
3565 }
3566 }
3567 }
3568 }
3569
3570 private void dispatchDemoCommandToView(String command, Bundle args, int id) {
3571 if (mStatusBarView == null) return;
3572 View v = mStatusBarView.findViewById(id);
3573 if (v instanceof DemoMode) {
3574 ((DemoMode)v).dispatchDemoCommand(command, args);
3575 }
3576 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003577
Jorim Jaggiecbab362014-04-23 16:13:15 +02003578 /**
3579 * @return The {@link StatusBarState} the status bar is in.
3580 */
3581 public int getBarState() {
3582 return mState;
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003583 }
3584
Chris Wren16895942015-06-23 11:22:20 -04003585 @Override
Yorke Leee4ea6ab2016-03-03 14:51:49 -08003586 public boolean isPanelFullyCollapsed() {
Chris Wren16895942015-06-23 11:22:20 -04003587 return mNotificationPanel.isFullyCollapsed();
3588 }
3589
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003590 public void showKeyguard() {
Jorim Jaggi5e08e692014-10-03 15:17:20 -07003591 if (mLaunchTransitionFadingAway) {
3592 mNotificationPanel.animate().cancel();
Selim Cinek37c110f2015-05-22 12:38:44 -07003593 onLaunchTransitionFadingEnded();
Jorim Jaggi5e08e692014-10-03 15:17:20 -07003594 }
Jorim Jaggi826730a2014-12-08 21:05:13 +01003595 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -07003596 if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) {
3597 setBarState(StatusBarState.FULLSCREEN_USER_SWITCHER);
3598 } else {
3599 setBarState(StatusBarState.KEYGUARD);
3600 }
Jorim Jaggi98f85302014-08-07 17:45:04 +02003601 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07003602 if (!mDeviceInteractive) {
Jorim Jaggid41083a2014-09-12 02:54:40 +02003603
3604 // If the screen is off already, we need to disable touch events because these might
3605 // collapse the panel after we expanded it, and thus we would end up with a blank
3606 // Keyguard.
3607 mNotificationPanel.setTouchDisabled(true);
3608 }
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -07003609 if (mState == StatusBarState.KEYGUARD) {
3610 instantExpandNotificationsPanel();
3611 } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
3612 instantCollapseNotificationPanel();
3613 }
Jorim Jaggiecbab362014-04-23 16:13:15 +02003614 mLeaveOpenOnKeyguardHide = false;
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003615 if (mDraggedDownRow != null) {
3616 mDraggedDownRow.setUserLocked(false);
Selim Cinekb5605e52015-02-20 18:21:41 +01003617 mDraggedDownRow.notifyHeightChanged(false /* needsAnimation */);
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003618 mDraggedDownRow = null;
3619 }
Adrian Roos3aec6382016-02-05 14:19:01 -08003620 mPendingRemoteInputView = null;
Jorim Jaggi19695d92015-07-20 15:51:40 -07003621 mAssistManager.onLockscreenShown();
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003622 }
3623
Selim Cinek37c110f2015-05-22 12:38:44 -07003624 private void onLaunchTransitionFadingEnded() {
3625 mNotificationPanel.setAlpha(1.0f);
Selim Cinek372d1bd2015-08-14 13:19:37 -07003626 mNotificationPanel.onAffordanceLaunchEnded();
3627 releaseGestureWakeLock();
Selim Cinek37c110f2015-05-22 12:38:44 -07003628 runLaunchTransitionEndRunnable();
3629 mLaunchTransitionFadingAway = false;
3630 mScrimController.forceHideScrims(false /* hide */);
Adrian Roos52738322016-01-29 08:49:21 -08003631 updateMediaMetaData(true /* metaDataChanged */, true);
Selim Cinek37c110f2015-05-22 12:38:44 -07003632 }
3633
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02003634 public boolean isCollapsing() {
3635 return mNotificationPanel.isCollapsing();
3636 }
3637
3638 public void addPostCollapseAction(Runnable r) {
3639 mPostCollapseRunnables.add(r);
3640 }
3641
Selim Cinekbaa23272014-07-08 18:01:07 +02003642 public boolean isInLaunchTransition() {
3643 return mNotificationPanel.isLaunchTransitionRunning()
3644 || mNotificationPanel.isLaunchTransitionFinished();
3645 }
3646
3647 /**
3648 * Fades the content of the keyguard away after the launch transition is done.
3649 *
3650 * @param beforeFading the runnable to be run when the circle is fully expanded and the fading
3651 * starts
3652 * @param endRunnable the runnable to be run when the transition is done
3653 */
3654 public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading,
Jorim Jaggi5e08e692014-10-03 15:17:20 -07003655 Runnable endRunnable) {
Jorim Jaggi826730a2014-12-08 21:05:13 +01003656 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
Jorim Jaggi5e08e692014-10-03 15:17:20 -07003657 mLaunchTransitionEndRunnable = endRunnable;
Selim Cinekbaa23272014-07-08 18:01:07 +02003658 Runnable hideRunnable = new Runnable() {
3659 @Override
3660 public void run() {
3661 mLaunchTransitionFadingAway = true;
3662 if (beforeFading != null) {
3663 beforeFading.run();
3664 }
Selim Cinek37c110f2015-05-22 12:38:44 -07003665 mScrimController.forceHideScrims(true /* hide */);
Adrian Roos52738322016-01-29 08:49:21 -08003666 updateMediaMetaData(false, true);
Selim Cinekbaa23272014-07-08 18:01:07 +02003667 mNotificationPanel.setAlpha(1);
3668 mNotificationPanel.animate()
3669 .alpha(0)
3670 .setStartDelay(FADE_KEYGUARD_START_DELAY)
3671 .setDuration(FADE_KEYGUARD_DURATION)
3672 .withLayer()
3673 .withEndAction(new Runnable() {
3674 @Override
3675 public void run() {
Selim Cinek37c110f2015-05-22 12:38:44 -07003676 onLaunchTransitionFadingEnded();
Selim Cinekbaa23272014-07-08 18:01:07 +02003677 }
3678 });
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01003679 mIconController.appTransitionStarting(SystemClock.uptimeMillis(),
3680 StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
Selim Cinekbaa23272014-07-08 18:01:07 +02003681 }
3682 };
3683 if (mNotificationPanel.isLaunchTransitionRunning()) {
3684 mNotificationPanel.setLaunchTransitionEndRunnable(hideRunnable);
3685 } else {
3686 hideRunnable.run();
3687 }
3688 }
3689
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003690 /**
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07003691 * Fades the content of the Keyguard while we are dozing and makes it invisible when finished
3692 * fading.
3693 */
3694 public void fadeKeyguardWhilePulsing() {
3695 mNotificationPanel.animate()
3696 .alpha(0f)
3697 .setStartDelay(0)
3698 .setDuration(FADE_KEYGUARD_DURATION_PULSING)
Jorim Jaggiab45a212015-08-20 16:59:44 -07003699 .setInterpolator(ScrimController.KEYGUARD_FADE_OUT_INTERPOLATOR)
3700 .start();
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07003701 }
3702
3703 /**
Jorim Jaggi826730a2014-12-08 21:05:13 +01003704 * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
3705 * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
3706 * because the launched app crashed or something else went wrong.
3707 */
3708 public void startLaunchTransitionTimeout() {
3709 mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT,
3710 LAUNCH_TRANSITION_TIMEOUT_MS);
3711 }
3712
3713 private void onLaunchTransitionTimeout() {
3714 Log.w(TAG, "Launch transition: Timeout!");
Selim Cinek372d1bd2015-08-14 13:19:37 -07003715 mNotificationPanel.onAffordanceLaunchEnded();
3716 releaseGestureWakeLock();
Jorim Jaggi826730a2014-12-08 21:05:13 +01003717 mNotificationPanel.resetViews();
3718 }
3719
3720 private void runLaunchTransitionEndRunnable() {
3721 if (mLaunchTransitionEndRunnable != null) {
3722 Runnable r = mLaunchTransitionEndRunnable;
3723
3724 // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again,
3725 // which would lead to infinite recursion. Protect against it.
3726 mLaunchTransitionEndRunnable = null;
3727 r.run();
3728 }
3729 }
3730
3731 /**
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003732 * @return true if we would like to stay in the shade, false if it should go away entirely
3733 */
3734 public boolean hideKeyguard() {
3735 boolean staying = mLeaveOpenOnKeyguardHide;
Jorim Jaggiecbab362014-04-23 16:13:15 +02003736 setBarState(StatusBarState.SHADE);
Adrian Roos3aec6382016-02-05 14:19:01 -08003737 View viewToClick = null;
Jorim Jaggiecbab362014-04-23 16:13:15 +02003738 if (mLeaveOpenOnKeyguardHide) {
3739 mLeaveOpenOnKeyguardHide = false;
Jorim Jaggi37c11802015-08-18 20:27:54 -07003740 long delay = calculateGoingToFullShadeDelay();
3741 mNotificationPanel.animateToFullShade(delay);
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003742 if (mDraggedDownRow != null) {
3743 mDraggedDownRow.setUserLocked(false);
3744 mDraggedDownRow = null;
3745 }
Adrian Roos3aec6382016-02-05 14:19:01 -08003746 viewToClick = mPendingRemoteInputView;
3747 mPendingRemoteInputView = null;
Jorim Jaggi37c11802015-08-18 20:27:54 -07003748
3749 // Disable layout transitions in navbar for this transition because the load is just
3750 // too heavy for the CPU and GPU on any device.
3751 if (mNavigationBarView != null) {
3752 mNavigationBarView.setLayoutTransitionsEnabled(false);
3753 mNavigationBarView.postDelayed(new Runnable() {
3754 @Override
3755 public void run() {
3756 mNavigationBarView.setLayoutTransitionsEnabled(true);
3757 }
3758 }, delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
3759 }
Jorim Jaggiecbab362014-04-23 16:13:15 +02003760 } else {
3761 instantCollapseNotificationPanel();
3762 }
Jorim Jaggi98f85302014-08-07 17:45:04 +02003763 updateKeyguardState(staying, false /* fromShadeLocked */);
Jorim Jaggi1ecd7cd2014-11-03 16:18:03 +01003764
Adrian Roos3aec6382016-02-05 14:19:01 -08003765 if (viewToClick != null) {
3766 viewToClick.callOnClick();
3767 }
3768
Jorim Jaggi1ecd7cd2014-11-03 16:18:03 +01003769 // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
3770 // visibilities so next time we open the panel we know the correct height already.
3771 if (mQSPanel != null) {
3772 mQSPanel.refreshAllTiles();
3773 }
Jorim Jaggi826730a2014-12-08 21:05:13 +01003774 mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
Selim Cinek372d1bd2015-08-14 13:19:37 -07003775 releaseGestureWakeLock();
3776 mNotificationPanel.onAffordanceLaunchEnded();
Jorim Jaggi52429b42015-09-03 19:58:19 -07003777 mNotificationPanel.animate().cancel();
Jorim Jaggi90978852015-08-18 19:55:53 -07003778 mNotificationPanel.setAlpha(1f);
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003779 return staying;
3780 }
3781
Selim Cinek372d1bd2015-08-14 13:19:37 -07003782 private void releaseGestureWakeLock() {
3783 if (mGestureWakeLock.isHeld()) {
3784 mGestureWakeLock.release();
3785 }
3786 }
3787
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003788 public long calculateGoingToFullShadeDelay() {
3789 return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
Jorim Jaggi15682502014-04-23 12:01:36 +02003790 }
3791
Jorim Jaggi44cf9192014-06-17 19:16:00 -07003792 /**
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01003793 * Notifies the status bar that Keyguard is going away very soon.
3794 */
3795 public void keyguardGoingAway() {
3796
3797 // Treat Keyguard exit animation as an app transition to achieve nice transition for status
3798 // bar.
Adrian Roos46df1ca2015-09-11 12:38:43 -07003799 mKeyguardGoingAway = true;
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01003800 mIconController.appTransitionPending();
3801 }
3802
3803 /**
Jorim Jaggi44cf9192014-06-17 19:16:00 -07003804 * Notifies the status bar the Keyguard is fading away with the specified timings.
3805 *
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01003806 * @param startTime the start time of the animations in uptime millis
3807 * @param delay the precalculated animation delay in miliseconds
Jorim Jaggi44cf9192014-06-17 19:16:00 -07003808 * @param fadeoutDuration the duration of the exit animation, in milliseconds
3809 */
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01003810 public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) {
Jorim Jaggi44cf9192014-06-17 19:16:00 -07003811 mKeyguardFadingAway = true;
3812 mKeyguardFadingAwayDelay = delay;
3813 mKeyguardFadingAwayDuration = fadeoutDuration;
3814 mWaitingForKeyguardExit = false;
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01003815 mIconController.appTransitionStarting(
3816 startTime + fadeoutDuration
3817 - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION,
3818 StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION);
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -07003819 disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */);
Jorim Jaggi44cf9192014-06-17 19:16:00 -07003820 }
3821
Jorim Jaggi416493b2014-09-13 03:57:32 +02003822 public boolean isKeyguardFadingAway() {
3823 return mKeyguardFadingAway;
3824 }
3825
Jorim Jaggi44cf9192014-06-17 19:16:00 -07003826 /**
3827 * Notifies that the Keyguard fading away animation is done.
3828 */
3829 public void finishKeyguardFadingAway() {
3830 mKeyguardFadingAway = false;
Adrian Roos46df1ca2015-09-11 12:38:43 -07003831 mKeyguardGoingAway = false;
Jorim Jaggi44cf9192014-06-17 19:16:00 -07003832 }
3833
Adrian Roosd322f1a2015-04-23 15:19:45 -07003834 public void stopWaitingForKeyguardExit() {
3835 mWaitingForKeyguardExit = false;
3836 }
3837
Jorim Jaggi15682502014-04-23 12:01:36 +02003838 private void updatePublicMode() {
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01003839 setLockscreenPublicMode(
3840 mStatusBarKeyguardViewManager.isShowing() && mStatusBarKeyguardViewManager
3841 .isSecure(mCurrentUserId));
Jorim Jaggi15682502014-04-23 12:01:36 +02003842 }
3843
Rakesh Iyer2790a372016-01-22 15:33:39 -08003844 protected void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
Jorim Jaggiecbab362014-04-23 16:13:15 +02003845 if (mState == StatusBarState.KEYGUARD) {
Adrian Roos12c1ef52014-06-04 13:54:08 +02003846 mKeyguardIndicationController.setVisible(true);
Selim Cinek4c6969a2014-05-26 19:22:17 +02003847 mNotificationPanel.resetViews();
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -07003848 if (mKeyguardUserSwitcher != null) {
3849 mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked);
3850 }
Selim Cinek80c2abe2015-06-17 15:37:30 -07003851 mStatusBarView.removePendingHideExpandedRunnables();
Jorim Jaggi15682502014-04-23 12:01:36 +02003852 } else {
Adrian Roos12c1ef52014-06-04 13:54:08 +02003853 mKeyguardIndicationController.setVisible(false);
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -07003854 if (mKeyguardUserSwitcher != null) {
3855 mKeyguardUserSwitcher.setKeyguard(false,
3856 goingToFullShade ||
3857 mState == StatusBarState.SHADE_LOCKED ||
3858 fromShadeLocked);
3859 }
Jorim Jaggi15682502014-04-23 12:01:36 +02003860 }
Jorim Jaggi2042ef22014-05-13 21:55:18 +02003861 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
Jorim Jaggiecc798e2014-05-26 18:14:37 +02003862 mScrimController.setKeyguardShowing(true);
Kenny Guy3094d4a2015-04-01 19:14:10 +01003863 mIconPolicy.setKeyguardShowing(true);
Jorim Jaggi2042ef22014-05-13 21:55:18 +02003864 } else {
Jorim Jaggiecc798e2014-05-26 18:14:37 +02003865 mScrimController.setKeyguardShowing(false);
Kenny Guy3094d4a2015-04-01 19:14:10 +01003866 mIconPolicy.setKeyguardShowing(false);
Jorim Jaggi2042ef22014-05-13 21:55:18 +02003867 }
Rakesh Iyer2790a372016-01-22 15:33:39 -08003868
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02003869 mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade);
John Spurlockbf370992014-06-17 13:58:31 -04003870 updateDozingState();
Jorim Jaggi15682502014-04-23 12:01:36 +02003871 updatePublicMode();
Selim Cinekd35c2792016-01-21 13:20:57 -08003872 updateStackScrollerState(goingToFullShade, fromShadeLocked);
Christoph Studer37fe6932014-05-26 13:10:30 +02003873 updateNotifications();
Jorim Jaggia6310292014-04-16 14:11:52 +02003874 checkBarModes();
Adrian Roos52738322016-01-29 08:49:21 -08003875 updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
John Spurlock657c62c2014-07-22 12:18:09 -04003876 mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
3877 mStatusBarKeyguardViewManager.isSecure());
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003878 }
3879
John Spurlockbf370992014-06-17 13:58:31 -04003880 private void updateDozingState() {
Jorim Jaggi4e857f42014-11-17 19:14:04 +01003881 boolean animate = !mDozing && mDozeScrimController.isPulsing();
3882 mNotificationPanel.setDozing(mDozing, animate);
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07003883 mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
Jorim Jaggi048af1f2014-11-11 22:51:10 +01003884 mScrimController.setDozing(mDozing);
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07003885
3886 // Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock
3887 // for pulsing so the Keyguard fade-out animation scrim can take over.
3888 mDozeScrimController.setDozing(mDozing &&
3889 mFingerprintUnlockController.getMode()
3890 != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, animate);
John Spurlockbf370992014-06-17 13:58:31 -04003891 }
3892
Selim Cinekd35c2792016-01-21 13:20:57 -08003893 public void updateStackScrollerState(boolean goingToFullShade, boolean fromShadeLocked) {
John Spurlock4b3bda22014-05-22 14:32:20 -04003894 if (mStackScroller == null) return;
Selim Cinek1408eb52014-06-02 14:45:38 +02003895 boolean onKeyguard = mState == StatusBarState.KEYGUARD;
Jorim Jaggiae441282014-08-01 02:45:18 +02003896 mStackScroller.setHideSensitive(isLockscreenPublicMode(), goingToFullShade);
Selim Cinekd35c2792016-01-21 13:20:57 -08003897 mStackScroller.setDimmed(onKeyguard, fromShadeLocked /* animate */);
Selim Cinek1408eb52014-06-02 14:45:38 +02003898 mStackScroller.setExpandingEnabled(!onKeyguard);
Selim Cineka32ab602014-06-11 15:06:01 +02003899 ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild();
3900 mStackScroller.setActivatedChild(null);
3901 if (activatedChild != null) {
3902 activatedChild.makeInactive(false /* animate */);
3903 }
Jorim Jaggid552d9d2014-05-07 19:41:13 +02003904 }
3905
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003906 public void userActivity() {
Jorim Jaggib690f0d2014-07-03 23:25:44 +02003907 if (mState == StatusBarState.KEYGUARD) {
3908 mKeyguardViewMediatorCallback.userActivity();
3909 }
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003910 }
3911
Jorim Jaggidf993512014-05-13 23:06:35 +02003912 public boolean interceptMediaKey(KeyEvent event) {
3913 return mState == StatusBarState.KEYGUARD
3914 && mStatusBarKeyguardViewManager.interceptMediaKey(event);
3915 }
3916
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +02003917 public boolean onMenuPressed() {
Selim Cinek28540192016-02-19 17:25:08 -08003918 if (mDeviceInteractive && mState != StatusBarState.SHADE
3919 && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed()) {
3920 animateCollapsePanels(
3921 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
3922 return true;
3923 }
3924 return false;
Jorim Jaggi8c8bcc12014-04-16 21:36:51 +02003925 }
3926
Selim Cinek372d1bd2015-08-14 13:19:37 -07003927 public void endAffordanceLaunch() {
3928 releaseGestureWakeLock();
3929 mNotificationPanel.onAffordanceLaunchEnded();
3930 }
3931
Jorim Jaggie5c7a892014-04-10 20:37:32 +02003932 public boolean onBackPressed() {
Adrian Roos0002a452014-07-03 13:46:07 +02003933 if (mStatusBarKeyguardViewManager.onBackPressed()) {
Jorim Jaggie5c7a892014-04-10 20:37:32 +02003934 return true;
3935 }
Adrian Roos0002a452014-07-03 13:46:07 +02003936 if (mNotificationPanel.isQsExpanded()) {
John Spurlockf7ae4422014-08-01 12:45:18 -04003937 if (mNotificationPanel.isQsDetailShowing()) {
3938 mNotificationPanel.closeQsDetail();
3939 } else {
3940 mNotificationPanel.animateCloseQs();
3941 }
Adrian Roos0002a452014-07-03 13:46:07 +02003942 return true;
3943 }
3944 if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) {
3945 animateCollapsePanels();
3946 return true;
3947 }
3948 return false;
Jorim Jaggie5c7a892014-04-10 20:37:32 +02003949 }
3950
Jorim Jaggi34250762014-07-03 23:51:19 +02003951 public boolean onSpacePressed() {
Xiyuan Xiacc3a74f62015-07-22 14:16:34 -07003952 if (mDeviceInteractive && mState != StatusBarState.SHADE) {
Jorim Jaggi4eedc1d2014-10-27 13:45:56 +01003953 animateCollapsePanels(
3954 CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
Jorim Jaggi34250762014-07-03 23:51:19 +02003955 return true;
3956 }
3957 return false;
3958 }
3959
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003960 private void showBouncer() {
Jorim Jaggiecbab362014-04-23 16:13:15 +02003961 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
Selim Cinekbaa23272014-07-08 18:01:07 +02003962 mWaitingForKeyguardExit = mStatusBarKeyguardViewManager.isShowing();
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003963 mStatusBarKeyguardViewManager.dismiss();
3964 }
3965 }
3966
3967 private void instantExpandNotificationsPanel() {
Jorim Jaggic357ca22014-04-25 14:56:15 +02003968
Jorim Jaggi0a27be82014-06-11 03:22:39 +02003969 // Make our window larger and the panel expanded.
Jorim Jaggifa505a72014-04-28 20:04:11 +02003970 makeExpandedVisible(true);
Oren Blasberg8d3fea12015-07-10 14:21:44 -07003971 mNotificationPanel.expand(false /* animate */);
Jorim Jaggi03c701e2014-04-02 12:39:51 +02003972 }
Adrian Roos5a46cd32014-04-03 16:51:58 +02003973
Jorim Jaggia005f1b2014-04-16 19:06:10 +02003974 private void instantCollapseNotificationPanel() {
Selim Cinek6bb4a9b2014-10-09 17:48:05 -07003975 mNotificationPanel.instantCollapse();
Jorim Jaggia005f1b2014-04-16 19:06:10 +02003976 }
3977
Jorim Jaggid4a57442014-04-10 02:45:55 +02003978 @Override
Selim Cineka32ab602014-06-11 15:06:01 +02003979 public void onActivated(ActivatableNotificationView view) {
Christoph Studerb0183992014-12-22 21:02:26 +01003980 EventLogTags.writeSysuiLockscreenGesture(
3981 EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_TAP_NOTIFICATION_ACTIVATE,
3982 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
Adrian Roos12c1ef52014-06-04 13:54:08 +02003983 mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again);
Selim Cineka32ab602014-06-11 15:06:01 +02003984 ActivatableNotificationView previousView = mStackScroller.getActivatedChild();
3985 if (previousView != null) {
3986 previousView.makeInactive(true /* animate */);
3987 }
Jorim Jaggid552d9d2014-05-07 19:41:13 +02003988 mStackScroller.setActivatedChild(view);
Jorim Jaggic5dc0d02014-04-15 15:42:55 +02003989 }
3990
Jorim Jaggiecbab362014-04-23 16:13:15 +02003991 /**
3992 * @param state The {@link StatusBarState} to set.
3993 */
3994 public void setBarState(int state) {
Christoph Studer2231c6e2014-12-19 12:40:13 +01003995 // If we're visible and switched to SHADE_LOCKED (the user dragged
3996 // down on the lockscreen), clear notification LED, vibration,
3997 // ringing.
3998 // Other transitions are covered in handleVisibleToUserChanged().
Selim Cinek6577cae2015-08-31 16:15:49 -07003999 if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED
4000 || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) {
4001 clearNotificationEffects();
Christoph Studer1f32c652014-11-26 15:32:20 +01004002 }
Jorim Jaggiecbab362014-04-23 16:13:15 +02004003 mState = state;
Selim Cinek9c4c4142015-12-04 16:44:56 -08004004 mGroupManager.setStatusBarState(state);
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004005 mFalsingManager.setStatusBarState(state);
Jorim Jaggiecbab362014-04-23 16:13:15 +02004006 mStatusBarWindowManager.setStatusBarState(state);
Jorim Jaggi83969702015-06-05 14:59:24 -07004007 updateDozing();
Jorim Jaggiecbab362014-04-23 16:13:15 +02004008 }
4009
Jorim Jaggic5dc0d02014-04-15 15:42:55 +02004010 @Override
Selim Cineka32ab602014-06-11 15:06:01 +02004011 public void onActivationReset(ActivatableNotificationView view) {
Jorim Jaggid552d9d2014-05-07 19:41:13 +02004012 if (view == mStackScroller.getActivatedChild()) {
Adrian Roos12c1ef52014-06-04 13:54:08 +02004013 mKeyguardIndicationController.hideTransientIndication();
Jorim Jaggid552d9d2014-05-07 19:41:13 +02004014 mStackScroller.setActivatedChild(null);
4015 }
Jorim Jaggie70d31f2014-04-24 22:08:30 +02004016 }
4017
4018 public void onTrackingStarted() {
Jorim Jaggi8de4311c2014-08-11 22:36:20 +02004019 runPostCollapseRunnables();
Jorim Jaggi90129582014-06-02 14:44:49 +02004020 }
4021
Selim Cinekdbbcfbe2014-10-24 17:52:35 +02004022 public void onClosingFinished() {
4023 runPostCollapseRunnables();
4024 }
4025
Jorim Jaggi90129582014-06-02 14:44:49 +02004026 public void onUnlockHintStarted() {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004027 mFalsingManager.onUnlockHintStarted();
Adrian Roos12c1ef52014-06-04 13:54:08 +02004028 mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
Jorim Jaggi90129582014-06-02 14:44:49 +02004029 }
4030
Jorim Jaggib3f0a2f2014-06-02 19:29:39 +02004031 public void onHintFinished() {
Jorim Jaggi93a2bb22014-06-02 19:57:28 +02004032 // Delay the reset a bit so the user can read the text.
Adrian Roos12c1ef52014-06-04 13:54:08 +02004033 mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
Jorim Jaggie70d31f2014-04-24 22:08:30 +02004034 }
4035
Jorim Jaggib3f0a2f2014-06-02 19:29:39 +02004036 public void onCameraHintStarted() {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004037 mFalsingManager.onCameraHintStarted();
Adrian Roos12c1ef52014-06-04 13:54:08 +02004038 mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
Jorim Jaggib3f0a2f2014-06-02 19:29:39 +02004039 }
4040
Selim Cineke70d6532015-04-24 16:46:13 -07004041 public void onVoiceAssistHintStarted() {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004042 mFalsingManager.onLeftAffordanceHintStarted();
Selim Cineke70d6532015-04-24 16:46:13 -07004043 mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
4044 }
4045
Jorim Jaggib3f0a2f2014-06-02 19:29:39 +02004046 public void onPhoneHintStarted() {
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004047 mFalsingManager.onLeftAffordanceHintStarted();
Adrian Roos12c1ef52014-06-04 13:54:08 +02004048 mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
Jorim Jaggib3f0a2f2014-06-02 19:29:39 +02004049 }
4050
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +02004051 public void onTrackingStopped(boolean expand) {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +02004052 if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
Selim Cineke8bae622015-07-15 13:24:06 -07004053 if (!expand && !mUnlockMethodCache.canSkipBouncer()) {
Jorim Jaggi2fbad7b2014-05-26 22:38:00 +02004054 showBouncer();
4055 }
4056 }
Jorim Jaggie70d31f2014-04-24 22:08:30 +02004057 }
4058
4059 @Override
Selim Cinek5f71bee2015-11-18 10:25:23 -08004060 protected int getMaxKeyguardNotifications(boolean recompute) {
4061 if (recompute) {
4062 mMaxKeyguardNotifications = Math.max(1,
4063 mNotificationPanel.computeMaxKeyguardNotifications(
4064 mMaxAllowedKeyguardNotifications));
4065 return mMaxKeyguardNotifications;
4066 }
4067 return mMaxKeyguardNotifications;
4068 }
4069
4070 public int getMaxKeyguardNotifications() {
4071 return getMaxKeyguardNotifications(false /* recompute */);
Jorim Jaggid4a57442014-04-10 02:45:55 +02004072 }
4073
Jorim Jaggia6310292014-04-16 14:11:52 +02004074 public NavigationBarView getNavigationBarView() {
4075 return mNavigationBarView;
4076 }
4077
Jorim Jaggiecbab362014-04-23 16:13:15 +02004078 // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
4079
4080 @Override
Christoph Studerb0183992014-12-22 21:02:26 +01004081 public boolean onDraggedDown(View startingChild, int dragLengthY) {
Christoph Studerc8db24b2014-07-25 17:50:30 +02004082 if (hasActiveNotifications()) {
Christoph Studerb0183992014-12-22 21:02:26 +01004083 EventLogTags.writeSysuiLockscreenGesture(
4084 EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DOWN_FULL_SHADE,
4085 (int) (dragLengthY / mDisplayMetrics.density),
4086 0 /* velocityDp - N/A */);
Jorim Jaggi48bc36a2014-07-25 23:16:04 +02004087
4088 // We have notifications, go to locked shade.
4089 goToLockedShade(startingChild);
4090 return true;
4091 } else {
4092
4093 // No notifications - abort gesture.
4094 return false;
4095 }
Jorim Jaggiecbab362014-04-23 16:13:15 +02004096 }
4097
4098 @Override
Jorim Jaggid552d9d2014-05-07 19:41:13 +02004099 public void onDragDownReset() {
4100 mStackScroller.setDimmed(true /* dimmed */, true /* animated */);
Selim Cinek177fd432015-11-18 11:53:47 -08004101 mStackScroller.resetScrollPosition();
Jorim Jaggiecbab362014-04-23 16:13:15 +02004102 }
4103
Jorim Jaggi48bc36a2014-07-25 23:16:04 +02004104 @Override
Selim Cinek177fd432015-11-18 11:53:47 -08004105 public void onCrossedThreshold(boolean above) {
4106 mStackScroller.setDimmed(!above /* dimmed */, true /* animate */);
Jorim Jaggiecbab362014-04-23 16:13:15 +02004107 }
4108
Selim Cinek1408eb52014-06-02 14:45:38 +02004109 @Override
4110 public void onTouchSlopExceeded() {
4111 mStackScroller.removeLongPressCallback();
4112 }
4113
Jorim Jaggi48bc36a2014-07-25 23:16:04 +02004114 @Override
4115 public void setEmptyDragAmount(float amount) {
4116 mNotificationPanel.setEmptyDragAmount(amount);
4117 }
4118
Jorim Jaggiecbab362014-04-23 16:13:15 +02004119 /**
4120 * If secure with redaction: Show bouncer, go to unlocked shade.
4121 *
Jorim Jaggi2042ef22014-05-13 21:55:18 +02004122 * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
Jorim Jaggiecbab362014-04-23 16:13:15 +02004123 *
4124 * @param expandView The view to expand after going to the shade.
4125 */
4126 public void goToLockedShade(View expandView) {
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02004127 ExpandableNotificationRow row = null;
Jorim Jaggiecbab362014-04-23 16:13:15 +02004128 if (expandView instanceof ExpandableNotificationRow) {
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02004129 row = (ExpandableNotificationRow) expandView;
Selim Cinekcb24ab82016-02-25 12:49:08 -08004130 row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */);
Jorim Jaggiecbab362014-04-23 16:13:15 +02004131 }
Adrian Roosaee70462014-09-03 16:27:39 +02004132 boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004133 || !mShowLockscreenNotifications || mFalsingManager.shouldEnforceBouncer();
Adrian Roosaee70462014-09-03 16:27:39 +02004134 if (isLockscreenPublicMode() && fullShadeNeedsBouncer) {
Jorim Jaggiecbab362014-04-23 16:13:15 +02004135 mLeaveOpenOnKeyguardHide = true;
4136 showBouncer();
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02004137 mDraggedDownRow = row;
Adrian Roos3aec6382016-02-05 14:19:01 -08004138 mPendingRemoteInputView = null;
Jorim Jaggi2042ef22014-05-13 21:55:18 +02004139 } else {
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02004140 mNotificationPanel.animateToFullShade(0 /* delay */);
Jorim Jaggiecbab362014-04-23 16:13:15 +02004141 setBarState(StatusBarState.SHADE_LOCKED);
Jorim Jaggi98f85302014-08-07 17:45:04 +02004142 updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */);
Jorim Jaggiecbab362014-04-23 16:13:15 +02004143 }
4144 }
4145
Selim Cinek570981d2015-12-01 11:37:01 -08004146 @Override
Adrian Roos3aec6382016-02-05 14:19:01 -08004147 protected void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) {
4148 mLeaveOpenOnKeyguardHide = true;
4149 showBouncer();
4150 mPendingRemoteInputView = clicked;
4151 }
4152
4153 @Override
Selim Cinek31aada42015-12-18 17:51:15 -08004154 public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
4155 mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
Selim Cinek570981d2015-12-01 11:37:01 -08004156 if (mState == StatusBarState.KEYGUARD && nowExpanded) {
Selim Cinek31aada42015-12-18 17:51:15 -08004157 goToLockedShade(clickedEntry.row);
Selim Cinek570981d2015-12-01 11:37:01 -08004158 }
4159 }
4160
Adrian Roos5a46cd32014-04-03 16:51:58 +02004161 /**
Jorim Jaggi6539a832014-06-03 23:33:09 +02004162 * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}.
4163 */
4164 public void goToKeyguard() {
4165 if (mState == StatusBarState.SHADE_LOCKED) {
Selim Cinekd9acca52014-09-01 22:33:25 +02004166 mStackScroller.onGoToKeyguard();
Jorim Jaggi6539a832014-06-03 23:33:09 +02004167 setBarState(StatusBarState.KEYGUARD);
Jorim Jaggi98f85302014-08-07 17:45:04 +02004168 updateKeyguardState(false /* goingToFullShade */, true /* fromShadeLocked*/);
Jorim Jaggi6539a832014-06-03 23:33:09 +02004169 }
4170 }
4171
Jorim Jaggidbc3dce2014-08-01 01:16:36 +02004172 public long getKeyguardFadingAwayDelay() {
4173 return mKeyguardFadingAwayDelay;
4174 }
4175
4176 public long getKeyguardFadingAwayDuration() {
4177 return mKeyguardFadingAwayDuration;
4178 }
4179
Jorim Jaggi44cf9192014-06-17 19:16:00 -07004180 @Override
4181 public void setBouncerShowing(boolean bouncerShowing) {
4182 super.setBouncerShowing(bouncerShowing);
Adrian Roosd0b2f7d2015-04-29 13:36:12 -07004183 mStatusBarView.setBouncerShowing(bouncerShowing);
Benjamin Franzcde0a2a2015-04-23 17:19:48 +01004184 disable(mDisabledUnmodified1, mDisabledUnmodified2, true /* animate */);
Jorim Jaggi44cf9192014-06-17 19:16:00 -07004185 }
4186
Jorim Jaggi18f18ae2015-09-10 15:48:21 -07004187 public void onStartedGoingToSleep() {
4188 mStartedGoingToSleep = true;
4189 }
4190
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07004191 public void onFinishedGoingToSleep() {
Selim Cinek372d1bd2015-08-14 13:19:37 -07004192 mNotificationPanel.onAffordanceLaunchEnded();
4193 releaseGestureWakeLock();
4194 mLaunchCameraOnScreenTurningOn = false;
Jorim Jaggi18f18ae2015-09-10 15:48:21 -07004195 mStartedGoingToSleep = false;
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07004196 mDeviceInteractive = false;
4197 mWakeUpComingFromTouch = false;
4198 mWakeUpTouchLocation = null;
Jorim Jaggi75c95042014-05-16 19:09:59 +02004199 mStackScroller.setAnimationsEnabled(false);
Christoph Studere8e28652014-10-29 17:27:53 +01004200 updateVisibleToUser();
Jorim Jaggi18f18ae2015-09-10 15:48:21 -07004201 if (mLaunchCameraOnFinishedGoingToSleep) {
4202 mLaunchCameraOnFinishedGoingToSleep = false;
4203
4204 // This gets executed before we will show Keyguard, so post it in order that the state
4205 // is correct.
4206 mHandler.post(new Runnable() {
4207 @Override
4208 public void run() {
Jorim Jaggi40aa8812015-09-23 12:59:22 -07004209 onCameraLaunchGestureDetected(mLastCameraLaunchSource);
Jorim Jaggi18f18ae2015-09-10 15:48:21 -07004210 }
4211 });
4212 }
Jorim Jaggi75c95042014-05-16 19:09:59 +02004213 }
4214
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07004215 public void onStartedWakingUp() {
4216 mDeviceInteractive = true;
Jorim Jaggi75c95042014-05-16 19:09:59 +02004217 mStackScroller.setAnimationsEnabled(true);
Jorim Jaggid41083a2014-09-12 02:54:40 +02004218 mNotificationPanel.setTouchDisabled(false);
Christoph Studere8e28652014-10-29 17:27:53 +01004219 updateVisibleToUser();
Jorim Jaggi75c95042014-05-16 19:09:59 +02004220 }
John Spurlockd08f91f2014-05-23 11:00:34 -04004221
Jorim Jaggi93739112015-08-13 15:53:14 -07004222 public void onScreenTurningOn() {
Selim Cinek1b6f8192015-09-03 16:01:53 -07004223 mScreenTurningOn = true;
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004224 mFalsingManager.onScreenTurningOn();
Jorim Jaggi93739112015-08-13 15:53:14 -07004225 mNotificationPanel.onScreenTurningOn();
Selim Cinek372d1bd2015-08-14 13:19:37 -07004226 if (mLaunchCameraOnScreenTurningOn) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -07004227 mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
Selim Cinek372d1bd2015-08-14 13:19:37 -07004228 mLaunchCameraOnScreenTurningOn = false;
4229 }
Jorim Jaggi93739112015-08-13 15:53:14 -07004230 }
4231
Selim Cinek69ff8af2015-08-25 19:03:48 -07004232 private void vibrateForCameraGesture() {
Jorim Jaggi18f18ae2015-09-10 15:48:21 -07004233 // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
Jorim Jaggi75b25972015-10-21 14:51:10 +02004234 mVibrator.vibrate(new long[]{0, 750L}, -1 /* repeat */);
Selim Cinek69ff8af2015-08-25 19:03:48 -07004235 }
4236
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07004237 public void onScreenTurnedOn() {
Selim Cinek1b6f8192015-09-03 16:01:53 -07004238 mScreenTurningOn = false;
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07004239 mDozeScrimController.onScreenTurnedOn();
4240 }
4241
Jason Monk815e0572014-08-12 17:26:36 -04004242 /**
Jorim Jaggi75b25972015-10-21 14:51:10 +02004243 * Handles long press for back button. This exits screen pinning.
Jason Monk815e0572014-08-12 17:26:36 -04004244 */
Jorim Jaggi75b25972015-10-21 14:51:10 +02004245 private boolean handleLongPressBack() {
Jason Monk62515be2014-05-21 16:06:19 -04004246 try {
4247 IActivityManager activityManager = ActivityManagerNative.getDefault();
Jorim Jaggi75b25972015-10-21 14:51:10 +02004248 if (activityManager.isInLockTaskMode()) {
4249 activityManager.stopLockTaskModeOnCurrent();
4250
4251 // When exiting refresh disabled flags.
4252 mNavigationBarView.setDisabledFlags(mDisabled1, true);
4253 return true;
Jason Monk62515be2014-05-21 16:06:19 -04004254 }
4255 } catch (RemoteException e) {
Jason Monk815e0572014-08-12 17:26:36 -04004256 Log.d(TAG, "Unable to reach activity manager", e);
Jason Monk62515be2014-05-21 16:06:19 -04004257 }
Jorim Jaggi75b25972015-10-21 14:51:10 +02004258 return false;
Jason Monk62515be2014-05-21 16:06:19 -04004259 }
4260
Winson3e7e3aa2015-09-22 14:22:58 -07004261 public void updateRecentsVisibility(boolean visible) {
Winson Chung9214eff2014-06-12 13:59:25 -07004262 // Update the recents visibility flag
4263 if (visible) {
4264 mSystemUiVisibility |= View.RECENT_APPS_VISIBLE;
4265 } else {
4266 mSystemUiVisibility &= ~View.RECENT_APPS_VISIBLE;
4267 }
4268 notifyUiVisibilityChanged(mSystemUiVisibility);
4269 }
John Spurlockbf370992014-06-17 13:58:31 -04004270
Jason Monk5565cb42014-09-12 10:59:21 -04004271 @Override
4272 public void showScreenPinningRequest() {
Jason Monk18f99d92014-09-11 13:36:42 -04004273 if (mKeyguardMonitor.isShowing()) {
4274 // Don't allow apps to trigger this from keyguard.
4275 return;
4276 }
4277 // Show screen pinning request, since this comes from an app, show 'no thanks', button.
4278 showScreenPinningRequest(true);
4279 }
4280
4281 public void showScreenPinningRequest(boolean allowCancel) {
4282 mScreenPinningRequest.showPrompt(allowCancel);
Jason Monk5565cb42014-09-12 10:59:21 -04004283 }
4284
Christoph Studerc8db24b2014-07-25 17:50:30 +02004285 public boolean hasActiveNotifications() {
4286 return !mNotificationData.getActiveNotifications().isEmpty();
Jorim Jaggi48bc36a2014-07-25 23:16:04 +02004287 }
4288
Jorim Jaggi2a5e4522014-11-24 21:45:20 +01004289 public void wakeUpIfDozing(long time, MotionEvent event) {
Jorim Jaggi048af1f2014-11-11 22:51:10 +01004290 if (mDozing && mDozeScrimController.isPulsing()) {
John Spurlock8b12f222014-09-09 11:54:11 -04004291 PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
Dianne Hackborn280a64e2015-07-13 14:48:08 -07004292 pm.wakeUp(time, "com.android.systemui:NODOZE");
Jorim Jaggi50ff3af2015-08-12 18:35:42 -07004293 mWakeUpComingFromTouch = true;
4294 mWakeUpTouchLocation = new PointF(event.getX(), event.getY());
Jorim Jaggi2a5e4522014-11-24 21:45:20 +01004295 mNotificationPanel.setTouchDisabled(false);
Jorim Jaggi0d210f62015-07-10 14:24:44 -07004296 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
Blazej Magnowski0e2ffbd2015-09-10 14:37:17 -07004297 mFalsingManager.onScreenOnFromTouch();
John Spurlock8b12f222014-09-09 11:54:11 -04004298 }
4299 }
4300
Jorim Jaggi24bec7c2015-02-04 12:40:14 +01004301 @Override
4302 public void appTransitionPending() {
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01004303
4304 // Use own timings when Keyguard is going away, see keyguardGoingAway and
4305 // setKeyguardFadingAway
4306 if (!mKeyguardFadingAway) {
4307 mIconController.appTransitionPending();
4308 }
Jorim Jaggi24bec7c2015-02-04 12:40:14 +01004309 }
4310
4311 @Override
4312 public void appTransitionCancelled() {
4313 mIconController.appTransitionCancelled();
Jorim Jaggi2adba072016-03-03 13:43:39 +01004314 EventBus.getDefault().send(new AppTransitionFinishedEvent());
Jorim Jaggi24bec7c2015-02-04 12:40:14 +01004315 }
4316
4317 @Override
4318 public void appTransitionStarting(long startTime, long duration) {
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01004319
4320 // Use own timings when Keyguard is going away, see keyguardGoingAway and
Adrian Roos46df1ca2015-09-11 12:38:43 -07004321 // setKeyguardFadingAway.
4322 if (!mKeyguardGoingAway) {
Jorim Jaggi33ae80e2015-02-04 16:37:11 +01004323 mIconController.appTransitionStarting(startTime, duration);
4324 }
Kenny Guy3094d4a2015-04-01 19:14:10 +01004325 if (mIconPolicy != null) {
4326 mIconPolicy.appTransitionStarting(startTime, duration);
4327 }
Jorim Jaggi24bec7c2015-02-04 12:40:14 +01004328 }
4329
Selim Cinek372d1bd2015-08-14 13:19:37 -07004330 @Override
Jorim Jaggi2adba072016-03-03 13:43:39 +01004331 public void appTransitionFinished() {
4332 EventBus.getDefault().send(new AppTransitionFinishedEvent());
4333 }
4334
4335 @Override
Jorim Jaggi40aa8812015-09-23 12:59:22 -07004336 public void onCameraLaunchGestureDetected(int source) {
4337 mLastCameraLaunchSource = source;
Jorim Jaggi18f18ae2015-09-10 15:48:21 -07004338 if (mStartedGoingToSleep) {
4339 mLaunchCameraOnFinishedGoingToSleep = true;
4340 return;
4341 }
Zhentao Sun04f97402015-08-26 17:37:30 -07004342 if (!mNotificationPanel.canCameraGestureBeLaunched(
4343 mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) {
Selim Cinek372d1bd2015-08-14 13:19:37 -07004344 return;
4345 }
4346 if (!mDeviceInteractive) {
4347 PowerManager pm = mContext.getSystemService(PowerManager.class);
4348 pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE");
4349 mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
4350 }
Selim Cinek69ff8af2015-08-25 19:03:48 -07004351 vibrateForCameraGesture();
Selim Cinek372d1bd2015-08-14 13:19:37 -07004352 if (!mStatusBarKeyguardViewManager.isShowing()) {
4353 startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT,
4354 true /* dismissShade */);
4355 } else {
4356 if (!mDeviceInteractive) {
4357 // Avoid flickering of the scrim when we instant launch the camera and the bouncer
4358 // comes on.
4359 mScrimController.dontAnimateBouncerChangesUntilNextFrame();
4360 mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
4361 }
Selim Cinek1b6f8192015-09-03 16:01:53 -07004362 if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
Jorim Jaggi40aa8812015-09-23 12:59:22 -07004363 mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
Selim Cinek372d1bd2015-08-14 13:19:37 -07004364 } else {
4365 // We need to defer the camera launch until the screen comes on, since otherwise
4366 // we will dismiss us too early since we are waiting on an activity to be drawn and
4367 // incorrectly get notified because of the screen on event (which resumes and pauses
4368 // some activities)
4369 mLaunchCameraOnScreenTurningOn = true;
4370 }
4371 }
4372 }
4373
Jaewan Kimc552b042016-01-18 16:08:45 +09004374 @Override
4375 public void requestTvPictureInPicture() {
4376 // no-op.
4377 }
4378
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07004379 public void notifyFpAuthModeChanged() {
4380 updateDozing();
4381 }
4382
Jorim Jaggi83969702015-06-05 14:59:24 -07004383 private void updateDozing() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07004384 // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
4385 mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD
4386 || mFingerprintUnlockController.getMode()
4387 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
Jorim Jaggi83969702015-06-05 14:59:24 -07004388 updateDozingState();
4389 }
4390
John Spurlockbf370992014-06-17 13:58:31 -04004391 private final class ShadeUpdates {
4392 private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
4393 private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
4394
4395 public void check() {
4396 mNewVisibleNotifications.clear();
Christoph Studerc8db24b2014-07-25 17:50:30 +02004397 ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
4398 for (int i = 0; i < activeNotifications.size(); i++) {
4399 final Entry entry = activeNotifications.get(i);
John Spurlockbf370992014-06-17 13:58:31 -04004400 final boolean visible = entry.row != null
4401 && entry.row.getVisibility() == View.VISIBLE;
4402 if (visible) {
4403 mNewVisibleNotifications.add(entry.key + entry.notification.getPostTime());
4404 }
4405 }
4406 final boolean updates = !mVisibleNotifications.containsAll(mNewVisibleNotifications);
4407 mVisibleNotifications.clear();
Dianne Hackborn497175b2014-07-01 12:56:08 -07004408 mVisibleNotifications.addAll(mNewVisibleNotifications);
John Spurlockbf370992014-06-17 13:58:31 -04004409
4410 // We have new notifications
4411 if (updates && mDozeServiceHost != null) {
4412 mDozeServiceHost.fireNewNotifications();
4413 }
4414 }
4415 }
4416
Jorim Jaggi007f0e82015-08-14 13:56:01 -07004417 private final class DozeServiceHost extends KeyguardUpdateMonitorCallback implements DozeHost {
John Spurlockbf370992014-06-17 13:58:31 -04004418 // Amount of time to allow to update the time shown on the screen before releasing
4419 // the wakelock. This timeout is design to compensate for the fact that we don't
4420 // currently have a way to know when time display contents have actually been
4421 // refreshed once we've finished rendering a new frame.
4422 private static final long PROCESSING_TIME = 500;
4423
4424 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
4425 private final H mHandler = new H();
4426
Christoph Studer1f32c652014-11-26 15:32:20 +01004427 // Keeps the last reported state by fireNotificationLight.
4428 private boolean mNotificationLightOn;
4429
John Spurlockc6eed842014-08-25 12:19:41 -04004430 @Override
4431 public String toString() {
Jeff Brown4d69e222014-09-18 15:27:50 -07004432 return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
John Spurlock8b12f222014-09-09 11:54:11 -04004433 }
4434
John Spurlockd96179e2014-08-21 16:43:45 -04004435 public void firePowerSaveChanged(boolean active) {
4436 for (Callback callback : mCallbacks) {
4437 callback.onPowerSaveChanged(active);
4438 }
4439 }
4440
John Spurlockcad57682014-07-26 17:09:56 -04004441 public void fireBuzzBeepBlinked() {
4442 for (Callback callback : mCallbacks) {
4443 callback.onBuzzBeepBlinked();
4444 }
4445 }
4446
John Spurlockcb566aa2014-08-03 22:58:28 -04004447 public void fireNotificationLight(boolean on) {
Christoph Studer1f32c652014-11-26 15:32:20 +01004448 mNotificationLightOn = on;
John Spurlockcb566aa2014-08-03 22:58:28 -04004449 for (Callback callback : mCallbacks) {
4450 callback.onNotificationLight(on);
4451 }
4452 }
4453
John Spurlockbf370992014-06-17 13:58:31 -04004454 public void fireNewNotifications() {
4455 for (Callback callback : mCallbacks) {
4456 callback.onNewNotifications();
4457 }
4458 }
4459
4460 @Override
Jeff Brown4d69e222014-09-18 15:27:50 -07004461 public void addCallback(@NonNull Callback callback) {
John Spurlockbf370992014-06-17 13:58:31 -04004462 mCallbacks.add(callback);
4463 }
4464
4465 @Override
Jeff Brown4d69e222014-09-18 15:27:50 -07004466 public void removeCallback(@NonNull Callback callback) {
John Spurlockbf370992014-06-17 13:58:31 -04004467 mCallbacks.remove(callback);
4468 }
4469
4470 @Override
Jeff Brown4d69e222014-09-18 15:27:50 -07004471 public void startDozing(@NonNull Runnable ready) {
4472 mHandler.obtainMessage(H.MSG_START_DOZING, ready).sendToTarget();
John Spurlockbf370992014-06-17 13:58:31 -04004473 }
4474
4475 @Override
John Spurlockeab28e62014-11-29 11:33:49 -05004476 public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) {
4477 mHandler.obtainMessage(H.MSG_PULSE_WHILE_DOZING, reason, 0, callback).sendToTarget();
John Spurlockbf370992014-06-17 13:58:31 -04004478 }
4479
4480 @Override
Jeff Brown4d69e222014-09-18 15:27:50 -07004481 public void stopDozing() {
4482 mHandler.obtainMessage(H.MSG_STOP_DOZING).sendToTarget();
John Spurlockbf370992014-06-17 13:58:31 -04004483 }
4484
John Spurlockd96179e2014-08-21 16:43:45 -04004485 @Override
4486 public boolean isPowerSaveActive() {
4487 return mBatteryController != null && mBatteryController.isPowerSave();
4488 }
4489
Christoph Studer1f32c652014-11-26 15:32:20 +01004490 @Override
Jorim Jaggi007f0e82015-08-14 13:56:01 -07004491 public boolean isPulsingBlocked() {
Jorim Jaggi83eb6bb2015-08-17 17:38:58 -07004492 return mFingerprintUnlockController.getMode()
4493 == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
Jorim Jaggi007f0e82015-08-14 13:56:01 -07004494 }
4495
4496 @Override
Christoph Studer1f32c652014-11-26 15:32:20 +01004497 public boolean isNotificationLightOn() {
4498 return mNotificationLightOn;
4499 }
4500
Jeff Brown4d69e222014-09-18 15:27:50 -07004501 private void handleStartDozing(@NonNull Runnable ready) {
Jorim Jaggi83969702015-06-05 14:59:24 -07004502 if (!mDozingRequested) {
4503 mDozingRequested = true;
John Spurlock813552c2014-09-19 08:30:21 -04004504 DozeLog.traceDozing(mContext, mDozing);
Jorim Jaggi83969702015-06-05 14:59:24 -07004505 updateDozing();
John Spurlockbf370992014-06-17 13:58:31 -04004506 }
Jeff Brown4d69e222014-09-18 15:27:50 -07004507 ready.run();
John Spurlockbf370992014-06-17 13:58:31 -04004508 }
4509
John Spurlockeab28e62014-11-29 11:33:49 -05004510 private void handlePulseWhileDozing(@NonNull PulseCallback callback, int reason) {
Selim Cinekcd5b22f2016-03-08 16:15:41 -08004511 mDozeScrimController.pulse(new PulseCallback() {
4512
4513 @Override
4514 public void onPulseStarted() {
4515 callback.onPulseStarted();
4516 mStackScroller.setPulsing(true);
4517 }
4518
4519 @Override
4520 public void onPulseFinished() {
4521 callback.onPulseFinished();
4522 mStackScroller.setPulsing(false);
4523 }
4524 }, reason);
John Spurlockbf370992014-06-17 13:58:31 -04004525 }
4526
Jeff Brown4d69e222014-09-18 15:27:50 -07004527 private void handleStopDozing() {
Jorim Jaggi83969702015-06-05 14:59:24 -07004528 if (mDozingRequested) {
4529 mDozingRequested = false;
John Spurlock813552c2014-09-19 08:30:21 -04004530 DozeLog.traceDozing(mContext, mDozing);
Jorim Jaggi83969702015-06-05 14:59:24 -07004531 updateDozing();
John Spurlockbf370992014-06-17 13:58:31 -04004532 }
4533 }
4534
4535 private final class H extends Handler {
Jeff Brown4d69e222014-09-18 15:27:50 -07004536 private static final int MSG_START_DOZING = 1;
4537 private static final int MSG_PULSE_WHILE_DOZING = 2;
4538 private static final int MSG_STOP_DOZING = 3;
John Spurlockbf370992014-06-17 13:58:31 -04004539
4540 @Override
4541 public void handleMessage(Message msg) {
Jeff Brown4d69e222014-09-18 15:27:50 -07004542 switch (msg.what) {
4543 case MSG_START_DOZING:
4544 handleStartDozing((Runnable) msg.obj);
4545 break;
4546 case MSG_PULSE_WHILE_DOZING:
John Spurlockeab28e62014-11-29 11:33:49 -05004547 handlePulseWhileDozing((PulseCallback) msg.obj, msg.arg1);
Jeff Brown4d69e222014-09-18 15:27:50 -07004548 break;
4549 case MSG_STOP_DOZING:
4550 handleStopDozing();
4551 break;
John Spurlockbf370992014-06-17 13:58:31 -04004552 }
4553 }
4554 }
4555 }
Romain Guy648342f2012-05-25 10:44:45 -07004556}