Revert "Refactor PanelView and NotificationPanelView into Controllers."
Revert "NoticationPanelView now has a controller."
Revert submission 9930899-b141751146-npv-controller
Reason for revert: b/147295216
Reverted Changes:
I9a92cad63: Refactor PanelView and NotificationPanelView into ...
I454bc4790: NoticationPanelView now has a controller.
Change-Id: Iae9db40e9385e1b88bd2f5f162a5f6d53d91878d
diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java
index 67cfc3a..27c2478 100644
--- a/core/java/com/android/internal/util/LatencyTracker.java
+++ b/core/java/com/android/internal/util/LatencyTracker.java
@@ -121,11 +121,7 @@
}
public static boolean isEnabled(Context ctx) {
- return getInstance(ctx).isEnabled();
- }
-
- public boolean isEnabled() {
- return Build.IS_DEBUGGABLE && mEnabled;
+ return Build.IS_DEBUGGABLE && getInstance(ctx).mEnabled;
}
/**
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
index 0b34626..37cd1d4 100644
--- a/packages/CarSystemUI/res/layout/super_status_bar.xml
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -93,7 +93,7 @@
android:layout_height="match_parent"
android:visibility="invisible"/>
- <include layout="@layout/status_bar_expanded"
+ <ViewStub android:id="@+id/status_bar_expanded"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 3c3ebe2..77db54c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -128,11 +128,11 @@
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarComponent;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -465,7 +465,7 @@
super.start();
- mNotificationPanelViewController.setScrollingEnabled(true);
+ mNotificationPanel.setScrollingEnabled(true);
mSettleOpenPercentage = mContext.getResources().getInteger(
R.integer.notification_settle_open_percentage);
mSettleClosePercentage = mContext.getResources().getInteger(
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index a1eccce..1ebaef7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -86,11 +86,11 @@
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBarComponent;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 479f255..4869be1 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -17,14 +17,9 @@
*/
-->
-
-<com.android.systemui.statusbar.phone.NotificationPanelView
+<merge
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:id="@+id/notification_panel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/transparent">
+ xmlns:systemui="http://schemas.android.com/apk/res-auto">
<FrameLayout
android:id="@+id/big_clock_container"
android:layout_width="match_parent"
@@ -102,4 +97,4 @@
android:background="@drawable/qs_navbar_scrim" />
<include layout="@layout/status_bar_expanded_plugin_frame"/>
-</com.android.systemui.statusbar.phone.NotificationPanelView>
+</merge>
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 9716a00..57834da 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -64,7 +64,7 @@
sysui:ignoreRightInset="true"
/>
- <include layout="@layout/status_bar_expanded"
+ <ViewStub android:id="@+id/status_bar_expanded"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index bb12b53..0b73ab6 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -45,7 +45,6 @@
import com.android.internal.util.LatencyTracker;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.PackageManagerWrapper;
@@ -73,19 +72,6 @@
@Provides
@Singleton
- static ActivityManager provideActivityManager(Context context) {
- return context.getSystemService(ActivityManager.class);
- }
-
-
- @Provides
- @DisplayId
- static int provideDisplayId(Context context) {
- return context.getDisplayId();
- }
-
- @Provides
- @Singleton
static DevicePolicyManager provideDevicePolicyManager(Context context) {
return context.getSystemService(DevicePolicyManager.class);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 58ddda9..442313d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -35,7 +35,7 @@
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.StatusBarComponent;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.concurrency.ConcurrencyModule;
import com.android.systemui.util.sensors.AsyncSensorManager;
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/DisplayId.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/DisplayId.java
deleted file mode 100644
index 155a6d2..0000000
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/DisplayId.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2019 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.dagger.qualifiers;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface DisplayId {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c1934c6..9fcf022 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -86,7 +86,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
@@ -2102,7 +2102,7 @@
}
public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
- ViewGroup container, NotificationPanelViewController panelView,
+ ViewGroup container, NotificationPanelView panelView,
BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer,
View notificationContainer, KeyguardBypassController bypassController) {
mStatusBarKeyguardViewManagerLazy.get().registerStatusBar(statusBar, container, panelView,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
index 12749fd..525b5b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
@@ -368,14 +368,13 @@
public static class Builder {
private final DisplayMetrics mDisplayMetrics;
float mMaxLengthSeconds;
- float mSpeedUpFactor;
- float mX2;
- float mY2;
+ float mSpeedUpFactor = 0.0f;
+ float mX2 = -1.0f;
+ float mY2 = 1.0f;
@Inject
public Builder(DisplayMetrics displayMetrics) {
mDisplayMetrics = displayMetrics;
- reset();
}
public Builder setMaxLengthSeconds(float maxLengthSeconds) {
@@ -398,15 +397,6 @@
return this;
}
- public Builder reset() {
- mMaxLengthSeconds = 0;
- mSpeedUpFactor = 0.0f;
- mX2 = -1.0f;
- mY2 = 1.0f;
-
- return this;
- }
-
public FlingAnimationUtils build() {
return new FlingAnimationUtils(mDisplayMetrics, mMaxLengthSeconds, mSpeedUpFactor,
mX2, mY2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 6660569..9b31234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -37,7 +37,7 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
/**
@@ -53,7 +53,7 @@
CollapsedStatusBarFragment.FADE_IN_DURATION - CollapsedStatusBarFragment.FADE_IN_DELAY
- 16;
private static final long LAUNCH_TIMEOUT = 500;
- private final NotificationPanelViewController mNotificationPanel;
+ private final NotificationPanelView mNotificationPanel;
private final NotificationListContainer mNotificationContainer;
private final float mWindowCornerRadius;
private final StatusBarWindowViewController mStatusBarWindowViewController;
@@ -69,7 +69,7 @@
public ActivityLaunchAnimator(
StatusBarWindowViewController statusBarWindowViewController,
Callback callback,
- NotificationPanelViewController notificationPanel,
+ NotificationPanelView notificationPanel,
NotificationListContainer container) {
mNotificationPanel = notificationPanel;
mNotificationContainer = container;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 823dd5a..71342c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -134,7 +134,7 @@
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -496,7 +496,8 @@
protected boolean mClearAllEnabled;
private Interpolator mHideXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
- private NotificationPanelViewController mNotificationPanelController;
+ private NotificationPanelView mNotificationPanel;
+ private final ShadeController mShadeController = Dependency.get(ShadeController.class);
private final NotificationGutsManager mNotificationGutsManager;
private final NotificationSectionsManager mSectionsManager;
@@ -5518,8 +5519,7 @@
if (viewsToRemove.isEmpty()) {
if (closeShade) {
- Dependency.get(ShadeController.class).animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_NONE);
+ mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
}
return;
}
@@ -5577,12 +5577,11 @@
final Runnable onSlideAwayAnimationComplete = () -> {
if (closeShade) {
- Dependency.get(ShadeController.class).addPostCollapseAction(() -> {
+ mShadeController.addPostCollapseAction(() -> {
setDismissAllInProgress(false);
onAnimationComplete.run();
});
- Dependency.get(ShadeController.class).animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_NONE);
+ mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
} else {
setDismissAllInProgress(false);
onAnimationComplete.run();
@@ -5658,9 +5657,8 @@
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setNotificationPanelController(
- NotificationPanelViewController notificationPanelViewController) {
- mNotificationPanelController = notificationPanelViewController;
+ public void setNotificationPanel(NotificationPanelView notificationPanelView) {
+ mNotificationPanel = notificationPanelView;
}
public void updateIconAreaViews() {
@@ -6404,7 +6402,7 @@
if (!mAmbientState.isDozing() || startingChild != null) {
// We have notifications, go to locked shade.
- Dependency.get(ShadeController.class).goToLockedShade(startingChild);
+ mShadeController.goToLockedShade(startingChild);
if (startingChild instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
row.onExpandedByGesture(true /* drag down is always an open */);
@@ -6443,7 +6441,7 @@
@Override
public void setEmptyDragAmount(float amount) {
- mNotificationPanelController.setEmptyDragAmount(amount);
+ mNotificationPanel.setEmptyDragAmount(amount);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index e03db2c..8b31da4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -230,7 +230,7 @@
// The shelf will be hidden when dozing with a custom clock, we must show notification
// icons in this occasion.
if (mStatusBarStateController.isDozing()
- && mStatusBarComponent.getPanelController().hasCustomClock()) {
+ && mStatusBarComponent.getPanel().hasCustomClock()) {
state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 86f621b..09ebb64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -92,7 +92,7 @@
private final LockscreenLockIconController mLockscreenLockIconController;
private NotificationIconAreaController mNotificationIconAreaController;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- private NotificationPanelViewController mNotificationPanel;
+ private NotificationPanelView mNotificationPanel;
private View mAmbientIndicationContainer;
private StatusBar mStatusBar;
@@ -142,7 +142,7 @@
NotificationIconAreaController notificationIconAreaController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
StatusBarWindowViewController statusBarWindowViewController,
- NotificationPanelViewController notificationPanel, View ambientIndicationContainer) {
+ NotificationPanelView notificationPanel, View ambientIndicationContainer) {
mStatusBar = statusBar;
mNotificationIconAreaController = notificationIconAreaController;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 7b20a7b..8e5a912 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -58,7 +58,7 @@
private final View mClockView;
private final View mOperatorNameView;
private final DarkIconDispatcher mDarkIconDispatcher;
- private final NotificationPanelViewController mNotificationPanelViewController;
+ private final NotificationPanelView mPanelView;
private final Consumer<ExpandableNotificationRow>
mSetTrackingHeadsUp = this::setTrackingHeadsUp;
private final Runnable mUpdatePanelTranslation = this::updatePanelTranslation;
@@ -96,14 +96,13 @@
SysuiStatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController,
KeyguardStateController keyguardStateController,
- NotificationWakeUpCoordinator wakeUpCoordinator, CommandQueue commandQueue,
- NotificationPanelViewController notificationPanelViewController) {
+ NotificationWakeUpCoordinator wakeUpCoordinator, CommandQueue commandQueue) {
this(notificationIconAreaController, headsUpManager, statusBarStateController,
keyguardBypassController, wakeUpCoordinator, keyguardStateController,
commandQueue,
statusbarView.findViewById(R.id.heads_up_status_bar_view),
statusbarView.findViewById(R.id.notification_stack_scroller),
- notificationPanelViewController,
+ statusbarView.findViewById(R.id.notification_panel),
statusbarView.findViewById(R.id.clock),
statusbarView.findViewById(R.id.operator_name_frame),
statusbarView.findViewById(R.id.centered_icon_area));
@@ -120,7 +119,7 @@
CommandQueue commandQueue,
HeadsUpStatusBarView headsUpStatusBarView,
NotificationStackScrollLayout stackScroller,
- NotificationPanelViewController notificationPanelViewController,
+ NotificationPanelView panelView,
View clockView,
View operatorNameView,
View centeredIconView) {
@@ -132,10 +131,10 @@
headsUpStatusBarView.setOnDrawingRectChangedListener(
() -> updateIsolatedIconLocation(true /* requireUpdate */));
mStackScroller = stackScroller;
- mNotificationPanelViewController = notificationPanelViewController;
- notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
- notificationPanelViewController.addVerticalTranslationListener(mUpdatePanelTranslation);
- notificationPanelViewController.setHeadsUpAppearanceController(this);
+ mPanelView = panelView;
+ panelView.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
+ panelView.addVerticalTranslationListener(mUpdatePanelTranslation);
+ panelView.setHeadsUpAppearanceController(this);
mStackScroller.addOnExpandedHeightChangedListener(mSetExpandedHeight);
mStackScroller.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
mStackScroller.setHeadsUpAppearanceController(this);
@@ -170,9 +169,9 @@
mHeadsUpManager.removeListener(this);
mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null);
mWakeUpCoordinator.removeListener(this);
- mNotificationPanelViewController.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
- mNotificationPanelViewController.removeVerticalTranslationListener(mUpdatePanelTranslation);
- mNotificationPanelViewController.setHeadsUpAppearanceController(null);
+ mPanelView.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
+ mPanelView.removeVerticalTranslationListener(mUpdatePanelTranslation);
+ mPanelView.setHeadsUpAppearanceController(null);
mStackScroller.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
mStackScroller.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener);
mDarkIconDispatcher.removeDarkReceiver(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index c282cb8..ac06d9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -39,12 +39,12 @@
private boolean mTouchingHeadsUpView;
private boolean mTrackingHeadsUp;
private boolean mCollapseSnoozes;
- private NotificationPanelViewController mPanel;
+ private NotificationPanelView mPanel;
private ExpandableNotificationRow mPickedChild;
public HeadsUpTouchHelper(HeadsUpManagerPhone headsUpManager,
Callback callback,
- NotificationPanelViewController notificationPanelView) {
+ NotificationPanelView notificationPanelView) {
mHeadsUpManager = headsUpManager;
mCallback = callback;
mPanel = notificationPanelView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index d3e44ea..d95d2b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -155,6 +155,7 @@
};
private boolean mLeftIsVoiceAssist;
+ private AssistManager mAssistManager;
private Drawable mLeftAssistIcon;
private IntentButton mRightButton = new DefaultRightButton();
@@ -253,6 +254,7 @@
mActivityStarter = Dependency.get(ActivityStarter.class);
mFlashlightController = Dependency.get(FlashlightController.class);
mAccessibilityController = Dependency.get(AccessibilityController.class);
+ mAssistManager = Dependency.get(AssistManager.class);
mActivityIntentHelper = new ActivityIntentHelper(getContext());
updateLeftAffordance();
}
@@ -549,7 +551,7 @@
Runnable runnable = new Runnable() {
@Override
public void run() {
- Dependency.get(AssistManager.class).launchVoiceAssistFromKeyguard();
+ mAssistManager.launchVoiceAssistFromKeyguard();
}
};
if (!mKeyguardStateController.canDismissLockScreen()) {
@@ -563,7 +565,7 @@
}
private boolean canLaunchVoiceAssist() {
- return Dependency.get(AssistManager.class).canVoiceAssistBeLaunchedFromKeyguard();
+ return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard();
}
private void launchPhone() {
@@ -645,7 +647,7 @@
}
if (mLeftIsVoiceAssist) {
mLeftPreview = mPreviewInflater.inflatePreviewFromService(
- Dependency.get(AssistManager.class).getVoiceInteractorComponentName());
+ mAssistManager.getVoiceInteractorComponentName());
} else {
mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index a3f14ba..4e91e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -90,7 +90,7 @@
private int mContainerTopPadding;
/**
- * @see NotificationPanelViewController#getExpandedFraction()
+ * @see NotificationPanelView#getExpandedFraction()
*/
private float mPanelExpansion;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index a3b1b5f..d4cf272 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -350,7 +350,7 @@
mIsOnDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
}
- mNavigationBarView.setComponents(mStatusBarLazy.get().getPanelController());
+ mNavigationBarView.setComponents(mStatusBarLazy.get().getPanel(), mAssistManager);
mNavigationBarView.setDisabledFlags(mDisabledFlags1);
mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index ba9ba6c..5a1b20d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -67,6 +67,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.assist.AssistHandleViewController;
+import com.android.systemui.assist.AssistManager;
import com.android.systemui.model.SysUiState;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
@@ -147,7 +148,7 @@
private NavigationBarInflaterView mNavigationInflaterView;
private RecentsOnboarding mRecentsOnboarding;
- private NotificationPanelViewController mPanelView;
+ private NotificationPanelView mPanelView;
private FloatingRotationButton mFloatingRotationButton;
private RotationButtonController mRotationButtonController;
@@ -348,7 +349,7 @@
return mBarTransitions.getLightTransitionsController();
}
- public void setComponents(NotificationPanelViewController panel) {
+ public void setComponents(NotificationPanelView panel, AssistManager assistManager) {
mPanelView = panel;
updatePanelSystemUiStateFlags();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 9dc8fbf..c74286d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -16,17 +16,118 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.app.Fragment;
+import android.app.StatusBarManager;
import android.content.Context;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.hardware.biometrics.BiometricSourceType;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardStatusView;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.HomeControlsPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.KeyguardAffordanceView;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.AnimatableProperty;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.stack.AnimationProperties;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
+import com.android.systemui.util.Utils;
-public class NotificationPanelView extends PanelView {
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+public class NotificationPanelView extends PanelView implements
+ ExpandableView.OnHeightChangedListener,
+ View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
+ KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
+ OnHeadsUpChangedListener, QS.HeightListener, ZenModeController.Callback,
+ ConfigurationController.ConfigurationListener, StateListener,
+ PulseExpansionHandler.ExpansionCallback, DynamicPrivacyController.Listener,
+ NotificationWakeUpCoordinator.WakeUpListener {
private static final boolean DEBUG = false;
@@ -35,26 +136,2542 @@
*/
public static final int FLING_EXPAND = 0;
+ /**
+ * Fling collapsing QS, potentially stopping when QS becomes QQS.
+ */
+ public static final int FLING_COLLAPSE = 1;
+
+ /**
+ * Fling until QS is completely hidden.
+ */
+ public static final int FLING_HIDE = 2;
+ private final DozeParameters mDozeParameters;
+
+ private double mQqsSplitFraction;
+
+ // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
+ // changed.
+ private static final int CAP_HEIGHT = 1456;
+ private static final int FONT_HEIGHT = 2163;
+
+ /**
+ * Maximum time before which we will expand the panel even for slow motions when getting a
+ * touch passed over from launcher.
+ */
+ private static final int MAX_TIME_TO_OPEN_WHEN_FLINGING_FROM_LAUNCHER = 300;
+
static final String COUNTER_PANEL_OPEN = "panel_open";
static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
+ private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek";
+
+ private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1);
+ private static final Rect mEmptyRect = new Rect();
+
+ private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties()
+ .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ private static final AnimatableProperty KEYGUARD_HEADS_UP_SHOWING_AMOUNT
+ = AnimatableProperty.from("KEYGUARD_HEADS_UP_SHOWING_AMOUNT",
+ NotificationPanelView::setKeyguardHeadsUpShowingAmount,
+ NotificationPanelView::getKeyguardHeadsUpShowingAmount,
+ R.id.keyguard_hun_animator_tag,
+ R.id.keyguard_hun_animator_end_tag,
+ R.id.keyguard_hun_animator_start_tag);
+ private static final AnimationProperties KEYGUARD_HUN_PROPERTIES =
+ new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ @VisibleForTesting
+ final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+
+ @Override
+ public void onBiometricAuthenticated(int userId,
+ BiometricSourceType biometricSourceType) {
+ if (mFirstBypassAttempt && mUpdateMonitor.isUnlockingWithBiometricAllowed()) {
+ mDelayShowingKeyguardStatusBar = true;
+ }
+ }
+
+ @Override
+ public void onBiometricRunningStateChanged(boolean running,
+ BiometricSourceType biometricSourceType) {
+ boolean keyguardOrShadeLocked = mBarState == StatusBarState.KEYGUARD
+ || mBarState == StatusBarState.SHADE_LOCKED;
+ if (!running && mFirstBypassAttempt && keyguardOrShadeLocked && !mDozing
+ && !mDelayShowingKeyguardStatusBar) {
+ mFirstBypassAttempt = false;
+ animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ }
+ }
+
+ @Override
+ public void onFinishedGoingToSleep(int why) {
+ mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
+ mDelayShowingKeyguardStatusBar = false;
+ }
+ };
+ private final KeyguardStateController.Callback mKeyguardMonitorCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onKeyguardFadingAwayChanged() {
+ if (!mKeyguardStateController.isKeyguardFadingAway()) {
+ mFirstBypassAttempt = false;
+ mDelayShowingKeyguardStatusBar = false;
+ }
+ }
+ };
+
+ private final InjectionInflationController mInjectionInflationController;
+ private final PowerManager mPowerManager;
+ private final AccessibilityManager mAccessibilityManager;
+ private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+ private final PulseExpansionHandler mPulseExpansionHandler;
+ private final KeyguardBypassController mKeyguardBypassController;
+ private final KeyguardUpdateMonitor mUpdateMonitor;
@VisibleForTesting
protected KeyguardAffordanceHelper mAffordanceHelper;
+ private KeyguardUserSwitcher mKeyguardUserSwitcher;
+ @VisibleForTesting
+ protected KeyguardStatusBarView mKeyguardStatusBar;
+ @VisibleForTesting
+ protected ViewGroup mBigClockContainer;
+ private QS mQs;
+ @VisibleForTesting
+ protected FrameLayout mQsFrame;
+ @VisibleForTesting
+ protected KeyguardStatusView mKeyguardStatusView;
+ private View mQsNavbarScrim;
+ protected NotificationsQuickSettingsContainer mNotificationContainerParent;
+ protected NotificationStackScrollLayout mNotificationStackScroller;
+ protected FrameLayout mHomeControlsLayout;
+ private boolean mAnimateNextPositionUpdate;
+ private int mTrackingPointer;
+ private VelocityTracker mQsVelocityTracker;
+ private boolean mQsTracking;
+
+ /**
+ * If set, the ongoing touch gesture might both trigger the expansion in {@link PanelView} and
+ * the expansion for quick settings.
+ */
+ private boolean mConflictingQsExpansionGesture;
+
+ /**
+ * Whether we are currently handling a motion gesture in #onInterceptTouchEvent, but haven't
+ * intercepted yet.
+ */
+ private boolean mIntercepting;
+ private boolean mPanelExpanded;
+ private boolean mQsExpanded;
+ private boolean mQsExpandedWhenExpandingStarted;
+ private boolean mQsFullyExpanded;
+ private boolean mKeyguardShowing;
+ private boolean mDozing;
+ private boolean mDozingOnDown;
+ protected int mBarState;
+ private float mInitialHeightOnTouch;
+ private float mInitialTouchX;
+ private float mInitialTouchY;
+ private float mLastTouchX;
+ private float mLastTouchY;
+ protected float mQsExpansionHeight;
+ protected int mQsMinExpansionHeight;
+ protected int mQsMaxExpansionHeight;
+ private int mQsPeekHeight;
+ private boolean mStackScrollerOverscrolling;
+ private boolean mQsExpansionFromOverscroll;
+ private float mLastOverscroll;
+ protected boolean mQsExpansionEnabled = true;
+ private ValueAnimator mQsExpansionAnimator;
+ private FlingAnimationUtils mFlingAnimationUtils;
+ private int mStatusBarMinHeight;
+ private int mNotificationsHeaderCollideDistance;
+ private int mUnlockMoveDistance;
+ private float mEmptyDragAmount;
+ private float mDownX;
+ private float mDownY;
+
+ private final KeyguardClockPositionAlgorithm mClockPositionAlgorithm =
+ new KeyguardClockPositionAlgorithm();
+ private final KeyguardClockPositionAlgorithm.Result mClockPositionResult =
+ new KeyguardClockPositionAlgorithm.Result();
+ private boolean mIsExpanding;
+
+ private boolean mBlockTouches;
+ // Used for two finger gesture as well as accessibility shortcut to QS.
+ private boolean mQsExpandImmediate;
+ private boolean mTwoFingerQsExpandPossible;
+
+ /**
+ * If we are in a panel collapsing motion, we reset scrollY of our scroll view but still
+ * need to take this into account in our panel height calculation.
+ */
+ private boolean mQsAnimatorExpand;
+ private boolean mIsLaunchTransitionFinished;
+ private boolean mIsLaunchTransitionRunning;
+ private Runnable mLaunchAnimationEndRunnable;
+ private boolean mOnlyAffordanceInThisMotion;
+ private boolean mKeyguardStatusViewAnimating;
+ private ValueAnimator mQsSizeChangeAnimator;
+
+ private boolean mShowEmptyShadeView;
+
+ private boolean mQsScrimEnabled = true;
+ private boolean mLastAnnouncementWasQuickSettings;
+ private boolean mQsTouchAboveFalsingThreshold;
+ private int mQsFalsingThreshold;
+
+ private float mKeyguardStatusBarAnimateAlpha = 1f;
private int mOldLayoutDirection;
+ private HeadsUpTouchHelper mHeadsUpTouchHelper;
+ private boolean mIsExpansionFromHeadsUp;
+ private boolean mListenForHeadsUp;
+ private int mNavigationBarBottomHeight;
+ private boolean mExpandingFromHeadsUp;
+ private boolean mCollapsedOnDown;
+ private int mPositionMinSideMargin;
+ private int mMaxFadeoutHeight;
+ private int mLastOrientation = -1;
+ private boolean mClosingWithAlphaFadeOut;
+ private boolean mHeadsUpAnimatingAway;
+ private boolean mLaunchingAffordance;
+ private boolean mAffordanceHasPreview;
+ private FalsingManager mFalsingManager;
+ private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
+ private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
+ @Override
+ public void run() {
+ setHeadsUpAnimatingAway(false);
+ notifyBarPanelExpansionChanged();
+ }
+ };
+ private NotificationGroupManager mGroupManager;
+ private boolean mShowIconsWhenExpanded;
+ private int mIndicationBottomPadding;
+ private int mAmbientIndicationBottomPadding;
+ private boolean mIsFullWidth;
+ private boolean mBlockingExpansionForCurrentTouch;
+
+ /**
+ * Following variables maintain state of events when input focus transfer may occur.
+ */
+ private boolean mExpectingSynthesizedDown; // expecting to see synthesized DOWN event
+ private boolean mLastEventSynthesizedDown; // last event was synthesized DOWN event
+
+ /**
+ * Current dark amount that follows regular interpolation curve of animation.
+ */
+ private float mInterpolatedDarkAmount;
+
+ /**
+ * Dark amount that animates from 0 to 1 or vice-versa in linear manner, even if the
+ * interpolation curve is different.
+ */
+ private float mLinearDarkAmount;
+
+ private boolean mPulsing;
+ private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+ private boolean mNoVisibleNotifications = true;
+ private boolean mUserSetupComplete;
+ private int mQsNotificationTopPadding;
+ private float mExpandOffset;
+ private boolean mHideIconsDuringNotificationLaunch = true;
+ private int mStackScrollerMeasuringPass;
+ private ArrayList<Consumer<ExpandableNotificationRow>> mTrackingHeadsUpListeners
+ = new ArrayList<>();
+ private ArrayList<Runnable> mVerticalTranslationListener = new ArrayList<>();
+ private HeadsUpAppearanceController mHeadsUpAppearanceController;
+
+ private int mPanelAlpha;
private int mCurrentPanelAlpha;
private final Paint mAlphaPaint = new Paint();
- private boolean mDozing;
+ private Runnable mPanelAlphaEndAction;
+ private float mBottomAreaShadeAlpha;
+ private final ValueAnimator mBottomAreaShadeAlphaAnimator;
+ private AnimatorListenerAdapter mAnimatorListenerAdapter = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mPanelAlphaEndAction != null) {
+ mPanelAlphaEndAction.run();
+ }
+ }
+ };
+ private final AnimatableProperty PANEL_ALPHA = AnimatableProperty.from(
+ "panelAlpha",
+ NotificationPanelView::setPanelAlphaInternal,
+ NotificationPanelView::getCurrentPanelAlpha,
+ R.id.panel_alpha_animator_tag,
+ R.id.panel_alpha_animator_start_tag,
+ R.id.panel_alpha_animator_end_tag);
+ private final AnimationProperties PANEL_ALPHA_OUT_PROPERTIES = new AnimationProperties()
+ .setDuration(150)
+ .setCustomInterpolator(PANEL_ALPHA.getProperty(), Interpolators.ALPHA_OUT);
+ private final AnimationProperties PANEL_ALPHA_IN_PROPERTIES = new AnimationProperties()
+ .setDuration(200)
+ .setAnimationFinishListener(mAnimatorListenerAdapter)
+ .setCustomInterpolator(PANEL_ALPHA.getProperty(), Interpolators.ALPHA_IN);
+ private final NotificationEntryManager mEntryManager;
- public NotificationPanelView(Context context, AttributeSet attrs) {
- super(context, attrs);
+ private final CommandQueue mCommandQueue;
+ private final NotificationLockscreenUserManager mLockscreenUserManager;
+ private final ShadeController mShadeController;
+ private int mDisplayId;
+
+ /**
+ * Cache the resource id of the theme to avoid unnecessary work in onThemeChanged.
+ *
+ * onThemeChanged is forced when the theme might not have changed. So, to avoid unncessary
+ * work, check the current id with the cached id.
+ */
+ private int mThemeResId;
+ private KeyguardIndicationController mKeyguardIndicationController;
+ private Consumer<Boolean> mAffordanceLaunchListener;
+ private int mShelfHeight;
+ private Runnable mOnReinflationListener;
+ private int mDarkIconSize;
+ private int mHeadsUpInset;
+ private boolean mHeadsUpPinnedMode;
+ private float mKeyguardHeadsUpShowingAmount = 0.0f;
+ private boolean mShowingKeyguardHeadsUp;
+ private boolean mAllowExpandForSmallExpansion;
+ private Runnable mExpandAfterLayoutRunnable;
+
+ /**
+ * If face auth with bypass is running for the first time after you turn on the screen.
+ * (From aod or screen off)
+ */
+ private boolean mFirstBypassAttempt;
+ /**
+ * If auth happens successfully during {@code mFirstBypassAttempt}, and we should wait until
+ * the keyguard is dismissed to show the status bar.
+ */
+ private boolean mDelayShowingKeyguardStatusBar;
+
+ private PluginManager mPluginManager;
+ private FrameLayout mPluginFrame;
+ private NPVPluginManager mNPVPluginManager;
+
+ @Inject
+ public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
+ InjectionInflationController injectionInflationController,
+ NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
+ DynamicPrivacyController dynamicPrivacyController,
+ KeyguardBypassController bypassController, FalsingManager falsingManager,
+ PluginManager pluginManager, ShadeController shadeController,
+ NotificationLockscreenUserManager notificationLockscreenUserManager,
+ NotificationEntryManager notificationEntryManager,
+ KeyguardStateController keyguardStateController,
+ StatusBarStateController statusBarStateController, DozeLog dozeLog,
+ DozeParameters dozeParameters, CommandQueue commandQueue) {
+ super(context, attrs, falsingManager, dozeLog, keyguardStateController,
+ (SysuiStatusBarStateController) statusBarStateController);
setWillNotDraw(!DEBUG);
+ mInjectionInflationController = injectionInflationController;
+ mFalsingManager = falsingManager;
+ mPowerManager = context.getSystemService(PowerManager.class);
+ mWakeUpCoordinator = coordinator;
+ mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
+ setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
mAlphaPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
+ setPanelAlpha(255, false /* animate */);
+ mCommandQueue = commandQueue;
+ mDisplayId = context.getDisplayId();
+ mPulseExpansionHandler = pulseExpansionHandler;
+ mDozeParameters = dozeParameters;
+ pulseExpansionHandler.setPulseExpandAbortListener(() -> {
+ if (mQs != null) {
+ mQs.animateHeaderSlidingOut();
+ }
+ });
+ mThemeResId = context.getThemeResId();
+ mKeyguardBypassController = bypassController;
+ mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+ mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
+ mKeyguardStateController.addCallback(mKeyguardMonitorCallback);
+ dynamicPrivacyController.addListener(this);
+
+ mBottomAreaShadeAlphaAnimator = ValueAnimator.ofFloat(1f, 0);
+ mBottomAreaShadeAlphaAnimator.addUpdateListener(animation -> {
+ mBottomAreaShadeAlpha = (float) animation.getAnimatedValue();
+ updateKeyguardBottomAreaAlpha();
+ });
+ mBottomAreaShadeAlphaAnimator.setDuration(160);
+ mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
+ mPluginManager = pluginManager;
+ mShadeController = shadeController;
+ mLockscreenUserManager = notificationLockscreenUserManager;
+ mEntryManager = notificationEntryManager;
setBackgroundColor(Color.TRANSPARENT);
}
+ /**
+ * Returns if there's a custom clock being presented.
+ */
+ public boolean hasCustomClock() {
+ return mKeyguardStatusView.hasCustomClock();
+ }
+
+ private void setStatusBar(StatusBar bar) {
+ mStatusBar = bar;
+ mKeyguardBottomArea.setStatusBar(mStatusBar);
+ }
+
+ /**
+ * Call after this view has been fully inflated and had its children attached.
+ */
+ public void onChildrenAttached() {
+ loadDimens();
+ mKeyguardStatusBar = findViewById(R.id.keyguard_header);
+ mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
+
+ KeyguardClockSwitch keyguardClockSwitch = findViewById(R.id.keyguard_clock_container);
+ mBigClockContainer = findViewById(R.id.big_clock_container);
+ keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+
+ mHomeControlsLayout = findViewById(R.id.home_controls_layout);
+ mNotificationContainerParent = findViewById(R.id.notification_container_parent);
+ mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
+ mNotificationStackScroller.setOnHeightChangedListener(this);
+ mNotificationStackScroller.setOverscrollTopChangedListener(this);
+ mNotificationStackScroller.setOnEmptySpaceClickListener(this);
+ addTrackingHeadsUpListener(mNotificationStackScroller::setTrackingHeadsUp);
+ mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area);
+ mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
+ mLastOrientation = getResources().getConfiguration().orientation;
+ mPluginFrame = findViewById(R.id.plugin_frame);
+ if (Settings.System.getInt(
+ mContext.getContentResolver(), "npv_plugin_flag", 0) == 1) {
+ mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
+ }
+
+
+ initBottomArea();
+
+ mWakeUpCoordinator.setStackScroller(mNotificationStackScroller);
+ mQsFrame = findViewById(R.id.qs_frame);
+ mPulseExpansionHandler.setUp(mNotificationStackScroller, this, mShadeController);
+ mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
+ @Override
+ public void onFullyHiddenChanged(boolean isFullyHidden) {
+ updateKeyguardStatusBarForHeadsUp();
+ }
+
+ @Override
+ public void onPulseExpansionChanged(boolean expandingChanged) {
+ if (mKeyguardBypassController.getBypassEnabled()) {
+ // Position the notifications while dragging down while pulsing
+ requestScrollerTopPaddingUpdate(false /* animate */);
+ updateQSPulseExpansion();
+ }
+ }
+ });
+
+ mPluginManager.addPluginListener(
+ new PluginListener<HomeControlsPlugin>() {
+
+ @Override
+ public void onPluginConnected(HomeControlsPlugin plugin,
+ Context pluginContext) {
+ plugin.sendParentGroup(mHomeControlsLayout);
+ }
+
+ @Override
+ public void onPluginDisconnected(HomeControlsPlugin plugin) {
+
+ }
+ }, HomeControlsPlugin.class, false);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ FragmentHostManager.get(this).addTagListener(QS.TAG, mFragmentListener);
+ Dependency.get(StatusBarStateController.class).addCallback(this);
+ Dependency.get(ZenModeController.class).addCallback(this);
+ Dependency.get(ConfigurationController.class).addCallback(this);
+ mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
+ // Theme might have changed between inflating this view and attaching it to the window, so
+ // force a call to onThemeChanged
+ onThemeChanged();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ FragmentHostManager.get(this).removeTagListener(QS.TAG, mFragmentListener);
+ Dependency.get(StatusBarStateController.class).removeCallback(this);
+ Dependency.get(ZenModeController.class).removeCallback(this);
+ Dependency.get(ConfigurationController.class).removeCallback(this);
+ mUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
+ }
+
+ @Override
+ protected void loadDimens() {
+ super.loadDimens();
+ mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.4f);
+ mStatusBarMinHeight = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ mQsPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_peek_height);
+ mNotificationsHeaderCollideDistance =
+ getResources().getDimensionPixelSize(R.dimen.header_notifications_collide_distance);
+ mUnlockMoveDistance = getResources().getDimensionPixelOffset(R.dimen.unlock_move_distance);
+ mClockPositionAlgorithm.loadDimens(getResources());
+ mQsFalsingThreshold = getResources().getDimensionPixelSize(
+ R.dimen.qs_falsing_threshold);
+ mPositionMinSideMargin = getResources().getDimensionPixelSize(
+ R.dimen.notification_panel_min_side_margin);
+ mMaxFadeoutHeight = getResources().getDimensionPixelSize(
+ R.dimen.max_notification_fadeout_height);
+ mIndicationBottomPadding = getResources().getDimensionPixelSize(
+ R.dimen.keyguard_indication_bottom_padding);
+ mQsNotificationTopPadding = getResources().getDimensionPixelSize(
+ R.dimen.qs_notification_padding);
+ mShelfHeight = getResources().getDimensionPixelSize(R.dimen.notification_shelf_height);
+ mDarkIconSize = getResources().getDimensionPixelSize(
+ R.dimen.status_bar_icon_drawing_size_dark);
+ int statusbarHeight = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ mHeadsUpInset = statusbarHeight + getResources().getDimensionPixelSize(
+ R.dimen.heads_up_status_bar_padding);
+ mQqsSplitFraction = ((float) getResources().getInteger(R.integer.qqs_split_fraction)) / (
+ getResources().getInteger(R.integer.qqs_split_fraction)
+ + getResources().getInteger(R.integer.qs_split_fraction));
+ }
+
+ /**
+ * @see #launchCamera(boolean, int)
+ * @see #setLaunchingAffordance(boolean)
+ */
+ public void setLaunchAffordanceListener(Consumer<Boolean> listener) {
+ mAffordanceLaunchListener = listener;
+ }
+
+ public void updateResources() {
+ Resources res = getResources();
+ int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width);
+ int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity);
+ FrameLayout.LayoutParams lp =
+ (FrameLayout.LayoutParams) mQsFrame.getLayoutParams();
+ if (lp.width != qsWidth || lp.gravity != panelGravity) {
+ lp.width = qsWidth;
+ lp.gravity = panelGravity;
+ mQsFrame.setLayoutParams(lp);
+ }
+
+ int panelWidth = res.getDimensionPixelSize(R.dimen.notification_panel_width);
+ lp = (FrameLayout.LayoutParams) mNotificationStackScroller.getLayoutParams();
+ if (lp.width != panelWidth || lp.gravity != panelGravity) {
+ lp.width = panelWidth;
+ lp.gravity = panelGravity;
+ mNotificationStackScroller.setLayoutParams(lp);
+ }
+ int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
+ int topMargin = sideMargin;
+ lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
+ if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
+ || lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
+ lp.width = qsWidth;
+ lp.gravity = panelGravity;
+ lp.leftMargin = sideMargin;
+ lp.rightMargin = sideMargin;
+ lp.topMargin = topMargin;
+ mPluginFrame.setLayoutParams(lp);
+ }
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ updateShowEmptyShadeView();
+ }
+
+ @Override
+ public void onThemeChanged() {
+ final int themeResId = getContext().getThemeResId();
+ if (mThemeResId == themeResId) {
+ return;
+ }
+ mThemeResId = themeResId;
+
+ reInflateViews();
+ }
+
+ @Override
+ public void onOverlayChanged() {
+ reInflateViews();
+ }
+
+ private void reInflateViews() {
+ updateShowEmptyShadeView();
+
+ // Re-inflate the status view group.
+ int index = indexOfChild(mKeyguardStatusView);
+ removeView(mKeyguardStatusView);
+ mKeyguardStatusView = (KeyguardStatusView) mInjectionInflationController
+ .injectable(LayoutInflater.from(mContext)).inflate(
+ R.layout.keyguard_status_view,
+ this,
+ false);
+ addView(mKeyguardStatusView, index);
+
+ // Re-associate the clock container with the keyguard clock switch.
+ mBigClockContainer.removeAllViews();
+ KeyguardClockSwitch keyguardClockSwitch = findViewById(R.id.keyguard_clock_container);
+ keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+
+ // Update keyguard bottom area
+ index = indexOfChild(mKeyguardBottomArea);
+ removeView(mKeyguardBottomArea);
+ KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea;
+ mKeyguardBottomArea = (KeyguardBottomAreaView) mInjectionInflationController
+ .injectable(LayoutInflater.from(mContext)).inflate(
+ R.layout.keyguard_bottom_area,
+ this,
+ false);
+ mKeyguardBottomArea.initFrom(oldBottomArea);
+ addView(mKeyguardBottomArea, index);
+ initBottomArea();
+ mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
+ onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
+ mStatusBarStateController.getInterpolatedDozeAmount());
+
+ if (mKeyguardStatusBar != null) {
+ mKeyguardStatusBar.onThemeChanged();
+ }
+
+ setKeyguardStatusViewVisibility(mBarState, false, false);
+ setKeyguardBottomAreaVisibility(mBarState, false);
+ if (mOnReinflationListener != null) {
+ mOnReinflationListener.run();
+ }
+ reinflatePluginContainer();
+ }
+
+ @Override
+ public void onUiModeChanged() {
+ reinflatePluginContainer();
+ }
+
+ private void reinflatePluginContainer() {
+ int index = indexOfChild(mPluginFrame);
+ removeView(mPluginFrame);
+ mPluginFrame = (FrameLayout) mInjectionInflationController
+ .injectable(LayoutInflater.from(mContext)).inflate(
+ R.layout.status_bar_expanded_plugin_frame,
+ this,
+ false);
+ addView(mPluginFrame, index);
+
+ Resources res = getResources();
+ int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width);
+ int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity);
+ FrameLayout.LayoutParams lp;
+ int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
+ int topMargin =
+ res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height);
+ if (Utils.useQsMediaPlayer(mContext)) {
+ topMargin = res.getDimensionPixelOffset(
+ com.android.internal.R.dimen.quick_qs_total_height_with_media);
+ }
+ lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
+ if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
+ || lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
+ lp.width = qsWidth;
+ lp.gravity = panelGravity;
+ lp.leftMargin = sideMargin;
+ lp.rightMargin = sideMargin;
+ lp.topMargin = topMargin;
+ mPluginFrame.setLayoutParams(lp);
+ }
+
+ if (mNPVPluginManager != null) mNPVPluginManager.replaceFrameLayout(mPluginFrame);
+ }
+
+ private void initBottomArea() {
+ mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext(), mFalsingManager);
+ mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
+ mKeyguardBottomArea.setStatusBar(mStatusBar);
+ mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
+ }
+
+ public void setKeyguardIndicationController(KeyguardIndicationController indicationController) {
+ mKeyguardIndicationController = indicationController;
+ mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ DejankUtils.startDetectingBlockingIpcs("NVP#onLayout");
+ super.onLayout(changed, left, top, right, bottom);
+ setIsFullWidth(mNotificationStackScroller.getWidth() == getWidth());
+
+ // Update Clock Pivot
+ mKeyguardStatusView.setPivotX(getWidth() / 2);
+ mKeyguardStatusView.setPivotY((FONT_HEIGHT - CAP_HEIGHT) / 2048f *
+ mKeyguardStatusView.getClockTextSize());
+
+ // Calculate quick setting heights.
+ int oldMaxHeight = mQsMaxExpansionHeight;
+ if (mQs != null) {
+ mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
+ if (mNPVPluginManager != null) {
+ mNPVPluginManager.setYOffset(mQsMinExpansionHeight);
+ mQsMinExpansionHeight += mNPVPluginManager.getHeight();
+ }
+ mQsMaxExpansionHeight = mQs.getDesiredHeight();
+ mNotificationStackScroller.setMaxTopPadding(
+ mQsMaxExpansionHeight + mQsNotificationTopPadding);
+ }
+ positionClockAndNotifications();
+ if (mQsExpanded && mQsFullyExpanded) {
+ mQsExpansionHeight = mQsMaxExpansionHeight;
+ requestScrollerTopPaddingUpdate(false /* animate */);
+ requestPanelHeightUpdate();
+
+ // Size has changed, start an animation.
+ if (mQsMaxExpansionHeight != oldMaxHeight) {
+ startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
+ }
+ } else if (!mQsExpanded) {
+ setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
+ }
+ updateExpandedHeight(getExpandedHeight());
+ updateHeader();
+
+ // If we are running a size change animation, the animation takes care of the height of
+ // the container. However, if we are not animating, we always need to make the QS container
+ // the desired height so when closing the QS detail, it stays smaller after the size change
+ // animation is finished but the detail view is still being animated away (this animation
+ // takes longer than the size change animation).
+ if (mQsSizeChangeAnimator == null && mQs != null) {
+ mQs.setHeightOverride(mQs.getDesiredHeight());
+ }
+ updateMaxHeadsUpTranslation();
+ updateGestureExclusionRect();
+ if (mExpandAfterLayoutRunnable != null) {
+ mExpandAfterLayoutRunnable.run();
+ mExpandAfterLayoutRunnable = null;
+ }
+ DejankUtils.stopDetectingBlockingIpcs("NVP#onLayout");
+ }
+
+ private void updateGestureExclusionRect() {
+ Rect exclusionRect = calculateGestureExclusionRect();
+ setSystemGestureExclusionRects(exclusionRect.isEmpty()
+ ? Collections.EMPTY_LIST
+ : Collections.singletonList(exclusionRect));
+ }
+
+ private Rect calculateGestureExclusionRect() {
+ Rect exclusionRect = null;
+ Region touchableRegion = mHeadsUpManager.calculateTouchableRegion();
+ if (isFullyCollapsed() && touchableRegion != null) {
+ // Note: The heads up manager also calculates the non-pinned touchable region
+ exclusionRect = touchableRegion.getBounds();
+ }
+ return exclusionRect != null
+ ? exclusionRect
+ : mEmptyRect;
+ }
+
+ private void setIsFullWidth(boolean isFullWidth) {
+ mIsFullWidth = isFullWidth;
+ mNotificationStackScroller.setIsFullWidth(isFullWidth);
+ }
+
+ private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) {
+ if (mQsSizeChangeAnimator != null) {
+ oldHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
+ mQsSizeChangeAnimator.cancel();
+ }
+ mQsSizeChangeAnimator = ValueAnimator.ofInt(oldHeight, newHeight);
+ mQsSizeChangeAnimator.setDuration(300);
+ mQsSizeChangeAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mQsSizeChangeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ requestScrollerTopPaddingUpdate(false /* animate */);
+ requestPanelHeightUpdate();
+ int height = (int) mQsSizeChangeAnimator.getAnimatedValue();
+ mQs.setHeightOverride(height);
+ }
+ });
+ mQsSizeChangeAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mQsSizeChangeAnimator = null;
+ }
+ });
+ mQsSizeChangeAnimator.start();
+ }
+
+ /**
+ * Positions the clock and notifications dynamically depending on how many notifications are
+ * showing.
+ */
+ private void positionClockAndNotifications() {
+ boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
+ boolean animateClock = animate || mAnimateNextPositionUpdate;
+ int stackScrollerPadding;
+ if (mBarState != StatusBarState.KEYGUARD) {
+ stackScrollerPadding = getUnlockedStackScrollerPadding();
+ } else {
+ int totalHeight = getHeight();
+ int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
+ int clockPreferredY = mKeyguardStatusView.getClockPreferredY(totalHeight);
+ boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
+ final boolean hasVisibleNotifications =
+ !bypassEnabled && mNotificationStackScroller.getVisibleNotificationCount() != 0;
+ mKeyguardStatusView.setHasVisibleNotifications(hasVisibleNotifications);
+ mClockPositionAlgorithm.setup(
+ mStatusBarMinHeight,
+ totalHeight - bottomPadding,
+ mNotificationStackScroller.getIntrinsicContentHeight(),
+ getExpandedFraction(),
+ totalHeight,
+ (int) (mKeyguardStatusView.getHeight()
+ - mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
+ clockPreferredY,
+ hasCustomClock(),
+ hasVisibleNotifications,
+ mInterpolatedDarkAmount,
+ mEmptyDragAmount,
+ bypassEnabled,
+ getUnlockedStackScrollerPadding());
+ mClockPositionAlgorithm.run(mClockPositionResult);
+ PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.X,
+ mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock);
+ PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.Y,
+ mClockPositionResult.clockY, CLOCK_ANIMATION_PROPERTIES, animateClock);
+ updateNotificationTranslucency();
+ updateClock();
+ stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
+ }
+ mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
+ mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
+
+ mStackScrollerMeasuringPass++;
+ requestScrollerTopPaddingUpdate(animate);
+ mStackScrollerMeasuringPass = 0;
+ mAnimateNextPositionUpdate = false;
+ }
+
+ /**
+ * @return the padding of the stackscroller when unlocked
+ */
+ private int getUnlockedStackScrollerPadding() {
+ return (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
+ + mQsNotificationTopPadding;
+ }
+
+ /**
+ * @param maximum the maximum to return at most
+ * @return the maximum keyguard notifications that can fit on the screen
+ */
+ public int computeMaxKeyguardNotifications(int maximum) {
+ float minPadding = mClockPositionAlgorithm.getMinStackScrollerPadding();
+ int notificationPadding = Math.max(1, getResources().getDimensionPixelSize(
+ R.dimen.notification_divider_height));
+ NotificationShelf shelf = mNotificationStackScroller.getNotificationShelf();
+ float shelfSize = shelf.getVisibility() == GONE ? 0
+ : shelf.getIntrinsicHeight() + notificationPadding;
+ float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize
+ - Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding)
+ - mKeyguardStatusView.getLogoutButtonHeight();
+ int count = 0;
+ for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i);
+ if (!(child instanceof ExpandableNotificationRow)) {
+ continue;
+ }
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ boolean suppressedSummary = mGroupManager != null
+ && mGroupManager.isSummaryOfSuppressedGroup(row.getEntry().getSbn());
+ if (suppressedSummary) {
+ continue;
+ }
+ if (!mLockscreenUserManager.shouldShowOnKeyguard(row.getEntry())) {
+ continue;
+ }
+ if (row.isRemoved()) {
+ continue;
+ }
+ availableSpace -= child.getMinHeight(true /* ignoreTemporaryStates */)
+ + notificationPadding;
+ if (availableSpace >= 0 && count < maximum) {
+ count++;
+ } else if (availableSpace > -shelfSize) {
+ // if we are exactly the last view, then we can show us still!
+ for (int j = i + 1; j < mNotificationStackScroller.getChildCount(); j++) {
+ if (mNotificationStackScroller.getChildAt(j)
+ instanceof ExpandableNotificationRow) {
+ return count;
+ }
+ }
+ count++;
+ return count;
+ } else {
+ return count;
+ }
+ }
+ return count;
+ }
+
+ private void updateClock() {
+ if (!mKeyguardStatusViewAnimating) {
+ mKeyguardStatusView.setAlpha(mClockPositionResult.clockAlpha);
+ }
+ }
+
+ public void animateToFullShade(long delay) {
+ mNotificationStackScroller.goToFullShade(delay);
+ requestLayout();
+ mAnimateNextPositionUpdate = true;
+ }
+
+ public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
+ mQsExpansionEnabled = qsExpansionEnabled;
+ if (mQs == null) return;
+ mQs.setHeaderClickable(qsExpansionEnabled);
+ }
+
+ @Override
+ public void resetViews(boolean animate) {
+ mIsLaunchTransitionFinished = false;
+ mBlockTouches = false;
+ if (!mLaunchingAffordance) {
+ mAffordanceHelper.reset(false);
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
+ }
+ mStatusBar.getGutsManager().closeAndSaveGuts(true /* leavebehind */, true /* force */,
+ true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
+ if (animate) {
+ animateCloseQs(true /* animateAway */);
+ } else {
+ closeQs();
+ }
+ mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, animate,
+ !animate /* cancelAnimators */);
+ mNotificationStackScroller.resetScrollPosition();
+ }
+
+ @Override
+ public void collapse(boolean delayed, float speedUpFactor) {
+ if (!canPanelBeCollapsed()) {
+ return;
+ }
+
+ if (mQsExpanded) {
+ mQsExpandImmediate = true;
+ mNotificationStackScroller.setShouldShowShelfOnly(true);
+ }
+ super.collapse(delayed, speedUpFactor);
+ }
+
+ public void closeQs() {
+ cancelQsAnimation();
+ setQsExpansion(mQsMinExpansionHeight);
+ }
+
+ /**
+ * Animate QS closing by flinging it.
+ * If QS is expanded, it will collapse into QQS and stop.
+ *
+ * @param animateAway Do not stop when QS becomes QQS. Fling until QS isn't visible anymore.
+ */
+ public void animateCloseQs(boolean animateAway) {
+ if (mQsExpansionAnimator != null) {
+ if (!mQsAnimatorExpand) {
+ return;
+ }
+ float height = mQsExpansionHeight;
+ mQsExpansionAnimator.cancel();
+ setQsExpansion(height);
+ }
+ flingSettings(0 /* vel */, animateAway ? FLING_HIDE : FLING_COLLAPSE);
+ }
+
+ public void expandWithQs() {
+ if (mQsExpansionEnabled) {
+ mQsExpandImmediate = true;
+ mNotificationStackScroller.setShouldShowShelfOnly(true);
+ }
+ if (isFullyCollapsed()) {
+ expand(true /* animate */);
+ } else {
+ flingSettings(0 /* velocity */, FLING_EXPAND);
+ }
+ }
+
+ public void expandWithoutQs() {
+ if (isQsExpanded()) {
+ flingSettings(0 /* velocity */, FLING_COLLAPSE);
+ } else {
+ expand(true /* animate */);
+ }
+ }
+
+ @Override
+ public void fling(float vel, boolean expand) {
+ GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
+ if (gr != null) {
+ gr.tag("fling " + ((vel > 0) ? "open" : "closed"), "notifications,v=" + vel);
+ }
+ super.fling(vel, expand);
+ }
+
+ @Override
+ protected void flingToHeight(float vel, boolean expand, float target,
+ float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
+ mHeadsUpTouchHelper.notifyFling(!expand);
+ setClosingWithAlphaFadeout(!expand && !isOnKeyguard() && getFadeoutAlpha() == 1.0f);
+ super.flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ if (mBlockTouches || mQsFullyExpanded && mQs.onInterceptTouchEvent(event)) {
+ return false;
+ }
+ initDownStates(event);
+ // Do not let touches go to shade or QS if the bouncer is visible,
+ // but still let user swipe down to expand the panel, dismissing the bouncer.
+ if (mStatusBar.isBouncerShowing()) {
+ return true;
+ }
+ if (mBar.panelEnabled() && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
+ mIsExpansionFromHeadsUp = true;
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1);
+ return true;
+ }
+ if (!shouldQuickSettingsIntercept(mDownX, mDownY, 0)
+ && mPulseExpansionHandler.onInterceptTouchEvent(event)) {
+ return true;
+ }
+
+ if (!isFullyCollapsed() && onQsIntercept(event)) {
+ return true;
+ }
+ return super.onInterceptTouchEvent(event);
+ }
+
+ private boolean onQsIntercept(MotionEvent event) {
+ int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ if (pointerIndex < 0) {
+ pointerIndex = 0;
+ mTrackingPointer = event.getPointerId(pointerIndex);
+ }
+ final float x = event.getX(pointerIndex);
+ final float y = event.getY(pointerIndex);
+
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mIntercepting = true;
+ mInitialTouchY = y;
+ mInitialTouchX = x;
+ initVelocityTracker();
+ trackMovement(event);
+ if (shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, 0)) {
+ getParent().requestDisallowInterceptTouchEvent(true);
+ }
+ if (mQsExpansionAnimator != null) {
+ onQsExpansionStarted();
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ mQsTracking = true;
+ mIntercepting = false;
+ mNotificationStackScroller.cancelLongPress();
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ final int upPointer = event.getPointerId(event.getActionIndex());
+ if (mTrackingPointer == upPointer) {
+ // gesture is ongoing, find a new pointer to track
+ final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+ mTrackingPointer = event.getPointerId(newIndex);
+ mInitialTouchX = event.getX(newIndex);
+ mInitialTouchY = event.getY(newIndex);
+ }
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ final float h = y - mInitialTouchY;
+ trackMovement(event);
+ if (mQsTracking) {
+
+ // Already tracking because onOverscrolled was called. We need to update here
+ // so we don't stop for a frame until the next touch event gets handled in
+ // onTouchEvent.
+ setQsExpansion(h + mInitialHeightOnTouch);
+ trackMovement(event);
+ mIntercepting = false;
+ return true;
+ }
+ if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)
+ && shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, h)) {
+ mQsTracking = true;
+ onQsExpansionStarted();
+ notifyExpandingFinished();
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ mInitialTouchY = y;
+ mInitialTouchX = x;
+ mIntercepting = false;
+ mNotificationStackScroller.cancelLongPress();
+ return true;
+ }
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ trackMovement(event);
+ if (mQsTracking) {
+ flingQsWithCurrentVelocity(y,
+ event.getActionMasked() == MotionEvent.ACTION_CANCEL);
+ mQsTracking = false;
+ }
+ mIntercepting = false;
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean isInContentBounds(float x, float y) {
+ float stackScrollerX = mNotificationStackScroller.getX();
+ return !mNotificationStackScroller.isBelowLastNotification(x - stackScrollerX, y)
+ && stackScrollerX < x && x < stackScrollerX + mNotificationStackScroller.getWidth();
+ }
+
+ private void initDownStates(MotionEvent event) {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mOnlyAffordanceInThisMotion = false;
+ mQsTouchAboveFalsingThreshold = mQsFullyExpanded;
+ mDozingOnDown = isDozing();
+ mDownX = event.getX();
+ mDownY = event.getY();
+ mCollapsedOnDown = isFullyCollapsed();
+ mListenForHeadsUp = mCollapsedOnDown && mHeadsUpManager.hasPinnedHeadsUp();
+ mAllowExpandForSmallExpansion = mExpectingSynthesizedDown;
+ mTouchSlopExceededBeforeDown = mExpectingSynthesizedDown;
+ if (mExpectingSynthesizedDown) {
+ mLastEventSynthesizedDown = true;
+ } else {
+ // down but not synthesized motion event.
+ mLastEventSynthesizedDown = false;
+ }
+ } else {
+ // not down event at all.
+ mLastEventSynthesizedDown = false;
+ }
+ }
+
+ private void flingQsWithCurrentVelocity(float y, boolean isCancelMotionEvent) {
+ float vel = getCurrentQSVelocity();
+ final boolean expandsQs = flingExpandsQs(vel);
+ if (expandsQs) {
+ logQsSwipeDown(y);
+ }
+ flingSettings(vel, expandsQs && !isCancelMotionEvent ? FLING_EXPAND : FLING_COLLAPSE);
+ }
+
+ private void logQsSwipeDown(float y) {
+ float vel = getCurrentQSVelocity();
+ final int gesture = mBarState == StatusBarState.KEYGUARD
+ ? MetricsEvent.ACTION_LS_QS
+ : MetricsEvent.ACTION_SHADE_QS_PULL;
+ mLockscreenGestureLogger.write(gesture,
+ (int) ((y - mInitialTouchY) / mStatusBar.getDisplayDensity()),
+ (int) (vel / mStatusBar.getDisplayDensity()));
+ }
+
+ private boolean flingExpandsQs(float vel) {
+ if (mFalsingManager.isUnlockingDisabled() || isFalseTouch()) {
+ return false;
+ }
+ if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+ return getQsExpansionFraction() > 0.5f;
+ } else {
+ return vel > 0;
+ }
+ }
+
+ private boolean isFalseTouch() {
+ if (!needsAntiFalsing()) {
+ return false;
+ }
+ if (mFalsingManager.isClassifierEnabled()) {
+ return mFalsingManager.isFalseTouch();
+ }
+ return !mQsTouchAboveFalsingThreshold;
+ }
+
+ private float getQsExpansionFraction() {
+ return Math.min(1f, (mQsExpansionHeight - mQsMinExpansionHeight)
+ / (mQsMaxExpansionHeight - mQsMinExpansionHeight));
+ }
+
+ @Override
+ protected boolean shouldExpandWhenNotFlinging() {
+ if (super.shouldExpandWhenNotFlinging()) {
+ return true;
+ }
+ if (mAllowExpandForSmallExpansion) {
+ // When we get a touch that came over from launcher, the velocity isn't always correct
+ // Let's err on expanding if the gesture has been reasonably slow
+ long timeSinceDown = SystemClock.uptimeMillis() - mDownTime;
+ return timeSinceDown <= MAX_TIME_TO_OPEN_WHEN_FLINGING_FROM_LAUNCHER;
+ }
+ return false;
+ }
+
+ @Override
+ protected float getOpeningHeight() {
+ return mNotificationStackScroller.getOpeningHeight();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mBlockTouches || (mQs != null && mQs.isCustomizing())) {
+ return false;
+ }
+
+ // Do not allow panel expansion if bouncer is scrimmed, otherwise user would be able to
+ // pull down QS or expand the shade.
+ if (mStatusBar.isBouncerShowingScrimmed()) {
+ return false;
+ }
+
+ // Make sure the next touch won't the blocked after the current ends.
+ if (event.getAction() == MotionEvent.ACTION_UP
+ || event.getAction() == MotionEvent.ACTION_CANCEL) {
+ mBlockingExpansionForCurrentTouch = false;
+ }
+ // When touch focus transfer happens, ACTION_DOWN->ACTION_UP may happen immediately
+ // without any ACTION_MOVE event.
+ // In such case, simply expand the panel instead of being stuck at the bottom bar.
+ if (mLastEventSynthesizedDown && event.getAction() == MotionEvent.ACTION_UP) {
+ expand(true /* animate */);
+ }
+ initDownStates(event);
+ if (!mIsExpanding && !shouldQuickSettingsIntercept(mDownX, mDownY, 0)
+ && mPulseExpansionHandler.onTouchEvent(event)) {
+ // We're expanding all the other ones shouldn't get this anymore
+ return true;
+ }
+ if (mListenForHeadsUp && !mHeadsUpTouchHelper.isTrackingHeadsUp()
+ && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
+ mIsExpansionFromHeadsUp = true;
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_PEEK, 1);
+ }
+ boolean handled = false;
+ if ((!mIsExpanding || mHintAnimationRunning)
+ && !mQsExpanded
+ && mBarState != StatusBarState.SHADE
+ && !mDozing) {
+ handled |= mAffordanceHelper.onTouchEvent(event);
+ }
+ if (mOnlyAffordanceInThisMotion) {
+ return true;
+ }
+ handled |= mHeadsUpTouchHelper.onTouchEvent(event);
+
+ if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
+ return true;
+ }
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN, 1);
+ updateVerticalPanelPosition(event.getX());
+ handled = true;
+ }
+ handled |= super.onTouchEvent(event);
+ return !mDozing || mPulsing || handled;
+ }
+
+ private boolean handleQsTouch(MotionEvent event) {
+ final int action = event.getActionMasked();
+ if (action == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
+ && mBarState != StatusBarState.KEYGUARD && !mQsExpanded
+ && mQsExpansionEnabled) {
+
+ // Down in the empty area while fully expanded - go to QS.
+ mQsTracking = true;
+ mConflictingQsExpansionGesture = true;
+ onQsExpansionStarted();
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ mInitialTouchY = event.getX();
+ mInitialTouchX = event.getY();
+ }
+ if (!isFullyCollapsed()) {
+ handleQsDown(event);
+ }
+ if (!mQsExpandImmediate && mQsTracking) {
+ onQsTouch(event);
+ if (!mConflictingQsExpansionGesture) {
+ return true;
+ }
+ }
+ if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
+ mConflictingQsExpansionGesture = false;
+ }
+ if (action == MotionEvent.ACTION_DOWN && isFullyCollapsed()
+ && mQsExpansionEnabled) {
+ mTwoFingerQsExpandPossible = true;
+ }
+ if (mTwoFingerQsExpandPossible && isOpenQsEvent(event)
+ && event.getY(event.getActionIndex()) < mStatusBarMinHeight) {
+ MetricsLogger.count(mContext, COUNTER_PANEL_OPEN_QS, 1);
+ mQsExpandImmediate = true;
+ mNotificationStackScroller.setShouldShowShelfOnly(true);
+ requestPanelHeightUpdate();
+
+ // Normally, we start listening when the panel is expanded, but here we need to start
+ // earlier so the state is already up to date when dragging down.
+ setListening(true);
+ }
+ if (isQsSplitEnabled() && !mKeyguardShowing) {
+ if (mQsExpandImmediate) {
+ mNotificationStackScroller.setVisibility(View.GONE);
+ mQsFrame.setVisibility(View.VISIBLE);
+ mHomeControlsLayout.setVisibility(View.VISIBLE);
+ } else {
+ mNotificationStackScroller.setVisibility(View.VISIBLE);
+ mQsFrame.setVisibility(View.GONE);
+ mHomeControlsLayout.setVisibility(View.GONE);
+ }
+ }
+ return false;
+ }
+
+ private boolean isInQsArea(float x, float y) {
+ return (x >= mQsFrame.getX()
+ && x <= mQsFrame.getX() + mQsFrame.getWidth())
+ && (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+ || y <= mQs.getView().getY() + mQs.getView().getHeight());
+ }
+
+ private boolean isOnQsEndArea(float x) {
+ if (!isQsSplitEnabled()) return false;
+ if (getLayoutDirection() == LAYOUT_DIRECTION_LTR) {
+ return x >= mQsFrame.getX() + mQqsSplitFraction * mQsFrame.getWidth()
+ && x <= mQsFrame.getX() + mQsFrame.getWidth();
+ } else {
+ return x >= mQsFrame.getX()
+ && x <= mQsFrame.getX() + (1 - mQqsSplitFraction) * mQsFrame.getWidth();
+ }
+ }
+
+ private boolean isOpenQsEvent(MotionEvent event) {
+ final int pointerCount = event.getPointerCount();
+ final int action = event.getActionMasked();
+
+ final boolean twoFingerDrag = action == MotionEvent.ACTION_POINTER_DOWN
+ && pointerCount == 2;
+
+ final boolean stylusButtonClickDrag = action == MotionEvent.ACTION_DOWN
+ && (event.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY)
+ || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY));
+
+ final boolean mouseButtonClickDrag = action == MotionEvent.ACTION_DOWN
+ && (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY)
+ || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
+
+ final boolean onHeaderRight = isOnQsEndArea(event.getX());
+
+ return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag || onHeaderRight;
+ }
+
+ private void handleQsDown(MotionEvent event) {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN
+ && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
+ mFalsingManager.onQsDown();
+ mQsTracking = true;
+ onQsExpansionStarted();
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ mInitialTouchY = event.getX();
+ mInitialTouchX = event.getY();
+
+ // If we interrupt an expansion gesture here, make sure to update the state correctly.
+ notifyExpandingFinished();
+ }
+ }
+
+ /**
+ * Input focus transfer is about to happen.
+ */
+ public void startWaitingForOpenPanelGesture() {
+ if (!isFullyCollapsed()) {
+ return;
+ }
+ mExpectingSynthesizedDown = true;
+ onTrackingStarted();
+ updatePanelExpanded();
+ }
+
+ /**
+ * Called when this view is no longer waiting for input focus transfer.
+ *
+ * There are two scenarios behind this function call. First, input focus transfer
+ * has successfully happened and this view already received synthetic DOWN event.
+ * (mExpectingSynthesizedDown == false). Do nothing.
+ *
+ * Second, before input focus transfer finished, user may have lifted finger
+ * in previous window and this window never received synthetic DOWN event.
+ * (mExpectingSynthesizedDown == true).
+ * In this case, we use the velocity to trigger fling event.
+ *
+ * @param velocity unit is in px / millis
+ */
+ public void stopWaitingForOpenPanelGesture(final float velocity) {
+ if (mExpectingSynthesizedDown) {
+ mExpectingSynthesizedDown = false;
+ maybeVibrateOnOpening();
+ Runnable runnable = () -> fling(velocity > 1f ? 1000f * velocity : 0,
+ true /* expand */);
+ if (mStatusBar.getStatusBarWindow().getHeight()
+ != mStatusBar.getStatusBarHeight()) {
+ // The panel is already expanded to its full size, let's expand directly
+ runnable.run();
+ } else {
+ mExpandAfterLayoutRunnable = runnable;
+ }
+ onTrackingStopped(false);
+ }
+ }
+
+ @Override
+ protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
+ boolean expands = super.flingExpands(vel, vectorVel, x, y);
+
+ // If we are already running a QS expansion, make sure that we keep the panel open.
+ if (mQsExpansionAnimator != null) {
+ expands = true;
+ }
+ return expands;
+ }
+
+ @Override
+ protected boolean shouldGestureWaitForTouchSlop() {
+ if (mExpectingSynthesizedDown) {
+ mExpectingSynthesizedDown = false;
+ return false;
+ }
+ return isFullyCollapsed() || mBarState != StatusBarState.SHADE;
+ }
+
+ @Override
+ protected boolean shouldGestureIgnoreXTouchSlop(float x, float y) {
+ return !mAffordanceHelper.isOnAffordanceIcon(x, y);
+ }
+
+ private void onQsTouch(MotionEvent event) {
+ int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ if (pointerIndex < 0) {
+ pointerIndex = 0;
+ mTrackingPointer = event.getPointerId(pointerIndex);
+ }
+ final float y = event.getY(pointerIndex);
+ final float x = event.getX(pointerIndex);
+ final float h = y - mInitialTouchY;
+
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mQsTracking = true;
+ mInitialTouchY = y;
+ mInitialTouchX = x;
+ onQsExpansionStarted();
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ initVelocityTracker();
+ trackMovement(event);
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ final int upPointer = event.getPointerId(event.getActionIndex());
+ if (mTrackingPointer == upPointer) {
+ // gesture is ongoing, find a new pointer to track
+ final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+ final float newY = event.getY(newIndex);
+ final float newX = event.getX(newIndex);
+ mTrackingPointer = event.getPointerId(newIndex);
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ mInitialTouchY = newY;
+ mInitialTouchX = newX;
+ }
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ setQsExpansion(h + mInitialHeightOnTouch);
+ if (h >= getFalsingThreshold()) {
+ mQsTouchAboveFalsingThreshold = true;
+ }
+ trackMovement(event);
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mQsTracking = false;
+ mTrackingPointer = -1;
+ trackMovement(event);
+ float fraction = getQsExpansionFraction();
+ if (fraction != 0f || y >= mInitialTouchY) {
+ flingQsWithCurrentVelocity(y,
+ event.getActionMasked() == MotionEvent.ACTION_CANCEL);
+ }
+ if (mQsVelocityTracker != null) {
+ mQsVelocityTracker.recycle();
+ mQsVelocityTracker = null;
+ }
+ break;
+ }
+ }
+
+ private int getFalsingThreshold() {
+ float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+ return (int) (mQsFalsingThreshold * factor);
+ }
+
+ @Override
+ public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
+ cancelQsAnimation();
+ if (!mQsExpansionEnabled) {
+ amount = 0f;
+ }
+ float rounded = amount >= 1f ? amount : 0f;
+ setOverScrolling(rounded != 0f && isRubberbanded);
+ mQsExpansionFromOverscroll = rounded != 0f;
+ mLastOverscroll = rounded;
+ updateQsState();
+ setQsExpansion(mQsMinExpansionHeight + rounded);
+ }
+
+ @Override
+ public void flingTopOverscroll(float velocity, boolean open) {
+ mLastOverscroll = 0f;
+ mQsExpansionFromOverscroll = false;
+ setQsExpansion(mQsExpansionHeight);
+ flingSettings(!mQsExpansionEnabled && open ? 0f : velocity,
+ open && mQsExpansionEnabled ? FLING_EXPAND : FLING_COLLAPSE,
+ new Runnable() {
+ @Override
+ public void run() {
+ mStackScrollerOverscrolling = false;
+ setOverScrolling(false);
+ updateQsState();
+ }
+ }, false /* isClick */);
+ }
+
+ private void setOverScrolling(boolean overscrolling) {
+ mStackScrollerOverscrolling = overscrolling;
+ if (mQs == null) return;
+ mQs.setOverscrolling(overscrolling);
+ }
+
+ private void onQsExpansionStarted() {
+ onQsExpansionStarted(0);
+ }
+
+ protected void onQsExpansionStarted(int overscrollAmount) {
+ cancelQsAnimation();
+ cancelHeightAnimator();
+
+ // Reset scroll position and apply that position to the expanded height.
+ float height = mQsExpansionHeight - overscrollAmount;
+ setQsExpansion(height);
+ requestPanelHeightUpdate();
+ mNotificationStackScroller.checkSnoozeLeavebehind();
+
+ // When expanding QS, let's authenticate the user if possible,
+ // this will speed up notification actions.
+ if (height == 0) {
+ mStatusBar.requestFaceAuth();
+ }
+ }
+
+ private void setQsExpanded(boolean expanded) {
+ boolean changed = mQsExpanded != expanded;
+ if (changed) {
+ mQsExpanded = expanded;
+ updateQsState();
+ requestPanelHeightUpdate();
+ mFalsingManager.setQsExpanded(expanded);
+ mStatusBar.setQsExpanded(expanded);
+ mNotificationContainerParent.setQsExpanded(expanded);
+ mPulseExpansionHandler.setQsExpanded(expanded);
+ mKeyguardBypassController.setQSExpanded(expanded);
+ }
+ }
+
+ @Override
+ public void onStateChanged(int statusBarState) {
+ boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
+ boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
+ int oldState = mBarState;
+ boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD;
+ setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
+ setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
+
+ mBarState = statusBarState;
+ mKeyguardShowing = keyguardShowing;
+ if (mKeyguardShowing && isQsSplitEnabled()) {
+ mNotificationStackScroller.setVisibility(View.VISIBLE);
+ mQsFrame.setVisibility(View.VISIBLE);
+ mHomeControlsLayout.setVisibility(View.GONE);
+ }
+
+ if (oldState == StatusBarState.KEYGUARD
+ && (goingToFullShade || statusBarState == StatusBarState.SHADE_LOCKED)) {
+ animateKeyguardStatusBarOut();
+ long delay = mBarState == StatusBarState.SHADE_LOCKED
+ ? 0 : mKeyguardStateController.calculateGoingToFullShadeDelay();
+ mQs.animateHeaderSlidingIn(delay);
+ } else if (oldState == StatusBarState.SHADE_LOCKED
+ && statusBarState == StatusBarState.KEYGUARD) {
+ animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ mNotificationStackScroller.resetScrollPosition();
+ // Only animate header if the header is visible. If not, it will partially animate out
+ // the top of QS
+ if (!mQsExpanded) {
+ mQs.animateHeaderSlidingOut();
+ }
+ } else {
+ mKeyguardStatusBar.setAlpha(1f);
+ mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
+ ((PhoneStatusBarView) mBar).maybeShowDivider(keyguardShowing);
+ if (keyguardShowing && oldState != mBarState) {
+ if (mQs != null) {
+ mQs.hideImmediately();
+ }
+ }
+ }
+ updateKeyguardStatusBarForHeadsUp();
+ if (keyguardShowing) {
+ updateDozingVisibilities(false /* animate */);
+ }
+ // THe update needs to happen after the headerSlide in above, otherwise the translation
+ // would reset
+ updateQSPulseExpansion();
+ maybeAnimateBottomAreaAlpha();
+ resetHorizontalPanelPosition();
+ updateQsState();
+ }
+
+ private void maybeAnimateBottomAreaAlpha() {
+ mBottomAreaShadeAlphaAnimator.cancel();
+ if (mBarState == StatusBarState.SHADE_LOCKED) {
+ mBottomAreaShadeAlphaAnimator.start();
+ } else {
+ mBottomAreaShadeAlpha = 1f;
+ }
+ }
+
+ private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardStatusViewAnimating = false;
+ mKeyguardStatusView.setVisibility(View.INVISIBLE);
+ }
+ };
+
+ private final Runnable mAnimateKeyguardStatusViewGoneEndRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardStatusViewAnimating = false;
+ mKeyguardStatusView.setVisibility(View.GONE);
+ }
+ };
+
+ private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardStatusViewAnimating = false;
+ }
+ };
+
+ private final Runnable mAnimateKeyguardStatusBarInvisibleEndRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardStatusBar.setVisibility(View.INVISIBLE);
+ mKeyguardStatusBar.setAlpha(1f);
+ mKeyguardStatusBarAnimateAlpha = 1f;
+ }
+ };
+
+ private void animateKeyguardStatusBarOut() {
+ ValueAnimator anim = ValueAnimator.ofFloat(mKeyguardStatusBar.getAlpha(), 0f);
+ anim.addUpdateListener(mStatusBarAnimateAlphaListener);
+ anim.setStartDelay(mKeyguardStateController.isKeyguardFadingAway()
+ ? mKeyguardStateController.getKeyguardFadingAwayDelay()
+ : 0);
+
+ long duration;
+ if (mKeyguardStateController.isKeyguardFadingAway()) {
+ duration = mKeyguardStateController.getShortenedFadingAwayDuration();
+ } else {
+ duration = StackStateAnimator.ANIMATION_DURATION_STANDARD;
+ }
+ anim.setDuration(duration);
+
+ anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimateKeyguardStatusBarInvisibleEndRunnable.run();
+ }
+ });
+ anim.start();
+ }
+
+ private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
+ updateHeaderKeyguardAlpha();
+ }
+ };
+
+ private void animateKeyguardStatusBarIn(long duration) {
+ mKeyguardStatusBar.setVisibility(View.VISIBLE);
+ mKeyguardStatusBar.setAlpha(0f);
+ ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+ anim.addUpdateListener(mStatusBarAnimateAlphaListener);
+ anim.setDuration(duration);
+ anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ anim.start();
+ }
+
+ private final Runnable mAnimateKeyguardBottomAreaInvisibleEndRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardBottomArea.setVisibility(View.GONE);
+ }
+ };
+
+ private void setKeyguardBottomAreaVisibility(int statusBarState, boolean goingToFullShade) {
+ mKeyguardBottomArea.animate().cancel();
+ if (goingToFullShade) {
+ mKeyguardBottomArea.animate()
+ .alpha(0f)
+ .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
+ .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration())
+ .setInterpolator(Interpolators.ALPHA_OUT)
+ .withEndAction(mAnimateKeyguardBottomAreaInvisibleEndRunnable)
+ .start();
+ } else if (statusBarState == StatusBarState.KEYGUARD
+ || statusBarState == StatusBarState.SHADE_LOCKED) {
+ mKeyguardBottomArea.setVisibility(View.VISIBLE);
+ mKeyguardBottomArea.setAlpha(1f);
+ } else {
+ mKeyguardBottomArea.setVisibility(View.GONE);
+ }
+ }
+
+ private void setKeyguardStatusViewVisibility(int statusBarState, boolean keyguardFadingAway,
+ boolean goingToFullShade) {
+ mKeyguardStatusView.animate().cancel();
+ mKeyguardStatusViewAnimating = false;
+ if ((!keyguardFadingAway && mBarState == StatusBarState.KEYGUARD
+ && statusBarState != StatusBarState.KEYGUARD) || goingToFullShade) {
+ mKeyguardStatusViewAnimating = true;
+ mKeyguardStatusView.animate()
+ .alpha(0f)
+ .setStartDelay(0)
+ .setDuration(160)
+ .setInterpolator(Interpolators.ALPHA_OUT)
+ .withEndAction(mAnimateKeyguardStatusViewGoneEndRunnable);
+ if (keyguardFadingAway) {
+ mKeyguardStatusView.animate()
+ .setStartDelay(mKeyguardStateController.getKeyguardFadingAwayDelay())
+ .setDuration(mKeyguardStateController.getShortenedFadingAwayDuration())
+ .start();
+ }
+ } else if (mBarState == StatusBarState.SHADE_LOCKED
+ && statusBarState == StatusBarState.KEYGUARD) {
+ mKeyguardStatusView.setVisibility(View.VISIBLE);
+ mKeyguardStatusViewAnimating = true;
+ mKeyguardStatusView.setAlpha(0f);
+ mKeyguardStatusView.animate()
+ .alpha(1f)
+ .setStartDelay(0)
+ .setDuration(320)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable);
+ } else if (statusBarState == StatusBarState.KEYGUARD) {
+ if (keyguardFadingAway) {
+ mKeyguardStatusViewAnimating = true;
+ mKeyguardStatusView.animate()
+ .alpha(0)
+ .translationYBy(-getHeight() * 0.05f)
+ .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
+ .setDuration(125)
+ .setStartDelay(0)
+ .withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
+ .start();
+ } else {
+ mKeyguardStatusView.setVisibility(View.VISIBLE);
+ mKeyguardStatusView.setAlpha(1f);
+ }
+ } else {
+ mKeyguardStatusView.setVisibility(View.GONE);
+ mKeyguardStatusView.setAlpha(1f);
+ }
+ }
+
+ private void updateQsState() {
+ mNotificationStackScroller.setQsExpanded(mQsExpanded);
+ mNotificationStackScroller.setScrollingEnabled(
+ mBarState != StatusBarState.KEYGUARD && (!mQsExpanded
+ || mQsExpansionFromOverscroll));
+ updateEmptyShadeView();
+ if (mNPVPluginManager != null) {
+ mNPVPluginManager.changeVisibility((mBarState != StatusBarState.KEYGUARD)
+ ? View.VISIBLE
+ : View.INVISIBLE);
+ }
+ mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded
+ && !mStackScrollerOverscrolling && mQsScrimEnabled
+ ? View.VISIBLE
+ : View.INVISIBLE);
+ if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
+ mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
+ }
+ if (mQs == null) return;
+ mQs.setExpanded(mQsExpanded);
+ }
+
+ private void setQsExpansion(float height) {
+ height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
+ mQsFullyExpanded = height == mQsMaxExpansionHeight && mQsMaxExpansionHeight != 0;
+ if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling
+ && !mDozing) {
+ setQsExpanded(true);
+ } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
+ setQsExpanded(false);
+ }
+ mQsExpansionHeight = height;
+ updateQsExpansion();
+ requestScrollerTopPaddingUpdate(false /* animate */);
+ updateHeaderKeyguardAlpha();
+ if (mBarState == StatusBarState.SHADE_LOCKED
+ || mBarState == StatusBarState.KEYGUARD) {
+ updateKeyguardBottomAreaAlpha();
+ updateBigClockAlpha();
+ }
+ if (mBarState == StatusBarState.SHADE && mQsExpanded
+ && !mStackScrollerOverscrolling && mQsScrimEnabled) {
+ mQsNavbarScrim.setAlpha(getQsExpansionFraction());
+ }
+
+ if (mAccessibilityManager.isEnabled()) {
+ setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
+ }
+
+ if (!mFalsingManager.isUnlockingDisabled() && mQsFullyExpanded
+ && mFalsingManager.shouldEnforceBouncer()) {
+ mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
+ false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
+ }
+ for (int i = 0; i < mExpansionListeners.size(); i++) {
+ mExpansionListeners.get(i).onQsExpansionChanged(mQsMaxExpansionHeight != 0
+ ? mQsExpansionHeight / mQsMaxExpansionHeight : 0);
+ }
+ if (DEBUG) {
+ invalidate();
+ }
+ }
+
+ protected void updateQsExpansion() {
+ if (mQs == null) return;
+ float qsExpansionFraction = getQsExpansionFraction();
+ mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
+ int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight();
+ if (mNPVPluginManager != null) {
+ mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff);
+ }
+ mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction);
+ }
+
+ private String determineAccessibilityPaneTitle() {
+ if (mQs != null && mQs.isCustomizing()) {
+ return getContext().getString(R.string.accessibility_desc_quick_settings_edit);
+ } else if (mQsExpansionHeight != 0.0f && mQsFullyExpanded) {
+ // Upon initialisation when we are not layouted yet we don't want to announce that we
+ // are fully expanded, hence the != 0.0f check.
+ return getContext().getString(R.string.accessibility_desc_quick_settings);
+ } else if (mBarState == StatusBarState.KEYGUARD) {
+ return getContext().getString(R.string.accessibility_desc_lock_screen);
+ } else {
+ return getContext().getString(R.string.accessibility_desc_notification_shade);
+ }
+ }
+
+ private float calculateQsTopPadding() {
+ if (mKeyguardShowing
+ && (mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted)) {
+
+ // Either QS pushes the notifications down when fully expanded, or QS is fully above the
+ // notifications (mostly on tablets). maxNotificationPadding denotes the normal top
+ // padding on Keyguard, maxQsPadding denotes the top padding from the quick settings
+ // panel. We need to take the maximum and linearly interpolate with the panel expansion
+ // for a nice motion.
+ int maxNotificationPadding = getKeyguardNotificationStaticPadding();
+ int maxQsPadding = mQsMaxExpansionHeight + mQsNotificationTopPadding;
+ int max = mBarState == StatusBarState.KEYGUARD
+ ? Math.max(maxNotificationPadding, maxQsPadding)
+ : maxQsPadding;
+ return (int) MathUtils.lerp((float) mQsMinExpansionHeight, (float) max,
+ getExpandedFraction());
+ } else if (mQsSizeChangeAnimator != null) {
+ return Math.max((int) mQsSizeChangeAnimator.getAnimatedValue(),
+ getKeyguardNotificationStaticPadding());
+ } else if (mKeyguardShowing) {
+ // We can only do the smoother transition on Keyguard when we also are not collapsing
+ // from a scrolled quick settings.
+ return MathUtils.lerp((float) getKeyguardNotificationStaticPadding(),
+ (float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
+ getQsExpansionFraction());
+ } else {
+ return mQsExpansionHeight + mQsNotificationTopPadding;
+ }
+ }
+
+ /**
+ * @return the topPadding of notifications when on keyguard not respecting quick settings
+ * expansion
+ */
+ private int getKeyguardNotificationStaticPadding() {
+ if (!mKeyguardShowing) {
+ return 0;
+ }
+ if (!mKeyguardBypassController.getBypassEnabled()) {
+ return mClockPositionResult.stackScrollerPadding;
+ }
+ int collapsedPosition = mHeadsUpInset;
+ if (!mNotificationStackScroller.isPulseExpanding()) {
+ return collapsedPosition;
+ } else {
+ int expandedPosition = mClockPositionResult.stackScrollerPadding;
+ return (int) MathUtils.lerp(collapsedPosition, expandedPosition,
+ mNotificationStackScroller.calculateAppearFractionBypass());
+ }
+ }
+
+
+ protected void requestScrollerTopPaddingUpdate(boolean animate) {
+ mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(), animate);
+ if (mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()) {
+ // update the position of the header
+ updateQsExpansion();
+ }
+ }
+
+
+ private void updateQSPulseExpansion() {
+ if (mQs != null) {
+ mQs.setShowCollapsedOnKeyguard(mKeyguardShowing
+ && mKeyguardBypassController.getBypassEnabled()
+ && mNotificationStackScroller.isPulseExpanding());
+ }
+ }
+
+ private void trackMovement(MotionEvent event) {
+ if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
+ mLastTouchX = event.getX();
+ mLastTouchY = event.getY();
+ }
+
+ private void initVelocityTracker() {
+ if (mQsVelocityTracker != null) {
+ mQsVelocityTracker.recycle();
+ }
+ mQsVelocityTracker = VelocityTracker.obtain();
+ }
+
+ private float getCurrentQSVelocity() {
+ if (mQsVelocityTracker == null) {
+ return 0;
+ }
+ mQsVelocityTracker.computeCurrentVelocity(1000);
+ return mQsVelocityTracker.getYVelocity();
+ }
+
+ private void cancelQsAnimation() {
+ if (mQsExpansionAnimator != null) {
+ mQsExpansionAnimator.cancel();
+ }
+ }
+
+ /**
+ * @see #flingSettings(float, int, Runnable, boolean)
+ */
+ public void flingSettings(float vel, int type) {
+ flingSettings(vel, type, null, false /* isClick */);
+ }
+
+ /**
+ * Animates QS or QQS as if the user had swiped up or down.
+ *
+ * @param vel Finger velocity or 0 when not initiated by touch events.
+ * @param type Either {@link #FLING_EXPAND}, {@link #FLING_COLLAPSE} or {@link #FLING_HIDE}.
+ * @param onFinishRunnable Runnable to be executed at the end of animation.
+ * @param isClick If originated by click (different interpolator and duration.)
+ */
+ protected void flingSettings(float vel, int type, final Runnable onFinishRunnable,
+ boolean isClick) {
+ float target;
+ switch (type) {
+ case FLING_EXPAND:
+ target = mQsMaxExpansionHeight;
+ break;
+ case FLING_COLLAPSE:
+ target = mQsMinExpansionHeight;
+ break;
+ case FLING_HIDE:
+ default:
+ target = 0;
+ }
+ if (target == mQsExpansionHeight) {
+ if (onFinishRunnable != null) {
+ onFinishRunnable.run();
+ }
+ return;
+ }
+
+ // If we move in the opposite direction, reset velocity and use a different duration.
+ boolean oppositeDirection = false;
+ boolean expanding = type == FLING_EXPAND;
+ if (vel > 0 && !expanding || vel < 0 && expanding) {
+ vel = 0;
+ oppositeDirection = true;
+ }
+ ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
+ if (isClick) {
+ animator.setInterpolator(Interpolators.TOUCH_RESPONSE);
+ animator.setDuration(368);
+ } else {
+ mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
+ }
+ if (oppositeDirection) {
+ animator.setDuration(350);
+ }
+ animator.addUpdateListener(animation -> {
+ setQsExpansion((Float) animation.getAnimatedValue());
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mNotificationStackScroller.resetCheckSnoozeLeavebehind();
+ mQsExpansionAnimator = null;
+ if (onFinishRunnable != null) {
+ onFinishRunnable.run();
+ }
+ }
+ });
+ animator.start();
+ mQsExpansionAnimator = animator;
+ mQsAnimatorExpand = expanding;
+ }
+
+ /**
+ * @return Whether we should intercept a gesture to open Quick Settings.
+ */
+ private boolean shouldQuickSettingsIntercept(float x, float y, float yDiff) {
+ if (!mQsExpansionEnabled || mCollapsedOnDown
+ || (mKeyguardShowing && mKeyguardBypassController.getBypassEnabled())) {
+ return false;
+ }
+ View header = mKeyguardShowing || mQs == null ? mKeyguardStatusBar : mQs.getHeader();
+ final boolean onHeader = x >= mQsFrame.getX()
+ && x <= mQsFrame.getX() + mQsFrame.getWidth()
+ && y >= header.getTop() && y <= header.getBottom();
+ if (mQsExpanded) {
+ return onHeader || (yDiff < 0 && isInQsArea(x, y));
+ } else {
+ return onHeader;
+ }
+ }
+
+ @Override
+ protected boolean isScrolledToBottom() {
+ if (!isInSettings()) {
+ return mBarState == StatusBarState.KEYGUARD
+ || mNotificationStackScroller.isScrolledToBottom();
+ } else {
+ return true;
+ }
+ }
+
+ @Override
+ protected int getMaxPanelHeight() {
+ if (mKeyguardBypassController.getBypassEnabled() && mBarState == StatusBarState.KEYGUARD) {
+ return getMaxPanelHeightBypass();
+ } else {
+ return getMaxPanelHeightNonBypass();
+ }
+ }
+
+ private int getMaxPanelHeightNonBypass() {
+ int min = mStatusBarMinHeight;
+ if (!(mBarState == StatusBarState.KEYGUARD)
+ && mNotificationStackScroller.getNotGoneChildCount() == 0) {
+ int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
+ min = Math.max(min, minHeight);
+ }
+ int maxHeight;
+ if (mQsExpandImmediate || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted
+ || mPulsing) {
+ maxHeight = calculatePanelHeightQsExpanded();
+ } else {
+ maxHeight = calculatePanelHeightShade();
+ }
+ maxHeight = Math.max(maxHeight, min);
+ return maxHeight;
+ }
+
+ private int getMaxPanelHeightBypass() {
+ int position = mClockPositionAlgorithm.getExpandedClockPosition()
+ + mKeyguardStatusView.getHeight();
+ if (mNotificationStackScroller.getVisibleNotificationCount() != 0) {
+ position += mShelfHeight / 2.0f + mDarkIconSize / 2.0f;
+ }
+ return position;
+ }
+
+ public boolean isInSettings() {
+ return mQsExpanded;
+ }
+
+ public boolean isExpanding() {
+ return mIsExpanding;
+ }
+
+ @Override
+ protected void onHeightUpdated(float expandedHeight) {
+ if (!mQsExpanded || mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted) {
+ // Updating the clock position will set the top padding which might
+ // trigger a new panel height and re-position the clock.
+ // This is a circular dependency and should be avoided, otherwise we'll have
+ // a stack overflow.
+ if (mStackScrollerMeasuringPass > 2) {
+ if (DEBUG) Log.d(TAG, "Unstable notification panel height. Aborting.");
+ } else {
+ positionClockAndNotifications();
+ }
+ }
+ if (mQsExpandImmediate || mQsExpanded && !mQsTracking && mQsExpansionAnimator == null
+ && !mQsExpansionFromOverscroll) {
+ float t;
+ if (mKeyguardShowing) {
+
+ // On Keyguard, interpolate the QS expansion linearly to the panel expansion
+ t = expandedHeight / (getMaxPanelHeight());
+ } else {
+ // In Shade, interpolate linearly such that QS is closed whenever panel height is
+ // minimum QS expansion + minStackHeight
+ float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
+ + mNotificationStackScroller.getLayoutMinHeight();
+ float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
+ t = (expandedHeight - panelHeightQsCollapsed)
+ / (panelHeightQsExpanded - panelHeightQsCollapsed);
+ }
+ float targetHeight = mQsMinExpansionHeight
+ + t * (mQsMaxExpansionHeight - mQsMinExpansionHeight);
+ setQsExpansion(targetHeight);
+ mHomeControlsLayout.setTranslationY(targetHeight);
+ }
+ updateExpandedHeight(expandedHeight);
+ updateHeader();
+ updateNotificationTranslucency();
+ updatePanelExpanded();
+ updateGestureExclusionRect();
+ if (DEBUG) {
+ invalidate();
+ }
+ }
+
+ private void updatePanelExpanded() {
+ boolean isExpanded = !isFullyCollapsed() || mExpectingSynthesizedDown;
+ if (mPanelExpanded != isExpanded) {
+ mHeadsUpManager.setIsPanelExpanded(isExpanded);
+ mStatusBar.setPanelExpanded(isExpanded);
+ mPanelExpanded = isExpanded;
+ }
+ }
+
+ private int calculatePanelHeightShade() {
+ int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
+ int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin;
+ maxHeight += mNotificationStackScroller.getTopPaddingOverflow();
+
+ if (mBarState == StatusBarState.KEYGUARD) {
+ int minKeyguardPanelBottom = mClockPositionAlgorithm.getExpandedClockPosition()
+ + mKeyguardStatusView.getHeight()
+ + mNotificationStackScroller.getIntrinsicContentHeight();
+ return Math.max(maxHeight, minKeyguardPanelBottom);
+ } else {
+ return maxHeight;
+ }
+ }
+
+ private int calculatePanelHeightQsExpanded() {
+ float notificationHeight = mNotificationStackScroller.getHeight()
+ - mNotificationStackScroller.getEmptyBottomMargin()
+ - mNotificationStackScroller.getTopPadding();
+
+ // When only empty shade view is visible in QS collapsed state, simulate that we would have
+ // it in expanded QS state as well so we don't run into troubles when fading the view in/out
+ // and expanding/collapsing the whole panel from/to quick settings.
+ if (mNotificationStackScroller.getNotGoneChildCount() == 0
+ && mShowEmptyShadeView) {
+ notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
+ }
+ int maxQsHeight = mQsMaxExpansionHeight;
+
+ if (mKeyguardShowing) {
+ maxQsHeight += mQsNotificationTopPadding;
+ }
+
+ // If an animation is changing the size of the QS panel, take the animated value.
+ if (mQsSizeChangeAnimator != null) {
+ maxQsHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
+ }
+ float totalHeight = Math.max(
+ maxQsHeight, mBarState == StatusBarState.KEYGUARD
+ ? mClockPositionResult.stackScrollerPadding : 0)
+ + notificationHeight + mNotificationStackScroller.getTopPaddingOverflow();
+ if (totalHeight > mNotificationStackScroller.getHeight()) {
+ float fullyCollapsedHeight = maxQsHeight
+ + mNotificationStackScroller.getLayoutMinHeight();
+ totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
+ }
+ return (int) totalHeight;
+ }
+
+ private void updateNotificationTranslucency() {
+ float alpha = 1f;
+ if (mClosingWithAlphaFadeOut && !mExpandingFromHeadsUp &&
+ !mHeadsUpManager.hasPinnedHeadsUp()) {
+ alpha = getFadeoutAlpha();
+ }
+ if (mBarState == StatusBarState.KEYGUARD && !mHintAnimationRunning
+ && !mKeyguardBypassController.getBypassEnabled()) {
+ alpha *= mClockPositionResult.clockAlpha;
+ }
+ mNotificationStackScroller.setAlpha(alpha);
+ }
+
+ private float getFadeoutAlpha() {
+ float alpha;
+ if (mQsMinExpansionHeight == 0) {
+ return 1.0f;
+ }
+ alpha = getExpandedHeight() / mQsMinExpansionHeight;
+ alpha = Math.max(0, Math.min(alpha, 1));
+ alpha = (float) Math.pow(alpha, 0.75);
+ return alpha;
+ }
+
+ @Override
+ protected float getOverExpansionAmount() {
+ return mNotificationStackScroller.getCurrentOverScrollAmount(true /* top */);
+ }
+
+ @Override
+ protected float getOverExpansionPixels() {
+ return mNotificationStackScroller.getCurrentOverScrolledPixels(true /* top */);
+ }
+
+ /**
+ * Hides the header when notifications are colliding with it.
+ */
+ private void updateHeader() {
+ if (mBarState == StatusBarState.KEYGUARD) {
+ updateHeaderKeyguardAlpha();
+ }
+ updateQsExpansion();
+ }
+
+ protected float getHeaderTranslation() {
+ if (mBarState == StatusBarState.KEYGUARD && !mKeyguardBypassController.getBypassEnabled()) {
+ return -mQs.getQsMinExpansionHeight();
+ }
+ float appearAmount = mNotificationStackScroller.calculateAppearFraction(mExpandedHeight);
+ float startHeight = -mQsExpansionHeight;
+ if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()
+ && mNotificationStackScroller.isPulseExpanding()) {
+ if (!mPulseExpansionHandler.isExpanding()
+ && !mPulseExpansionHandler.getLeavingLockscreen()) {
+ // If we aborted the expansion we need to make sure the header doesn't reappear
+ // again after the header has animated away
+ appearAmount = 0;
+ } else {
+ appearAmount = mNotificationStackScroller.calculateAppearFractionBypass();
+ }
+ startHeight = -mQs.getQsMinExpansionHeight();
+ if (mNPVPluginManager != null) startHeight -= mNPVPluginManager.getHeight();
+ }
+ float translation = MathUtils.lerp(startHeight, 0,
+ Math.min(1.0f, appearAmount))
+ + mExpandOffset;
+ return Math.min(0, translation);
+ }
+
+ /**
+ * @return the alpha to be used to fade out the contents on Keyguard (status bar, bottom area)
+ * during swiping up
+ */
+ private float getKeyguardContentsAlpha() {
+ float alpha;
+ if (mBarState == StatusBarState.KEYGUARD) {
+
+ // When on Keyguard, we hide the header as soon as we expanded close enough to the
+ // header
+ alpha = getExpandedHeight()
+ /
+ (mKeyguardStatusBar.getHeight() + mNotificationsHeaderCollideDistance);
+ } else {
+
+ // In SHADE_LOCKED, the top card is already really close to the header. Hide it as
+ // soon as we start translating the stack.
+ alpha = getExpandedHeight() / mKeyguardStatusBar.getHeight();
+ }
+ alpha = MathUtils.saturate(alpha);
+ alpha = (float) Math.pow(alpha, 0.75);
+ return alpha;
+ }
+
+ private void updateHeaderKeyguardAlpha() {
+ if (!mKeyguardShowing) {
+ return;
+ }
+ float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
+ float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
+ * mKeyguardStatusBarAnimateAlpha;
+ newAlpha *= 1.0f - mKeyguardHeadsUpShowingAmount;
+ mKeyguardStatusBar.setAlpha(newAlpha);
+ boolean hideForBypass = mFirstBypassAttempt && mUpdateMonitor.shouldListenForFace()
+ || mDelayShowingKeyguardStatusBar;
+ mKeyguardStatusBar.setVisibility(newAlpha != 0f && !mDozing && !hideForBypass
+ ? VISIBLE : INVISIBLE);
+ }
+
+ private void updateKeyguardBottomAreaAlpha() {
+ // There are two possible panel expansion behaviors:
+ // • User dragging up to unlock: we want to fade out as quick as possible
+ // (ALPHA_EXPANSION_THRESHOLD) to avoid seeing the bouncer over the bottom area.
+ // • User tapping on lock screen: bouncer won't be visible but panel expansion will
+ // change due to "unlock hint animation." In this case, fading out the bottom area
+ // would also hide the message that says "swipe to unlock," we don't want to do that.
+ float expansionAlpha = MathUtils.map(isUnlockHintRunning()
+ ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f,
+ 0f, 1f, getExpandedFraction());
+ float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
+ alpha *= mBottomAreaShadeAlpha;
+ mKeyguardBottomArea.setAffordanceAlpha(alpha);
+ mKeyguardBottomArea.setImportantForAccessibility(alpha == 0f
+ ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+ : IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ View ambientIndicationContainer = mStatusBar.getAmbientIndicationContainer();
+ if (ambientIndicationContainer != null) {
+ ambientIndicationContainer.setAlpha(alpha);
+ }
+ }
+
+ /**
+ * Custom clock fades away when user drags up to unlock or pulls down quick settings.
+ *
+ * Updates alpha of custom clock to match the alpha of the KeyguardBottomArea. See
+ * {@link updateKeyguardBottomAreaAlpha}.
+ */
+ private void updateBigClockAlpha() {
+ float expansionAlpha = MathUtils.map(isUnlockHintRunning()
+ ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f, getExpandedFraction());
+ float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
+ mBigClockContainer.setAlpha(alpha);
+ }
+
+ @Override
+ protected void onExpandingStarted() {
+ super.onExpandingStarted();
+ mNotificationStackScroller.onExpansionStarted();
+ mIsExpanding = true;
+ mQsExpandedWhenExpandingStarted = mQsFullyExpanded;
+ if (mQsExpanded) {
+ onQsExpansionStarted();
+ }
+ // Since there are QS tiles in the header now, we need to make sure we start listening
+ // immediately so they can be up to date.
+ if (mQs == null) return;
+ mQs.setHeaderListening(true);
+ }
+
+ @Override
+ protected void onExpandingFinished() {
+ super.onExpandingFinished();
+ mNotificationStackScroller.onExpansionStopped();
+ mHeadsUpManager.onExpandingFinished();
+ mIsExpanding = false;
+ if (isFullyCollapsed()) {
+ DejankUtils.postAfterTraversal(new Runnable() {
+ @Override
+ public void run() {
+ setListening(false);
+ }
+ });
+
+ // Workaround b/22639032: Make sure we invalidate something because else RenderThread
+ // thinks we are actually drawing a frame put in reality we don't, so RT doesn't go
+ // ahead with rendering and we jank.
+ postOnAnimation(new Runnable() {
+ @Override
+ public void run() {
+ getParent().invalidateChild(NotificationPanelView.this, mDummyDirtyRect);
+ }
+ });
+ } else {
+ setListening(true);
+ }
+ mQsExpandImmediate = false;
+ mNotificationStackScroller.setShouldShowShelfOnly(false);
+ mTwoFingerQsExpandPossible = false;
+ mIsExpansionFromHeadsUp = false;
+ notifyListenersTrackingHeadsUp(null);
+ mExpandingFromHeadsUp = false;
+ setPanelScrimMinFraction(0.0f);
+ }
+
+ private void notifyListenersTrackingHeadsUp(ExpandableNotificationRow pickedChild) {
+ for (int i = 0; i < mTrackingHeadsUpListeners.size(); i++) {
+ Consumer<ExpandableNotificationRow> listener
+ = mTrackingHeadsUpListeners.get(i);
+ listener.accept(pickedChild);
+ }
+ }
+
+ private void setListening(boolean listening) {
+ mKeyguardStatusBar.setListening(listening);
+ if (mQs == null) return;
+ mQs.setListening(listening);
+ if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening);
+ }
+
+ @Override
+ public void expand(boolean animate) {
+ super.expand(animate);
+ setListening(true);
+ }
+
+ @Override
+ protected void setOverExpansion(float overExpansion, boolean isPixels) {
+ if (mConflictingQsExpansionGesture || mQsExpandImmediate) {
+ return;
+ }
+ if (mBarState != StatusBarState.KEYGUARD) {
+ mNotificationStackScroller.setOnHeightChangedListener(null);
+ if (isPixels) {
+ mNotificationStackScroller.setOverScrolledPixels(
+ overExpansion, true /* onTop */, false /* animate */);
+ } else {
+ mNotificationStackScroller.setOverScrollAmount(
+ overExpansion, true /* onTop */, false /* animate */);
+ }
+ mNotificationStackScroller.setOnHeightChangedListener(this);
+ }
+ }
+
+ @Override
+ protected void onTrackingStarted() {
+ mFalsingManager.onTrackingStarted(!mKeyguardStateController.canDismissLockScreen());
+ super.onTrackingStarted();
+ if (mQsFullyExpanded) {
+ mQsExpandImmediate = true;
+ mNotificationStackScroller.setShouldShowShelfOnly(true);
+ }
+ if (mBarState == StatusBarState.KEYGUARD
+ || mBarState == StatusBarState.SHADE_LOCKED) {
+ mAffordanceHelper.animateHideLeftRightIcon();
+ }
+ mNotificationStackScroller.onPanelTrackingStarted();
+ }
+
+ @Override
+ protected void onTrackingStopped(boolean expand) {
+ mFalsingManager.onTrackingStopped();
+ super.onTrackingStopped(expand);
+ if (expand) {
+ mNotificationStackScroller.setOverScrolledPixels(
+ 0.0f, true /* onTop */, true /* animate */);
+ }
+ mNotificationStackScroller.onPanelTrackingStopped();
+ if (expand && (mBarState == StatusBarState.KEYGUARD
+ || mBarState == StatusBarState.SHADE_LOCKED)) {
+ if (!mHintAnimationRunning) {
+ mAffordanceHelper.reset(true);
+ }
+ }
+ }
+
+ @Override
+ public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
+
+ // Block update if we are in quick settings and just the top padding changed
+ // (i.e. view == null).
+ if (view == null && mQsExpanded) {
+ return;
+ }
+ if (needsAnimation && mInterpolatedDarkAmount == 0) {
+ mAnimateNextPositionUpdate = true;
+ }
+ ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone();
+ ExpandableNotificationRow firstRow = firstChildNotGone instanceof ExpandableNotificationRow
+ ? (ExpandableNotificationRow) firstChildNotGone
+ : null;
+ if (firstRow != null
+ && (view == firstRow || (firstRow.getNotificationParent() == firstRow))) {
+ requestScrollerTopPaddingUpdate(false /* animate */);
+ }
+ requestPanelHeightUpdate();
+ }
+
+ @Override
+ public void onReset(ExpandableView view) {
+ }
+
+ public void onQsHeightChanged() {
+ mQsMaxExpansionHeight = mQs != null ? mQs.getDesiredHeight() : 0;
+ if (mQsExpanded && mQsFullyExpanded) {
+ mQsExpansionHeight = mQsMaxExpansionHeight;
+ requestScrollerTopPaddingUpdate(false /* animate */);
+ requestPanelHeightUpdate();
+ }
+ if (mAccessibilityManager.isEnabled()) {
+ setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
+ }
+ mNotificationStackScroller.setMaxTopPadding(
+ mQsMaxExpansionHeight + mQsNotificationTopPadding);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mAffordanceHelper.onConfigurationChanged();
+ if (newConfig.orientation != mLastOrientation) {
+ resetHorizontalPanelPosition();
+ }
+ mLastOrientation = newConfig.orientation;
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ mNavigationBarBottomHeight = insets.getStableInsetBottom();
+ updateMaxHeadsUpTranslation();
+ return insets;
+ }
+
+ private void updateMaxHeadsUpTranslation() {
+ mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mNavigationBarBottomHeight);
+ }
+
@Override
public void onRtlPropertiesChanged(int layoutDirection) {
if (layoutDirection != mOldLayoutDirection) {
@@ -64,10 +2681,328 @@
}
@Override
+ public void onClick(View v) {
+ onQsExpansionStarted();
+ if (mQsExpanded) {
+ flingSettings(0 /* vel */, FLING_COLLAPSE, null /* onFinishRunnable */,
+ true /* isClick */);
+ } else if (mQsExpansionEnabled) {
+ mLockscreenGestureLogger.write(MetricsEvent.ACTION_SHADE_QS_TAP, 0, 0);
+ flingSettings(0 /* vel */, FLING_EXPAND, null /* onFinishRunnable */,
+ true /* isClick */);
+ }
+ }
+
+ @Override
+ public void onAnimationToSideStarted(boolean rightPage, float translation, float vel) {
+ boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? rightPage : !rightPage;
+ mIsLaunchTransitionRunning = true;
+ mLaunchAnimationEndRunnable = null;
+ float displayDensity = mStatusBar.getDisplayDensity();
+ int lengthDp = Math.abs((int) (translation / displayDensity));
+ int velocityDp = Math.abs((int) (vel / displayDensity));
+ if (start) {
+ mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_DIALER, lengthDp, velocityDp);
+
+ mFalsingManager.onLeftAffordanceOn();
+ if (mFalsingManager.shouldEnforceBouncer()) {
+ mStatusBar.executeRunnableDismissingKeyguard(new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardBottomArea.launchLeftAffordance();
+ }
+ }, null, true /* dismissShade */, false /* afterKeyguardGone */,
+ true /* deferred */);
+ } else {
+ mKeyguardBottomArea.launchLeftAffordance();
+ }
+ } else {
+ if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals(
+ mLastCameraLaunchSource)) {
+ mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_CAMERA, lengthDp, velocityDp);
+ }
+ mFalsingManager.onCameraOn();
+ if (mFalsingManager.shouldEnforceBouncer()) {
+ mStatusBar.executeRunnableDismissingKeyguard(new Runnable() {
+ @Override
+ public void run() {
+ mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource);
+ }
+ }, null, true /* dismissShade */, false /* afterKeyguardGone */,
+ true /* deferred */);
+ }
+ else {
+ mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource);
+ }
+ }
+ mStatusBar.startLaunchTransitionTimeout();
+ mBlockTouches = true;
+ }
+
+ @Override
+ public void onAnimationToSideEnded() {
+ mIsLaunchTransitionRunning = false;
+ mIsLaunchTransitionFinished = true;
+ if (mLaunchAnimationEndRunnable != null) {
+ mLaunchAnimationEndRunnable.run();
+ mLaunchAnimationEndRunnable = null;
+ }
+ mStatusBar.readyForKeyguardDone();
+ }
+
+ @Override
+ protected void startUnlockHintAnimation() {
+ if (mPowerManager.isPowerSaveMode()) {
+ onUnlockHintStarted();
+ onUnlockHintFinished();
+ return;
+ }
+ super.startUnlockHintAnimation();
+ }
+
+ @Override
+ public float getMaxTranslationDistance() {
+ return (float) Math.hypot(getWidth(), getHeight());
+ }
+
+ @Override
+ public void onSwipingStarted(boolean rightIcon) {
+ mFalsingManager.onAffordanceSwipingStarted(rightIcon);
+ boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon
+ : rightIcon;
+ if (camera) {
+ mKeyguardBottomArea.bindCameraPrewarmService();
+ }
+ requestDisallowInterceptTouchEvent(true);
+ mOnlyAffordanceInThisMotion = true;
+ mQsTracking = false;
+ }
+
+ @Override
+ public void onSwipingAborted() {
+ mFalsingManager.onAffordanceSwipingAborted();
+ mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */);
+ }
+
+ @Override
+ public void onIconClicked(boolean rightIcon) {
+ if (mHintAnimationRunning) {
+ return;
+ }
+ mHintAnimationRunning = true;
+ mAffordanceHelper.startHintAnimation(rightIcon, new Runnable() {
+ @Override
+ public void run() {
+ mHintAnimationRunning = false;
+ mStatusBar.onHintFinished();
+ }
+ });
+ rightIcon = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon : rightIcon;
+ if (rightIcon) {
+ mStatusBar.onCameraHintStarted();
+ } else {
+ if (mKeyguardBottomArea.isLeftVoiceAssist()) {
+ mStatusBar.onVoiceAssistHintStarted();
+ } else {
+ mStatusBar.onPhoneHintStarted();
+ }
+ }
+ }
+
+ @Override
+ protected void onUnlockHintFinished() {
+ super.onUnlockHintFinished();
+ mNotificationStackScroller.setUnlockHintRunning(false);
+ }
+
+ @Override
+ protected void onUnlockHintStarted() {
+ super.onUnlockHintStarted();
+ mNotificationStackScroller.setUnlockHintRunning(true);
+ }
+
+ @Override
+ public KeyguardAffordanceView getLeftIcon() {
+ return getLayoutDirection() == LAYOUT_DIRECTION_RTL
+ ? mKeyguardBottomArea.getRightView()
+ : mKeyguardBottomArea.getLeftView();
+ }
+
+ @Override
+ public KeyguardAffordanceView getRightIcon() {
+ return getLayoutDirection() == LAYOUT_DIRECTION_RTL
+ ? mKeyguardBottomArea.getLeftView()
+ : mKeyguardBottomArea.getRightView();
+ }
+
+ @Override
+ public View getLeftPreview() {
+ return getLayoutDirection() == LAYOUT_DIRECTION_RTL
+ ? mKeyguardBottomArea.getRightPreview()
+ : mKeyguardBottomArea.getLeftPreview();
+ }
+
+ @Override
+ public View getRightPreview() {
+ return getLayoutDirection() == LAYOUT_DIRECTION_RTL
+ ? mKeyguardBottomArea.getLeftPreview()
+ : mKeyguardBottomArea.getRightPreview();
+ }
+
+ @Override
+ public float getAffordanceFalsingFactor() {
+ return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+ }
+
+ @Override
+ public boolean needsAntiFalsing() {
+ return mBarState == StatusBarState.KEYGUARD;
+ }
+
+ @Override
+ protected float getPeekHeight() {
+ if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
+ return mNotificationStackScroller.getPeekHeight();
+ } else {
+ return mQsMinExpansionHeight;
+ }
+ }
+
+ @Override
+ protected boolean shouldUseDismissingAnimation() {
+ return mBarState != StatusBarState.SHADE
+ && (mKeyguardStateController.canDismissLockScreen() || !isTracking());
+ }
+
+ @Override
+ protected boolean fullyExpandedClearAllVisible() {
+ return mNotificationStackScroller.isFooterViewNotGone()
+ && mNotificationStackScroller.isScrolledToBottom() && !mQsExpandImmediate;
+ }
+
+ @Override
+ protected boolean isClearAllVisible() {
+ return mNotificationStackScroller.isFooterViewContentVisible();
+ }
+
+ @Override
+ protected int getClearAllHeight() {
+ return mNotificationStackScroller.getFooterViewHeight();
+ }
+
+ @Override
+ protected boolean isTrackingBlocked() {
+ return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
+ }
+
+ public boolean isQsExpanded() {
+ return mQsExpanded;
+ }
+
+ public boolean isQsDetailShowing() {
+ return mQs.isShowingDetail();
+ }
+
+ public void closeQsDetail() {
+ mQs.closeDetail();
+ }
+
+ @Override
public boolean shouldDelayChildPressedState() {
return true;
}
+ public boolean isLaunchTransitionFinished() {
+ return mIsLaunchTransitionFinished;
+ }
+
+ public boolean isLaunchTransitionRunning() {
+ return mIsLaunchTransitionRunning;
+ }
+
+ public void setLaunchTransitionEndRunnable(Runnable r) {
+ mLaunchAnimationEndRunnable = r;
+ }
+
+ public void setEmptyDragAmount(float amount) {
+ mEmptyDragAmount = amount * 0.2f;
+ positionClockAndNotifications();
+ }
+
+ private void updateDozingVisibilities(boolean animate) {
+ mKeyguardBottomArea.setDozing(mDozing, animate);
+ if (!mDozing && animate) {
+ animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ }
+ }
+
+ @Override
+ public boolean isDozing() {
+ return mDozing;
+ }
+
+ public void showEmptyShadeView(boolean emptyShadeViewVisible) {
+ mShowEmptyShadeView = emptyShadeViewVisible;
+ updateEmptyShadeView();
+ }
+
+ private void updateEmptyShadeView() {
+ // Hide "No notifications" in QS.
+ mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
+ }
+
+ public void setQsScrimEnabled(boolean qsScrimEnabled) {
+ boolean changed = mQsScrimEnabled != qsScrimEnabled;
+ mQsScrimEnabled = qsScrimEnabled;
+ if (changed) {
+ updateQsState();
+ }
+ }
+
+ public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
+ mKeyguardUserSwitcher = keyguardUserSwitcher;
+ }
+
+ public void onScreenTurningOn() {
+ mKeyguardStatusView.dozeTimeTick();
+ }
+
+ @Override
+ public void onEmptySpaceClicked(float x, float y) {
+ onEmptySpaceClick(x);
+ }
+
+ @Override
+ protected boolean onMiddleClicked() {
+ switch (mBarState) {
+ case StatusBarState.KEYGUARD:
+ if (!mDozingOnDown) {
+ if (mKeyguardBypassController.getBypassEnabled()) {
+ mUpdateMonitor.requestFaceAuth();
+ } else {
+ mLockscreenGestureLogger.write(
+ MetricsEvent.ACTION_LS_HINT,
+ 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
+ startUnlockHintAnimation();
+ }
+ }
+ return true;
+ case StatusBarState.SHADE_LOCKED:
+ if (!mQsExpanded) {
+ mStatusBarStateController.setState(StatusBarState.KEYGUARD);
+ }
+ return true;
+ case StatusBarState.SHADE:
+
+ // This gets called in the middle of the touch handling, where the state is still
+ // that we are tracking the panel. Collapse the panel after this is done.
+ post(mPostCollapseRunnable);
+ return false;
+ default:
+ return true;
+ }
+ }
+
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
@@ -76,18 +3011,250 @@
}
}
- float getCurrentPanelAlpha() {
+ public float getCurrentPanelAlpha() {
return mCurrentPanelAlpha;
}
- void setPanelAlphaInternal(float alpha) {
+ public boolean setPanelAlpha(int alpha, boolean animate) {
+ if (mPanelAlpha != alpha) {
+ mPanelAlpha = alpha;
+ PropertyAnimator.setProperty(this, PANEL_ALPHA, alpha,
+ alpha == 255 ? PANEL_ALPHA_IN_PROPERTIES : PANEL_ALPHA_OUT_PROPERTIES, animate);
+ return true;
+ }
+ return false;
+ }
+
+ public void setPanelAlphaInternal(float alpha) {
mCurrentPanelAlpha = (int) alpha;
mAlphaPaint.setARGB(mCurrentPanelAlpha, 255, 255, 255);
invalidate();
}
- public void setDozing(boolean dozing) {
- mDozing = dozing;
+ public void setPanelAlphaEndAction(Runnable r) {
+ mPanelAlphaEndAction = r;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (DEBUG) {
+ Paint p = new Paint();
+ p.setColor(Color.RED);
+ p.setStrokeWidth(2);
+ p.setStyle(Paint.Style.STROKE);
+ canvas.drawLine(0, getMaxPanelHeight(), getWidth(), getMaxPanelHeight(), p);
+ p.setColor(Color.BLUE);
+ canvas.drawLine(0, getExpandedHeight(), getWidth(), getExpandedHeight(), p);
+ p.setColor(Color.GREEN);
+ canvas.drawLine(0, calculatePanelHeightQsExpanded(), getWidth(),
+ calculatePanelHeightQsExpanded(), p);
+ p.setColor(Color.YELLOW);
+ canvas.drawLine(0, calculatePanelHeightShade(), getWidth(),
+ calculatePanelHeightShade(), p);
+ p.setColor(Color.MAGENTA);
+ canvas.drawLine(0, calculateQsTopPadding(), getWidth(),
+ calculateQsTopPadding(), p);
+ p.setColor(Color.CYAN);
+ canvas.drawLine(0, mClockPositionResult.stackScrollerPadding, getWidth(),
+ mNotificationStackScroller.getTopPadding(), p);
+ p.setColor(Color.GRAY);
+ canvas.drawLine(0, mClockPositionResult.clockY, getWidth(),
+ mClockPositionResult.clockY, p);
+ }
+ }
+
+ @Override
+ public void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) {
+ mNotificationStackScroller.setInHeadsUpPinnedMode(inPinnedMode);
+ if (inPinnedMode) {
+ mHeadsUpExistenceChangedRunnable.run();
+ updateNotificationTranslucency();
+ } else {
+ setHeadsUpAnimatingAway(true);
+ mNotificationStackScroller.runAfterAnimationFinished(
+ mHeadsUpExistenceChangedRunnable);
+ }
+ updateGestureExclusionRect();
+ mHeadsUpPinnedMode = inPinnedMode;
+ updateHeadsUpVisibility();
+ updateKeyguardStatusBarForHeadsUp();
+ }
+
+ private void updateKeyguardStatusBarForHeadsUp() {
+ boolean showingKeyguardHeadsUp = mKeyguardShowing
+ && mHeadsUpAppearanceController.shouldBeVisible();
+ if (mShowingKeyguardHeadsUp != showingKeyguardHeadsUp) {
+ mShowingKeyguardHeadsUp = showingKeyguardHeadsUp;
+ if (mKeyguardShowing) {
+ PropertyAnimator.setProperty(this, KEYGUARD_HEADS_UP_SHOWING_AMOUNT,
+ showingKeyguardHeadsUp ? 1.0f : 0.0f, KEYGUARD_HUN_PROPERTIES,
+ true /* animate */);
+ } else {
+ PropertyAnimator.applyImmediately(this, KEYGUARD_HEADS_UP_SHOWING_AMOUNT, 0.0f);
+ }
+ }
+ }
+
+ private void setKeyguardHeadsUpShowingAmount(float amount) {
+ mKeyguardHeadsUpShowingAmount = amount;
+ updateHeaderKeyguardAlpha();
+ }
+
+ private float getKeyguardHeadsUpShowingAmount() {
+ return mKeyguardHeadsUpShowingAmount;
+ }
+
+ public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+ mHeadsUpAnimatingAway = headsUpAnimatingAway;
+ mNotificationStackScroller.setHeadsUpAnimatingAway(headsUpAnimatingAway);
+ updateHeadsUpVisibility();
+ }
+
+ private void updateHeadsUpVisibility() {
+ ((PhoneStatusBarView) mBar).setHeadsUpVisible(mHeadsUpAnimatingAway || mHeadsUpPinnedMode);
+ }
+
+ @Override
+ public void onHeadsUpPinned(NotificationEntry entry) {
+ if (!isOnKeyguard()) {
+ mNotificationStackScroller.generateHeadsUpAnimation(entry.getHeadsUpAnimationView(),
+ true);
+ }
+ }
+
+ @Override
+ public void onHeadsUpUnPinned(NotificationEntry entry) {
+
+ // When we're unpinning the notification via active edge they remain heads-upped,
+ // we need to make sure that an animation happens in this case, otherwise the notification
+ // will stick to the top without any interaction.
+ if (isFullyCollapsed() && entry.isRowHeadsUp() && !isOnKeyguard()) {
+ mNotificationStackScroller.generateHeadsUpAnimation(
+ entry.getHeadsUpAnimationView(), false);
+ entry.setHeadsUpIsVisible();
+ }
+ }
+
+ @Override
+ public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
+ mNotificationStackScroller.generateHeadsUpAnimation(entry, isHeadsUp);
+ }
+
+ @Override
+ public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
+ super.setHeadsUpManager(headsUpManager);
+ mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager,
+ mNotificationStackScroller.getHeadsUpCallback(), this);
+ }
+
+ public void setTrackedHeadsUp(ExpandableNotificationRow pickedChild) {
+ if (pickedChild != null) {
+ notifyListenersTrackingHeadsUp(pickedChild);
+ mExpandingFromHeadsUp = true;
+ }
+ // otherwise we update the state when the expansion is finished
+ }
+
+ @Override
+ protected void onClosingFinished() {
+ super.onClosingFinished();
+ resetHorizontalPanelPosition();
+ setClosingWithAlphaFadeout(false);
+ }
+
+ private void setClosingWithAlphaFadeout(boolean closing) {
+ mClosingWithAlphaFadeOut = closing;
+ mNotificationStackScroller.forceNoOverlappingRendering(closing);
+ }
+
+ /**
+ * Updates the vertical position of the panel so it is positioned closer to the touch
+ * responsible for opening the panel.
+ *
+ * @param x the x-coordinate the touch event
+ */
+ protected void updateVerticalPanelPosition(float x) {
+ if (mNotificationStackScroller.getWidth() * 1.75f > getWidth()) {
+ resetHorizontalPanelPosition();
+ return;
+ }
+ float leftMost = mPositionMinSideMargin + mNotificationStackScroller.getWidth() / 2;
+ float rightMost = getWidth() - mPositionMinSideMargin
+ - mNotificationStackScroller.getWidth() / 2;
+ if (Math.abs(x - getWidth() / 2) < mNotificationStackScroller.getWidth() / 4) {
+ x = getWidth() / 2;
+ }
+ x = Math.min(rightMost, Math.max(leftMost, x));
+ float center =
+ mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2;
+ setHorizontalPanelTranslation(x - center);
+ }
+
+ private void resetHorizontalPanelPosition() {
+ setHorizontalPanelTranslation(0f);
+ }
+
+ protected void setHorizontalPanelTranslation(float translation) {
+ mNotificationStackScroller.setTranslationX(translation);
+ mQsFrame.setTranslationX(translation);
+ int size = mVerticalTranslationListener.size();
+ for (int i = 0; i < size; i++) {
+ mVerticalTranslationListener.get(i).run();
+ }
+ }
+
+ protected void updateExpandedHeight(float expandedHeight) {
+ if (mTracking) {
+ mNotificationStackScroller.setExpandingVelocity(getCurrentExpandVelocity());
+ }
+ if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) {
+ // The expandedHeight is always the full panel Height when bypassing
+ expandedHeight = getMaxPanelHeightNonBypass();
+ }
+ mNotificationStackScroller.setExpandedHeight(expandedHeight);
+ updateKeyguardBottomAreaAlpha();
+ updateBigClockAlpha();
+ updateStatusBarIcons();
+ }
+
+ /**
+ * @return whether the notifications are displayed full width and don't have any margins on
+ * the side.
+ */
+ public boolean isFullWidth() {
+ return mIsFullWidth;
+ }
+
+ private void updateStatusBarIcons() {
+ boolean showIconsWhenExpanded = (isPanelVisibleBecauseOfHeadsUp() || isFullWidth())
+ && getExpandedHeight() < getOpeningHeight();
+ if (showIconsWhenExpanded && mNoVisibleNotifications && isOnKeyguard()) {
+ showIconsWhenExpanded = false;
+ }
+ if (showIconsWhenExpanded != mShowIconsWhenExpanded) {
+ mShowIconsWhenExpanded = showIconsWhenExpanded;
+ mCommandQueue.recomputeDisableFlags(mDisplayId, false);
+ }
+ }
+
+ private boolean isOnKeyguard() {
+ return mBarState == StatusBarState.KEYGUARD;
+ }
+
+ public void setPanelScrimMinFraction(float minFraction) {
+ mBar.panelScrimMinFractionChanged(minFraction);
+ }
+
+ public void clearNotificationEffects() {
+ mStatusBar.clearNotificationEffects();
+ }
+
+ @Override
+ protected boolean isPanelVisibleBecauseOfHeadsUp() {
+ return (mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway)
+ && mBarState == StatusBarState.SHADE;
}
@Override
@@ -95,4 +3262,382 @@
return !mDozing;
}
+ public void launchCamera(boolean animate, int source) {
+ if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
+ } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
+ } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) {
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER;
+ } else {
+
+ // Default.
+ mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
+ }
+
+ // If we are launching it when we are occluded already we don't want it to animate,
+ // nor setting these flags, since the occluded state doesn't change anymore, hence it's
+ // never reset.
+ if (!isFullyCollapsed()) {
+ setLaunchingAffordance(true);
+ } else {
+ animate = false;
+ }
+ mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null;
+ mAffordanceHelper.launchAffordance(animate, getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+ }
+
+ public void onAffordanceLaunchEnded() {
+ setLaunchingAffordance(false);
+ }
+
+ /**
+ * Set whether we are currently launching an affordance. This is currently only set when
+ * launched via a camera gesture.
+ */
+ private void setLaunchingAffordance(boolean launchingAffordance) {
+ mLaunchingAffordance = launchingAffordance;
+ getLeftIcon().setLaunchingAffordance(launchingAffordance);
+ getRightIcon().setLaunchingAffordance(launchingAffordance);
+ mKeyguardBypassController.setLaunchingAffordance(launchingAffordance);
+ if (mAffordanceLaunchListener != null) {
+ mAffordanceLaunchListener.accept(launchingAffordance);
+ }
+ }
+
+ /**
+ * Return true when a bottom affordance is launching an occluded activity with a splash screen.
+ */
+ public boolean isLaunchingAffordanceWithPreview() {
+ return mLaunchingAffordance && mAffordanceHasPreview;
+ }
+
+ /**
+ * Whether the camera application can be launched for the camera launch gesture.
+ */
+ public boolean canCameraGestureBeLaunched() {
+ if (!mStatusBar.isCameraAllowedByAdmin()) {
+ return false;
+ }
+
+ ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent();
+ String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
+ ? null : resolveInfo.activityInfo.packageName;
+ return packageToLaunch != null &&
+ (mBarState != StatusBarState.SHADE || !isForegroundApp(packageToLaunch))
+ && !mAffordanceHelper.isSwipingInProgress();
+ }
+
+ /**
+ * Return true if the applications with the package name is running in foreground.
+ *
+ * @param pkgName application package name.
+ */
+ private boolean isForegroundApp(String pkgName) {
+ ActivityManager am = getContext().getSystemService(ActivityManager.class);
+ List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+ return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
+ }
+
+ private void setGroupManager(NotificationGroupManager groupManager) {
+ mGroupManager = groupManager;
+ }
+
+ public boolean hideStatusBarIconsWhenExpanded() {
+ if (mLaunchingNotification) {
+ return mHideIconsDuringNotificationLaunch;
+ }
+ if (mHeadsUpAppearanceController != null
+ && mHeadsUpAppearanceController.shouldBeVisible()) {
+ return false;
+ }
+ return !isFullWidth() || !mShowIconsWhenExpanded;
+ }
+
+ private final FragmentListener mFragmentListener = new FragmentListener() {
+ @Override
+ public void onFragmentViewCreated(String tag, Fragment fragment) {
+ mQs = (QS) fragment;
+ mQs.setPanelView(NotificationPanelView.this);
+ mQs.setExpandClickListener(NotificationPanelView.this);
+ mQs.setHeaderClickable(mQsExpansionEnabled);
+ updateQSPulseExpansion();
+ mQs.setOverscrolling(mStackScrollerOverscrolling);
+
+ // recompute internal state when qspanel height changes
+ mQs.getView().addOnLayoutChangeListener(
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ final int height = bottom - top;
+ final int oldHeight = oldBottom - oldTop;
+ if (height != oldHeight) {
+ onQsHeightChanged();
+ }
+ });
+ mNotificationStackScroller.setQsContainer((ViewGroup) mQs.getView());
+ if (mQs instanceof QSFragment) {
+ mKeyguardStatusBar.setQSPanel(((QSFragment) mQs).getQsPanel());
+ }
+ updateQsExpansion();
+ }
+
+ @Override
+ public void onFragmentViewDestroyed(String tag, Fragment fragment) {
+ // Manual handling of fragment lifecycle is only required because this bridges
+ // non-fragment and fragment code. Once we are using a fragment for the notification
+ // panel, mQs will not need to be null cause it will be tied to the same lifecycle.
+ if (fragment == mQs) {
+ mQs = null;
+ }
+ }
+ };
+
+ @Override
+ public void setTouchAndAnimationDisabled(boolean disabled) {
+ super.setTouchAndAnimationDisabled(disabled);
+ if (disabled && mAffordanceHelper.isSwipingInProgress() && !mIsLaunchTransitionRunning) {
+ mAffordanceHelper.reset(false /* animate */);
+ }
+ mNotificationStackScroller.setAnimationsEnabled(!disabled);
+ }
+
+ /**
+ * Sets the dozing state.
+ *
+ * @param dozing {@code true} when dozing.
+ * @param animate if transition should be animated.
+ * @param wakeUpTouchLocation touch event location - if woken up by SLPI sensor.
+ */
+ public void setDozing(boolean dozing, boolean animate, PointF wakeUpTouchLocation) {
+ if (dozing == mDozing) return;
+ mDozing = dozing;
+ mNotificationStackScroller.setDozing(mDozing, animate, wakeUpTouchLocation);
+ mKeyguardBottomArea.setDozing(mDozing, animate);
+
+ if (dozing) {
+ mBottomAreaShadeAlphaAnimator.cancel();
+ }
+
+ if (mBarState == StatusBarState.KEYGUARD
+ || mBarState == StatusBarState.SHADE_LOCKED) {
+ updateDozingVisibilities(animate);
+ }
+
+ final float dozeAmount = dozing ? 1 : 0;
+ mStatusBarStateController.setDozeAmount(dozeAmount, animate);
+ }
+
+ @Override
+ public void onDozeAmountChanged(float linearAmount, float amount) {
+ mInterpolatedDarkAmount = amount;
+ mLinearDarkAmount = linearAmount;
+ mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount);
+ mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
+ positionClockAndNotifications();
+ }
+
+ public void setPulsing(boolean pulsing) {
+ mPulsing = pulsing;
+ final boolean animatePulse = !mDozeParameters.getDisplayNeedsBlanking()
+ && mDozeParameters.getAlwaysOn();
+ if (animatePulse) {
+ mAnimateNextPositionUpdate = true;
+ }
+ // Do not animate the clock when waking up from a pulse.
+ // The height callback will take care of pushing the clock to the right position.
+ if (!mPulsing && !mDozing) {
+ mAnimateNextPositionUpdate = false;
+ }
+ mNotificationStackScroller.setPulsing(pulsing, animatePulse);
+ mKeyguardStatusView.setPulsing(pulsing);
+ }
+
+ public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
+ if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) {
+ mAmbientIndicationBottomPadding = ambientIndicationBottomPadding;
+ mStatusBar.updateKeyguardMaxNotifications();
+ }
+ }
+
+ public void dozeTimeTick() {
+ mKeyguardBottomArea.dozeTimeTick();
+ mKeyguardStatusView.dozeTimeTick();
+ if (mInterpolatedDarkAmount > 0) {
+ positionClockAndNotifications();
+ }
+ }
+
+ public void setStatusAccessibilityImportance(int mode) {
+ mKeyguardStatusView.setImportantForAccessibility(mode);
+ }
+
+ /**
+ * TODO: this should be removed.
+ * It's not correct to pass this view forward because other classes will end up adding
+ * children to it. Theme will be out of sync.
+ *
+ * @return bottom area view
+ */
+ public KeyguardBottomAreaView getKeyguardBottomAreaView() {
+ return mKeyguardBottomArea;
+ }
+
+ public void setUserSetupComplete(boolean userSetupComplete) {
+ mUserSetupComplete = userSetupComplete;
+ mKeyguardBottomArea.setUserSetupComplete(userSetupComplete);
+ }
+
+ public void applyExpandAnimationParams(ExpandAnimationParameters params) {
+ mExpandOffset = params != null ? params.getTopChange() : 0;
+ updateQsExpansion();
+ if (params != null) {
+ boolean hideIcons = params.getProgress(
+ ActivityLaunchAnimator.ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f;
+ if (hideIcons != mHideIconsDuringNotificationLaunch) {
+ mHideIconsDuringNotificationLaunch = hideIcons;
+ if (!hideIcons) {
+ mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
+ }
+ }
+ }
+ }
+
+ public void addTrackingHeadsUpListener(Consumer<ExpandableNotificationRow> listener) {
+ mTrackingHeadsUpListeners.add(listener);
+ }
+
+ public void removeTrackingHeadsUpListener(Consumer<ExpandableNotificationRow> listener) {
+ mTrackingHeadsUpListeners.remove(listener);
+ }
+
+ public void addVerticalTranslationListener(Runnable verticalTranslationListener) {
+ mVerticalTranslationListener.add(verticalTranslationListener);
+ }
+
+ public void removeVerticalTranslationListener(Runnable verticalTranslationListener) {
+ mVerticalTranslationListener.remove(verticalTranslationListener);
+ }
+
+ public void setHeadsUpAppearanceController(
+ HeadsUpAppearanceController headsUpAppearanceController) {
+ mHeadsUpAppearanceController = headsUpAppearanceController;
+ }
+
+ /**
+ * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
+ * security view of the bouncer.
+ */
+ public void onBouncerPreHideAnimation() {
+ setKeyguardStatusViewVisibility(mBarState, true /* keyguardFadingAway */,
+ false /* goingToFullShade */);
+ }
+
+ /**
+ * Do not let the user drag the shade up and down for the current touch session.
+ * This is necessary to avoid shade expansion while/after the bouncer is dismissed.
+ */
+ public void blockExpansionForCurrentTouch() {
+ mBlockingExpansionForCurrentTouch = mTracking;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ super.dump(fd, pw, args);
+ pw.println(" gestureExclusionRect: " + calculateGestureExclusionRect());
+ if (mKeyguardStatusBar != null) {
+ mKeyguardStatusBar.dump(fd, pw, args);
+ }
+ if (mKeyguardStatusView != null) {
+ mKeyguardStatusView.dump(fd, pw, args);
+ }
+ }
+
+ public boolean hasActiveClearableNotifications() {
+ return mNotificationStackScroller.hasActiveClearableNotifications(ROWS_ALL);
+ }
+
+ @Override
+ public void onZenChanged(int zen) {
+ updateShowEmptyShadeView();
+ }
+
+ private void updateShowEmptyShadeView() {
+ boolean showEmptyShadeView =
+ mBarState != StatusBarState.KEYGUARD && !mEntryManager.hasActiveNotifications();
+ showEmptyShadeView(showEmptyShadeView);
+ }
+
+ public RemoteInputController.Delegate createRemoteInputDelegate() {
+ return mNotificationStackScroller.createDelegate();
+ }
+
+ public void updateNotificationViews() {
+ mNotificationStackScroller.updateSectionBoundaries();
+ mNotificationStackScroller.updateSpeedBumpIndex();
+ mNotificationStackScroller.updateFooter();
+ updateShowEmptyShadeView();
+ mNotificationStackScroller.updateIconAreaViews();
+ }
+
+ public void onUpdateRowStates() {
+ mNotificationStackScroller.onUpdateRowStates();
+ }
+
+ public boolean hasPulsingNotifications() {
+ return mNotificationStackScroller.hasPulsingNotifications();
+ }
+
+ public ActivatableNotificationView getActivatedChild() {
+ return mNotificationStackScroller.getActivatedChild();
+ }
+
+ public void setActivatedChild(ActivatableNotificationView o) {
+ mNotificationStackScroller.setActivatedChild(o);
+ }
+
+ public void runAfterAnimationFinished(Runnable r) {
+ mNotificationStackScroller.runAfterAnimationFinished(r);
+ }
+
+ public void setScrollingEnabled(boolean b) {
+ mNotificationStackScroller.setScrollingEnabled(b);
+ }
+
+ public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager,
+ NotificationShelf notificationShelf,
+ HeadsUpManagerPhone headsUpManager,
+ NotificationIconAreaController notificationIconAreaController,
+ ScrimController scrimController) {
+ setStatusBar(statusBar);
+ setGroupManager(mGroupManager);
+ mNotificationStackScroller.setNotificationPanel(this);
+ mNotificationStackScroller.setIconAreaController(notificationIconAreaController);
+ mNotificationStackScroller.setStatusBar(statusBar);
+ mNotificationStackScroller.setGroupManager(groupManager);
+ mNotificationStackScroller.setShelf(notificationShelf);
+ mNotificationStackScroller.setScrimController(scrimController);
+ updateShowEmptyShadeView();
+ }
+
+ public void showTransientIndication(int id) {
+ mKeyguardIndicationController.showTransientIndication(id);
+ }
+
+ @Override
+ public void onDynamicPrivacyChanged() {
+ // Do not request animation when pulsing or waking up, otherwise the clock wiill be out
+ // of sync with the notification panel.
+ if (mLinearDarkAmount != 0) {
+ return;
+ }
+ mAnimateNextPositionUpdate = true;
+ }
+
+ public void setOnReinflationListener(Runnable onReinflationListener) {
+ mOnReinflationListener = onReinflationListener;
+ }
+
+ public static boolean isQsSplitEnabled() {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.QS_SPLIT_ENABLED, false);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
deleted file mode 100644
index bbde25b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ /dev/null
@@ -1,3733 +0,0 @@
-/*
- * Copyright (C) 2019 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 com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.app.ActivityManager;
-import android.app.Fragment;
-import android.app.StatusBarManager;
-import android.content.Context;
-import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.drawable.Drawable;
-import android.hardware.biometrics.BiometricSourceType;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.provider.DeviceConfig;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.LatencyTracker;
-import com.android.keyguard.KeyguardClockSwitch;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.DisplayId;
-import com.android.systemui.doze.DozeLog;
-import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.HomeControlsPlugin;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.qs.QSFragment;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FlingAnimationUtils;
-import com.android.systemui.statusbar.GestureRecorder;
-import com.android.systemui.statusbar.KeyguardAffordanceView;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
-import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
-import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
-import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
-import com.android.systemui.util.Utils;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-import javax.inject.Inject;
-
-@StatusBarComponent.StatusBarScope
-public class NotificationPanelViewController extends PanelViewController {
-
- private static final boolean DEBUG = false;
-
- /**
- * Fling expanding QS.
- */
- private static final int FLING_EXPAND = 0;
-
- /**
- * Fling collapsing QS, potentially stopping when QS becomes QQS.
- */
- private static final int FLING_COLLAPSE = 1;
-
- /**
- * Fling until QS is completely hidden.
- */
- private static final int FLING_HIDE = 2;
- private final DozeParameters mDozeParameters;
- private final OnHeightChangedListener mOnHeightChangedListener = new OnHeightChangedListener();
- private final OnClickListener mOnClickListener = new OnClickListener();
- private final OnOverscrollTopChangedListener
- mOnOverscrollTopChangedListener =
- new OnOverscrollTopChangedListener();
- private final KeyguardAffordanceHelperCallback
- mKeyguardAffordanceHelperCallback =
- new KeyguardAffordanceHelperCallback();
- private final OnEmptySpaceClickListener
- mOnEmptySpaceClickListener =
- new OnEmptySpaceClickListener();
- private final MyOnHeadsUpChangedListener
- mOnHeadsUpChangedListener =
- new MyOnHeadsUpChangedListener();
- private final HeightListener mHeightListener = new HeightListener();
- private final ZenModeControllerCallback
- mZenModeControllerCallback =
- new ZenModeControllerCallback();
- private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
- private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener();
- private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
- private final NotificationPanelView mView;
- private final MetricsLogger mMetricsLogger;
- private final ActivityManager mActivityManager;
- private final ZenModeController mZenModeController;
- private final ConfigurationController mConfigurationController;
- private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
-
- private double mQqsSplitFraction;
-
- // Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
- // changed.
- private static final int CAP_HEIGHT = 1456;
- private static final int FONT_HEIGHT = 2163;
-
- /**
- * Maximum time before which we will expand the panel even for slow motions when getting a
- * touch passed over from launcher.
- */
- private static final int MAX_TIME_TO_OPEN_WHEN_FLINGING_FROM_LAUNCHER = 300;
-
- private static final String COUNTER_PANEL_OPEN = "panel_open";
- private static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
- private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek";
-
- private static final Rect M_DUMMY_DIRTY_RECT = new Rect(0, 0, 1, 1);
- private static final Rect EMPTY_RECT = new Rect();
-
- private static final AnimationProperties
- CLOCK_ANIMATION_PROPERTIES =
- new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- private final AnimatableProperty KEYGUARD_HEADS_UP_SHOWING_AMOUNT = AnimatableProperty.from(
- "KEYGUARD_HEADS_UP_SHOWING_AMOUNT",
- (notificationPanelView, aFloat) -> setKeyguardHeadsUpShowingAmount(aFloat),
- (Function<NotificationPanelView, Float>) notificationPanelView ->
- getKeyguardHeadsUpShowingAmount(),
- R.id.keyguard_hun_animator_tag, R.id.keyguard_hun_animator_end_tag,
- R.id.keyguard_hun_animator_start_tag);
- private static final AnimationProperties
- KEYGUARD_HUN_PROPERTIES =
- new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- @VisibleForTesting
- final KeyguardUpdateMonitorCallback
- mKeyguardUpdateCallback =
- new KeyguardUpdateMonitorCallback() {
-
- @Override
- public void onBiometricAuthenticated(int userId,
- BiometricSourceType biometricSourceType) {
- if (mFirstBypassAttempt && mUpdateMonitor.isUnlockingWithBiometricAllowed()) {
- mDelayShowingKeyguardStatusBar = true;
- }
- }
-
- @Override
- public void onBiometricRunningStateChanged(boolean running,
- BiometricSourceType biometricSourceType) {
- boolean
- keyguardOrShadeLocked =
- mBarState == StatusBarState.KEYGUARD
- || mBarState == StatusBarState.SHADE_LOCKED;
- if (!running && mFirstBypassAttempt && keyguardOrShadeLocked && !mDozing
- && !mDelayShowingKeyguardStatusBar) {
- mFirstBypassAttempt = false;
- animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- }
- }
-
- @Override
- public void onFinishedGoingToSleep(int why) {
- mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
- mDelayShowingKeyguardStatusBar = false;
- }
- };
-
- private final InjectionInflationController mInjectionInflationController;
- private final PowerManager mPowerManager;
- private final AccessibilityManager mAccessibilityManager;
- private final NotificationWakeUpCoordinator mWakeUpCoordinator;
- private final PulseExpansionHandler mPulseExpansionHandler;
- private final KeyguardBypassController mKeyguardBypassController;
- private final KeyguardUpdateMonitor mUpdateMonitor;
-
- private KeyguardAffordanceHelper mAffordanceHelper;
- private KeyguardUserSwitcher mKeyguardUserSwitcher;
- private KeyguardStatusBarView mKeyguardStatusBar;
- private ViewGroup mBigClockContainer;
- private QS mQs;
- private FrameLayout mQsFrame;
- private KeyguardStatusView mKeyguardStatusView;
- private View mQsNavbarScrim;
- private NotificationsQuickSettingsContainer mNotificationContainerParent;
- private NotificationStackScrollLayout mNotificationStackScroller;
- private FrameLayout mHomeControlsLayout;
- private boolean mAnimateNextPositionUpdate;
-
- private int mTrackingPointer;
- private VelocityTracker mQsVelocityTracker;
- private boolean mQsTracking;
-
- /**
- * If set, the ongoing touch gesture might both trigger the expansion in {@link PanelView} and
- * the expansion for quick settings.
- */
- private boolean mConflictingQsExpansionGesture;
-
- private boolean mPanelExpanded;
- private boolean mQsExpanded;
- private boolean mQsExpandedWhenExpandingStarted;
- private boolean mQsFullyExpanded;
- private boolean mKeyguardShowing;
- private boolean mDozing;
- private boolean mDozingOnDown;
- private int mBarState;
- private float mInitialHeightOnTouch;
- private float mInitialTouchX;
- private float mInitialTouchY;
- private float mQsExpansionHeight;
- private int mQsMinExpansionHeight;
- private int mQsMaxExpansionHeight;
- private int mQsPeekHeight;
- private boolean mStackScrollerOverscrolling;
- private boolean mQsExpansionFromOverscroll;
- private float mLastOverscroll;
- private boolean mQsExpansionEnabled = true;
- private ValueAnimator mQsExpansionAnimator;
- private FlingAnimationUtils mFlingAnimationUtils;
- private int mStatusBarMinHeight;
- private int mNotificationsHeaderCollideDistance;
- private float mEmptyDragAmount;
- private float mDownX;
- private float mDownY;
-
- private final KeyguardClockPositionAlgorithm
- mClockPositionAlgorithm =
- new KeyguardClockPositionAlgorithm();
- private final KeyguardClockPositionAlgorithm.Result
- mClockPositionResult =
- new KeyguardClockPositionAlgorithm.Result();
- private boolean mIsExpanding;
-
- private boolean mBlockTouches;
- // Used for two finger gesture as well as accessibility shortcut to QS.
- private boolean mQsExpandImmediate;
- private boolean mTwoFingerQsExpandPossible;
-
- /**
- * If we are in a panel collapsing motion, we reset scrollY of our scroll view but still
- * need to take this into account in our panel height calculation.
- */
- private boolean mQsAnimatorExpand;
- private boolean mIsLaunchTransitionFinished;
- private boolean mIsLaunchTransitionRunning;
- private Runnable mLaunchAnimationEndRunnable;
- private boolean mOnlyAffordanceInThisMotion;
- private boolean mKeyguardStatusViewAnimating;
- private ValueAnimator mQsSizeChangeAnimator;
-
- private boolean mShowEmptyShadeView;
-
- private boolean mQsScrimEnabled = true;
- private boolean mQsTouchAboveFalsingThreshold;
- private int mQsFalsingThreshold;
-
- private float mKeyguardStatusBarAnimateAlpha = 1f;
- private HeadsUpTouchHelper mHeadsUpTouchHelper;
- private boolean mListenForHeadsUp;
- private int mNavigationBarBottomHeight;
- private boolean mExpandingFromHeadsUp;
- private boolean mCollapsedOnDown;
- private int mPositionMinSideMargin;
- private int mLastOrientation = -1;
- private boolean mClosingWithAlphaFadeOut;
- private boolean mHeadsUpAnimatingAway;
- private boolean mLaunchingAffordance;
- private boolean mAffordanceHasPreview;
- private FalsingManager mFalsingManager;
- private String mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
-
- private Runnable mHeadsUpExistenceChangedRunnable = () -> {
- setHeadsUpAnimatingAway(false);
- notifyBarPanelExpansionChanged();
- };
- private NotificationGroupManager mGroupManager;
- private boolean mShowIconsWhenExpanded;
- private int mIndicationBottomPadding;
- private int mAmbientIndicationBottomPadding;
- private boolean mIsFullWidth;
- private boolean mBlockingExpansionForCurrentTouch;
-
- /**
- * Following variables maintain state of events when input focus transfer may occur.
- */
- private boolean mExpectingSynthesizedDown; // expecting to see synthesized DOWN event
- private boolean mLastEventSynthesizedDown; // last event was synthesized DOWN event
-
- /**
- * Current dark amount that follows regular interpolation curve of animation.
- */
- private float mInterpolatedDarkAmount;
-
- /**
- * Dark amount that animates from 0 to 1 or vice-versa in linear manner, even if the
- * interpolation curve is different.
- */
- private float mLinearDarkAmount;
-
- private boolean mPulsing;
- private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
- private boolean mUserSetupComplete;
- private int mQsNotificationTopPadding;
- private float mExpandOffset;
- private boolean mHideIconsDuringNotificationLaunch = true;
- private int mStackScrollerMeasuringPass;
- private ArrayList<Consumer<ExpandableNotificationRow>>
- mTrackingHeadsUpListeners =
- new ArrayList<>();
- private ArrayList<Runnable> mVerticalTranslationListener = new ArrayList<>();
- private HeadsUpAppearanceController mHeadsUpAppearanceController;
-
- private int mPanelAlpha;
- private Runnable mPanelAlphaEndAction;
- private float mBottomAreaShadeAlpha;
- private final ValueAnimator mBottomAreaShadeAlphaAnimator;
- private AnimatorListenerAdapter mAnimatorListenerAdapter = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mPanelAlphaEndAction != null) {
- mPanelAlphaEndAction.run();
- }
- }
- };
- private final AnimatableProperty mPanelAlphaAnimator = AnimatableProperty.from("panelAlpha",
- NotificationPanelView::setPanelAlphaInternal,
- NotificationPanelView::getCurrentPanelAlpha,
- R.id.panel_alpha_animator_tag, R.id.panel_alpha_animator_start_tag,
- R.id.panel_alpha_animator_end_tag);
- private final AnimationProperties mPanelAlphaOutPropertiesAnimator =
- new AnimationProperties().setDuration(150).setCustomInterpolator(
- mPanelAlphaAnimator.getProperty(), Interpolators.ALPHA_OUT);
- private final AnimationProperties mPanelAlphaInPropertiesAnimator =
- new AnimationProperties().setDuration(200).setAnimationFinishListener(
- mAnimatorListenerAdapter).setCustomInterpolator(
- mPanelAlphaAnimator.getProperty(), Interpolators.ALPHA_IN);
- private final NotificationEntryManager mEntryManager;
-
- private final CommandQueue mCommandQueue;
- private final NotificationLockscreenUserManager mLockscreenUserManager;
- private final ShadeController mShadeController;
- private int mDisplayId;
-
- /**
- * Cache the resource id of the theme to avoid unnecessary work in onThemeChanged.
- *
- * onThemeChanged is forced when the theme might not have changed. So, to avoid unncessary
- * work, check the current id with the cached id.
- */
- private int mThemeResId;
- private KeyguardIndicationController mKeyguardIndicationController;
- private Consumer<Boolean> mAffordanceLaunchListener;
- private int mShelfHeight;
- private Runnable mOnReinflationListener;
- private int mDarkIconSize;
- private int mHeadsUpInset;
- private boolean mHeadsUpPinnedMode;
- private float mKeyguardHeadsUpShowingAmount = 0.0f;
- private boolean mShowingKeyguardHeadsUp;
- private boolean mAllowExpandForSmallExpansion;
- private Runnable mExpandAfterLayoutRunnable;
-
- /**
- * If face auth with bypass is running for the first time after you turn on the screen.
- * (From aod or screen off)
- */
- private boolean mFirstBypassAttempt;
- /**
- * If auth happens successfully during {@code mFirstBypassAttempt}, and we should wait until
- * the keyguard is dismissed to show the status bar.
- */
- private boolean mDelayShowingKeyguardStatusBar;
-
- private PluginManager mPluginManager;
- private FrameLayout mPluginFrame;
- private NPVPluginManager mNPVPluginManager;
-
- @Inject
- public NotificationPanelViewController(NotificationPanelView view,
- InjectionInflationController injectionInflationController,
- NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
- DynamicPrivacyController dynamicPrivacyController,
- KeyguardBypassController bypassController, FalsingManager falsingManager,
- PluginManager pluginManager, ShadeController shadeController,
- NotificationLockscreenUserManager notificationLockscreenUserManager,
- NotificationEntryManager notificationEntryManager,
- KeyguardStateController keyguardStateController,
- StatusBarStateController statusBarStateController, DozeLog dozeLog,
- DozeParameters dozeParameters, CommandQueue commandQueue, VibratorHelper vibratorHelper,
- LatencyTracker latencyTracker, PowerManager powerManager,
- AccessibilityManager accessibilityManager, @DisplayId int displayId,
- KeyguardUpdateMonitor keyguardUpdateMonitor, MetricsLogger metricsLogger,
- ActivityManager activityManager, ZenModeController zenModeController,
- ConfigurationController configurationController,
- FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
- super(view, falsingManager, dozeLog, keyguardStateController,
- (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
- latencyTracker, flingAnimationUtilsBuilder);
- mView = view;
- mMetricsLogger = metricsLogger;
- mActivityManager = activityManager;
- mZenModeController = zenModeController;
- mConfigurationController = configurationController;
- mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
- mView.setWillNotDraw(!DEBUG);
- mInjectionInflationController = injectionInflationController;
- mFalsingManager = falsingManager;
- mPowerManager = powerManager;
- mWakeUpCoordinator = coordinator;
- mAccessibilityManager = accessibilityManager;
- mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
- setPanelAlpha(255, false /* animate */);
- mCommandQueue = commandQueue;
- mDisplayId = displayId;
- mPulseExpansionHandler = pulseExpansionHandler;
- mDozeParameters = dozeParameters;
- pulseExpansionHandler.setPulseExpandAbortListener(() -> {
- if (mQs != null) {
- mQs.animateHeaderSlidingOut();
- }
- });
- mThemeResId = mView.getContext().getThemeResId();
- mKeyguardBypassController = bypassController;
- mUpdateMonitor = keyguardUpdateMonitor;
- mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
- KeyguardStateController.Callback
- keyguardMonitorCallback =
- new KeyguardStateController.Callback() {
- @Override
- public void onKeyguardFadingAwayChanged() {
- if (!mKeyguardStateController.isKeyguardFadingAway()) {
- mFirstBypassAttempt = false;
- mDelayShowingKeyguardStatusBar = false;
- }
- }
- };
- mKeyguardStateController.addCallback(keyguardMonitorCallback);
- DynamicPrivacyControlListener
- dynamicPrivacyControlListener =
- new DynamicPrivacyControlListener();
- dynamicPrivacyController.addListener(dynamicPrivacyControlListener);
-
- mBottomAreaShadeAlphaAnimator = ValueAnimator.ofFloat(1f, 0);
- mBottomAreaShadeAlphaAnimator.addUpdateListener(animation -> {
- mBottomAreaShadeAlpha = (float) animation.getAnimatedValue();
- updateKeyguardBottomAreaAlpha();
- });
- mBottomAreaShadeAlphaAnimator.setDuration(160);
- mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
- mPluginManager = pluginManager;
- mShadeController = shadeController;
- mLockscreenUserManager = notificationLockscreenUserManager;
- mEntryManager = notificationEntryManager;
-
- mView.setBackgroundColor(Color.TRANSPARENT);
- OnAttachStateChangeListener onAttachStateChangeListener = new OnAttachStateChangeListener();
- mView.addOnAttachStateChangeListener(onAttachStateChangeListener);
- if (mView.isAttachedToWindow()) {
- onAttachStateChangeListener.onViewAttachedToWindow(mView);
- }
-
- mView.setOnApplyWindowInsetsListener(new OnApplyWindowInsetsListener());
-
- if (DEBUG) {
- mView.getOverlay().add(new DebugDrawable());
- }
-
- onFinishInflate();
- }
-
- private void onFinishInflate() {
- loadDimens();
- mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
- mKeyguardStatusView = mView.findViewById(R.id.keyguard_status_view);
-
- KeyguardClockSwitch keyguardClockSwitch = mView.findViewById(R.id.keyguard_clock_container);
- mBigClockContainer = mView.findViewById(R.id.big_clock_container);
- keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
-
- mHomeControlsLayout = mView.findViewById(R.id.home_controls_layout);
- mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
- mNotificationStackScroller = mView.findViewById(R.id.notification_stack_scroller);
- mNotificationStackScroller.setOnHeightChangedListener(mOnHeightChangedListener);
- mNotificationStackScroller.setOverscrollTopChangedListener(mOnOverscrollTopChangedListener);
- mNotificationStackScroller.setOnEmptySpaceClickListener(mOnEmptySpaceClickListener);
- addTrackingHeadsUpListener(mNotificationStackScroller::setTrackingHeadsUp);
- mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area);
- mQsNavbarScrim = mView.findViewById(R.id.qs_navbar_scrim);
- mLastOrientation = mResources.getConfiguration().orientation;
- mPluginFrame = mView.findViewById(R.id.plugin_frame);
- if (Settings.System.getInt(mView.getContext().getContentResolver(), "npv_plugin_flag", 0)
- == 1) {
- mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
- }
-
-
- initBottomArea();
-
- mWakeUpCoordinator.setStackScroller(mNotificationStackScroller);
- mQsFrame = mView.findViewById(R.id.qs_frame);
- mPulseExpansionHandler.setUp(
- mNotificationStackScroller, mExpansionCallback, mShadeController);
- mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
- @Override
- public void onFullyHiddenChanged(boolean isFullyHidden) {
- updateKeyguardStatusBarForHeadsUp();
- }
-
- @Override
- public void onPulseExpansionChanged(boolean expandingChanged) {
- if (mKeyguardBypassController.getBypassEnabled()) {
- // Position the notifications while dragging down while pulsing
- requestScrollerTopPaddingUpdate(false /* animate */);
- updateQSPulseExpansion();
- }
- }
- });
-
- mPluginManager.addPluginListener(new PluginListener<HomeControlsPlugin>() {
-
- @Override
- public void onPluginConnected(HomeControlsPlugin plugin, Context pluginContext) {
- plugin.sendParentGroup(mHomeControlsLayout);
- }
-
- @Override
- public void onPluginDisconnected(HomeControlsPlugin plugin) {
-
- }
- }, HomeControlsPlugin.class, false);
- }
-
- @Override
- protected void loadDimens() {
- super.loadDimens();
- mFlingAnimationUtils = mFlingAnimationUtilsBuilder.reset()
- .setMaxLengthSeconds(0.4f).build();
- mStatusBarMinHeight = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- mQsPeekHeight = mResources.getDimensionPixelSize(R.dimen.qs_peek_height);
- mNotificationsHeaderCollideDistance = mResources.getDimensionPixelSize(
- R.dimen.header_notifications_collide_distance);
- mClockPositionAlgorithm.loadDimens(mResources);
- mQsFalsingThreshold = mResources.getDimensionPixelSize(R.dimen.qs_falsing_threshold);
- mPositionMinSideMargin = mResources.getDimensionPixelSize(
- R.dimen.notification_panel_min_side_margin);
- mIndicationBottomPadding = mResources.getDimensionPixelSize(
- R.dimen.keyguard_indication_bottom_padding);
- mQsNotificationTopPadding = mResources.getDimensionPixelSize(
- R.dimen.qs_notification_padding);
- mShelfHeight = mResources.getDimensionPixelSize(R.dimen.notification_shelf_height);
- mDarkIconSize = mResources.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark);
- int statusbarHeight = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
- R.dimen.heads_up_status_bar_padding);
- mQqsSplitFraction = ((float) mResources.getInteger(R.integer.qqs_split_fraction)) / (
- mResources.getInteger(R.integer.qqs_split_fraction) + mResources.getInteger(
- R.integer.qs_split_fraction));
- }
-
- /**
- * Returns if there's a custom clock being presented.
- */
- public boolean hasCustomClock() {
- return mKeyguardStatusView.hasCustomClock();
- }
-
- private void setStatusBar(StatusBar bar) {
- // TODO: this can be injected.
- mStatusBar = bar;
- mKeyguardBottomArea.setStatusBar(mStatusBar);
- }
- /**
- * @see #launchCamera(boolean, int)
- * @see #setLaunchingAffordance(boolean)
- */
- public void setLaunchAffordanceListener(Consumer<Boolean> listener) {
- mAffordanceLaunchListener = listener;
- }
-
- public void updateResources() {
- int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
- int panelGravity = mResources.getInteger(R.integer.notification_panel_layout_gravity);
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mQsFrame.getLayoutParams();
- if (lp.width != qsWidth || lp.gravity != panelGravity) {
- lp.width = qsWidth;
- lp.gravity = panelGravity;
- mQsFrame.setLayoutParams(lp);
- }
-
- int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
- lp = (FrameLayout.LayoutParams) mNotificationStackScroller.getLayoutParams();
- if (lp.width != panelWidth || lp.gravity != panelGravity) {
- lp.width = panelWidth;
- lp.gravity = panelGravity;
- mNotificationStackScroller.setLayoutParams(lp);
- }
- int sideMargin = mResources.getDimensionPixelOffset(R.dimen.notification_side_paddings);
- int topMargin = sideMargin;
- lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
- if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
- || lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
- lp.width = qsWidth;
- lp.gravity = panelGravity;
- lp.leftMargin = sideMargin;
- lp.rightMargin = sideMargin;
- lp.topMargin = topMargin;
- mPluginFrame.setLayoutParams(lp);
- }
- }
-
- private void reInflateViews() {
- updateShowEmptyShadeView();
-
- // Re-inflate the status view group.
- int index = mView.indexOfChild(mKeyguardStatusView);
- mView.removeView(mKeyguardStatusView);
- mKeyguardStatusView = (KeyguardStatusView) mInjectionInflationController.injectable(
- LayoutInflater.from(mView.getContext())).inflate(
- R.layout.keyguard_status_view, mView, false);
- mView.addView(mKeyguardStatusView, index);
-
- // Re-associate the clock container with the keyguard clock switch.
- mBigClockContainer.removeAllViews();
- KeyguardClockSwitch keyguardClockSwitch = mView.findViewById(R.id.keyguard_clock_container);
- keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
-
- // Update keyguard bottom area
- index = mView.indexOfChild(mKeyguardBottomArea);
- mView.removeView(mKeyguardBottomArea);
- KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea;
- mKeyguardBottomArea = (KeyguardBottomAreaView) mInjectionInflationController.injectable(
- LayoutInflater.from(mView.getContext())).inflate(
- R.layout.keyguard_bottom_area, mView, false);
- mKeyguardBottomArea.initFrom(oldBottomArea);
- mView.addView(mKeyguardBottomArea, index);
- initBottomArea();
- mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
- mStatusBarStateListener.onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
- mStatusBarStateController.getInterpolatedDozeAmount());
-
- if (mKeyguardStatusBar != null) {
- mKeyguardStatusBar.onThemeChanged();
- }
-
- setKeyguardStatusViewVisibility(mBarState, false, false);
- setKeyguardBottomAreaVisibility(mBarState, false);
- if (mOnReinflationListener != null) {
- mOnReinflationListener.run();
- }
- reinflatePluginContainer();
- }
-
- private void reinflatePluginContainer() {
- int index = mView.indexOfChild(mPluginFrame);
- mView.removeView(mPluginFrame);
- mPluginFrame = (FrameLayout) mInjectionInflationController.injectable(
- LayoutInflater.from(mView.getContext())).inflate(
- R.layout.status_bar_expanded_plugin_frame, mView, false);
- mView.addView(mPluginFrame, index);
-
- Resources res = mView.getResources();
- int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width);
- int panelGravity = mView.getResources().getInteger(
- R.integer.notification_panel_layout_gravity);
- FrameLayout.LayoutParams lp;
- int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
- int topMargin = res.getDimensionPixelOffset(
- com.android.internal.R.dimen.quick_qs_total_height);
- if (Utils.useQsMediaPlayer(mView.getContext())) {
- topMargin = res.getDimensionPixelOffset(
- com.android.internal.R.dimen.quick_qs_total_height_with_media);
- }
- lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
- if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
- || lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
- lp.width = qsWidth;
- lp.gravity = panelGravity;
- lp.leftMargin = sideMargin;
- lp.rightMargin = sideMargin;
- lp.topMargin = topMargin;
- mPluginFrame.setLayoutParams(lp);
- }
-
- if (mNPVPluginManager != null) mNPVPluginManager.replaceFrameLayout(mPluginFrame);
- }
-
- private void initBottomArea() {
- mAffordanceHelper = new KeyguardAffordanceHelper(
- mKeyguardAffordanceHelperCallback, mView.getContext(), mFalsingManager);
- mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
- mKeyguardBottomArea.setStatusBar(mStatusBar);
- mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
- }
-
- public void setKeyguardIndicationController(KeyguardIndicationController indicationController) {
- mKeyguardIndicationController = indicationController;
- mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
- }
-
- private void updateGestureExclusionRect() {
- Rect exclusionRect = calculateGestureExclusionRect();
- mView.setSystemGestureExclusionRects(exclusionRect.isEmpty() ? Collections.EMPTY_LIST
- : Collections.singletonList(exclusionRect));
- }
-
- private Rect calculateGestureExclusionRect() {
- Rect exclusionRect = null;
- Region touchableRegion = mHeadsUpManager.calculateTouchableRegion();
- if (isFullyCollapsed() && touchableRegion != null) {
- // Note: The heads up manager also calculates the non-pinned touchable region
- exclusionRect = touchableRegion.getBounds();
- }
- return exclusionRect != null ? exclusionRect : EMPTY_RECT;
- }
-
- private void setIsFullWidth(boolean isFullWidth) {
- mIsFullWidth = isFullWidth;
- mNotificationStackScroller.setIsFullWidth(isFullWidth);
- }
-
- private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) {
- if (mQsSizeChangeAnimator != null) {
- oldHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
- mQsSizeChangeAnimator.cancel();
- }
- mQsSizeChangeAnimator = ValueAnimator.ofInt(oldHeight, newHeight);
- mQsSizeChangeAnimator.setDuration(300);
- mQsSizeChangeAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mQsSizeChangeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- requestScrollerTopPaddingUpdate(false /* animate */);
- requestPanelHeightUpdate();
- int height = (int) mQsSizeChangeAnimator.getAnimatedValue();
- mQs.setHeightOverride(height);
- }
- });
- mQsSizeChangeAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mQsSizeChangeAnimator = null;
- }
- });
- mQsSizeChangeAnimator.start();
- }
-
- /**
- * Positions the clock and notifications dynamically depending on how many notifications are
- * showing.
- */
- private void positionClockAndNotifications() {
- boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
- boolean animateClock = animate || mAnimateNextPositionUpdate;
- int stackScrollerPadding;
- if (mBarState != StatusBarState.KEYGUARD) {
- stackScrollerPadding = getUnlockedStackScrollerPadding();
- } else {
- int totalHeight = mView.getHeight();
- int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
- int clockPreferredY = mKeyguardStatusView.getClockPreferredY(totalHeight);
- boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
- final boolean
- hasVisibleNotifications =
- !bypassEnabled && mNotificationStackScroller.getVisibleNotificationCount() != 0;
- mKeyguardStatusView.setHasVisibleNotifications(hasVisibleNotifications);
- mClockPositionAlgorithm.setup(mStatusBarMinHeight, totalHeight - bottomPadding,
- mNotificationStackScroller.getIntrinsicContentHeight(), getExpandedFraction(),
- totalHeight, (int) (mKeyguardStatusView.getHeight() - mShelfHeight / 2.0f
- - mDarkIconSize / 2.0f), clockPreferredY, hasCustomClock(),
- hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
- bypassEnabled, getUnlockedStackScrollerPadding());
- mClockPositionAlgorithm.run(mClockPositionResult);
- PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.X,
- mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock);
- PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.Y,
- mClockPositionResult.clockY, CLOCK_ANIMATION_PROPERTIES, animateClock);
- updateNotificationTranslucency();
- updateClock();
- stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
- }
- mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
- mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
-
- mStackScrollerMeasuringPass++;
- requestScrollerTopPaddingUpdate(animate);
- mStackScrollerMeasuringPass = 0;
- mAnimateNextPositionUpdate = false;
- }
-
- /**
- * @return the padding of the stackscroller when unlocked
- */
- private int getUnlockedStackScrollerPadding() {
- return (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
- + mQsNotificationTopPadding;
- }
-
- /**
- * @param maximum the maximum to return at most
- * @return the maximum keyguard notifications that can fit on the screen
- */
- public int computeMaxKeyguardNotifications(int maximum) {
- float minPadding = mClockPositionAlgorithm.getMinStackScrollerPadding();
- int notificationPadding = Math.max(
- 1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height));
- NotificationShelf shelf = mNotificationStackScroller.getNotificationShelf();
- float
- shelfSize =
- shelf.getVisibility() == View.GONE ? 0
- : shelf.getIntrinsicHeight() + notificationPadding;
- float
- availableSpace =
- mNotificationStackScroller.getHeight() - minPadding - shelfSize - Math.max(
- mIndicationBottomPadding, mAmbientIndicationBottomPadding)
- - mKeyguardStatusView.getLogoutButtonHeight();
- int count = 0;
- for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) {
- ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i);
- if (!(child instanceof ExpandableNotificationRow)) {
- continue;
- }
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- boolean
- suppressedSummary =
- mGroupManager != null && mGroupManager.isSummaryOfSuppressedGroup(
- row.getEntry().getSbn());
- if (suppressedSummary) {
- continue;
- }
- if (!mLockscreenUserManager.shouldShowOnKeyguard(row.getEntry())) {
- continue;
- }
- if (row.isRemoved()) {
- continue;
- }
- availableSpace -= child.getMinHeight(true /* ignoreTemporaryStates */)
- + notificationPadding;
- if (availableSpace >= 0 && count < maximum) {
- count++;
- } else if (availableSpace > -shelfSize) {
- // if we are exactly the last view, then we can show us still!
- for (int j = i + 1; j < mNotificationStackScroller.getChildCount(); j++) {
- if (mNotificationStackScroller.getChildAt(
- j) instanceof ExpandableNotificationRow) {
- return count;
- }
- }
- count++;
- return count;
- } else {
- return count;
- }
- }
- return count;
- }
-
- private void updateClock() {
- if (!mKeyguardStatusViewAnimating) {
- mKeyguardStatusView.setAlpha(mClockPositionResult.clockAlpha);
- }
- }
-
- public void animateToFullShade(long delay) {
- mNotificationStackScroller.goToFullShade(delay);
- mView.requestLayout();
- mAnimateNextPositionUpdate = true;
- }
-
- public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
- mQsExpansionEnabled = qsExpansionEnabled;
- if (mQs == null) return;
- mQs.setHeaderClickable(qsExpansionEnabled);
- }
-
- @Override
- public void resetViews(boolean animate) {
- mIsLaunchTransitionFinished = false;
- mBlockTouches = false;
- if (!mLaunchingAffordance) {
- mAffordanceHelper.reset(false);
- mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
- }
- mStatusBar.getGutsManager().closeAndSaveGuts(true /* leavebehind */, true /* force */,
- true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
- if (animate) {
- animateCloseQs(true /* animateAway */);
- } else {
- closeQs();
- }
- mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, animate,
- !animate /* cancelAnimators */);
- mNotificationStackScroller.resetScrollPosition();
- }
-
- @Override
- public void collapse(boolean delayed, float speedUpFactor) {
- if (!canPanelBeCollapsed()) {
- return;
- }
-
- if (mQsExpanded) {
- mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
- }
- super.collapse(delayed, speedUpFactor);
- }
-
- public void closeQs() {
- cancelQsAnimation();
- setQsExpansion(mQsMinExpansionHeight);
- }
-
- public void cancelAnimation() {
- mView.animate().cancel();
- }
-
-
- /**
- * Animate QS closing by flinging it.
- * If QS is expanded, it will collapse into QQS and stop.
- *
- * @param animateAway Do not stop when QS becomes QQS. Fling until QS isn't visible anymore.
- */
- public void animateCloseQs(boolean animateAway) {
- if (mQsExpansionAnimator != null) {
- if (!mQsAnimatorExpand) {
- return;
- }
- float height = mQsExpansionHeight;
- mQsExpansionAnimator.cancel();
- setQsExpansion(height);
- }
- flingSettings(0 /* vel */, animateAway ? FLING_HIDE : FLING_COLLAPSE);
- }
-
- public void expandWithQs() {
- if (mQsExpansionEnabled) {
- mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
- }
- if (isFullyCollapsed()) {
- expand(true /* animate */);
- } else {
- flingSettings(0 /* velocity */, FLING_EXPAND);
- }
- }
-
- public void expandWithoutQs() {
- if (isQsExpanded()) {
- flingSettings(0 /* velocity */, FLING_COLLAPSE);
- } else {
- expand(true /* animate */);
- }
- }
-
- @Override
- public void fling(float vel, boolean expand) {
- GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
- if (gr != null) {
- gr.tag("fling " + ((vel > 0) ? "open" : "closed"), "notifications,v=" + vel);
- }
- super.fling(vel, expand);
- }
-
- @Override
- protected void flingToHeight(float vel, boolean expand, float target,
- float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
- mHeadsUpTouchHelper.notifyFling(!expand);
- setClosingWithAlphaFadeout(!expand && !isOnKeyguard() && getFadeoutAlpha() == 1.0f);
- super.flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
- }
-
-
- private boolean onQsIntercept(MotionEvent event) {
- int pointerIndex = event.findPointerIndex(mTrackingPointer);
- if (pointerIndex < 0) {
- pointerIndex = 0;
- mTrackingPointer = event.getPointerId(pointerIndex);
- }
- final float x = event.getX(pointerIndex);
- final float y = event.getY(pointerIndex);
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mInitialTouchY = y;
- mInitialTouchX = x;
- initVelocityTracker();
- trackMovement(event);
- if (shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, 0)) {
- mView.getParent().requestDisallowInterceptTouchEvent(true);
- }
- if (mQsExpansionAnimator != null) {
- onQsExpansionStarted();
- mInitialHeightOnTouch = mQsExpansionHeight;
- mQsTracking = true;
- mNotificationStackScroller.cancelLongPress();
- }
- break;
- case MotionEvent.ACTION_POINTER_UP:
- final int upPointer = event.getPointerId(event.getActionIndex());
- if (mTrackingPointer == upPointer) {
- // gesture is ongoing, find a new pointer to track
- final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
- mTrackingPointer = event.getPointerId(newIndex);
- mInitialTouchX = event.getX(newIndex);
- mInitialTouchY = event.getY(newIndex);
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- final float h = y - mInitialTouchY;
- trackMovement(event);
- if (mQsTracking) {
-
- // Already tracking because onOverscrolled was called. We need to update here
- // so we don't stop for a frame until the next touch event gets handled in
- // onTouchEvent.
- setQsExpansion(h + mInitialHeightOnTouch);
- trackMovement(event);
- return true;
- }
- if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)
- && shouldQuickSettingsIntercept(mInitialTouchX, mInitialTouchY, h)) {
- mQsTracking = true;
- onQsExpansionStarted();
- notifyExpandingFinished();
- mInitialHeightOnTouch = mQsExpansionHeight;
- mInitialTouchY = y;
- mInitialTouchX = x;
- mNotificationStackScroller.cancelLongPress();
- return true;
- }
- break;
-
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- trackMovement(event);
- if (mQsTracking) {
- flingQsWithCurrentVelocity(y,
- event.getActionMasked() == MotionEvent.ACTION_CANCEL);
- mQsTracking = false;
- }
- break;
- }
- return false;
- }
-
- @Override
- protected boolean isInContentBounds(float x, float y) {
- float stackScrollerX = mNotificationStackScroller.getX();
- return !mNotificationStackScroller.isBelowLastNotification(x - stackScrollerX, y)
- && stackScrollerX < x && x < stackScrollerX + mNotificationStackScroller.getWidth();
- }
-
- private void initDownStates(MotionEvent event) {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
- mOnlyAffordanceInThisMotion = false;
- mQsTouchAboveFalsingThreshold = mQsFullyExpanded;
- mDozingOnDown = isDozing();
- mDownX = event.getX();
- mDownY = event.getY();
- mCollapsedOnDown = isFullyCollapsed();
- mListenForHeadsUp = mCollapsedOnDown && mHeadsUpManager.hasPinnedHeadsUp();
- mAllowExpandForSmallExpansion = mExpectingSynthesizedDown;
- mTouchSlopExceededBeforeDown = mExpectingSynthesizedDown;
- if (mExpectingSynthesizedDown) {
- mLastEventSynthesizedDown = true;
- } else {
- // down but not synthesized motion event.
- mLastEventSynthesizedDown = false;
- }
- } else {
- // not down event at all.
- mLastEventSynthesizedDown = false;
- }
- }
-
- private void flingQsWithCurrentVelocity(float y, boolean isCancelMotionEvent) {
- float vel = getCurrentQSVelocity();
- final boolean expandsQs = flingExpandsQs(vel);
- if (expandsQs) {
- logQsSwipeDown(y);
- }
- flingSettings(vel, expandsQs && !isCancelMotionEvent ? FLING_EXPAND : FLING_COLLAPSE);
- }
-
- private void logQsSwipeDown(float y) {
- float vel = getCurrentQSVelocity();
- final int
- gesture =
- mBarState == StatusBarState.KEYGUARD ? MetricsEvent.ACTION_LS_QS
- : MetricsEvent.ACTION_SHADE_QS_PULL;
- mLockscreenGestureLogger.write(gesture,
- (int) ((y - mInitialTouchY) / mStatusBar.getDisplayDensity()),
- (int) (vel / mStatusBar.getDisplayDensity()));
- }
-
- private boolean flingExpandsQs(float vel) {
- if (mFalsingManager.isUnlockingDisabled() || isFalseTouch()) {
- return false;
- }
- if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
- return getQsExpansionFraction() > 0.5f;
- } else {
- return vel > 0;
- }
- }
-
- private boolean isFalseTouch() {
- if (!mKeyguardAffordanceHelperCallback.needsAntiFalsing()) {
- return false;
- }
- if (mFalsingManager.isClassifierEnabled()) {
- return mFalsingManager.isFalseTouch();
- }
- return !mQsTouchAboveFalsingThreshold;
- }
-
- private float getQsExpansionFraction() {
- return Math.min(
- 1f, (mQsExpansionHeight - mQsMinExpansionHeight) / (mQsMaxExpansionHeight
- - mQsMinExpansionHeight));
- }
-
- @Override
- protected boolean shouldExpandWhenNotFlinging() {
- if (super.shouldExpandWhenNotFlinging()) {
- return true;
- }
- if (mAllowExpandForSmallExpansion) {
- // When we get a touch that came over from launcher, the velocity isn't always correct
- // Let's err on expanding if the gesture has been reasonably slow
- long timeSinceDown = SystemClock.uptimeMillis() - mDownTime;
- return timeSinceDown <= MAX_TIME_TO_OPEN_WHEN_FLINGING_FROM_LAUNCHER;
- }
- return false;
- }
-
- @Override
- protected float getOpeningHeight() {
- return mNotificationStackScroller.getOpeningHeight();
- }
-
-
- private boolean handleQsTouch(MotionEvent event) {
- final int action = event.getActionMasked();
- if (action == MotionEvent.ACTION_DOWN && getExpandedFraction() == 1f
- && mBarState != StatusBarState.KEYGUARD && !mQsExpanded && mQsExpansionEnabled) {
-
- // Down in the empty area while fully expanded - go to QS.
- mQsTracking = true;
- mConflictingQsExpansionGesture = true;
- onQsExpansionStarted();
- mInitialHeightOnTouch = mQsExpansionHeight;
- mInitialTouchY = event.getX();
- mInitialTouchX = event.getY();
- }
- if (!isFullyCollapsed()) {
- handleQsDown(event);
- }
- if (!mQsExpandImmediate && mQsTracking) {
- onQsTouch(event);
- if (!mConflictingQsExpansionGesture) {
- return true;
- }
- }
- if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
- mConflictingQsExpansionGesture = false;
- }
- if (action == MotionEvent.ACTION_DOWN && isFullyCollapsed() && mQsExpansionEnabled) {
- mTwoFingerQsExpandPossible = true;
- }
- if (mTwoFingerQsExpandPossible && isOpenQsEvent(event) && event.getY(event.getActionIndex())
- < mStatusBarMinHeight) {
- mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1);
- mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
- requestPanelHeightUpdate();
-
- // Normally, we start listening when the panel is expanded, but here we need to start
- // earlier so the state is already up to date when dragging down.
- setListening(true);
- }
- if (isQsSplitEnabled() && !mKeyguardShowing) {
- if (mQsExpandImmediate) {
- mNotificationStackScroller.setVisibility(View.GONE);
- mQsFrame.setVisibility(View.VISIBLE);
- mHomeControlsLayout.setVisibility(View.VISIBLE);
- } else {
- mNotificationStackScroller.setVisibility(View.VISIBLE);
- mQsFrame.setVisibility(View.GONE);
- mHomeControlsLayout.setVisibility(View.GONE);
- }
- }
- return false;
- }
-
- private boolean isInQsArea(float x, float y) {
- return (x >= mQsFrame.getX() && x <= mQsFrame.getX() + mQsFrame.getWidth()) && (
- y <= mNotificationStackScroller.getBottomMostNotificationBottom()
- || y <= mQs.getView().getY() + mQs.getView().getHeight());
- }
-
- private boolean isOnQsEndArea(float x) {
- if (!isQsSplitEnabled()) return false;
- if (mView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
- return x >= mQsFrame.getX() + mQqsSplitFraction * mQsFrame.getWidth()
- && x <= mQsFrame.getX() + mQsFrame.getWidth();
- } else {
- return x >= mQsFrame.getX()
- && x <= mQsFrame.getX() + (1 - mQqsSplitFraction) * mQsFrame.getWidth();
- }
- }
-
- private boolean isOpenQsEvent(MotionEvent event) {
- final int pointerCount = event.getPointerCount();
- final int action = event.getActionMasked();
-
- final boolean
- twoFingerDrag =
- action == MotionEvent.ACTION_POINTER_DOWN && pointerCount == 2;
-
- final boolean
- stylusButtonClickDrag =
- action == MotionEvent.ACTION_DOWN && (event.isButtonPressed(
- MotionEvent.BUTTON_STYLUS_PRIMARY) || event.isButtonPressed(
- MotionEvent.BUTTON_STYLUS_SECONDARY));
-
- final boolean
- mouseButtonClickDrag =
- action == MotionEvent.ACTION_DOWN && (event.isButtonPressed(
- MotionEvent.BUTTON_SECONDARY) || event.isButtonPressed(
- MotionEvent.BUTTON_TERTIARY));
-
- final boolean onHeaderRight = isOnQsEndArea(event.getX());
-
- return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag || onHeaderRight;
- }
-
- private void handleQsDown(MotionEvent event) {
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN && shouldQuickSettingsIntercept(
- event.getX(), event.getY(), -1)) {
- mFalsingManager.onQsDown();
- mQsTracking = true;
- onQsExpansionStarted();
- mInitialHeightOnTouch = mQsExpansionHeight;
- mInitialTouchY = event.getX();
- mInitialTouchX = event.getY();
-
- // If we interrupt an expansion gesture here, make sure to update the state correctly.
- notifyExpandingFinished();
- }
- }
-
- /**
- * Input focus transfer is about to happen.
- */
- public void startWaitingForOpenPanelGesture() {
- if (!isFullyCollapsed()) {
- return;
- }
- mExpectingSynthesizedDown = true;
- onTrackingStarted();
- updatePanelExpanded();
- }
-
- /**
- * Called when this view is no longer waiting for input focus transfer.
- *
- * There are two scenarios behind this function call. First, input focus transfer
- * has successfully happened and this view already received synthetic DOWN event.
- * (mExpectingSynthesizedDown == false). Do nothing.
- *
- * Second, before input focus transfer finished, user may have lifted finger
- * in previous window and this window never received synthetic DOWN event.
- * (mExpectingSynthesizedDown == true).
- * In this case, we use the velocity to trigger fling event.
- *
- * @param velocity unit is in px / millis
- */
- public void stopWaitingForOpenPanelGesture(final float velocity) {
- if (mExpectingSynthesizedDown) {
- mExpectingSynthesizedDown = false;
- maybeVibrateOnOpening();
- Runnable runnable = () -> fling(velocity > 1f ? 1000f * velocity : 0,
- true /* expand */);
- if (mStatusBar.getStatusBarWindow().getHeight() != mStatusBar.getStatusBarHeight()) {
- // The panel is already expanded to its full size, let's expand directly
- runnable.run();
- } else {
- mExpandAfterLayoutRunnable = runnable;
- }
- onTrackingStopped(false);
- }
- }
-
- @Override
- protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
- boolean expands = super.flingExpands(vel, vectorVel, x, y);
-
- // If we are already running a QS expansion, make sure that we keep the panel open.
- if (mQsExpansionAnimator != null) {
- expands = true;
- }
- return expands;
- }
-
- @Override
- protected boolean shouldGestureWaitForTouchSlop() {
- if (mExpectingSynthesizedDown) {
- mExpectingSynthesizedDown = false;
- return false;
- }
- return isFullyCollapsed() || mBarState != StatusBarState.SHADE;
- }
-
- @Override
- protected boolean shouldGestureIgnoreXTouchSlop(float x, float y) {
- return !mAffordanceHelper.isOnAffordanceIcon(x, y);
- }
-
- private void onQsTouch(MotionEvent event) {
- int pointerIndex = event.findPointerIndex(mTrackingPointer);
- if (pointerIndex < 0) {
- pointerIndex = 0;
- mTrackingPointer = event.getPointerId(pointerIndex);
- }
- final float y = event.getY(pointerIndex);
- final float x = event.getX(pointerIndex);
- final float h = y - mInitialTouchY;
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mQsTracking = true;
- mInitialTouchY = y;
- mInitialTouchX = x;
- onQsExpansionStarted();
- mInitialHeightOnTouch = mQsExpansionHeight;
- initVelocityTracker();
- trackMovement(event);
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- final int upPointer = event.getPointerId(event.getActionIndex());
- if (mTrackingPointer == upPointer) {
- // gesture is ongoing, find a new pointer to track
- final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
- final float newY = event.getY(newIndex);
- final float newX = event.getX(newIndex);
- mTrackingPointer = event.getPointerId(newIndex);
- mInitialHeightOnTouch = mQsExpansionHeight;
- mInitialTouchY = newY;
- mInitialTouchX = newX;
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- setQsExpansion(h + mInitialHeightOnTouch);
- if (h >= getFalsingThreshold()) {
- mQsTouchAboveFalsingThreshold = true;
- }
- trackMovement(event);
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mQsTracking = false;
- mTrackingPointer = -1;
- trackMovement(event);
- float fraction = getQsExpansionFraction();
- if (fraction != 0f || y >= mInitialTouchY) {
- flingQsWithCurrentVelocity(y,
- event.getActionMasked() == MotionEvent.ACTION_CANCEL);
- }
- if (mQsVelocityTracker != null) {
- mQsVelocityTracker.recycle();
- mQsVelocityTracker = null;
- }
- break;
- }
- }
-
- private int getFalsingThreshold() {
- float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
- return (int) (mQsFalsingThreshold * factor);
- }
-
- private void setOverScrolling(boolean overscrolling) {
- mStackScrollerOverscrolling = overscrolling;
- if (mQs == null) return;
- mQs.setOverscrolling(overscrolling);
- }
-
- private void onQsExpansionStarted() {
- onQsExpansionStarted(0);
- }
-
- protected void onQsExpansionStarted(int overscrollAmount) {
- cancelQsAnimation();
- cancelHeightAnimator();
-
- // Reset scroll position and apply that position to the expanded height.
- float height = mQsExpansionHeight - overscrollAmount;
- setQsExpansion(height);
- requestPanelHeightUpdate();
- mNotificationStackScroller.checkSnoozeLeavebehind();
-
- // When expanding QS, let's authenticate the user if possible,
- // this will speed up notification actions.
- if (height == 0) {
- mStatusBar.requestFaceAuth();
- }
- }
-
- private void setQsExpanded(boolean expanded) {
- boolean changed = mQsExpanded != expanded;
- if (changed) {
- mQsExpanded = expanded;
- updateQsState();
- requestPanelHeightUpdate();
- mFalsingManager.setQsExpanded(expanded);
- mStatusBar.setQsExpanded(expanded);
- mNotificationContainerParent.setQsExpanded(expanded);
- mPulseExpansionHandler.setQsExpanded(expanded);
- mKeyguardBypassController.setQSExpanded(expanded);
- }
- }
-
- private void maybeAnimateBottomAreaAlpha() {
- mBottomAreaShadeAlphaAnimator.cancel();
- if (mBarState == StatusBarState.SHADE_LOCKED) {
- mBottomAreaShadeAlphaAnimator.start();
- } else {
- mBottomAreaShadeAlpha = 1f;
- }
- }
-
- private final Runnable mAnimateKeyguardStatusViewInvisibleEndRunnable = new Runnable() {
- @Override
- public void run() {
- mKeyguardStatusViewAnimating = false;
- mKeyguardStatusView.setVisibility(View.INVISIBLE);
- }
- };
-
- private final Runnable mAnimateKeyguardStatusViewGoneEndRunnable = new Runnable() {
- @Override
- public void run() {
- mKeyguardStatusViewAnimating = false;
- mKeyguardStatusView.setVisibility(View.GONE);
- }
- };
-
- private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = new Runnable() {
- @Override
- public void run() {
- mKeyguardStatusViewAnimating = false;
- }
- };
-
- private final Runnable mAnimateKeyguardStatusBarInvisibleEndRunnable = new Runnable() {
- @Override
- public void run() {
- mKeyguardStatusBar.setVisibility(View.INVISIBLE);
- mKeyguardStatusBar.setAlpha(1f);
- mKeyguardStatusBarAnimateAlpha = 1f;
- }
- };
-
- private void animateKeyguardStatusBarOut() {
- ValueAnimator anim = ValueAnimator.ofFloat(mKeyguardStatusBar.getAlpha(), 0f);
- anim.addUpdateListener(mStatusBarAnimateAlphaListener);
- anim.setStartDelay(mKeyguardStateController.isKeyguardFadingAway()
- ? mKeyguardStateController.getKeyguardFadingAwayDelay() : 0);
-
- long duration;
- if (mKeyguardStateController.isKeyguardFadingAway()) {
- duration = mKeyguardStateController.getShortenedFadingAwayDuration();
- } else {
- duration = StackStateAnimator.ANIMATION_DURATION_STANDARD;
- }
- anim.setDuration(duration);
-
- anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- anim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mAnimateKeyguardStatusBarInvisibleEndRunnable.run();
- }
- });
- anim.start();
- }
-
- private final ValueAnimator.AnimatorUpdateListener
- mStatusBarAnimateAlphaListener =
- new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
- updateHeaderKeyguardAlpha();
- }
- };
-
- private void animateKeyguardStatusBarIn(long duration) {
- mKeyguardStatusBar.setVisibility(View.VISIBLE);
- mKeyguardStatusBar.setAlpha(0f);
- ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
- anim.addUpdateListener(mStatusBarAnimateAlphaListener);
- anim.setDuration(duration);
- anim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- anim.start();
- }
-
- private final Runnable mAnimateKeyguardBottomAreaInvisibleEndRunnable = new Runnable() {
- @Override
- public void run() {
- mKeyguardBottomArea.setVisibility(View.GONE);
- }
- };
-
- private void setKeyguardBottomAreaVisibility(int statusBarState, boolean goingToFullShade) {
- mKeyguardBottomArea.animate().cancel();
- if (goingToFullShade) {
- mKeyguardBottomArea.animate().alpha(0f).setStartDelay(
- mKeyguardStateController.getKeyguardFadingAwayDelay()).setDuration(
- mKeyguardStateController.getShortenedFadingAwayDuration()).setInterpolator(
- Interpolators.ALPHA_OUT).withEndAction(
- mAnimateKeyguardBottomAreaInvisibleEndRunnable).start();
- } else if (statusBarState == StatusBarState.KEYGUARD
- || statusBarState == StatusBarState.SHADE_LOCKED) {
- mKeyguardBottomArea.setVisibility(View.VISIBLE);
- mKeyguardBottomArea.setAlpha(1f);
- } else {
- mKeyguardBottomArea.setVisibility(View.GONE);
- }
- }
-
- private void setKeyguardStatusViewVisibility(int statusBarState, boolean keyguardFadingAway,
- boolean goingToFullShade) {
- mKeyguardStatusView.animate().cancel();
- mKeyguardStatusViewAnimating = false;
- if ((!keyguardFadingAway && mBarState == StatusBarState.KEYGUARD
- && statusBarState != StatusBarState.KEYGUARD) || goingToFullShade) {
- mKeyguardStatusViewAnimating = true;
- mKeyguardStatusView.animate().alpha(0f).setStartDelay(0).setDuration(
- 160).setInterpolator(Interpolators.ALPHA_OUT).withEndAction(
- mAnimateKeyguardStatusViewGoneEndRunnable);
- if (keyguardFadingAway) {
- mKeyguardStatusView.animate().setStartDelay(
- mKeyguardStateController.getKeyguardFadingAwayDelay()).setDuration(
- mKeyguardStateController.getShortenedFadingAwayDuration()).start();
- }
- } else if (mBarState == StatusBarState.SHADE_LOCKED
- && statusBarState == StatusBarState.KEYGUARD) {
- mKeyguardStatusView.setVisibility(View.VISIBLE);
- mKeyguardStatusViewAnimating = true;
- mKeyguardStatusView.setAlpha(0f);
- mKeyguardStatusView.animate().alpha(1f).setStartDelay(0).setDuration(
- 320).setInterpolator(Interpolators.ALPHA_IN).withEndAction(
- mAnimateKeyguardStatusViewVisibleEndRunnable);
- } else if (statusBarState == StatusBarState.KEYGUARD) {
- if (keyguardFadingAway) {
- mKeyguardStatusViewAnimating = true;
- mKeyguardStatusView.animate().alpha(0).translationYBy(
- -getHeight() * 0.05f).setInterpolator(
- Interpolators.FAST_OUT_LINEAR_IN).setDuration(125).setStartDelay(
- 0).withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable).start();
- } else {
- mKeyguardStatusView.setVisibility(View.VISIBLE);
- mKeyguardStatusView.setAlpha(1f);
- }
- } else {
- mKeyguardStatusView.setVisibility(View.GONE);
- mKeyguardStatusView.setAlpha(1f);
- }
- }
-
- private void updateQsState() {
- mNotificationStackScroller.setQsExpanded(mQsExpanded);
- mNotificationStackScroller.setScrollingEnabled(
- mBarState != StatusBarState.KEYGUARD && (!mQsExpanded
- || mQsExpansionFromOverscroll));
- updateEmptyShadeView();
- if (mNPVPluginManager != null) {
- mNPVPluginManager.changeVisibility(
- (mBarState != StatusBarState.KEYGUARD) ? View.VISIBLE : View.INVISIBLE);
- }
- mQsNavbarScrim.setVisibility(
- mBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling
- && mQsScrimEnabled ? View.VISIBLE : View.INVISIBLE);
- if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
- mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
- }
- if (mQs == null) return;
- mQs.setExpanded(mQsExpanded);
- }
-
- private void setQsExpansion(float height) {
- height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
- mQsFullyExpanded = height == mQsMaxExpansionHeight && mQsMaxExpansionHeight != 0;
- if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling
- && !mDozing) {
- setQsExpanded(true);
- } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
- setQsExpanded(false);
- }
- mQsExpansionHeight = height;
- updateQsExpansion();
- requestScrollerTopPaddingUpdate(false /* animate */);
- updateHeaderKeyguardAlpha();
- if (mBarState == StatusBarState.SHADE_LOCKED || mBarState == StatusBarState.KEYGUARD) {
- updateKeyguardBottomAreaAlpha();
- updateBigClockAlpha();
- }
- if (mBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling
- && mQsScrimEnabled) {
- mQsNavbarScrim.setAlpha(getQsExpansionFraction());
- }
-
- if (mAccessibilityManager.isEnabled()) {
- mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
- }
-
- if (!mFalsingManager.isUnlockingDisabled() && mQsFullyExpanded
- && mFalsingManager.shouldEnforceBouncer()) {
- mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
- false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
- }
- for (int i = 0; i < mExpansionListeners.size(); i++) {
- mExpansionListeners.get(i).onQsExpansionChanged(
- mQsMaxExpansionHeight != 0 ? mQsExpansionHeight / mQsMaxExpansionHeight : 0);
- }
- if (DEBUG) {
- mView.invalidate();
- }
- }
-
- protected void updateQsExpansion() {
- if (mQs == null) return;
- float qsExpansionFraction = getQsExpansionFraction();
- mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
- int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight();
- if (mNPVPluginManager != null) {
- mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff);
- }
- mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction);
- }
-
- private String determineAccessibilityPaneTitle() {
- if (mQs != null && mQs.isCustomizing()) {
- return mResources.getString(R.string.accessibility_desc_quick_settings_edit);
- } else if (mQsExpansionHeight != 0.0f && mQsFullyExpanded) {
- // Upon initialisation when we are not layouted yet we don't want to announce that we
- // are fully expanded, hence the != 0.0f check.
- return mResources.getString(R.string.accessibility_desc_quick_settings);
- } else if (mBarState == StatusBarState.KEYGUARD) {
- return mResources.getString(R.string.accessibility_desc_lock_screen);
- } else {
- return mResources.getString(R.string.accessibility_desc_notification_shade);
- }
- }
-
- private float calculateQsTopPadding() {
- if (mKeyguardShowing && (mQsExpandImmediate
- || mIsExpanding && mQsExpandedWhenExpandingStarted)) {
-
- // Either QS pushes the notifications down when fully expanded, or QS is fully above the
- // notifications (mostly on tablets). maxNotificationPadding denotes the normal top
- // padding on Keyguard, maxQsPadding denotes the top padding from the quick settings
- // panel. We need to take the maximum and linearly interpolate with the panel expansion
- // for a nice motion.
- int maxNotificationPadding = getKeyguardNotificationStaticPadding();
- int maxQsPadding = mQsMaxExpansionHeight + mQsNotificationTopPadding;
- int max = mBarState == StatusBarState.KEYGUARD ? Math.max(
- maxNotificationPadding, maxQsPadding) : maxQsPadding;
- return (int) MathUtils.lerp((float) mQsMinExpansionHeight, (float) max,
- getExpandedFraction());
- } else if (mQsSizeChangeAnimator != null) {
- return Math.max(
- (int) mQsSizeChangeAnimator.getAnimatedValue(),
- getKeyguardNotificationStaticPadding());
- } else if (mKeyguardShowing) {
- // We can only do the smoother transition on Keyguard when we also are not collapsing
- // from a scrolled quick settings.
- return MathUtils.lerp((float) getKeyguardNotificationStaticPadding(),
- (float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
- getQsExpansionFraction());
- } else {
- return mQsExpansionHeight + mQsNotificationTopPadding;
- }
- }
-
- /**
- * @return the topPadding of notifications when on keyguard not respecting quick settings
- * expansion
- */
- private int getKeyguardNotificationStaticPadding() {
- if (!mKeyguardShowing) {
- return 0;
- }
- if (!mKeyguardBypassController.getBypassEnabled()) {
- return mClockPositionResult.stackScrollerPadding;
- }
- int collapsedPosition = mHeadsUpInset;
- if (!mNotificationStackScroller.isPulseExpanding()) {
- return collapsedPosition;
- } else {
- int expandedPosition = mClockPositionResult.stackScrollerPadding;
- return (int) MathUtils.lerp(collapsedPosition, expandedPosition,
- mNotificationStackScroller.calculateAppearFractionBypass());
- }
- }
-
-
- protected void requestScrollerTopPaddingUpdate(boolean animate) {
- mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(), animate);
- if (mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()) {
- // update the position of the header
- updateQsExpansion();
- }
- }
-
-
- private void updateQSPulseExpansion() {
- if (mQs != null) {
- mQs.setShowCollapsedOnKeyguard(
- mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()
- && mNotificationStackScroller.isPulseExpanding());
- }
- }
-
- private void trackMovement(MotionEvent event) {
- if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
- }
-
- private void initVelocityTracker() {
- if (mQsVelocityTracker != null) {
- mQsVelocityTracker.recycle();
- }
- mQsVelocityTracker = VelocityTracker.obtain();
- }
-
- private float getCurrentQSVelocity() {
- if (mQsVelocityTracker == null) {
- return 0;
- }
- mQsVelocityTracker.computeCurrentVelocity(1000);
- return mQsVelocityTracker.getYVelocity();
- }
-
- private void cancelQsAnimation() {
- if (mQsExpansionAnimator != null) {
- mQsExpansionAnimator.cancel();
- }
- }
-
- /**
- * @see #flingSettings(float, int, Runnable, boolean)
- */
- public void flingSettings(float vel, int type) {
- flingSettings(vel, type, null, false /* isClick */);
- }
-
- /**
- * Animates QS or QQS as if the user had swiped up or down.
- *
- * @param vel Finger velocity or 0 when not initiated by touch events.
- * @param type Either {@link #FLING_EXPAND}, {@link #FLING_COLLAPSE} or {@link
- * #FLING_HIDE}.
- * @param onFinishRunnable Runnable to be executed at the end of animation.
- * @param isClick If originated by click (different interpolator and duration.)
- */
- protected void flingSettings(float vel, int type, final Runnable onFinishRunnable,
- boolean isClick) {
- float target;
- switch (type) {
- case FLING_EXPAND:
- target = mQsMaxExpansionHeight;
- break;
- case FLING_COLLAPSE:
- target = mQsMinExpansionHeight;
- break;
- case FLING_HIDE:
- default:
- target = 0;
- }
- if (target == mQsExpansionHeight) {
- if (onFinishRunnable != null) {
- onFinishRunnable.run();
- }
- return;
- }
-
- // If we move in the opposite direction, reset velocity and use a different duration.
- boolean oppositeDirection = false;
- boolean expanding = type == FLING_EXPAND;
- if (vel > 0 && !expanding || vel < 0 && expanding) {
- vel = 0;
- oppositeDirection = true;
- }
- ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
- if (isClick) {
- animator.setInterpolator(Interpolators.TOUCH_RESPONSE);
- animator.setDuration(368);
- } else {
- mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
- }
- if (oppositeDirection) {
- animator.setDuration(350);
- }
- animator.addUpdateListener(animation -> {
- setQsExpansion((Float) animation.getAnimatedValue());
- });
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mNotificationStackScroller.resetCheckSnoozeLeavebehind();
- mQsExpansionAnimator = null;
- if (onFinishRunnable != null) {
- onFinishRunnable.run();
- }
- }
- });
- animator.start();
- mQsExpansionAnimator = animator;
- mQsAnimatorExpand = expanding;
- }
-
- /**
- * @return Whether we should intercept a gesture to open Quick Settings.
- */
- private boolean shouldQuickSettingsIntercept(float x, float y, float yDiff) {
- if (!mQsExpansionEnabled || mCollapsedOnDown || (mKeyguardShowing
- && mKeyguardBypassController.getBypassEnabled())) {
- return false;
- }
- View header = mKeyguardShowing || mQs == null ? mKeyguardStatusBar : mQs.getHeader();
- final boolean
- onHeader =
- x >= mQsFrame.getX() && x <= mQsFrame.getX() + mQsFrame.getWidth()
- && y >= header.getTop() && y <= header.getBottom();
- if (mQsExpanded) {
- return onHeader || (yDiff < 0 && isInQsArea(x, y));
- } else {
- return onHeader;
- }
- }
-
- @Override
- protected boolean isScrolledToBottom() {
- if (!isInSettings()) {
- return mBarState == StatusBarState.KEYGUARD
- || mNotificationStackScroller.isScrolledToBottom();
- } else {
- return true;
- }
- }
-
- @Override
- protected int getMaxPanelHeight() {
- if (mKeyguardBypassController.getBypassEnabled() && mBarState == StatusBarState.KEYGUARD) {
- return getMaxPanelHeightBypass();
- } else {
- return getMaxPanelHeightNonBypass();
- }
- }
-
- private int getMaxPanelHeightNonBypass() {
- int min = mStatusBarMinHeight;
- if (!(mBarState == StatusBarState.KEYGUARD)
- && mNotificationStackScroller.getNotGoneChildCount() == 0) {
- int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
- min = Math.max(min, minHeight);
- }
- int maxHeight;
- if (mQsExpandImmediate || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted
- || mPulsing) {
- maxHeight = calculatePanelHeightQsExpanded();
- } else {
- maxHeight = calculatePanelHeightShade();
- }
- maxHeight = Math.max(maxHeight, min);
- return maxHeight;
- }
-
- private int getMaxPanelHeightBypass() {
- int position =
- mClockPositionAlgorithm.getExpandedClockPosition()
- + mKeyguardStatusView.getHeight();
- if (mNotificationStackScroller.getVisibleNotificationCount() != 0) {
- position += mShelfHeight / 2.0f + mDarkIconSize / 2.0f;
- }
- return position;
- }
-
- public boolean isInSettings() {
- return mQsExpanded;
- }
-
- public boolean isExpanding() {
- return mIsExpanding;
- }
-
- @Override
- protected void onHeightUpdated(float expandedHeight) {
- if (!mQsExpanded || mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted) {
- // Updating the clock position will set the top padding which might
- // trigger a new panel height and re-position the clock.
- // This is a circular dependency and should be avoided, otherwise we'll have
- // a stack overflow.
- if (mStackScrollerMeasuringPass > 2) {
- if (DEBUG) Log.d(TAG, "Unstable notification panel height. Aborting.");
- } else {
- positionClockAndNotifications();
- }
- }
- if (mQsExpandImmediate || mQsExpanded && !mQsTracking && mQsExpansionAnimator == null
- && !mQsExpansionFromOverscroll) {
- float t;
- if (mKeyguardShowing) {
-
- // On Keyguard, interpolate the QS expansion linearly to the panel expansion
- t = expandedHeight / (getMaxPanelHeight());
- } else {
- // In Shade, interpolate linearly such that QS is closed whenever panel height is
- // minimum QS expansion + minStackHeight
- float
- panelHeightQsCollapsed =
- mNotificationStackScroller.getIntrinsicPadding()
- + mNotificationStackScroller.getLayoutMinHeight();
- float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
- t =
- (expandedHeight - panelHeightQsCollapsed) / (panelHeightQsExpanded
- - panelHeightQsCollapsed);
- }
- float
- targetHeight =
- mQsMinExpansionHeight + t * (mQsMaxExpansionHeight - mQsMinExpansionHeight);
- setQsExpansion(targetHeight);
- mHomeControlsLayout.setTranslationY(targetHeight);
- }
- updateExpandedHeight(expandedHeight);
- updateHeader();
- updateNotificationTranslucency();
- updatePanelExpanded();
- updateGestureExclusionRect();
- if (DEBUG) {
- mView.invalidate();
- }
- }
-
- private void updatePanelExpanded() {
- boolean isExpanded = !isFullyCollapsed() || mExpectingSynthesizedDown;
- if (mPanelExpanded != isExpanded) {
- mHeadsUpManager.setIsPanelExpanded(isExpanded);
- mStatusBar.setPanelExpanded(isExpanded);
- mPanelExpanded = isExpanded;
- }
- }
-
- private int calculatePanelHeightShade() {
- int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
- int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin;
- maxHeight += mNotificationStackScroller.getTopPaddingOverflow();
-
- if (mBarState == StatusBarState.KEYGUARD) {
- int
- minKeyguardPanelBottom =
- mClockPositionAlgorithm.getExpandedClockPosition()
- + mKeyguardStatusView.getHeight()
- + mNotificationStackScroller.getIntrinsicContentHeight();
- return Math.max(maxHeight, minKeyguardPanelBottom);
- } else {
- return maxHeight;
- }
- }
-
- private int calculatePanelHeightQsExpanded() {
- float
- notificationHeight =
- mNotificationStackScroller.getHeight()
- - mNotificationStackScroller.getEmptyBottomMargin()
- - mNotificationStackScroller.getTopPadding();
-
- // When only empty shade view is visible in QS collapsed state, simulate that we would have
- // it in expanded QS state as well so we don't run into troubles when fading the view in/out
- // and expanding/collapsing the whole panel from/to quick settings.
- if (mNotificationStackScroller.getNotGoneChildCount() == 0 && mShowEmptyShadeView) {
- notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
- }
- int maxQsHeight = mQsMaxExpansionHeight;
-
- if (mKeyguardShowing) {
- maxQsHeight += mQsNotificationTopPadding;
- }
-
- // If an animation is changing the size of the QS panel, take the animated value.
- if (mQsSizeChangeAnimator != null) {
- maxQsHeight = (int) mQsSizeChangeAnimator.getAnimatedValue();
- }
- float totalHeight = Math.max(maxQsHeight,
- mBarState == StatusBarState.KEYGUARD ? mClockPositionResult.stackScrollerPadding
- : 0) + notificationHeight
- + mNotificationStackScroller.getTopPaddingOverflow();
- if (totalHeight > mNotificationStackScroller.getHeight()) {
- float
- fullyCollapsedHeight =
- maxQsHeight + mNotificationStackScroller.getLayoutMinHeight();
- totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
- }
- return (int) totalHeight;
- }
-
- private void updateNotificationTranslucency() {
- float alpha = 1f;
- if (mClosingWithAlphaFadeOut && !mExpandingFromHeadsUp
- && !mHeadsUpManager.hasPinnedHeadsUp()) {
- alpha = getFadeoutAlpha();
- }
- if (mBarState == StatusBarState.KEYGUARD && !mHintAnimationRunning
- && !mKeyguardBypassController.getBypassEnabled()) {
- alpha *= mClockPositionResult.clockAlpha;
- }
- mNotificationStackScroller.setAlpha(alpha);
- }
-
- private float getFadeoutAlpha() {
- float alpha;
- if (mQsMinExpansionHeight == 0) {
- return 1.0f;
- }
- alpha = getExpandedHeight() / mQsMinExpansionHeight;
- alpha = Math.max(0, Math.min(alpha, 1));
- alpha = (float) Math.pow(alpha, 0.75);
- return alpha;
- }
-
- @Override
- protected float getOverExpansionAmount() {
- return mNotificationStackScroller.getCurrentOverScrollAmount(true /* top */);
- }
-
- @Override
- protected float getOverExpansionPixels() {
- return mNotificationStackScroller.getCurrentOverScrolledPixels(true /* top */);
- }
-
- /**
- * Hides the header when notifications are colliding with it.
- */
- private void updateHeader() {
- if (mBarState == StatusBarState.KEYGUARD) {
- updateHeaderKeyguardAlpha();
- }
- updateQsExpansion();
- }
-
- protected float getHeaderTranslation() {
- if (mBarState == StatusBarState.KEYGUARD && !mKeyguardBypassController.getBypassEnabled()) {
- return -mQs.getQsMinExpansionHeight();
- }
- float appearAmount = mNotificationStackScroller.calculateAppearFraction(mExpandedHeight);
- float startHeight = -mQsExpansionHeight;
- if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()
- && mNotificationStackScroller.isPulseExpanding()) {
- if (!mPulseExpansionHandler.isExpanding()
- && !mPulseExpansionHandler.getLeavingLockscreen()) {
- // If we aborted the expansion we need to make sure the header doesn't reappear
- // again after the header has animated away
- appearAmount = 0;
- } else {
- appearAmount = mNotificationStackScroller.calculateAppearFractionBypass();
- }
- startHeight = -mQs.getQsMinExpansionHeight();
- if (mNPVPluginManager != null) startHeight -= mNPVPluginManager.getHeight();
- }
- float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount))
- + mExpandOffset;
- return Math.min(0, translation);
- }
-
- /**
- * @return the alpha to be used to fade out the contents on Keyguard (status bar, bottom area)
- * during swiping up
- */
- private float getKeyguardContentsAlpha() {
- float alpha;
- if (mBarState == StatusBarState.KEYGUARD) {
-
- // When on Keyguard, we hide the header as soon as we expanded close enough to the
- // header
- alpha =
- getExpandedHeight() / (mKeyguardStatusBar.getHeight()
- + mNotificationsHeaderCollideDistance);
- } else {
-
- // In SHADE_LOCKED, the top card is already really close to the header. Hide it as
- // soon as we start translating the stack.
- alpha = getExpandedHeight() / mKeyguardStatusBar.getHeight();
- }
- alpha = MathUtils.saturate(alpha);
- alpha = (float) Math.pow(alpha, 0.75);
- return alpha;
- }
-
- private void updateHeaderKeyguardAlpha() {
- if (!mKeyguardShowing) {
- return;
- }
- float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
- float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
- * mKeyguardStatusBarAnimateAlpha;
- newAlpha *= 1.0f - mKeyguardHeadsUpShowingAmount;
- mKeyguardStatusBar.setAlpha(newAlpha);
- boolean
- hideForBypass =
- mFirstBypassAttempt && mUpdateMonitor.shouldListenForFace()
- || mDelayShowingKeyguardStatusBar;
- mKeyguardStatusBar.setVisibility(
- newAlpha != 0f && !mDozing && !hideForBypass ? View.VISIBLE : View.INVISIBLE);
- }
-
- private void updateKeyguardBottomAreaAlpha() {
- // There are two possible panel expansion behaviors:
- // • User dragging up to unlock: we want to fade out as quick as possible
- // (ALPHA_EXPANSION_THRESHOLD) to avoid seeing the bouncer over the bottom area.
- // • User tapping on lock screen: bouncer won't be visible but panel expansion will
- // change due to "unlock hint animation." In this case, fading out the bottom area
- // would also hide the message that says "swipe to unlock," we don't want to do that.
- float expansionAlpha = MathUtils.map(
- isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
- getExpandedFraction());
- float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
- alpha *= mBottomAreaShadeAlpha;
- mKeyguardBottomArea.setAffordanceAlpha(alpha);
- mKeyguardBottomArea.setImportantForAccessibility(
- alpha == 0f ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
- : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
- View ambientIndicationContainer = mStatusBar.getAmbientIndicationContainer();
- if (ambientIndicationContainer != null) {
- ambientIndicationContainer.setAlpha(alpha);
- }
- }
-
- /**
- * Custom clock fades away when user drags up to unlock or pulls down quick settings.
- *
- * Updates alpha of custom clock to match the alpha of the KeyguardBottomArea. See
- * {@link #updateKeyguardBottomAreaAlpha}.
- */
- private void updateBigClockAlpha() {
- float expansionAlpha = MathUtils.map(
- isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
- getExpandedFraction());
- float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
- mBigClockContainer.setAlpha(alpha);
- }
-
- @Override
- protected void onExpandingStarted() {
- super.onExpandingStarted();
- mNotificationStackScroller.onExpansionStarted();
- mIsExpanding = true;
- mQsExpandedWhenExpandingStarted = mQsFullyExpanded;
- if (mQsExpanded) {
- onQsExpansionStarted();
- }
- // Since there are QS tiles in the header now, we need to make sure we start listening
- // immediately so they can be up to date.
- if (mQs == null) return;
- mQs.setHeaderListening(true);
- }
-
- @Override
- protected void onExpandingFinished() {
- super.onExpandingFinished();
- mNotificationStackScroller.onExpansionStopped();
- mHeadsUpManager.onExpandingFinished();
- mIsExpanding = false;
- if (isFullyCollapsed()) {
- DejankUtils.postAfterTraversal(new Runnable() {
- @Override
- public void run() {
- setListening(false);
- }
- });
-
- // Workaround b/22639032: Make sure we invalidate something because else RenderThread
- // thinks we are actually drawing a frame put in reality we don't, so RT doesn't go
- // ahead with rendering and we jank.
- mView.postOnAnimation(new Runnable() {
- @Override
- public void run() {
- mView.getParent().invalidateChild(mView, M_DUMMY_DIRTY_RECT);
- }
- });
- } else {
- setListening(true);
- }
- mQsExpandImmediate = false;
- mNotificationStackScroller.setShouldShowShelfOnly(false);
- mTwoFingerQsExpandPossible = false;
- notifyListenersTrackingHeadsUp(null);
- mExpandingFromHeadsUp = false;
- setPanelScrimMinFraction(0.0f);
- }
-
- private void notifyListenersTrackingHeadsUp(ExpandableNotificationRow pickedChild) {
- for (int i = 0; i < mTrackingHeadsUpListeners.size(); i++) {
- Consumer<ExpandableNotificationRow> listener = mTrackingHeadsUpListeners.get(i);
- listener.accept(pickedChild);
- }
- }
-
- private void setListening(boolean listening) {
- mKeyguardStatusBar.setListening(listening);
- if (mQs == null) return;
- mQs.setListening(listening);
- if (mNPVPluginManager != null) mNPVPluginManager.setListening(listening);
- }
-
- @Override
- public void expand(boolean animate) {
- super.expand(animate);
- setListening(true);
- }
-
- @Override
- protected void setOverExpansion(float overExpansion, boolean isPixels) {
- if (mConflictingQsExpansionGesture || mQsExpandImmediate) {
- return;
- }
- if (mBarState != StatusBarState.KEYGUARD) {
- mNotificationStackScroller.setOnHeightChangedListener(null);
- if (isPixels) {
- mNotificationStackScroller.setOverScrolledPixels(overExpansion, true /* onTop */,
- false /* animate */);
- } else {
- mNotificationStackScroller.setOverScrollAmount(overExpansion, true /* onTop */,
- false /* animate */);
- }
- mNotificationStackScroller.setOnHeightChangedListener(mOnHeightChangedListener);
- }
- }
-
- @Override
- protected void onTrackingStarted() {
- mFalsingManager.onTrackingStarted(!mKeyguardStateController.canDismissLockScreen());
- super.onTrackingStarted();
- if (mQsFullyExpanded) {
- mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
- }
- if (mBarState == StatusBarState.KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) {
- mAffordanceHelper.animateHideLeftRightIcon();
- }
- mNotificationStackScroller.onPanelTrackingStarted();
- }
-
- @Override
- protected void onTrackingStopped(boolean expand) {
- mFalsingManager.onTrackingStopped();
- super.onTrackingStopped(expand);
- if (expand) {
- mNotificationStackScroller.setOverScrolledPixels(0.0f, true /* onTop */,
- true /* animate */);
- }
- mNotificationStackScroller.onPanelTrackingStopped();
- if (expand && (mBarState == StatusBarState.KEYGUARD
- || mBarState == StatusBarState.SHADE_LOCKED)) {
- if (!mHintAnimationRunning) {
- mAffordanceHelper.reset(true);
- }
- }
- }
-
- private void updateMaxHeadsUpTranslation() {
- mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mNavigationBarBottomHeight);
- }
-
- @Override
- protected void startUnlockHintAnimation() {
- if (mPowerManager.isPowerSaveMode()) {
- onUnlockHintStarted();
- onUnlockHintFinished();
- return;
- }
- super.startUnlockHintAnimation();
- }
-
- @Override
- protected void onUnlockHintFinished() {
- super.onUnlockHintFinished();
- mNotificationStackScroller.setUnlockHintRunning(false);
- }
-
- @Override
- protected void onUnlockHintStarted() {
- super.onUnlockHintStarted();
- mNotificationStackScroller.setUnlockHintRunning(true);
- }
-
- @Override
- protected float getPeekHeight() {
- if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
- return mNotificationStackScroller.getPeekHeight();
- } else {
- return mQsMinExpansionHeight;
- }
- }
-
- @Override
- protected boolean shouldUseDismissingAnimation() {
- return mBarState != StatusBarState.SHADE && (mKeyguardStateController.canDismissLockScreen()
- || !isTracking());
- }
-
- @Override
- protected boolean fullyExpandedClearAllVisible() {
- return mNotificationStackScroller.isFooterViewNotGone()
- && mNotificationStackScroller.isScrolledToBottom() && !mQsExpandImmediate;
- }
-
- @Override
- protected boolean isClearAllVisible() {
- return mNotificationStackScroller.isFooterViewContentVisible();
- }
-
- @Override
- protected int getClearAllHeight() {
- return mNotificationStackScroller.getFooterViewHeight();
- }
-
- @Override
- protected boolean isTrackingBlocked() {
- return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
- }
-
- public boolean isQsExpanded() {
- return mQsExpanded;
- }
-
- public boolean isQsDetailShowing() {
- return mQs.isShowingDetail();
- }
-
- public void closeQsDetail() {
- mQs.closeDetail();
- }
-
- public boolean isLaunchTransitionFinished() {
- return mIsLaunchTransitionFinished;
- }
-
- public boolean isLaunchTransitionRunning() {
- return mIsLaunchTransitionRunning;
- }
-
- public void setLaunchTransitionEndRunnable(Runnable r) {
- mLaunchAnimationEndRunnable = r;
- }
-
- private void updateDozingVisibilities(boolean animate) {
- mKeyguardBottomArea.setDozing(mDozing, animate);
- if (!mDozing && animate) {
- animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- }
- }
-
- @Override
- public boolean isDozing() {
- return mDozing;
- }
-
- public void showEmptyShadeView(boolean emptyShadeViewVisible) {
- mShowEmptyShadeView = emptyShadeViewVisible;
- updateEmptyShadeView();
- }
-
- private void updateEmptyShadeView() {
- // Hide "No notifications" in QS.
- mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
- }
-
- public void setQsScrimEnabled(boolean qsScrimEnabled) {
- boolean changed = mQsScrimEnabled != qsScrimEnabled;
- mQsScrimEnabled = qsScrimEnabled;
- if (changed) {
- updateQsState();
- }
- }
-
- public void setKeyguardUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
- mKeyguardUserSwitcher = keyguardUserSwitcher;
- }
-
- public void onScreenTurningOn() {
- mKeyguardStatusView.dozeTimeTick();
- }
-
- @Override
- protected boolean onMiddleClicked() {
- switch (mBarState) {
- case StatusBarState.KEYGUARD:
- if (!mDozingOnDown) {
- if (mKeyguardBypassController.getBypassEnabled()) {
- mUpdateMonitor.requestFaceAuth();
- } else {
- mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_HINT,
- 0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
- startUnlockHintAnimation();
- }
- }
- return true;
- case StatusBarState.SHADE_LOCKED:
- if (!mQsExpanded) {
- mStatusBarStateController.setState(StatusBarState.KEYGUARD);
- }
- return true;
- case StatusBarState.SHADE:
-
- // This gets called in the middle of the touch handling, where the state is still
- // that we are tracking the panel. Collapse the panel after this is done.
- mView.post(mPostCollapseRunnable);
- return false;
- default:
- return true;
- }
- }
-
- public void setPanelAlpha(int alpha, boolean animate) {
- if (mPanelAlpha != alpha) {
- mPanelAlpha = alpha;
- PropertyAnimator.setProperty(mView, mPanelAlphaAnimator, alpha, alpha == 255
- ? mPanelAlphaInPropertiesAnimator : mPanelAlphaOutPropertiesAnimator,
- animate);
- }
- }
-
- public void setPanelAlphaEndAction(Runnable r) {
- mPanelAlphaEndAction = r;
- }
-
- private void updateKeyguardStatusBarForHeadsUp() {
- boolean
- showingKeyguardHeadsUp =
- mKeyguardShowing && mHeadsUpAppearanceController.shouldBeVisible();
- if (mShowingKeyguardHeadsUp != showingKeyguardHeadsUp) {
- mShowingKeyguardHeadsUp = showingKeyguardHeadsUp;
- if (mKeyguardShowing) {
- PropertyAnimator.setProperty(mView, KEYGUARD_HEADS_UP_SHOWING_AMOUNT,
- showingKeyguardHeadsUp ? 1.0f : 0.0f, KEYGUARD_HUN_PROPERTIES,
- true /* animate */);
- } else {
- PropertyAnimator.applyImmediately(mView, KEYGUARD_HEADS_UP_SHOWING_AMOUNT, 0.0f);
- }
- }
- }
-
- private void setKeyguardHeadsUpShowingAmount(float amount) {
- mKeyguardHeadsUpShowingAmount = amount;
- updateHeaderKeyguardAlpha();
- }
-
- private float getKeyguardHeadsUpShowingAmount() {
- return mKeyguardHeadsUpShowingAmount;
- }
-
- public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
- mHeadsUpAnimatingAway = headsUpAnimatingAway;
- mNotificationStackScroller.setHeadsUpAnimatingAway(headsUpAnimatingAway);
- updateHeadsUpVisibility();
- }
-
- private void updateHeadsUpVisibility() {
- ((PhoneStatusBarView) mBar).setHeadsUpVisible(mHeadsUpAnimatingAway || mHeadsUpPinnedMode);
- }
-
- @Override
- public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
- super.setHeadsUpManager(headsUpManager);
- mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager,
- mNotificationStackScroller.getHeadsUpCallback(),
- NotificationPanelViewController.this);
- }
-
- public void setTrackedHeadsUp(ExpandableNotificationRow pickedChild) {
- if (pickedChild != null) {
- notifyListenersTrackingHeadsUp(pickedChild);
- mExpandingFromHeadsUp = true;
- }
- // otherwise we update the state when the expansion is finished
- }
-
- @Override
- protected void onClosingFinished() {
- super.onClosingFinished();
- resetHorizontalPanelPosition();
- setClosingWithAlphaFadeout(false);
- }
-
- private void setClosingWithAlphaFadeout(boolean closing) {
- mClosingWithAlphaFadeOut = closing;
- mNotificationStackScroller.forceNoOverlappingRendering(closing);
- }
-
- /**
- * Updates the vertical position of the panel so it is positioned closer to the touch
- * responsible for opening the panel.
- *
- * @param x the x-coordinate the touch event
- */
- protected void updateVerticalPanelPosition(float x) {
- if (mNotificationStackScroller.getWidth() * 1.75f > mView.getWidth()) {
- resetHorizontalPanelPosition();
- return;
- }
- float leftMost = mPositionMinSideMargin + mNotificationStackScroller.getWidth() / 2;
- float
- rightMost =
- mView.getWidth() - mPositionMinSideMargin
- - mNotificationStackScroller.getWidth() / 2;
- if (Math.abs(x - mView.getWidth() / 2) < mNotificationStackScroller.getWidth() / 4) {
- x = mView.getWidth() / 2;
- }
- x = Math.min(rightMost, Math.max(leftMost, x));
- float
- center =
- mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2;
- setHorizontalPanelTranslation(x - center);
- }
-
- private void resetHorizontalPanelPosition() {
- setHorizontalPanelTranslation(0f);
- }
-
- protected void setHorizontalPanelTranslation(float translation) {
- mNotificationStackScroller.setTranslationX(translation);
- mQsFrame.setTranslationX(translation);
- int size = mVerticalTranslationListener.size();
- for (int i = 0; i < size; i++) {
- mVerticalTranslationListener.get(i).run();
- }
- }
-
- protected void updateExpandedHeight(float expandedHeight) {
- if (mTracking) {
- mNotificationStackScroller.setExpandingVelocity(getCurrentExpandVelocity());
- }
- if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) {
- // The expandedHeight is always the full panel Height when bypassing
- expandedHeight = getMaxPanelHeightNonBypass();
- }
- mNotificationStackScroller.setExpandedHeight(expandedHeight);
- updateKeyguardBottomAreaAlpha();
- updateBigClockAlpha();
- updateStatusBarIcons();
- }
-
- /**
- * @return whether the notifications are displayed full width and don't have any margins on
- * the side.
- */
- public boolean isFullWidth() {
- return mIsFullWidth;
- }
-
- private void updateStatusBarIcons() {
- boolean
- showIconsWhenExpanded =
- (isPanelVisibleBecauseOfHeadsUp() || isFullWidth())
- && getExpandedHeight() < getOpeningHeight();
- boolean noVisibleNotifications = true;
- if (showIconsWhenExpanded && noVisibleNotifications && isOnKeyguard()) {
- showIconsWhenExpanded = false;
- }
- if (showIconsWhenExpanded != mShowIconsWhenExpanded) {
- mShowIconsWhenExpanded = showIconsWhenExpanded;
- mCommandQueue.recomputeDisableFlags(mDisplayId, false);
- }
- }
-
- private boolean isOnKeyguard() {
- return mBarState == StatusBarState.KEYGUARD;
- }
-
- public void setPanelScrimMinFraction(float minFraction) {
- mBar.panelScrimMinFractionChanged(minFraction);
- }
-
- public void clearNotificationEffects() {
- mStatusBar.clearNotificationEffects();
- }
-
- @Override
- protected boolean isPanelVisibleBecauseOfHeadsUp() {
- return (mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpAnimatingAway)
- && mBarState == StatusBarState.SHADE;
- }
-
- public void launchCamera(boolean animate, int source) {
- if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) {
- mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP;
- } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_WIGGLE) {
- mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_WIGGLE;
- } else if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER) {
- mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_LIFT_TRIGGER;
- } else {
-
- // Default.
- mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
- }
-
- // If we are launching it when we are occluded already we don't want it to animate,
- // nor setting these flags, since the occluded state doesn't change anymore, hence it's
- // never reset.
- if (!isFullyCollapsed()) {
- setLaunchingAffordance(true);
- } else {
- animate = false;
- }
- mAffordanceHasPreview = mKeyguardBottomArea.getRightPreview() != null;
- mAffordanceHelper.launchAffordance(
- animate, mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- }
-
- public void onAffordanceLaunchEnded() {
- setLaunchingAffordance(false);
- }
-
- /**
- * Set whether we are currently launching an affordance. This is currently only set when
- * launched via a camera gesture.
- */
- private void setLaunchingAffordance(boolean launchingAffordance) {
- mLaunchingAffordance = launchingAffordance;
- mKeyguardAffordanceHelperCallback.getLeftIcon().setLaunchingAffordance(launchingAffordance);
- mKeyguardAffordanceHelperCallback.getRightIcon().setLaunchingAffordance(
- launchingAffordance);
- mKeyguardBypassController.setLaunchingAffordance(launchingAffordance);
- if (mAffordanceLaunchListener != null) {
- mAffordanceLaunchListener.accept(launchingAffordance);
- }
- }
-
- /**
- * Return true when a bottom affordance is launching an occluded activity with a splash screen.
- */
- public boolean isLaunchingAffordanceWithPreview() {
- return mLaunchingAffordance && mAffordanceHasPreview;
- }
-
- /**
- * Whether the camera application can be launched for the camera launch gesture.
- */
- public boolean canCameraGestureBeLaunched() {
- if (!mStatusBar.isCameraAllowedByAdmin()) {
- return false;
- }
-
- ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent();
- String
- packageToLaunch =
- (resolveInfo == null || resolveInfo.activityInfo == null) ? null
- : resolveInfo.activityInfo.packageName;
- return packageToLaunch != null && (mBarState != StatusBarState.SHADE || !isForegroundApp(
- packageToLaunch)) && !mAffordanceHelper.isSwipingInProgress();
- }
-
- /**
- * Return true if the applications with the package name is running in foreground.
- *
- * @param pkgName application package name.
- */
- private boolean isForegroundApp(String pkgName) {
- List<ActivityManager.RunningTaskInfo> tasks = mActivityManager.getRunningTasks(1);
- return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
- }
-
- private void setGroupManager(NotificationGroupManager groupManager) {
- mGroupManager = groupManager;
- }
-
- public boolean hideStatusBarIconsWhenExpanded() {
- if (mLaunchingNotification) {
- return mHideIconsDuringNotificationLaunch;
- }
- if (mHeadsUpAppearanceController != null
- && mHeadsUpAppearanceController.shouldBeVisible()) {
- return false;
- }
- return !isFullWidth() || !mShowIconsWhenExpanded;
- }
-
- private final FragmentListener mFragmentListener = new FragmentListener() {
- @Override
- public void onFragmentViewCreated(String tag, Fragment fragment) {
- mQs = (QS) fragment;
- mQs.setPanelView(mHeightListener);
- mQs.setExpandClickListener(mOnClickListener);
- mQs.setHeaderClickable(mQsExpansionEnabled);
- updateQSPulseExpansion();
- mQs.setOverscrolling(mStackScrollerOverscrolling);
-
- // recompute internal state when qspanel height changes
- mQs.getView().addOnLayoutChangeListener(
- (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
- final int height = bottom - top;
- final int oldHeight = oldBottom - oldTop;
- if (height != oldHeight) {
- mHeightListener.onQsHeightChanged();
- }
- });
- mNotificationStackScroller.setQsContainer((ViewGroup) mQs.getView());
- if (mQs instanceof QSFragment) {
- mKeyguardStatusBar.setQSPanel(((QSFragment) mQs).getQsPanel());
- }
- updateQsExpansion();
- }
-
- @Override
- public void onFragmentViewDestroyed(String tag, Fragment fragment) {
- // Manual handling of fragment lifecycle is only required because this bridges
- // non-fragment and fragment code. Once we are using a fragment for the notification
- // panel, mQs will not need to be null cause it will be tied to the same lifecycle.
- if (fragment == mQs) {
- mQs = null;
- }
- }
- };
-
- @Override
- public void setTouchAndAnimationDisabled(boolean disabled) {
- super.setTouchAndAnimationDisabled(disabled);
- if (disabled && mAffordanceHelper.isSwipingInProgress() && !mIsLaunchTransitionRunning) {
- mAffordanceHelper.reset(false /* animate */);
- }
- mNotificationStackScroller.setAnimationsEnabled(!disabled);
- }
-
- /**
- * Sets the dozing state.
- *
- * @param dozing {@code true} when dozing.
- * @param animate if transition should be animated.
- * @param wakeUpTouchLocation touch event location - if woken up by SLPI sensor.
- */
- public void setDozing(boolean dozing, boolean animate, PointF wakeUpTouchLocation) {
- if (dozing == mDozing) return;
- mView.setDozing(dozing);
- mDozing = dozing;
- mNotificationStackScroller.setDozing(mDozing, animate, wakeUpTouchLocation);
- mKeyguardBottomArea.setDozing(mDozing, animate);
-
- if (dozing) {
- mBottomAreaShadeAlphaAnimator.cancel();
- }
-
- if (mBarState == StatusBarState.KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) {
- updateDozingVisibilities(animate);
- }
-
- final float dozeAmount = dozing ? 1 : 0;
- mStatusBarStateController.setDozeAmount(dozeAmount, animate);
- }
-
- public void setPulsing(boolean pulsing) {
- mPulsing = pulsing;
- final boolean
- animatePulse =
- !mDozeParameters.getDisplayNeedsBlanking() && mDozeParameters.getAlwaysOn();
- if (animatePulse) {
- mAnimateNextPositionUpdate = true;
- }
- // Do not animate the clock when waking up from a pulse.
- // The height callback will take care of pushing the clock to the right position.
- if (!mPulsing && !mDozing) {
- mAnimateNextPositionUpdate = false;
- }
- mNotificationStackScroller.setPulsing(pulsing, animatePulse);
- mKeyguardStatusView.setPulsing(pulsing);
- }
-
- public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
- if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) {
- mAmbientIndicationBottomPadding = ambientIndicationBottomPadding;
- mStatusBar.updateKeyguardMaxNotifications();
- }
- }
-
- public void dozeTimeTick() {
- mKeyguardBottomArea.dozeTimeTick();
- mKeyguardStatusView.dozeTimeTick();
- if (mInterpolatedDarkAmount > 0) {
- positionClockAndNotifications();
- }
- }
-
- public void setStatusAccessibilityImportance(int mode) {
- mKeyguardStatusView.setImportantForAccessibility(mode);
- }
-
- /**
- * TODO: this should be removed.
- * It's not correct to pass this view forward because other classes will end up adding
- * children to it. Theme will be out of sync.
- *
- * @return bottom area view
- */
- public KeyguardBottomAreaView getKeyguardBottomAreaView() {
- return mKeyguardBottomArea;
- }
-
- public void setUserSetupComplete(boolean userSetupComplete) {
- mUserSetupComplete = userSetupComplete;
- mKeyguardBottomArea.setUserSetupComplete(userSetupComplete);
- }
-
- public void applyExpandAnimationParams(ExpandAnimationParameters params) {
- mExpandOffset = params != null ? params.getTopChange() : 0;
- updateQsExpansion();
- if (params != null) {
- boolean hideIcons = params.getProgress(
- ActivityLaunchAnimator.ANIMATION_DELAY_ICON_FADE_IN, 100) == 0.0f;
- if (hideIcons != mHideIconsDuringNotificationLaunch) {
- mHideIconsDuringNotificationLaunch = hideIcons;
- if (!hideIcons) {
- mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
- }
- }
- }
- }
-
- public void addTrackingHeadsUpListener(Consumer<ExpandableNotificationRow> listener) {
- mTrackingHeadsUpListeners.add(listener);
- }
-
- public void removeTrackingHeadsUpListener(Consumer<ExpandableNotificationRow> listener) {
- mTrackingHeadsUpListeners.remove(listener);
- }
-
- public void addVerticalTranslationListener(Runnable verticalTranslationListener) {
- mVerticalTranslationListener.add(verticalTranslationListener);
- }
-
- public void removeVerticalTranslationListener(Runnable verticalTranslationListener) {
- mVerticalTranslationListener.remove(verticalTranslationListener);
- }
-
- public void setHeadsUpAppearanceController(
- HeadsUpAppearanceController headsUpAppearanceController) {
- mHeadsUpAppearanceController = headsUpAppearanceController;
- }
-
- /**
- * Starts the animation before we dismiss Keyguard, i.e. an disappearing animation on the
- * security view of the bouncer.
- */
- public void onBouncerPreHideAnimation() {
- setKeyguardStatusViewVisibility(mBarState, true /* keyguardFadingAway */,
- false /* goingToFullShade */);
- }
-
- /**
- * Do not let the user drag the shade up and down for the current touch session.
- * This is necessary to avoid shade expansion while/after the bouncer is dismissed.
- */
- public void blockExpansionForCurrentTouch() {
- mBlockingExpansionForCurrentTouch = mTracking;
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
- pw.println(" gestureExclusionRect: " + calculateGestureExclusionRect());
- if (mKeyguardStatusBar != null) {
- mKeyguardStatusBar.dump(fd, pw, args);
- }
- if (mKeyguardStatusView != null) {
- mKeyguardStatusView.dump(fd, pw, args);
- }
- }
-
- public boolean hasActiveClearableNotifications() {
- return mNotificationStackScroller.hasActiveClearableNotifications(ROWS_ALL);
- }
-
- private void updateShowEmptyShadeView() {
- boolean
- showEmptyShadeView =
- mBarState != StatusBarState.KEYGUARD && !mEntryManager.hasActiveNotifications();
- showEmptyShadeView(showEmptyShadeView);
- }
-
- public RemoteInputController.Delegate createRemoteInputDelegate() {
- return mNotificationStackScroller.createDelegate();
- }
-
- public void updateNotificationViews() {
- mNotificationStackScroller.updateSectionBoundaries();
- mNotificationStackScroller.updateSpeedBumpIndex();
- mNotificationStackScroller.updateFooter();
- updateShowEmptyShadeView();
- mNotificationStackScroller.updateIconAreaViews();
- }
-
- public void onUpdateRowStates() {
- mNotificationStackScroller.onUpdateRowStates();
- }
-
- public boolean hasPulsingNotifications() {
- return mNotificationStackScroller.hasPulsingNotifications();
- }
-
- public ActivatableNotificationView getActivatedChild() {
- return mNotificationStackScroller.getActivatedChild();
- }
-
- public void setActivatedChild(ActivatableNotificationView o) {
- mNotificationStackScroller.setActivatedChild(o);
- }
-
- public void runAfterAnimationFinished(Runnable r) {
- mNotificationStackScroller.runAfterAnimationFinished(r);
- }
-
- public void setScrollingEnabled(boolean b) {
- mNotificationStackScroller.setScrollingEnabled(b);
- }
-
- public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager,
- NotificationShelf notificationShelf,
- NotificationIconAreaController notificationIconAreaController,
- ScrimController scrimController) {
- setStatusBar(statusBar);
- setGroupManager(mGroupManager);
- mNotificationStackScroller.setNotificationPanelController(this);
- mNotificationStackScroller.setIconAreaController(notificationIconAreaController);
- mNotificationStackScroller.setStatusBar(statusBar);
- mNotificationStackScroller.setGroupManager(groupManager);
- mNotificationStackScroller.setShelf(notificationShelf);
- mNotificationStackScroller.setScrimController(scrimController);
- updateShowEmptyShadeView();
- }
-
- public void showTransientIndication(int id) {
- mKeyguardIndicationController.showTransientIndication(id);
- }
-
- public void setOnReinflationListener(Runnable onReinflationListener) {
- mOnReinflationListener = onReinflationListener;
- }
-
- public static boolean isQsSplitEnabled() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.QS_SPLIT_ENABLED, false);
- }
-
- public void setAlpha(float alpha) {
- mView.setAlpha(alpha);
- }
-
- public ViewPropertyAnimator fadeOut(long startDelayMs, long durationMs, Runnable endAction) {
- return mView.animate().alpha(0).setStartDelay(startDelayMs).setDuration(
- durationMs).setInterpolator(Interpolators.ALPHA_OUT).withLayer().withEndAction(
- endAction);
- }
-
- public void resetViewGroupFade() {
- ViewGroupFadeHelper.reset(mView);
- }
-
- public void addOnGlobalLayoutListener(ViewTreeObserver.OnGlobalLayoutListener listener) {
- mView.getViewTreeObserver().addOnGlobalLayoutListener(listener);
- }
-
- public void removeOnGlobalLayoutListener(ViewTreeObserver.OnGlobalLayoutListener listener) {
- mView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
- }
-
- public MyOnHeadsUpChangedListener getOnHeadsUpChangedListener() {
- return mOnHeadsUpChangedListener;
- }
-
- public int getHeight() {
- return mView.getHeight();
- }
-
- public TextView getHeaderDebugInfo() {
- return mView.findViewById(R.id.header_debug_info);
- }
-
- public void onThemeChanged() {
- mConfigurationListener.onThemeChanged();
- }
-
- @Override
- public OnLayoutChangeListener createLayoutChangeListener() {
- return new OnLayoutChangeListener();
- }
-
- public void setEmptyDragAmount(float amount) {
- mExpansionCallback.setEmptyDragAmount(amount);
- }
-
- @Override
- protected TouchHandler createTouchHandler() {
- return new TouchHandler() {
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if (mBlockTouches || mQsFullyExpanded && mQs.onInterceptTouchEvent(event)) {
- return false;
- }
- initDownStates(event);
- // Do not let touches go to shade or QS if the bouncer is visible,
- // but still let user swipe down to expand the panel, dismissing the bouncer.
- if (mStatusBar.isBouncerShowing()) {
- return true;
- }
- if (mBar.panelEnabled() && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
- mMetricsLogger.count(COUNTER_PANEL_OPEN, 1);
- mMetricsLogger.count(COUNTER_PANEL_OPEN_PEEK, 1);
- return true;
- }
- if (!shouldQuickSettingsIntercept(mDownX, mDownY, 0)
- && mPulseExpansionHandler.onInterceptTouchEvent(event)) {
- return true;
- }
-
- if (!isFullyCollapsed() && onQsIntercept(event)) {
- return true;
- }
- return super.onInterceptTouchEvent(event);
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (mBlockTouches || (mQs != null && mQs.isCustomizing())) {
- return false;
- }
-
- // Do not allow panel expansion if bouncer is scrimmed, otherwise user would be able
- // to pull down QS or expand the shade.
- if (mStatusBar.isBouncerShowingScrimmed()) {
- return false;
- }
-
- // Make sure the next touch won't the blocked after the current ends.
- if (event.getAction() == MotionEvent.ACTION_UP
- || event.getAction() == MotionEvent.ACTION_CANCEL) {
- mBlockingExpansionForCurrentTouch = false;
- }
- // When touch focus transfer happens, ACTION_DOWN->ACTION_UP may happen immediately
- // without any ACTION_MOVE event.
- // In such case, simply expand the panel instead of being stuck at the bottom bar.
- if (mLastEventSynthesizedDown && event.getAction() == MotionEvent.ACTION_UP) {
- expand(true /* animate */);
- }
- initDownStates(event);
- if (!mIsExpanding && !shouldQuickSettingsIntercept(mDownX, mDownY, 0)
- && mPulseExpansionHandler.onTouchEvent(event)) {
- // We're expanding all the other ones shouldn't get this anymore
- return true;
- }
- if (mListenForHeadsUp && !mHeadsUpTouchHelper.isTrackingHeadsUp()
- && mHeadsUpTouchHelper.onInterceptTouchEvent(event)) {
- mMetricsLogger.count(COUNTER_PANEL_OPEN_PEEK, 1);
- }
- boolean handled = false;
- if ((!mIsExpanding || mHintAnimationRunning) && !mQsExpanded
- && mBarState != StatusBarState.SHADE && !mDozing) {
- handled |= mAffordanceHelper.onTouchEvent(event);
- }
- if (mOnlyAffordanceInThisMotion) {
- return true;
- }
- handled |= mHeadsUpTouchHelper.onTouchEvent(event);
-
- if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && handleQsTouch(event)) {
- return true;
- }
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
- mMetricsLogger.count(COUNTER_PANEL_OPEN, 1);
- updateVerticalPanelPosition(event.getX());
- handled = true;
- }
- handled |= super.onTouch(v, event);
- return !mDozing || mPulsing || handled;
- }
- };
- }
-
- @Override
- protected PanelViewController.OnConfigurationChangedListener
- createOnConfigurationChangedListener() {
- return new OnConfigurationChangedListener();
- }
-
- private class OnHeightChangedListener implements ExpandableView.OnHeightChangedListener {
- @Override
- public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
-
- // Block update if we are in quick settings and just the top padding changed
- // (i.e. view == null).
- if (view == null && mQsExpanded) {
- return;
- }
- if (needsAnimation && mInterpolatedDarkAmount == 0) {
- mAnimateNextPositionUpdate = true;
- }
- ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone();
- ExpandableNotificationRow
- firstRow =
- firstChildNotGone instanceof ExpandableNotificationRow
- ? (ExpandableNotificationRow) firstChildNotGone : null;
- if (firstRow != null && (view == firstRow || (firstRow.getNotificationParent()
- == firstRow))) {
- requestScrollerTopPaddingUpdate(false /* animate */);
- }
- requestPanelHeightUpdate();
- }
-
- @Override
- public void onReset(ExpandableView view) {
- }
- }
-
- private class OnClickListener implements View.OnClickListener {
- @Override
- public void onClick(View v) {
- onQsExpansionStarted();
- if (mQsExpanded) {
- flingSettings(0 /* vel */, FLING_COLLAPSE, null /* onFinishRunnable */,
- true /* isClick */);
- } else if (mQsExpansionEnabled) {
- mLockscreenGestureLogger.write(MetricsEvent.ACTION_SHADE_QS_TAP, 0, 0);
- flingSettings(0 /* vel */, FLING_EXPAND, null /* onFinishRunnable */,
- true /* isClick */);
- }
- }
- }
-
- private class OnOverscrollTopChangedListener implements
- NotificationStackScrollLayout.OnOverscrollTopChangedListener {
- @Override
- public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
- cancelQsAnimation();
- if (!mQsExpansionEnabled) {
- amount = 0f;
- }
- float rounded = amount >= 1f ? amount : 0f;
- setOverScrolling(rounded != 0f && isRubberbanded);
- mQsExpansionFromOverscroll = rounded != 0f;
- mLastOverscroll = rounded;
- updateQsState();
- setQsExpansion(mQsMinExpansionHeight + rounded);
- }
-
- @Override
- public void flingTopOverscroll(float velocity, boolean open) {
- mLastOverscroll = 0f;
- mQsExpansionFromOverscroll = false;
- setQsExpansion(mQsExpansionHeight);
- flingSettings(!mQsExpansionEnabled && open ? 0f : velocity,
- open && mQsExpansionEnabled ? FLING_EXPAND : FLING_COLLAPSE, () -> {
- mStackScrollerOverscrolling = false;
- setOverScrolling(false);
- updateQsState();
- }, false /* isClick */);
- }
- }
-
- private class DynamicPrivacyControlListener implements DynamicPrivacyController.Listener {
- @Override
- public void onDynamicPrivacyChanged() {
- // Do not request animation when pulsing or waking up, otherwise the clock wiill be out
- // of sync with the notification panel.
- if (mLinearDarkAmount != 0) {
- return;
- }
- mAnimateNextPositionUpdate = true;
- }
- }
-
- private class KeyguardAffordanceHelperCallback implements KeyguardAffordanceHelper.Callback {
- @Override
- public void onAnimationToSideStarted(boolean rightPage, float translation, float vel) {
- boolean
- start =
- mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? rightPage
- : !rightPage;
- mIsLaunchTransitionRunning = true;
- mLaunchAnimationEndRunnable = null;
- float displayDensity = mStatusBar.getDisplayDensity();
- int lengthDp = Math.abs((int) (translation / displayDensity));
- int velocityDp = Math.abs((int) (vel / displayDensity));
- if (start) {
- mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_DIALER, lengthDp, velocityDp);
-
- mFalsingManager.onLeftAffordanceOn();
- if (mFalsingManager.shouldEnforceBouncer()) {
- mStatusBar.executeRunnableDismissingKeyguard(
- () -> mKeyguardBottomArea.launchLeftAffordance(), null,
- true /* dismissShade */, false /* afterKeyguardGone */,
- true /* deferred */);
- } else {
- mKeyguardBottomArea.launchLeftAffordance();
- }
- } else {
- if (KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE.equals(
- mLastCameraLaunchSource)) {
- mLockscreenGestureLogger.write(
- MetricsEvent.ACTION_LS_CAMERA, lengthDp, velocityDp);
- }
- mFalsingManager.onCameraOn();
- if (mFalsingManager.shouldEnforceBouncer()) {
- mStatusBar.executeRunnableDismissingKeyguard(
- () -> mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource), null,
- true /* dismissShade */, false /* afterKeyguardGone */,
- true /* deferred */);
- } else {
- mKeyguardBottomArea.launchCamera(mLastCameraLaunchSource);
- }
- }
- mStatusBar.startLaunchTransitionTimeout();
- mBlockTouches = true;
- }
-
- @Override
- public void onAnimationToSideEnded() {
- mIsLaunchTransitionRunning = false;
- mIsLaunchTransitionFinished = true;
- if (mLaunchAnimationEndRunnable != null) {
- mLaunchAnimationEndRunnable.run();
- mLaunchAnimationEndRunnable = null;
- }
- mStatusBar.readyForKeyguardDone();
- }
-
- @Override
- public float getMaxTranslationDistance() {
- return (float) Math.hypot(mView.getWidth(), getHeight());
- }
-
- @Override
- public void onSwipingStarted(boolean rightIcon) {
- mFalsingManager.onAffordanceSwipingStarted(rightIcon);
- boolean
- camera =
- mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? !rightIcon
- : rightIcon;
- if (camera) {
- mKeyguardBottomArea.bindCameraPrewarmService();
- }
- mView.requestDisallowInterceptTouchEvent(true);
- mOnlyAffordanceInThisMotion = true;
- mQsTracking = false;
- }
-
- @Override
- public void onSwipingAborted() {
- mFalsingManager.onAffordanceSwipingAborted();
- mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */);
- }
-
- @Override
- public void onIconClicked(boolean rightIcon) {
- if (mHintAnimationRunning) {
- return;
- }
- mHintAnimationRunning = true;
- mAffordanceHelper.startHintAnimation(rightIcon, () -> {
- mHintAnimationRunning = false;
- mStatusBar.onHintFinished();
- });
- rightIcon =
- mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? !rightIcon
- : rightIcon;
- if (rightIcon) {
- mStatusBar.onCameraHintStarted();
- } else {
- if (mKeyguardBottomArea.isLeftVoiceAssist()) {
- mStatusBar.onVoiceAssistHintStarted();
- } else {
- mStatusBar.onPhoneHintStarted();
- }
- }
- }
-
- @Override
- public KeyguardAffordanceView getLeftIcon() {
- return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
- ? mKeyguardBottomArea.getRightView() : mKeyguardBottomArea.getLeftView();
- }
-
- @Override
- public KeyguardAffordanceView getRightIcon() {
- return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
- ? mKeyguardBottomArea.getLeftView() : mKeyguardBottomArea.getRightView();
- }
-
- @Override
- public View getLeftPreview() {
- return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
- ? mKeyguardBottomArea.getRightPreview() : mKeyguardBottomArea.getLeftPreview();
- }
-
- @Override
- public View getRightPreview() {
- return mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
- ? mKeyguardBottomArea.getLeftPreview() : mKeyguardBottomArea.getRightPreview();
- }
-
- @Override
- public float getAffordanceFalsingFactor() {
- return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
- }
-
- @Override
- public boolean needsAntiFalsing() {
- return mBarState == StatusBarState.KEYGUARD;
- }
- }
-
- private class OnEmptySpaceClickListener implements
- NotificationStackScrollLayout.OnEmptySpaceClickListener {
- @Override
- public void onEmptySpaceClicked(float x, float y) {
- onEmptySpaceClick(x);
- }
- }
-
- private class MyOnHeadsUpChangedListener implements OnHeadsUpChangedListener {
- @Override
- public void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) {
- mNotificationStackScroller.setInHeadsUpPinnedMode(inPinnedMode);
- if (inPinnedMode) {
- mHeadsUpExistenceChangedRunnable.run();
- updateNotificationTranslucency();
- } else {
- setHeadsUpAnimatingAway(true);
- mNotificationStackScroller.runAfterAnimationFinished(
- mHeadsUpExistenceChangedRunnable);
- }
- updateGestureExclusionRect();
- mHeadsUpPinnedMode = inPinnedMode;
- updateHeadsUpVisibility();
- updateKeyguardStatusBarForHeadsUp();
- }
-
- @Override
- public void onHeadsUpPinned(NotificationEntry entry) {
- if (!isOnKeyguard()) {
- mNotificationStackScroller.generateHeadsUpAnimation(entry.getHeadsUpAnimationView(),
- true);
- }
- }
-
- @Override
- public void onHeadsUpUnPinned(NotificationEntry entry) {
-
- // When we're unpinning the notification via active edge they remain heads-upped,
- // we need to make sure that an animation happens in this case, otherwise the
- // notification
- // will stick to the top without any interaction.
- if (isFullyCollapsed() && entry.isRowHeadsUp() && !isOnKeyguard()) {
- mNotificationStackScroller.generateHeadsUpAnimation(
- entry.getHeadsUpAnimationView(), false);
- entry.setHeadsUpIsVisible();
- }
- }
-
- @Override
- public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- mNotificationStackScroller.generateHeadsUpAnimation(entry, isHeadsUp);
- }
- }
-
- private class HeightListener implements QS.HeightListener {
- public void onQsHeightChanged() {
- mQsMaxExpansionHeight = mQs != null ? mQs.getDesiredHeight() : 0;
- if (mQsExpanded && mQsFullyExpanded) {
- mQsExpansionHeight = mQsMaxExpansionHeight;
- requestScrollerTopPaddingUpdate(false /* animate */);
- requestPanelHeightUpdate();
- }
- if (mAccessibilityManager.isEnabled()) {
- mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
- }
- mNotificationStackScroller.setMaxTopPadding(
- mQsMaxExpansionHeight + mQsNotificationTopPadding);
- }
- }
-
- private class ZenModeControllerCallback implements ZenModeController.Callback {
- @Override
- public void onZenChanged(int zen) {
- updateShowEmptyShadeView();
- }
- }
-
- private class ConfigurationListener implements ConfigurationController.ConfigurationListener {
- @Override
- public void onDensityOrFontScaleChanged() {
- updateShowEmptyShadeView();
- }
-
- @Override
- public void onThemeChanged() {
- final int themeResId = mView.getContext().getThemeResId();
- if (mThemeResId == themeResId) {
- return;
- }
- mThemeResId = themeResId;
-
- reInflateViews();
- }
-
- @Override
- public void onOverlayChanged() {
- reInflateViews();
- }
-
- @Override
- public void onUiModeChanged() {
- reinflatePluginContainer();
- }
- }
-
- private class StatusBarStateListener implements StateListener {
- @Override
- public void onStateChanged(int statusBarState) {
- boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
- boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
- int oldState = mBarState;
- boolean keyguardShowing = statusBarState == StatusBarState.KEYGUARD;
- setKeyguardStatusViewVisibility(statusBarState, keyguardFadingAway, goingToFullShade);
- setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);
-
- mBarState = statusBarState;
- mKeyguardShowing = keyguardShowing;
- if (mKeyguardShowing && isQsSplitEnabled()) {
- mNotificationStackScroller.setVisibility(View.VISIBLE);
- mQsFrame.setVisibility(View.VISIBLE);
- mHomeControlsLayout.setVisibility(View.GONE);
- }
-
- if (oldState == StatusBarState.KEYGUARD && (goingToFullShade
- || statusBarState == StatusBarState.SHADE_LOCKED)) {
- animateKeyguardStatusBarOut();
- long
- delay =
- mBarState == StatusBarState.SHADE_LOCKED ? 0
- : mKeyguardStateController.calculateGoingToFullShadeDelay();
- mQs.animateHeaderSlidingIn(delay);
- } else if (oldState == StatusBarState.SHADE_LOCKED
- && statusBarState == StatusBarState.KEYGUARD) {
- animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- mNotificationStackScroller.resetScrollPosition();
- // Only animate header if the header is visible. If not, it will partially
- // animate out
- // the top of QS
- if (!mQsExpanded) {
- mQs.animateHeaderSlidingOut();
- }
- } else {
- mKeyguardStatusBar.setAlpha(1f);
- mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
- ((PhoneStatusBarView) mBar).maybeShowDivider(keyguardShowing);
- if (keyguardShowing && oldState != mBarState) {
- if (mQs != null) {
- mQs.hideImmediately();
- }
- }
- }
- updateKeyguardStatusBarForHeadsUp();
- if (keyguardShowing) {
- updateDozingVisibilities(false /* animate */);
- }
- // THe update needs to happen after the headerSlide in above, otherwise the translation
- // would reset
- updateQSPulseExpansion();
- maybeAnimateBottomAreaAlpha();
- resetHorizontalPanelPosition();
- updateQsState();
- }
-
- @Override
- public void onDozeAmountChanged(float linearAmount, float amount) {
- mInterpolatedDarkAmount = amount;
- mLinearDarkAmount = linearAmount;
- mKeyguardStatusView.setDarkAmount(mInterpolatedDarkAmount);
- mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount);
- positionClockAndNotifications();
- }
- }
-
- private class ExpansionCallback implements PulseExpansionHandler.ExpansionCallback {
- public void setEmptyDragAmount(float amount) {
- mEmptyDragAmount = amount * 0.2f;
- positionClockAndNotifications();
- }
- }
-
- private class OnAttachStateChangeListener implements View.OnAttachStateChangeListener {
- @Override
- public void onViewAttachedToWindow(View v) {
- FragmentHostManager.get(mView).addTagListener(QS.TAG, mFragmentListener);
- mStatusBarStateController.addCallback(mStatusBarStateListener);
- mZenModeController.addCallback(mZenModeControllerCallback);
- mConfigurationController.addCallback(mConfigurationListener);
- mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
- // Theme might have changed between inflating this view and attaching it to the
- // window, so
- // force a call to onThemeChanged
- mConfigurationListener.onThemeChanged();
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- FragmentHostManager.get(mView).removeTagListener(QS.TAG, mFragmentListener);
- mStatusBarStateController.removeCallback(mStatusBarStateListener);
- mZenModeController.removeCallback(mZenModeControllerCallback);
- mConfigurationController.removeCallback(mConfigurationListener);
- mUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
- }
- }
-
- private class OnLayoutChangeListener extends PanelViewController.OnLayoutChangeListener {
-
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
- int oldTop, int oldRight, int oldBottom) {
- DejankUtils.startDetectingBlockingIpcs("NVP#onLayout");
- super.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom);
- setIsFullWidth(mNotificationStackScroller.getWidth() == mView.getWidth());
-
- // Update Clock Pivot
- mKeyguardStatusView.setPivotX(mView.getWidth() / 2);
- mKeyguardStatusView.setPivotY(
- (FONT_HEIGHT - CAP_HEIGHT) / 2048f * mKeyguardStatusView.getClockTextSize());
-
- // Calculate quick setting heights.
- int oldMaxHeight = mQsMaxExpansionHeight;
- if (mQs != null) {
- mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
- if (mNPVPluginManager != null) {
- mNPVPluginManager.setYOffset(mQsMinExpansionHeight);
- mQsMinExpansionHeight += mNPVPluginManager.getHeight();
- }
- mQsMaxExpansionHeight = mQs.getDesiredHeight();
- mNotificationStackScroller.setMaxTopPadding(
- mQsMaxExpansionHeight + mQsNotificationTopPadding);
- }
- positionClockAndNotifications();
- if (mQsExpanded && mQsFullyExpanded) {
- mQsExpansionHeight = mQsMaxExpansionHeight;
- requestScrollerTopPaddingUpdate(false /* animate */);
- requestPanelHeightUpdate();
-
- // Size has changed, start an animation.
- if (mQsMaxExpansionHeight != oldMaxHeight) {
- startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
- }
- } else if (!mQsExpanded) {
- setQsExpansion(mQsMinExpansionHeight + mLastOverscroll);
- }
- updateExpandedHeight(getExpandedHeight());
- updateHeader();
-
- // If we are running a size change animation, the animation takes care of the height of
- // the container. However, if we are not animating, we always need to make the QS
- // container
- // the desired height so when closing the QS detail, it stays smaller after the size
- // change
- // animation is finished but the detail view is still being animated away (this
- // animation
- // takes longer than the size change animation).
- if (mQsSizeChangeAnimator == null && mQs != null) {
- mQs.setHeightOverride(mQs.getDesiredHeight());
- }
- updateMaxHeadsUpTranslation();
- updateGestureExclusionRect();
- if (mExpandAfterLayoutRunnable != null) {
- mExpandAfterLayoutRunnable.run();
- mExpandAfterLayoutRunnable = null;
- }
- DejankUtils.stopDetectingBlockingIpcs("NVP#onLayout");
- }
- }
-
- private class DebugDrawable extends Drawable {
-
- @Override
- public void draw(Canvas canvas) {
- Paint p = new Paint();
- p.setColor(Color.RED);
- p.setStrokeWidth(2);
- p.setStyle(Paint.Style.STROKE);
- canvas.drawLine(0, getMaxPanelHeight(), mView.getWidth(), getMaxPanelHeight(), p);
- p.setColor(Color.BLUE);
- canvas.drawLine(0, getExpandedHeight(), mView.getWidth(), getExpandedHeight(), p);
- p.setColor(Color.GREEN);
- canvas.drawLine(0, calculatePanelHeightQsExpanded(), mView.getWidth(),
- calculatePanelHeightQsExpanded(), p);
- p.setColor(Color.YELLOW);
- canvas.drawLine(0, calculatePanelHeightShade(), mView.getWidth(),
- calculatePanelHeightShade(), p);
- p.setColor(Color.MAGENTA);
- canvas.drawLine(
- 0, calculateQsTopPadding(), mView.getWidth(), calculateQsTopPadding(), p);
- p.setColor(Color.CYAN);
- canvas.drawLine(0, mClockPositionResult.stackScrollerPadding, mView.getWidth(),
- mNotificationStackScroller.getTopPadding(), p);
- p.setColor(Color.GRAY);
- canvas.drawLine(0, mClockPositionResult.clockY, mView.getWidth(),
- mClockPositionResult.clockY, p);
- }
-
- @Override
- public void setAlpha(int alpha) {
-
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
-
- }
-
- @Override
- public int getOpacity() {
- return 0;
- }
- }
-
- private class OnConfigurationChangedListener extends
- PanelViewController.OnConfigurationChangedListener {
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- mAffordanceHelper.onConfigurationChanged();
- if (newConfig.orientation != mLastOrientation) {
- resetHorizontalPanelPosition();
- }
- mLastOrientation = newConfig.orientation;
- }
- }
-
- private class OnApplyWindowInsetsListener implements View.OnApplyWindowInsetsListener {
- public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
- mNavigationBarBottomHeight = insets.getStableInsetBottom();
- updateMaxHeadsUpTranslation();
- return insets;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 8d8c8da..063d00b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -43,7 +43,7 @@
public static final int STATE_OPENING = 1;
public static final int STATE_OPEN = 2;
- PanelViewController mPanel;
+ PanelView mPanel;
private int mState = STATE_CLOSED;
private boolean mTracking;
@@ -83,8 +83,7 @@
super.onFinishInflate();
}
- /** Set the PanelViewController */
- public void setPanel(PanelViewController pv) {
+ public void setPanel(PanelView pv) {
mPanel = pv;
pv.setBar(this);
}
@@ -97,7 +96,7 @@
setImportantForAccessibility(important);
updateVisibility();
- if (mPanel != null) mPanel.getView().setImportantForAccessibility(important);
+ if (mPanel != null) mPanel.setImportantForAccessibility(important);
}
public float getExpansionFraction() {
@@ -109,7 +108,7 @@
}
protected void updateVisibility() {
- mPanel.getView().setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE);
+ mPanel.setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE);
}
protected boolean shouldPanelBeVisible() {
@@ -132,7 +131,7 @@
}
if (event.getAction() == MotionEvent.ACTION_DOWN) {
- final PanelViewController panel = mPanel;
+ final PanelView panel = mPanel;
if (panel == null) {
// panel is not there, so we'll eat the gesture
Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",
@@ -150,7 +149,7 @@
return true;
}
}
- return mPanel == null || mPanel.getView().dispatchTouchEvent(event);
+ return mPanel == null || mPanel.onTouchEvent(event);
}
public abstract void panelScrimMinFractionChanged(float minFraction);
@@ -164,7 +163,7 @@
boolean fullyClosed = true;
boolean fullyOpened = false;
if (SPEW) LOG("panelExpansionChanged: start state=%d", mState);
- PanelViewController pv = mPanel;
+ PanelView pv = mPanel;
mExpanded = expanded;
mPanelFraction = frac;
updateVisibility();
@@ -193,7 +192,7 @@
public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {
boolean waiting = false;
- PanelViewController pv = mPanel;
+ PanelView pv = mPanel;
if (animate && !pv.isFullyCollapsed()) {
pv.collapse(delayed, speedUpFactor);
waiting = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 2719a32..cd56d06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -16,62 +16,1255 @@
package com.android.systemui.statusbar.phone;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.SystemClock;
+import android.os.VibrationEffect;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.InputDevice;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewTreeObserver;
+import android.view.animation.Interpolator;
import android.widget.FrameLayout;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.LatencyTracker;
+import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
public abstract class PanelView extends FrameLayout {
public static final boolean DEBUG = PanelBar.DEBUG;
public static final String TAG = PanelView.class.getSimpleName();
- private PanelViewController.TouchHandler mTouchHandler;
+ private static final int INITIAL_OPENING_PEEK_DURATION = 200;
+ private static final int PEEK_ANIMATION_DURATION = 360;
+ private static final int NO_FIXED_DURATION = -1;
+ protected long mDownTime;
+ protected boolean mTouchSlopExceededBeforeDown;
+ private float mMinExpandHeight;
+ private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+ private boolean mPanelUpdateWhenAnimatorEnds;
+ private boolean mVibrateOnOpening;
+ protected boolean mLaunchingNotification;
+ private int mFixedDuration = NO_FIXED_DURATION;
+ protected ArrayList<PanelExpansionListener> mExpansionListeners = new ArrayList<>();
+
+ private final void logf(String fmt, Object... args) {
+ Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
+ }
protected StatusBar mStatusBar;
protected HeadsUpManagerPhone mHeadsUpManager;
+ private float mPeekHeight;
+ private float mHintDistance;
+ private float mInitialOffsetOnTouch;
+ private boolean mCollapsedAndHeadsUpOnDown;
+ private float mExpandedFraction = 0;
+ protected float mExpandedHeight = 0;
+ private boolean mPanelClosedOnDown;
+ private boolean mHasLayoutedSinceDown;
+ private float mUpdateFlingVelocity;
+ private boolean mUpdateFlingOnLayout;
+ private boolean mPeekTouching;
+ private boolean mJustPeeked;
+ private boolean mClosing;
+ protected boolean mTracking;
+ private boolean mTouchSlopExceeded;
+ private int mTrackingPointer;
protected int mTouchSlop;
+ protected boolean mHintAnimationRunning;
+ private boolean mOverExpandedBeforeFling;
+ private boolean mTouchAboveFalsingThreshold;
+ private int mUnlockFalsingThreshold;
+ private boolean mTouchStartedInEmptyArea;
+ private boolean mMotionAborted;
+ private boolean mUpwardsWhenTresholdReached;
+ private boolean mAnimatingOnDown;
+ private ValueAnimator mHeightAnimator;
+ private ObjectAnimator mPeekAnimator;
+ private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
+ private FlingAnimationUtils mFlingAnimationUtils;
+ private FlingAnimationUtils mFlingAnimationUtilsClosing;
+ private FlingAnimationUtils mFlingAnimationUtilsDismissing;
+ private final FalsingManager mFalsingManager;
+ private final DozeLog mDozeLog;
+ private final VibratorHelper mVibratorHelper;
+
+ /**
+ * Whether an instant expand request is currently pending and we are just waiting for layout.
+ */
+ private boolean mInstantExpanding;
+ private boolean mAnimateAfterExpanding;
+
+ PanelBar mBar;
+
+ private String mViewName;
+ private float mInitialTouchY;
+ private float mInitialTouchX;
+ private boolean mTouchDisabled;
+
+ /**
+ * Whether or not the PanelView can be expanded or collapsed with a drag.
+ */
+ private boolean mNotificationsDragEnabled;
+
+ private Interpolator mBounceInterpolator;
protected KeyguardBottomAreaView mKeyguardBottomArea;
- private OnConfigurationChangedListener mOnConfigurationChangedListener;
- public PanelView(Context context) {
- super(context);
+ /**
+ * Speed-up factor to be used when {@link #mFlingCollapseRunnable} runs the next time.
+ */
+ private float mNextCollapseSpeedUpFactor = 1.0f;
+
+ protected boolean mExpanding;
+ private boolean mGestureWaitForTouchSlop;
+ private boolean mIgnoreXTouchSlop;
+ private boolean mExpandLatencyTracking;
+ protected final KeyguardStateController mKeyguardStateController;
+ protected final SysuiStatusBarStateController mStatusBarStateController;
+
+ protected void onExpandingFinished() {
+ mBar.onExpandingFinished();
}
- public PanelView(Context context, AttributeSet attrs) {
+ protected void onExpandingStarted() {
+ }
+
+ private void notifyExpandingStarted() {
+ if (!mExpanding) {
+ mExpanding = true;
+ onExpandingStarted();
+ }
+ }
+
+ protected final void notifyExpandingFinished() {
+ endClosing();
+ if (mExpanding) {
+ mExpanding = false;
+ onExpandingFinished();
+ }
+ }
+
+ private void runPeekAnimation(long duration, float peekHeight, boolean collapseWhenFinished) {
+ mPeekHeight = peekHeight;
+ if (DEBUG) logf("peek to height=%.1f", mPeekHeight);
+ if (mHeightAnimator != null) {
+ return;
+ }
+ if (mPeekAnimator != null) {
+ mPeekAnimator.cancel();
+ }
+ mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight)
+ .setDuration(duration);
+ mPeekAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ mPeekAnimator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mPeekAnimator = null;
+ if (!mCancelled && collapseWhenFinished) {
+ postOnAnimation(mPostCollapseRunnable);
+ }
+
+ }
+ });
+ notifyExpandingStarted();
+ mPeekAnimator.start();
+ mJustPeeked = true;
+ }
+
+ public PanelView(Context context, AttributeSet attrs, FalsingManager falsingManager,
+ DozeLog dozeLog, KeyguardStateController keyguardStateController,
+ SysuiStatusBarStateController statusBarStateController) {
super(context, attrs);
+ mKeyguardStateController = keyguardStateController;
+ mStatusBarStateController = statusBarStateController;
+ DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+ mFlingAnimationUtils = new FlingAnimationUtils(displayMetrics,
+ 0.6f /* maxLengthSeconds */, 0.6f /* speedUpFactor */);
+ mFlingAnimationUtilsClosing = new FlingAnimationUtils(displayMetrics,
+ 0.5f /* maxLengthSeconds */, 0.6f /* speedUpFactor */);
+ mFlingAnimationUtilsDismissing = new FlingAnimationUtils(displayMetrics,
+ 0.5f /* maxLengthSeconds */, 0.2f /* speedUpFactor */, 0.6f /* x2 */,
+ 0.84f /* y2 */);
+ mBounceInterpolator = new BounceInterpolator();
+ mFalsingManager = falsingManager;
+ mDozeLog = dozeLog;
+ mNotificationsDragEnabled =
+ getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
+ mVibratorHelper = Dependency.get(VibratorHelper.class);
+ mVibrateOnOpening = mContext.getResources().getBoolean(
+ R.bool.config_vibrateOnIconAnimation);
}
- public PanelView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
+ protected void loadDimens() {
+ final Resources res = getContext().getResources();
+ final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+ mTouchSlop = configuration.getScaledTouchSlop();
+ mHintDistance = res.getDimension(R.dimen.hint_move_distance);
+ mUnlockFalsingThreshold = res.getDimensionPixelSize(R.dimen.unlock_falsing_threshold);
}
- public PanelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
+ private void addMovement(MotionEvent event) {
+ // Add movement to velocity tracker using raw screen X and Y coordinates instead
+ // of window coordinates because the window frame may be moving at the same time.
+ float deltaX = event.getRawX() - event.getX();
+ float deltaY = event.getRawY() - event.getY();
+ event.offsetLocation(deltaX, deltaY);
+ mVelocityTracker.addMovement(event);
+ event.offsetLocation(-deltaX, -deltaY);
}
- public void setOnTouchListener(PanelViewController.TouchHandler touchHandler) {
- super.setOnTouchListener(touchHandler);
- mTouchHandler = touchHandler;
+ public void setTouchAndAnimationDisabled(boolean disabled) {
+ mTouchDisabled = disabled;
+ if (mTouchDisabled) {
+ cancelHeightAnimator();
+ if (mTracking) {
+ onTrackingStopped(true /* expanded */);
+ }
+ notifyExpandingFinished();
+ }
}
- public void setOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
- mOnConfigurationChangedListener = listener;
+ public void startExpandLatencyTracking() {
+ if (LatencyTracker.isEnabled(mContext)) {
+ LatencyTracker.getInstance(mContext).onActionStart(
+ LatencyTracker.ACTION_EXPAND_PANEL);
+ mExpandLatencyTracking = true;
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mInstantExpanding
+ || (mTouchDisabled && event.getActionMasked() != MotionEvent.ACTION_CANCEL)
+ || (mMotionAborted && event.getActionMasked() != MotionEvent.ACTION_DOWN)) {
+ return false;
+ }
+
+ // If dragging should not expand the notifications shade, then return false.
+ if (!mNotificationsDragEnabled) {
+ if (mTracking) {
+ // Turn off tracking if it's on or the shade can get stuck in the down position.
+ onTrackingStopped(true /* expand */);
+ }
+ return false;
+ }
+
+ // On expanding, single mouse click expands the panel instead of dragging.
+ if (isFullyCollapsed() && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ expand(true);
+ }
+ return true;
+ }
+
+ /*
+ * We capture touch events here and update the expand height here in case according to
+ * the users fingers. This also handles multi-touch.
+ *
+ * If the user just clicks shortly, we show a quick peek of the shade.
+ *
+ * Flinging is also enabled in order to open or close the shade.
+ */
+
+ int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ if (pointerIndex < 0) {
+ pointerIndex = 0;
+ mTrackingPointer = event.getPointerId(pointerIndex);
+ }
+ final float x = event.getX(pointerIndex);
+ final float y = event.getY(pointerIndex);
+
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop();
+ mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
+ }
+
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
+ mJustPeeked = false;
+ mMinExpandHeight = 0.0f;
+ mPanelClosedOnDown = isFullyCollapsed();
+ mHasLayoutedSinceDown = false;
+ mUpdateFlingOnLayout = false;
+ mMotionAborted = false;
+ mPeekTouching = mPanelClosedOnDown;
+ mDownTime = SystemClock.uptimeMillis();
+ mTouchAboveFalsingThreshold = false;
+ mCollapsedAndHeadsUpOnDown = isFullyCollapsed()
+ && mHeadsUpManager.hasPinnedHeadsUp();
+ addMovement(event);
+ if (!mGestureWaitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning)
+ || mPeekAnimator != null) {
+ mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning)
+ || mPeekAnimator != null || mTouchSlopExceededBeforeDown;
+ cancelHeightAnimator();
+ cancelPeek();
+ onTrackingStarted();
+ }
+ if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()
+ && !mStatusBar.isBouncerShowing()) {
+ startOpening(event);
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ final int upPointer = event.getPointerId(event.getActionIndex());
+ if (mTrackingPointer == upPointer) {
+ // gesture is ongoing, find a new pointer to track
+ final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+ final float newY = event.getY(newIndex);
+ final float newX = event.getX(newIndex);
+ mTrackingPointer = event.getPointerId(newIndex);
+ startExpandMotion(newX, newY, true /* startTracking */, mExpandedHeight);
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+ mMotionAborted = true;
+ endMotionEvent(event, x, y, true /* forceCancel */);
+ return false;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ addMovement(event);
+ float h = y - mInitialTouchY;
+
+ // If the panel was collapsed when touching, we only need to check for the
+ // y-component of the gesture, as we have no conflicting horizontal gesture.
+ if (Math.abs(h) > mTouchSlop
+ && (Math.abs(h) > Math.abs(x - mInitialTouchX)
+ || mIgnoreXTouchSlop)) {
+ mTouchSlopExceeded = true;
+ if (mGestureWaitForTouchSlop && !mTracking && !mCollapsedAndHeadsUpOnDown) {
+ if (!mJustPeeked && mInitialOffsetOnTouch != 0f) {
+ startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
+ h = 0;
+ }
+ cancelHeightAnimator();
+ onTrackingStarted();
+ }
+ }
+ float newHeight = Math.max(0, h + mInitialOffsetOnTouch);
+ if (newHeight > mPeekHeight) {
+ if (mPeekAnimator != null) {
+ mPeekAnimator.cancel();
+ }
+ mJustPeeked = false;
+ } else if (mPeekAnimator == null && mJustPeeked) {
+ // The initial peek has finished, but we haven't dragged as far yet, lets
+ // speed it up by starting at the peek height.
+ mInitialOffsetOnTouch = mExpandedHeight;
+ mInitialTouchY = y;
+ mMinExpandHeight = mExpandedHeight;
+ mJustPeeked = false;
+ }
+ newHeight = Math.max(newHeight, mMinExpandHeight);
+ if (-h >= getFalsingThreshold()) {
+ mTouchAboveFalsingThreshold = true;
+ mUpwardsWhenTresholdReached = isDirectionUpwards(x, y);
+ }
+ if (!mJustPeeked && (!mGestureWaitForTouchSlop || mTracking) &&
+ !isTrackingBlocked()) {
+ setExpandedHeightInternal(newHeight);
+ }
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ addMovement(event);
+ endMotionEvent(event, x, y, false /* forceCancel */);
+ break;
+ }
+ return !mGestureWaitForTouchSlop || mTracking;
+ }
+
+ private void startOpening(MotionEvent event) {
+ runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(),
+ false /* collapseWhenFinished */);
+ notifyBarPanelExpansionChanged();
+ maybeVibrateOnOpening();
+
+ //TODO: keyguard opens QS a different way; log that too?
+
+ // Log the position of the swipe that opened the panel
+ float width = mStatusBar.getDisplayWidth();
+ float height = mStatusBar.getDisplayHeight();
+ int rot = mStatusBar.getRotation();
+
+ mLockscreenGestureLogger.writeAtFractionalPosition(MetricsEvent.ACTION_PANEL_VIEW_EXPAND,
+ (int) (event.getX() / width * 100),
+ (int) (event.getY() / height * 100),
+ rot);
+ }
+
+ protected void maybeVibrateOnOpening() {
+ if (mVibrateOnOpening) {
+ mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
+ }
+ }
+
+ protected abstract float getOpeningHeight();
+
+ /**
+ * @return whether the swiping direction is upwards and above a 45 degree angle compared to the
+ * horizontal direction
+ */
+ private boolean isDirectionUpwards(float x, float y) {
+ float xDiff = x - mInitialTouchX;
+ float yDiff = y - mInitialTouchY;
+ if (yDiff >= 0) {
+ return false;
+ }
+ return Math.abs(yDiff) >= Math.abs(xDiff);
+ }
+
+ protected void startExpandingFromPeek() {
+ mStatusBar.handlePeekToExpandTransistion();
+ }
+
+ protected void startExpandMotion(float newX, float newY, boolean startTracking,
+ float expandedHeight) {
+ mInitialOffsetOnTouch = expandedHeight;
+ mInitialTouchY = newY;
+ mInitialTouchX = newX;
+ if (startTracking) {
+ mTouchSlopExceeded = true;
+ setExpandedHeight(mInitialOffsetOnTouch);
+ onTrackingStarted();
+ }
+ }
+
+ private void endMotionEvent(MotionEvent event, float x, float y, boolean forceCancel) {
+ mTrackingPointer = -1;
+ if ((mTracking && mTouchSlopExceeded)
+ || Math.abs(x - mInitialTouchX) > mTouchSlop
+ || Math.abs(y - mInitialTouchY) > mTouchSlop
+ || event.getActionMasked() == MotionEvent.ACTION_CANCEL
+ || forceCancel) {
+ mVelocityTracker.computeCurrentVelocity(1000);
+ float vel = mVelocityTracker.getYVelocity();
+ float vectorVel = (float) Math.hypot(
+ mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
+
+ boolean expand = flingExpands(vel, vectorVel, x, y)
+ || event.getActionMasked() == MotionEvent.ACTION_CANCEL
+ || forceCancel;
+ mDozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
+ mStatusBar.isFalsingThresholdNeeded(),
+ mStatusBar.isWakeUpComingFromTouch());
+ // Log collapse gesture if on lock screen.
+ if (!expand && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+ float displayDensity = mStatusBar.getDisplayDensity();
+ int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity);
+ int velocityDp = (int) Math.abs(vel / displayDensity);
+ mLockscreenGestureLogger.write(
+ MetricsEvent.ACTION_LS_UNLOCK,
+ heightDp, velocityDp);
+ }
+ fling(vel, expand, isFalseTouch(x, y));
+ onTrackingStopped(expand);
+ mUpdateFlingOnLayout = expand && mPanelClosedOnDown && !mHasLayoutedSinceDown;
+ if (mUpdateFlingOnLayout) {
+ mUpdateFlingVelocity = vel;
+ }
+ } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking
+ && !mStatusBar.isBouncerShowing()
+ && !mKeyguardStateController.isKeyguardFadingAway()) {
+ long timePassed = SystemClock.uptimeMillis() - mDownTime;
+ if (timePassed < ViewConfiguration.getLongPressTimeout()) {
+ // Lets show the user that he can actually expand the panel
+ runPeekAnimation(PEEK_ANIMATION_DURATION, getPeekHeight(), true /* collapseWhenFinished */);
+ } else {
+ // We need to collapse the panel since we peeked to the small height.
+ postOnAnimation(mPostCollapseRunnable);
+ }
+ } else if (!mStatusBar.isBouncerShowing()) {
+ boolean expands = onEmptySpaceClick(mInitialTouchX);
+ onTrackingStopped(expands);
+ }
+
+ mVelocityTracker.clear();
+ mPeekTouching = false;
+ }
+
+ protected float getCurrentExpandVelocity() {
+ mVelocityTracker.computeCurrentVelocity(1000);
+ return mVelocityTracker.getYVelocity();
+ }
+
+ private int getFalsingThreshold() {
+ float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+ return (int) (mUnlockFalsingThreshold * factor);
+ }
+
+ protected abstract boolean shouldGestureWaitForTouchSlop();
+
+ protected abstract boolean shouldGestureIgnoreXTouchSlop(float x, float y);
+
+ protected void onTrackingStopped(boolean expand) {
+ mTracking = false;
+ mBar.onTrackingStopped(expand);
+ notifyBarPanelExpansionChanged();
+ }
+
+ protected void onTrackingStarted() {
+ endClosing();
+ mTracking = true;
+ mBar.onTrackingStarted();
+ notifyExpandingStarted();
+ notifyBarPanelExpansionChanged();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
- return mTouchHandler.onInterceptTouchEvent(event);
+ if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled
+ || (mMotionAborted && event.getActionMasked() != MotionEvent.ACTION_DOWN)) {
+ return false;
+ }
+
+ /*
+ * If the user drags anywhere inside the panel we intercept it if the movement is
+ * upwards. This allows closing the shade from anywhere inside the panel.
+ *
+ * We only do this if the current content is scrolled to the bottom,
+ * i.e isScrolledToBottom() is true and therefore there is no conflicting scrolling gesture
+ * possible.
+ */
+ int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ if (pointerIndex < 0) {
+ pointerIndex = 0;
+ mTrackingPointer = event.getPointerId(pointerIndex);
+ }
+ final float x = event.getX(pointerIndex);
+ final float y = event.getY(pointerIndex);
+ boolean scrolledToBottom = isScrolledToBottom();
+
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mStatusBar.userActivity();
+ mAnimatingOnDown = mHeightAnimator != null;
+ mMinExpandHeight = 0.0f;
+ mDownTime = SystemClock.uptimeMillis();
+ if (mAnimatingOnDown && mClosing && !mHintAnimationRunning
+ || mPeekAnimator != null) {
+ cancelHeightAnimator();
+ cancelPeek();
+ mTouchSlopExceeded = true;
+ return true;
+ }
+ mInitialTouchY = y;
+ mInitialTouchX = x;
+ mTouchStartedInEmptyArea = !isInContentBounds(x, y);
+ mTouchSlopExceeded = mTouchSlopExceededBeforeDown;
+ mJustPeeked = false;
+ mMotionAborted = false;
+ mPanelClosedOnDown = isFullyCollapsed();
+ mCollapsedAndHeadsUpOnDown = false;
+ mHasLayoutedSinceDown = false;
+ mUpdateFlingOnLayout = false;
+ mTouchAboveFalsingThreshold = false;
+ addMovement(event);
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ final int upPointer = event.getPointerId(event.getActionIndex());
+ if (mTrackingPointer == upPointer) {
+ // gesture is ongoing, find a new pointer to track
+ final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+ mTrackingPointer = event.getPointerId(newIndex);
+ mInitialTouchX = event.getX(newIndex);
+ mInitialTouchY = event.getY(newIndex);
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+ mMotionAborted = true;
+ mVelocityTracker.clear();
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ final float h = y - mInitialTouchY;
+ addMovement(event);
+ if (scrolledToBottom || mTouchStartedInEmptyArea || mAnimatingOnDown) {
+ float hAbs = Math.abs(h);
+ if ((h < -mTouchSlop || (mAnimatingOnDown && hAbs > mTouchSlop))
+ && hAbs > Math.abs(x - mInitialTouchX)) {
+ cancelHeightAnimator();
+ startExpandMotion(x, y, true /* startTracking */, mExpandedHeight);
+ return true;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mVelocityTracker.clear();
+ break;
+ }
+ return false;
+ }
+
+ /**
+ * @return Whether a pair of coordinates are inside the visible view content bounds.
+ */
+ protected abstract boolean isInContentBounds(float x, float y);
+
+ protected void cancelHeightAnimator() {
+ if (mHeightAnimator != null) {
+ if (mHeightAnimator.isRunning()) {
+ mPanelUpdateWhenAnimatorEnds = false;
+ }
+ mHeightAnimator.cancel();
+ }
+ endClosing();
+ }
+
+ private void endClosing() {
+ if (mClosing) {
+ mClosing = false;
+ onClosingFinished();
+ }
+ }
+
+ protected boolean isScrolledToBottom() {
+ return true;
+ }
+
+ protected float getContentHeight() {
+ return mExpandedHeight;
}
@Override
- public void dispatchConfigurationChanged(Configuration newConfig) {
- super.dispatchConfigurationChanged(newConfig);
- mOnConfigurationChangedListener.onConfigurationChanged(newConfig);
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ loadDimens();
}
- interface OnConfigurationChangedListener {
- void onConfigurationChanged(Configuration newConfig);
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ loadDimens();
+ }
+
+ /**
+ * @param vel the current vertical velocity of the motion
+ * @param vectorVel the length of the vectorial velocity
+ * @return whether a fling should expands the panel; contracts otherwise
+ */
+ protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
+ if (mFalsingManager.isUnlockingDisabled()) {
+ return true;
+ }
+
+ if (isFalseTouch(x, y)) {
+ return true;
+ }
+ if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+ return shouldExpandWhenNotFlinging();
+ } else {
+ return vel > 0;
+ }
+ }
+
+ protected boolean shouldExpandWhenNotFlinging() {
+ return getExpandedFraction() > 0.5f;
+ }
+
+ /**
+ * @param x the final x-coordinate when the finger was lifted
+ * @param y the final y-coordinate when the finger was lifted
+ * @return whether this motion should be regarded as a false touch
+ */
+ private boolean isFalseTouch(float x, float y) {
+ if (!mStatusBar.isFalsingThresholdNeeded()) {
+ return false;
+ }
+ if (mFalsingManager.isClassifierEnabled()) {
+ return mFalsingManager.isFalseTouch();
+ }
+ if (!mTouchAboveFalsingThreshold) {
+ return true;
+ }
+ if (mUpwardsWhenTresholdReached) {
+ return false;
+ }
+ return !isDirectionUpwards(x, y);
+ }
+
+ protected void fling(float vel, boolean expand) {
+ fling(vel, expand, 1.0f /* collapseSpeedUpFactor */, false);
+ }
+
+ protected void fling(float vel, boolean expand, boolean expandBecauseOfFalsing) {
+ fling(vel, expand, 1.0f /* collapseSpeedUpFactor */, expandBecauseOfFalsing);
+ }
+
+ protected void fling(float vel, boolean expand, float collapseSpeedUpFactor,
+ boolean expandBecauseOfFalsing) {
+ cancelPeek();
+ float target = expand ? getMaxPanelHeight() : 0;
+ if (!expand) {
+ mClosing = true;
+ }
+ flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
+ }
+
+ protected void flingToHeight(float vel, boolean expand, float target,
+ float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
+ // Hack to make the expand transition look nice when clear all button is visible - we make
+ // the animation only to the last notification, and then jump to the maximum panel height so
+ // clear all just fades in and the decelerating motion is towards the last notification.
+ final boolean clearAllExpandHack = expand && fullyExpandedClearAllVisible()
+ && mExpandedHeight < getMaxPanelHeight() - getClearAllHeight()
+ && !isClearAllVisible();
+ if (clearAllExpandHack) {
+ target = getMaxPanelHeight() - getClearAllHeight();
+ }
+ if (target == mExpandedHeight || getOverExpansionAmount() > 0f && expand) {
+ notifyExpandingFinished();
+ return;
+ }
+ mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
+ ValueAnimator animator = createHeightAnimator(target);
+ if (expand) {
+ if (expandBecauseOfFalsing && vel < 0) {
+ vel = 0;
+ }
+ mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, getHeight());
+ if (vel == 0) {
+ animator.setDuration(350);
+ }
+ } else {
+ if (shouldUseDismissingAnimation()) {
+ if (vel == 0) {
+ animator.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
+ long duration = (long) (200 + mExpandedHeight / getHeight() * 100);
+ animator.setDuration(duration);
+ } else {
+ mFlingAnimationUtilsDismissing.apply(animator, mExpandedHeight, target, vel,
+ getHeight());
+ }
+ } else {
+ mFlingAnimationUtilsClosing
+ .apply(animator, mExpandedHeight, target, vel, getHeight());
+ }
+
+ // Make it shorter if we run a canned animation
+ if (vel == 0) {
+ animator.setDuration((long) (animator.getDuration() / collapseSpeedUpFactor));
+ }
+ if (mFixedDuration != NO_FIXED_DURATION) {
+ animator.setDuration(mFixedDuration);
+ }
+ }
+ animator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (clearAllExpandHack && !mCancelled) {
+ setExpandedHeightInternal(getMaxPanelHeight());
+ }
+ setAnimator(null);
+ if (!mCancelled) {
+ notifyExpandingFinished();
+ }
+ notifyBarPanelExpansionChanged();
+ }
+ });
+ setAnimator(animator);
+ animator.start();
+ }
+
+ protected abstract boolean shouldUseDismissingAnimation();
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mViewName = getResources().getResourceName(getId());
+ }
+
+ public String getName() {
+ return mViewName;
+ }
+
+ public void setExpandedHeight(float height) {
+ if (DEBUG) logf("setExpandedHeight(%.1f)", height);
+ setExpandedHeightInternal(height + getOverExpansionPixels());
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ mStatusBar.onPanelLaidOut();
+ requestPanelHeightUpdate();
+ mHasLayoutedSinceDown = true;
+ if (mUpdateFlingOnLayout) {
+ abortAnimations();
+ fling(mUpdateFlingVelocity, true /* expands */);
+ mUpdateFlingOnLayout = false;
+ }
+ }
+
+ protected void requestPanelHeightUpdate() {
+ float currentMaxPanelHeight = getMaxPanelHeight();
+
+ if (isFullyCollapsed()) {
+ return;
+ }
+
+ if (currentMaxPanelHeight == mExpandedHeight) {
+ return;
+ }
+
+ if (mPeekAnimator != null || mPeekTouching) {
+ return;
+ }
+
+ if (mTracking && !isTrackingBlocked()) {
+ return;
+ }
+
+ if (mHeightAnimator != null) {
+ mPanelUpdateWhenAnimatorEnds = true;
+ return;
+ }
+
+ setExpandedHeight(currentMaxPanelHeight);
+ }
+
+ public void setExpandedHeightInternal(float h) {
+ if (mExpandLatencyTracking && h != 0f) {
+ DejankUtils.postAfterTraversal(() -> LatencyTracker.getInstance(mContext).onActionEnd(
+ LatencyTracker.ACTION_EXPAND_PANEL));
+ mExpandLatencyTracking = false;
+ }
+ float fhWithoutOverExpansion = getMaxPanelHeight() - getOverExpansionAmount();
+ if (mHeightAnimator == null) {
+ float overExpansionPixels = Math.max(0, h - fhWithoutOverExpansion);
+ if (getOverExpansionPixels() != overExpansionPixels && mTracking) {
+ setOverExpansion(overExpansionPixels, true /* isPixels */);
+ }
+ mExpandedHeight = Math.min(h, fhWithoutOverExpansion) + getOverExpansionAmount();
+ } else {
+ mExpandedHeight = h;
+ if (mOverExpandedBeforeFling) {
+ setOverExpansion(Math.max(0, h - fhWithoutOverExpansion), false /* isPixels */);
+ }
+ }
+
+ // If we are closing the panel and we are almost there due to a slow decelerating
+ // interpolator, abort the animation.
+ if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) {
+ mExpandedHeight = 0f;
+ if (mHeightAnimator != null) {
+ mHeightAnimator.end();
+ }
+ }
+ mExpandedFraction = Math.min(1f,
+ fhWithoutOverExpansion == 0 ? 0 : mExpandedHeight / fhWithoutOverExpansion);
+ onHeightUpdated(mExpandedHeight);
+ notifyBarPanelExpansionChanged();
+ }
+
+ /**
+ * @return true if the panel tracking should be temporarily blocked; this is used when a
+ * conflicting gesture (opening QS) is happening
+ */
+ protected abstract boolean isTrackingBlocked();
+
+ protected abstract void setOverExpansion(float overExpansion, boolean isPixels);
+
+ protected abstract void onHeightUpdated(float expandedHeight);
+
+ protected abstract float getOverExpansionAmount();
+
+ protected abstract float getOverExpansionPixels();
+
+ /**
+ * This returns the maximum height of the panel. Children should override this if their
+ * desired height is not the full height.
+ *
+ * @return the default implementation simply returns the maximum height.
+ */
+ protected abstract int getMaxPanelHeight();
+
+ public void setExpandedFraction(float frac) {
+ setExpandedHeight(getMaxPanelHeight() * frac);
+ }
+
+ public float getExpandedHeight() {
+ return mExpandedHeight;
+ }
+
+ public float getExpandedFraction() {
+ return mExpandedFraction;
+ }
+
+ public boolean isFullyExpanded() {
+ return mExpandedHeight >= getMaxPanelHeight();
+ }
+
+ public boolean isFullyCollapsed() {
+ return mExpandedFraction <= 0.0f;
+ }
+
+ public boolean isCollapsing() {
+ return mClosing || mLaunchingNotification;
+ }
+
+ public boolean isTracking() {
+ return mTracking;
+ }
+
+ public void setBar(PanelBar panelBar) {
+ mBar = panelBar;
+ }
+
+ public void collapse(boolean delayed, float speedUpFactor) {
+ if (DEBUG) logf("collapse: " + this);
+ if (canPanelBeCollapsed()) {
+ cancelHeightAnimator();
+ notifyExpandingStarted();
+
+ // Set after notifyExpandingStarted, as notifyExpandingStarted resets the closing state.
+ mClosing = true;
+ if (delayed) {
+ mNextCollapseSpeedUpFactor = speedUpFactor;
+ postDelayed(mFlingCollapseRunnable, 120);
+ } else {
+ fling(0, false /* expand */, speedUpFactor, false /* expandBecauseOfFalsing */);
+ }
+ }
+ }
+
+ public boolean canPanelBeCollapsed() {
+ return !isFullyCollapsed() && !mTracking && !mClosing;
+ }
+
+ private final Runnable mFlingCollapseRunnable = new Runnable() {
+ @Override
+ public void run() {
+ fling(0, false /* expand */, mNextCollapseSpeedUpFactor,
+ false /* expandBecauseOfFalsing */);
+ }
+ };
+
+ public void cancelPeek() {
+ boolean cancelled = false;
+ if (mPeekAnimator != null) {
+ cancelled = true;
+ mPeekAnimator.cancel();
+ }
+
+ if (cancelled) {
+ // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also
+ // notify mBar that we might have closed ourselves.
+ notifyBarPanelExpansionChanged();
+ }
+ }
+
+ public void expand(final boolean animate) {
+ if (!isFullyCollapsed() && !isCollapsing()) {
+ return;
+ }
+
+ mInstantExpanding = true;
+ mAnimateAfterExpanding = animate;
+ mUpdateFlingOnLayout = false;
+ abortAnimations();
+ cancelPeek();
+ if (mTracking) {
+ onTrackingStopped(true /* expands */); // The panel is expanded after this call.
+ }
+ if (mExpanding) {
+ notifyExpandingFinished();
+ }
+ notifyBarPanelExpansionChanged();
+
+ // Wait for window manager to pickup the change, so we know the maximum height of the panel
+ // then.
+ getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (!mInstantExpanding) {
+ getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ return;
+ }
+ if (mStatusBar.getStatusBarWindow().getHeight()
+ != mStatusBar.getStatusBarHeight()) {
+ getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ if (mAnimateAfterExpanding) {
+ notifyExpandingStarted();
+ fling(0, true /* expand */);
+ } else {
+ setExpandedFraction(1f);
+ }
+ mInstantExpanding = false;
+ }
+ }
+ });
+
+ // Make sure a layout really happens.
+ requestLayout();
+ }
+
+ public void instantCollapse() {
+ abortAnimations();
+ setExpandedFraction(0f);
+ if (mExpanding) {
+ notifyExpandingFinished();
+ }
+ if (mInstantExpanding) {
+ mInstantExpanding = false;
+ notifyBarPanelExpansionChanged();
+ }
+ }
+
+ private void abortAnimations() {
+ cancelPeek();
+ cancelHeightAnimator();
+ removeCallbacks(mPostCollapseRunnable);
+ removeCallbacks(mFlingCollapseRunnable);
+ }
+
+ protected void onClosingFinished() {
+ mBar.onClosingFinished();
+ }
+
+
+ protected void startUnlockHintAnimation() {
+
+ // We don't need to hint the user if an animation is already running or the user is changing
+ // the expansion.
+ if (mHeightAnimator != null || mTracking) {
+ return;
+ }
+ cancelPeek();
+ notifyExpandingStarted();
+ startUnlockHintAnimationPhase1(() -> {
+ notifyExpandingFinished();
+ onUnlockHintFinished();
+ mHintAnimationRunning = false;
+ });
+ onUnlockHintStarted();
+ mHintAnimationRunning = true;
+ }
+
+ protected void onUnlockHintFinished() {
+ mStatusBar.onHintFinished();
+ }
+
+ protected void onUnlockHintStarted() {
+ mStatusBar.onUnlockHintStarted();
+ }
+
+ public boolean isUnlockHintRunning() {
+ return mHintAnimationRunning;
+ }
+
+ /**
+ * Phase 1: Move everything upwards.
+ */
+ private void startUnlockHintAnimationPhase1(final Runnable onAnimationFinished) {
+ float target = Math.max(0, getMaxPanelHeight() - mHintDistance);
+ ValueAnimator animator = createHeightAnimator(target);
+ animator.setDuration(250);
+ animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ animator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mCancelled) {
+ setAnimator(null);
+ onAnimationFinished.run();
+ } else {
+ startUnlockHintAnimationPhase2(onAnimationFinished);
+ }
+ }
+ });
+ animator.start();
+ setAnimator(animator);
+
+ View[] viewsToAnimate = {
+ mKeyguardBottomArea.getIndicationArea(),
+ mStatusBar.getAmbientIndicationContainer()};
+ for (View v : viewsToAnimate) {
+ if (v == null) {
+ continue;
+ }
+ v.animate()
+ .translationY(-mHintDistance)
+ .setDuration(250)
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .withEndAction(() -> v.animate()
+ .translationY(0)
+ .setDuration(450)
+ .setInterpolator(mBounceInterpolator)
+ .start())
+ .start();
+ }
+ }
+
+ private void setAnimator(ValueAnimator animator) {
+ mHeightAnimator = animator;
+ if (animator == null && mPanelUpdateWhenAnimatorEnds) {
+ mPanelUpdateWhenAnimatorEnds = false;
+ requestPanelHeightUpdate();
+ }
+ }
+
+ /**
+ * Phase 2: Bounce down.
+ */
+ private void startUnlockHintAnimationPhase2(final Runnable onAnimationFinished) {
+ ValueAnimator animator = createHeightAnimator(getMaxPanelHeight());
+ animator.setDuration(450);
+ animator.setInterpolator(mBounceInterpolator);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ setAnimator(null);
+ onAnimationFinished.run();
+ notifyBarPanelExpansionChanged();
+ }
+ });
+ animator.start();
+ setAnimator(animator);
+ }
+
+ private ValueAnimator createHeightAnimator(float targetHeight) {
+ ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight);
+ animator.addUpdateListener(
+ animation -> setExpandedHeightInternal((float) animation.getAnimatedValue()));
+ return animator;
+ }
+
+ protected void notifyBarPanelExpansionChanged() {
+ if (mBar != null) {
+ mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f
+ || mPeekAnimator != null || mInstantExpanding
+ || isPanelVisibleBecauseOfHeadsUp() || mTracking || mHeightAnimator != null);
+ }
+ for (int i = 0; i < mExpansionListeners.size(); i++) {
+ mExpansionListeners.get(i).onPanelExpansionChanged(mExpandedFraction, mTracking);
+ }
+ }
+
+ public void addExpansionListener(PanelExpansionListener panelExpansionListener) {
+ mExpansionListeners.add(panelExpansionListener);
+ }
+
+ protected abstract boolean isPanelVisibleBecauseOfHeadsUp();
+
+ /**
+ * Gets called when the user performs a click anywhere in the empty area of the panel.
+ *
+ * @return whether the panel will be expanded after the action performed by this method
+ */
+ protected boolean onEmptySpaceClick(float x) {
+ if (mHintAnimationRunning) {
+ return true;
+ }
+ return onMiddleClicked();
+ }
+
+ protected final Runnable mPostCollapseRunnable = new Runnable() {
+ @Override
+ public void run() {
+ collapse(false /* delayed */, 1.0f /* speedUpFactor */);
+ }
+ };
+
+ protected abstract boolean onMiddleClicked();
+
+ protected abstract boolean isDozing();
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
+ + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s touchDisabled=%s"
+ + "]",
+ this.getClass().getSimpleName(),
+ getExpandedHeight(),
+ getMaxPanelHeight(),
+ mClosing?"T":"f",
+ mTracking?"T":"f",
+ mJustPeeked?"T":"f",
+ mPeekAnimator, ((mPeekAnimator!=null && mPeekAnimator.isStarted())?" (started)":""),
+ mHeightAnimator, ((mHeightAnimator !=null && mHeightAnimator.isStarted())?" (started)":""),
+ mTouchDisabled?"T":"f"
+ ));
+ }
+
+ public abstract void resetViews(boolean animate);
+
+ protected abstract float getPeekHeight();
+ /**
+ * @return whether "Clear all" button will be visible when the panel is fully expanded
+ */
+ protected abstract boolean fullyExpandedClearAllVisible();
+
+ protected abstract boolean isClearAllVisible();
+
+ /**
+ * @return the height of the clear all button, in pixels
+ */
+ protected abstract int getClearAllHeight();
+
+ public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
+ mHeadsUpManager = headsUpManager;
+ }
+
+ public void setLaunchingNotification(boolean launchingNotification) {
+ mLaunchingNotification = launchingNotification;
+ }
+
+ public void collapseWithDuration(int animationDuration) {
+ mFixedDuration = animationDuration;
+ collapse(false /* delayed */, 1.0f /* speedUpFactor */);
+ mFixedDuration = NO_FIXED_DURATION;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
deleted file mode 100644
index 3d8e09a..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ /dev/null
@@ -1,1297 +0,0 @@
-/*
- * Copyright (C) 2019 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 android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.os.SystemClock;
-import android.os.VibrationEffect;
-import android.util.Log;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
-import android.view.animation.Interpolator;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.LatencyTracker;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.doze.DozeLog;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.statusbar.FlingAnimationUtils;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-public abstract class PanelViewController {
- public static final boolean DEBUG = PanelBar.DEBUG;
- public static final String TAG = PanelView.class.getSimpleName();
- private static final int INITIAL_OPENING_PEEK_DURATION = 200;
- private static final int PEEK_ANIMATION_DURATION = 360;
- private static final int NO_FIXED_DURATION = -1;
- protected long mDownTime;
- protected boolean mTouchSlopExceededBeforeDown;
- private float mMinExpandHeight;
- private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
- private boolean mPanelUpdateWhenAnimatorEnds;
- private boolean mVibrateOnOpening;
- protected boolean mLaunchingNotification;
- private int mFixedDuration = NO_FIXED_DURATION;
- protected ArrayList<PanelExpansionListener> mExpansionListeners = new ArrayList<>();
-
- private void logf(String fmt, Object... args) {
- Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
- }
-
- protected StatusBar mStatusBar;
- protected HeadsUpManagerPhone mHeadsUpManager;
-
- private float mPeekHeight;
- private float mHintDistance;
- private float mInitialOffsetOnTouch;
- private boolean mCollapsedAndHeadsUpOnDown;
- private float mExpandedFraction = 0;
- protected float mExpandedHeight = 0;
- private boolean mPanelClosedOnDown;
- private boolean mHasLayoutedSinceDown;
- private float mUpdateFlingVelocity;
- private boolean mUpdateFlingOnLayout;
- private boolean mPeekTouching;
- private boolean mJustPeeked;
- private boolean mClosing;
- protected boolean mTracking;
- private boolean mTouchSlopExceeded;
- private int mTrackingPointer;
- protected int mTouchSlop;
- protected boolean mHintAnimationRunning;
- private boolean mOverExpandedBeforeFling;
- private boolean mTouchAboveFalsingThreshold;
- private int mUnlockFalsingThreshold;
- private boolean mTouchStartedInEmptyArea;
- private boolean mMotionAborted;
- private boolean mUpwardsWhenThresholdReached;
- private boolean mAnimatingOnDown;
-
- private ValueAnimator mHeightAnimator;
- private ObjectAnimator mPeekAnimator;
- private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
- private FlingAnimationUtils mFlingAnimationUtils;
- private FlingAnimationUtils mFlingAnimationUtilsClosing;
- private FlingAnimationUtils mFlingAnimationUtilsDismissing;
- private final LatencyTracker mLatencyTracker;
- private final FalsingManager mFalsingManager;
- private final DozeLog mDozeLog;
- private final VibratorHelper mVibratorHelper;
-
- /**
- * Whether an instant expand request is currently pending and we are just waiting for layout.
- */
- private boolean mInstantExpanding;
- private boolean mAnimateAfterExpanding;
-
- PanelBar mBar;
-
- private String mViewName;
- private float mInitialTouchY;
- private float mInitialTouchX;
- private boolean mTouchDisabled;
-
- /**
- * Whether or not the PanelView can be expanded or collapsed with a drag.
- */
- private boolean mNotificationsDragEnabled;
-
- private Interpolator mBounceInterpolator;
- protected KeyguardBottomAreaView mKeyguardBottomArea;
-
- /**
- * Speed-up factor to be used when {@link #mFlingCollapseRunnable} runs the next time.
- */
- private float mNextCollapseSpeedUpFactor = 1.0f;
-
- protected boolean mExpanding;
- private boolean mGestureWaitForTouchSlop;
- private boolean mIgnoreXTouchSlop;
- private boolean mExpandLatencyTracking;
- private final PanelView mView;
- protected final Resources mResources;
- protected final KeyguardStateController mKeyguardStateController;
- protected final SysuiStatusBarStateController mStatusBarStateController;
-
- protected void onExpandingFinished() {
- mBar.onExpandingFinished();
- }
-
- protected void onExpandingStarted() {
- }
-
- private void notifyExpandingStarted() {
- if (!mExpanding) {
- mExpanding = true;
- onExpandingStarted();
- }
- }
-
- protected final void notifyExpandingFinished() {
- endClosing();
- if (mExpanding) {
- mExpanding = false;
- onExpandingFinished();
- }
- }
-
- private void runPeekAnimation(long duration, float peekHeight, boolean collapseWhenFinished) {
- mPeekHeight = peekHeight;
- if (DEBUG) logf("peek to height=%.1f", mPeekHeight);
- if (mHeightAnimator != null) {
- return;
- }
- if (mPeekAnimator != null) {
- mPeekAnimator.cancel();
- }
- mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight).setDuration(
- duration);
- mPeekAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- mPeekAnimator.addListener(new AnimatorListenerAdapter() {
- private boolean mCancelled;
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCancelled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- mPeekAnimator = null;
- if (!mCancelled && collapseWhenFinished) {
- mView.postOnAnimation(mPostCollapseRunnable);
- }
-
- }
- });
- notifyExpandingStarted();
- mPeekAnimator.start();
- mJustPeeked = true;
- }
-
- public PanelViewController(PanelView view,
- FalsingManager falsingManager, DozeLog dozeLog,
- KeyguardStateController keyguardStateController,
- SysuiStatusBarStateController statusBarStateController, VibratorHelper vibratorHelper,
- LatencyTracker latencyTracker, FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
- mView = view;
- mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
- @Override
- public void onViewAttachedToWindow(View v) {
- mViewName = mResources.getResourceName(mView.getId());
- }
-
- @Override
- public void onViewDetachedFromWindow(View v) {
- }
- });
-
- mView.addOnLayoutChangeListener(createLayoutChangeListener());
- mView.setOnTouchListener(createTouchHandler());
- mView.setOnConfigurationChangedListener(createOnConfigurationChangedListener());
-
- mResources = mView.getResources();
- mKeyguardStateController = keyguardStateController;
- mStatusBarStateController = statusBarStateController;
- mFlingAnimationUtils = flingAnimationUtilsBuilder
- .reset()
- .setMaxLengthSeconds(0.6f)
- .setSpeedUpFactor(0.6f)
- .build();
- mFlingAnimationUtilsClosing = flingAnimationUtilsBuilder
- .reset()
- .setMaxLengthSeconds(0.5f)
- .setSpeedUpFactor(0.6f)
- .build();
- mFlingAnimationUtilsDismissing = flingAnimationUtilsBuilder
- .reset()
- .setMaxLengthSeconds(0.5f)
- .setSpeedUpFactor(0.6f)
- .setX2(0.6f)
- .setY2(0.84f)
- .build();
- mLatencyTracker = latencyTracker;
- mBounceInterpolator = new BounceInterpolator();
- mFalsingManager = falsingManager;
- mDozeLog = dozeLog;
- mNotificationsDragEnabled = mResources.getBoolean(
- R.bool.config_enableNotificationShadeDrag);
- mVibratorHelper = vibratorHelper;
- mVibrateOnOpening = mResources.getBoolean(R.bool.config_vibrateOnIconAnimation);
- }
-
- protected void loadDimens() {
- final ViewConfiguration configuration = ViewConfiguration.get(mView.getContext());
- mTouchSlop = configuration.getScaledTouchSlop();
- mHintDistance = mResources.getDimension(R.dimen.hint_move_distance);
- mUnlockFalsingThreshold = mResources.getDimensionPixelSize(
- R.dimen.unlock_falsing_threshold);
- }
-
- private void addMovement(MotionEvent event) {
- // Add movement to velocity tracker using raw screen X and Y coordinates instead
- // of window coordinates because the window frame may be moving at the same time.
- float deltaX = event.getRawX() - event.getX();
- float deltaY = event.getRawY() - event.getY();
- event.offsetLocation(deltaX, deltaY);
- mVelocityTracker.addMovement(event);
- event.offsetLocation(-deltaX, -deltaY);
- }
-
- public void setTouchAndAnimationDisabled(boolean disabled) {
- mTouchDisabled = disabled;
- if (mTouchDisabled) {
- cancelHeightAnimator();
- if (mTracking) {
- onTrackingStopped(true /* expanded */);
- }
- notifyExpandingFinished();
- }
- }
-
- public void startExpandLatencyTracking() {
- if (mLatencyTracker.isEnabled()) {
- mLatencyTracker.onActionStart(LatencyTracker.ACTION_EXPAND_PANEL);
- mExpandLatencyTracking = true;
- }
- }
-
- private void startOpening(MotionEvent event) {
- runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(),
- false /* collapseWhenFinished */);
- notifyBarPanelExpansionChanged();
- maybeVibrateOnOpening();
-
- //TODO: keyguard opens QS a different way; log that too?
-
- // Log the position of the swipe that opened the panel
- float width = mStatusBar.getDisplayWidth();
- float height = mStatusBar.getDisplayHeight();
- int rot = mStatusBar.getRotation();
-
- mLockscreenGestureLogger.writeAtFractionalPosition(MetricsEvent.ACTION_PANEL_VIEW_EXPAND,
- (int) (event.getX() / width * 100), (int) (event.getY() / height * 100), rot);
- }
-
- protected void maybeVibrateOnOpening() {
- if (mVibrateOnOpening) {
- mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
- }
- }
-
- protected abstract float getOpeningHeight();
-
- /**
- * @return whether the swiping direction is upwards and above a 45 degree angle compared to the
- * horizontal direction
- */
- private boolean isDirectionUpwards(float x, float y) {
- float xDiff = x - mInitialTouchX;
- float yDiff = y - mInitialTouchY;
- if (yDiff >= 0) {
- return false;
- }
- return Math.abs(yDiff) >= Math.abs(xDiff);
- }
-
- protected void startExpandingFromPeek() {
- mStatusBar.handlePeekToExpandTransistion();
- }
-
- protected void startExpandMotion(float newX, float newY, boolean startTracking,
- float expandedHeight) {
- mInitialOffsetOnTouch = expandedHeight;
- mInitialTouchY = newY;
- mInitialTouchX = newX;
- if (startTracking) {
- mTouchSlopExceeded = true;
- setExpandedHeight(mInitialOffsetOnTouch);
- onTrackingStarted();
- }
- }
-
- private void endMotionEvent(MotionEvent event, float x, float y, boolean forceCancel) {
- mTrackingPointer = -1;
- if ((mTracking && mTouchSlopExceeded) || Math.abs(x - mInitialTouchX) > mTouchSlop
- || Math.abs(y - mInitialTouchY) > mTouchSlop
- || event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel) {
- mVelocityTracker.computeCurrentVelocity(1000);
- float vel = mVelocityTracker.getYVelocity();
- float vectorVel = (float) Math.hypot(
- mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
-
- boolean expand = flingExpands(vel, vectorVel, x, y)
- || event.getActionMasked() == MotionEvent.ACTION_CANCEL || forceCancel;
- mDozeLog.traceFling(expand, mTouchAboveFalsingThreshold,
- mStatusBar.isFalsingThresholdNeeded(), mStatusBar.isWakeUpComingFromTouch());
- // Log collapse gesture if on lock screen.
- if (!expand && mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
- float displayDensity = mStatusBar.getDisplayDensity();
- int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity);
- int velocityDp = (int) Math.abs(vel / displayDensity);
- mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp);
- }
- fling(vel, expand, isFalseTouch(x, y));
- onTrackingStopped(expand);
- mUpdateFlingOnLayout = expand && mPanelClosedOnDown && !mHasLayoutedSinceDown;
- if (mUpdateFlingOnLayout) {
- mUpdateFlingVelocity = vel;
- }
- } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking
- && !mStatusBar.isBouncerShowing()
- && !mKeyguardStateController.isKeyguardFadingAway()) {
- long timePassed = SystemClock.uptimeMillis() - mDownTime;
- if (timePassed < ViewConfiguration.getLongPressTimeout()) {
- // Lets show the user that he can actually expand the panel
- runPeekAnimation(
- PEEK_ANIMATION_DURATION, getPeekHeight(), true /* collapseWhenFinished */);
- } else {
- // We need to collapse the panel since we peeked to the small height.
- mView.postOnAnimation(mPostCollapseRunnable);
- }
- } else if (!mStatusBar.isBouncerShowing()) {
- boolean expands = onEmptySpaceClick(mInitialTouchX);
- onTrackingStopped(expands);
- }
-
- mVelocityTracker.clear();
- mPeekTouching = false;
- }
-
- protected float getCurrentExpandVelocity() {
- mVelocityTracker.computeCurrentVelocity(1000);
- return mVelocityTracker.getYVelocity();
- }
-
- private int getFalsingThreshold() {
- float factor = mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
- return (int) (mUnlockFalsingThreshold * factor);
- }
-
- protected abstract boolean shouldGestureWaitForTouchSlop();
-
- protected abstract boolean shouldGestureIgnoreXTouchSlop(float x, float y);
-
- protected void onTrackingStopped(boolean expand) {
- mTracking = false;
- mBar.onTrackingStopped(expand);
- notifyBarPanelExpansionChanged();
- }
-
- protected void onTrackingStarted() {
- endClosing();
- mTracking = true;
- mBar.onTrackingStarted();
- notifyExpandingStarted();
- notifyBarPanelExpansionChanged();
- }
-
- /**
- * @return Whether a pair of coordinates are inside the visible view content bounds.
- */
- protected abstract boolean isInContentBounds(float x, float y);
-
- protected void cancelHeightAnimator() {
- if (mHeightAnimator != null) {
- if (mHeightAnimator.isRunning()) {
- mPanelUpdateWhenAnimatorEnds = false;
- }
- mHeightAnimator.cancel();
- }
- endClosing();
- }
-
- private void endClosing() {
- if (mClosing) {
- mClosing = false;
- onClosingFinished();
- }
- }
-
- protected boolean isScrolledToBottom() {
- return true;
- }
-
- protected float getContentHeight() {
- return mExpandedHeight;
- }
-
- /**
- * @param vel the current vertical velocity of the motion
- * @param vectorVel the length of the vectorial velocity
- * @return whether a fling should expands the panel; contracts otherwise
- */
- protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
- if (mFalsingManager.isUnlockingDisabled()) {
- return true;
- }
-
- if (isFalseTouch(x, y)) {
- return true;
- }
- if (Math.abs(vectorVel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
- return shouldExpandWhenNotFlinging();
- } else {
- return vel > 0;
- }
- }
-
- protected boolean shouldExpandWhenNotFlinging() {
- return getExpandedFraction() > 0.5f;
- }
-
- /**
- * @param x the final x-coordinate when the finger was lifted
- * @param y the final y-coordinate when the finger was lifted
- * @return whether this motion should be regarded as a false touch
- */
- private boolean isFalseTouch(float x, float y) {
- if (!mStatusBar.isFalsingThresholdNeeded()) {
- return false;
- }
- if (mFalsingManager.isClassifierEnabled()) {
- return mFalsingManager.isFalseTouch();
- }
- if (!mTouchAboveFalsingThreshold) {
- return true;
- }
- if (mUpwardsWhenThresholdReached) {
- return false;
- }
- return !isDirectionUpwards(x, y);
- }
-
- protected void fling(float vel, boolean expand) {
- fling(vel, expand, 1.0f /* collapseSpeedUpFactor */, false);
- }
-
- protected void fling(float vel, boolean expand, boolean expandBecauseOfFalsing) {
- fling(vel, expand, 1.0f /* collapseSpeedUpFactor */, expandBecauseOfFalsing);
- }
-
- protected void fling(float vel, boolean expand, float collapseSpeedUpFactor,
- boolean expandBecauseOfFalsing) {
- cancelPeek();
- float target = expand ? getMaxPanelHeight() : 0;
- if (!expand) {
- mClosing = true;
- }
- flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
- }
-
- protected void flingToHeight(float vel, boolean expand, float target,
- float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) {
- // Hack to make the expand transition look nice when clear all button is visible - we make
- // the animation only to the last notification, and then jump to the maximum panel height so
- // clear all just fades in and the decelerating motion is towards the last notification.
- final boolean
- clearAllExpandHack =
- expand && fullyExpandedClearAllVisible()
- && mExpandedHeight < getMaxPanelHeight() - getClearAllHeight()
- && !isClearAllVisible();
- if (clearAllExpandHack) {
- target = getMaxPanelHeight() - getClearAllHeight();
- }
- if (target == mExpandedHeight || getOverExpansionAmount() > 0f && expand) {
- notifyExpandingFinished();
- return;
- }
- mOverExpandedBeforeFling = getOverExpansionAmount() > 0f;
- ValueAnimator animator = createHeightAnimator(target);
- if (expand) {
- if (expandBecauseOfFalsing && vel < 0) {
- vel = 0;
- }
- mFlingAnimationUtils.apply(animator, mExpandedHeight, target, vel, mView.getHeight());
- if (vel == 0) {
- animator.setDuration(350);
- }
- } else {
- if (shouldUseDismissingAnimation()) {
- if (vel == 0) {
- animator.setInterpolator(Interpolators.PANEL_CLOSE_ACCELERATED);
- long duration = (long) (200 + mExpandedHeight / mView.getHeight() * 100);
- animator.setDuration(duration);
- } else {
- mFlingAnimationUtilsDismissing.apply(animator, mExpandedHeight, target, vel,
- mView.getHeight());
- }
- } else {
- mFlingAnimationUtilsClosing.apply(
- animator, mExpandedHeight, target, vel, mView.getHeight());
- }
-
- // Make it shorter if we run a canned animation
- if (vel == 0) {
- animator.setDuration((long) (animator.getDuration() / collapseSpeedUpFactor));
- }
- if (mFixedDuration != NO_FIXED_DURATION) {
- animator.setDuration(mFixedDuration);
- }
- }
- animator.addListener(new AnimatorListenerAdapter() {
- private boolean mCancelled;
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCancelled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (clearAllExpandHack && !mCancelled) {
- setExpandedHeightInternal(getMaxPanelHeight());
- }
- setAnimator(null);
- if (!mCancelled) {
- notifyExpandingFinished();
- }
- notifyBarPanelExpansionChanged();
- }
- });
- setAnimator(animator);
- animator.start();
- }
-
- protected abstract boolean shouldUseDismissingAnimation();
-
- public String getName() {
- return mViewName;
- }
-
- public void setExpandedHeight(float height) {
- if (DEBUG) logf("setExpandedHeight(%.1f)", height);
- setExpandedHeightInternal(height + getOverExpansionPixels());
- }
-
- protected void requestPanelHeightUpdate() {
- float currentMaxPanelHeight = getMaxPanelHeight();
-
- if (isFullyCollapsed()) {
- return;
- }
-
- if (currentMaxPanelHeight == mExpandedHeight) {
- return;
- }
-
- if (mPeekAnimator != null || mPeekTouching) {
- return;
- }
-
- if (mTracking && !isTrackingBlocked()) {
- return;
- }
-
- if (mHeightAnimator != null) {
- mPanelUpdateWhenAnimatorEnds = true;
- return;
- }
-
- setExpandedHeight(currentMaxPanelHeight);
- }
-
- public void setExpandedHeightInternal(float h) {
- if (mExpandLatencyTracking && h != 0f) {
- DejankUtils.postAfterTraversal(
- () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL));
- mExpandLatencyTracking = false;
- }
- float fhWithoutOverExpansion = getMaxPanelHeight() - getOverExpansionAmount();
- if (mHeightAnimator == null) {
- float overExpansionPixels = Math.max(0, h - fhWithoutOverExpansion);
- if (getOverExpansionPixels() != overExpansionPixels && mTracking) {
- setOverExpansion(overExpansionPixels, true /* isPixels */);
- }
- mExpandedHeight = Math.min(h, fhWithoutOverExpansion) + getOverExpansionAmount();
- } else {
- mExpandedHeight = h;
- if (mOverExpandedBeforeFling) {
- setOverExpansion(Math.max(0, h - fhWithoutOverExpansion), false /* isPixels */);
- }
- }
-
- // If we are closing the panel and we are almost there due to a slow decelerating
- // interpolator, abort the animation.
- if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) {
- mExpandedHeight = 0f;
- if (mHeightAnimator != null) {
- mHeightAnimator.end();
- }
- }
- mExpandedFraction = Math.min(1f,
- fhWithoutOverExpansion == 0 ? 0 : mExpandedHeight / fhWithoutOverExpansion);
- onHeightUpdated(mExpandedHeight);
- notifyBarPanelExpansionChanged();
- }
-
- /**
- * @return true if the panel tracking should be temporarily blocked; this is used when a
- * conflicting gesture (opening QS) is happening
- */
- protected abstract boolean isTrackingBlocked();
-
- protected abstract void setOverExpansion(float overExpansion, boolean isPixels);
-
- protected abstract void onHeightUpdated(float expandedHeight);
-
- protected abstract float getOverExpansionAmount();
-
- protected abstract float getOverExpansionPixels();
-
- /**
- * This returns the maximum height of the panel. Children should override this if their
- * desired height is not the full height.
- *
- * @return the default implementation simply returns the maximum height.
- */
- protected abstract int getMaxPanelHeight();
-
- public void setExpandedFraction(float frac) {
- setExpandedHeight(getMaxPanelHeight() * frac);
- }
-
- public float getExpandedHeight() {
- return mExpandedHeight;
- }
-
- public float getExpandedFraction() {
- return mExpandedFraction;
- }
-
- public boolean isFullyExpanded() {
- return mExpandedHeight >= getMaxPanelHeight();
- }
-
- public boolean isFullyCollapsed() {
- return mExpandedFraction <= 0.0f;
- }
-
- public boolean isCollapsing() {
- return mClosing || mLaunchingNotification;
- }
-
- public boolean isTracking() {
- return mTracking;
- }
-
- public void setBar(PanelBar panelBar) {
- mBar = panelBar;
- }
-
- public void collapse(boolean delayed, float speedUpFactor) {
- if (DEBUG) logf("collapse: " + this);
- if (canPanelBeCollapsed()) {
- cancelHeightAnimator();
- notifyExpandingStarted();
-
- // Set after notifyExpandingStarted, as notifyExpandingStarted resets the closing state.
- mClosing = true;
- if (delayed) {
- mNextCollapseSpeedUpFactor = speedUpFactor;
- mView.postDelayed(mFlingCollapseRunnable, 120);
- } else {
- fling(0, false /* expand */, speedUpFactor, false /* expandBecauseOfFalsing */);
- }
- }
- }
-
- public boolean canPanelBeCollapsed() {
- return !isFullyCollapsed() && !mTracking && !mClosing;
- }
-
- private final Runnable mFlingCollapseRunnable = new Runnable() {
- @Override
- public void run() {
- fling(0, false /* expand */, mNextCollapseSpeedUpFactor,
- false /* expandBecauseOfFalsing */);
- }
- };
-
- public void cancelPeek() {
- boolean cancelled = false;
- if (mPeekAnimator != null) {
- cancelled = true;
- mPeekAnimator.cancel();
- }
-
- if (cancelled) {
- // When peeking, we already tell mBar that we expanded ourselves. Make sure that we also
- // notify mBar that we might have closed ourselves.
- notifyBarPanelExpansionChanged();
- }
- }
-
- public void expand(final boolean animate) {
- if (!isFullyCollapsed() && !isCollapsing()) {
- return;
- }
-
- mInstantExpanding = true;
- mAnimateAfterExpanding = animate;
- mUpdateFlingOnLayout = false;
- abortAnimations();
- cancelPeek();
- if (mTracking) {
- onTrackingStopped(true /* expands */); // The panel is expanded after this call.
- }
- if (mExpanding) {
- notifyExpandingFinished();
- }
- notifyBarPanelExpansionChanged();
-
- // Wait for window manager to pickup the change, so we know the maximum height of the panel
- // then.
- mView.getViewTreeObserver().addOnGlobalLayoutListener(
- new ViewTreeObserver.OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- if (!mInstantExpanding) {
- mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- return;
- }
- if (mStatusBar.getStatusBarWindow().getHeight()
- != mStatusBar.getStatusBarHeight()) {
- mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
- if (mAnimateAfterExpanding) {
- notifyExpandingStarted();
- fling(0, true /* expand */);
- } else {
- setExpandedFraction(1f);
- }
- mInstantExpanding = false;
- }
- }
- });
-
- // Make sure a layout really happens.
- mView.requestLayout();
- }
-
- public void instantCollapse() {
- abortAnimations();
- setExpandedFraction(0f);
- if (mExpanding) {
- notifyExpandingFinished();
- }
- if (mInstantExpanding) {
- mInstantExpanding = false;
- notifyBarPanelExpansionChanged();
- }
- }
-
- private void abortAnimations() {
- cancelPeek();
- cancelHeightAnimator();
- mView.removeCallbacks(mPostCollapseRunnable);
- mView.removeCallbacks(mFlingCollapseRunnable);
- }
-
- protected void onClosingFinished() {
- mBar.onClosingFinished();
- }
-
-
- protected void startUnlockHintAnimation() {
-
- // We don't need to hint the user if an animation is already running or the user is changing
- // the expansion.
- if (mHeightAnimator != null || mTracking) {
- return;
- }
- cancelPeek();
- notifyExpandingStarted();
- startUnlockHintAnimationPhase1(() -> {
- notifyExpandingFinished();
- onUnlockHintFinished();
- mHintAnimationRunning = false;
- });
- onUnlockHintStarted();
- mHintAnimationRunning = true;
- }
-
- protected void onUnlockHintFinished() {
- mStatusBar.onHintFinished();
- }
-
- protected void onUnlockHintStarted() {
- mStatusBar.onUnlockHintStarted();
- }
-
- public boolean isUnlockHintRunning() {
- return mHintAnimationRunning;
- }
-
- /**
- * Phase 1: Move everything upwards.
- */
- private void startUnlockHintAnimationPhase1(final Runnable onAnimationFinished) {
- float target = Math.max(0, getMaxPanelHeight() - mHintDistance);
- ValueAnimator animator = createHeightAnimator(target);
- animator.setDuration(250);
- animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- animator.addListener(new AnimatorListenerAdapter() {
- private boolean mCancelled;
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCancelled = true;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mCancelled) {
- setAnimator(null);
- onAnimationFinished.run();
- } else {
- startUnlockHintAnimationPhase2(onAnimationFinished);
- }
- }
- });
- animator.start();
- setAnimator(animator);
-
- View[] viewsToAnimate = {
- mKeyguardBottomArea.getIndicationArea(),
- mStatusBar.getAmbientIndicationContainer()};
- for (View v : viewsToAnimate) {
- if (v == null) {
- continue;
- }
- v.animate().translationY(-mHintDistance).setDuration(250).setInterpolator(
- Interpolators.FAST_OUT_SLOW_IN).withEndAction(() -> v.animate().translationY(
- 0).setDuration(450).setInterpolator(mBounceInterpolator).start()).start();
- }
- }
-
- private void setAnimator(ValueAnimator animator) {
- mHeightAnimator = animator;
- if (animator == null && mPanelUpdateWhenAnimatorEnds) {
- mPanelUpdateWhenAnimatorEnds = false;
- requestPanelHeightUpdate();
- }
- }
-
- /**
- * Phase 2: Bounce down.
- */
- private void startUnlockHintAnimationPhase2(final Runnable onAnimationFinished) {
- ValueAnimator animator = createHeightAnimator(getMaxPanelHeight());
- animator.setDuration(450);
- animator.setInterpolator(mBounceInterpolator);
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- setAnimator(null);
- onAnimationFinished.run();
- notifyBarPanelExpansionChanged();
- }
- });
- animator.start();
- setAnimator(animator);
- }
-
- private ValueAnimator createHeightAnimator(float targetHeight) {
- ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight);
- animator.addUpdateListener(
- animation -> setExpandedHeightInternal((float) animation.getAnimatedValue()));
- return animator;
- }
-
- protected void notifyBarPanelExpansionChanged() {
- if (mBar != null) {
- mBar.panelExpansionChanged(
- mExpandedFraction,
- mExpandedFraction > 0f || mPeekAnimator != null || mInstantExpanding
- || isPanelVisibleBecauseOfHeadsUp() || mTracking
- || mHeightAnimator != null);
- }
- for (int i = 0; i < mExpansionListeners.size(); i++) {
- mExpansionListeners.get(i).onPanelExpansionChanged(mExpandedFraction, mTracking);
- }
- }
-
- public void addExpansionListener(PanelExpansionListener panelExpansionListener) {
- mExpansionListeners.add(panelExpansionListener);
- }
-
- protected abstract boolean isPanelVisibleBecauseOfHeadsUp();
-
- /**
- * Gets called when the user performs a click anywhere in the empty area of the panel.
- *
- * @return whether the panel will be expanded after the action performed by this method
- */
- protected boolean onEmptySpaceClick(float x) {
- if (mHintAnimationRunning) {
- return true;
- }
- return onMiddleClicked();
- }
-
- protected final Runnable mPostCollapseRunnable = new Runnable() {
- @Override
- public void run() {
- collapse(false /* delayed */, 1.0f /* speedUpFactor */);
- }
- };
-
- protected abstract boolean onMiddleClicked();
-
- protected abstract boolean isDozing();
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
- + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s "
- + "touchDisabled=%s" + "]",
- this.getClass().getSimpleName(), getExpandedHeight(), getMaxPanelHeight(),
- mClosing ? "T" : "f", mTracking ? "T" : "f", mJustPeeked ? "T" : "f", mPeekAnimator,
- ((mPeekAnimator != null && mPeekAnimator.isStarted()) ? " (started)" : ""),
- mHeightAnimator,
- ((mHeightAnimator != null && mHeightAnimator.isStarted()) ? " (started)" : ""),
- mTouchDisabled ? "T" : "f"));
- }
-
- public abstract void resetViews(boolean animate);
-
- protected abstract float getPeekHeight();
-
- /**
- * @return whether "Clear all" button will be visible when the panel is fully expanded
- */
- protected abstract boolean fullyExpandedClearAllVisible();
-
- protected abstract boolean isClearAllVisible();
-
- /**
- * @return the height of the clear all button, in pixels
- */
- protected abstract int getClearAllHeight();
-
- public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
- mHeadsUpManager = headsUpManager;
- }
-
- public void setLaunchingNotification(boolean launchingNotification) {
- mLaunchingNotification = launchingNotification;
- }
-
- public void collapseWithDuration(int animationDuration) {
- mFixedDuration = animationDuration;
- collapse(false /* delayed */, 1.0f /* speedUpFactor */);
- mFixedDuration = NO_FIXED_DURATION;
- }
-
- public ViewGroup getView() {
- // TODO: remove this method, or at least reduce references to it.
- return mView;
- }
-
- public boolean isEnabled() {
- return mView.isEnabled();
- }
-
- public OnLayoutChangeListener createLayoutChangeListener() {
- return new OnLayoutChangeListener();
- }
-
- protected TouchHandler createTouchHandler() {
- return new TouchHandler();
- }
-
- protected OnConfigurationChangedListener createOnConfigurationChangedListener() {
- return new OnConfigurationChangedListener();
- }
-
- public class TouchHandler implements View.OnTouchListener {
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled || (mMotionAborted
- && event.getActionMasked() != MotionEvent.ACTION_DOWN)) {
- return false;
- }
-
- /*
- * If the user drags anywhere inside the panel we intercept it if the movement is
- * upwards. This allows closing the shade from anywhere inside the panel.
- *
- * We only do this if the current content is scrolled to the bottom,
- * i.e isScrolledToBottom() is true and therefore there is no conflicting scrolling
- * gesture
- * possible.
- */
- int pointerIndex = event.findPointerIndex(mTrackingPointer);
- if (pointerIndex < 0) {
- pointerIndex = 0;
- mTrackingPointer = event.getPointerId(pointerIndex);
- }
- final float x = event.getX(pointerIndex);
- final float y = event.getY(pointerIndex);
- boolean scrolledToBottom = isScrolledToBottom();
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mStatusBar.userActivity();
- mAnimatingOnDown = mHeightAnimator != null;
- mMinExpandHeight = 0.0f;
- mDownTime = SystemClock.uptimeMillis();
- if (mAnimatingOnDown && mClosing && !mHintAnimationRunning
- || mPeekAnimator != null) {
- cancelHeightAnimator();
- cancelPeek();
- mTouchSlopExceeded = true;
- return true;
- }
- mInitialTouchY = y;
- mInitialTouchX = x;
- mTouchStartedInEmptyArea = !isInContentBounds(x, y);
- mTouchSlopExceeded = mTouchSlopExceededBeforeDown;
- mJustPeeked = false;
- mMotionAborted = false;
- mPanelClosedOnDown = isFullyCollapsed();
- mCollapsedAndHeadsUpOnDown = false;
- mHasLayoutedSinceDown = false;
- mUpdateFlingOnLayout = false;
- mTouchAboveFalsingThreshold = false;
- addMovement(event);
- break;
- case MotionEvent.ACTION_POINTER_UP:
- final int upPointer = event.getPointerId(event.getActionIndex());
- if (mTrackingPointer == upPointer) {
- // gesture is ongoing, find a new pointer to track
- final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
- mTrackingPointer = event.getPointerId(newIndex);
- mInitialTouchX = event.getX(newIndex);
- mInitialTouchY = event.getY(newIndex);
- }
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
- mMotionAborted = true;
- mVelocityTracker.clear();
- }
- break;
- case MotionEvent.ACTION_MOVE:
- final float h = y - mInitialTouchY;
- addMovement(event);
- if (scrolledToBottom || mTouchStartedInEmptyArea || mAnimatingOnDown) {
- float hAbs = Math.abs(h);
- if ((h < -mTouchSlop || (mAnimatingOnDown && hAbs > mTouchSlop))
- && hAbs > Math.abs(x - mInitialTouchX)) {
- cancelHeightAnimator();
- startExpandMotion(x, y, true /* startTracking */, mExpandedHeight);
- return true;
- }
- }
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- mVelocityTracker.clear();
- break;
- }
- return false;
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (mInstantExpanding || (mTouchDisabled
- && event.getActionMasked() != MotionEvent.ACTION_CANCEL) || (mMotionAborted
- && event.getActionMasked() != MotionEvent.ACTION_DOWN)) {
- return false;
- }
-
- // If dragging should not expand the notifications shade, then return false.
- if (!mNotificationsDragEnabled) {
- if (mTracking) {
- // Turn off tracking if it's on or the shade can get stuck in the down position.
- onTrackingStopped(true /* expand */);
- }
- return false;
- }
-
- // On expanding, single mouse click expands the panel instead of dragging.
- if (isFullyCollapsed() && event.isFromSource(InputDevice.SOURCE_MOUSE)) {
- if (event.getAction() == MotionEvent.ACTION_UP) {
- expand(true);
- }
- return true;
- }
-
- /*
- * We capture touch events here and update the expand height here in case according to
- * the users fingers. This also handles multi-touch.
- *
- * If the user just clicks shortly, we show a quick peek of the shade.
- *
- * Flinging is also enabled in order to open or close the shade.
- */
-
- int pointerIndex = event.findPointerIndex(mTrackingPointer);
- if (pointerIndex < 0) {
- pointerIndex = 0;
- mTrackingPointer = event.getPointerId(pointerIndex);
- }
- final float x = event.getX(pointerIndex);
- final float y = event.getY(pointerIndex);
-
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
- mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop();
- mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
- }
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
- mJustPeeked = false;
- mMinExpandHeight = 0.0f;
- mPanelClosedOnDown = isFullyCollapsed();
- mHasLayoutedSinceDown = false;
- mUpdateFlingOnLayout = false;
- mMotionAborted = false;
- mPeekTouching = mPanelClosedOnDown;
- mDownTime = SystemClock.uptimeMillis();
- mTouchAboveFalsingThreshold = false;
- mCollapsedAndHeadsUpOnDown =
- isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
- addMovement(event);
- if (!mGestureWaitForTouchSlop || (mHeightAnimator != null
- && !mHintAnimationRunning) || mPeekAnimator != null) {
- mTouchSlopExceeded =
- (mHeightAnimator != null && !mHintAnimationRunning)
- || mPeekAnimator != null || mTouchSlopExceededBeforeDown;
- cancelHeightAnimator();
- cancelPeek();
- onTrackingStarted();
- }
- if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()
- && !mStatusBar.isBouncerShowing()) {
- startOpening(event);
- }
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- final int upPointer = event.getPointerId(event.getActionIndex());
- if (mTrackingPointer == upPointer) {
- // gesture is ongoing, find a new pointer to track
- final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
- final float newY = event.getY(newIndex);
- final float newX = event.getX(newIndex);
- mTrackingPointer = event.getPointerId(newIndex);
- startExpandMotion(newX, newY, true /* startTracking */, mExpandedHeight);
- }
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
- mMotionAborted = true;
- endMotionEvent(event, x, y, true /* forceCancel */);
- return false;
- }
- break;
- case MotionEvent.ACTION_MOVE:
- addMovement(event);
- float h = y - mInitialTouchY;
-
- // If the panel was collapsed when touching, we only need to check for the
- // y-component of the gesture, as we have no conflicting horizontal gesture.
- if (Math.abs(h) > mTouchSlop && (Math.abs(h) > Math.abs(x - mInitialTouchX)
- || mIgnoreXTouchSlop)) {
- mTouchSlopExceeded = true;
- if (mGestureWaitForTouchSlop && !mTracking && !mCollapsedAndHeadsUpOnDown) {
- if (!mJustPeeked && mInitialOffsetOnTouch != 0f) {
- startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
- h = 0;
- }
- cancelHeightAnimator();
- onTrackingStarted();
- }
- }
- float newHeight = Math.max(0, h + mInitialOffsetOnTouch);
- if (newHeight > mPeekHeight) {
- if (mPeekAnimator != null) {
- mPeekAnimator.cancel();
- }
- mJustPeeked = false;
- } else if (mPeekAnimator == null && mJustPeeked) {
- // The initial peek has finished, but we haven't dragged as far yet, lets
- // speed it up by starting at the peek height.
- mInitialOffsetOnTouch = mExpandedHeight;
- mInitialTouchY = y;
- mMinExpandHeight = mExpandedHeight;
- mJustPeeked = false;
- }
- newHeight = Math.max(newHeight, mMinExpandHeight);
- if (-h >= getFalsingThreshold()) {
- mTouchAboveFalsingThreshold = true;
- mUpwardsWhenThresholdReached = isDirectionUpwards(x, y);
- }
- if (!mJustPeeked && (!mGestureWaitForTouchSlop || mTracking)
- && !isTrackingBlocked()) {
- setExpandedHeightInternal(newHeight);
- }
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- addMovement(event);
- endMotionEvent(event, x, y, false /* forceCancel */);
- break;
- }
- return !mGestureWaitForTouchSlop || mTracking;
- }
- }
-
- public class OnLayoutChangeListener implements View.OnLayoutChangeListener {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
- int oldTop, int oldRight, int oldBottom) {
- mStatusBar.onPanelLaidOut();
- requestPanelHeightUpdate();
- mHasLayoutedSinceDown = true;
- if (mUpdateFlingOnLayout) {
- abortAnimations();
- fling(mUpdateFlingVelocity, true /* expands */);
- mUpdateFlingOnLayout = false;
- }
- }
- }
-
- public class OnConfigurationChangedListener implements
- PanelView.OnConfigurationChangedListener {
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- loadDimens();
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 45f3bf9..312ca26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -236,7 +236,7 @@
public void onPanelFullyOpened() {
super.onPanelFullyOpened();
if (!mIsFullyOpenedPanel) {
- mPanel.getView().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+ mPanel.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
mIsFullyOpenedPanel = true;
maybeShowDivider(!mBar.mPanelExpanded);
@@ -420,8 +420,7 @@
void maybeShowDivider(boolean showDivider) {
int state =
- showDivider && NotificationPanelViewController.isQsSplitEnabled()
- ? View.VISIBLE : View.GONE;
+ showDivider && NotificationPanelView.isQsSplitEnabled() ? View.VISIBLE : View.GONE;
mDividerContainer.setVisibility(state);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
index 866dc2d..57e7014 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeControllerImpl.java
@@ -79,7 +79,7 @@
public void instantExpandNotificationsPanel() {
// Make our window larger and the panel expanded.
getStatusBar().makeExpandedVisible(true /* force */);
- getNotificationPanelViewController().expand(false /* animate */);
+ getNotificationPanelView().expand(false /* animate */);
mCommandQueue.recomputeDisableFlags(mDisplayId, false /* animate */);
}
@@ -123,9 +123,8 @@
// TODO(b/62444020): remove when this bug is fixed
Log.v(TAG, "mStatusBarWindow: " + getStatusBarWindowView() + " canPanelBeCollapsed(): "
- + getNotificationPanelViewController().canPanelBeCollapsed());
- if (getStatusBarWindowView() != null
- && getNotificationPanelViewController().canPanelBeCollapsed()) {
+ + getNotificationPanelView().canPanelBeCollapsed());
+ if (getStatusBarWindowView() != null && getNotificationPanelView().canPanelBeCollapsed()) {
// release focus immediately to kick off focus change transition
mStatusBarWindowController.setStatusBarFocusable(false);
@@ -139,7 +138,7 @@
@Override
public boolean closeShadeIfOpen() {
- if (!getNotificationPanelViewController().isFullyCollapsed()) {
+ if (!getNotificationPanelView().isFullyCollapsed()) {
mCommandQueue.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
getStatusBar().visibilityChanged(false);
@@ -150,14 +149,15 @@
@Override
public void postOnShadeExpanded(Runnable executable) {
- getNotificationPanelViewController().addOnGlobalLayoutListener(
+ getNotificationPanelView().getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (getStatusBar().getStatusBarWindow().getHeight()
!= getStatusBar().getStatusBarHeight()) {
- getNotificationPanelViewController().removeOnGlobalLayoutListener(this);
- getNotificationPanelViewController().getView().post(executable);
+ getNotificationPanelView().getViewTreeObserver()
+ .removeOnGlobalLayoutListener(this);
+ getNotificationPanelView().post(executable);
}
}
});
@@ -187,7 +187,7 @@
@Override
public boolean collapsePanel() {
- if (!getNotificationPanelViewController().isFullyCollapsed()) {
+ if (!getNotificationPanelView().isFullyCollapsed()) {
// close the shade if it was open
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
true /* force */, true /* delayed */);
@@ -230,7 +230,7 @@
return (PhoneStatusBarView) getStatusBar().getStatusBarView();
}
- private NotificationPanelViewController getNotificationPanelViewController() {
- return getStatusBar().getPanelController();
+ private NotificationPanelView getNotificationPanelView() {
+ return getStatusBar().getPanel();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 09662e6..a6a734a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -131,6 +131,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.EventLogTags;
import com.android.systemui.InitController;
+import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -198,6 +199,7 @@
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationListController;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.ViewGroupFadeHelper;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
@@ -206,7 +208,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -391,8 +392,7 @@
private final DismissCallbackRegistry mDismissCallbackRegistry;
// expanded notifications
- // the sliding/resizing panel within the notification window
- protected NotificationPanelViewController mNotificationPanelViewController;
+ protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
// settings
private QSPanel mQSPanel;
@@ -461,8 +461,8 @@
mUserSetup = userSetup;
if (!mUserSetup && mStatusBarView != null)
animateCollapseQuickSettings();
- if (mNotificationPanelViewController != null) {
- mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
+ if (mNotificationPanel != null) {
+ mNotificationPanel.setUserSetupComplete(mUserSetup);
}
updateQsExpansionEnabled();
}
@@ -913,8 +913,9 @@
mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
mDozeServiceHost.initialize(this, mNotificationIconAreaController,
- mStatusBarKeyguardViewManager, mStatusBarWindowViewController,
- mNotificationPanelViewController, mAmbientIndicationContainer);
+ mStatusBarKeyguardViewManager,
+ mStatusBarWindowViewController,
+ mNotificationPanel, mAmbientIndicationContainer);
mConfigurationController.addCallback(this);
@@ -984,6 +985,8 @@
// 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 = mSuperStatusBarViewFactory.getNotificationPanelView();
+
mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
mNotificationLogger.setUpWithContainer(notifListContainer);
@@ -997,9 +1000,8 @@
mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController);
inflateShelf();
mNotificationIconAreaController.setupShelf(mNotificationShelf);
- mNotificationPanelViewController.setOnReinflationListener(
- mNotificationIconAreaController::initAodIcons);
- mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
+ mNotificationPanel.setOnReinflationListener(mNotificationIconAreaController::initAodIcons);
+ mNotificationPanel.addExpansionListener(mWakeUpCoordinator);
mDarkIconDispatcher.addDarkReceiver(mNotificationIconAreaController);
// Allow plugins to reference DarkIconDispatcher and StatusBarStateController
@@ -1013,7 +1015,7 @@
PhoneStatusBarView oldStatusBarView = mStatusBarView;
mStatusBarView = (PhoneStatusBarView) fragment.getView();
mStatusBarView.setBar(this);
- mStatusBarView.setPanel(mNotificationPanelViewController);
+ mStatusBarView.setPanel(mNotificationPanel);
mStatusBarView.setScrimController(mScrimController);
// CollapsedStatusBarFragment re-inflated PhoneStatusBarView and both of
@@ -1024,7 +1026,7 @@
// it needs to notify PhoneStatusBarView's new instance to update the correct
// status by calling mNotificationPanel.notifyBarPanelExpansionChanged().
if (mHeadsUpManager.hasPinnedHeadsUp()) {
- mNotificationPanelViewController.notifyBarPanelExpansionChanged();
+ mNotificationPanel.notifyBarPanelExpansionChanged();
}
mStatusBarView.setBouncerShowing(mBouncerShowing);
if (oldStatusBarView != null) {
@@ -1038,12 +1040,10 @@
// This view is being recreated, let's destroy the old one
mHeadsUpAppearanceController.destroy();
}
- // TODO: this should probably be scoped to the StatusBarComponent
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow,
mStatusBarStateController, mKeyguardBypassController,
- mKeyguardStateController, mWakeUpCoordinator, mCommandQueue,
- mNotificationPanelViewController);
+ mKeyguardStateController, mWakeUpCoordinator, mCommandQueue);
mHeadsUpAppearanceController.readFrom(oldController);
mLightsOutNotifController.setLightsOutNotifView(
@@ -1059,11 +1059,11 @@
mHeadsUpManager.setUp(mStatusBarWindow, mGroupManager, this, mVisualStabilityManager);
mConfigurationController.addCallback(mHeadsUpManager);
mHeadsUpManager.addListener(this);
- mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener());
+ mHeadsUpManager.addListener(mNotificationPanel);
mHeadsUpManager.addListener(mGroupManager);
mHeadsUpManager.addListener(mGroupAlertTransferHelper);
mHeadsUpManager.addListener(mVisualStabilityManager);
- mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
+ mNotificationPanel.setHeadsUpManager(mHeadsUpManager);
mGroupManager.setHeadsUpManager(mHeadsUpManager);
mGroupAlertTransferHelper.setHeadsUpManager(mHeadsUpManager);
mNotificationLogger.setHeadsUpManager(mHeadsUpManager);
@@ -1078,8 +1078,7 @@
SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
mStatusBarWindow.findViewById(R.id.lock_icon));
- mNotificationPanelViewController.setKeyguardIndicationController(
- mKeyguardIndicationController);
+ mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController);
mAmbientIndicationContainer = mStatusBarWindow.findViewById(
R.id.ambient_indication_container);
@@ -1114,19 +1113,19 @@
});
mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble);
- mNotificationPanelViewController.initDependencies(this, mGroupManager, mNotificationShelf,
- mNotificationIconAreaController, mScrimController);
+ mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
+ mHeadsUpManager, mNotificationIconAreaController, mScrimController);
BackDropView backdrop = mStatusBarWindow.findViewById(R.id.backdrop);
mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
- mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
+ mNotificationPanel.setUserSetupComplete(mUserSetup);
if (UserManager.get(mContext).isUserSwitcherEnabled()) {
createUserSwitcher();
}
- mNotificationPanelViewController.setLaunchAffordanceListener(
+ mNotificationPanel.setLaunchAffordanceListener(
mLockscreenLockIconController::onShowingLaunchAffordanceChanged);
// Set up the quick settings tile panel
@@ -1140,7 +1139,6 @@
.withDefault(this::createDefaultQSFragment)
.build());
mBrightnessMirrorController = new BrightnessMirrorController(mStatusBarWindow,
- mNotificationPanelViewController,
(visible) -> {
mBrightnessMirrorVisible = visible;
updateScrimController();
@@ -1234,7 +1232,7 @@
private void setUpPresenter() {
// Set up the initial notification state.
mActivityLaunchAnimator = new ActivityLaunchAnimator(
- mStatusBarWindowViewController, this, mNotificationPanelViewController,
+ mStatusBarWindowViewController, this, mNotificationPanel,
(NotificationListContainer) mStackScroller);
final NotificationRowBinderImpl rowBinder =
@@ -1246,7 +1244,7 @@
mNotificationLogger);
// TODO: inject this.
- mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController,
+ mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
mNotificationAlertingManager, rowBinder, mKeyguardStateController,
@@ -1267,7 +1265,6 @@
.setStatusBar(this)
.setActivityLaunchAnimator(mActivityLaunchAnimator)
.setNotificationPresenter(mPresenter)
- .setNotificationPanelViewController(mNotificationPanelViewController)
.build();
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
@@ -1377,7 +1374,7 @@
}
// We need the new R.id.keyguard_indication_area before recreating
// mKeyguardIndicationController
- mNotificationPanelViewController.onThemeChanged();
+ mNotificationPanel.onThemeChanged();
onThemeChanged();
}
@@ -1392,7 +1389,7 @@
mKeyguardUserSwitcher = new KeyguardUserSwitcher(mContext,
mStatusBarWindow.findViewById(R.id.keyguard_user_switcher),
mStatusBarWindow.findViewById(R.id.keyguard_header),
- mNotificationPanelViewController);
+ mNotificationPanel);
}
private void inflateStatusBarWindow() {
@@ -1401,17 +1398,16 @@
.statusBarWindowView(mStatusBarWindow).build();
mStatusBarWindowViewController = statusBarComponent.getStatusBarWindowViewController();
mStatusBarWindowViewController.setupExpandedStatusBar();
- mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController();
}
protected void startKeyguard() {
Trace.beginSection("StatusBar#startKeyguard");
mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
mStatusBarKeyguardViewManager.registerStatusBar(
- /* statusBar= */ this, getBouncerContainer(),
- mNotificationPanelViewController, mBiometricUnlockController,
- mDismissCallbackRegistry, mStatusBarWindow.findViewById(R.id.lock_icon_container),
- mStackScroller, mKeyguardBypassController, mFalsingManager);
+ /* statusBar= */ this, getBouncerContainer(), mNotificationPanel,
+ mBiometricUnlockController, mDismissCallbackRegistry,
+ mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
+ mKeyguardBypassController, mFalsingManager);
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -1488,7 +1484,7 @@
&& ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
&& !mDozing
&& !ONLY_CORE_APPS;
- mNotificationPanelViewController.setQsExpansionEnabled(expandEnabled);
+ mNotificationPanel.setQsExpansionEnabled(expandEnabled);
Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
}
@@ -1648,7 +1644,7 @@
public void setQsExpanded(boolean expanded) {
mStatusBarWindowController.setQsExpanded(expanded);
- mNotificationPanelViewController.setStatusAccessibilityImportance(expanded
+ mNotificationPanel.setStatusAccessibilityImportance(expanded
? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
: View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
if (getNavigationBarView() != null) {
@@ -1682,22 +1678,22 @@
if (inPinnedMode) {
mStatusBarWindowController.setHeadsUpShowing(true);
mStatusBarWindowController.setForceStatusBarVisible(true);
- if (mNotificationPanelViewController.isFullyCollapsed()) {
+ 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.
- mNotificationPanelViewController.getView().requestLayout();
+ mNotificationPanel.requestLayout();
mStatusBarWindowController.setForceWindowCollapsed(true);
- mNotificationPanelViewController.getView().post(() -> {
+ mNotificationPanel.post(() -> {
mStatusBarWindowController.setForceWindowCollapsed(false);
});
}
} else {
boolean bypassKeyguard = mKeyguardBypassController.getBypassEnabled()
&& mState == StatusBarState.KEYGUARD;
- if (!mNotificationPanelViewController.isFullyCollapsed()
- || mNotificationPanelViewController.isTracking() || bypassKeyguard) {
+ if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()
+ || bypassKeyguard) {
// We are currently tracking or is open and the shade doesn't need to be kept
// open artificially.
mStatusBarWindowController.setHeadsUpShowing(false);
@@ -1708,7 +1704,7 @@
// we need to keep the panel open artificially, let's wait until the animation
// is finished.
mHeadsUpManager.setHeadsUpGoingAway(true);
- mNotificationPanelViewController.runAfterAnimationFinished(() -> {
+ mNotificationPanel.runAfterAnimationFinished(() -> {
if (!mHeadsUpManager.hasPinnedHeadsUp()) {
mStatusBarWindowController.setHeadsUpShowing(false);
mHeadsUpManager.setHeadsUpGoingAway(false);
@@ -1761,7 +1757,7 @@
}
public boolean hideStatusBarIconsWhenExpanded() {
- return mNotificationPanelViewController.hideStatusBarIconsWhenExpanded();
+ return mNotificationPanel.hideStatusBarIconsWhenExpanded();
}
@Override
@@ -1951,21 +1947,19 @@
if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key) {
mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP);
- mNotificationPanelViewController.collapse(
- false /* delayed */, 1.0f /* speedUpFactor */);
+ mNotificationPanel.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
} else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key) {
mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN);
- if (mNotificationPanelViewController.isFullyCollapsed()) {
+ if (mNotificationPanel.isFullyCollapsed()) {
if (mVibrateOnOpening) {
mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK);
}
- mNotificationPanelViewController.expand(true /* animate */);
+ mNotificationPanel.expand(true /* animate */);
((NotificationListContainer) mStackScroller).setWillExpand(true);
mHeadsUpManager.unpinAll(true /* userUnpinned */);
mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1);
- } else if (!mNotificationPanelViewController.isInSettings()
- && !mNotificationPanelViewController.isExpanding()) {
- mNotificationPanelViewController.flingSettings(0 /* velocity */,
+ } else if (!mNotificationPanel.isInSettings() && !mNotificationPanel.isExpanding()){
+ mNotificationPanel.flingSettings(0 /* velocity */,
NotificationPanelView.FLING_EXPAND);
mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
}
@@ -2060,9 +2054,9 @@
}
if (start) {
- mNotificationPanelViewController.startWaitingForOpenPanelGesture();
+ mNotificationPanel.startWaitingForOpenPanelGesture();
} else {
- mNotificationPanelViewController.stopWaitingForOpenPanelGesture(velocity);
+ mNotificationPanel.stopWaitingForOpenPanelGesture(velocity);
}
}
@@ -2073,7 +2067,7 @@
return ;
}
- mNotificationPanelViewController.expandWithoutQs();
+ mNotificationPanel.expandWithoutQs();
if (false) postStartTracing();
}
@@ -2091,7 +2085,7 @@
if (subPanel != null) {
mQSPanel.openDetails(subPanel);
}
- mNotificationPanelViewController.expandWithQs();
+ mNotificationPanel.expandWithQs();
if (false) postStartTracing();
}
@@ -2114,7 +2108,7 @@
mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/,
1.0f /* speedUpFactor */);
- mNotificationPanelViewController.closeQs();
+ mNotificationPanel.closeQs();
mExpandedVisible = false;
visibilityChanged(false);
@@ -2135,8 +2129,7 @@
Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");
}
mCommandQueue.recomputeDisableFlags(
- mDisplayId,
- mNotificationPanelViewController.hideStatusBarIconsWhenExpanded() /* animate */);
+ mDisplayId, mNotificationPanel.hideStatusBarIconsWhenExpanded() /* animate */);
// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
// the bouncer appear animation.
@@ -2317,12 +2310,12 @@
batteryLevel, new WirelessChargingAnimation.Callback() {
@Override
public void onAnimationStarting() {
- CrossFadeHelper.fadeOut(mNotificationPanelViewController.getView(), 1);
+ CrossFadeHelper.fadeOut(mNotificationPanel, 1);
}
@Override
public void onAnimationEnded() {
- CrossFadeHelper.fadeIn(mNotificationPanelViewController.getView());
+ CrossFadeHelper.fadeIn(mNotificationPanel);
}
}, mDozing).show();
} else {
@@ -2351,7 +2344,7 @@
// Called by NavigationBarFragment
void setQsScrimEnabled(boolean scrimEnabled) {
- mNotificationPanelViewController.setQsScrimEnabled(scrimEnabled);
+ mNotificationPanel.setQsScrimEnabled(scrimEnabled);
}
void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState,
@@ -2443,12 +2436,11 @@
}
pw.println(" Panels: ");
- if (mNotificationPanelViewController != null) {
- pw.println(" mNotificationPanel="
- + mNotificationPanelViewController.getView() + " params="
- + mNotificationPanelViewController.getView().getLayoutParams().debug(""));
+ if (mNotificationPanel != null) {
+ pw.println(" mNotificationPanel=" +
+ mNotificationPanel + " params=" + mNotificationPanel.getLayoutParams().debug(""));
pw.print (" ");
- mNotificationPanelViewController.dump(fd, pw, args);
+ mNotificationPanel.dump(fd, pw, args);
}
pw.println(" mStackScroller: ");
if (mStackScroller instanceof Dumpable) {
@@ -2661,8 +2653,7 @@
// Do it after DismissAction has been processed to conserve the needed ordering.
mHandler.post(mShadeController::runPostCollapseRunnables);
}
- } else if (isInLaunchTransition()
- && mNotificationPanelViewController.isLaunchTransitionFinished()) {
+ } 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
@@ -2819,8 +2810,8 @@
if (mStatusBarView != null) {
mStatusBarView.updateResources();
}
- if (mNotificationPanelViewController != null) {
- mNotificationPanelViewController.updateResources();
+ if (mNotificationPanel != null) {
+ mNotificationPanel.updateResources();
}
if (mBrightnessMirrorController != null) {
mBrightnessMirrorController.updateResources();
@@ -3112,7 +3103,7 @@
public void showKeyguardImpl() {
mIsKeyguard = true;
if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
- mNotificationPanelViewController.cancelAnimation();
+ mNotificationPanel.animate().cancel();
onLaunchTransitionFadingEnded();
}
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
@@ -3139,8 +3130,8 @@
}
private void onLaunchTransitionFadingEnded() {
- mNotificationPanelViewController.setAlpha(1.0f);
- mNotificationPanelViewController.onAffordanceLaunchEnded();
+ mNotificationPanel.setAlpha(1.0f);
+ mNotificationPanel.onAffordanceLaunchEnded();
releaseGestureWakeLock();
runLaunchTransitionEndRunnable();
mKeyguardStateController.setLaunchTransitionFadingAway(false);
@@ -3148,8 +3139,8 @@
}
public boolean isInLaunchTransition() {
- return mNotificationPanelViewController.isLaunchTransitionRunning()
- || mNotificationPanelViewController.isLaunchTransitionFinished();
+ return mNotificationPanel.isLaunchTransitionRunning()
+ || mNotificationPanel.isLaunchTransitionFinished();
}
/**
@@ -3170,15 +3161,18 @@
}
updateScrimController();
mPresenter.updateMediaMetaData(false, true);
- mNotificationPanelViewController.setAlpha(1);
- mNotificationPanelViewController.fadeOut(
- FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
- this::onLaunchTransitionFadingEnded);
+ mNotificationPanel.setAlpha(1);
+ mNotificationPanel.animate()
+ .alpha(0)
+ .setStartDelay(FADE_KEYGUARD_START_DELAY)
+ .setDuration(FADE_KEYGUARD_DURATION)
+ .withLayer()
+ .withEndAction(this::onLaunchTransitionFadingEnded);
mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(),
LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
};
- if (mNotificationPanelViewController.isLaunchTransitionRunning()) {
- mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable);
+ if (mNotificationPanel.isLaunchTransitionRunning()) {
+ mNotificationPanel.setLaunchTransitionEndRunnable(hideRunnable);
} else {
hideRunnable.run();
}
@@ -3189,18 +3183,22 @@
* fading.
*/
public void fadeKeyguardWhilePulsing() {
- mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
- ()-> {
- hideKeyguard();
- mStatusBarKeyguardViewManager.onKeyguardFadedAway();
- }).start();
+ 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.
*/
public void animateKeyguardUnoccluding() {
- mNotificationPanelViewController.setExpandedFraction(0f);
+ mNotificationPanel.setExpandedFraction(0f);
animateExpandNotificationsPanel();
}
@@ -3216,9 +3214,9 @@
private void onLaunchTransitionTimeout() {
Log.w(TAG, "Launch transition: Timeout!");
- mNotificationPanelViewController.onAffordanceLaunchEnded();
+ mNotificationPanel.onAffordanceLaunchEnded();
releaseGestureWakeLock();
- mNotificationPanelViewController.resetViews(false /* animate */);
+ mNotificationPanel.resetViews(false /* animate */);
}
private void runLaunchTransitionEndRunnable() {
@@ -3251,7 +3249,7 @@
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
}
long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
- mNotificationPanelViewController.animateToFullShade(delay);
+ mNotificationPanel.animateToFullShade(delay);
if (mDraggedDownEntry != null) {
mDraggedDownEntry.setUserLocked(false);
mDraggedDownEntry = null;
@@ -3260,7 +3258,7 @@
// Disable layout transitions in navbar for this transition because the load is just
// too heavy for the CPU and GPU on any device.
mNavigationBarController.disableAnimationsDuringHide(mDisplayId, delay);
- } else if (!mNotificationPanelViewController.isCollapsing()) {
+ } else if (!mNotificationPanel.isCollapsing()) {
instantCollapseNotificationPanel();
}
@@ -3271,10 +3269,10 @@
}
mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
releaseGestureWakeLock();
- mNotificationPanelViewController.onAffordanceLaunchEnded();
- mNotificationPanelViewController.cancelAnimation();
- mNotificationPanelViewController.setAlpha(1f);
- mNotificationPanelViewController.resetViewGroupFade();
+ mNotificationPanel.onAffordanceLaunchEnded();
+ mNotificationPanel.animate().cancel();
+ mNotificationPanel.setAlpha(1f);
+ ViewGroupFadeHelper.reset(mNotificationPanel);
updateScrimController();
Trace.endSection();
return staying;
@@ -3349,7 +3347,7 @@
boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock)
|| (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard);
- mNotificationPanelViewController.setDozing(mDozing, animate, mWakeUpTouchLocation);
+ mNotificationPanel.setDozing(mDozing, animate, mWakeUpTouchLocation);
updateQsExpansionEnabled();
Trace.endSection();
}
@@ -3381,27 +3379,27 @@
public void endAffordanceLaunch() {
releaseGestureWakeLock();
- mNotificationPanelViewController.onAffordanceLaunchEnded();
+ mNotificationPanel.onAffordanceLaunchEnded();
}
public boolean onBackPressed() {
boolean isScrimmedBouncer = mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED;
if (mStatusBarKeyguardViewManager.onBackPressed(isScrimmedBouncer /* hideImmediately */)) {
if (!isScrimmedBouncer) {
- mNotificationPanelViewController.expandWithoutQs();
+ mNotificationPanel.expandWithoutQs();
}
return true;
}
- if (mNotificationPanelViewController.isQsExpanded()) {
- if (mNotificationPanelViewController.isQsDetailShowing()) {
- mNotificationPanelViewController.closeQsDetail();
+ if (mNotificationPanel.isQsExpanded()) {
+ if (mNotificationPanel.isQsDetailShowing()) {
+ mNotificationPanel.closeQsDetail();
} else {
- mNotificationPanelViewController.animateCloseQs(false /* animateAway */);
+ mNotificationPanel.animateCloseQs(false /* animateAway */);
}
return true;
}
if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) {
- if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+ if (mNotificationPanel.canPanelBeCollapsed()) {
mShadeController.animateCollapsePanels();
} else {
mBubbleController.performBackPressIfNeeded();
@@ -3431,7 +3429,7 @@
}
void instantCollapseNotificationPanel() {
- mNotificationPanelViewController.instantCollapse();
+ mNotificationPanel.instantCollapse();
mShadeController.runPostCollapseRunnables();
}
@@ -3498,7 +3496,7 @@
// Collapse the notification panel if open
boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
&& mDozeParameters.shouldControlScreenOff();
- mNotificationPanelViewController.resetViews(dozingAnimated);
+ mNotificationPanel.resetViews(dozingAnimated);
updateQsExpansionEnabled();
mKeyguardViewMediator.setDozing(mDozing);
@@ -3572,7 +3570,7 @@
* @return bottom area view
*/
public KeyguardBottomAreaView getKeyguardBottomAreaView() {
- return mNotificationPanelViewController.getKeyguardBottomAreaView();
+ return mNotificationPanel.getKeyguardBottomAreaView();
}
/**
@@ -3611,7 +3609,7 @@
mDraggedDownEntry = entry;
mPendingRemoteInputView = null;
} else {
- mNotificationPanelViewController.animateToFullShade(0 /* delay */);
+ mNotificationPanel.animateToFullShade(0 /* delay */);
mStatusBarStateController.setState(StatusBarState.SHADE_LOCKED);
}
}
@@ -3637,7 +3635,7 @@
* Collapses the notification shade if it is tracking or expanded.
*/
public void collapseShade() {
- if (mNotificationPanelViewController.isTracking()) {
+ if (mNotificationPanel.isTracking()) {
mStatusBarWindowViewController.cancelCurrentTouch();
}
if (mPanelExpanded && mState == StatusBarState.SHADE) {
@@ -3649,7 +3647,7 @@
final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
@Override
public void onFinishedGoingToSleep() {
- mNotificationPanelViewController.onAffordanceLaunchEnded();
+ mNotificationPanel.onAffordanceLaunchEnded();
releaseGestureWakeLock();
mLaunchCameraWhenFinishedWaking = false;
mDeviceInteractive = false;
@@ -3710,8 +3708,7 @@
mBypassHeadsUpNotifier.setFullyAwake(true);
mWakeUpCoordinator.setWakingUp(false);
if (mLaunchCameraWhenFinishedWaking) {
- mNotificationPanelViewController.launchCamera(
- false /* animate */, mLastCameraLaunchSource);
+ mNotificationPanel.launchCamera(false /* animate */, mLastCameraLaunchSource);
mLaunchCameraWhenFinishedWaking = false;
}
updateScrimController();
@@ -3728,7 +3725,7 @@
&& !mDozeParameters.shouldControlScreenOff();
boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
|| goingToSleepWithoutAnimation;
- mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled);
+ mNotificationPanel.setTouchAndAnimationDisabled(disabled);
mNotificationIconAreaController.setAnimationsEnabled(!disabled);
}
@@ -3736,7 +3733,7 @@
@Override
public void onScreenTurningOn() {
mFalsingManager.onScreenTurningOn();
- mNotificationPanelViewController.onScreenTurningOn();
+ mNotificationPanel.onScreenTurningOn();
}
@Override
@@ -3805,7 +3802,7 @@
mLaunchCameraOnFinishedGoingToSleep = true;
return;
}
- if (!mNotificationPanelViewController.canCameraGestureBeLaunched()) {
+ if (!mNotificationPanel.canCameraGestureBeLaunched()) {
if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Can't launch camera right now");
return;
}
@@ -3835,8 +3832,7 @@
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.reset(true /* hide */);
}
- mNotificationPanelViewController.launchCamera(
- mDeviceInteractive /* animate */, source);
+ mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
updateScrimController();
} else {
// We need to defer the camera launch until the screen comes on, since otherwise
@@ -3895,7 +3891,7 @@
!mBiometricUnlockController.isBiometricUnlock());
boolean launchingAffordanceWithPreview =
- mNotificationPanelViewController.isLaunchingAffordanceWithPreview();
+ mNotificationPanel.isLaunchingAffordanceWithPreview();
mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
if (mBouncerShowing) {
@@ -4244,7 +4240,7 @@
* When {@link KeyguardBouncer} starts to be dismissed, playing its animation.
*/
public void onBouncerPreHideAnimation() {
- mNotificationPanelViewController.onBouncerPreHideAnimation();
+ mNotificationPanel.onBouncerPreHideAnimation();
mLockscreenLockIconController.onBouncerPreHideAnimation();
}
@@ -4287,8 +4283,8 @@
mAssistManagerLazy.get().showDisclosure();
}
- public NotificationPanelViewController getPanelController() {
- return mNotificationPanelViewController;
+ public NotificationPanelView getPanel() {
+ return mNotificationPanel;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarComponent.java
similarity index 74%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarComponent.java
index 21d0bb8..f3c843c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarComponent.java
@@ -14,14 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.phone.dagger;
+package com.android.systemui.statusbar.phone;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
-import com.android.systemui.statusbar.phone.StatusBarWindowView;
-import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
-
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
@@ -33,8 +29,7 @@
/**
* Dagger subcomponent tied to the lifecycle of StatusBar views.
*/
-@Subcomponent(modules = {StatusBarViewModule.class})
-@StatusBarComponent.StatusBarScope
+@Subcomponent
public interface StatusBarComponent {
/**
* Builder for {@link StatusBarComponent}.
@@ -59,10 +54,4 @@
@StatusBarScope
StatusBarWindowViewController getStatusBarWindowViewController();
- /**
- * Creates a NotificationPanelViewController.
- */
- @StatusBarScope
- NotificationPanelViewController getNotificationPanelViewController();
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 407d256..f51174b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -133,7 +133,7 @@
protected LockPatternUtils mLockPatternUtils;
protected ViewMediatorCallback mViewMediatorCallback;
protected StatusBar mStatusBar;
- private NotificationPanelViewController mNotificationPanelViewController;
+ private NotificationPanelView mNotificationPanelView;
private BiometricUnlockController mBiometricUnlockController;
private ViewGroup mContainer;
@@ -224,7 +224,7 @@
public void registerStatusBar(StatusBar statusBar,
ViewGroup container,
- NotificationPanelViewController notificationPanelViewController,
+ NotificationPanelView notificationPanelView,
BiometricUnlockController biometricUnlockController,
DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
@@ -239,8 +239,8 @@
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
mExpansionCallback, mKeyguardStateController, falsingManager, bypassController);
- mNotificationPanelViewController = notificationPanelViewController;
- notificationPanelViewController.addExpansionListener(this);
+ mNotificationPanelView = notificationPanelView;
+ notificationPanelView.addExpansionListener(this);
mBypassController = bypassController;
mNotificationContainer = notificationContainer;
}
@@ -253,7 +253,7 @@
// • The user quickly taps on the display and we show "swipe up to unlock."
// • Keyguard will be dismissed by an action. a.k.a: FLAG_DISMISS_KEYGUARD_ACTIVITY
// • Full-screen user switcher is displayed.
- if (mNotificationPanelViewController.isUnlockHintRunning()) {
+ if (mNotificationPanelView.isUnlockHintRunning()) {
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
} else if (bouncerNeedsScrimming()) {
mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
@@ -284,7 +284,7 @@
return;
}
boolean keyguardWithoutQs = mStatusBarStateController.getState() == StatusBarState.KEYGUARD
- && !mNotificationPanelViewController.isQsExpanded();
+ && !mNotificationPanelView.isQsExpanded();
boolean lockVisible = (mBouncer.isShowing() || keyguardWithoutQs)
&& !mBouncer.isAnimatingAway() && !mKeyguardStateController.isKeyguardFadingAway();
@@ -555,7 +555,7 @@
} else if (finishRunnable != null) {
finishRunnable.run();
}
- mNotificationPanelViewController.blockExpansionForCurrentTouch();
+ mNotificationPanelView.blockExpansionForCurrentTouch();
updateLockIcon();
}
@@ -609,8 +609,7 @@
hideBouncer(true /* destroyView */);
if (wakeUnlockPulsing) {
if (needsFading) {
- ViewGroupFadeHelper.fadeOutAllChildrenExcept(
- mNotificationPanelViewController.getView(),
+ ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
mNotificationContainer,
fadeoutDuration,
() -> {
@@ -626,8 +625,7 @@
if (!staying) {
mStatusBarWindowController.setKeyguardFadingAway(true);
if (needsFading) {
- ViewGroupFadeHelper.fadeOutAllChildrenExcept(
- mNotificationPanelViewController.getView(),
+ ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
mNotificationContainer,
fadeoutDuration,
() -> {
@@ -686,7 +684,7 @@
public void onKeyguardFadedAway() {
mContainer.postDelayed(() -> mStatusBarWindowController.setKeyguardFadingAway(false),
100);
- ViewGroupFadeHelper.reset(mNotificationPanelViewController.getView());
+ ViewGroupFadeHelper.reset(mNotificationPanelView);
mStatusBar.finishKeyguardFadingAway();
mBiometricUnlockController.finishKeyguardFadingAway();
WindowManagerGlobal.getInstance().trimMemory(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
index 153ca22..12033de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -69,7 +69,6 @@
import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 0f3b5db..661a7b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -61,6 +61,7 @@
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -101,7 +102,7 @@
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private final MetricsLogger mMetricsLogger;
private final Context mContext;
- private final NotificationPanelViewController mNotificationPanel;
+ private final NotificationPanelView mNotificationPanel;
private final NotificationPresenter mPresenter;
private final LockPatternUtils mLockPatternUtils;
private final HeadsUpManagerPhone mHeadsUpManager;
@@ -120,7 +121,7 @@
private boolean mIsCollapsingToShowActivityOverLockscreen;
private StatusBarNotificationActivityStarter(Context context, CommandQueue commandQueue,
- Lazy<AssistManager> assistManagerLazy, NotificationPanelViewController panel,
+ Lazy<AssistManager> assistManagerLazy, NotificationPanelView panel,
NotificationPresenter presenter, NotificationEntryManager entryManager,
HeadsUpManagerPhone headsUpManager, ActivityStarter activityStarter,
ActivityLaunchAnimator activityLaunchAnimator, IStatusBarService statusBarService,
@@ -518,6 +519,7 @@
private final NotificationGroupManager mGroupManager;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final KeyguardStateController mKeyguardStateController;
+ private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private final MetricsLogger mMetricsLogger;
private final LockPatternUtils mLockPatternUtils;
private final Handler mMainThreadHandler;
@@ -525,8 +527,7 @@
private final Executor mUiBgExecutor;
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController;
- private NotificationPanelViewController mNotificationPanelViewController;
- private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private final ShadeController mShadeController;
private NotificationPresenter mNotificationPresenter;
private ActivityLaunchAnimator mActivityLaunchAnimator;
@@ -557,7 +558,8 @@
@UiBackground Executor uiBgExecutor,
ActivityIntentHelper activityIntentHelper,
BubbleController bubbleController,
- ShadeController shadeController) {
+ ShadeController shadeController,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
mContext = context;
mCommandQueue = commandQueue;
mAssistManagerLazy = assistManagerLazy;
@@ -583,6 +585,7 @@
mActivityIntentHelper = activityIntentHelper;
mBubbleController = bubbleController;
mShadeController = shadeController;
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
}
/** Sets the status bar to use as {@link StatusBar}. */
@@ -601,19 +604,10 @@
return this;
}
- /** Set the NotificationPanelViewController */
- public Builder setNotificationPanelViewController(
- NotificationPanelViewController notificationPanelViewController) {
- mNotificationPanelViewController = notificationPanelViewController;
- return this;
- }
-
-
-
public StatusBarNotificationActivityStarter build() {
return new StatusBarNotificationActivityStarter(mContext,
mCommandQueue, mAssistManagerLazy,
- mNotificationPanelViewController,
+ mSuperStatusBarViewFactory.getNotificationPanelView(),
mNotificationPresenter,
mEntryManager,
mHeadsUpManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 0fd0dab..beb4579 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -107,7 +107,7 @@
private final NotificationGutsManager mGutsManager =
Dependency.get(NotificationGutsManager.class);
- private final NotificationPanelViewController mNotificationPanel;
+ private final NotificationPanelView mNotificationPanel;
private final HeadsUpManagerPhone mHeadsUpManager;
private final AboveShelfObserver mAboveShelfObserver;
private final DozeScrimController mDozeScrimController;
@@ -132,7 +132,7 @@
private int mMaxKeyguardNotifications;
public StatusBarNotificationPresenter(Context context,
- NotificationPanelViewController panel,
+ NotificationPanelView panel,
HeadsUpManagerPhone headsUp,
StatusBarWindowView statusBarWindow,
ViewGroup stackScroller,
@@ -172,7 +172,7 @@
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
if (MULTIUSER_DEBUG) {
- mNotificationPanelDebugText = mNotificationPanel.getHeaderDebugInfo();
+ mNotificationPanelDebugText = mNotificationPanel.findViewById(R.id.header_debug_info);
mNotificationPanelDebugText.setVisibility(View.VISIBLE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1e3c5d6..6b51391 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -75,10 +75,6 @@
setMotionEventSplittingEnabled(false);
}
- public NotificationPanelView getNotificationPanelView() {
- return findViewById(R.id.notification_panel);
- }
-
@Override
public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
final Insets insets = windowInsets.getMaxInsets(WindowInsets.Type.systemBars());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index 4935f0e..eb86bcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -26,9 +26,11 @@
import android.view.GestureDetector;
import android.view.InputDevice;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.ExpandHelper;
@@ -91,7 +93,6 @@
private boolean mSingleTapEnabled;
private boolean mExpandingBelowNotch;
private final DockManager mDockManager;
- private final NotificationPanelViewController mNotificationPanelViewController;
@Inject
public StatusBarWindowViewController(
@@ -112,8 +113,7 @@
CommandQueue commandQueue,
ShadeController shadeController,
DockManager dockManager,
- StatusBarWindowView statusBarWindowView,
- NotificationPanelViewController notificationPanelViewController) {
+ StatusBarWindowView statusBarWindowView) {
mInjectionInflationController = injectionInflationController;
mCoordinator = coordinator;
mPulseExpansionHandler = pulseExpansionHandler;
@@ -132,7 +132,6 @@
mView = statusBarWindowView;
mShadeController = shadeController;
mDockManager = dockManager;
- mNotificationPanelViewController = notificationPanelViewController;
// This view is not part of the newly inflated expanded status bar.
mBrightnessMirror = mView.findViewById(R.id.brightness_mirror);
@@ -140,6 +139,39 @@
/** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */
public void setupExpandedStatusBar() {
+ // TODO: create controller for NotificationPanelView
+ NotificationPanelView notificationPanelView = new NotificationPanelView(
+ mView.getContext(),
+ null,
+ mInjectionInflationController,
+ mCoordinator,
+ mPulseExpansionHandler,
+ mDynamicPrivacyController,
+ mBypassController,
+ mFalsingManager,
+ mPluginManager,
+ mShadeController,
+ mNotificationLockscreenUserManager,
+ mNotificationEntryManager,
+ mKeyguardStateController,
+ mStatusBarStateController,
+ mDozeLog,
+ mDozeParameters,
+ mCommandQueue);
+ ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ notificationPanelView.setVisibility(View.INVISIBLE);
+ notificationPanelView.setId(R.id.notification_panel);
+ LayoutInflater li = mInjectionInflationController.injectable(
+ LayoutInflater.from(mView.getContext()));
+
+ li.inflate(R.layout.status_bar_expanded, notificationPanelView);
+ notificationPanelView.onChildrenAttached();
+
+ ViewStub statusBarExpanded = mView.findViewById(R.id.status_bar_expanded);
+ mView.addView(notificationPanelView, mView.indexOfChild(statusBarExpanded), lp);
+ mView.removeView(statusBarExpanded);
+
mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller);
TunerService.Tunable tunable = (key, newValue) -> {
@@ -201,8 +233,8 @@
if (!isCancel && mService.shouldIgnoreTouch()) {
return false;
}
- if (isDown && mNotificationPanelViewController.isFullyCollapsed()) {
- mNotificationPanelViewController.startExpandLatencyTracking();
+ if (isDown && notificationPanelView.isFullyCollapsed()) {
+ notificationPanelView.startExpandLatencyTracking();
}
if (isDown) {
setTouchActive(true);
@@ -255,7 +287,7 @@
return true;
}
boolean intercept = false;
- if (mNotificationPanelViewController.isFullyExpanded()
+ if (notificationPanelView.isFullyExpanded()
&& mDragDownHelper.isDragDownEnabled()
&& !mService.isBouncerShowing()
&& !mStatusBarStateController.isDozing()) {
@@ -271,7 +303,7 @@
MotionEvent cancellation = MotionEvent.obtain(ev);
cancellation.setAction(MotionEvent.ACTION_CANCEL);
mStackScrollLayout.onInterceptTouchEvent(cancellation);
- mNotificationPanelViewController.getView().onInterceptTouchEvent(cancellation);
+ notificationPanelView.onInterceptTouchEvent(cancellation);
cancellation.recycle();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
deleted file mode 100644
index 20bd51d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 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.dagger;
-
-import com.android.systemui.statusbar.phone.NotificationPanelView;
-import com.android.systemui.statusbar.phone.StatusBarWindowView;
-
-import dagger.Module;
-import dagger.Provides;
-
-@Module
-public abstract class StatusBarViewModule {
- /** */
- @Provides
- @StatusBarComponent.StatusBarScope
- public static NotificationPanelView getNotificationPanelView(
- StatusBarWindowView statusBarWindowView) {
- return statusBarWindowView.getNotificationPanelView();
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 625d884..88edf8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -24,7 +24,7 @@
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
import java.util.Objects;
@@ -38,17 +38,16 @@
private final StatusBarWindowView mStatusBarWindow;
private final Consumer<Boolean> mVisibilityCallback;
- private final NotificationPanelViewController mNotificationPanel;
+ private final NotificationPanelView mNotificationPanel;
private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
private final int[] mInt2Cache = new int[2];
private View mBrightnessMirror;
public BrightnessMirrorController(StatusBarWindowView statusBarWindow,
- NotificationPanelViewController notificationPanelViewController,
@NonNull Consumer<Boolean> visibilityCallback) {
mStatusBarWindow = statusBarWindow;
mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror);
- mNotificationPanel = notificationPanelViewController;
+ mNotificationPanel = statusBarWindow.findViewById(R.id.notification_panel);
mNotificationPanel.setPanelAlphaEndAction(() -> {
mBrightnessMirror.setVisibility(View.INVISIBLE);
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index d28a6699..4b283fed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -35,7 +35,7 @@
import com.android.systemui.R;
import com.android.systemui.qs.tiles.UserDetailItemView;
import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
/**
* Manages the user switcher on the Keyguard.
@@ -57,8 +57,7 @@
private boolean mAnimating;
public KeyguardUserSwitcher(Context context, ViewStub userSwitcher,
- KeyguardStatusBarView statusBarView,
- NotificationPanelViewController panelViewController) {
+ KeyguardStatusBarView statusBarView, NotificationPanelView panelView) {
boolean keyguardUserSwitcherEnabled =
context.getResources().getBoolean(R.bool.config_keyguardUserSwitcher) || ALWAYS_ON;
UserSwitcherController userSwitcherController = Dependency.get(UserSwitcherController.class);
@@ -68,7 +67,7 @@
reinflateViews();
mStatusBarView = statusBarView;
mStatusBarView.setKeyguardUserSwitcher(this);
- panelViewController.setKeyguardUserSwitcher(this);
+ panelView.setKeyguardUserSwitcher(this);
mAdapter = new Adapter(context, userSwitcherController, this);
mAdapter.registerDataSetObserver(mDataSetObserver);
mUserSwitcherController = userSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 56aae17..6976649 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -128,6 +129,11 @@
NotificationStackScrollLayout createNotificationStackScrollLayout();
/**
+ * Creates the NotificationPanelView.
+ */
+ NotificationPanelView createPanelView();
+
+ /**
* Creates the Shelf.
*/
NotificationShelf creatNotificationShelf();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
index a54f733..145a25c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
@@ -33,7 +33,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.NotificationPanelView;
import com.android.systemui.statusbar.phone.StatusBarWindowView;
import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
@@ -64,7 +64,7 @@
mLaunchAnimator = new ActivityLaunchAnimator(
mStatusBarWindowViewController,
mCallback,
- mock(NotificationPanelViewController.class),
+ mock(NotificationPanelView.class),
mNotificationContainer);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index ae87eef..8decae3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -64,8 +64,7 @@
mMockNotificiationAreaController = mock(NotificationIconAreaController.class);
mNotificationAreaInner = mock(View.class);
mCenteredNotificationAreaView = mock(View.class);
- when(statusBar.getPanelController()).thenReturn(
- mock(NotificationPanelViewController.class));
+ when(statusBar.getPanel()).thenReturn(mock(NotificationPanelView.class));
when(mNotificationAreaInner.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mMockNotificiationAreaController.getNotificationInnerAreaView()).thenReturn(
mNotificationAreaInner);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
index d31f175..46f6cfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -86,7 +86,7 @@
@Mock private NotificationIconAreaController mNotificationIconAreaController;
@Mock private StatusBarWindowViewController mStatusBarWindowViewController;
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- @Mock private NotificationPanelViewController mNotificationPanel;
+ @Mock private NotificationPanelView mNotificationPanel;
@Mock private View mAmbientIndicationContainer;
@Mock private BiometricUnlockController mBiometricUnlockController;
@Mock private LockscreenLockIconController mLockscreenLockIconController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 7448dbd..0260269 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -53,8 +53,7 @@
private final NotificationStackScrollLayout mStackScroller =
mock(NotificationStackScrollLayout.class);
- private final NotificationPanelViewController mPanelView =
- mock(NotificationPanelViewController.class);
+ private final NotificationPanelView mPanelView = mock(NotificationPanelView.class);
private final DarkIconDispatcher mDarkIconDispatcher = mock(DarkIconDispatcher.class);
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private ExpandableNotificationRow mFirst;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 1f37ad8..c165e56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -16,13 +16,9 @@
package com.android.systemui.statusbar.phone;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -30,44 +26,37 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.ActivityManager;
import android.app.StatusBarManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
import android.hardware.biometrics.BiometricSourceType;
-import android.os.PowerManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.util.LatencyTracker;
-import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -81,7 +70,6 @@
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
import java.util.function.Consumer;
@@ -97,6 +85,8 @@
@Mock
private NotificationStackScrollLayout mNotificationStackScrollLayout;
@Mock
+ private KeyguardStatusView mKeyguardStatusView;
+ @Mock
private KeyguardBottomAreaView mKeyguardBottomArea;
@Mock
private KeyguardBottomAreaView mQsFrame;
@@ -119,89 +109,27 @@
@Mock
private PanelBar mPanelBar;
@Mock
+ private KeyguardAffordanceHelper mAffordanceHelper;
+ @Mock
private KeyguardUpdateMonitor mUpdateMonitor;
@Mock
private FalsingManager mFalsingManager;
@Mock
private KeyguardBypassController mKeyguardBypassController;
- @Mock
- private DozeParameters mDozeParameters;
- @Mock
- private NotificationPanelView mView;
- @Mock
- private InjectionInflationController mInjectionInflationController;
- @Mock
- private DynamicPrivacyController mDynamicPrivacyController;
- @Mock
- private PluginManager mPluginManager;
- @Mock
- private ShadeController mShadeController;
- @Mock
- private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
- @Mock
- private NotificationEntryManager mNotificationEntryManager;
- @Mock
- private KeyguardStateController mKeyguardStateController;
- @Mock
- private DozeLog mDozeLog;
- @Mock
- private CommandQueue mCommandQueue;
- @Mock
- private VibratorHelper mVibratorHelper;
- @Mock
- private LatencyTracker mLatencyTracker;
- @Mock
- private PowerManager mPowerManager;
- @Mock
- private AccessibilityManager mAccessibilityManager;
- @Mock
- private MetricsLogger mMetricsLogger;
- @Mock
- private ActivityManager mActivityManager;
- @Mock
- private Resources mResources;
- @Mock
- private Configuration mConfiguration;
- private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
- @Mock
- private KeyguardClockSwitch mKeyguardClockSwitch;
- private PanelViewController.TouchHandler mTouchHandler;
- @Mock
- private ZenModeController mZenModeController;
- @Mock
- private ConfigurationController mConfigurationController;
- private FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
-
- private NotificationPanelViewController mNotificationPanelViewController;
+ @Mock private DozeParameters mDozeParameters;
+ private NotificationPanelView mNotificationPanelView;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- when(mHeadsUpCallback.getContext()).thenReturn(mContext);
- when(mView.getResources()).thenReturn(mResources);
- when(mResources.getConfiguration()).thenReturn(mConfiguration);
- mConfiguration.orientation = ORIENTATION_PORTRAIT;
- when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
- mDisplayMetrics.density = 100;
- when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
- when(mView.getContext()).thenReturn(getContext());
- when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
- when(mView.findViewById(R.id.notification_stack_scroller))
- .thenReturn(mNotificationStackScrollLayout);
when(mNotificationStackScrollLayout.getHeight()).thenReturn(1000);
when(mNotificationStackScrollLayout.getHeadsUpCallback()).thenReturn(mHeadsUpCallback);
- when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
- when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
- when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
- when(mView.findViewById(R.id.big_clock_container)).thenReturn(mBigClockContainer);
- when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
- mFlingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(mDisplayMetrics);
-
- doAnswer((Answer<Void>) invocation -> {
- mTouchHandler = invocation.getArgument(0);
- return null;
- }).when(mView).setOnTouchListener(any(PanelViewController.TouchHandler.class));
-
+ when(mHeadsUpCallback.getContext()).thenReturn(mContext);
+ mDependency.injectTestDependency(StatusBarStateController.class,
+ mStatusBarStateController);
+ mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mUpdateMonitor);
+ mDependency.injectMockDependency(ConfigurationController.class);
+ mDependency.injectMockDependency(ZenModeController.class);
NotificationWakeUpCoordinator coordinator =
new NotificationWakeUpCoordinator(
mock(HeadsUpManagerPhone.class),
@@ -215,26 +143,18 @@
mock(NotificationRoundnessManager.class),
mStatusBarStateController,
new FalsingManagerFake());
- mNotificationPanelViewController = new NotificationPanelViewController(mView,
- mInjectionInflationController,
- coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
- mFalsingManager, mPluginManager, mShadeController,
- mNotificationLockscreenUserManager, mNotificationEntryManager,
- mKeyguardStateController, mStatusBarStateController, mDozeLog,
- mDozeParameters, mCommandQueue, mVibratorHelper,
- mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
- mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
- mFlingAnimationUtilsBuilder);
- mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
- mNotificationShelf, mNotificationAreaController, mScrimController);
- mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
- mNotificationPanelViewController.setBar(mPanelBar);
+ mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler,
+ mKeyguardBypassController, mStatusBarStateController);
+ mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
+ mNotificationPanelView.setBar(mPanelBar);
+
+ when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
+ when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
}
@Test
public void testSetDozing_notifiesNsslAndStateController() {
- mNotificationPanelViewController.setDozing(true /* dozing */, true /* animate */,
- null /* touch */);
+ mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
InOrder inOrder = inOrder(mNotificationStackScrollLayout, mStatusBarStateController);
inOrder.verify(mNotificationStackScrollLayout).setDozing(eq(true), eq(true), eq(null));
inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true));
@@ -242,63 +162,103 @@
@Test
public void testSetExpandedHeight() {
- mNotificationPanelViewController.setExpandedHeight(200);
- assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
+ mNotificationPanelView.setExpandedHeight(200);
+ assertThat((int) mNotificationPanelView.getExpandedHeight()).isEqualTo(200);
}
@Test
public void testAffordanceLaunchingListener() {
Consumer<Boolean> listener = spy((showing) -> { });
- mNotificationPanelViewController.setExpandedFraction(1f);
- mNotificationPanelViewController.setLaunchAffordanceListener(listener);
- mNotificationPanelViewController.launchCamera(false /* animate */,
+ mNotificationPanelView.setExpandedFraction(1f);
+ mNotificationPanelView.setLaunchAffordanceListener(listener);
+ mNotificationPanelView.launchCamera(false /* animate */,
StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
verify(listener).accept(eq(true));
- mNotificationPanelViewController.onAffordanceLaunchEnded();
+ mNotificationPanelView.onAffordanceLaunchEnded();
verify(listener).accept(eq(false));
}
@Test
public void testOnTouchEvent_expansionCanBeBlocked() {
- onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+ mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
0 /* metaState */));
- onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+ mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 200f /* y */,
0 /* metaState */));
- assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
- assertThat(mNotificationPanelViewController.isTrackingBlocked()).isFalse();
+ assertThat((int) mNotificationPanelView.getExpandedHeight()).isEqualTo(200);
+ assertThat(mNotificationPanelView.isTrackingBlocked()).isFalse();
- mNotificationPanelViewController.blockExpansionForCurrentTouch();
- onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+ mNotificationPanelView.blockExpansionForCurrentTouch();
+ mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
0L /* eventTime */, MotionEvent.ACTION_MOVE, 0f /* x */, 300f /* y */,
0 /* metaState */));
// Expansion should not have changed because it was blocked
- assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
- assertThat(mNotificationPanelViewController.isTrackingBlocked()).isTrue();
+ assertThat((int) mNotificationPanelView.getExpandedHeight()).isEqualTo(200);
+ assertThat(mNotificationPanelView.isTrackingBlocked()).isTrue();
- onTouchEvent(MotionEvent.obtain(0L /* downTime */,
+ mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
0L /* eventTime */, MotionEvent.ACTION_UP, 0f /* x */, 300f /* y */,
0 /* metaState */));
- assertThat(mNotificationPanelViewController.isTrackingBlocked()).isFalse();
+ assertThat(mNotificationPanelView.isTrackingBlocked()).isFalse();
}
@Test
public void testKeyguardStatusBarVisibility_hiddenForBypass() {
when(mUpdateMonitor.shouldListenForFace()).thenReturn(true);
- mNotificationPanelViewController.mKeyguardUpdateCallback.onBiometricRunningStateChanged(
- true, BiometricSourceType.FACE);
+ mNotificationPanelView.mKeyguardUpdateCallback.onBiometricRunningStateChanged(true,
+ BiometricSourceType.FACE);
verify(mKeyguardStatusBar, never()).setVisibility(View.VISIBLE);
when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
- mNotificationPanelViewController.mKeyguardUpdateCallback.onFinishedGoingToSleep(0);
- mNotificationPanelViewController.mKeyguardUpdateCallback.onBiometricRunningStateChanged(
- true, BiometricSourceType.FACE);
+ mNotificationPanelView.mKeyguardUpdateCallback.onFinishedGoingToSleep(0);
+ mNotificationPanelView.mKeyguardUpdateCallback.onBiometricRunningStateChanged(true,
+ BiometricSourceType.FACE);
verify(mKeyguardStatusBar, never()).setVisibility(View.VISIBLE);
}
- private void onTouchEvent(MotionEvent ev) {
- mTouchHandler.onTouch(mView, ev);
+ private class TestableNotificationPanelView extends NotificationPanelView {
+ TestableNotificationPanelView(NotificationWakeUpCoordinator coordinator,
+ PulseExpansionHandler expansionHandler,
+ KeyguardBypassController bypassController,
+ SysuiStatusBarStateController statusBarStateController) {
+ super(
+ NotificationPanelViewTest.this.mContext,
+ null,
+ new InjectionInflationController(
+ SystemUIFactory.getInstance().getRootComponent()),
+ coordinator,
+ expansionHandler,
+ mock(DynamicPrivacyController.class),
+ bypassController,
+ mFalsingManager,
+ mock(PluginManager.class),
+ mock(ShadeController.class),
+ mock(NotificationLockscreenUserManager.class),
+ new NotificationEntryManager(
+ mock(NotifLog.class),
+ mock(NotificationGroupManager.class),
+ mock(NotificationRankingManager.class),
+ mock(NotificationEntryManager.KeyguardEnvironment.class)),
+ mock(KeyguardStateController.class),
+ statusBarStateController,
+ mock(DozeLog.class),
+ mDozeParameters,
+ new CommandQueue(NotificationPanelViewTest.this.mContext));
+ mNotificationStackScroller = mNotificationStackScrollLayout;
+ mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
+ mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
+ mKeyguardBottomArea = NotificationPanelViewTest.this.mKeyguardBottomArea;
+ mBigClockContainer = NotificationPanelViewTest.this.mBigClockContainer;
+ mQsFrame = NotificationPanelViewTest.this.mQsFrame;
+ mAffordanceHelper = NotificationPanelViewTest.this.mAffordanceHelper;
+ initDependencies(NotificationPanelViewTest.this.mStatusBar,
+ NotificationPanelViewTest.this.mGroupManager,
+ NotificationPanelViewTest.this.mNotificationShelf,
+ NotificationPanelViewTest.this.mHeadsUpManager,
+ NotificationPanelViewTest.this.mNotificationAreaController,
+ NotificationPanelViewTest.this.mScrimController);
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 5b5eaad..b27e84a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -74,7 +74,7 @@
@Mock
private ViewGroup mContainer;
@Mock
- private NotificationPanelViewController mNotificationPanelView;
+ private NotificationPanelView mNotificationPanelView;
@Mock
private BiometricUnlockController mBiometrucUnlockController;
@Mock
@@ -281,12 +281,12 @@
@Override
public void registerStatusBar(StatusBar statusBar, ViewGroup container,
- NotificationPanelViewController notificationPanelViewController,
+ NotificationPanelView notificationPanelView,
BiometricUnlockController fingerprintUnlockController,
DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
KeyguardBypassController bypassController, FalsingManager falsingManager) {
- super.registerStatusBar(statusBar, container, notificationPanelViewController,
+ super.registerStatusBar(statusBar, container, notificationPanelView,
fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer,
notificationContainer, bypassController, falsingManager);
mBouncer = StatusBarKeyguardViewManagerTest.this.mBouncer;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index fea4b8b..86b2a44 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -64,6 +64,7 @@
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -123,6 +124,10 @@
private Intent mContentIntentInner;
@Mock
private NotificationActivityStarter mNotificationActivityStarter;
+ @Mock
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ @Mock
+ private NotificationPanelView mNotificationPanelView;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private NotificationTestHelper mNotificationTestHelper;
@@ -162,6 +167,8 @@
mActiveNotifications.add(mBubbleNotificationRow.getEntry());
when(mEntryManager.getVisibleNotifications()).thenReturn(mActiveNotifications);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
+ when(mSuperStatusBarViewFactory.getNotificationPanelView())
+ .thenReturn(mNotificationPanelView);
mNotificationActivityStarter = (new StatusBarNotificationActivityStarter.Builder(
getContext(), mock(CommandQueue.class), () -> mAssistManager,
@@ -175,9 +182,9 @@
mKeyguardStateController,
mock(NotificationInterruptionStateProvider.class), mock(MetricsLogger.class),
mock(LockPatternUtils.class), mHandler, mHandler, mUiBgExecutor,
- mActivityIntentHelper, mBubbleController, mShadeController))
+ mActivityIntentHelper, mBubbleController, mShadeController,
+ mSuperStatusBarViewFactory))
.setStatusBar(mStatusBar)
- .setNotificationPanelViewController(mock(NotificationPanelViewController.class))
.setNotificationPresenter(mock(NotificationPresenter.class))
.setActivityLaunchAnimator(mock(ActivityLaunchAnimator.class))
.build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 5ac7bfb..1296a97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -108,7 +108,7 @@
StatusBarWindowView statusBarWindowView = mock(StatusBarWindowView.class);
when(statusBarWindowView.getResources()).thenReturn(mContext.getResources());
mStatusBarNotificationPresenter = new StatusBarNotificationPresenter(mContext,
- mock(NotificationPanelViewController.class), mock(HeadsUpManagerPhone.class),
+ mock(NotificationPanelView.class), mock(HeadsUpManagerPhone.class),
statusBarWindowView, mock(NotificationListContainerViewGroup.class),
mock(DozeScrimController.class), mock(ScrimController.class),
mock(ActivityLaunchAnimator.class), mock(DynamicPrivacyController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 7e485f4..1cdba47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -124,7 +124,6 @@
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -173,7 +172,6 @@
@Mock private KeyguardIndicationController mKeyguardIndicationController;
@Mock private NotificationStackScrollLayout mStackScroller;
@Mock private HeadsUpManagerPhone mHeadsUpManager;
- @Mock private NotificationPanelViewController mNotificationPanelViewController;
@Mock private NotificationPanelView mNotificationPanelView;
@Mock private IStatusBarService mBarService;
@Mock private IDreamManager mDreamManager;
@@ -287,7 +285,6 @@
mContext.setTheme(R.style.Theme_SystemUI_Light);
when(mStackScroller.generateLayoutParams(any())).thenReturn(new LayoutParams(0, 0));
- when(mNotificationPanelViewController.getView()).thenReturn(mNotificationPanelView);
when(mNotificationPanelView.getLayoutParams()).thenReturn(new LayoutParams(0, 0));
when(powerManagerService.isInteractive()).thenReturn(true);
when(mStackScroller.getActivatedChild()).thenReturn(null);
@@ -419,7 +416,7 @@
mLockIconContainer);
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
- any(NotificationPanelViewController.class), any(BiometricUnlockController.class),
+ any(NotificationPanelView.class), any(BiometricUnlockController.class),
any(ViewGroup.class), any(ViewGroup.class), any(KeyguardBypassController.class)))
.thenReturn(mStatusBarKeyguardViewManager);
@@ -429,7 +426,7 @@
// TODO: we should be able to call mStatusBar.start() and have all the below values
// initialized automatically.
mStatusBar.mStatusBarWindow = mStatusBarWindowView;
- mStatusBar.mNotificationPanelViewController = mNotificationPanelViewController;
+ mStatusBar.mNotificationPanel = mNotificationPanelView;
mStatusBar.mDozeScrimController = mDozeScrimController;
mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController;
mStatusBar.mPresenter = mNotificationPresenter;
@@ -734,20 +731,20 @@
when(mCommandQueue.panelsEnabled()).thenReturn(false);
mStatusBar.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false);
- verify(mNotificationPanelViewController).setQsExpansionEnabled(false);
+ verify(mNotificationPanelView).setQsExpansionEnabled(false);
mStatusBar.animateExpandNotificationsPanel();
- verify(mNotificationPanelViewController, never()).expand(anyBoolean());
+ verify(mNotificationPanelView, never()).expand(anyBoolean());
mStatusBar.animateExpandSettingsPanel(null);
- verify(mNotificationPanelViewController, never()).expand(anyBoolean());
+ verify(mNotificationPanelView, never()).expand(anyBoolean());
when(mCommandQueue.panelsEnabled()).thenReturn(true);
mStatusBar.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NONE, false);
- verify(mNotificationPanelViewController).setQsExpansionEnabled(true);
+ verify(mNotificationPanelView).setQsExpansionEnabled(true);
mStatusBar.animateExpandNotificationsPanel();
- verify(mNotificationPanelViewController).expandWithoutQs();
+ verify(mNotificationPanelView).expandWithoutQs();
mStatusBar.animateExpandSettingsPanel(null);
- verify(mNotificationPanelViewController).expandWithQs();
+ verify(mNotificationPanelView).expandWithQs();
}
@Test
@@ -837,12 +834,12 @@
when(mDozeServiceHost.getDozingRequested()).thenReturn(true);
mStatusBar.updateIsKeyguard();
// TODO: mNotificationPanelView.expand(false) gets called twice. Should be once.
- verify(mNotificationPanelViewController, times(2)).expand(eq(false));
- clearInvocations(mNotificationPanelViewController);
+ verify(mNotificationPanelView, times(2)).expand(eq(false));
+ clearInvocations(mNotificationPanelView);
mStatusBar.mWakefulnessObserver.onStartedWakingUp();
verify(mDozeServiceHost).stopDozing();
- verify(mNotificationPanelViewController).expand(eq(false));
+ verify(mNotificationPanelView).expand(eq(false));
}
@Test
@@ -851,11 +848,11 @@
when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
when(mDozeServiceHost.getDozingRequested()).thenReturn(true);
mStatusBar.updateIsKeyguard();
- clearInvocations(mNotificationPanelViewController);
+ clearInvocations(mNotificationPanelView);
mStatusBar.setBouncerShowing(true);
mStatusBar.mWakefulnessObserver.onStartedWakingUp();
- verify(mNotificationPanelViewController, never()).expand(anyBoolean());
+ verify(mNotificationPanelView, never()).expand(anyBoolean());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index f9848f3..9f899ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,7 +26,6 @@
import androidx.test.filters.SmallTest;
-import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
@@ -42,7 +40,6 @@
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.InjectionInflationController;
@@ -77,16 +74,12 @@
@Mock private DozeLog mDozeLog;
@Mock private DozeParameters mDozeParameters;
@Mock private DockManager mDockManager;
- @Mock private NotificationPanelViewController mNotificationPanelViewController;
- @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mView = spy(new StatusBarWindowView(getContext(), null));
- when(mView.findViewById(R.id.notification_stack_scroller))
- .thenReturn(mNotificationStackScrollLayout);
+ mView = new StatusBarWindowView(getContext(), null);
when(mStatusBarStateController.isDozing()).thenReturn(false);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
@@ -111,8 +104,7 @@
new CommandQueue(mContext),
mShadeController,
mDockManager,
- mView,
- mNotificationPanelViewController);
+ mView);
mController.setupExpandedStatusBar();
mController.setService(mStatusBar);
mController.setDragDownHelper(mDragDownHelper);