/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.phone;

import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;

import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_LEFT;
import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_INVALID;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager
        .NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
import static com.android.systemui.statusbar.NotificationMediaManager.DEBUG_MEDIA;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AlarmManager;
import android.app.IWallpaperManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.TaskStackBuilder;
import android.app.UiModeManager;
import android.app.WallpaperColors;
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioAttributes;
import android.media.MediaMetadata;
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.ThreadedRenderer;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.widget.DateTimeView;
import android.widget.ImageView;
import android.widget.TextView;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.MessagingGroup;
import com.android.internal.widget.MessagingMessage;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.AutoReinflateContainer;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.car.CarQSFragment;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
import com.android.systemui.recents.events.activity.UndockingTaskEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.WindowManagerProxy;
import com.android.systemui.statusbar.ActivatableNotificationView;
import com.android.systemui.statusbar.AppOpsListener;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.FooterView;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.NotificationEntryManager;
import com.android.systemui.statusbar.NotificationGutsManager;
import com.android.systemui.statusbar.NotificationInfo;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLogger;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.AboveShelfObserver;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.PreviewInflater;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.volume.VolumeComponent;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class StatusBar extends SystemUI implements DemoMode,
        DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
        OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
        ColorExtractor.OnColorsChangedListener, ConfigurationListener, NotificationPresenter {
    public static final boolean MULTIUSER_DEBUG = false;

    public static final boolean ENABLE_CHILD_NOTIFICATIONS
            = SystemProperties.getBoolean("debug.child_notifs", true);

    protected static final int MSG_HIDE_RECENT_APPS = 1020;
    protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
    protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
    protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
    protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;

    // Should match the values in PhoneWindowManager
    public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
    public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";

    private static final String BANNER_ACTION_CANCEL =
            "com.android.systemui.statusbar.banner_action_cancel";
    private static final String BANNER_ACTION_SETUP =
            "com.android.systemui.statusbar.banner_action_setup";
    public static final String TAG = "StatusBar";
    public static final boolean DEBUG = false;
    public static final boolean SPEW = false;
    public static final boolean DUMPTRUCK = true; // extra dumpsys info
    public static final boolean DEBUG_GESTURES = false;
    public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
    public static final boolean DEBUG_CAMERA_LIFT = false;

    public static final boolean DEBUG_WINDOW_STATE = false;

    // additional instrumentation for testing purposes; intended to be left on during development
    public static final boolean CHATTY = DEBUG;

    public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;

    public static final String ACTION_FAKE_ARTWORK = "fake_artwork";

    private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
    private static final int MSG_CLOSE_PANELS = 1001;
    private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
    private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003;
    // 1020-1040 reserved for BaseStatusBar

    // Time after we abort the launch transition.
    private static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000;

    protected static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;

    private static final int STATUS_OR_NAV_TRANSIENT =
            View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
    private static final long AUTOHIDE_TIMEOUT_MS = 2250;

    
The delay to reset the hint text when the hint animation is finished running.
/** * The delay to reset the hint text when the hint animation is finished running. */
private static final int HINT_RESET_DELAY_MS = 1200; private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) .build(); public static final int FADE_KEYGUARD_START_DELAY = 100; public static final int FADE_KEYGUARD_DURATION = 300; public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
If true, the system is in the half-boot-to-decryption-screen state. Prudently disable QS and notifications.
/** If true, the system is in the half-boot-to-decryption-screen state. * Prudently disable QS and notifications. */
private static final boolean ONLY_CORE_APPS;
If true, the lockscreen will show a distinct wallpaper
/** If true, the lockscreen will show a distinct wallpaper */
private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
Whether to force dark theme if Configuration.UI_MODE_NIGHT_YES.
/** Whether to force dark theme if Configuration.UI_MODE_NIGHT_YES. */
private static final boolean DARK_THEME_IN_NIGHT_MODE = true;
Whether to switch the device into night mode in battery saver.
/** Whether to switch the device into night mode in battery saver. */
private static final boolean NIGHT_MODE_IN_BATTERY_SAVER = true;
Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode won't draw anything and uninitialized memory will show through if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in libhwui.
/** * Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode * won't draw anything and uninitialized memory will show through * if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in * libhwui. */
private static final float SRC_MIN_ALPHA = 0.002f; static { boolean onlyCoreApps; try { IPackageManager packageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package")); onlyCoreApps = packageManager.isOnlyCoreApps(); } catch (RemoteException e) { onlyCoreApps = false; } ONLY_CORE_APPS = onlyCoreApps; }
The StatusBarState of the status bar.
/** * The {@link StatusBarState} of the status bar. */
protected int mState; protected boolean mBouncerShowing; private PhoneStatusBarPolicy mIconPolicy; private StatusBarSignalPolicy mSignalPolicy; private VolumeComponent mVolumeComponent; private BrightnessMirrorController mBrightnessMirrorController; private boolean mBrightnessMirrorVisible; protected FingerprintUnlockController mFingerprintUnlockController; private LightBarController mLightBarController; protected LockscreenWallpaper mLockscreenWallpaper; private int mNaturalBarHeight = -1; private final Point mCurrentDisplaySize = new Point(); protected StatusBarWindowView mStatusBarWindow; protected PhoneStatusBarView mStatusBarView; private int mStatusBarWindowState = WINDOW_STATE_SHOWING; protected StatusBarWindowManager mStatusBarWindowManager; protected UnlockMethodCache mUnlockMethodCache; private DozeServiceHost mDozeServiceHost = new DozeServiceHost(); private boolean mWakeUpComingFromTouch; private PointF mWakeUpTouchLocation; private final Object mQueueLock = new Object(); protected StatusBarIconController mIconController; // expanded notifications protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window private TextView mNotificationPanelDebugText; // settings private QSPanel mQSPanel; // top bar private KeyguardStatusBarView mKeyguardStatusBar; private boolean mLeaveOpenOnKeyguardHide; KeyguardIndicationController mKeyguardIndicationController; // Keyguard is actually fading away now. protected boolean mKeyguardFadingAway; protected long mKeyguardFadingAwayDelay; protected long mKeyguardFadingAwayDuration; // RemoteInputView to be activated after unlock private View mPendingRemoteInputView; private View mPendingWorkRemoteInputView; private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler = Dependency.get(RemoteInputQuickSettingsDisabler.class); private View mReportRejectedTouch; private int mMaxAllowedKeyguardNotifications; private boolean mExpandedVisible; private final int[] mAbsPos = new int[2]; private final ArrayList<Runnable> mPostCollapseRunnables = new ArrayList<>(); private NotificationGutsManager mGutsManager; protected NotificationLogger mNotificationLogger; protected NotificationEntryManager mEntryManager; protected NotificationViewHierarchyManager mViewHierarchyManager; protected AppOpsListener mAppOpsListener; protected KeyguardViewMediator mKeyguardViewMediator; private ZenModeController mZenController;
Helper that is responsible for showing the right toast when a disallowed activity operation occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in fully locked mode we only show that unlocking is blocked.
/** * Helper that is responsible for showing the right toast when a disallowed activity operation * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in * fully locked mode we only show that unlocking is blocked. */
private ScreenPinningNotify mScreenPinningNotify; // for disabling the status bar private int mDisabled1 = 0; private int mDisabled2 = 0; // tracking calls to View.setSystemUiVisibility() private int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; private final Rect mLastFullscreenStackBounds = new Rect(); private final Rect mLastDockedStackBounds = new Rect(); private final Rect mTmpRect = new Rect(); // last value sent to window manager private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE; private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); // XXX: gesture research private final GestureRecorder mGestureRec = DEBUG_GESTURES ? new GestureRecorder("/sdcard/statusbar_gestures.dat") : null; private ScreenPinningRequest mScreenPinningRequest; private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); // ensure quick settings is disabled until the current user makes it through the setup wizard @VisibleForTesting protected boolean mUserSetup = false; private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() { @Override public void onUserSetupChanged() { final boolean userSetup = mDeviceProvisionedController.isUserSetup( mDeviceProvisionedController.getCurrentUser()); if (MULTIUSER_DEBUG) { Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s", userSetup, mUserSetup)); } if (userSetup != mUserSetup) { mUserSetup = userSetup; if (!mUserSetup && mStatusBarView != null) animateCollapseQuickSettings(); if (mNotificationPanel != null) { mNotificationPanel.setUserSetupComplete(mUserSetup); } updateQsExpansionEnabled(); } } }; protected final H mHandler = createHandler(); private int mInteractingWindows; private boolean mAutohideSuspended; private int mStatusBarMode; private int mMaxKeyguardNotifications; private ViewMediatorCallback mKeyguardViewMediatorCallback; protected ScrimController mScrimController; protected DozeScrimController mDozeScrimController; private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class); private final Runnable mAutohide = () -> { int requested = mSystemUiVisibility & ~STATUS_OR_NAV_TRANSIENT; if (mSystemUiVisibility != requested) { notifyUiVisibilityChanged(requested); } }; protected boolean mDozing; private boolean mDozingRequested; protected boolean mScrimSrcModeEnabled; protected BackDropView mBackdrop; protected ImageView mBackdropFront, mBackdropBack; protected final PorterDuffXfermode mSrcXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); protected final PorterDuffXfermode mSrcOverXferMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER); private NotificationMediaManager mMediaManager; protected NotificationLockscreenUserManager mLockscreenUserManager; protected NotificationRemoteInputManager mRemoteInputManager; private BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { WallpaperManager wallpaperManager = context.getSystemService(WallpaperManager.class); if (wallpaperManager == null) { Log.w(TAG, "WallpaperManager not available"); return; } WallpaperInfo info = wallpaperManager.getWallpaperInfo(); final boolean supportsAmbientMode = info != null && info.getSupportsAmbientMode(); mStatusBarWindowManager.setWallpaperSupportsAmbientMode(supportsAmbientMode); mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode); } }; private Runnable mLaunchTransitionEndRunnable; protected boolean mLaunchTransitionFadingAway; private ExpandableNotificationRow mDraggedDownRow; private boolean mLaunchCameraOnScreenTurningOn; private boolean mLaunchCameraOnFinishedGoingToSleep; private int mLastCameraLaunchSource; private PowerManager.WakeLock mGestureWakeLock; private Vibrator mVibrator; private long[] mCameraLaunchGestureVibePattern; private final int[] mTmpInt2 = new int[2]; // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. private int mLastLoggedStateFingerprint; private boolean mTopHidesStatusBar; private boolean mStatusBarWindowHidden; private boolean mHideIconsForBouncer; private boolean mIsOccluded; private boolean mWereIconsJustHidden; private boolean mBouncerWasShowingWhenHidden; // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over, // this animation is tied to the scrim for historic reasons. // TODO: notify when keyguard has faded away instead of the scrim. private final ScrimController.Callback mUnlockScrimCallback = new ScrimController .Callback() { @Override public void onFinished() { if (mStatusBarKeyguardViewManager == null) { Log.w(TAG, "Tried to notify keyguard visibility when " + "mStatusBarKeyguardViewManager was null"); return; } if (mKeyguardFadingAway) { mStatusBarKeyguardViewManager.onKeyguardFadedAway(); } } @Override public void onCancelled() { onFinished(); } }; private KeyguardUserSwitcher mKeyguardUserSwitcher; protected UserSwitcherController mUserSwitcherController; private NetworkController mNetworkController; private KeyguardMonitorImpl mKeyguardMonitor = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class); private BatteryController mBatteryController; protected boolean mPanelExpanded; private IOverlayManager mOverlayManager; private boolean mKeyguardRequested; private boolean mIsKeyguard; private LogMaker mStatusBarStateLog; private final LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); protected NotificationIconAreaController mNotificationIconAreaController; private boolean mReinflateNotificationsOnUserSwitched; protected boolean mClearAllEnabled; @Nullable private View mAmbientIndicationContainer; private SysuiColorExtractor mColorExtractor; private ScreenLifecycle mScreenLifecycle; @VisibleForTesting WakefulnessLifecycle mWakefulnessLifecycle; private final View.OnClickListener mGoToLockedShadeListener = v -> { if (mState == StatusBarState.KEYGUARD) { wakeUpIfDozing(SystemClock.uptimeMillis(), v); goToLockedShade(null); } }; private boolean mNoAnimationOnNextBarModeChange; protected FalsingManager mFalsingManager; private final KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override public void onDreamingStateChanged(boolean dreaming) { if (dreaming) { maybeEscalateHeadsUp(); } } @Override public void onStrongAuthStateChanged(int userId) { super.onStrongAuthStateChanged(userId); mEntryManager.updateNotifications(); } }; private NavigationBarFragment mNavigationBar; private View mNavigationBarView; protected ActivityLaunchAnimator mActivityLaunchAnimator; private HeadsUpAppearanceController mHeadsUpAppearanceController; private boolean mVibrateOnOpening; private VibratorHelper mVibratorHelper; @Override public void start() { mGroupManager = Dependency.get(NotificationGroupManager.class); mVisualStabilityManager = Dependency.get(VisualStabilityManager.class); mNotificationLogger = Dependency.get(NotificationLogger.class); mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class); mNotificationListener = Dependency.get(NotificationListener.class); mGroupManager = Dependency.get(NotificationGroupManager.class); mNetworkController = Dependency.get(NetworkController.class); mUserSwitcherController = Dependency.get(UserSwitcherController.class); mScreenLifecycle = Dependency.get(ScreenLifecycle.class); mScreenLifecycle.addObserver(mScreenObserver); mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class); mWakefulnessLifecycle.addObserver(mWakefulnessObserver); mBatteryController = Dependency.get(BatteryController.class); mAssistManager = Dependency.get(AssistManager.class); mOverlayManager = IOverlayManager.Stub.asInterface( ServiceManager.getService(Context.OVERLAY_SERVICE)); mLockscreenUserManager = Dependency.get(NotificationLockscreenUserManager.class); mGutsManager = Dependency.get(NotificationGutsManager.class); mMediaManager = Dependency.get(NotificationMediaManager.class); mEntryManager = Dependency.get(NotificationEntryManager.class); mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class); mAppOpsListener = Dependency.get(AppOpsListener.class); mAppOpsListener.setUpWithPresenter(this, mEntryManager); mZenController = Dependency.get(ZenModeController.class); mKeyguardViewMediator = getComponent(KeyguardViewMediator.class); mColorExtractor = Dependency.get(SysuiColorExtractor.class); mColorExtractor.addOnColorsChangedListener(this); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mDisplay = mWindowManager.getDefaultDisplay(); updateDisplaySize(); Resources res = mContext.getResources(); mVibrateOnOpening = mContext.getResources().getBoolean( R.bool.config_vibrateOnIconAnimation); mVibratorHelper = Dependency.get(VibratorHelper.class); mScrimSrcModeEnabled = res.getBoolean(R.bool.config_status_bar_scrim_behind_use_src); mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll); DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER)); putComponent(StatusBar.class, this); // start old BaseStatusBar.start(). mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService( Context.DEVICE_POLICY_SERVICE); mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); mRecents = getComponent(Recents.class); mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mLockPatternUtils = new LockPatternUtils(mContext); mMediaManager.setUpWithPresenter(this, mEntryManager); // Connect in to the status bar manager service mCommandQueue = getComponent(CommandQueue.class); mCommandQueue.addCallbacks(this); int[] switches = new int[9]; ArrayList<IBinder> binders = new ArrayList<>(); ArrayList<String> iconSlots = new ArrayList<>(); ArrayList<StatusBarIcon> icons = new ArrayList<>(); Rect fullscreenStackBounds = new Rect(); Rect dockedStackBounds = new Rect(); try { mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders, fullscreenStackBounds, dockedStackBounds); } catch (RemoteException ex) { // If the system process isn't there we're doomed anyway. } createAndAddWindows(); // Make sure we always have the most current wallpaper info. IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); mContext.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter); mWallpaperChangedReceiver.onReceive(mContext, null); mLockscreenUserManager.setUpWithPresenter(this, mEntryManager); mCommandQueue.disable(switches[0], switches[6], false /* animate */); setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff, fullscreenStackBounds, dockedStackBounds); topAppWindowChanged(switches[2] != 0); // StatusBarManagerService has a back up of IME token and it's restored here. setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0); // Set up the initial icon state int N = iconSlots.size(); for (int i=0; i < N; i++) { mCommandQueue.setIcon(iconSlots.get(i), icons.get(i)); } // Set up the initial notification state. mNotificationListener.setUpWithPresenter(this, mEntryManager); if (DEBUG) { Log.d(TAG, String.format( "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x", icons.size(), switches[0], switches[1], switches[2], switches[3] )); } setHeadsUpUser(mLockscreenUserManager.getCurrentUserId()); IntentFilter internalFilter = new IntentFilter(); internalFilter.addAction(BANNER_ACTION_CANCEL); internalFilter.addAction(BANNER_ACTION_SETUP); mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF, null); IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService( Context.VR_SERVICE)); if (vrManager != null) { try { vrManager.registerListener(mVrStateCallbacks); } catch (RemoteException e) { Slog.e(TAG, "Failed to register VR mode state listener: " + e); } } IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface( ServiceManager.getService(Context.WALLPAPER_SERVICE)); try { wallpaperManager.setInAmbientMode(false /* ambientMode */, false /* animated */); } catch (RemoteException e) { // Just pass, nothing critical. } // end old BaseStatusBar.start(). // Lastly, call to the icon policy to install/update all the icons. mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController); mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController); mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); mUnlockMethodCache.addListener(this); startKeyguard(); KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback); putComponent(DozeHost.class, mDozeServiceHost); mScreenPinningRequest = new ScreenPinningRequest(mContext); mFalsingManager = FalsingManager.getInstance(mContext); Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this); Dependency.get(ConfigurationController.class).addCallback(this); } // ================================================================================ // Constructing the view // ================================================================================ protected void makeStatusBarView() { final Context context = mContext; updateDisplaySize(); // populates mDisplayMetrics updateResources(); updateTheme(); inflateStatusBarWindow(context); mStatusBarWindow.setService(this); mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener()); // TODO: Deal with the ugliness that comes from having some of the statusbar broken out // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot. mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel); mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller); mZenController.addCallback(this); mActivityLaunchAnimator = new ActivityLaunchAnimator(mStatusBarWindow, this, mNotificationPanel, mStackScroller); mGutsManager.setUpWithPresenter(this, mEntryManager, mStackScroller, mCheckSaveListener, key -> { try { mBarService.onNotificationSettingsViewed(key); } catch (RemoteException e) { // if we're here we're dead } }); mNotificationLogger.setUpWithEntryManager(mEntryManager, mStackScroller); mNotificationPanel.setStatusBar(this); mNotificationPanel.setGroupManager(mGroupManager); mAboveShelfObserver = new AboveShelfObserver(mStackScroller); mAboveShelfObserver.setListener(mStatusBarWindow.findViewById( R.id.notification_container_parent)); mKeyguardStatusBar = mStatusBarWindow.findViewById(R.id.keyguard_header); mNotificationIconAreaController = SystemUIFactory.getInstance() .createNotificationIconAreaController(context, this); inflateShelf(); mNotificationIconAreaController.setupShelf(mNotificationShelf); mStackScroller.setIconAreaController(mNotificationIconAreaController); Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController); FragmentHostManager.get(mStatusBarWindow) .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> { CollapsedStatusBarFragment statusBarFragment = (CollapsedStatusBarFragment) fragment; statusBarFragment.initNotificationIconArea(mNotificationIconAreaController); PhoneStatusBarView oldStatusBarView = mStatusBarView; mStatusBarView = (PhoneStatusBarView) fragment.getView(); mStatusBarView.setBar(this); mStatusBarView.setPanel(mNotificationPanel); mStatusBarView.setScrimController(mScrimController); // CollapsedStatusBarFragment re-inflated PhoneStatusBarView and both of // mStatusBarView.mExpanded and mStatusBarView.mBouncerShowing are false. // PhoneStatusBarView's new instance will set to be gone in // PanelBar.updateVisibility after calling mStatusBarView.setBouncerShowing // that will trigger PanelBar.updateVisibility. If there is a heads up showing, // it needs to notify PhoneStatusBarView's new instance to update the correct // status by calling mNotificationPanel.notifyBarPanelExpansionChanged(). if (mHeadsUpManager.hasPinnedHeadsUp()) { mNotificationPanel.notifyBarPanelExpansionChanged(); } mStatusBarView.setBouncerShowing(mBouncerShowing); if (oldStatusBarView != null) { float fraction = oldStatusBarView.getExpansionFraction(); boolean expanded = oldStatusBarView.isExpanded(); mStatusBarView.panelExpansionChanged(fraction, expanded); } HeadsUpAppearanceController oldController = mHeadsUpAppearanceController; if (mHeadsUpAppearanceController != null) { // This view is being recreated, let's destroy the old one mHeadsUpAppearanceController.destroy(); } mHeadsUpAppearanceController = new HeadsUpAppearanceController( mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow); mStatusBarWindow.setStatusBarView(mStatusBarView); mHeadsUpAppearanceController.readFrom(oldController); setAreThereNotifications(); checkBarModes(); }).getFragmentManager() .beginTransaction() .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG) .commit(); mIconController = Dependency.get(StatusBarIconController.class); mHeadsUpManager = new HeadsUpManagerPhone(context, mStatusBarWindow, mGroupManager, this, mVisualStabilityManager); Dependency.get(ConfigurationController.class).addCallback(mHeadsUpManager); mHeadsUpManager.addListener(this); mHeadsUpManager.addListener(mNotificationPanel); mHeadsUpManager.addListener(mGroupManager); mHeadsUpManager.addListener(mVisualStabilityManager); mNotificationPanel.setHeadsUpManager(mHeadsUpManager); mGroupManager.setHeadsUpManager(mHeadsUpManager); putComponent(HeadsUpManager.class, mHeadsUpManager); mEntryManager.setUpWithPresenter(this, mStackScroller, this, mHeadsUpManager); mViewHierarchyManager.setUpWithPresenter(this, mEntryManager, mStackScroller); if (MULTIUSER_DEBUG) { mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info); mNotificationPanelDebugText.setVisibility(View.VISIBLE); } try { boolean showNav = mWindowManagerService.hasNavigationBar(); if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav); if (showNav) { createNavigationBar(); } } catch (RemoteException ex) { // no window manager? good luck with that } mScreenPinningNotify = new ScreenPinningNotify(mContext); mStackScroller.setLongPressListener(mEntryManager.getNotificationLongClicker()); mStackScroller.setStatusBar(this); mStackScroller.setGroupManager(mGroupManager); mStackScroller.setHeadsUpManager(mHeadsUpManager); mGroupManager.setOnGroupChangeListener(mStackScroller); mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller); inflateEmptyShadeView(); inflateFooterView(); mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop); mBackdropFront = mBackdrop.findViewById(R.id.backdrop_front); mBackdropBack = mBackdrop.findViewById(R.id.backdrop_back); if (ENABLE_LOCKSCREEN_WALLPAPER) { mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler); } mKeyguardIndicationController = SystemUIFactory.getInstance().createKeyguardIndicationController(mContext, mStatusBarWindow.findViewById(R.id.keyguard_indication_area), mNotificationPanel.getLockIcon()); mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController); mAmbientIndicationContainer = mStatusBarWindow.findViewById( R.id.ambient_indication_container); // set the initial view visibility setAreThereNotifications(); // TODO: Find better place for this callback. mBatteryController.addCallback(new BatteryStateChangeCallback() { @Override public void onPowerSaveChanged(boolean isPowerSave) { mHandler.post(mCheckBarModes); if (mDozeServiceHost != null) { mDozeServiceHost.firePowerSaveChanged(isPowerSave); } if (NIGHT_MODE_IN_BATTERY_SAVER) { mContext.getSystemService(UiModeManager.class).setNightMode( isPowerSave ? UiModeManager.MODE_NIGHT_YES : UiModeManager.MODE_NIGHT_NO); } } @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { // noop } }); mLightBarController = Dependency.get(LightBarController.class); if (mNavigationBar != null) { mNavigationBar.setLightBarController(mLightBarController); } ScrimView scrimBehind = mStatusBarWindow.findViewById(R.id.scrim_behind); ScrimView scrimInFront = mStatusBarWindow.findViewById(R.id.scrim_in_front); mScrimController = SystemUIFactory.getInstance().createScrimController( scrimBehind, scrimInFront, mLockscreenWallpaper, (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color), scrimsVisible -> { if (mStatusBarWindowManager != null) { mStatusBarWindowManager.setScrimsVisibility(scrimsVisible); } }, DozeParameters.getInstance(mContext), mContext.getSystemService(AlarmManager.class)); if (mScrimSrcModeEnabled) { Runnable runnable = () -> { boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE; mScrimController.setDrawBehindAsSrc(asSrc); mStackScroller.setDrawBackgroundAsSrc(asSrc); }; mBackdrop.setOnVisibilityChangedRunnable(runnable); runnable.run(); } mStackScroller.setScrimController(mScrimController); mDozeScrimController = new DozeScrimController(mScrimController, context, DozeParameters.getInstance(context)); // Other icons mVolumeComponent = getComponent(VolumeComponent.class); mNotificationPanel.setUserSetupComplete(mUserSetup); if (UserManager.get(mContext).isUserSwitcherEnabled()) { createUserSwitcher(); } // Set up the quick settings tile panel View container = mStatusBarWindow.findViewById(R.id.qs_frame); if (container != null) { FragmentHostManager fragmentHostManager = FragmentHostManager.get(container); ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame, Dependency.get(ExtensionController.class) .newExtension(QS.class) .withPlugin(QS.class) .withFeature(PackageManager.FEATURE_AUTOMOTIVE, CarQSFragment::new) .withDefault(QSFragment::new) .build()); final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this, mIconController); mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow, (visible) -> { mBrightnessMirrorVisible = visible; updateScrimController(); }); fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> { QS qs = (QS) f; if (qs instanceof QSFragment) { ((QSFragment) qs).setHost(qsh); mQSPanel = ((QSFragment) qs).getQsPanel(); mQSPanel.setBrightnessMirror(mBrightnessMirrorController); mKeyguardStatusBar.setQSPanel(mQSPanel); } }); } mReportRejectedTouch = mStatusBarWindow.findViewById(R.id.report_rejected_touch); if (mReportRejectedTouch != null) { updateReportRejectedTouchVisibility(); mReportRejectedTouch.setOnClickListener(v -> { Uri session = mFalsingManager.reportRejectedTouch(); if (session == null) { return; } StringWriter message = new StringWriter(); message.write("Build info: "); message.write(SystemProperties.get("ro.build.description")); message.write("\nSerial number: "); message.write(SystemProperties.get("ro.serialno")); message.write("\n"); PrintWriter falsingPw = new PrintWriter(message); FalsingLog.dump(falsingPw); falsingPw.flush(); startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND) .setType("*/*") .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report") .putExtra(Intent.EXTRA_STREAM, session) .putExtra(Intent.EXTRA_TEXT, message.toString()), "Share rejected touch report") .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), true /* onlyProvisioned */, true /* dismissShade */); }); } PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); if (!pm.isScreenOn()) { mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF)); } mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "GestureWakeLock"); mVibrator = mContext.getSystemService(Vibrator.class); int[] pattern = mContext.getResources().getIntArray( R.array.config_cameraLaunchGestureVibePattern); mCameraLaunchGestureVibePattern = new long[pattern.length]; for (int i = 0; i < pattern.length; i++) { mCameraLaunchGestureVibePattern[i] = pattern[i]; } // receive broadcasts IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); IntentFilter demoFilter = new IntentFilter(); if (DEBUG_MEDIA_FAKE_ARTWORK) { demoFilter.addAction(ACTION_FAKE_ARTWORK); } demoFilter.addAction(ACTION_DEMO); context.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter, android.Manifest.permission.DUMP, null); // listen for USER_SETUP_COMPLETE setting (per-user) mDeviceProvisionedController.addCallback(mUserSetupObserver); mUserSetupObserver.onUserSetupChanged(); // disable profiling bars, since they overlap and clutter the output on app windows ThreadedRenderer.overrideProperty("disableProfileBars", "true"); // Private API call to make the shadows look better for Recents ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); } protected void createNavigationBar() { mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> { mNavigationBar = (NavigationBarFragment) fragment; if (mLightBarController != null) { mNavigationBar.setLightBarController(mLightBarController); } mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility); }); }
Returns the OnTouchListener that will be invoked when the background window of the status bar is clicked.
/** * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the * background window of the status bar is clicked. */
protected View.OnTouchListener getStatusBarWindowTouchListener() { return (v, event) -> { checkUserAutohide(event); mRemoteInputManager.checkRemoteInputOutside(event); if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mExpandedVisible) { animateCollapsePanels(); } } return mStatusBarWindow.onTouchEvent(event); }; } private void inflateShelf() { mNotificationShelf = (NotificationShelf) LayoutInflater.from(mContext).inflate( R.layout.status_bar_notification_shelf, mStackScroller, false); mNotificationShelf.setOnActivatedListener(this); mStackScroller.setShelf(mNotificationShelf); mNotificationShelf.setOnClickListener(mGoToLockedShadeListener); mNotificationShelf.setStatusBarState(mState); } public void onDensityOrFontScaleChanged() { MessagingMessage.dropCache(); MessagingGroup.dropCache(); // start old BaseStatusBar.onDensityOrFontScaleChanged(). if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) { mEntryManager.updateNotificationsOnDensityOrFontScaleChanged(); } else { mReinflateNotificationsOnUserSwitched = true; } // end old BaseStatusBar.onDensityOrFontScaleChanged(). // TODO: Remove this. if (mBrightnessMirrorController != null) { mBrightnessMirrorController.onDensityOrFontScaleChanged(); } mStatusBarKeyguardViewManager.onDensityOrFontScaleChanged(); // TODO: Bring these out of StatusBar. ((UserInfoControllerImpl) Dependency.get(UserInfoController.class)) .onDensityOrFontScaleChanged(); Dependency.get(UserSwitcherController.class).onDensityOrFontScaleChanged(); if (mKeyguardUserSwitcher != null) { mKeyguardUserSwitcher.onDensityOrFontScaleChanged(); } mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext); mHeadsUpManager.onDensityOrFontScaleChanged(); reevaluateStyles(); } private void onThemeChanged() { reevaluateStyles(); // Clock and bottom icons mNotificationPanel.onThemeChanged(); // The status bar on the keyguard is a special layout. if (mKeyguardStatusBar != null) mKeyguardStatusBar.onThemeChanged(); // Recreate Indication controller because internal references changed mKeyguardIndicationController = SystemUIFactory.getInstance().createKeyguardIndicationController(mContext, mStatusBarWindow.findViewById(R.id.keyguard_indication_area), mNotificationPanel.getLockIcon()); mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController); mKeyguardIndicationController .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD); mKeyguardIndicationController.setDozing(mDozing); if (mStatusBarKeyguardViewManager != null) { mStatusBarKeyguardViewManager.onThemeChanged(); } if (mAmbientIndicationContainer instanceof AutoReinflateContainer) { ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout(); } } protected void reevaluateStyles() { inflateFooterView(); updateFooter(); inflateEmptyShadeView(); updateEmptyShadeView(); } @Override public void onOverlayChanged() { if (mBrightnessMirrorController != null) { mBrightnessMirrorController.onOverlayChanged(); } } private void inflateEmptyShadeView() { if (mStackScroller == null) { return; } mEmptyShadeView = (EmptyShadeView) LayoutInflater.from(mContext).inflate( R.layout.status_bar_no_notifications, mStackScroller, false); mEmptyShadeView.setText(R.string.empty_shade_text); mStackScroller.setEmptyShadeView(mEmptyShadeView); } private void inflateFooterView() { if (mStackScroller == null) { return; } mFooterView = (FooterView) LayoutInflater.from(mContext).inflate( R.layout.status_bar_notification_footer, mStackScroller, false); mFooterView.setDismissButtonClickListener(v -> { mMetricsLogger.action(MetricsEvent.ACTION_DISMISS_ALL_NOTES); clearAllNotifications(); }); mFooterView.setManageButtonClickListener(v -> { manageNotifications(); }); mStackScroller.setFooterView(mFooterView); } protected void createUserSwitcher() { mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext, mStatusBarWindow.findViewById(R.id.keyguard_user_switcher), mKeyguardStatusBar, mNotificationPanel); } protected void inflateStatusBarWindow(Context context) { mStatusBarWindow = (StatusBarWindowView) View.inflate(context, R.layout.super_status_bar, null); } public void manageNotifications() { Intent intent = new Intent(Settings.ACTION_ALL_APPS_NOTIFICATION_SETTINGS); startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP); } public void clearAllNotifications() { // animate-swipe all dismissable notifications, then animate the shade closed int numChildren = mStackScroller.getChildCount(); final ArrayList<View> viewsToHide = new ArrayList<>(numChildren); final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren); for (int i = 0; i < numChildren; i++) { final View child = mStackScroller.getChildAt(i); if (child instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) child; boolean parentVisible = false; boolean hasClipBounds = child.getClipBounds(mTmpRect); if (mStackScroller.canChildBeDismissed(child)) { viewsToRemove.add(row); if (child.getVisibility() == View.VISIBLE && (!hasClipBounds || mTmpRect.height() > 0)) { viewsToHide.add(child); parentVisible = true; } } else if (child.getVisibility() == View.VISIBLE && (!hasClipBounds || mTmpRect.height() > 0)) { parentVisible = true; } List<ExpandableNotificationRow> children = row.getNotificationChildren(); if (children != null) { for (ExpandableNotificationRow childRow : children) { viewsToRemove.add(childRow); if (parentVisible && row.areChildrenExpanded() && mStackScroller.canChildBeDismissed(childRow)) { hasClipBounds = childRow.getClipBounds(mTmpRect); if (childRow.getVisibility() == View.VISIBLE && (!hasClipBounds || mTmpRect.height() > 0)) { viewsToHide.add(childRow); } } } } } } if (viewsToRemove.isEmpty()) { animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); return; } addPostCollapseAction(() -> { mStackScroller.setDismissAllInProgress(false); for (ExpandableNotificationRow rowToRemove : viewsToRemove) { if (mStackScroller.canChildBeDismissed(rowToRemove)) { mEntryManager.removeNotification(rowToRemove.getEntry().key, null); } else { rowToRemove.resetTranslation(); } } try { mBarService.onClearAllNotifications(mLockscreenUserManager.getCurrentUserId()); } catch (Exception ex) { } }); performDismissAllAnimations(viewsToHide); } private void performDismissAllAnimations(ArrayList<View> hideAnimatedList) { Runnable animationFinishAction = () -> { animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); }; if (hideAnimatedList.isEmpty()) { animationFinishAction.run(); return; } // let's disable our normal animations mStackScroller.setDismissAllInProgress(true); // Decrease the delay for every row we animate to give the sense of // accelerating the swipes int rowDelayDecrement = 10; int currentDelay = 140; int totalDelay = 180; int numItems = hideAnimatedList.size(); for (int i = numItems - 1; i >= 0; i--) { View view = hideAnimatedList.get(i); Runnable endRunnable = null; if (i == 0) { endRunnable = animationFinishAction; } mStackScroller.dismissViewAnimated(view, endRunnable, totalDelay, 260); currentDelay = Math.max(50, currentDelay - rowDelayDecrement); totalDelay += currentDelay; } } protected void startKeyguard() { Trace.beginSection("StatusBar#startKeyguard"); KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class); mFingerprintUnlockController = new FingerprintUnlockController(mContext, mDozeScrimController, keyguardViewMediator, mScrimController, this, UnlockMethodCache.getInstance(mContext)); mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, getBouncerContainer(), mNotificationPanel, mFingerprintUnlockController); mKeyguardIndicationController .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); mRemoteInputManager.getController().addCallback(mStatusBarKeyguardViewManager); mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback(); mLightBarController.setFingerprintUnlockController(mFingerprintUnlockController); Dependency.get(KeyguardDismissUtil.class).setDismissHandler(this::executeWhenUnlocked); Trace.endSection(); } protected View getStatusBarView() { return mStatusBarView; } public StatusBarWindowView getStatusBarWindow() { return mStatusBarWindow; } protected ViewGroup getBouncerContainer() { return mStatusBarWindow; } public int getStatusBarHeight() { if (mNaturalBarHeight < 0) { final Resources res = mContext.getResources(); mNaturalBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); } return mNaturalBarHeight; } protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) { if (mRecents == null) { return false; } int dockSide = WindowManagerProxy.getInstance().getDockSide(); if (dockSide == WindowManager.DOCKED_INVALID) { final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition(); if (navbarPos == NAV_BAR_POS_INVALID) { return false; } int createMode = navbarPos == NAV_BAR_POS_LEFT ? ActivityManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT : ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT; return mRecents.splitPrimaryTask(NavigationBarGestureHelper.DRAG_MODE_NONE, createMode, null, metricsDockAction); } else { Divider divider = getComponent(Divider.class); if (divider != null && divider.isMinimized() && !divider.isHomeStackResizable()) { // Undocking from the minimized state is not supported return false; } else { EventBus.getDefault().send(new UndockingTaskEvent()); if (metricsUndockAction != -1) { mMetricsLogger.action(metricsUndockAction); } } } return true; } @Override public void onPerformRemoveNotification(StatusBarNotification n) { if (mStackScroller.hasPulsingNotifications() && !mHeadsUpManager.hasHeadsUpNotifications()) { // We were showing a pulse for a notification, but no notifications are pulsing anymore. // Finish the pulse. mDozeScrimController.pulseOutNow(); } } @Override public void updateNotificationViews() { // The function updateRowStates depends on both of these being non-null, so check them here. // We may be called before they are set from DeviceProvisionedController's callback. if (mStackScroller == null || mScrimController == null) return; // Do not modify the notifications during collapse. if (isCollapsing()) { addPostCollapseAction(this::updateNotificationViews); return; } mViewHierarchyManager.updateNotificationViews(); updateSpeedBumpIndex(); updateFooter(); updateEmptyShadeView(); updateQsExpansionEnabled(); // Let's also update the icons mNotificationIconAreaController.updateNotificationIcons(); } @Override public void onNotificationAdded(Entry shadeEntry) { // Recalculate the position of the sliding windows and the titles. setAreThereNotifications(); } @Override public void onNotificationUpdated(StatusBarNotification notification) { setAreThereNotifications(); } @Override public void onNotificationRemoved(String key, StatusBarNotification old) { if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old); if (old != null) { if (CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications() && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()) { if (mState == StatusBarState.SHADE) { animateCollapsePanels(); } else if (mState == StatusBarState.SHADE_LOCKED && !isCollapsing()) { goToKeyguard(); } } } setAreThereNotifications(); }
Disable QS if device not provisioned. If the user switcher is simple then disable QS during setup because the user intends to use the lock screen user switcher, QS in not needed.
/** * Disable QS if device not provisioned. * If the user switcher is simple then disable QS during setup because * the user intends to use the lock screen user switcher, QS in not needed. */
private void updateQsExpansionEnabled() { mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() && (mUserSetup || mUserSwitcherController == null || !mUserSwitcherController.isSimpleUserSwitcher()) && ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0) && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) && !mDozing && !ONLY_CORE_APPS); } public void addQsTile(ComponentName tile) { if (mQSPanel != null && mQSPanel.getHost() != null) { mQSPanel.getHost().addTile(tile); } } public void remQsTile(ComponentName tile) { if (mQSPanel != null && mQSPanel.getHost() != null) { mQSPanel.getHost().removeTile(tile); } } public void clickTile(ComponentName tile) { mQSPanel.clickTile(tile); } @VisibleForTesting protected void updateFooter() { boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(); boolean showFooterView = (showDismissView || mEntryManager.getNotificationData().getActiveNotifications().size() != 0) && mState != StatusBarState.KEYGUARD && !mRemoteInputManager.getController().isRemoteInputActive(); mStackScroller.updateFooterView(showFooterView, showDismissView); }
Return whether there are any clearable notifications
/** * Return whether there are any clearable notifications */
private boolean hasActiveClearableNotifications() { int childCount = mStackScroller.getChildCount(); for (int i = 0; i < childCount; i++) { View child = mStackScroller.getChildAt(i); if (!(child instanceof ExpandableNotificationRow)) { continue; } if (((ExpandableNotificationRow) child).canViewBeDismissed()) { return true; } } return false; } private void updateEmptyShadeView() { boolean showEmptyShadeView = mState != StatusBarState.KEYGUARD && mEntryManager.getNotificationData().getActiveNotifications().size() == 0; mNotificationPanel.showEmptyShadeView(showEmptyShadeView); } private void updateSpeedBumpIndex() { int speedBumpIndex = 0; int currentIndex = 0; final int N = mStackScroller.getChildCount(); for (int i = 0; i < N; i++) { View view = mStackScroller.getChildAt(i); if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) { continue; } ExpandableNotificationRow row = (ExpandableNotificationRow) view; currentIndex++; if (!mEntryManager.getNotificationData().isAmbient( row.getStatusBarNotification().getKey())) { speedBumpIndex = currentIndex; } } boolean noAmbient = speedBumpIndex == N; mStackScroller.updateSpeedBumpIndex(speedBumpIndex, noAmbient); } public static boolean isTopLevelChild(Entry entry) { return entry.row.getParent() instanceof NotificationStackScrollLayout; } public boolean areNotificationsHidden() { return mZenController.areNotificationsHiddenInShade(); } public void requestNotificationUpdate() { mEntryManager.updateNotifications(); } protected void setAreThereNotifications() { if (SPEW) { final boolean clearable = hasActiveNotifications() && hasActiveClearableNotifications(); Log.d(TAG, "setAreThereNotifications: N=" + mEntryManager.getNotificationData().getActiveNotifications().size() + " any=" + hasActiveNotifications() + " clearable=" + clearable); } if (mStatusBarView != null) { final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out); final boolean showDot = hasActiveNotifications() && !areLightsOn(); if (showDot != (nlo.getAlpha() == 1.0f)) { if (showDot) { nlo.setAlpha(0f); nlo.setVisibility(View.VISIBLE); } nlo.animate() .alpha(showDot ? 1 : 0) .setDuration(showDot ? 750 : 250) .setInterpolator(new AccelerateInterpolator(2.0f)) .setListener(showDot ? null : new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator _a) { nlo.setVisibility(View.GONE); } }) .start(); } } mMediaManager.findAndUpdateMediaNotifications(); }
Hide the album artwork that is fading out and release its bitmap.
/** * Hide the album artwork that is fading out and release its bitmap. */
protected final Runnable mHideBackdropFront = new Runnable() { @Override public void run() { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: removing fade layer"); } mBackdropFront.setVisibility(View.INVISIBLE); mBackdropFront.animate().cancel(); mBackdropFront.setImageDrawable(null); } }; // TODO: Move this to NotificationMediaManager.
Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
/** * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper. */
@Override public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) { Trace.beginSection("StatusBar#updateMediaMetaData"); if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) { Trace.endSection(); return; } if (mBackdrop == null) { Trace.endSection(); return; // called too early } boolean wakeAndUnlock = mFingerprintUnlockController != null && mFingerprintUnlockController.isWakeAndUnlock(); if (mLaunchTransitionFadingAway || wakeAndUnlock) { mBackdrop.setVisibility(View.INVISIBLE); Trace.endSection(); return; } MediaMetadata mediaMetadata = mMediaManager.getMediaMetadata(); if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: updating album art for notification " + mMediaManager.getMediaNotificationKey() + " metadata=" + mediaMetadata + " metaDataChanged=" + metaDataChanged + " state=" + mState); } Drawable artworkDrawable = null; if (mediaMetadata != null) { Bitmap artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART); if (artworkBitmap == null) { artworkBitmap = mediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART); // might still be null } if (artworkBitmap != null) { artworkDrawable = new BitmapDrawable(mBackdropBack.getResources(), artworkBitmap); } } boolean allowWhenShade = false; if (ENABLE_LOCKSCREEN_WALLPAPER && artworkDrawable == null) { Bitmap lockWallpaper = mLockscreenWallpaper.getBitmap(); if (lockWallpaper != null) { artworkDrawable = new LockscreenWallpaper.WallpaperDrawable( mBackdropBack.getResources(), lockWallpaper); // We're in the SHADE mode on the SIM screen - yet we still need to show // the lockscreen wallpaper in that mode. allowWhenShade = mStatusBarKeyguardViewManager != null && mStatusBarKeyguardViewManager.isShowing(); } } boolean hideBecauseOccluded = mStatusBarKeyguardViewManager != null && mStatusBarKeyguardViewManager.isOccluded(); final boolean hasArtwork = artworkDrawable != null; mColorExtractor.setHasBackdrop(hasArtwork); if (mScrimController != null) { mScrimController.setHasBackdrop(hasArtwork); } if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK) && (mState != StatusBarState.SHADE || allowWhenShade) && mFingerprintUnlockController.getMode() != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING && !hideBecauseOccluded) { // time to show some art! if (mBackdrop.getVisibility() != View.VISIBLE) { mBackdrop.setVisibility(View.VISIBLE); if (allowEnterAnimation) { mBackdrop.setAlpha(SRC_MIN_ALPHA); mBackdrop.animate().alpha(1f); } else { mBackdrop.animate().cancel(); mBackdrop.setAlpha(1f); } mStatusBarWindowManager.setBackdropShowing(true); metaDataChanged = true; if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork"); } } if (metaDataChanged) { if (mBackdropBack.getDrawable() != null) { Drawable drawable = mBackdropBack.getDrawable().getConstantState() .newDrawable(mBackdropFront.getResources()).mutate(); mBackdropFront.setImageDrawable(drawable); if (mScrimSrcModeEnabled) { mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode); } mBackdropFront.setAlpha(1f); mBackdropFront.setVisibility(View.VISIBLE); } else { mBackdropFront.setVisibility(View.INVISIBLE); } if (DEBUG_MEDIA_FAKE_ARTWORK) { final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF); Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c)); mBackdropBack.setBackgroundColor(0xFFFFFFFF); mBackdropBack.setImageDrawable(new ColorDrawable(c)); } else { mBackdropBack.setImageDrawable(artworkDrawable); } if (mScrimSrcModeEnabled) { mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode); } if (mBackdropFront.getVisibility() == View.VISIBLE) { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from " + mBackdropFront.getDrawable() + " to " + mBackdropBack.getDrawable()); } mBackdropFront.animate() .setDuration(250) .alpha(0f).withEndAction(mHideBackdropFront); } } } else { // need to hide the album art, either because we are unlocked, on AOD // or because the metadata isn't there to support it if (mBackdrop.getVisibility() != View.GONE) { if (DEBUG_MEDIA) { Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork"); } boolean cannotAnimateDoze = mDozing && !ScrimState.AOD.getAnimateChange(); if (mFingerprintUnlockController.getMode() == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING || hideBecauseOccluded || cannotAnimateDoze) { // We are unlocking directly - no animation! mBackdrop.setVisibility(View.GONE); mBackdropBack.setImageDrawable(null); mStatusBarWindowManager.setBackdropShowing(false); } else { mStatusBarWindowManager.setBackdropShowing(false); mBackdrop.animate() .alpha(SRC_MIN_ALPHA) .setInterpolator(Interpolators.ACCELERATE_DECELERATE) .setDuration(300) .setStartDelay(0) .withEndAction(() -> { mBackdrop.setVisibility(View.GONE); mBackdropFront.animate().cancel(); mBackdropBack.setImageDrawable(null); mHandler.post(mHideBackdropFront); }); if (mKeyguardFadingAway) { mBackdrop.animate() // Make it disappear faster, as the focus should be on the activity // behind. .setDuration(mKeyguardFadingAwayDuration / 2) .setStartDelay(mKeyguardFadingAwayDelay) .setInterpolator(Interpolators.LINEAR) .start(); } } } } Trace.endSection(); } private void updateReportRejectedTouchVisibility() { if (mReportRejectedTouch == null) { return; } mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing && mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE); }
State is one or more of the DISABLE constants from StatusBarManager.
/** * State is one or more of the DISABLE constants from StatusBarManager. */
@Override public void disable(int state1, int state2, boolean animate) { state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2); animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN; final int old1 = mDisabled1; final int diff1 = state1 ^ old1; mDisabled1 = state1; final int old2 = mDisabled2; final int diff2 = state2 ^ old2; mDisabled2 = state2; if (DEBUG) { Log.d(TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)", old1, state1, diff1)); Log.d(TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)", old2, state2, diff2)); } StringBuilder flagdbg = new StringBuilder(); flagdbg.append("disable<"); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_EXPAND)) ? 'E' : 'e'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_EXPAND)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? 'I' : 'i'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? 'A' : 'a'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? 'S' : 's'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_BACK)) ? 'B' : 'b'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_BACK)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_HOME)) ? 'H' : 'h'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_HOME)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_RECENT)) ? 'R' : 'r'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_RECENT)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_CLOCK)) ? 'C' : 'c'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_CLOCK)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH)) ? 'S' : 's'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SEARCH)) ? '!' : ' '); flagdbg.append("> disable2<"); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? 'Q' : 'q'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? '!' : ' '); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? 'I' : 'i'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? '!' : ' '); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? 'N' : 'n'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? '!' : ' '); flagdbg.append('>'); Log.d(TAG, flagdbg.toString()); if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) { if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) { animateCollapsePanels(); } } if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0) { if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) { // close recents if it's visible mHandler.removeMessages(MSG_HIDE_RECENT_APPS); mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); } } if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) { mEntryManager.setDisableNotificationAlerts( (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0); } if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0) { updateQsExpansionEnabled(); } if ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { updateQsExpansionEnabled(); if ((state1 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { animateCollapsePanels(); } } }
Reapplies the disable flags as last requested by StatusBarManager. This needs to be called if state used by adjustDisableFlags changes.
/** * Reapplies the disable flags as last requested by StatusBarManager. * * This needs to be called if state used by {@link #adjustDisableFlags} changes. */
public void recomputeDisableFlags(boolean animate) { mCommandQueue.recomputeDisableFlags(animate); } protected H createHandler() { return new StatusBar.H(); } private void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags) { startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags); } @Override public void startActivity(Intent intent, boolean dismissShade) { startActivityDismissingKeyguard(intent, false, dismissShade); } @Override public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) { startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade); } @Override public void startActivity(Intent intent, boolean dismissShade, Callback callback) { startActivityDismissingKeyguard(intent, false, dismissShade, false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0); } public void setQsExpanded(boolean expanded) { mStatusBarWindowManager.setQsExpanded(expanded); mNotificationPanel.setStatusAccessibilityImportance(expanded ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); } public boolean isGoingToNotificationShade() { return mLeaveOpenOnKeyguardHide; } public boolean isWakeUpComingFromTouch() { return mWakeUpComingFromTouch; } public boolean isFalsingThresholdNeeded() { return getBarState() == StatusBarState.KEYGUARD; } @Override public boolean isDozing() { return mDozing && mStackScroller.isFullyDark(); } @Override public boolean shouldPeek(Entry entry, StatusBarNotification sbn) { if (mIsOccluded && !isDozing()) { boolean devicePublic = mLockscreenUserManager. isLockscreenPublicMode(mLockscreenUserManager.getCurrentUserId()); boolean userPublic = devicePublic || mLockscreenUserManager.isLockscreenPublicMode(sbn.getUserId()); boolean needsRedaction = mLockscreenUserManager.needsRedaction(entry); if (userPublic && needsRedaction) { return false; } } if (!panelsEnabled()) { if (DEBUG) { Log.d(TAG, "No peeking: disabled panel : " + sbn.getKey()); } return false; } if (sbn.getNotification().fullScreenIntent != null) { if (mAccessibilityManager.isTouchExplorationEnabled()) { if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey()); return false; } else if (isDozing()) { // We never want heads up when we are dozing. return false; } else { // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent return !mStatusBarKeyguardViewManager.isShowing() || mStatusBarKeyguardViewManager.isOccluded(); } } return true; } @Override // NotificationData.Environment public String getCurrentMediaNotificationKey() { return mMediaManager.getMediaNotificationKey(); } public boolean isScrimSrcModeEnabled() { return mScrimSrcModeEnabled; }
To be called when there's a state change in StatusBarKeyguardViewManager.
/** * To be called when there's a state change in StatusBarKeyguardViewManager. */
public void onKeyguardViewManagerStatesUpdated() { logStateToEventlog(); } @Override // UnlockMethodCache.OnUnlockMethodChangedListener public void onUnlockMethodStateChanged() { logStateToEventlog(); } @Override public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) { if (inPinnedMode) { mStatusBarWindowManager.setHeadsUpShowing(true); mStatusBarWindowManager.setForceStatusBarVisible(true); if (mNotificationPanel.isFullyCollapsed()) { // We need to ensure that the touchable region is updated before the window will be // resized, in order to not catch any touches. A layout will ensure that // onComputeInternalInsets will be called and after that we can resize the layout. Let's // make sure that the window stays small for one frame until the touchableRegion is set. mNotificationPanel.requestLayout(); mStatusBarWindowManager.setForceWindowCollapsed(true); mNotificationPanel.post(() -> { mStatusBarWindowManager.setForceWindowCollapsed(false); }); } } else { if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()) { // We are currently tracking or is open and the shade doesn't need to be kept // open artificially. mStatusBarWindowManager.setHeadsUpShowing(false); } else { // we need to keep the panel open artificially, let's wait until the animation // is finished. mHeadsUpManager.setHeadsUpGoingAway(true); mStackScroller.runAfterAnimationFinished(() -> { if (!mHeadsUpManager.hasPinnedHeadsUp()) { mStatusBarWindowManager.setHeadsUpShowing(false); mHeadsUpManager.setHeadsUpGoingAway(false); } mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); }); } } } @Override public void onHeadsUpPinned(ExpandableNotificationRow headsUp) { dismissVolumeDialog(); } @Override public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) { } @Override public void onHeadsUpStateChanged(Entry entry, boolean isHeadsUp) { mEntryManager.onHeadsUpStateChanged(entry, isHeadsUp); if (isHeadsUp) { mDozeServiceHost.fireNotificationHeadsUp(); } } protected void setHeadsUpUser(int newUserId) { if (mHeadsUpManager != null) { mHeadsUpManager.setUser(newUserId); } } public boolean isKeyguardCurrentlySecure() { return !mUnlockMethodCache.canSkipBouncer(); } public void setPanelExpanded(boolean isExpanded) { mPanelExpanded = isExpanded; updateHideIconsForBouncer(false /* animate */); mStatusBarWindowManager.setPanelExpanded(isExpanded); mVisualStabilityManager.setPanelExpanded(isExpanded); if (isExpanded && getBarState() != StatusBarState.KEYGUARD) { if (DEBUG) { Log.v(TAG, "clearing notification effects from setExpandedHeight"); } clearNotificationEffects(); } if (!isExpanded) { mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); } } public NotificationStackScrollLayout getNotificationScrollLayout() { return mStackScroller; } public boolean isPulsing() { return mDozeScrimController != null && mDozeScrimController.isPulsing(); } public boolean isLaunchTransitionFadingAway() { return mLaunchTransitionFadingAway; } public boolean hideStatusBarIconsWhenExpanded() { return mNotificationPanel.hideStatusBarIconsWhenExpanded(); } @Override public void onColorsChanged(ColorExtractor extractor, int which) { updateTheme(); } public boolean isUsingDarkTheme() { OverlayInfo themeInfo = null; try { themeInfo = mOverlayManager.getOverlayInfo("com.android.systemui.theme.dark", mLockscreenUserManager.getCurrentUserId()); } catch (RemoteException e) { e.printStackTrace(); } return themeInfo != null && themeInfo.isEnabled(); } @Nullable public View getAmbientIndicationContainer() { return mAmbientIndicationContainer; } public void setOccluded(boolean occluded) { mIsOccluded = occluded; mScrimController.setKeyguardOccluded(occluded); updateHideIconsForBouncer(false /* animate */); } public boolean hideStatusBarIconsForBouncer() { return mHideIconsForBouncer || mWereIconsJustHidden; }
Decides if the status bar (clock + notifications + signal cluster) should be visible or not when showing the bouncer. We want to hide it when: • User swipes up on the keyguard • Locked activity that doesn't show a status bar requests the bouncer
Params:
  • animate – should the change of the icons be animated.
/** * Decides if the status bar (clock + notifications + signal cluster) should be visible * or not when showing the bouncer. * * We want to hide it when: * • User swipes up on the keyguard * • Locked activity that doesn't show a status bar requests the bouncer * * @param animate should the change of the icons be animated. */
private void updateHideIconsForBouncer(boolean animate) { boolean hideBecauseApp = mTopHidesStatusBar && mIsOccluded && (mStatusBarWindowHidden || mBouncerShowing); boolean hideBecauseKeyguard = !mPanelExpanded && !mIsOccluded && mBouncerShowing; boolean shouldHideIconsForBouncer = hideBecauseApp || hideBecauseKeyguard; if (mHideIconsForBouncer != shouldHideIconsForBouncer) { mHideIconsForBouncer = shouldHideIconsForBouncer; if (!shouldHideIconsForBouncer && mBouncerWasShowingWhenHidden) { // We're delaying the showing, since most of the time the fullscreen app will // hide the icons again and we don't want them to fade in and out immediately again. mWereIconsJustHidden = true; mHandler.postDelayed(() -> { mWereIconsJustHidden = false; recomputeDisableFlags(true); }, 500); } else { recomputeDisableFlags(animate); } } if (shouldHideIconsForBouncer) { mBouncerWasShowingWhenHidden = mBouncerShowing; } } public void onLaunchAnimationCancelled() { if (!isCollapsing()) { onClosingFinished(); } } public boolean isHeadsUpShouldBeVisible() { return mHeadsUpAppearanceController.shouldBeVisible(); }
All changes to the status bar and notifications funnel through here and are batched.
/** * All changes to the status bar and notifications funnel through here and are batched. */
protected class H extends Handler { @Override public void handleMessage(Message m) { switch (m.what) { case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU: toggleKeyboardShortcuts(m.arg1); break; case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU: dismissKeyboardShortcuts(); break; // End old BaseStatusBar.H handling. case MSG_OPEN_NOTIFICATION_PANEL: animateExpandNotificationsPanel(); break; case MSG_OPEN_SETTINGS_PANEL: animateExpandSettingsPanel((String) m.obj); break; case MSG_CLOSE_PANELS: animateCollapsePanels(); break; case MSG_LAUNCH_TRANSITION_TIMEOUT: onLaunchTransitionTimeout(); break; } } } public void maybeEscalateHeadsUp() { mHeadsUpManager.getAllEntries().forEach(entry -> { final StatusBarNotification sbn = entry.notification; final Notification notification = sbn.getNotification(); if (notification.fullScreenIntent != null) { if (DEBUG) { Log.d(TAG, "converting a heads up to fullScreen"); } try { EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, sbn.getKey()); notification.fullScreenIntent.send(); entry.notifyFullScreenIntentLaunched(); } catch (PendingIntent.CanceledException e) { } } }); mHeadsUpManager.releaseAllImmediately(); }
Called for system navigation gestures. First action opens the panel, second opens settings. Down action closes the entire panel.
/** * Called for system navigation gestures. First action opens the panel, second opens * settings. Down action closes the entire panel. */
@Override public void handleSystemKey(int key) { if (SPEW) Log.d(TAG, "handleNavigationKey: " + key); if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive() || mKeyguardMonitor.isShowing() && !mKeyguardMonitor.isOccluded()) { return; } // Panels are not available in setup if (!mUserSetup) return; if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) { mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP); mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */); } else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) { mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN); if (mNotificationPanel.isFullyCollapsed()) { if (mVibrateOnOpening) { mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK); } mNotificationPanel.expand(true /* animate */); mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1); } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){ mNotificationPanel.flingSettings(0 /* velocity */, true /* expand */); mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1); } } } @Override public void showPinningEnterExitToast(boolean entering) { if (entering) { mScreenPinningNotify.showPinningStartToast(); } else { mScreenPinningNotify.showPinningExitToast(); } } @Override public void showPinningEscapeToast() { mScreenPinningNotify.showEscapeToast(getNavigationBarView() == null || getNavigationBarView().isRecentsButtonVisible()); } boolean panelsEnabled() { return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0 && !ONLY_CORE_APPS; } void makeExpandedVisible(boolean force) { if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); if (!force && (mExpandedVisible || !panelsEnabled())) { return; } mExpandedVisible = true; // Expand the window to encompass the full screen in anticipation of the drag. // This is only possible to do atomically because the status bar is at the top of the screen! mStatusBarWindowManager.setPanelVisible(true); visibilityChanged(true); recomputeDisableFlags(!force /* animate */); setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); } public void animateCollapsePanels() { animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE); } private final Runnable mAnimateCollapsePanels = this::animateCollapsePanels; public void postAnimateCollapsePanels() { mHandler.post(mAnimateCollapsePanels); } public void postAnimateForceCollapsePanels() { mHandler.post(() -> { animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */); }); } public void postAnimateOpenPanels() { mHandler.sendEmptyMessage(MSG_OPEN_SETTINGS_PANEL); } @Override public void togglePanel() { if (mPanelExpanded) { animateCollapsePanels(); } else { animateExpandNotificationsPanel(); } } @Override public void animateCollapsePanels(int flags) { animateCollapsePanels(flags, false /* force */, false /* delayed */, 1.0f /* speedUpFactor */); } public void animateCollapsePanels(int flags, boolean force) { animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */); } public void animateCollapsePanels(int flags, boolean force, boolean delayed) { animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */); } public void animateCollapsePanels(int flags, boolean force, boolean delayed, float speedUpFactor) { if (!force && mState != StatusBarState.SHADE) { runPostCollapseRunnables(); return; } if (SPEW) { Log.d(TAG, "animateCollapse():" + " mExpandedVisible=" + mExpandedVisible + " flags=" + flags); } if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) { if (!mHandler.hasMessages(MSG_HIDE_RECENT_APPS)) { mHandler.removeMessages(MSG_HIDE_RECENT_APPS); mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); } } // TODO(b/62444020): remove when this bug is fixed Log.v(TAG, "mStatusBarWindow: " + mStatusBarWindow + " canPanelBeCollapsed(): " + mNotificationPanel.canPanelBeCollapsed()); if (mStatusBarWindow != null && mNotificationPanel.canPanelBeCollapsed()) { // release focus immediately to kick off focus change transition mStatusBarWindowManager.setStatusBarFocusable(false); mStatusBarWindow.cancelExpandHelper(); mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor); } } private void runPostCollapseRunnables() { ArrayList<Runnable> clonedList = new ArrayList<>(mPostCollapseRunnables); mPostCollapseRunnables.clear(); int size = clonedList.size(); for (int i = 0; i < size; i++) { clonedList.get(i).run(); } mStatusBarKeyguardViewManager.readyForKeyguardDone(); } @Override public void animateExpandNotificationsPanel() { if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); if (!panelsEnabled()) { return ; } mNotificationPanel.expandWithoutQs(); if (false) postStartTracing(); } @Override public void animateExpandSettingsPanel(String subPanel) { if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible); if (!panelsEnabled()) { return; } // Settings are not available in setup if (!mUserSetup) return; if (subPanel != null) { mQSPanel.openDetails(subPanel); } mNotificationPanel.expandWithQs(); if (false) postStartTracing(); } public void animateCollapseQuickSettings() { if (mState == StatusBarState.SHADE) { mStatusBarView.collapsePanel(true, false /* delayed */, 1.0f /* speedUpFactor */); } } void makeExpandedInvisible() { if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible + " mExpandedVisible=" + mExpandedVisible); if (!mExpandedVisible || mStatusBarWindow == null) { return; } // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868) mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/, 1.0f /* speedUpFactor */); mNotificationPanel.closeQs(); mExpandedVisible = false; visibilityChanged(false); // Shrink the window to the size of the status bar only mStatusBarWindowManager.setPanelVisible(false); mStatusBarWindowManager.setForceStatusBarVisible(false); // Close any guts that might be visible mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); runPostCollapseRunnables(); setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); showBouncerIfKeyguard(); recomputeDisableFlags(mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */); // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in // the bouncer appear animation. if (!mStatusBarKeyguardViewManager.isShowing()) { WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); } } public boolean interceptTouchEvent(MotionEvent event) { if (DEBUG_GESTURES) { if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH, event.getActionMasked(), (int) event.getX(), (int) event.getY(), mDisabled1, mDisabled2); } } if (SPEW) { Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1=" + mDisabled1 + " mDisabled2=" + mDisabled2); } else if (CHATTY) { if (event.getAction() != MotionEvent.ACTION_MOVE) { Log.d(TAG, String.format( "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x", MotionEvent.actionToString(event.getAction()), event.getRawX(), event.getRawY(), mDisabled1, mDisabled2)); } } if (DEBUG_GESTURES) { mGestureRec.add(event); } if (mStatusBarWindowState == WINDOW_STATE_SHOWING) { final boolean upOrCancel = event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL; if (upOrCancel && !mExpandedVisible) { setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); } else { setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true); } } return false; } public GestureRecorder getGestureRecorder() { return mGestureRec; } public FingerprintUnlockController getFingerprintUnlockController() { return mFingerprintUnlockController; } @Override // CommandQueue public void setWindowState(int window, int state) { boolean showing = state == WINDOW_STATE_SHOWING; if (mStatusBarWindow != null && window == StatusBarManager.WINDOW_STATUS_BAR && mStatusBarWindowState != state) { mStatusBarWindowState = state; if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state)); if (!showing && mState == StatusBarState.SHADE) { mStatusBarView.collapsePanel(false /* animate */, false /* delayed */, 1.0f /* speedUpFactor */); } if (mStatusBarView != null) { mStatusBarWindowHidden = state == WINDOW_STATE_HIDDEN; updateHideIconsForBouncer(false /* animate */); } } } @Override // CommandQueue public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) { final int oldVal = mSystemUiVisibility; final int newVal = (oldVal&~mask) | (vis&mask); final int diff = newVal ^ oldVal; if (DEBUG) Log.d(TAG, String.format( "setSystemUiVisibility vis=%s mask=%s oldVal=%s newVal=%s diff=%s", Integer.toHexString(vis), Integer.toHexString(mask), Integer.toHexString(oldVal), Integer.toHexString(newVal), Integer.toHexString(diff))); boolean sbModeChanged = false; if (diff != 0) { mSystemUiVisibility = newVal; // update low profile if ((diff & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0) { setAreThereNotifications(); } // ready to unhide if ((vis & View.STATUS_BAR_UNHIDE) != 0) { mSystemUiVisibility &= ~View.STATUS_BAR_UNHIDE; mNoAnimationOnNextBarModeChange = true; } // update status bar mode final int sbMode = computeStatusBarMode(oldVal, newVal); sbModeChanged = sbMode != -1; if (sbModeChanged && sbMode != mStatusBarMode) { mStatusBarMode = sbMode; checkBarModes(); touchAutoHide(); } if ((vis & View.NAVIGATION_BAR_UNHIDE) != 0) { mSystemUiVisibility &= ~View.NAVIGATION_BAR_UNHIDE; } // send updated sysui visibility to window manager notifyUiVisibilityChanged(mSystemUiVisibility); } mLightBarController.onSystemUiVisibilityChanged(fullscreenStackVis, dockedStackVis, mask, fullscreenStackBounds, dockedStackBounds, sbModeChanged, mStatusBarMode); } @Override public void showWirelessChargingAnimation(int batteryLevel) { if (mDozing || mKeyguardManager.isKeyguardLocked()) { // on ambient or lockscreen, hide notification panel WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, batteryLevel, new WirelessChargingAnimation.Callback() { @Override public void onAnimationStarting() { CrossFadeHelper.fadeOut(mNotificationPanel, 1); } @Override public void onAnimationEnded() { CrossFadeHelper.fadeIn(mNotificationPanel); } }, mDozing).show(); } else { // workspace WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, batteryLevel, null, false).show(); } } void touchAutoHide() { // update transient bar autohide if (mStatusBarMode == MODE_SEMI_TRANSPARENT || (mNavigationBar != null && mNavigationBar.isSemiTransparent())) { scheduleAutohide(); } else { cancelAutohide(); } } protected int computeStatusBarMode(int oldVal, int newVal) { return computeBarMode(oldVal, newVal, View.STATUS_BAR_TRANSIENT, View.STATUS_BAR_TRANSLUCENT, View.STATUS_BAR_TRANSPARENT); } protected BarTransitions getStatusBarTransitions() { return mStatusBarView.getBarTransitions(); } protected int computeBarMode(int oldVis, int newVis, int transientFlag, int translucentFlag, int transparentFlag) { final int oldMode = barMode(oldVis, transientFlag, translucentFlag, transparentFlag); final int newMode = barMode(newVis, transientFlag, translucentFlag, transparentFlag); if (oldMode == newMode) { return -1; // no mode change } return newMode; } private int barMode(int vis, int transientFlag, int translucentFlag, int transparentFlag) { int lightsOutTransparent = View.SYSTEM_UI_FLAG_LOW_PROFILE | transparentFlag; return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT : (vis & translucentFlag) != 0 ? MODE_TRANSLUCENT : (vis & lightsOutTransparent) == lightsOutTransparent ? MODE_LIGHTS_OUT_TRANSPARENT : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT : (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE) != 0 ? MODE_LIGHTS_OUT : MODE_OPAQUE; } void checkBarModes() { if (mDemoMode) return; if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions()); if (mNavigationBar != null) mNavigationBar.checkNavBarModes(); mNoAnimationOnNextBarModeChange = false; } // Called by NavigationBarFragment void setQsScrimEnabled(boolean scrimEnabled) { mNotificationPanel.setQsScrimEnabled(scrimEnabled); } void checkBarMode(int mode, int windowState, BarTransitions transitions) { final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive && windowState != WINDOW_STATE_HIDDEN; transitions.transitionTo(mode, anim); } private void finishBarAnimations() { if (mStatusBarView != null) { mStatusBarView.getBarTransitions().finishAnimations(); } if (mNavigationBar != null) { mNavigationBar.finishBarAnimations(); } } private final Runnable mCheckBarModes = this::checkBarModes; public void setInteracting(int barWindow, boolean interacting) { final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting; mInteractingWindows = interacting ? (mInteractingWindows | barWindow) : (mInteractingWindows & ~barWindow); if (mInteractingWindows != 0) { suspendAutohide(); } else { resumeSuspendedAutohide(); } // manually dismiss the volume panel when interacting with the nav bar if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) { touchAutoDim(); dismissVolumeDialog(); } checkBarModes(); } private void dismissVolumeDialog() { if (mVolumeComponent != null) { mVolumeComponent.dismissNow(); } } private void resumeSuspendedAutohide() { if (mAutohideSuspended) { scheduleAutohide(); mHandler.postDelayed(mCheckBarModes, 500); // longer than home -> launcher } } private void suspendAutohide() { mHandler.removeCallbacks(mAutohide); mHandler.removeCallbacks(mCheckBarModes); mAutohideSuspended = (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0; } private void cancelAutohide() { mAutohideSuspended = false; mHandler.removeCallbacks(mAutohide); } private void scheduleAutohide() { cancelAutohide(); mHandler.postDelayed(mAutohide, AUTOHIDE_TIMEOUT_MS); } public void touchAutoDim() { if (mNavigationBar != null) { mNavigationBar.getBarTransitions().setAutoDim(false); } mHandler.removeCallbacks(mAutoDim); if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { mHandler.postDelayed(mAutoDim, AUTOHIDE_TIMEOUT_MS); } } void checkUserAutohide(MotionEvent event) { if ((mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT) != 0 // a transient bar is revealed && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar && event.getX() == 0 && event.getY() == 0 // a touch outside both bars && !mRemoteInputManager.getController() .isRemoteInputActive()) { // not due to typing in IME userAutohide(); } } private void userAutohide() { cancelAutohide(); mHandler.postDelayed(mAutohide, 350); // longer than app gesture -> flag clear } private boolean areLightsOn() { return 0 == (mSystemUiVisibility & View.SYSTEM_UI_FLAG_LOW_PROFILE); } public void setLightsOn(boolean on) { Log.v(TAG, "setLightsOn(" + on + ")"); if (on) { setSystemUiVisibility(0, 0, 0, View.SYSTEM_UI_FLAG_LOW_PROFILE, mLastFullscreenStackBounds, mLastDockedStackBounds); } else { setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, 0, 0, View.SYSTEM_UI_FLAG_LOW_PROFILE, mLastFullscreenStackBounds, mLastDockedStackBounds); } } private void notifyUiVisibilityChanged(int vis) { try { if (mLastDispatchedSystemUiVisibility != vis) { mWindowManagerService.statusBarVisibilityChanged(vis); mLastDispatchedSystemUiVisibility = vis; } } catch (RemoteException ex) { } } @Override public void topAppWindowChanged(boolean showMenu) { if (SPEW) { Log.d(TAG, (showMenu?"showing":"hiding") + " the MENU button"); } // See above re: lights-out policy for legacy apps. if (showMenu) setLightsOn(true); } public static String viewInfo(View v) { return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom() + ") " + v.getWidth() + "x" + v.getHeight() + "]"; } @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { synchronized (mQueueLock) { pw.println("Current Status Bar state:"); pw.println(" mExpandedVisible=" + mExpandedVisible); pw.println(" mDisplayMetrics=" + mDisplayMetrics); pw.println(" mStackScroller: " + viewInfo(mStackScroller)); pw.println(" mStackScroller: " + viewInfo(mStackScroller) + " scroll " + mStackScroller.getScrollX() + "," + mStackScroller.getScrollY()); } pw.print(" mInteractingWindows="); pw.println(mInteractingWindows); pw.print(" mStatusBarWindowState="); pw.println(windowStateToString(mStatusBarWindowState)); pw.print(" mStatusBarMode="); pw.println(BarTransitions.modeToString(mStatusBarMode)); pw.print(" mDozing="); pw.println(mDozing); pw.print(" mZenMode="); pw.println(Settings.Global.zenModeToString(Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF))); if (mStatusBarView != null) { dumpBarTransitions(pw, "mStatusBarView", mStatusBarView.getBarTransitions()); } pw.println(" StatusBarWindowView: "); if (mStatusBarWindow != null) { mStatusBarWindow.dump(fd, pw, args); } pw.println(" mMediaManager: "); if (mMediaManager != null) { mMediaManager.dump(fd, pw, args); } pw.println(" Panels: "); if (mNotificationPanel != null) { pw.println(" mNotificationPanel=" + mNotificationPanel + " params=" + mNotificationPanel.getLayoutParams().debug("")); pw.print (" "); mNotificationPanel.dump(fd, pw, args); } pw.println(" mStackScroller: "); if (mStackScroller != null) { pw.print (" "); mStackScroller.dump(fd, pw, args); } pw.println(" Theme:"); if (mOverlayManager == null) { pw.println(" overlay manager not initialized!"); } else { pw.println(" dark overlay on: " + isUsingDarkTheme()); } final boolean lightWpTheme = mContext.getThemeResId() == R.style.Theme_SystemUI_Light; pw.println(" light wallpaper theme: " + lightWpTheme); DozeLog.dump(pw); if (mFingerprintUnlockController != null) { mFingerprintUnlockController.dump(pw); } if (mKeyguardIndicationController != null) { mKeyguardIndicationController.dump(fd, pw, args); } if (mScrimController != null) { mScrimController.dump(fd, pw, args); } if (mStatusBarKeyguardViewManager != null) { mStatusBarKeyguardViewManager.dump(pw); } if (DUMPTRUCK) { synchronized (mEntryManager.getNotificationData()) { mEntryManager.getNotificationData().dump(pw, " "); } if (false) { pw.println("see the logcat for a dump of the views we have created."); // must happen on ui thread mHandler.post(() -> { mStatusBarView.getLocationOnScreen(mAbsPos); Log.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1] + ") " + mStatusBarView.getWidth() + "x" + getStatusBarHeight()); mStatusBarView.debug(); }); } } if (DEBUG_GESTURES) { pw.print(" status bar gestures: "); mGestureRec.dump(fd, pw, args); } if (mHeadsUpManager != null) { mHeadsUpManager.dump(fd, pw, args); } else { pw.println(" mHeadsUpManager: null"); } if (mGroupManager != null) { mGroupManager.dump(fd, pw, args); } else { pw.println(" mGroupManager: null"); } if (mLightBarController != null) { mLightBarController.dump(fd, pw, args); } if (KeyguardUpdateMonitor.getInstance(mContext) != null) { KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args); } FalsingManager.getInstance(mContext).dump(pw); FalsingLog.dump(pw); pw.println("SharedPreferences:"); for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) { pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue()); } } static void dumpBarTransitions(PrintWriter pw, String var, BarTransitions transitions) { pw.print(" "); pw.print(var); pw.print(".BarTransitions.mMode="); pw.println(BarTransitions.modeToString(transitions.getMode())); } public void createAndAddWindows() { addStatusBarWindow(); } private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class); mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this, new RemoteInputController.Delegate() { public void setRemoteInputActive(NotificationData.Entry entry, boolean remoteInputActive) { mHeadsUpManager.setRemoteInputActive(entry, remoteInputActive); entry.row.notifyHeightChanged(true /* needsAnimation */); updateFooter(); } public void lockScrollTo(NotificationData.Entry entry) { mStackScroller.lockScrollTo(entry.row); } public void requestDisallowLongPressAndDismiss() { mStackScroller.requestDisallowLongPress(); mStackScroller.requestDisallowDismiss(); } }); mRemoteInputManager.getController().addCallback(mStatusBarWindowManager); mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight()); } // called by makeStatusbar and also by PhoneStatusBarView void updateDisplaySize() { mDisplay.getMetrics(mDisplayMetrics); mDisplay.getSize(mCurrentDisplaySize); if (DEBUG_GESTURES) { mGestureRec.tag("display", String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels)); } } float getDisplayDensity() { return mDisplayMetrics.density; } float getDisplayWidth() { return mDisplayMetrics.widthPixels; } float getDisplayHeight() { return mDisplayMetrics.heightPixels; } int getRotation() { return mDisplay.getRotation(); } public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade, int flags) { startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, flags); } public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, boolean dismissShade) { startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0); } public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching, final Callback callback, int flags) { if (onlyProvisioned && !isDeviceProvisioned()) return; final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( mContext, intent, mLockscreenUserManager.getCurrentUserId()); Runnable runnable = () -> { mAssistManager.hideAssist(); intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.addFlags(flags); int result = ActivityManager.START_CANCELED; ActivityOptions options = new ActivityOptions(getActivityOptions( null /* remoteAnimation */)); options.setDisallowEnterPictureInPictureWhileLaunching( disallowEnterPictureInPictureWhileLaunching); if (intent == KeyguardBottomAreaView.INSECURE_CAMERA_INTENT) { // Normally an activity will set it's requested rotation // animation on its window. However when launching an activity // causes the orientation to change this is too late. In these cases // the default animation is used. This doesn't look good for // the camera (as it rotates the camera contents out of sync // with physical reality). So, we ask the WindowManager to // force the crossfade animation if an orientation change // happens to occur during the launch. options.setRotationAnimationHint( WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS); } try { result = ActivityManager.getService().startActivityAsUser( null, mContext.getBasePackageName(), intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options.toBundle(), UserHandle.CURRENT.getIdentifier()); } catch (RemoteException e) { Log.w(TAG, "Unable to start activity", e); } if (callback != null) { callback.onActivityStarted(result); } }; Runnable cancelRunnable = () -> { if (callback != null) { callback.onActivityStarted(ActivityManager.START_CANCELED); } }; executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, afterKeyguardGone, true /* deferred */); } public void readyForKeyguardDone() { mStatusBarKeyguardViewManager.readyForKeyguardDone(); } public void executeRunnableDismissingKeyguard(final Runnable runnable, final Runnable cancelAction, final boolean dismissShade, final boolean afterKeyguardGone, final boolean deferred) { dismissKeyguardThenExecute(() -> { if (runnable != null) { if (mStatusBarKeyguardViewManager.isShowing() && mStatusBarKeyguardViewManager.isOccluded()) { mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); } else { AsyncTask.execute(runnable); } } if (dismissShade) { if (mExpandedVisible) { animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */, true /* delayed*/); } else { // Do it after DismissAction has been processed to conserve the needed ordering. mHandler.post(this::runPostCollapseRunnables); } } else if (isInLaunchTransition() && mNotificationPanel.isLaunchTransitionFinished()) { // We are not dismissing the shade, but the launch transition is already finished, // so nobody will call readyForKeyguardDone anymore. Post it such that // keyguardDonePending gets called first. mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone); } return deferred; }, cancelAction, afterKeyguardGone); } private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG) Log.v(TAG, "onReceive: " + intent); String action = intent.getAction(); if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { KeyboardShortcuts.dismiss(); if (mRemoteInputManager.getController() != null) { mRemoteInputManager.getController().closeRemoteInputs(); } if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) { int flags = CommandQueue.FLAG_EXCLUDE_NONE; String reason = intent.getStringExtra("reason"); if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; } animateCollapsePanels(flags); } } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { finishBarAnimations(); resetUserExpandedStates(); } else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) { mQSPanel.showDeviceMonitoringDialog(); } } }; private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DEBUG) Log.v(TAG, "onReceive: " + intent); String action = intent.getAction(); if (ACTION_DEMO.equals(action)) { Bundle bundle = intent.getExtras(); if (bundle != null) { String command = bundle.getString("command", "").trim().toLowerCase(); if (command.length() > 0) { try { dispatchDemoCommand(command, bundle); } catch (Throwable t) { Log.w(TAG, "Error running demo command, intent=" + intent, t); } } } } else if (ACTION_FAKE_ARTWORK.equals(action)) { if (DEBUG_MEDIA_FAKE_ARTWORK) { updateMediaMetaData(true, true); } } } }; public void resetUserExpandedStates() { ArrayList<Entry> activeNotifications = mEntryManager.getNotificationData() .getActiveNotifications(); final int notificationCount = activeNotifications.size(); for (int i = 0; i < notificationCount; i++) { NotificationData.Entry entry = activeNotifications.get(i); if (entry.row != null) { entry.row.resetUserExpansion(); } } } private void executeWhenUnlocked(OnDismissAction action) { if (mStatusBarKeyguardViewManager.isShowing()) { mLeaveOpenOnKeyguardHide = true; } dismissKeyguardThenExecute(action, null /* cancelAction */, false /* afterKeyguardGone */); } protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); } private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone) { if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP && mUnlockMethodCache.canSkipBouncer() && !mLeaveOpenOnKeyguardHide && isPulsing()) { // Reuse the fingerprint wake-and-unlock transition if we dismiss keyguard from a pulse. // TODO: Factor this transition out of FingerprintUnlockController. mFingerprintUnlockController.startWakeAndUnlock( FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING); } if (mStatusBarKeyguardViewManager.isShowing()) { mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, afterKeyguardGone); } else { action.onDismiss(); } } // SystemUIService notifies SystemBars of configuration changes, which then calls down here @Override public void onConfigChanged(Configuration newConfig) { updateResources(); updateDisplaySize(); // populates mDisplayMetrics updateTheme(); if (DEBUG) { Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration()); } mViewHierarchyManager.updateRowStates(); mScreenPinningRequest.onConfigurationChanged(); } @Override public void onUserSwitched(int newUserId) { // Begin old BaseStatusBar.userSwitched setHeadsUpUser(newUserId); // End old BaseStatusBar.userSwitched if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId); animateCollapsePanels(); updatePublicMode(); mEntryManager.getNotificationData().filterAndSort(); if (mReinflateNotificationsOnUserSwitched) { mEntryManager.updateNotificationsOnDensityOrFontScaleChanged(); mReinflateNotificationsOnUserSwitched = false; } updateNotificationViews(); mMediaManager.clearCurrentMediaNotification(); setLockscreenUser(newUserId); } @Override public NotificationLockscreenUserManager getNotificationLockscreenUserManager() { return mLockscreenUserManager; } @Override public void onBindRow(Entry entry, PackageManager pmUser, StatusBarNotification sbn, ExpandableNotificationRow row) { row.setAboveShelfChangedListener(mAboveShelfObserver); row.setSecureStateProvider(this::isKeyguardCurrentlySecure); } protected void setLockscreenUser(int newUserId) { mLockscreenWallpaper.setCurrentUser(newUserId); mScrimController.setCurrentUser(newUserId); updateMediaMetaData(true, false); }
Reload some of our resources when the configuration changes. We don't reload everything when the configuration changes -- we probably should, but getting that smooth is tough. Someday we'll fix that. In the meantime, just update the things that we know change.
/** * Reload some of our resources when the configuration changes. * * We don't reload everything when the configuration changes -- we probably * should, but getting that smooth is tough. Someday we'll fix that. In the * meantime, just update the things that we know change. */
void updateResources() { // Update the quick setting tiles if (mQSPanel != null) { mQSPanel.updateResources(); } loadDimens(); if (mStatusBarView != null) { mStatusBarView.updateResources(); } if (mNotificationPanel != null) { mNotificationPanel.updateResources(); } if (mBrightnessMirrorController != null) { mBrightnessMirrorController.updateResources(); } } protected void loadDimens() { final Resources res = mContext.getResources(); int oldBarHeight = mNaturalBarHeight; mNaturalBarHeight = res.getDimensionPixelSize( com.android.internal.R.dimen.status_bar_height); if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) { mStatusBarWindowManager.setBarHeight(mNaturalBarHeight); } mMaxAllowedKeyguardNotifications = res.getInteger( R.integer.keyguard_max_notification_count); if (DEBUG) Log.v(TAG, "defineSlots"); } // Visibility reporting protected void handleVisibleToUserChanged(boolean visibleToUser) { if (visibleToUser) { handleVisibleToUserChangedImpl(visibleToUser); mNotificationLogger.startNotificationLogging(); } else { mNotificationLogger.stopNotificationLogging(); handleVisibleToUserChangedImpl(visibleToUser); } } void handlePeekToExpandTransistion() { try { // consider the transition from peek to expanded to be a panel open, // but not one that clears notification effects. int notificationLoad = mEntryManager.getNotificationData() .getActiveNotifications().size(); mBarService.onPanelRevealed(false, notificationLoad); } catch (RemoteException ex) { // Won't fail unless the world has ended. } }
The LEDs are turned off when the notification panel is shown, even just a little bit. See also StatusBar.setPanelExpanded for another place where we attempt to do this.
/** * The LEDs are turned off when the notification panel is shown, even just a little bit. * See also StatusBar.setPanelExpanded for another place where we attempt to do this. */
private void handleVisibleToUserChangedImpl(boolean visibleToUser) { if (visibleToUser) { boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp(); boolean clearNotificationEffects = !isPresenterFullyCollapsed() && (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED); int notificationLoad = mEntryManager.getNotificationData().getActiveNotifications() .size(); if (pinnedHeadsUp && isPresenterFullyCollapsed()) { notificationLoad = 1; } final int finalNotificationLoad = notificationLoad; mUiOffloadThread.submit(() -> { try { mBarService.onPanelRevealed(clearNotificationEffects, finalNotificationLoad); } catch (RemoteException ex) { // Won't fail unless the world has ended. } }); } else { mUiOffloadThread.submit(() -> { try { mBarService.onPanelHidden(); } catch (RemoteException ex) { // Won't fail unless the world has ended. } }); } } private void logStateToEventlog() { boolean isShowing = mStatusBarKeyguardViewManager.isShowing(); boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded(); boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing(); boolean isSecure = mUnlockMethodCache.isMethodSecure(); boolean canSkipBouncer = mUnlockMethodCache.canSkipBouncer(); int stateFingerprint = getLoggingFingerprint(mState, isShowing, isOccluded, isBouncerShowing, isSecure, canSkipBouncer); if (stateFingerprint != mLastLoggedStateFingerprint) { if (mStatusBarStateLog == null) { mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN); } mMetricsLogger.write(mStatusBarStateLog .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN) .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE) .setSubtype(isSecure ? 1 : 0)); EventLogTags.writeSysuiStatusBarState(mState, isShowing ? 1 : 0, isOccluded ? 1 : 0, isBouncerShowing ? 1 : 0, isSecure ? 1 : 0, canSkipBouncer ? 1 : 0); mLastLoggedStateFingerprint = stateFingerprint; } }
Returns a fingerprint of fields logged to eventlog
/** * Returns a fingerprint of fields logged to eventlog */
private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing, boolean keyguardOccluded, boolean bouncerShowing, boolean secure, boolean currentlyInsecure) { // Reserve 8 bits for statusBarState. We'll never go higher than // that, right? Riiiight. return (statusBarState & 0xFF) | ((keyguardShowing ? 1 : 0) << 8) | ((keyguardOccluded ? 1 : 0) << 9) | ((bouncerShowing ? 1 : 0) << 10) | ((secure ? 1 : 0) << 11) | ((currentlyInsecure ? 1 : 0) << 12); } // // tracing // void postStartTracing() { mHandler.postDelayed(mStartTracing, 3000); } void vibrate() { android.os.Vibrator vib = (android.os.Vibrator)mContext.getSystemService( Context.VIBRATOR_SERVICE); vib.vibrate(250, VIBRATION_ATTRIBUTES); } final Runnable mStartTracing = new Runnable() { @Override public void run() { vibrate(); SystemClock.sleep(250); Log.d(TAG, "startTracing"); android.os.Debug.startMethodTracing("/data/statusbar-traces/trace"); mHandler.postDelayed(mStopTracing, 10000); } }; final Runnable mStopTracing = () -> { android.os.Debug.stopMethodTracing(); Log.d(TAG, "stopTracing"); vibrate(); }; @Override public void postQSRunnableDismissingKeyguard(final Runnable runnable) { mHandler.post(() -> { mLeaveOpenOnKeyguardHide = true; executeRunnableDismissingKeyguard(() -> mHandler.post(runnable), null, false, false, false); }); } @Override public void postStartActivityDismissingKeyguard(final PendingIntent intent) { mHandler.post(() -> startPendingIntentDismissingKeyguard(intent)); } @Override public void postStartActivityDismissingKeyguard(final Intent intent, int delay) { mHandler.postDelayed(() -> handleStartActivityDismissingKeyguard(intent, true /*onlyProvisioned*/), delay); } private void handleStartActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned) { startActivityDismissingKeyguard(intent, onlyProvisioned, true /* dismissShade */); } public void destroy() { // Begin old BaseStatusBar.destroy(). mContext.unregisterReceiver(mBannerActionBroadcastReceiver); mLockscreenUserManager.destroy(); try { mNotificationListener.unregisterAsSystemService(); } catch (RemoteException e) { // Ignore. } mEntryManager.destroy(); // End old BaseStatusBar.destroy(). if (mStatusBarWindow != null) { mWindowManager.removeViewImmediate(mStatusBarWindow); mStatusBarWindow = null; } if (mNavigationBarView != null) { mWindowManager.removeViewImmediate(mNavigationBarView); mNavigationBarView = null; } mContext.unregisterReceiver(mBroadcastReceiver); mContext.unregisterReceiver(mDemoReceiver); mAssistManager.destroy(); if (mQSPanel != null && mQSPanel.getHost() != null) { mQSPanel.getHost().destroy(); } Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null); mDeviceProvisionedController.removeCallback(mUserSetupObserver); Dependency.get(ConfigurationController.class).removeCallback(this); mZenController.removeCallback(this); mAppOpsListener.destroy(); } private boolean mDemoModeAllowed; private boolean mDemoMode; @Override public void dispatchDemoCommand(String command, Bundle args) { if (!mDemoModeAllowed) { mDemoModeAllowed = Settings.Global.getInt(mContext.getContentResolver(), DEMO_MODE_ALLOWED, 0) != 0; } if (!mDemoModeAllowed) return; if (command.equals(COMMAND_ENTER)) { mDemoMode = true; } else if (command.equals(COMMAND_EXIT)) { mDemoMode = false; checkBarModes(); } else if (!mDemoMode) { // automatically enter demo mode on first demo command dispatchDemoCommand(COMMAND_ENTER, new Bundle()); } boolean modeChange = command.equals(COMMAND_ENTER) || command.equals(COMMAND_EXIT); if ((modeChange || command.equals(COMMAND_VOLUME)) && mVolumeComponent != null) { mVolumeComponent.dispatchDemoCommand(command, args); } if (modeChange || command.equals(COMMAND_CLOCK)) { dispatchDemoCommandToView(command, args, R.id.clock); } if (modeChange || command.equals(COMMAND_BATTERY)) { mBatteryController.dispatchDemoCommand(command, args); } if (modeChange || command.equals(COMMAND_STATUS)) { ((StatusBarIconControllerImpl) mIconController).dispatchDemoCommand(command, args); } if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) { mNetworkController.dispatchDemoCommand(command, args); } if (modeChange || command.equals(COMMAND_NOTIFICATIONS)) { View notifications = mStatusBarView == null ? null : mStatusBarView.findViewById(R.id.notification_icon_area); if (notifications != null) { String visible = args.getString("visible"); int vis = mDemoMode && "false".equals(visible) ? View.INVISIBLE : View.VISIBLE; notifications.setVisibility(vis); } } if (command.equals(COMMAND_BARS)) { String mode = args.getString("mode"); int barMode = "opaque".equals(mode) ? MODE_OPAQUE : "translucent".equals(mode) ? MODE_TRANSLUCENT : "semi-transparent".equals(mode) ? MODE_SEMI_TRANSPARENT : "transparent".equals(mode) ? MODE_TRANSPARENT : "warning".equals(mode) ? MODE_WARNING : -1; if (barMode != -1) { boolean animate = true; if (mStatusBarView != null) { mStatusBarView.getBarTransitions().transitionTo(barMode, animate); } if (mNavigationBar != null) { mNavigationBar.getBarTransitions().transitionTo(barMode, animate); } } } if (modeChange || command.equals(COMMAND_OPERATOR)) { dispatchDemoCommandToView(command, args, R.id.operator_name); } } private void dispatchDemoCommandToView(String command, Bundle args, int id) { if (mStatusBarView == null) return; View v = mStatusBarView.findViewById(id); if (v instanceof DemoMode) { ((DemoMode)v).dispatchDemoCommand(command, args); } }
Returns:The StatusBarState the status bar is in.
/** * @return The {@link StatusBarState} the status bar is in. */
public int getBarState() { return mState; } @Override public boolean isPresenterFullyCollapsed() { return mNotificationPanel.isFullyCollapsed(); } public void showKeyguard() { mKeyguardRequested = true; mLeaveOpenOnKeyguardHide = false; mPendingRemoteInputView = null; updateIsKeyguard(); mAssistManager.onLockscreenShown(); } public boolean hideKeyguard() { mKeyguardRequested = false; return updateIsKeyguard(); }
Returns:True if StatusBar state is FULLSCREEN_USER_SWITCHER.
/** * @return True if StatusBar state is FULLSCREEN_USER_SWITCHER. */
public boolean isFullScreenUserSwitcherState() { return mState == StatusBarState.FULLSCREEN_USER_SWITCHER; } private boolean updateIsKeyguard() { boolean wakeAndUnlocking = mFingerprintUnlockController.getMode() == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise // there's no surface we can show to the user. Note that the device goes fully interactive // late in the transition, so we also allow the device to start dozing once the screen has // turned off fully. boolean keyguardForDozing = mDozingRequested && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); boolean shouldBeKeyguard = (mKeyguardRequested || keyguardForDozing) && !wakeAndUnlocking; if (keyguardForDozing) { updatePanelExpansionForKeyguard(); } if (shouldBeKeyguard) { if (isGoingToSleep() && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF) { // Delay showing the keyguard until screen turned off. } else { showKeyguardImpl(); } } else { return hideKeyguardImpl(); } return false; } public void showKeyguardImpl() { mIsKeyguard = true; if (mLaunchTransitionFadingAway) { mNotificationPanel.animate().cancel(); onLaunchTransitionFadingEnded(); } mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); if (mUserSwitcherController != null && mUserSwitcherController.useFullscreenUserSwitcher()) { setBarState(StatusBarState.FULLSCREEN_USER_SWITCHER); } else { setBarState(StatusBarState.KEYGUARD); } updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); updatePanelExpansionForKeyguard(); if (mDraggedDownRow != null) { mDraggedDownRow.setUserLocked(false); mDraggedDownRow.notifyHeightChanged(false /* needsAnimation */); mDraggedDownRow = null; } } private void updatePanelExpansionForKeyguard() { if (mState == StatusBarState.KEYGUARD && mFingerprintUnlockController.getMode() != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) { instantExpandNotificationsPanel(); } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) { instantCollapseNotificationPanel(); } } private void onLaunchTransitionFadingEnded() { mNotificationPanel.setAlpha(1.0f); mNotificationPanel.onAffordanceLaunchEnded(); releaseGestureWakeLock(); runLaunchTransitionEndRunnable(); mLaunchTransitionFadingAway = false; updateMediaMetaData(true /* metaDataChanged */, true); } public boolean isCollapsing() { return mNotificationPanel.isCollapsing() || mActivityLaunchAnimator.isAnimationPending(); } public void addPostCollapseAction(Runnable r) { mPostCollapseRunnables.add(r); } public boolean isInLaunchTransition() { return mNotificationPanel.isLaunchTransitionRunning() || mNotificationPanel.isLaunchTransitionFinished(); }
Fades the content of the keyguard away after the launch transition is done.
Params:
  • beforeFading – the runnable to be run when the circle is fully expanded and the fading starts
  • endRunnable – the runnable to be run when the transition is done
/** * Fades the content of the keyguard away after the launch transition is done. * * @param beforeFading the runnable to be run when the circle is fully expanded and the fading * starts * @param endRunnable the runnable to be run when the transition is done */
public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading, Runnable endRunnable) { mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); mLaunchTransitionEndRunnable = endRunnable; Runnable hideRunnable = () -> { mLaunchTransitionFadingAway = true; if (beforeFading != null) { beforeFading.run(); } updateScrimController(); updateMediaMetaData(false, true); mNotificationPanel.setAlpha(1); mStackScroller.setParentNotFullyVisible(true); mNotificationPanel.animate() .alpha(0) .setStartDelay(FADE_KEYGUARD_START_DELAY) .setDuration(FADE_KEYGUARD_DURATION) .withLayer() .withEndAction(this::onLaunchTransitionFadingEnded); mCommandQueue.appTransitionStarting(SystemClock.uptimeMillis(), LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); }; if (mNotificationPanel.isLaunchTransitionRunning()) { mNotificationPanel.setLaunchTransitionEndRunnable(hideRunnable); } else { hideRunnable.run(); } }
Fades the content of the Keyguard while we are dozing and makes it invisible when finished fading.
/** * Fades the content of the Keyguard while we are dozing and makes it invisible when finished * fading. */
public void fadeKeyguardWhilePulsing() { mNotificationPanel.notifyStartFading(); mNotificationPanel.animate() .alpha(0f) .setStartDelay(0) .setDuration(FADE_KEYGUARD_DURATION_PULSING) .setInterpolator(Interpolators.ALPHA_OUT) .withEndAction(()-> { hideKeyguard(); mStatusBarKeyguardViewManager.onKeyguardFadedAway(); }).start(); }
Plays the animation when an activity that was occluding Keyguard goes away.
/** * Plays the animation when an activity that was occluding Keyguard goes away. */
public void animateKeyguardUnoccluding() { mNotificationPanel.setExpandedFraction(0f); animateExpandNotificationsPanel(); }
Starts the timeout when we try to start the affordances on Keyguard. We usually rely that Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen because the launched app crashed or something else went wrong.
/** * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen * because the launched app crashed or something else went wrong. */
public void startLaunchTransitionTimeout() { mHandler.sendEmptyMessageDelayed(MSG_LAUNCH_TRANSITION_TIMEOUT, LAUNCH_TRANSITION_TIMEOUT_MS); } private void onLaunchTransitionTimeout() { Log.w(TAG, "Launch transition: Timeout!"); mNotificationPanel.onAffordanceLaunchEnded(); releaseGestureWakeLock(); mNotificationPanel.resetViews(); } private void runLaunchTransitionEndRunnable() { if (mLaunchTransitionEndRunnable != null) { Runnable r = mLaunchTransitionEndRunnable; // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again, // which would lead to infinite recursion. Protect against it. mLaunchTransitionEndRunnable = null; r.run(); } }
Returns:true if we would like to stay in the shade, false if it should go away entirely
/** * @return true if we would like to stay in the shade, false if it should go away entirely */
public boolean hideKeyguardImpl() { mIsKeyguard = false; Trace.beginSection("StatusBar#hideKeyguard"); boolean staying = mLeaveOpenOnKeyguardHide; setBarState(StatusBarState.SHADE); View viewToClick = null; if (mLeaveOpenOnKeyguardHide) { if (!mKeyguardRequested) { mLeaveOpenOnKeyguardHide = false; } long delay = calculateGoingToFullShadeDelay(); mNotificationPanel.animateToFullShade(delay); if (mDraggedDownRow != null) { mDraggedDownRow.setUserLocked(false); mDraggedDownRow = null; } if (!mKeyguardRequested) { viewToClick = mPendingRemoteInputView; mPendingRemoteInputView = null; } // Disable layout transitions in navbar for this transition because the load is just // too heavy for the CPU and GPU on any device. if (mNavigationBar != null) { mNavigationBar.disableAnimationsDuringHide(delay); } } else if (!mNotificationPanel.isCollapsing()) { instantCollapseNotificationPanel(); } updateKeyguardState(staying, false /* fromShadeLocked */); if (viewToClick != null && viewToClick.isAttachedToWindow()) { viewToClick.callOnClick(); } // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile // visibilities so next time we open the panel we know the correct height already. if (mQSPanel != null) { mQSPanel.refreshAllTiles(); } mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT); releaseGestureWakeLock(); mNotificationPanel.onAffordanceLaunchEnded(); mNotificationPanel.animate().cancel(); mNotificationPanel.setAlpha(1f); Trace.endSection(); return staying; } private void releaseGestureWakeLock() { if (mGestureWakeLock.isHeld()) { mGestureWakeLock.release(); } } public long calculateGoingToFullShadeDelay() { return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration; }
Notifies the status bar that Keyguard is going away very soon.
/** * Notifies the status bar that Keyguard is going away very soon. */
public void keyguardGoingAway() { // Treat Keyguard exit animation as an app transition to achieve nice transition for status // bar. mKeyguardMonitor.notifyKeyguardGoingAway(true); mCommandQueue.appTransitionPending(true); }
Notifies the status bar the Keyguard is fading away with the specified timings.
Params:
  • startTime – the start time of the animations in uptime millis
  • delay – the precalculated animation delay in milliseconds
  • fadeoutDuration – the duration of the exit animation, in milliseconds
/** * Notifies the status bar the Keyguard is fading away with the specified timings. * * @param startTime the start time of the animations in uptime millis * @param delay the precalculated animation delay in milliseconds * @param fadeoutDuration the duration of the exit animation, in milliseconds */
public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration) { mKeyguardFadingAway = true; mKeyguardFadingAwayDelay = delay; mKeyguardFadingAwayDuration = fadeoutDuration; mCommandQueue.appTransitionStarting(startTime + fadeoutDuration - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); recomputeDisableFlags(fadeoutDuration > 0 /* animate */); mCommandQueue.appTransitionStarting( startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true); mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration); } public boolean isKeyguardFadingAway() { return mKeyguardFadingAway; }
Notifies that the Keyguard fading away animation is done.
/** * Notifies that the Keyguard fading away animation is done. */
public void finishKeyguardFadingAway() { mKeyguardFadingAway = false; mKeyguardMonitor.notifyKeyguardDoneFading(); mScrimController.setExpansionAffectsAlpha(true); } // TODO: Move this to NotificationLockscreenUserManager. private void updatePublicMode() { final boolean showingKeyguard = mStatusBarKeyguardViewManager.isShowing(); final boolean devicePublic = showingKeyguard && mStatusBarKeyguardViewManager.isSecure( mLockscreenUserManager.getCurrentUserId()); // Look for public mode users. Users are considered public in either case of: // - device keyguard is shown in secure mode; // - profile is locked with a work challenge. SparseArray<UserInfo> currentProfiles = mLockscreenUserManager.getCurrentProfiles(); for (int i = currentProfiles.size() - 1; i >= 0; i--) { final int userId = currentProfiles.valueAt(i).id; boolean isProfilePublic = devicePublic; if (!devicePublic && userId != mLockscreenUserManager.getCurrentUserId()) { // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge // due to a race condition where this code could be called before // TrustManagerService updates its internal records, resulting in an incorrect // state being cached in mLockscreenPublicMode. (b/35951989) if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) && mStatusBarKeyguardViewManager.isSecure(userId)) { isProfilePublic = mKeyguardManager.isDeviceLocked(userId); } } mLockscreenUserManager.setLockscreenPublicMode(isProfilePublic, userId); } } protected void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) { Trace.beginSection("StatusBar#updateKeyguardState"); if (mState == StatusBarState.KEYGUARD) { mKeyguardIndicationController.setVisible(true); mNotificationPanel.resetViews(); if (mKeyguardUserSwitcher != null) { mKeyguardUserSwitcher.setKeyguard(true, fromShadeLocked); } if (mStatusBarView != null) mStatusBarView.removePendingHideExpandedRunnables(); if (mAmbientIndicationContainer != null) { mAmbientIndicationContainer.setVisibility(View.VISIBLE); } } else { mKeyguardIndicationController.setVisible(false); if (mKeyguardUserSwitcher != null) { mKeyguardUserSwitcher.setKeyguard(false, goingToFullShade || mState == StatusBarState.SHADE_LOCKED || fromShadeLocked); } if (mAmbientIndicationContainer != null) { mAmbientIndicationContainer.setVisibility(View.INVISIBLE); } } mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade); updateTheme(); updateDozingState(); updatePublicMode(); updateStackScrollerState(goingToFullShade, fromShadeLocked); mEntryManager.updateNotifications(); checkBarModes(); updateScrimController(); updateMediaMetaData(false, mState != StatusBarState.KEYGUARD); mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(), mUnlockMethodCache.isMethodSecure(), mStatusBarKeyguardViewManager.isOccluded()); Trace.endSection(); }
Switches theme from light to dark and vice-versa.
/** * Switches theme from light to dark and vice-versa. */
protected void updateTheme() { final boolean inflated = mStackScroller != null && mStatusBarWindowManager != null; // The system wallpaper defines if QS should be light or dark. WallpaperColors systemColors = mColorExtractor .getWallpaperColors(WallpaperManager.FLAG_SYSTEM); final boolean wallpaperWantsDarkTheme = systemColors != null && (systemColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0; final Configuration config = mContext.getResources().getConfiguration(); final boolean nightModeWantsDarkTheme = DARK_THEME_IN_NIGHT_MODE && (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; final boolean useDarkTheme = wallpaperWantsDarkTheme || nightModeWantsDarkTheme; if (isUsingDarkTheme() != useDarkTheme) { mUiOffloadThread.submit(() -> { try { mOverlayManager.setEnabled("com.android.systemui.theme.dark", useDarkTheme, mLockscreenUserManager.getCurrentUserId()); } catch (RemoteException e) { Log.w(TAG, "Can't change theme", e); } }); } // Lock wallpaper defines the color of the majority of the views, hence we'll use it // to set our default theme. final boolean lockDarkText = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, true /* ignoreVisibility */).supportsDarkText(); final int themeResId = lockDarkText ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI; if (mContext.getThemeResId() != themeResId) { mContext.setTheme(themeResId); if (inflated) { onThemeChanged(); } } if (inflated) { int which; if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { which = WallpaperManager.FLAG_LOCK; } else { which = WallpaperManager.FLAG_SYSTEM; } final boolean useDarkText = mColorExtractor.getColors(which, true /* ignoreVisibility */).supportsDarkText(); mStackScroller.updateDecorViews(useDarkText); // Make sure we have the correct navbar/statusbar colors. mStatusBarWindowManager.setKeyguardDark(useDarkText); } } private void updateDozingState() { Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0); Trace.beginSection("StatusBar#updateDozingState"); boolean sleepingFromKeyguard = mStatusBarKeyguardViewManager.isGoingToSleepVisibleNotOccluded(); boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup()) || (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard); mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation); mDozeScrimController.setDozing(mDozing); mKeyguardIndicationController.setDozing(mDozing); mNotificationPanel.setDozing(mDozing, animate); updateQsExpansionEnabled(); Trace.endSection(); } public void updateStackScrollerState(boolean goingToFullShade, boolean fromShadeLocked) { if (mStackScroller == null) return; boolean onKeyguard = mState == StatusBarState.KEYGUARD; boolean publicMode = mLockscreenUserManager.isAnyProfilePublicMode(); if (mHeadsUpAppearanceController != null) { mHeadsUpAppearanceController.setPublicMode(publicMode); } mStackScroller.setHideSensitive(publicMode, goingToFullShade); mStackScroller.setDimmed(onKeyguard, fromShadeLocked /* animate */); mStackScroller.setExpandingEnabled(!onKeyguard); ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild(); mStackScroller.setActivatedChild(null); if (activatedChild != null) { activatedChild.makeInactive(false /* animate */); } } public void userActivity() { if (mState == StatusBarState.KEYGUARD) { mKeyguardViewMediatorCallback.userActivity(); } } public boolean interceptMediaKey(KeyEvent event) { return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.interceptMediaKey(event); } protected boolean shouldUnlockOnMenuPressed() { return mDeviceInteractive && mState != StatusBarState.SHADE && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed(); } public boolean onMenuPressed() { if (shouldUnlockOnMenuPressed()) { animateCollapsePanels( CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); return true; } return false; } public void endAffordanceLaunch() { releaseGestureWakeLock(); mNotificationPanel.onAffordanceLaunchEnded(); } public boolean onBackPressed() { boolean isScrimmedBouncer = mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED; if (mStatusBarKeyguardViewManager.onBackPressed(isScrimmedBouncer /* hideImmediately */)) { if (!isScrimmedBouncer) { mNotificationPanel.expandWithoutQs(); } return true; } if (mNotificationPanel.isQsExpanded()) { if (mNotificationPanel.isQsDetailShowing()) { mNotificationPanel.closeQsDetail(); } else { mNotificationPanel.animateCloseQs(); } return true; } if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) { animateCollapsePanels(); return true; } if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) { return true; } return false; } public boolean onSpacePressed() { if (mDeviceInteractive && mState != StatusBarState.SHADE) { animateCollapsePanels( CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */); return true; } return false; } private void showBouncerIfKeyguard() { if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) && !mKeyguardViewMediator.isHiding()) { showBouncer(true /* scrimmed */); } } protected void showBouncer(boolean scrimmed) { mStatusBarKeyguardViewManager.showBouncer(scrimmed); } private void instantExpandNotificationsPanel() { // Make our window larger and the panel expanded. makeExpandedVisible(true); mNotificationPanel.expand(false /* animate */); recomputeDisableFlags(false /* animate */); } private void instantCollapseNotificationPanel() { mNotificationPanel.instantCollapse(); runPostCollapseRunnables(); } @Override public void onActivated(ActivatableNotificationView view) { onActivated((View) view); mStackScroller.setActivatedChild(view); } public void onActivated(View view) { mLockscreenGestureLogger.write( MetricsEvent.ACTION_LS_NOTE, 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */); mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again); ActivatableNotificationView previousView = mStackScroller.getActivatedChild(); if (previousView != null) { previousView.makeInactive(true /* animate */); } }
Params:
/** * @param state The {@link StatusBarState} to set. */
public void setBarState(int state) { // If we're visible and switched to SHADE_LOCKED (the user dragged // down on the lockscreen), clear notification LED, vibration, // ringing. // Other transitions are covered in handleVisibleToUserChanged(). if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) { clearNotificationEffects(); } if (state == StatusBarState.KEYGUARD) { mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed(); maybeEscalateHeadsUp(); } mState = state; mGroupManager.setStatusBarState(state); mHeadsUpManager.setStatusBarState(state); mFalsingManager.setStatusBarState(state); mStatusBarWindowManager.setStatusBarState(state); mStackScroller.setStatusBarState(state); updateReportRejectedTouchVisibility(); updateDozing(); updateTheme(); touchAutoDim(); mNotificationShelf.setStatusBarState(state); } @Override public void onActivationReset(ActivatableNotificationView view) { if (view == mStackScroller.getActivatedChild()) { mStackScroller.setActivatedChild(null); onActivationReset((View)view); } } public void onActivationReset(View view) { mKeyguardIndicationController.hideTransientIndication(); } public void onTrackingStarted() { runPostCollapseRunnables(); } public void onClosingFinished() { runPostCollapseRunnables(); if (!isPresenterFullyCollapsed()) { // if we set it not to be focusable when collapsing, we have to undo it when we aborted // the closing mStatusBarWindowManager.setStatusBarFocusable(true); } } public void onUnlockHintStarted() { mFalsingManager.onUnlockHintStarted(); mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock); } public void onHintFinished() { // Delay the reset a bit so the user can read the text. mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS); } public void onCameraHintStarted() { mFalsingManager.onCameraHintStarted(); mKeyguardIndicationController.showTransientIndication(R.string.camera_hint); } public void onVoiceAssistHintStarted() { mFalsingManager.onLeftAffordanceHintStarted(); mKeyguardIndicationController.showTransientIndication(R.string.voice_hint); } public void onPhoneHintStarted() { mFalsingManager.onLeftAffordanceHintStarted(); mKeyguardIndicationController.showTransientIndication(R.string.phone_hint); } public void onTrackingStopped(boolean expand) { if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { if (!expand && !mUnlockMethodCache.canSkipBouncer()) { showBouncer(false /* scrimmed */); } } } @Override public int getMaxNotificationsWhileLocked(boolean recompute) { if (recompute) { mMaxKeyguardNotifications = Math.max(1, mNotificationPanel.computeMaxKeyguardNotifications( mMaxAllowedKeyguardNotifications)); return mMaxKeyguardNotifications; } return mMaxKeyguardNotifications; } public int getMaxNotificationsWhileLocked() { return getMaxNotificationsWhileLocked(false /* recompute */); } // TODO: Figure out way to remove these. public NavigationBarView getNavigationBarView() { return (mNavigationBar != null ? (NavigationBarView) mNavigationBar.getView() : null); } public View getNavigationBarWindow() { return mNavigationBarView; }
TODO: Remove this method. Views should not be passed forward. Will cause theme issues.
Returns:bottom area view
/** * TODO: Remove this method. Views should not be passed forward. Will cause theme issues. * @return bottom area view */
public KeyguardBottomAreaView getKeyguardBottomAreaView() { return mNotificationPanel.getKeyguardBottomAreaView(); } // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------ /* Only ever called as a consequence of a lockscreen expansion gesture. */ @Override public boolean onDraggedDown(View startingChild, int dragLengthY) { if (mState == StatusBarState.KEYGUARD && hasActiveNotifications() && (!isDozing() || isPulsing())) { mLockscreenGestureLogger.write( MetricsEvent.ACTION_LS_SHADE, (int) (dragLengthY / mDisplayMetrics.density), 0 /* velocityDp - N/A */); // We have notifications, go to locked shade. goToLockedShade(startingChild); if (startingChild instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild; row.onExpandedByGesture(true /* drag down is always an open */); } return true; } else { // abort gesture. return false; } } @Override public void onDragDownReset() { mStackScroller.setDimmed(true /* dimmed */, true /* animated */); mStackScroller.resetScrollPosition(); mStackScroller.resetCheckSnoozeLeavebehind(); } @Override public void onCrossedThreshold(boolean above) { mStackScroller.setDimmed(!above /* dimmed */, true /* animate */); } @Override public void onTouchSlopExceeded() { mStackScroller.cancelLongPress(); mStackScroller.checkSnoozeLeavebehind(); } @Override public void setEmptyDragAmount(float amount) { mNotificationPanel.setEmptyDragAmount(amount); } @Override public boolean isFalsingCheckNeeded() { return mState == StatusBarState.KEYGUARD; }
If secure with redaction: Show bouncer, go to unlocked shade.

If secure without redaction or no security: Go to StatusBarState.SHADE_LOCKED.

Params:
  • expandView – The view to expand after going to the shade.
/** * If secure with redaction: Show bouncer, go to unlocked shade. * * <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p> * * @param expandView The view to expand after going to the shade. */
public void goToLockedShade(View expandView) { if ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { return; } int userId = mLockscreenUserManager.getCurrentUserId(); ExpandableNotificationRow row = null; if (expandView instanceof ExpandableNotificationRow) { row = (ExpandableNotificationRow) expandView; row.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */); // Indicate that the group expansion is changing at this time -- this way the group // and children backgrounds / divider animations will look correct. row.setGroupExpansionChanging(true); if (row.getStatusBarNotification() != null) { userId = row.getStatusBarNotification().getUserId(); } } boolean fullShadeNeedsBouncer = !mLockscreenUserManager. userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId()) || !mLockscreenUserManager.shouldShowLockscreenNotifications() || mFalsingManager.shouldEnforceBouncer(); if (mLockscreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) { mLeaveOpenOnKeyguardHide = true; showBouncerIfKeyguard(); mDraggedDownRow = row; mPendingRemoteInputView = null; } else { mNotificationPanel.animateToFullShade(0 /* delay */); setBarState(StatusBarState.SHADE_LOCKED); updateKeyguardState(false /* goingToFullShade */, false /* fromShadeLocked */); } } public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) { mLeaveOpenOnKeyguardHide = true; dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */); } @Override public void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) { mLeaveOpenOnKeyguardHide = true; showBouncer(true /* scrimmed */); mPendingRemoteInputView = clicked; } @Override public void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row, View clickedView) { if (isKeyguardShowing()) { onLockedRemoteInput(row, clickedView); } else { row.setUserExpanded(true); row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick); } } @Override public boolean shouldHandleRemoteInput(View view, PendingIntent pendingIntent) { // Skip remote input as doing so will expand the notification shade. return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0; } @Override public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent, Intent fillInIntent, NotificationRemoteInputManager.ClickHandler defaultHandler) { final boolean isActivity = pendingIntent.isActivity(); if (isActivity) { final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( mContext, pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId()); dismissKeyguardThenExecute(() -> { try { ActivityManager.getService().resumeAppSwitches(); } catch (RemoteException e) { } boolean handled = defaultHandler.handleClick(); // close the shade if it was open if (handled && !mNotificationPanel.isFullyCollapsed()) { animateCollapsePanels( CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); visibilityChanged(false); mAssistManager.hideAssist(); // Wait for activity start. return true; } else { return false; } }, afterKeyguardGone); return true; } else { return defaultHandler.handleClick(); } } protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender, String notificationKey) { // Clear pending remote view, as we do not want to trigger pending remote input view when // it's called by other code mPendingWorkRemoteInputView = null; // Begin old BaseStatusBar.startWorkChallengeIfNecessary. final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null, userId); if (newIntent == null) { return false; } final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION); callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender); callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey); callBackIntent.setPackage(mContext.getPackageName()); PendingIntent callBackPendingIntent = PendingIntent.getBroadcast( mContext, 0, callBackIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE); newIntent.putExtra( Intent.EXTRA_INTENT, callBackPendingIntent.getIntentSender()); try { ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent, null /*options*/); } catch (RemoteException ex) { // ignore } return true; // End old BaseStatusBar.startWorkChallengeIfNecessary. } @Override public void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row, View clicked) { // Collapse notification and show work challenge animateCollapsePanels(); startWorkChallengeIfNecessary(userId, null, null); // Add pending remote input view after starting work challenge, as starting work challenge // will clear all previous pending review view mPendingWorkRemoteInputView = clicked; } @Override public void onWorkChallengeChanged() { updatePublicMode(); mEntryManager.updateNotifications(); if (mPendingWorkRemoteInputView != null && !mLockscreenUserManager.isAnyProfilePublicMode()) { // Expand notification panel and the notification row, then click on remote input view final Runnable clickPendingViewRunnable = () -> { final View pendingWorkRemoteInputView = mPendingWorkRemoteInputView; if (pendingWorkRemoteInputView == null) { return; } // Climb up the hierarchy until we get to the container for this row. ViewParent p = pendingWorkRemoteInputView.getParent(); while (!(p instanceof ExpandableNotificationRow)) { if (p == null) { return; } p = p.getParent(); } final ExpandableNotificationRow row = (ExpandableNotificationRow) p; ViewParent viewParent = row.getParent(); if (viewParent instanceof NotificationStackScrollLayout) { final NotificationStackScrollLayout scrollLayout = (NotificationStackScrollLayout) viewParent; row.makeActionsVisibile(); row.post(() -> { final Runnable finishScrollingCallback = () -> { mPendingWorkRemoteInputView.callOnClick(); mPendingWorkRemoteInputView = null; scrollLayout.setFinishScrollingCallback(null); }; if (scrollLayout.scrollTo(row)) { // It scrolls! So call it when it's finished. scrollLayout.setFinishScrollingCallback(finishScrollingCallback); } else { // It does not scroll, so call it now! finishScrollingCallback.run(); } }); } }; mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mNotificationPanel.mStatusBar.getStatusBarWindow() .getHeight() != mNotificationPanel.mStatusBar .getStatusBarHeight()) { mNotificationPanel.getViewTreeObserver() .removeOnGlobalLayoutListener(this); mNotificationPanel.post(clickPendingViewRunnable); } } }); instantExpandNotificationsPanel(); } } @Override public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) { mHeadsUpManager.setExpanded(clickedEntry, nowExpanded); if (mState == StatusBarState.KEYGUARD && nowExpanded) { goToLockedShade(clickedEntry.row); } }
Goes back to the keyguard after hanging around in StatusBarState.SHADE_LOCKED.
/** * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}. */
public void goToKeyguard() { if (mState == StatusBarState.SHADE_LOCKED) { mStackScroller.onGoToKeyguard(); setBarState(StatusBarState.KEYGUARD); updateKeyguardState(false /* goingToFullShade */, true /* fromShadeLocked*/); } } public long getKeyguardFadingAwayDelay() { return mKeyguardFadingAwayDelay; } public long getKeyguardFadingAwayDuration() { return mKeyguardFadingAwayDuration; } public void setBouncerShowing(boolean bouncerShowing) { mBouncerShowing = bouncerShowing; if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing); updateHideIconsForBouncer(true /* animate */); recomputeDisableFlags(true /* animate */); updateScrimController(); } public void cancelCurrentTouch() { if (mNotificationPanel.isTracking()) { mStatusBarWindow.cancelCurrentTouch(); if (mState == StatusBarState.SHADE) { animateCollapsePanels(); } } } final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override public void onFinishedGoingToSleep() { mNotificationPanel.onAffordanceLaunchEnded(); releaseGestureWakeLock(); mLaunchCameraOnScreenTurningOn = false; mDeviceInteractive = false; mWakeUpComingFromTouch = false; mWakeUpTouchLocation = null; mStackScroller.setAnimationsEnabled(false); mVisualStabilityManager.setScreenOn(false); updateVisibleToUser(); // We need to disable touch events because these might // collapse the panel after we expanded it, and thus we would end up with a blank // Keyguard. mNotificationPanel.setTouchDisabled(true); mStatusBarWindow.cancelCurrentTouch(); if (mLaunchCameraOnFinishedGoingToSleep) { mLaunchCameraOnFinishedGoingToSleep = false; // This gets executed before we will show Keyguard, so post it in order that the state // is correct. mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource)); } updateIsKeyguard(); } @Override public void onStartedGoingToSleep() { notifyHeadsUpGoingToSleep(); dismissVolumeDialog(); } @Override public void onStartedWakingUp() { mDeviceInteractive = true; mStackScroller.setAnimationsEnabled(true); mVisualStabilityManager.setScreenOn(true); mNotificationPanel.setTouchDisabled(false); mDozeServiceHost.stopDozing(); updateVisibleToUser(); updateIsKeyguard(); updateScrimController(); } }; final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() { @Override public void onScreenTurningOn() { mFalsingManager.onScreenTurningOn(); mNotificationPanel.onScreenTurningOn(); if (mLaunchCameraOnScreenTurningOn) { mNotificationPanel.launchCamera(false, mLastCameraLaunchSource); mLaunchCameraOnScreenTurningOn = false; } updateScrimController(); } @Override public void onScreenTurnedOn() { mScrimController.onScreenTurnedOn(); } @Override public void onScreenTurnedOff() { mFalsingManager.onScreenOff(); mScrimController.onScreenTurnedOff(); // If we pulse in from AOD, we turn the screen off first. However, updatingIsKeyguard // in that case destroys the HeadsUpManager state, so don't do it in that case. if (!isPulsing()) { updateIsKeyguard(); } } }; public int getWakefulnessState() { return mWakefulnessLifecycle.getWakefulness(); } private void vibrateForCameraGesture() { // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep. mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */); }
Returns:true if the screen is currently fully off, i.e. has finished turning off and has since not started turning on.
/** * @return true if the screen is currently fully off, i.e. has finished turning off and has * since not started turning on. */
public boolean isScreenFullyOff() { return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF; } @Override public void showScreenPinningRequest(int taskId) { if (mKeyguardMonitor.isShowing()) { // Don't allow apps to trigger this from keyguard. return; } // Show screen pinning request, since this comes from an app, show 'no thanks', button. showScreenPinningRequest(taskId, true); } public void showScreenPinningRequest(int taskId, boolean allowCancel) { mScreenPinningRequest.showPrompt(taskId, allowCancel); } public boolean hasActiveNotifications() { return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty(); } @Override public void wakeUpIfDozing(long time, View where) { if (mDozing) { PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); pm.wakeUp(time, "com.android.systemui:NODOZE"); mWakeUpComingFromTouch = true; where.getLocationInWindow(mTmpInt2); mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2, mTmpInt2[1] + where.getHeight() / 2); mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); mFalsingManager.onScreenOnFromTouch(); } } @Override public boolean isDeviceLocked(int userId) { return mKeyguardManager.isDeviceLocked(userId); } @Override public void appTransitionCancelled() { EventBus.getDefault().send(new AppTransitionFinishedEvent()); } @Override public void appTransitionFinished() { EventBus.getDefault().send(new AppTransitionFinishedEvent()); } @Override public void onCameraLaunchGestureDetected(int source) { mLastCameraLaunchSource = source; if (isGoingToSleep()) { if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera"); mLaunchCameraOnFinishedGoingToSleep = true; return; } if (!mNotificationPanel.canCameraGestureBeLaunched( mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) { if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now, mExpandedVisible: " + mExpandedVisible); return; } if (!mDeviceInteractive) { PowerManager pm = mContext.getSystemService(PowerManager.class); pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE"); mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); } vibrateForCameraGesture(); if (!mStatusBarKeyguardViewManager.isShowing()) { startActivityDismissingKeyguard(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT, false /* onlyProvisioned */, true /* dismissShade */, true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0); } else { if (!mDeviceInteractive) { // Avoid flickering of the scrim when we instant launch the camera and the bouncer // comes on. mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L); } if (isScreenTurningOnOrOn()) { if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera"); if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.reset(true /* hide */); } mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source); updateScrimController(); } else { // We need to defer the camera launch until the screen comes on, since otherwise // we will dismiss us too early since we are waiting on an activity to be drawn and // incorrectly get notified because of the screen on event (which resumes and pauses // some activities) if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Deferring until screen turns on"); mLaunchCameraOnScreenTurningOn = true; } } } boolean isCameraAllowedByAdmin() { if (mDevicePolicyManager.getCameraDisabled(null, mLockscreenUserManager.getCurrentUserId())) { return false; } else if (mStatusBarKeyguardViewManager == null || (isKeyguardShowing() && isKeyguardSecure())) { // Check if the admin has disabled the camera specifically for the keyguard return (mDevicePolicyManager. getKeyguardDisabledFeatures(null, mLockscreenUserManager.getCurrentUserId()) & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0; } return true; } private boolean isGoingToSleep() { return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; } private boolean isScreenTurningOnOrOn() { return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_ON || mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON; } public void notifyFpAuthModeChanged() { updateDozing(); updateScrimController(); } private void updateDozing() { Trace.beginSection("StatusBar#updateDozing"); // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD || mFingerprintUnlockController.getMode() == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; // When in wake-and-unlock we may not have received a change to mState // but we still should not be dozing, manually set to false. if (mFingerprintUnlockController.getMode() == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) { dozing = false; } if (mDozing != dozing) { mDozing = dozing; mKeyguardViewMediator.setAodShowing(mDozing); mStatusBarWindowManager.setDozing(mDozing); mStatusBarKeyguardViewManager.setDozing(mDozing); if (mAmbientIndicationContainer instanceof DozeReceiver) { ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing); } mEntryManager.updateNotifications(); updateDozingState(); updateReportRejectedTouchVisibility(); } Trace.endSection(); } @VisibleForTesting void updateScrimController() { Trace.beginSection("StatusBar#updateScrimController"); // We don't want to end up in KEYGUARD state when we're unlocking with // fingerprint from doze. We should cross fade directly from black. boolean wakeAndUnlocking = mFingerprintUnlockController.isWakeAndUnlock(); // Do not animate the scrim expansion when triggered by the fingerprint sensor. mScrimController.setExpansionAffectsAlpha( !mFingerprintUnlockController.isFingerprintUnlock()); boolean launchingAffordanceWithPreview = mNotificationPanel.isLaunchingAffordanceWithPreview(); mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview); if (mBouncerShowing) { // Bouncer needs the front scrim when it's on top of an activity, // tapping on a notification, editing QS or being dismissed by // FLAG_DISMISS_KEYGUARD_ACTIVITY. ScrimState state = mIsOccluded || mStatusBarKeyguardViewManager.bouncerNeedsScrimming() || mStatusBarKeyguardViewManager.willDismissWithAction() || mStatusBarKeyguardViewManager.isFullscreenBouncer() ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER; mScrimController.transitionTo(state); } else if (isInLaunchTransition() || mLaunchCameraOnScreenTurningOn || launchingAffordanceWithPreview) { mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } else if (mBrightnessMirrorVisible) { mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR); } else if (isPulsing()) { // Handled in DozeScrimController#setPulsing } else if (mDozing) { mScrimController.transitionTo(ScrimState.AOD); } else if (mIsKeyguard && !wakeAndUnlocking) { mScrimController.transitionTo(ScrimState.KEYGUARD); } else { mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } Trace.endSection(); } public boolean isKeyguardShowing() { if (mStatusBarKeyguardViewManager == null) { Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true"); return true; } return mStatusBarKeyguardViewManager.isShowing(); } private final class DozeServiceHost implements DozeHost { private final ArrayList<Callback> mCallbacks = new ArrayList<>(); private boolean mAnimateWakeup; private boolean mAnimateScreenOff; private boolean mIgnoreTouchWhilePulsing; @Override public String toString() { return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; } public void firePowerSaveChanged(boolean active) { for (Callback callback : mCallbacks) { callback.onPowerSaveChanged(active); } } public void fireNotificationHeadsUp() { for (Callback callback : mCallbacks) { callback.onNotificationHeadsUp(); } } @Override public void addCallback(@NonNull Callback callback) { mCallbacks.add(callback); } @Override public void removeCallback(@NonNull Callback callback) { mCallbacks.remove(callback); } @Override public void startDozing() { if (!mDozingRequested) { mDozingRequested = true; DozeLog.traceDozing(mContext, mDozing); updateDozing(); updateIsKeyguard(); } } @Override public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { if (reason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS) { mPowerManager.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE"); startAssist(new Bundle()); return; } mDozeScrimController.pulse(new PulseCallback() { @Override public void onPulseStarted() { callback.onPulseStarted(); if (mHeadsUpManager.hasHeadsUpNotifications()) { // Only pulse the stack scroller if there's actually something to show. // Otherwise just show the always-on screen. setPulsing(true); } } @Override public void onPulseFinished() { callback.onPulseFinished(); setPulsing(false); } private void setPulsing(boolean pulsing) { mKeyguardViewMediator.setPulsing(pulsing); mNotificationPanel.setPulsing(pulsing); mVisualStabilityManager.setPulsing(pulsing); mIgnoreTouchWhilePulsing = false; } }, reason); } @Override public void stopDozing() { if (mDozingRequested) { mDozingRequested = false; DozeLog.traceDozing(mContext, mDozing); mWakefulnessLifecycle.dispatchStartedWakingUp(); updateDozing(); } } @Override public void onIgnoreTouchWhilePulsing(boolean ignore) { if (ignore != mIgnoreTouchWhilePulsing) { DozeLog.tracePulseTouchDisabledByProx(mContext, ignore); } mIgnoreTouchWhilePulsing = ignore; if (isDozing() && ignore) { mStatusBarWindow.cancelCurrentTouch(); } } @Override public void dozeTimeTick() { mNotificationPanel.dozeTimeTick(); } @Override public boolean isPowerSaveActive() { return mBatteryController.isAodPowerSave(); } @Override public boolean isPulsingBlocked() { return mFingerprintUnlockController.getMode() == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; } @Override public boolean isProvisioned() { return mDeviceProvisionedController.isDeviceProvisioned() && mDeviceProvisionedController.isCurrentUserSetup(); } @Override public boolean isBlockingDoze() { if (mFingerprintUnlockController.hasPendingAuthentication()) { Log.i(TAG, "Blocking AOD because fingerprint has authenticated"); return true; } return false; } @Override public void startPendingIntentDismissingKeyguard(PendingIntent intent) { StatusBar.this.startPendingIntentDismissingKeyguard(intent); } @Override public void extendPulse() { mDozeScrimController.extendPulse(); } @Override public void setAnimateWakeup(boolean animateWakeup) { if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) { // Too late to change the wakeup animation. return; } mAnimateWakeup = animateWakeup; } @Override public void setAnimateScreenOff(boolean animateScreenOff) { mAnimateScreenOff = animateScreenOff; } @Override public void onDoubleTap(float screenX, float screenY) { if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2); float viewX = screenX - mTmpInt2[0]; float viewY = screenY - mTmpInt2[1]; if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth() && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) { dispatchDoubleTap(viewX, viewY); } } } @Override public void setDozeScreenBrightness(int value) { mStatusBarWindowManager.setDozeScreenBrightness(value); } @Override public void setAodDimmingScrim(float scrimOpacity) { mScrimController.setAodFrontScrimAlpha(scrimOpacity); } public void dispatchDoubleTap(float viewX, float viewY) { dispatchTap(mAmbientIndicationContainer, viewX, viewY); dispatchTap(mAmbientIndicationContainer, viewX, viewY); } private void dispatchTap(View view, float x, float y) { long now = SystemClock.elapsedRealtime(); dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN); dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP); } private void dispatchTouchEvent(View view, float x, float y, long now, int action) { MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */); view.dispatchTouchEvent(ev); ev.recycle(); } private boolean shouldAnimateWakeup() { return mAnimateWakeup; } public boolean shouldAnimateScreenOff() { return mAnimateScreenOff; } } public boolean shouldIgnoreTouch() { return isDozing() && mDozeServiceHost.mIgnoreTouchWhilePulsing; } // Begin Extra BaseStatusBar methods. protected CommandQueue mCommandQueue; protected IStatusBarService mBarService; // all notifications protected NotificationStackScrollLayout mStackScroller; protected NotificationGroupManager mGroupManager; // for heads up notifications protected HeadsUpManagerPhone mHeadsUpManager; private AboveShelfObserver mAboveShelfObserver; // handling reordering protected VisualStabilityManager mVisualStabilityManager; protected AccessibilityManager mAccessibilityManager; protected boolean mDeviceInteractive; protected boolean mVisible; // mScreenOnFromKeyguard && mVisible. private boolean mVisibleToUser; protected DevicePolicyManager mDevicePolicyManager; protected PowerManager mPowerManager; protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; protected KeyguardManager mKeyguardManager; private LockPatternUtils mLockPatternUtils; private DeviceProvisionedController mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); // UI-specific methods protected WindowManager mWindowManager; protected IWindowManager mWindowManagerService; protected Display mDisplay; protected RecentsComponent mRecents; protected NotificationShelf mNotificationShelf; protected FooterView mFooterView; protected EmptyShadeView mEmptyShadeView; protected AssistManager mAssistManager; protected boolean mVrMode; public boolean isDeviceInteractive() { return mDeviceInteractive; } @Override // NotificationData.Environment public boolean isDeviceProvisioned() { return mDeviceProvisionedController.isDeviceProvisioned(); } private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() { @Override public void onVrStateChanged(boolean enabled) { mVrMode = enabled; } }; public boolean isDeviceInVrMode() { return mVrMode; } private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) { NotificationManager noMan = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage. NOTE_HIDDEN_NOTIFICATIONS); Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); if (BANNER_ACTION_SETUP.equals(action)) { animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ); } } } }; @Override public void onNotificationClicked(StatusBarNotification sbn, ExpandableNotificationRow row) { RemoteInputController controller = mRemoteInputManager.getController(); if (controller.isRemoteInputActive(row.getEntry()) && !TextUtils.isEmpty(row.getActiveRemoteInputText())) { // We have an active remote input typed and the user clicked on the notification. // this was probably unintentional, so we're closing the edit text instead. controller.closeRemoteInputs(); return; } Notification notification = sbn.getNotification(); final PendingIntent intent = notification.contentIntent != null ? notification.contentIntent : notification.fullScreenIntent; final String notificationKey = sbn.getKey(); final boolean afterKeyguardGone = intent.isActivity() && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), mLockscreenUserManager.getCurrentUserId()); final boolean wasOccluded = mIsOccluded; dismissKeyguardThenExecute(() -> { // TODO: Some of this code may be able to move to NotificationEntryManager. if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) { // Release the HUN notification to the shade. if (isPresenterFullyCollapsed()) { HeadsUpUtil.setIsClickedHeadsUpNotification(row, true); } // // In most cases, when FLAG_AUTO_CANCEL is set, the notification will // become canceled shortly by NoMan, but we can't assume that. mHeadsUpManager.releaseImmediately(notificationKey); } StatusBarNotification parentToCancel = null; if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) { StatusBarNotification summarySbn = mGroupManager.getLogicalGroupSummary(sbn).getStatusBarNotification(); if (shouldAutoCancel(summarySbn)) { parentToCancel = summarySbn; } } final StatusBarNotification parentToCancelFinal = parentToCancel; final Runnable runnable = () -> { try { // The intent we are sending is for the application, which // won't have permission to immediately start an activity after // the user switches to home. We know it is safe to do at this // point, so make sure new activity switches are now allowed. ActivityManager.getService().resumeAppSwitches(); } catch (RemoteException e) { } int launchResult = ActivityManager.START_CANCELED; if (intent != null) { // If we are launching a work activity and require to launch // separate work challenge, we defer the activity action and cancel // notification until work challenge is unlocked. if (intent.isActivity()) { final int userId = intent.getCreatorUserHandle().getIdentifier(); if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) && mKeyguardManager.isDeviceLocked(userId)) { // TODO(b/28935539): should allow certain activities to // bypass work challenge if (startWorkChallengeIfNecessary(userId, intent.getIntentSender(), notificationKey)) { // Show work challenge, do not run PendingIntent and // remove notification collapseOnMainThread(); return; } } } Intent fillInIntent = null; Entry entry = row.getEntry(); CharSequence remoteInputText = null; if (!TextUtils.isEmpty(entry.remoteInputText)) { remoteInputText = entry.remoteInputText; } if (!TextUtils.isEmpty(remoteInputText) && !controller.isSpinning(entry.key)) { fillInIntent = new Intent().putExtra(Notification.EXTRA_REMOTE_INPUT_DRAFT, remoteInputText.toString()); } RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation( row, wasOccluded); try { if (adapter != null) { ActivityManager.getService() .registerRemoteAnimationForNextActivityStart( intent.getCreatorPackage(), adapter); } launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null, null, null, getActivityOptions(adapter)); mActivityLaunchAnimator.setLaunchResult(launchResult); } catch (RemoteException | PendingIntent.CanceledException e) { // the stack trace isn't very helpful here. // Just log the exception message. Log.w(TAG, "Sending contentIntent failed: " + e); // TODO: Dismiss Keyguard. } if (intent.isActivity()) { mAssistManager.hideAssist(); } } if (shouldCollapse()) { collapseOnMainThread(); } final int count = mEntryManager.getNotificationData().getActiveNotifications().size(); final int rank = mEntryManager.getNotificationData().getRank(notificationKey); final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey, rank, count, true); try { mBarService.onNotificationClick(notificationKey, nv); } catch (RemoteException ex) { // system process is dead if we're here. } if (parentToCancelFinal != null) { removeNotification(parentToCancelFinal); } if (shouldAutoCancel(sbn) || mEntryManager.isNotificationKeptForRemoteInput(notificationKey)) { // Automatically remove all notifications that we may have kept around longer removeNotification(sbn); } }; if (mStatusBarKeyguardViewManager.isShowing() && mStatusBarKeyguardViewManager.isOccluded()) { mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable); collapsePanel(true /* animate */); } else { new Thread(runnable).start(); } return !mNotificationPanel.isFullyCollapsed(); }, afterKeyguardGone); } private void collapseOnMainThread() { if (Looper.getMainLooper().isCurrentThread()) { collapsePanel(); } else { mStackScroller.post(this::collapsePanel); } } private boolean shouldCollapse() { return mState != StatusBarState.SHADE || !mActivityLaunchAnimator.isAnimationPending(); } public void collapsePanel(boolean animate) { if (animate) { collapsePanel(); } else if (!isPresenterFullyCollapsed()) { instantCollapseNotificationPanel(); visibilityChanged(false); } else { runPostCollapseRunnables(); } } private boolean collapsePanel() { if (!mNotificationPanel.isFullyCollapsed()) { // close the shade if it was open animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */, true /* delayed */); visibilityChanged(false); return true; } else { return false; } } private void removeNotification(StatusBarNotification notification) { // We have to post it to the UI thread for synchronization mHandler.post(() -> { Runnable removeRunnable = () -> mEntryManager.performRemoveNotification(notification); if (isCollapsing()) { // To avoid lags we're only performing the remove // after the shade was collapsed addPostCollapseAction(removeRunnable); } else { removeRunnable.run(); } }); } protected NotificationListener mNotificationListener; @Override // NotificationData.Environment public boolean isNotificationForCurrentProfiles(StatusBarNotification n) { final int notificationUserId = n.getUserId(); if (DEBUG && MULTIUSER_DEBUG) { Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d", n, mLockscreenUserManager.getCurrentUserId(), notificationUserId)); } return mLockscreenUserManager.isCurrentProfile(notificationUserId); } @Override public NotificationGroupManager getGroupManager() { return mGroupManager; } @Override public void startNotificationGutsIntent(final Intent intent, final int appUid, ExpandableNotificationRow row) { dismissKeyguardThenExecute(() -> { AsyncTask.execute(() -> { int launchResult = TaskStackBuilder.create(mContext) .addNextIntentWithParentStack(intent) .startActivities(getActivityOptions( mActivityLaunchAnimator.getLaunchAnimation(row, mIsOccluded)), new UserHandle(UserHandle.getUserId(appUid))); mActivityLaunchAnimator.setLaunchResult(launchResult); if (shouldCollapse()) { // Putting it back on the main thread, since we're touching views mStatusBarWindow.post(() -> animateCollapsePanels( CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */)); } }); return true; }, false /* afterKeyguardGone */); } public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) { if (snoozeOption.getSnoozeCriterion() != null) { mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.getSnoozeCriterion().getId()); } else { mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.getMinutesToSnoozeFor() * 60 * 1000); } } @Override public void toggleSplitScreen() { toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */); } void awakenDreams() { SystemServicesProxy.getInstance(mContext).awakenDreamsAsync(); } @Override public void preloadRecentApps() { int msg = MSG_PRELOAD_RECENT_APPS; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); } @Override public void cancelPreloadRecentApps() { int msg = MSG_CANCEL_PRELOAD_RECENT_APPS; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); } @Override public void dismissKeyboardShortcutsMenu() { int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU; mHandler.removeMessages(msg); mHandler.sendEmptyMessage(msg); } @Override public void toggleKeyboardShortcutsMenu(int deviceId) { int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU; mHandler.removeMessages(msg); mHandler.obtainMessage(msg, deviceId, 0).sendToTarget(); } @Override public void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { mTopHidesStatusBar = topAppHidesStatusBar; if (!topAppHidesStatusBar && mWereIconsJustHidden) { // Immediately update the icon hidden state, since that should only apply if we're // staying fullscreen. mWereIconsJustHidden = false; recomputeDisableFlags(true); } updateHideIconsForBouncer(true /* animate */); } protected void toggleKeyboardShortcuts(int deviceId) { KeyboardShortcuts.toggle(mContext, deviceId); } protected void dismissKeyboardShortcuts() { KeyboardShortcuts.dismiss(); } @Override // NotificationData.Environment public boolean shouldHideNotifications(int userId) { return mLockscreenUserManager.shouldHideNotifications(userId); } @Override // NotificationDate.Environment public boolean shouldHideNotifications(String key) { return mLockscreenUserManager.shouldHideNotifications(key); }
Returns true if we're on a secure lockscreen.
/** * Returns true if we're on a secure lockscreen. */
@Override // NotificationData.Environment public boolean isSecurelyLocked(int userId) { return mLockscreenUserManager.isLockscreenPublicMode(userId); }
Called when the notification panel layouts
/** * Called when the notification panel layouts */
public void onPanelLaidOut() { updateKeyguardMaxNotifications(); } public void updateKeyguardMaxNotifications() { if (mState == StatusBarState.KEYGUARD) { // Since the number of notifications is determined based on the height of the view, we // need to update them. int maxBefore = getMaxNotificationsWhileLocked(false /* recompute */); int maxNotifications = getMaxNotificationsWhileLocked(true /* recompute */); if (maxBefore != maxNotifications) { mViewHierarchyManager.updateRowStates(); } } } public void startPendingIntentDismissingKeyguard(final PendingIntent intent) { if (!isDeviceProvisioned()) return; final boolean afterKeyguardGone = intent.isActivity() && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(), mLockscreenUserManager.getCurrentUserId()); dismissKeyguardThenExecute(() -> { new Thread(() -> { try { // The intent we are sending is for the application, which // won't have permission to immediately start an activity after // the user switches to home. We know it is safe to do at this // point, so make sure new activity switches are now allowed. ActivityManager.getService().resumeAppSwitches(); } catch (RemoteException e) { } try { intent.send(null, 0, null, null, null, null, getActivityOptions( null /* animationAdapter */)); } catch (PendingIntent.CanceledException e) { // the stack trace isn't very helpful here. // Just log the exception message. Log.w(TAG, "Sending intent failed: " + e); // TODO: Dismiss Keyguard. } if (intent.isActivity()) { mAssistManager.hideAssist(); } }).start(); return collapsePanel(); }, afterKeyguardGone); } private boolean shouldAutoCancel(StatusBarNotification sbn) { int flags = sbn.getNotification().flags; if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) { return false; } if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) { return false; } return true; } protected Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) { ActivityOptions options; if (animationAdapter != null) { options = ActivityOptions.makeRemoteAnimation(animationAdapter); } else { options = ActivityOptions.makeBasic(); } // Anything launched from the notification shade should always go into the secondary // split-screen windowing mode. options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY); return options.toBundle(); } protected void visibilityChanged(boolean visible) { if (mVisible != visible) { mVisible = visible; if (!visible) { mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */, true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */); } } updateVisibleToUser(); } protected void updateVisibleToUser() { boolean oldVisibleToUser = mVisibleToUser; mVisibleToUser = mVisible && mDeviceInteractive; if (oldVisibleToUser != mVisibleToUser) { handleVisibleToUserChanged(mVisibleToUser); } }
Clear Buzz/Beep/Blink.
/** * Clear Buzz/Beep/Blink. */
public void clearNotificationEffects() { try { mBarService.clearNotificationEffects(); } catch (RemoteException e) { // Won't fail unless the world has ended. } }
Updates expanded, dimmed and locked states of notification rows.
/** * Updates expanded, dimmed and locked states of notification rows. */
@Override public void onUpdateRowStates() { // The following views will be moved to the end of mStackScroller. This counter represents // the offset from the last child. Initialized to 1 for the very last position. It is post- // incremented in the following "changeViewPosition" calls so that its value is correct for // subsequent calls. int offsetFromEnd = 1; if (mFooterView != null) { mStackScroller.changeViewPosition(mFooterView, mStackScroller.getChildCount() - offsetFromEnd++); } mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - offsetFromEnd++); // No post-increment for this call because it is the last one. Make sure to add one if // another "changeViewPosition" call is ever added. mStackScroller.changeViewPosition(mNotificationShelf, mStackScroller.getChildCount() - offsetFromEnd); // Scrim opacity varies based on notification count mScrimController.setNotificationCount(mStackScroller.getNotGoneChildCount()); } protected void notifyHeadsUpGoingToSleep() { maybeEscalateHeadsUp(); }
Returns:Whether the security bouncer from Keyguard is showing.
/** * @return Whether the security bouncer from Keyguard is showing. */
public boolean isBouncerShowing() { return mBouncerShowing; }
Returns:a PackageManger for userId or if userId is < 0 (USER_ALL etc) then return PackageManager for mContext
/** * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then * return PackageManager for mContext */
public static PackageManager getPackageManagerForUser(Context context, int userId) { Context contextForUser = context; // UserHandle defines special userId as negative values, e.g. USER_ALL if (userId >= 0) { try { // Create a context for the correct user so if a package isn't installed // for user 0 we can still load information about the package. contextForUser = context.createPackageContextAsUser(context.getPackageName(), Context.CONTEXT_RESTRICTED, new UserHandle(userId)); } catch (NameNotFoundException e) { // Shouldn't fail to find the package name for system ui. } } return contextForUser.getPackageManager(); } public boolean isKeyguardSecure() { if (mStatusBarKeyguardViewManager == null) { // startKeyguard() hasn't been called yet, so we don't know. // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this // value onVisibilityChanged(). Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false", new Throwable()); return false; } return mStatusBarKeyguardViewManager.isSecure(); } @Override public void onZenChanged(int zen) { updateEmptyShadeView(); } @Override public void showAssistDisclosure() { if (mAssistManager != null) { mAssistManager.showDisclosure(); } } public NotificationPanelView getPanel() { return mNotificationPanel; } @Override public void startAssist(Bundle args) { if (mAssistManager != null) { mAssistManager.startAssist(args); } } // End Extra BaseStatusBarMethods. private final Runnable mAutoDim = () -> { if (mNavigationBar != null) { mNavigationBar.getBarTransitions().setAutoDim(true); } }; public NotificationGutsManager getGutsManager() { return mGutsManager; } @Override public boolean isPresenterLocked() { return mState == StatusBarState.KEYGUARD; } @Override public Handler getHandler() { return mHandler; } private final NotificationInfo.CheckSaveListener mCheckSaveListener = (Runnable saveImportance, StatusBarNotification sbn) -> { // If the user has security enabled, show challenge if the setting is changed. if (mLockscreenUserManager.isLockscreenPublicMode(sbn.getUser().getIdentifier()) && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) { onLockedNotificationImportanceChange(() -> { saveImportance.run(); return true; }); } else { saveImportance.run(); } }; }