Implemented Lockscreen to shade transition
When dragging down on the lockscreen, we now pull down the quick settings while dragging instead of wating for the release Bug: 184946919 Test: atest SystemUITests Change-Id: Ib233282dd7ce4ba63ceab3e1b788aa164e88c8c0
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.animation;
|
||||
|
||||
import android.util.MathUtils;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.BounceInterpolator;
|
||||
@@ -71,6 +72,27 @@ public class Interpolators {
|
||||
public static final Interpolator TOUCH_RESPONSE_REVERSE =
|
||||
new PathInterpolator(0.9f, 0f, 0.7f, 1f);
|
||||
|
||||
/**
|
||||
* Calculate the amount of overshoot using an exponential falloff function with desired
|
||||
* properties, where the overshoot smoothly transitions at the 1.0f boundary into the
|
||||
* overshoot, retaining its acceleration.
|
||||
*
|
||||
* @param progress a progress value going from 0 to 1
|
||||
* @param overshootAmount the amount > 0 of overshoot desired. A value of 0.1 means the max
|
||||
* value of the overall progress will be at 1.1.
|
||||
* @param overshootStart the point in (0,1] where the result should reach 1
|
||||
* @return the interpolated overshoot
|
||||
*/
|
||||
public static float getOvershootInterpolation(float progress, float overshootAmount,
|
||||
float overshootStart) {
|
||||
if (overshootAmount == 0.0f || overshootStart == 0.0f) {
|
||||
throw new IllegalArgumentException("Invalid values for overshoot");
|
||||
}
|
||||
float b = MathUtils.log((overshootAmount + 1) / (overshootAmount)) / overshootStart;
|
||||
return MathUtils.max(0.0f,
|
||||
(float) (1.0f - Math.exp(-b * progress)) * (overshootAmount + 1.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpolate alpha for notifications background scrim during shade expansion.
|
||||
* @param fraction Shade expansion fraction
|
||||
|
||||
@@ -33,7 +33,7 @@ public interface QS extends FragmentBase {
|
||||
|
||||
String ACTION = "com.android.systemui.action.PLUGIN_QS";
|
||||
|
||||
int VERSION = 8;
|
||||
int VERSION = 9;
|
||||
|
||||
String TAG = "QS";
|
||||
|
||||
@@ -50,8 +50,13 @@ public interface QS extends FragmentBase {
|
||||
void setListening(boolean listening);
|
||||
boolean isShowingDetail();
|
||||
void closeDetail();
|
||||
default void setShowCollapsedOnKeyguard(boolean showCollapsedOnKeyguard) {}
|
||||
void animateHeaderSlidingIn(long delay);
|
||||
|
||||
/**
|
||||
* Set that we're currently pulse expanding
|
||||
*
|
||||
* @param pulseExpanding if we're currently expanding during pulsing
|
||||
*/
|
||||
default void setPulseExpanding(boolean pulseExpanding) {}
|
||||
void animateHeaderSlidingOut();
|
||||
void setQsExpansion(float qsExpansionFraction, float headerTranslation);
|
||||
void setHeaderListening(boolean listening);
|
||||
@@ -78,11 +83,24 @@ public interface QS extends FragmentBase {
|
||||
*/
|
||||
void setTranslateWhileExpanding(boolean shouldTranslate);
|
||||
|
||||
/**
|
||||
* Set the amount of pixels we have currently dragged down if we're transitioning to the full
|
||||
* shade. 0.0f means we're not transitioning yet.
|
||||
*/
|
||||
default void setTransitionToFullShadeAmount(float pxAmount, boolean animated) {}
|
||||
|
||||
/**
|
||||
* A rounded corner clipping that makes QS feel as if it were behind everything.
|
||||
*/
|
||||
void setFancyClipping(int top, int bottom, int cornerRadius, boolean visible);
|
||||
|
||||
/**
|
||||
* @return if quick settings is fully collapsed currently
|
||||
*/
|
||||
default boolean isFullyCollapsed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ProvidesInterface(version = HeightListener.VERSION)
|
||||
interface HeightListener {
|
||||
int VERSION = 1;
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
android:id="@+id/keyguard_bottom_area"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:outlineProvider="none"
|
||||
android:elevation="5dp" > <!-- Put it above the status bar header -->
|
||||
android:outlineProvider="none" > <!-- Put it above the status bar header -->
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/keyguard_indication_area"
|
||||
@@ -58,12 +57,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/preview_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
</FrameLayout>
|
||||
|
||||
<com.android.systemui.statusbar.KeyguardAffordanceView
|
||||
android:id="@+id/camera_button"
|
||||
android:layout_height="@dimen/keyguard_affordance_height"
|
||||
|
||||
@@ -37,6 +37,25 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<include
|
||||
layout="@layout/keyguard_bottom_area"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/keyguard_user_switcher_stub"
|
||||
android:layout="@layout/keyguard_user_switcher"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<include layout="@layout/status_bar_expanded_plugin_frame"/>
|
||||
|
||||
<include layout="@layout/dock_info_bottom_area_overlay" />
|
||||
|
||||
<com.android.keyguard.LockIconView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/lock_icon_view" />
|
||||
|
||||
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -49,6 +68,18 @@
|
||||
layout="@layout/keyguard_status_view"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<com.android.systemui.scrim.ScrimView
|
||||
android:id="@+id/scrim_notifications"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:importantForAccessibility="no"
|
||||
systemui:ignoreRightInset="true"
|
||||
systemui:layout_constraintStart_toStartOf="parent"
|
||||
systemui:layout_constraintEnd_toEndOf="parent"
|
||||
systemui:layout_constraintTop_toTopOf="parent"
|
||||
systemui:layout_constraintBottom_toBottomOf="parent"
|
||||
/>
|
||||
|
||||
<include layout="@layout/dock_info_overlay" />
|
||||
|
||||
<FrameLayout
|
||||
@@ -101,22 +132,9 @@
|
||||
|
||||
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
|
||||
|
||||
<include layout="@layout/dock_info_bottom_area_overlay" />
|
||||
|
||||
<include
|
||||
layout="@layout/keyguard_bottom_area"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ViewStub
|
||||
android:id="@+id/keyguard_user_switcher_stub"
|
||||
android:layout="@layout/keyguard_user_switcher"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent" />
|
||||
|
||||
<include layout="@layout/status_bar_expanded_plugin_frame"/>
|
||||
|
||||
<com.android.keyguard.LockIconView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/lock_icon_view" />
|
||||
<FrameLayout
|
||||
android:id="@+id/preview_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
</FrameLayout>
|
||||
</com.android.systemui.statusbar.phone.NotificationPanelView>
|
||||
|
||||
@@ -51,14 +51,6 @@
|
||||
sysui:ignoreRightInset="true"
|
||||
/>
|
||||
|
||||
<com.android.systemui.scrim.ScrimView
|
||||
android:id="@+id/scrim_notifications"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no"
|
||||
sysui:ignoreRightInset="true"
|
||||
/>
|
||||
|
||||
<com.android.systemui.statusbar.LightRevealScrim
|
||||
android:id="@+id/light_reveal_scrim"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -1409,6 +1409,26 @@
|
||||
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
||||
<dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
|
||||
|
||||
<!-- Delay after which the media will start transitioning to the full shade on
|
||||
the lockscreen -->
|
||||
<dimen name="lockscreen_shade_media_transition_start_delay">40dp</dimen>
|
||||
|
||||
<!-- Distance that the full shade transition takes in order for qs to fully transition to the
|
||||
shade -->
|
||||
<dimen name="lockscreen_shade_qs_transition_distance">200dp</dimen>
|
||||
|
||||
<!-- Distance that the full shade transition takes in order for scrim to fully transition to
|
||||
the shade (in alpha) -->
|
||||
<dimen name="lockscreen_shade_scrim_transition_distance">80dp</dimen>
|
||||
|
||||
<!-- Extra inset for the notifications when accounting for media during the lockscreen to
|
||||
shade transition to compensate for the disappearing media -->
|
||||
<dimen name="lockscreen_shade_transition_extra_media_inset">-48dp</dimen>
|
||||
|
||||
<!-- Maximum overshoot for the topPadding of notifications when transitioning to the full
|
||||
shade -->
|
||||
<dimen name="lockscreen_shade_max_top_overshoot">32dp</dimen>
|
||||
|
||||
<dimen name="people_space_widget_radius">28dp</dimen>
|
||||
<dimen name="people_space_image_radius">20dp</dimen>
|
||||
<dimen name="people_space_messages_count_radius">12dp</dimen>
|
||||
|
||||
@@ -197,6 +197,13 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
||||
animate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if we are currently animating the screen off from unlock
|
||||
*/
|
||||
public boolean isAnimatingScreenOffFromUnlocked() {
|
||||
return mKeyguardVisibilityHelper.isAnimatingScreenOffFromUnlocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the visibility of the keyguard status view based on some new state.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,9 @@ import android.view.View;
|
||||
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.notification.AnimatableProperty;
|
||||
import com.android.systemui.statusbar.notification.PropertyAnimator;
|
||||
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
|
||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
|
||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
@@ -37,6 +40,8 @@ public class KeyguardVisibilityHelper {
|
||||
private final DozeParameters mDozeParameters;
|
||||
private boolean mKeyguardViewVisibilityAnimating;
|
||||
private boolean mLastOccludedState = false;
|
||||
private boolean mAnimatingScreenOff;
|
||||
private final AnimationProperties mAnimationProperties = new AnimationProperties();
|
||||
|
||||
public KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController,
|
||||
DozeParameters dozeParameters) {
|
||||
@@ -89,12 +94,21 @@ public class KeyguardVisibilityHelper {
|
||||
} else if (statusBarState == KEYGUARD) {
|
||||
if (keyguardFadingAway) {
|
||||
mKeyguardViewVisibilityAnimating = true;
|
||||
float target = mView.getY() - mView.getHeight() * 0.05f;
|
||||
int delay = 0;
|
||||
int duration = 125;
|
||||
// We animate the Y properly separately using the PropertyAnimator, as the panel
|
||||
// view als needs to update the end position.
|
||||
mAnimationProperties.setDuration(duration).setDelay(delay);
|
||||
PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y);
|
||||
PropertyAnimator.setProperty(mView, AnimatableProperty.Y, target,
|
||||
mAnimationProperties,
|
||||
true /* animate */);
|
||||
mView.animate()
|
||||
.alpha(0)
|
||||
.translationYBy(-mView.getHeight() * 0.05f)
|
||||
.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
|
||||
.setDuration(125)
|
||||
.setStartDelay(0)
|
||||
.setDuration(duration)
|
||||
.setStartDelay(delay)
|
||||
.withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
|
||||
.start();
|
||||
} else if (mLastOccludedState && !isOccluded) {
|
||||
@@ -110,20 +124,30 @@ public class KeyguardVisibilityHelper {
|
||||
.start();
|
||||
} else if (mDozeParameters.shouldControlUnlockedScreenOff()) {
|
||||
mKeyguardViewVisibilityAnimating = true;
|
||||
mAnimatingScreenOff = true;
|
||||
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mView.setAlpha(0f);
|
||||
float currentY = mView.getY();
|
||||
mView.setY(currentY - mView.getHeight() * 0.1f);
|
||||
int duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
|
||||
int delay = (int) (duration * .6f);
|
||||
// We animate the Y properly separately using the PropertyAnimator, as the panel
|
||||
// view als needs to update the end position.
|
||||
mAnimationProperties.setDuration(duration).setDelay(delay);
|
||||
PropertyAnimator.cancelAnimation(mView, AnimatableProperty.Y);
|
||||
PropertyAnimator.setProperty(mView, AnimatableProperty.Y, currentY,
|
||||
mAnimationProperties,
|
||||
true /* animate */);
|
||||
|
||||
float curTranslationY = mView.getTranslationY();
|
||||
mView.setTranslationY(curTranslationY - mView.getHeight() * 0.1f);
|
||||
mView.animate()
|
||||
.setStartDelay((int) (StackStateAnimator.ANIMATION_DURATION_WAKEUP * .6f))
|
||||
.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
|
||||
.setStartDelay(delay)
|
||||
.setDuration(duration)
|
||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
||||
.alpha(1f)
|
||||
.translationY(curTranslationY)
|
||||
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
|
||||
.start();
|
||||
|
||||
} else {
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
mView.setAlpha(1f);
|
||||
@@ -148,5 +172,13 @@ public class KeyguardVisibilityHelper {
|
||||
|
||||
private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
|
||||
mKeyguardViewVisibilityAnimating = false;
|
||||
mAnimatingScreenOff = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {@code true} if we are currently animating the screen off from unlock
|
||||
*/
|
||||
public boolean isAnimatingScreenOffFromUnlocked() {
|
||||
return mAnimatingScreenOff;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
|
||||
final boolean hasUdfps = mAuthController.getUdfpsSensorLocation() != null;
|
||||
mHasUdfpsOrFaceAuthFeatures = hasFaceAuth || hasUdfps;
|
||||
if (!mHasUdfpsOrFaceAuthFeatures) {
|
||||
((ViewGroup) mView.getParent()).removeView(mView);
|
||||
// Posting since removing a view in the middle of onAttach can lead to a crash in the
|
||||
// iteration loop when the view isn't last
|
||||
mView.setVisibility(View.GONE);
|
||||
mView.post(() -> {
|
||||
mView.setVisibility(View.VISIBLE);
|
||||
((ViewGroup) mView.getParent()).removeView(mView);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,12 @@ class KeyguardMediaController @Inject constructor(
|
||||
mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the media player visible?
|
||||
*/
|
||||
var visible = false
|
||||
private set
|
||||
|
||||
var visibilityChangedListener: ((Boolean) -> Unit)? = null
|
||||
|
||||
/**
|
||||
@@ -106,11 +112,11 @@ class KeyguardMediaController @Inject constructor(
|
||||
val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
|
||||
statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
|
||||
// mediaHost.visible required for proper animations handling
|
||||
val shouldBeVisible = mediaHost.visible &&
|
||||
visible = mediaHost.visible &&
|
||||
!bypassController.bypassEnabled &&
|
||||
keyguardOrUserSwitcher &&
|
||||
notifLockscreenUserManager.shouldShowLockscreenNotifications()
|
||||
if (shouldBeVisible) {
|
||||
if (visible) {
|
||||
showMediaPlayer()
|
||||
} else {
|
||||
hideMediaPlayer()
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.util.MathUtils
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroupOverlay
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle
|
||||
@@ -35,6 +36,7 @@ import com.android.systemui.statusbar.StatusBarState
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.util.animation.UniqueObjectHostView
|
||||
import javax.inject.Inject
|
||||
@@ -74,6 +76,7 @@ class MediaHierarchyManager @Inject constructor(
|
||||
private val bypassController: KeyguardBypassController,
|
||||
private val mediaCarouselController: MediaCarouselController,
|
||||
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
|
||||
configurationController: ConfigurationController,
|
||||
wakefulnessLifecycle: WakefulnessLifecycle,
|
||||
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
||||
) {
|
||||
@@ -182,6 +185,58 @@ class MediaHierarchyManager @Inject constructor(
|
||||
mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser()
|
||||
}
|
||||
|
||||
/**
|
||||
* distance that the full shade transition takes in order for media to fully transition to the
|
||||
* shade
|
||||
*/
|
||||
private var distanceForFullShadeTransition = 0
|
||||
|
||||
/**
|
||||
* Delay after which the media will start transitioning to the full shade on the lockscreen.
|
||||
*/
|
||||
private var fullShadeTransitionDelay = 0
|
||||
|
||||
/**
|
||||
* The amount of progress we are currently in if we're transitioning to the full shade.
|
||||
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
|
||||
* shade.
|
||||
*/
|
||||
private var fullShadeTransitionProgress = 0f
|
||||
set(value) {
|
||||
if (field == value) {
|
||||
return
|
||||
}
|
||||
field = value
|
||||
if (bypassController.bypassEnabled) {
|
||||
return
|
||||
}
|
||||
updateDesiredLocation()
|
||||
if (value >= 0) {
|
||||
updateTargetState()
|
||||
applyTargetStateIfNotAnimating()
|
||||
}
|
||||
}
|
||||
|
||||
private val isTransitioningToFullShade: Boolean
|
||||
get() = fullShadeTransitionProgress != 0f && !bypassController.bypassEnabled
|
||||
|
||||
/**
|
||||
* Set the amount of pixels we have currently dragged down if we're transitioning to the full
|
||||
* shade. 0.0f means we're not transitioning yet.
|
||||
*/
|
||||
fun setTransitionToFullShadeAmount(value: Float) {
|
||||
// If we're transitioning starting on the shade_locked, we don't want any delay and rather
|
||||
// have it aligned with the rest of the animation
|
||||
val delay = if (statusbarState == StatusBarState.KEYGUARD) {
|
||||
fullShadeTransitionDelay
|
||||
} else {
|
||||
0
|
||||
}
|
||||
val progress = MathUtils.saturate((value - delay) /
|
||||
(distanceForFullShadeTransition - delay))
|
||||
fullShadeTransitionProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(progress)
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the shade currently collapsing from the expanded qs? If we're on the lockscreen and in qs,
|
||||
* we wouldn't want to transition in that case.
|
||||
@@ -242,6 +297,12 @@ class MediaHierarchyManager @Inject constructor(
|
||||
}
|
||||
|
||||
init {
|
||||
updateConfiguration()
|
||||
configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
|
||||
override fun onDensityOrFontScaleChanged() {
|
||||
updateConfiguration()
|
||||
}
|
||||
})
|
||||
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
|
||||
override fun onStatePreChange(oldState: Int, newState: Int) {
|
||||
// We're updating the location before the state change happens, since we want the
|
||||
@@ -312,6 +373,13 @@ class MediaHierarchyManager @Inject constructor(
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateConfiguration() {
|
||||
distanceForFullShadeTransition = context.resources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_qs_transition_distance)
|
||||
fullShadeTransitionDelay = context.resources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_media_transition_start_delay)
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a media host and create a view can be attached to a view hierarchy
|
||||
* and where the players will be placed in when the host is the currently desired state.
|
||||
@@ -546,6 +614,9 @@ class MediaHierarchyManager @Inject constructor(
|
||||
if (progress >= 0) {
|
||||
return progress
|
||||
}
|
||||
if (isTransitioningToFullShade) {
|
||||
return fullShadeTransitionProgress
|
||||
}
|
||||
return -1.0f
|
||||
}
|
||||
|
||||
@@ -643,6 +714,7 @@ class MediaHierarchyManager @Inject constructor(
|
||||
val location = when {
|
||||
qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
|
||||
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
|
||||
onLockscreen && isTransitioningToFullShade -> LOCATION_QQS
|
||||
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
|
||||
else -> LOCATION_QQS
|
||||
}
|
||||
|
||||
@@ -112,6 +112,17 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
* otherwise.
|
||||
*/
|
||||
private boolean mTranslateWhileExpanding;
|
||||
private boolean mPulseExpanding;
|
||||
|
||||
/**
|
||||
* Are we currently transitioning from lockscreen to the full shade?
|
||||
*/
|
||||
private boolean mTransitioningToFullShade;
|
||||
|
||||
/**
|
||||
* Whether the next Quick settings
|
||||
*/
|
||||
private boolean mAnimateNextQsUpdate;
|
||||
|
||||
@Inject
|
||||
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
|
||||
@@ -265,6 +276,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullyCollapsed() {
|
||||
return mLastQSExpansion == 0.0f || mLastQSExpansion == -1;
|
||||
}
|
||||
|
||||
private void setEditLocation(View view) {
|
||||
View edit = view.findViewById(android.R.id.edit);
|
||||
int[] loc = edit.getLocationOnScreen();
|
||||
@@ -335,14 +351,22 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShowCollapsedOnKeyguard(boolean showCollapsedOnKeyguard) {
|
||||
if (showCollapsedOnKeyguard != mShowCollapsedOnKeyguard) {
|
||||
mShowCollapsedOnKeyguard = showCollapsedOnKeyguard;
|
||||
public void setPulseExpanding(boolean pulseExpanding) {
|
||||
if (pulseExpanding != mPulseExpanding) {
|
||||
mPulseExpanding = pulseExpanding;
|
||||
updateShowCollapsedOnKeyguard();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateShowCollapsedOnKeyguard() {
|
||||
boolean showCollapsed = mPulseExpanding || mTransitioningToFullShade;
|
||||
if (showCollapsed != mShowCollapsedOnKeyguard) {
|
||||
mShowCollapsedOnKeyguard = showCollapsed;
|
||||
updateQsState();
|
||||
if (mQSAnimator != null) {
|
||||
mQSAnimator.setShowCollapsedOnKeyguard(showCollapsedOnKeyguard);
|
||||
mQSAnimator.setShowCollapsedOnKeyguard(showCollapsed);
|
||||
}
|
||||
if (!showCollapsedOnKeyguard && isKeyguardShowing()) {
|
||||
if (!showCollapsed && isKeyguardShowing()) {
|
||||
setQsExpansion(mLastQSExpansion, 0);
|
||||
}
|
||||
}
|
||||
@@ -411,13 +435,24 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQsExpansion(float expansion, float headerTranslation) {
|
||||
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
|
||||
public void setTransitionToFullShadeAmount(float pxAmount, boolean animated) {
|
||||
boolean isTransitioningToFullShade = pxAmount > 0;
|
||||
if (isTransitioningToFullShade != mTransitioningToFullShade) {
|
||||
mTransitioningToFullShade = isTransitioningToFullShade;
|
||||
updateShowCollapsedOnKeyguard();
|
||||
setQsExpansion(mLastQSExpansion, mLastHeaderTranslation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQsExpansion(float expansion, float proposedTranslation) {
|
||||
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + proposedTranslation);
|
||||
float headerTranslation = mTransitioningToFullShade ? 0 : proposedTranslation;
|
||||
if (mQSAnimator != null) {
|
||||
final boolean showQSOnLockscreen = expansion > 0;
|
||||
final boolean showQSUnlocked = headerTranslation == 0 || !mTranslateWhileExpanding;
|
||||
mQSAnimator.startAlphaAnimation(showQSOnLockscreen || showQSUnlocked);
|
||||
mQSAnimator.startAlphaAnimation(showQSOnLockscreen || showQSUnlocked
|
||||
|| mTransitioningToFullShade);
|
||||
}
|
||||
mContainer.setExpansion(expansion);
|
||||
final float translationScaleY = (mTranslateWhileExpanding
|
||||
@@ -541,18 +576,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
||||
&& !isKeyguardShowing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateHeaderSlidingIn(long delay) {
|
||||
if (DEBUG) Log.d(TAG, "animateHeaderSlidingIn");
|
||||
// If the QS is already expanded we don't need to slide in the header as it's already
|
||||
// visible.
|
||||
if (!mQsExpanded && getView().getTranslationY() != 0) {
|
||||
mHeaderAnimating = true;
|
||||
mDelay = delay;
|
||||
getView().getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void animateHeaderSlidingOut() {
|
||||
if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut");
|
||||
|
||||
@@ -5,35 +5,489 @@ import android.animation.AnimatorListenerAdapter
|
||||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.os.SystemClock
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.MathUtils
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewConfiguration
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent
|
||||
import com.android.systemui.ExpandHelper
|
||||
import com.android.systemui.Gefingerpoken
|
||||
import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.Interpolators
|
||||
import com.android.systemui.classifier.Classifier
|
||||
import com.android.systemui.classifier.FalsingCollector
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.media.MediaHierarchyManager
|
||||
import com.android.systemui.plugins.ActivityStarter.OnDismissAction
|
||||
import com.android.systemui.plugins.FalsingManager
|
||||
import com.android.systemui.plugins.qs.QS
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableView
|
||||
import com.android.systemui.statusbar.notification.stack.AmbientState
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||
import com.android.systemui.statusbar.phone.LockscreenGestureLogger
|
||||
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelViewController
|
||||
import com.android.systemui.statusbar.phone.ScrimController
|
||||
import com.android.systemui.statusbar.phone.StatusBar
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.util.Utils
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val SPRING_BACK_ANIMATION_LENGTH_MS = 375L
|
||||
private const val RUBBERBAND_FACTOR_STATIC = 0.15f
|
||||
private const val RUBBERBAND_FACTOR_EXPANDABLE = 0.5f
|
||||
|
||||
/**
|
||||
* A class that controls the lockscreen to shade transition
|
||||
*/
|
||||
@SysUISingleton
|
||||
class LockscreenShadeTransitionController @Inject constructor(
|
||||
private val statusBarStateController: SysuiStatusBarStateController,
|
||||
private val lockscreenGestureLogger: LockscreenGestureLogger,
|
||||
private val keyguardBypassController: KeyguardBypassController,
|
||||
private val lockScreenUserManager: NotificationLockscreenUserManager,
|
||||
private val falsingCollector: FalsingCollector,
|
||||
private val ambientState: AmbientState,
|
||||
private val displayMetrics: DisplayMetrics,
|
||||
private val mediaHierarchyManager: MediaHierarchyManager,
|
||||
private val scrimController: ScrimController,
|
||||
private val featureFlags: FeatureFlags,
|
||||
private val context: Context,
|
||||
configurationController: ConfigurationController,
|
||||
falsingManager: FalsingManager
|
||||
) {
|
||||
private var useSplitShade: Boolean = false
|
||||
private lateinit var nsslController: NotificationStackScrollLayoutController
|
||||
lateinit var notificationPanelController: NotificationPanelViewController
|
||||
lateinit var statusbar: StatusBar
|
||||
lateinit var qS: QS
|
||||
|
||||
/**
|
||||
* A handler that handles the next keyguard dismiss animation.
|
||||
*/
|
||||
private var animationHandlerOnKeyguardDismiss: ((Long) -> Unit)? = null
|
||||
|
||||
/**
|
||||
* The entry that was just dragged down on.
|
||||
*/
|
||||
private var draggedDownEntry: NotificationEntry? = null
|
||||
|
||||
/**
|
||||
* The current animator if any
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal var dragDownAnimator: ValueAnimator? = null
|
||||
|
||||
/**
|
||||
* Distance that the full shade transition takes in order for scrim to fully transition to
|
||||
* the shade (in alpha)
|
||||
*/
|
||||
private var scrimTransitionDistance = 0
|
||||
|
||||
/**
|
||||
* Distance that the full transition takes in order for us to fully transition to the shade
|
||||
*/
|
||||
private var fullTransitionDistance = 0
|
||||
|
||||
/**
|
||||
* Flag to make sure that the dragDownAmount is applied to the listeners even when in the
|
||||
* locked down shade.
|
||||
*/
|
||||
private var forceApplyAmount = false
|
||||
|
||||
/**
|
||||
* A flag to suppress the default animation when unlocking in the locked down shade.
|
||||
*/
|
||||
private var nextHideKeyguardNeedsNoAnimation = false
|
||||
|
||||
/**
|
||||
* The touch helper responsible for the drag down animation.
|
||||
*/
|
||||
val touchHelper = DragDownHelper(falsingManager, falsingCollector, this, context)
|
||||
|
||||
init {
|
||||
updateResources()
|
||||
configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
|
||||
override fun onConfigChanged(newConfig: Configuration?) {
|
||||
updateResources()
|
||||
touchHelper.updateResources(context)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateResources() {
|
||||
scrimTransitionDistance = context.resources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_scrim_transition_distance)
|
||||
fullTransitionDistance = context.resources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_qs_transition_distance)
|
||||
useSplitShade = Utils.shouldUseSplitNotificationShade(featureFlags, context.resources)
|
||||
}
|
||||
|
||||
fun setStackScroller(nsslController: NotificationStackScrollLayoutController) {
|
||||
this.nsslController = nsslController
|
||||
touchHelper.host = nsslController.view
|
||||
touchHelper.expandCallback = nsslController.expandHelperCallback
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the shelf controller such that clicks on it will expand the shade
|
||||
*/
|
||||
fun bindController(notificationShelfController: NotificationShelfController) {
|
||||
// Bind the click listener of the shelf to go to the full shade
|
||||
notificationShelfController.setOnClickListener {
|
||||
if (statusBarStateController.state == StatusBarState.KEYGUARD) {
|
||||
statusbar.wakeUpIfDozing(SystemClock.uptimeMillis(), it, "SHADE_CLICK")
|
||||
goToLockedShade(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the interaction is accepted, false if it should be cancelled
|
||||
*/
|
||||
internal fun canDragDown(): Boolean {
|
||||
return (statusBarStateController.state == StatusBarState.KEYGUARD ||
|
||||
nsslController.isInLockedDownShade()) &&
|
||||
qS.isFullyCollapsed
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the touch helper when when a gesture has completed all the way and released.
|
||||
*/
|
||||
internal fun onDraggedDown(startingChild: View?, dragLengthY: Int) {
|
||||
if (canDragDown()) {
|
||||
if (nsslController.isInLockedDownShade()) {
|
||||
statusBarStateController.setLeaveOpenOnKeyguardHide(true)
|
||||
statusbar.dismissKeyguardThenExecute(OnDismissAction {
|
||||
nextHideKeyguardNeedsNoAnimation = true
|
||||
false
|
||||
},
|
||||
null /* cancelRunnable */, false /* afterKeyguardGone */)
|
||||
} else {
|
||||
lockscreenGestureLogger.write(
|
||||
MetricsEvent.ACTION_LS_SHADE,
|
||||
(dragLengthY / displayMetrics.density).toInt(),
|
||||
0 /* velocityDp */)
|
||||
lockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_PULL_SHADE_OPEN)
|
||||
if (!ambientState.isDozing() || startingChild != null) {
|
||||
// go to locked shade while animating the drag down amount from its current
|
||||
// value
|
||||
val animationHandler = { delay: Long ->
|
||||
if (startingChild is ExpandableNotificationRow) {
|
||||
startingChild.onExpandedByGesture(
|
||||
true /* drag down is always an open */)
|
||||
}
|
||||
notificationPanelController.animateToFullShade(delay)
|
||||
notificationPanelController.setTransitionToFullShadeAmount(0f,
|
||||
true /* animated */, delay)
|
||||
|
||||
// Let's reset ourselves, ready for the next animation
|
||||
|
||||
// changing to shade locked will make isInLockDownShade true, so let's
|
||||
// override that
|
||||
forceApplyAmount = true
|
||||
// Reset the behavior. At this point the animation is already started
|
||||
dragDownAmount = 0f
|
||||
forceApplyAmount = false
|
||||
}
|
||||
val cancelRunnable = Runnable { setDragDownAmountAnimated(0f) }
|
||||
goToLockedShadeInternal(startingChild, animationHandler, cancelRunnable)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setDragDownAmountAnimated(0f)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the touch helper when the drag down was aborted and should be reset.
|
||||
*/
|
||||
internal fun onDragDownReset() {
|
||||
nsslController.setDimmed(true /* dimmed */, true /* animated */)
|
||||
nsslController.resetScrollPosition()
|
||||
nsslController.resetCheckSnoozeLeavebehind()
|
||||
setDragDownAmountAnimated(0f)
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has dragged either above or below the threshold which changes the dimmed state.
|
||||
* @param above whether they dragged above it
|
||||
*/
|
||||
internal fun onCrossedThreshold(above: Boolean) {
|
||||
nsslController.setDimmed(!above /* dimmed */, true /* animate */)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the touch helper when the drag down was started
|
||||
*/
|
||||
internal fun onDragDownStarted() {
|
||||
nsslController.cancelLongPress()
|
||||
nsslController.checkSnoozeLeavebehind()
|
||||
dragDownAnimator?.cancel()
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we need a falsing check currently?
|
||||
*/
|
||||
internal val isFalsingCheckNeeded: Boolean
|
||||
get() = statusBarStateController.state == StatusBarState.KEYGUARD
|
||||
|
||||
/**
|
||||
* Is dragging down enabled on a given view
|
||||
* @param view The view to check or `null` to check if it's enabled at all
|
||||
*/
|
||||
internal fun isDragDownEnabledForView(view: ExpandableView?): Boolean {
|
||||
if (isDragDownAnywhereEnabled) {
|
||||
return true
|
||||
}
|
||||
if (nsslController.isInLockedDownShade()) {
|
||||
if (view == null) {
|
||||
// Dragging down is allowed in general
|
||||
return true
|
||||
}
|
||||
if (view is ExpandableNotificationRow) {
|
||||
// Only drag down on sensitive views, otherwise the ExpandHelper will take this
|
||||
return view.entry.isSensitive
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if drag down is enabled anywhere, not just on selected views.
|
||||
*/
|
||||
internal val isDragDownAnywhereEnabled: Boolean
|
||||
get() = (statusBarStateController.getState() == StatusBarState.KEYGUARD &&
|
||||
!keyguardBypassController.bypassEnabled &&
|
||||
qS.isFullyCollapsed)
|
||||
|
||||
/**
|
||||
* The amount in pixels that the user has dragged down.
|
||||
*/
|
||||
internal var dragDownAmount = 0f
|
||||
set(value) {
|
||||
if (field != value || forceApplyAmount) {
|
||||
field = value
|
||||
if (!nsslController.isInLockedDownShade() || forceApplyAmount) {
|
||||
nsslController.setTransitionToFullShadeAmount(field)
|
||||
notificationPanelController.setTransitionToFullShadeAmount(field,
|
||||
false /* animate */, 0 /* delay */)
|
||||
mediaHierarchyManager.setTransitionToFullShadeAmount(field)
|
||||
val scrimProgress = MathUtils.saturate(field / scrimTransitionDistance)
|
||||
scrimController.setTransitionToFullShadeProgress(scrimProgress)
|
||||
// TODO: appear qs also in split shade
|
||||
val qsAmount = if (useSplitShade) 0f else field
|
||||
qS.setTransitionToFullShadeAmount(qsAmount, false /* animate */)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setDragDownAmountAnimated(
|
||||
target: Float,
|
||||
delay: Long = 0,
|
||||
endlistener: (() -> Unit)? = null
|
||||
) {
|
||||
val dragDownAnimator = ValueAnimator.ofFloat(dragDownAmount, target)
|
||||
dragDownAnimator.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||
dragDownAnimator.duration = SPRING_BACK_ANIMATION_LENGTH_MS
|
||||
dragDownAnimator.addUpdateListener { animation: ValueAnimator ->
|
||||
dragDownAmount = animation.animatedValue as Float
|
||||
}
|
||||
if (delay > 0) {
|
||||
dragDownAnimator.startDelay = delay
|
||||
}
|
||||
if (endlistener != null) {
|
||||
dragDownAnimator.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
endlistener.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
dragDownAnimator.start()
|
||||
this.dragDownAnimator = dragDownAnimator
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate appear the drag down amount.
|
||||
*/
|
||||
private fun animateAppear(delay: Long = 0) {
|
||||
// changing to shade locked will make isInLockDownShade true, so let's override
|
||||
// that
|
||||
forceApplyAmount = true
|
||||
|
||||
// we set the value initially to 1 pixel, since that will make sure we're
|
||||
// transitioning to the full shade. this is important to avoid flickering,
|
||||
// as the below animation only starts once the shade is unlocked, which can
|
||||
// be a couple of frames later. if we're setting it to 0, it will use the
|
||||
// default inset and therefore flicker
|
||||
dragDownAmount = 1f
|
||||
setDragDownAmountAnimated(fullTransitionDistance.toFloat(), delay = delay) {
|
||||
// End listener:
|
||||
// Reset
|
||||
dragDownAmount = 0f
|
||||
forceApplyAmount = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask this controller to go to the locked shade, changing the state change and doing
|
||||
* an animation, where the qs appears from 0 from the top
|
||||
*
|
||||
* If secure with redaction: Show bouncer, go to unlocked shade.
|
||||
* If secure without redaction or no security: Go to [StatusBarState.SHADE_LOCKED].
|
||||
*
|
||||
* @param expandView The view to expand after going to the shade
|
||||
* @param needsQSAnimation if this needs the quick settings to slide in from the top or if
|
||||
* that's already handled separately
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun goToLockedShade(expandedView: View?, needsQSAnimation: Boolean = true) {
|
||||
if (statusBarStateController.state == StatusBarState.KEYGUARD) {
|
||||
val animationHandler: ((Long) -> Unit)?
|
||||
if (needsQSAnimation) {
|
||||
// Let's use the default animation
|
||||
animationHandler = null
|
||||
} else {
|
||||
// Let's only animate notifications
|
||||
animationHandler = { delay: Long ->
|
||||
notificationPanelController.animateToFullShade(delay)
|
||||
}
|
||||
}
|
||||
goToLockedShadeInternal(expandedView, animationHandler,
|
||||
cancelAction = null)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If secure with redaction: Show bouncer, go to unlocked shade.
|
||||
*
|
||||
* If secure without redaction or no security: Go to [StatusBarState.SHADE_LOCKED].
|
||||
*
|
||||
* @param expandView The view to expand after going to the shade.
|
||||
* @param animationHandler The handler which performs the go to full shade animation. If null,
|
||||
* the default handler will do the animation, otherwise the caller is
|
||||
* responsible for the animation. The input value is a Long for the
|
||||
* delay for the animation.
|
||||
* @param cancelAction The runnable to invoke when the transition is aborted. This happens if
|
||||
* the user goes to the bouncer and goes back.
|
||||
*/
|
||||
private fun goToLockedShadeInternal(
|
||||
expandView: View?,
|
||||
animationHandler: ((Long) -> Unit)? = null,
|
||||
cancelAction: Runnable? = null
|
||||
) {
|
||||
if (statusbar.isShadeDisabled) {
|
||||
cancelAction?.run()
|
||||
return
|
||||
}
|
||||
var userId: Int = lockScreenUserManager.getCurrentUserId()
|
||||
var entry: NotificationEntry? = null
|
||||
if (expandView is ExpandableNotificationRow) {
|
||||
entry = expandView.entry
|
||||
entry.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */)
|
||||
// Indicate that the group expansion is changing at this time -- this way the group
|
||||
// and children backgrounds / divider animations will look correct.
|
||||
entry.setGroupExpansionChanging(true)
|
||||
userId = entry.sbn.userId
|
||||
}
|
||||
var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
|
||||
lockScreenUserManager.getCurrentUserId()) ||
|
||||
!lockScreenUserManager.shouldShowLockscreenNotifications() ||
|
||||
falsingCollector.shouldEnforceBouncer())
|
||||
if (keyguardBypassController.bypassEnabled) {
|
||||
fullShadeNeedsBouncer = false
|
||||
}
|
||||
if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
|
||||
statusBarStateController.setLeaveOpenOnKeyguardHide(true)
|
||||
var onDismissAction: OnDismissAction? = null
|
||||
if (animationHandler != null) {
|
||||
onDismissAction = OnDismissAction {
|
||||
// We're waiting on keyguard to hide before triggering the action,
|
||||
// as that will make the animation work properly
|
||||
animationHandlerOnKeyguardDismiss = animationHandler
|
||||
false
|
||||
}
|
||||
}
|
||||
val cancelHandler = Runnable {
|
||||
draggedDownEntry?.apply {
|
||||
setUserLocked(false)
|
||||
notifyHeightChanged(false /* needsAnimation */)
|
||||
draggedDownEntry = null
|
||||
}
|
||||
cancelAction?.run()
|
||||
}
|
||||
statusbar.showBouncerWithDimissAndCancelIfKeyguard(onDismissAction, cancelHandler)
|
||||
draggedDownEntry = entry
|
||||
} else {
|
||||
statusBarStateController.setState(StatusBarState.SHADE_LOCKED)
|
||||
// This call needs to be after updating the shade state since otherwise
|
||||
// the scrimstate resets too early
|
||||
if (animationHandler != null) {
|
||||
animationHandler.invoke(0 /* delay */)
|
||||
} else {
|
||||
performDefaultGoToFullShadeAnimation(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify this handler that the keyguard was just dismissed and that a animation to
|
||||
* the full shade should happen.
|
||||
*/
|
||||
fun onHideKeyguard(delay: Long) {
|
||||
if (animationHandlerOnKeyguardDismiss != null) {
|
||||
animationHandlerOnKeyguardDismiss!!.invoke(delay)
|
||||
animationHandlerOnKeyguardDismiss = null
|
||||
} else {
|
||||
if (nextHideKeyguardNeedsNoAnimation) {
|
||||
nextHideKeyguardNeedsNoAnimation = false
|
||||
} else {
|
||||
performDefaultGoToFullShadeAnimation(delay)
|
||||
}
|
||||
}
|
||||
draggedDownEntry?.apply {
|
||||
setUserLocked(false)
|
||||
draggedDownEntry = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the default appear animation when going to the full shade. This is called when
|
||||
* not triggered by gestures, e.g. when clicking on the shelf or expand button.
|
||||
*/
|
||||
private fun performDefaultGoToFullShadeAnimation(delay: Long) {
|
||||
notificationPanelController.animateToFullShade(delay)
|
||||
animateAppear(delay)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand
|
||||
* the notification where the drag started.
|
||||
*/
|
||||
class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
private val expandCallback: ExpandHelper.Callback,
|
||||
private val dragDownCallback: DragDownCallback,
|
||||
private val falsingCollector: FalsingCollector,
|
||||
private val host: View,
|
||||
context: Context): Gefingerpoken {
|
||||
class DragDownHelper(
|
||||
private val falsingManager: FalsingManager,
|
||||
private val falsingCollector: FalsingCollector,
|
||||
private val dragDownCallback: LockscreenShadeTransitionController,
|
||||
context: Context
|
||||
) : Gefingerpoken {
|
||||
|
||||
private val minDragDistance: Int
|
||||
private var dragDownAmountOnStart = 0.0f
|
||||
lateinit var expandCallback: ExpandHelper.Callback
|
||||
lateinit var host: View
|
||||
|
||||
private var minDragDistance = 0
|
||||
private var initialTouchX = 0f
|
||||
private var initialTouchY = 0f
|
||||
private val touchSlop: Float
|
||||
private val slopMultiplier: Float
|
||||
private var touchSlop = 0f
|
||||
private var slopMultiplier = 0f
|
||||
private val temp2 = IntArray(2)
|
||||
private var draggedFarEnough = false
|
||||
private var startingChild: ExpandableView? = null
|
||||
@@ -41,7 +495,23 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
var isDraggingDown = false
|
||||
private set
|
||||
|
||||
private val isFalseTouch: Boolean
|
||||
get() {
|
||||
return if (!dragDownCallback.isFalsingCheckNeeded) {
|
||||
false
|
||||
} else {
|
||||
falsingManager.isFalseTouch(Classifier.NOTIFICATION_DRAG_DOWN) || !draggedFarEnough
|
||||
}
|
||||
}
|
||||
|
||||
val isDragDownEnabled: Boolean
|
||||
get() = dragDownCallback.isDragDownEnabledForView(null)
|
||||
|
||||
init {
|
||||
updateResources(context)
|
||||
}
|
||||
|
||||
fun updateResources(context: Context) {
|
||||
minDragDistance = context.resources.getDimensionPixelSize(
|
||||
R.dimen.keyguard_drag_down_min_distance)
|
||||
val configuration = ViewConfiguration.get(context)
|
||||
@@ -74,7 +544,8 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
captureStartingChild(initialTouchX, initialTouchY)
|
||||
initialTouchY = y
|
||||
initialTouchX = x
|
||||
dragDownCallback.onTouchSlopExceeded()
|
||||
dragDownCallback.onDragDownStarted()
|
||||
dragDownAmountOnStart = dragDownCallback.dragDownAmount
|
||||
return startingChild != null || dragDownCallback.isDragDownAnywhereEnabled
|
||||
}
|
||||
}
|
||||
@@ -92,10 +563,9 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
lastHeight = y - initialTouchY
|
||||
captureStartingChild(initialTouchX, initialTouchY)
|
||||
dragDownCallback.dragDownAmount = lastHeight + dragDownAmountOnStart
|
||||
if (startingChild != null) {
|
||||
handleExpansion(lastHeight, startingChild!!)
|
||||
} else {
|
||||
dragDownCallback.setEmptyDragAmount(lastHeight)
|
||||
}
|
||||
if (lastHeight > minDragDistance) {
|
||||
if (!draggedFarEnough) {
|
||||
@@ -110,12 +580,10 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
}
|
||||
return true
|
||||
}
|
||||
MotionEvent.ACTION_UP -> if (!falsingManager.isUnlockingDisabled && !isFalseTouch
|
||||
&& dragDownCallback.canDragDown()) {
|
||||
MotionEvent.ACTION_UP -> if (!falsingManager.isUnlockingDisabled && !isFalseTouch &&
|
||||
dragDownCallback.canDragDown()) {
|
||||
dragDownCallback.onDraggedDown(startingChild, (y - initialTouchY).toInt())
|
||||
if (startingChild == null) {
|
||||
cancelExpansion()
|
||||
} else {
|
||||
if (startingChild != null) {
|
||||
expandCallback.setUserLockedChild(startingChild, false)
|
||||
startingChild = null
|
||||
}
|
||||
@@ -132,15 +600,6 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
return false
|
||||
}
|
||||
|
||||
private val isFalseTouch: Boolean
|
||||
get() {
|
||||
return if (!dragDownCallback.isFalsingCheckNeeded) {
|
||||
false
|
||||
} else {
|
||||
falsingManager.isFalseTouch(Classifier.NOTIFICATION_DRAG_DOWN) || !draggedFarEnough
|
||||
}
|
||||
}
|
||||
|
||||
private fun captureStartingChild(x: Float, y: Float) {
|
||||
if (startingChild == null) {
|
||||
startingChild = findView(x, y)
|
||||
@@ -174,7 +633,7 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
child.actualHeight = (child.collapsedHeight + rubberband).toInt()
|
||||
}
|
||||
|
||||
private fun cancelExpansion(child: ExpandableView) {
|
||||
private fun cancelChildExpansion(child: ExpandableView) {
|
||||
if (child.actualHeight == child.collapsedHeight) {
|
||||
expandCallback.setUserLockedChild(child, false)
|
||||
return
|
||||
@@ -182,7 +641,7 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
val anim = ObjectAnimator.ofInt(child, "actualHeight",
|
||||
child.actualHeight, child.collapsedHeight)
|
||||
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
|
||||
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS
|
||||
anim.addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
expandCallback.setUserLockedChild(child, false)
|
||||
@@ -191,73 +650,18 @@ class DragDownHelper(private val falsingManager: FalsingManager,
|
||||
anim.start()
|
||||
}
|
||||
|
||||
private fun cancelExpansion() {
|
||||
val anim = ValueAnimator.ofFloat(lastHeight, 0f)
|
||||
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
|
||||
anim.addUpdateListener { animation: ValueAnimator ->
|
||||
dragDownCallback.setEmptyDragAmount(animation.animatedValue as Float)
|
||||
}
|
||||
anim.start()
|
||||
}
|
||||
|
||||
private fun stopDragging() {
|
||||
falsingCollector.onNotificationStopDraggingDown()
|
||||
if (startingChild != null) {
|
||||
cancelExpansion(startingChild!!)
|
||||
cancelChildExpansion(startingChild!!)
|
||||
startingChild = null
|
||||
} else {
|
||||
cancelExpansion()
|
||||
}
|
||||
isDraggingDown = false
|
||||
dragDownCallback.onDragDownReset()
|
||||
}
|
||||
|
||||
private fun findView(x: Float, y: Float): ExpandableView {
|
||||
private fun findView(x: Float, y: Float): ExpandableView? {
|
||||
host.getLocationOnScreen(temp2)
|
||||
return expandCallback.getChildAtRawPosition(x + temp2[0] , y + temp2[1])
|
||||
}
|
||||
|
||||
val isDragDownEnabled: Boolean
|
||||
get() = dragDownCallback.isDragDownEnabledForView(null)
|
||||
|
||||
interface DragDownCallback {
|
||||
|
||||
/**
|
||||
* @return true if the interaction is accepted, false if it should be cancelled
|
||||
*/
|
||||
fun canDragDown(): Boolean
|
||||
|
||||
/**
|
||||
* Call when a view has been dragged.
|
||||
**/
|
||||
fun onDraggedDown(startingChild: View?, dragLengthY: Int)
|
||||
fun onDragDownReset()
|
||||
|
||||
/**
|
||||
* The user has dragged either above or below the threshold
|
||||
* @param above whether they dragged above it
|
||||
*/
|
||||
fun onCrossedThreshold(above: Boolean)
|
||||
fun onTouchSlopExceeded()
|
||||
fun setEmptyDragAmount(amount: Float)
|
||||
val isFalsingCheckNeeded: Boolean
|
||||
|
||||
/**
|
||||
* Is dragging down enabled on a given view
|
||||
* @param view The view to check or `null` to check if it's enabled at all
|
||||
*/
|
||||
fun isDragDownEnabledForView(view: ExpandableView?): Boolean
|
||||
|
||||
/**
|
||||
* @return if drag down is enabled anywhere, not just on selected views.
|
||||
*/
|
||||
val isDragDownAnywhereEnabled: Boolean
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val RUBBERBAND_FACTOR_EXPANDABLE = 0.5f
|
||||
private const val RUBBERBAND_FACTOR_STATIC = 0.15f
|
||||
private const val SPRING_BACK_ANIMATION_LENGTH_MS = 375
|
||||
return expandCallback.getChildAtRawPosition(x + temp2[0], y + temp2[1])
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ import com.android.systemui.statusbar.notification.stack.NotificationRoundnessMa
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||
import com.android.systemui.statusbar.phone.ShadeController
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
||||
@@ -59,6 +58,7 @@ constructor(
|
||||
private val roundnessManager: NotificationRoundnessManager,
|
||||
private val statusBarStateController: StatusBarStateController,
|
||||
private val falsingManager: FalsingManager,
|
||||
private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
|
||||
private val falsingCollector: FalsingCollector
|
||||
) : Gefingerpoken {
|
||||
companion object {
|
||||
@@ -66,7 +66,6 @@ constructor(
|
||||
private val SPRING_BACK_ANIMATION_LENGTH_MS = 375
|
||||
}
|
||||
private val mPowerManager: PowerManager?
|
||||
private lateinit var shadeController: ShadeController
|
||||
|
||||
private val mMinDragDistance: Int
|
||||
private var mInitialTouchX: Float = 0.0f
|
||||
@@ -95,7 +94,7 @@ constructor(
|
||||
var leavingLockscreen: Boolean = false
|
||||
private set
|
||||
private val mTouchSlop: Float
|
||||
private lateinit var expansionCallback: ExpansionCallback
|
||||
private lateinit var overStretchHandler: OverStretchHandler
|
||||
private lateinit var stackScrollerController: NotificationStackScrollLayoutController
|
||||
private val mTemp2 = IntArray(2)
|
||||
private var mDraggedFarEnough: Boolean = false
|
||||
@@ -103,7 +102,7 @@ constructor(
|
||||
private var mPulsing: Boolean = false
|
||||
var isWakingToShadeLocked: Boolean = false
|
||||
private set
|
||||
private var mEmptyDragAmount: Float = 0.0f
|
||||
private var overStretchAmount: Float = 0.0f
|
||||
private var mWakeUpHeight: Float = 0.0f
|
||||
private var mReachedWakeUpHeight: Boolean = false
|
||||
private var velocityTracker: VelocityTracker? = null
|
||||
@@ -215,6 +214,7 @@ constructor(
|
||||
|
||||
private fun finishExpansion() {
|
||||
resetClock()
|
||||
val startingChild = mStartingChild
|
||||
if (mStartingChild != null) {
|
||||
setUserLocked(mStartingChild!!, false)
|
||||
mStartingChild = null
|
||||
@@ -225,7 +225,8 @@ constructor(
|
||||
mPowerManager!!.wakeUp(SystemClock.uptimeMillis(), WAKE_REASON_GESTURE,
|
||||
"com.android.systemui:PULSEDRAG")
|
||||
}
|
||||
shadeController.goToLockedShade(mStartingChild)
|
||||
lockscreenShadeTransitionController.goToLockedShade(startingChild,
|
||||
needsQSAnimation = false)
|
||||
leavingLockscreen = true
|
||||
isExpanding = false
|
||||
if (mStartingChild is ExpandableNotificationRow) {
|
||||
@@ -252,8 +253,8 @@ constructor(
|
||||
true /* increaseSpeed */)
|
||||
expansionHeight = max(mWakeUpHeight, expansionHeight)
|
||||
}
|
||||
val emptyDragAmount = wakeUpCoordinator.setPulseHeight(expansionHeight)
|
||||
setEmptyDragAmount(emptyDragAmount * RUBBERBAND_FACTOR_STATIC)
|
||||
val dragDownAmount = wakeUpCoordinator.setPulseHeight(expansionHeight)
|
||||
setOverStretchAmount(dragDownAmount)
|
||||
}
|
||||
|
||||
private fun captureStartingChild(x: Float, y: Float) {
|
||||
@@ -265,9 +266,9 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun setEmptyDragAmount(amount: Float) {
|
||||
mEmptyDragAmount = amount
|
||||
expansionCallback.setEmptyDragAmount(amount)
|
||||
private fun setOverStretchAmount(amount: Float) {
|
||||
overStretchAmount = amount
|
||||
overStretchHandler.setOverStretchAmount(amount)
|
||||
}
|
||||
|
||||
private fun reset(child: ExpandableView) {
|
||||
@@ -294,10 +295,12 @@ constructor(
|
||||
}
|
||||
|
||||
private fun resetClock() {
|
||||
val anim = ValueAnimator.ofFloat(mEmptyDragAmount, 0f)
|
||||
val anim = ValueAnimator.ofFloat(overStretchAmount, 0f)
|
||||
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
|
||||
anim.addUpdateListener { animation -> setEmptyDragAmount(animation.animatedValue as Float) }
|
||||
anim.addUpdateListener {
|
||||
animation -> setOverStretchAmount(animation.animatedValue as Float)
|
||||
}
|
||||
anim.start()
|
||||
}
|
||||
|
||||
@@ -329,11 +332,9 @@ constructor(
|
||||
|
||||
fun setUp(
|
||||
stackScrollerController: NotificationStackScrollLayoutController,
|
||||
expansionCallback: ExpansionCallback,
|
||||
shadeController: ShadeController
|
||||
overStrechHandler: OverStretchHandler
|
||||
) {
|
||||
this.expansionCallback = expansionCallback
|
||||
this.shadeController = shadeController
|
||||
this.overStretchHandler = overStrechHandler
|
||||
this.stackScrollerController = stackScrollerController
|
||||
}
|
||||
|
||||
@@ -345,7 +346,11 @@ constructor(
|
||||
isWakingToShadeLocked = false
|
||||
}
|
||||
|
||||
interface ExpansionCallback {
|
||||
fun setEmptyDragAmount(amount: Float)
|
||||
interface OverStretchHandler {
|
||||
|
||||
/**
|
||||
* Set the overstretch amount in pixels This will be rubberbanded later
|
||||
*/
|
||||
fun setOverStretchAmount(amount: Float)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ public class AmbientState {
|
||||
|
||||
/** Height of the notifications panel without top padding when expansion completes. */
|
||||
private float mStackEndHeight;
|
||||
private float mTransitionToFullShadeAmount;
|
||||
|
||||
/**
|
||||
* @return Height of the notifications panel without top padding when expansion completes.
|
||||
@@ -594,6 +595,21 @@ public class AmbientState {
|
||||
mTrackedHeadsUpRow = row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of pixels we have currently dragged down if we're transitioning to the full
|
||||
* shade. 0.0f means we're not transitioning yet.
|
||||
*/
|
||||
public void setTransitionToFullShadeAmount(float transitionToFullShadeAmount) {
|
||||
mTransitionToFullShadeAmount = transitionToFullShadeAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* get
|
||||
*/
|
||||
public float getTransitionToFullShadeAmount() {
|
||||
return mTransitionToFullShadeAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently tracked heads up row, if there is one and it is currently above the
|
||||
* shelf (still appearing).
|
||||
|
||||
@@ -46,7 +46,6 @@ import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.util.Pair;
|
||||
@@ -71,17 +70,14 @@ import android.widget.ScrollView;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.graphics.ColorUtils;
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.keyguard.KeyguardSliceView;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.ExpandHelper;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
|
||||
import com.android.systemui.statusbar.EmptyShadeView;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
@@ -89,7 +85,6 @@ import com.android.systemui.statusbar.NotificationShelf;
|
||||
import com.android.systemui.statusbar.NotificationShelfController;
|
||||
import com.android.systemui.statusbar.RemoteInputController;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
|
||||
import com.android.systemui.statusbar.notification.FakeShadowView;
|
||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
||||
@@ -108,9 +103,6 @@ import com.android.systemui.statusbar.notification.row.ForegroundServiceDungeonV
|
||||
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
|
||||
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
|
||||
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
|
||||
import com.android.systemui.statusbar.phone.ShadeController;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpUtil;
|
||||
@@ -151,7 +143,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
*/
|
||||
private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1;
|
||||
private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
|
||||
private final SysuiStatusBarStateController mStatusbarStateController;
|
||||
|
||||
private ExpandHelper mExpandHelper;
|
||||
private NotificationSwipeHelper mSwipeHelper;
|
||||
@@ -433,13 +424,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
private ShadeController mShadeController;
|
||||
private Runnable mOnStackYChanged;
|
||||
|
||||
private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class);
|
||||
private final LockscreenGestureLogger mLockscreenGestureLogger =
|
||||
Dependency.get(LockscreenGestureLogger.class);
|
||||
protected boolean mClearAllEnabled;
|
||||
|
||||
private Interpolator mHideXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
|
||||
private NotificationPanelViewController mNotificationPanelController;
|
||||
|
||||
private final NotificationSectionsManager mSectionsManager;
|
||||
private ForegroundServiceDungeonView mFgsSectionView;
|
||||
@@ -449,6 +436,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
private boolean mWillExpand;
|
||||
private int mGapHeight;
|
||||
|
||||
/**
|
||||
* The extra inset during the full shade transition
|
||||
*/
|
||||
private float mExtraTopInsetForFullShadeTransition;
|
||||
|
||||
private int mWaterfallTopInset;
|
||||
private NotificationStackScrollLayoutController mController;
|
||||
|
||||
@@ -496,7 +488,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
NotificationSectionsManager notificationSectionsManager,
|
||||
GroupMembershipManager groupMembershipManager,
|
||||
GroupExpansionManager groupExpansionManager,
|
||||
SysuiStatusBarStateController statusbarStateController,
|
||||
AmbientState ambientState,
|
||||
FeatureFlags featureFlags) {
|
||||
super(context, attrs, 0, 0);
|
||||
@@ -535,7 +526,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
|
||||
mGroupMembershipManager = groupMembershipManager;
|
||||
mGroupExpansionManager = groupExpansionManager;
|
||||
mStatusbarStateController = statusbarStateController;
|
||||
}
|
||||
|
||||
void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) {
|
||||
@@ -1142,8 +1132,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
*/
|
||||
private void updateStackPosition() {
|
||||
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
|
||||
float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition;
|
||||
final float fraction = mAmbientState.getExpansionFraction();
|
||||
final float stackY = MathUtils.lerp(0, mTopPadding, fraction);
|
||||
final float stackY = MathUtils.lerp(0, endTopPosition, fraction);
|
||||
mAmbientState.setStackY(stackY);
|
||||
if (mOnStackYChanged != null) {
|
||||
mOnStackYChanged.run();
|
||||
@@ -4278,6 +4269,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
+ mGapHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the padding after the media header on the lockscreen
|
||||
*/
|
||||
public int getPaddingAfterMedia() {
|
||||
return mGapHeight + mPaddingBetweenElements;
|
||||
}
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
public int getEmptyShadeViewHeight() {
|
||||
return mEmptyShadeView.getHeight();
|
||||
@@ -4933,12 +4931,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
getChildCount() - offsetFromEnd);
|
||||
}
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
public void setNotificationPanelController(
|
||||
NotificationPanelViewController notificationPanelViewController) {
|
||||
mNotificationPanelController = notificationPanelViewController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set how far the wake up is when waking up from pulsing. This is a height and will adjust the
|
||||
* notification positions accordingly.
|
||||
@@ -5154,6 +5146,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
mShadeController = shadeController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the extra top inset for the full shade transition. This is needed to compensate for
|
||||
* media transitioning to quick settings
|
||||
*/
|
||||
public void setExtraTopInsetForFullShadeTransition(float inset) {
|
||||
mExtraTopInsetForFullShadeTransition = inset;
|
||||
updateStackPosition();
|
||||
requestChildrenUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* A listener that is notified when the empty space below the notifications is clicked on
|
||||
*/
|
||||
@@ -5526,108 +5528,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
}
|
||||
}
|
||||
|
||||
public void setKeyguardMediaControllorVisible(boolean keyguardMediaControllorVisible) {
|
||||
mKeyguardMediaControllorVisible = keyguardMediaControllorVisible;
|
||||
}
|
||||
|
||||
void resetCheckSnoozeLeavebehind() {
|
||||
setCheckForLeaveBehind(true);
|
||||
}
|
||||
|
||||
// ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.INPUT)
|
||||
private final DragDownCallback mDragDownCallback = new DragDownCallback() {
|
||||
|
||||
@Override
|
||||
public boolean canDragDown() {
|
||||
return mStatusBarState == StatusBarState.KEYGUARD
|
||||
&& (mController.hasActiveNotifications() || mKeyguardMediaControllorVisible)
|
||||
|| mController.isInLockedDownShade();
|
||||
}
|
||||
|
||||
/* Only ever called as a consequence of a lockscreen expansion gesture. */
|
||||
@Override
|
||||
public void onDraggedDown(View startingChild, int dragLengthY) {
|
||||
boolean canDragDown =
|
||||
mController.hasActiveNotifications() || mKeyguardMediaControllorVisible;
|
||||
if (mStatusBarState == StatusBarState.KEYGUARD && canDragDown) {
|
||||
mLockscreenGestureLogger.write(
|
||||
MetricsEvent.ACTION_LS_SHADE,
|
||||
(int) (dragLengthY / mDisplayMetrics.density),
|
||||
0 /* velocityDp - N/A */);
|
||||
mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_PULL_SHADE_OPEN);
|
||||
|
||||
if (!mAmbientState.isDozing() || startingChild != null) {
|
||||
// We have notifications, go to locked shade.
|
||||
mShadeController.goToLockedShade(startingChild);
|
||||
if (startingChild instanceof ExpandableNotificationRow) {
|
||||
ExpandableNotificationRow row = (ExpandableNotificationRow) startingChild;
|
||||
row.onExpandedByGesture(true /* drag down is always an open */);
|
||||
}
|
||||
}
|
||||
} else if (mController.isInLockedDownShade()) {
|
||||
mStatusbarStateController.setLeaveOpenOnKeyguardHide(true);
|
||||
mStatusBar.dismissKeyguardThenExecute(() -> false /* dismissAction */,
|
||||
null /* cancelRunnable */, false /* afterKeyguardGone */);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragDownReset() {
|
||||
setDimmed(true /* dimmed */, true /* animated */);
|
||||
resetScrollPosition();
|
||||
resetCheckSnoozeLeavebehind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCrossedThreshold(boolean above) {
|
||||
setDimmed(!above /* dimmed */, true /* animate */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTouchSlopExceeded() {
|
||||
cancelLongPress();
|
||||
mController.checkSnoozeLeavebehind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmptyDragAmount(float amount) {
|
||||
mNotificationPanelController.setEmptyDragAmount(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFalsingCheckNeeded() {
|
||||
return mStatusBarState == StatusBarState.KEYGUARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDragDownEnabledForView(ExpandableView view) {
|
||||
if (isDragDownAnywhereEnabled()) {
|
||||
return true;
|
||||
}
|
||||
if (mController.isInLockedDownShade()) {
|
||||
if (view == null) {
|
||||
// Dragging down is allowed in general
|
||||
return true;
|
||||
}
|
||||
if (view instanceof ExpandableNotificationRow) {
|
||||
// Only drag down on sensitive views, otherwise the ExpandHelper will take this
|
||||
return ((ExpandableNotificationRow) view).getEntry().isSensitive();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDragDownAnywhereEnabled() {
|
||||
return mStatusbarStateController.getState() == StatusBarState.KEYGUARD
|
||||
&& !mKeyguardBypassEnabledProvider.getBypassEnabled();
|
||||
}
|
||||
};
|
||||
|
||||
public DragDownCallback getDragDownCallback() { return mDragDownCallback; }
|
||||
|
||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||
private final HeadsUpTouchHelper.Callback mHeadsUpCallback = new HeadsUpTouchHelper.Callback() {
|
||||
@Override
|
||||
|
||||
@@ -31,6 +31,7 @@ import static com.android.systemui.statusbar.notification.stack.NotificationStac
|
||||
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.canChildBeDismissed;
|
||||
import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
@@ -38,6 +39,7 @@ import android.provider.Settings;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.util.Pair;
|
||||
import android.view.Display;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -59,6 +61,7 @@ import com.android.systemui.ExpandHelper;
|
||||
import com.android.systemui.Gefingerpoken;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SwipeHelper;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.classifier.Classifier;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||
@@ -70,6 +73,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEv
|
||||
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
@@ -107,7 +111,6 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
|
||||
import com.android.systemui.statusbar.phone.ScrimController;
|
||||
import com.android.systemui.statusbar.phone.ShadeController;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
@@ -168,6 +171,7 @@ public class NotificationStackScrollLayoutController {
|
||||
// TODO: StatusBar should be encapsulated behind a Controller
|
||||
private final StatusBar mStatusBar;
|
||||
private final SectionHeaderController mSilentHeaderController;
|
||||
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
|
||||
private NotificationStackScrollLayout mView;
|
||||
private boolean mFadeNotificationsOnDismiss;
|
||||
@@ -181,6 +185,9 @@ public class NotificationStackScrollLayoutController {
|
||||
|
||||
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
|
||||
|
||||
private int mTotalDistanceForFullShadeTransition;
|
||||
private int mTotalExtraMediaInsetFullShadeTransition;
|
||||
|
||||
@VisibleForTesting
|
||||
final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
|
||||
new View.OnAttachStateChangeListener() {
|
||||
@@ -240,8 +247,20 @@ public class NotificationStackScrollLayoutController {
|
||||
public void onThemeChanged() {
|
||||
updateFooter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigChanged(Configuration newConfig) {
|
||||
updateResources();
|
||||
}
|
||||
};
|
||||
|
||||
private void updateResources() {
|
||||
mTotalExtraMediaInsetFullShadeTransition = mResources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_transition_extra_media_inset);
|
||||
mTotalDistanceForFullShadeTransition = mResources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_qs_transition_distance);
|
||||
}
|
||||
|
||||
private final StatusBarStateController.StateListener mStateListener =
|
||||
new StatusBarStateController.StateListener() {
|
||||
@Override
|
||||
@@ -571,6 +590,7 @@ public class NotificationStackScrollLayoutController {
|
||||
NotifPipeline notifPipeline,
|
||||
NotifCollection notifCollection,
|
||||
NotificationEntryManager notificationEntryManager,
|
||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||
IStatusBarService iStatusBarService,
|
||||
UiEventLogger uiEventLogger,
|
||||
ForegroundServiceDismissalFeatureController fgFeatureController,
|
||||
@@ -592,6 +612,7 @@ public class NotificationStackScrollLayoutController {
|
||||
mZenModeController = zenModeController;
|
||||
mLockscreenUserManager = lockscreenUserManager;
|
||||
mMetricsLogger = metricsLogger;
|
||||
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||
mFalsingCollector = falsingCollector;
|
||||
mFalsingManager = falsingManager;
|
||||
mResources = resources;
|
||||
@@ -624,6 +645,7 @@ public class NotificationStackScrollLayoutController {
|
||||
mRemoteInputManager = remoteInputManager;
|
||||
mVisualStabilityManager = visualStabilityManager;
|
||||
mShadeController = shadeController;
|
||||
updateResources();
|
||||
}
|
||||
|
||||
public void attach(NotificationStackScrollLayout view) {
|
||||
@@ -676,6 +698,8 @@ public class NotificationStackScrollLayoutController {
|
||||
|
||||
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
|
||||
|
||||
mLockscreenShadeTransitionController.setStackScroller(this);
|
||||
|
||||
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
|
||||
|
||||
mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly
|
||||
@@ -705,7 +729,6 @@ public class NotificationStackScrollLayoutController {
|
||||
Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
|
||||
|
||||
mKeyguardMediaController.setVisibilityChangedListener(visible -> {
|
||||
mView.setKeyguardMediaControllorVisible(visible);
|
||||
if (visible) {
|
||||
mView.generateAddAnimation(
|
||||
mKeyguardMediaController.getSinglePaneContainer(),
|
||||
@@ -1203,11 +1226,6 @@ public class NotificationStackScrollLayoutController {
|
||||
mView.runAfterAnimationFinished(r);
|
||||
}
|
||||
|
||||
public void setNotificationPanelController(
|
||||
NotificationPanelViewController notificationPanelViewController) {
|
||||
mView.setNotificationPanelController(notificationPanelViewController);
|
||||
}
|
||||
|
||||
public void setShelfController(NotificationShelfController notificationShelfController) {
|
||||
mView.setShelfController(notificationShelfController);
|
||||
}
|
||||
@@ -1275,7 +1293,10 @@ public class NotificationStackScrollLayoutController {
|
||||
NotificationLogger.getNotificationLocation(entry)));
|
||||
}
|
||||
|
||||
boolean hasActiveNotifications() {
|
||||
/**
|
||||
* @return if the shade has currently any active notifications.
|
||||
*/
|
||||
public boolean hasActiveNotifications() {
|
||||
if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
|
||||
return !mNotifPipeline.getShadeList().isEmpty();
|
||||
} else {
|
||||
@@ -1354,10 +1375,59 @@ public class NotificationStackScrollLayoutController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expand helper callback.
|
||||
*/
|
||||
public ExpandHelper.Callback getExpandHelperCallback() {
|
||||
return mView.getExpandHelperCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If the shade is in the locked down shade.
|
||||
*/
|
||||
public boolean isInLockedDownShade() {
|
||||
return mDynamicPrivacyController.isInLockedDownShade();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the dimmed state for all of the notification views.
|
||||
*/
|
||||
public void setDimmed(boolean dimmed, boolean animate) {
|
||||
mView.setDimmed(dimmed, animate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the inset during the full shade transition, that needs to be added to the position
|
||||
* of the quick settings edge. This is relevant for media, that is transitioning
|
||||
* from the keyguard host to the quick settings one.
|
||||
*/
|
||||
public int getFullShadeTransitionInset() {
|
||||
MediaHeaderView view = mKeyguardMediaController.getSinglePaneContainer();
|
||||
if (view == null || view.getHeight() == 0
|
||||
|| mStatusBarStateController.getState() != KEYGUARD) {
|
||||
return 0;
|
||||
}
|
||||
return view.getHeight() + mView.getPaddingAfterMedia();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of pixels we have currently dragged down if we're transitioning to the full
|
||||
* shade. 0.0f means we're not transitioning yet.
|
||||
*/
|
||||
public void setTransitionToFullShadeAmount(float amount) {
|
||||
float extraTopInset;
|
||||
MediaHeaderView view = mKeyguardMediaController.getSinglePaneContainer();
|
||||
if (view == null || view.getHeight() == 0
|
||||
|| mStatusBarStateController.getState() != KEYGUARD) {
|
||||
extraTopInset = 0;
|
||||
} else {
|
||||
extraTopInset = MathUtils.saturate(amount / mTotalDistanceForFullShadeTransition);
|
||||
extraTopInset = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(extraTopInset);
|
||||
extraTopInset = extraTopInset * mTotalExtraMediaInsetFullShadeTransition;
|
||||
}
|
||||
mView.setExtraTopInsetForFullShadeTransition(extraTopInset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum for UiEvent logged from this class
|
||||
*/
|
||||
|
||||
@@ -251,7 +251,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
super.onFinishInflate();
|
||||
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
|
||||
new ActivityIntentHelper(mContext));
|
||||
mPreviewContainer = findViewById(R.id.preview_container);
|
||||
mOverlayContainer = findViewById(R.id.overlay_container);
|
||||
mRightAffordanceView = findViewById(R.id.camera_button);
|
||||
mLeftAffordanceView = findViewById(R.id.left_button);
|
||||
@@ -268,7 +267,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mKeyguardStateController.addCallback(this);
|
||||
setClipChildren(false);
|
||||
setClipToPadding(false);
|
||||
inflateCameraPreview();
|
||||
mRightAffordanceView.setOnClickListener(this);
|
||||
mLeftAffordanceView.setOnClickListener(this);
|
||||
initAccessibility();
|
||||
@@ -276,13 +274,21 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
mFlashlightController = Dependency.get(FlashlightController.class);
|
||||
mAccessibilityController = Dependency.get(AccessibilityController.class);
|
||||
mActivityIntentHelper = new ActivityIntentHelper(getContext());
|
||||
updateLeftAffordance();
|
||||
|
||||
mIndicationPadding = getResources().getDimensionPixelSize(
|
||||
R.dimen.keyguard_indication_area_padding);
|
||||
updateWalletVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the container where the previews are rendered.
|
||||
*/
|
||||
public void setPreviewContainer(ViewGroup previewContainer) {
|
||||
mPreviewContainer = previewContainer;
|
||||
inflateCameraPreview();
|
||||
updateLeftAffordance();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
@@ -680,6 +686,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
}
|
||||
|
||||
private void inflateCameraPreview() {
|
||||
if (mPreviewContainer == null) {
|
||||
return;
|
||||
}
|
||||
View previewBefore = mCameraPreview;
|
||||
boolean visibleBefore = false;
|
||||
if (previewBefore != null) {
|
||||
@@ -697,6 +706,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
||||
}
|
||||
|
||||
private void updateLeftPreview() {
|
||||
if (mPreviewContainer == null) {
|
||||
return;
|
||||
}
|
||||
View previewBefore = mLeftPreview;
|
||||
if (previewBefore != null) {
|
||||
mPreviewContainer.removeView(previewBefore);
|
||||
|
||||
@@ -140,7 +140,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
*/
|
||||
private float mQsExpansion;
|
||||
|
||||
private float mEmptyDragAmount;
|
||||
private float mOverStretchAmount;
|
||||
|
||||
/**
|
||||
* Setting if bypass is enabled. If true the clock should always be positioned like it's dark
|
||||
@@ -181,7 +181,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
int notificationStackHeight, float panelExpansion, int parentHeight,
|
||||
int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
|
||||
int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
|
||||
float emptyDragAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
|
||||
float overStrechAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
|
||||
float qsExpansion, int cutoutTopInset, boolean isSplitShade) {
|
||||
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
|
||||
userSwitchHeight);
|
||||
@@ -196,7 +196,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
mHasCustomClock = hasCustomClock;
|
||||
mHasVisibleNotifs = hasVisibleNotifs;
|
||||
mDarkAmount = dark;
|
||||
mEmptyDragAmount = emptyDragAmount;
|
||||
mOverStretchAmount = overStrechAmount;
|
||||
mBypassEnabled = bypassEnabled;
|
||||
mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
|
||||
mQsExpansion = qsExpansion;
|
||||
@@ -301,7 +301,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
}
|
||||
clockYDark = clockY + burnInPreventionOffsetY() + shift;
|
||||
}
|
||||
return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mEmptyDragAmount);
|
||||
return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mOverStretchAmount);
|
||||
}
|
||||
|
||||
private int getUserSwitcherY(float panelExpansion) {
|
||||
@@ -312,7 +312,7 @@ public class KeyguardClockPositionAlgorithm {
|
||||
float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
|
||||
float userSwitchY = MathUtils.lerp(userSwitchYBouncer, userSwitchYRegular, shadeExpansion);
|
||||
|
||||
return (int) (userSwitchY + mEmptyDragAmount);
|
||||
return (int) (userSwitchY + mOverStretchAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -114,6 +114,7 @@ import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.GestureRecorder;
|
||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShelfController;
|
||||
@@ -207,7 +208,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
|
||||
@VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
|
||||
new StatusBarStateListener();
|
||||
private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
|
||||
private final BiometricUnlockController mBiometricUnlockController;
|
||||
private final NotificationPanelView mView;
|
||||
private final VibratorHelper mVibratorHelper;
|
||||
@@ -312,10 +312,12 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
// Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
|
||||
// If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
|
||||
private final int mMaxKeyguardNotifications;
|
||||
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
private boolean mShouldUseSplitNotificationShade;
|
||||
// Current max allowed keyguard notifications determined by measuring the panel
|
||||
private int mMaxAllowedKeyguardNotifications;
|
||||
|
||||
private ViewGroup mPreviewContainer;
|
||||
private KeyguardAffordanceHelper mAffordanceHelper;
|
||||
private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
|
||||
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
|
||||
@@ -365,7 +367,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private int mStatusBarMinHeight;
|
||||
private int mStatusBarHeaderHeightKeyguard;
|
||||
private int mNotificationsHeaderCollideDistance;
|
||||
private float mEmptyDragAmount;
|
||||
private float mOverStretchAmount;
|
||||
private float mDownX;
|
||||
private float mDownY;
|
||||
private int mDisplayCutoutTopInset = 0; // in pixels
|
||||
@@ -481,7 +483,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final NotificationLockscreenUserManager mLockscreenUserManager;
|
||||
private final UserManager mUserManager;
|
||||
private final ShadeController mShadeController;
|
||||
private final MediaDataManager mMediaDataManager;
|
||||
private NotificationShadeDepthController mDepthController;
|
||||
private int mDisplayId;
|
||||
@@ -504,6 +505,39 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private Runnable mExpandAfterLayoutRunnable;
|
||||
private float mSectionPadding;
|
||||
|
||||
/**
|
||||
* The amount of progress we are currently in if we're transitioning to the full shade.
|
||||
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
|
||||
* shade. This value can also go beyond 1.1 when we're overshooting!
|
||||
*/
|
||||
private float mTransitioningToFullShadeProgress;
|
||||
|
||||
/**
|
||||
* Position of the qs bottom during the full shade transition. This is needed as the toppadding
|
||||
* can change during state changes, which makes it much harder to do animations
|
||||
*/
|
||||
private int mTransitionToFullShadeQSPosition;
|
||||
|
||||
/**
|
||||
* Distance that the full shade transition takes in order for qs to fully transition to the
|
||||
* shade.
|
||||
*/
|
||||
private int mDistanceForQSFullShadeTransition;
|
||||
|
||||
/**
|
||||
* The maximum overshoot allowed for the top padding for the full shade transition
|
||||
*/
|
||||
private int mMaxOverscrollAmountForDragDown;
|
||||
|
||||
/**
|
||||
* Should we animate the next bounds update
|
||||
*/
|
||||
private boolean mAnimateNextNotificationBounds;
|
||||
/**
|
||||
* The delay for the next bounds animation
|
||||
*/
|
||||
private long mNotificationBoundsAnimationDelay;
|
||||
|
||||
/**
|
||||
* Is this a collapse that started on the panel where we should allow the panel to intercept
|
||||
*/
|
||||
@@ -521,6 +555,16 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
private boolean mDelayShowingKeyguardStatusBar;
|
||||
|
||||
private boolean mAnimatingQS;
|
||||
|
||||
/**
|
||||
* The end bounds of a clipping animation.
|
||||
*/
|
||||
private final Rect mQsClippingAnimationEndBounds = new Rect();
|
||||
|
||||
/**
|
||||
* The animator for the qs clipping bounds.
|
||||
*/
|
||||
private ValueAnimator mQsClippingAnimation = null;
|
||||
private final Rect mKeyguardStatusAreaClipBounds = new Rect();
|
||||
private int mOldLayoutDirection;
|
||||
private NotificationShelfController mNotificationShelfController;
|
||||
@@ -569,7 +613,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
|
||||
DynamicPrivacyController dynamicPrivacyController,
|
||||
KeyguardBypassController bypassController, FalsingManager falsingManager,
|
||||
FalsingCollector falsingCollector, ShadeController shadeController,
|
||||
FalsingCollector falsingCollector,
|
||||
NotificationLockscreenUserManager notificationLockscreenUserManager,
|
||||
NotificationEntryManager notificationEntryManager,
|
||||
KeyguardStateController keyguardStateController,
|
||||
@@ -591,6 +635,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
KeyguardQsUserSwitchComponent.Factory keyguardQsUserSwitchComponentFactory,
|
||||
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
||||
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
|
||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||
QSDetailDisplayer qsDetailDisplayer,
|
||||
NotificationGroupManagerLegacy groupManager,
|
||||
NotificationIconAreaController notificationIconAreaController,
|
||||
@@ -677,6 +722,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
};
|
||||
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||
lockscreenShadeTransitionController.setNotificationPanelController(this);
|
||||
mKeyguardStateController.addCallback(keyguardMonitorCallback);
|
||||
DynamicPrivacyControlListener
|
||||
dynamicPrivacyControlListener =
|
||||
@@ -690,7 +737,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
});
|
||||
mBottomAreaShadeAlphaAnimator.setDuration(160);
|
||||
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
|
||||
mShadeController = shadeController;
|
||||
mLockscreenUserManager = notificationLockscreenUserManager;
|
||||
mEntryManager = notificationEntryManager;
|
||||
mConversationNotificationManager = conversationNotificationManager;
|
||||
@@ -749,14 +795,22 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mOnEmptySpaceClickListener);
|
||||
addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
|
||||
mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area);
|
||||
mPreviewContainer = mView.findViewById(R.id.preview_container);
|
||||
mKeyguardBottomArea.setPreviewContainer(mPreviewContainer);
|
||||
mLastOrientation = mResources.getConfiguration().orientation;
|
||||
|
||||
initBottomArea();
|
||||
|
||||
mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController);
|
||||
mQsFrame = mView.findViewById(R.id.qs_frame);
|
||||
mPulseExpansionHandler.setUp(
|
||||
mNotificationStackScrollLayoutController, mExpansionCallback, mShadeController);
|
||||
mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController,
|
||||
amount -> {
|
||||
float progress = amount / mView.getHeight();
|
||||
float overstretch = Interpolators.getOvershootInterpolation(progress,
|
||||
(float) mMaxOverscrollAmountForDragDown / mView.getHeight(),
|
||||
0.2f);
|
||||
setOverStrechAmount(overstretch);
|
||||
});
|
||||
mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
|
||||
@Override
|
||||
public void onFullyHiddenChanged(boolean isFullyHidden) {
|
||||
@@ -812,6 +866,10 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
com.android.internal.R.dimen.status_bar_height);
|
||||
mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
|
||||
R.dimen.heads_up_status_bar_padding);
|
||||
mDistanceForQSFullShadeTransition = mResources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_qs_transition_distance);
|
||||
mMaxOverscrollAmountForDragDown = mResources.getDimensionPixelSize(
|
||||
R.dimen.lockscreen_shade_max_top_overshoot);
|
||||
mScrimCornerRadius = mResources.getDimensionPixelSize(
|
||||
R.dimen.notification_scrim_corner_radius);
|
||||
mScreenCornerRadius = mResources.getDimensionPixelSize(
|
||||
@@ -989,6 +1047,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate(
|
||||
R.layout.keyguard_bottom_area, mView, false);
|
||||
mKeyguardBottomArea.initFrom(oldBottomArea);
|
||||
mKeyguardBottomArea.setPreviewContainer(mPreviewContainer);
|
||||
mView.addView(mKeyguardBottomArea, index);
|
||||
initBottomArea();
|
||||
mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
|
||||
@@ -1108,58 +1167,28 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
* showing.
|
||||
*/
|
||||
private void positionClockAndNotifications() {
|
||||
positionClockAndNotifications(false /* forceUpdate */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Positions the clock and notifications dynamically depending on how many notifications are
|
||||
* showing.
|
||||
*
|
||||
* @param forceClockUpdate Should the clock be updated even when not on keyguard
|
||||
*/
|
||||
private void positionClockAndNotifications(boolean forceClockUpdate) {
|
||||
boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
|
||||
boolean animateClock = animate || mAnimateNextPositionUpdate;
|
||||
int stackScrollerPadding;
|
||||
if (mBarState != KEYGUARD) {
|
||||
boolean onKeyguard = isOnKeyguard();
|
||||
if (onKeyguard || forceClockUpdate) {
|
||||
updateClockAppearance();
|
||||
}
|
||||
if (!onKeyguard) {
|
||||
stackScrollerPadding = getUnlockedStackScrollerPadding();
|
||||
} else {
|
||||
int totalHeight = mView.getHeight();
|
||||
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
|
||||
int clockPreferredY = mKeyguardStatusViewController.getClockPreferredY(totalHeight);
|
||||
int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard;
|
||||
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
|
||||
final boolean hasVisibleNotifications = mNotificationStackScrollLayoutController
|
||||
.getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia();
|
||||
mKeyguardStatusViewController.setHasVisibleNotifications(hasVisibleNotifications);
|
||||
int userIconHeight = mKeyguardQsUserSwitchController != null
|
||||
? mKeyguardQsUserSwitchController.getUserIconHeight() : 0;
|
||||
mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
|
||||
totalHeight - bottomPadding,
|
||||
mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
|
||||
getExpandedFraction(),
|
||||
totalHeight,
|
||||
mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1
|
||||
? mKeyguardStatusViewController.getHeight()
|
||||
: (int) (mKeyguardStatusViewController.getHeight()
|
||||
- mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
|
||||
userIconHeight,
|
||||
clockPreferredY, userSwitcherPreferredY, hasCustomClock(),
|
||||
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
|
||||
bypassEnabled, getUnlockedStackScrollerPadding(),
|
||||
getQsExpansionFraction(),
|
||||
mDisplayCutoutTopInset,
|
||||
shouldUseSplitNotificationShade(mFeatureFlags, mResources));
|
||||
mClockPositionAlgorithm.run(mClockPositionResult);
|
||||
mKeyguardStatusViewController.updatePosition(
|
||||
mClockPositionResult.clockX, mClockPositionResult.clockY,
|
||||
mClockPositionResult.clockScale, animateClock);
|
||||
if (mKeyguardQsUserSwitchController != null) {
|
||||
mKeyguardQsUserSwitchController.updatePosition(
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.userSwitchY,
|
||||
animateClock);
|
||||
}
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.updatePosition(
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.userSwitchY,
|
||||
animateClock);
|
||||
}
|
||||
updateNotificationTranslucency();
|
||||
updateClock();
|
||||
stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
|
||||
}
|
||||
|
||||
mNotificationStackScrollLayoutController.setIntrinsicPadding(stackScrollerPadding);
|
||||
mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
|
||||
|
||||
@@ -1169,6 +1198,60 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mAnimateNextPositionUpdate = false;
|
||||
}
|
||||
|
||||
private void updateClockAppearance() {
|
||||
int totalHeight = mView.getHeight();
|
||||
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
|
||||
int clockPreferredY = mKeyguardStatusViewController.getClockPreferredY(totalHeight);
|
||||
int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard;
|
||||
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
|
||||
final boolean hasVisibleNotifications = mNotificationStackScrollLayoutController
|
||||
.getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia();
|
||||
mKeyguardStatusViewController.setHasVisibleNotifications(hasVisibleNotifications);
|
||||
int userIconHeight = mKeyguardQsUserSwitchController != null
|
||||
? mKeyguardQsUserSwitchController.getUserIconHeight() : 0;
|
||||
float expandedFraction =
|
||||
mKeyguardStatusViewController.isAnimatingScreenOffFromUnlocked() ? 1.0f
|
||||
: getExpandedFraction();
|
||||
float darkamount = mKeyguardStatusViewController.isAnimatingScreenOffFromUnlocked() ? 1.0f
|
||||
: mInterpolatedDarkAmount;
|
||||
mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
|
||||
totalHeight - bottomPadding,
|
||||
mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
|
||||
expandedFraction,
|
||||
totalHeight,
|
||||
mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1
|
||||
? mKeyguardStatusViewController.getHeight()
|
||||
: (int) (mKeyguardStatusViewController.getHeight()
|
||||
- mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
|
||||
userIconHeight,
|
||||
clockPreferredY, userSwitcherPreferredY, hasCustomClock(),
|
||||
hasVisibleNotifications, darkamount, mOverStretchAmount,
|
||||
bypassEnabled, getUnlockedStackScrollerPadding(),
|
||||
computeQsExpansionFraction(),
|
||||
mDisplayCutoutTopInset,
|
||||
shouldUseSplitNotificationShade(mFeatureFlags, mResources));
|
||||
mClockPositionAlgorithm.run(mClockPositionResult);
|
||||
boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
|
||||
boolean animateClock = animate || mAnimateNextPositionUpdate;
|
||||
mKeyguardStatusViewController.updatePosition(
|
||||
mClockPositionResult.clockX, mClockPositionResult.clockY,
|
||||
mClockPositionResult.clockScale, animateClock);
|
||||
if (mKeyguardQsUserSwitchController != null) {
|
||||
mKeyguardQsUserSwitchController.updatePosition(
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.userSwitchY,
|
||||
animateClock);
|
||||
}
|
||||
if (mKeyguardUserSwitcherController != null) {
|
||||
mKeyguardUserSwitcherController.updatePosition(
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.userSwitchY,
|
||||
animateClock);
|
||||
}
|
||||
updateNotificationTranslucency();
|
||||
updateClock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the padding of the stackscroller when unlocked
|
||||
*/
|
||||
@@ -1600,7 +1683,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
|
||||
private boolean flingExpandsQs(float vel) {
|
||||
if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
|
||||
return getQsExpansionFraction() > 0.5f;
|
||||
return computeQsExpansionFraction() > 0.5f;
|
||||
} else {
|
||||
return vel > 0;
|
||||
}
|
||||
@@ -1613,7 +1696,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
return !mQsTouchAboveFalsingThreshold;
|
||||
}
|
||||
|
||||
private float getQsExpansionFraction() {
|
||||
private float computeQsExpansionFraction() {
|
||||
return Math.min(
|
||||
1f, (mQsExpansionHeight - mQsMinExpansionHeight) / (mQsMaxExpansionHeight
|
||||
- mQsMinExpansionHeight));
|
||||
@@ -1838,7 +1921,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mQsTracking = false;
|
||||
mTrackingPointer = -1;
|
||||
trackMovement(event);
|
||||
float fraction = getQsExpansionFraction();
|
||||
float fraction = computeQsExpansionFraction();
|
||||
if (fraction != 0f || y >= mInitialTouchY) {
|
||||
flingQsWithCurrentVelocity(y,
|
||||
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
|
||||
@@ -2044,18 +2127,19 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
|
||||
protected void updateQsExpansion() {
|
||||
if (mQs == null) return;
|
||||
float qsExpansionFraction = getQsExpansionFraction();
|
||||
float qsExpansionFraction = computeQsExpansionFraction();
|
||||
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
|
||||
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
|
||||
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
|
||||
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
|
||||
setQSClippingBounds();
|
||||
mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
|
||||
mDepthController.setQsPanelExpansion(qsExpansionFraction);
|
||||
}
|
||||
|
||||
private Runnable mOnStackYChanged = () -> {
|
||||
if (mQs != null) {
|
||||
setNotificationBounds();
|
||||
setQSClippingBounds();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2063,57 +2147,121 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
|
||||
* and QS state.
|
||||
*/
|
||||
private void setNotificationBounds() {
|
||||
private void setQSClippingBounds() {
|
||||
int top = 0;
|
||||
int bottom = 0;
|
||||
int left = 0;
|
||||
int right = 0;
|
||||
|
||||
final int qsPanelBottomY = calculateQsBottomPosition(getQsExpansionFraction());
|
||||
final boolean visible = (getQsExpansionFraction() > 0 || qsPanelBottomY > 0)
|
||||
final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
|
||||
final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0)
|
||||
&& !mShouldUseSplitNotificationShade;
|
||||
final float notificationTop = mAmbientState.getStackY() - mAmbientState.getScrollY();
|
||||
setQsExpansionEnabled(mAmbientState.getScrollY() == 0);
|
||||
|
||||
int radius = mScrimCornerRadius;
|
||||
if (!mShouldUseSplitNotificationShade) {
|
||||
top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
|
||||
: notificationTop);
|
||||
if (mTransitioningToFullShadeProgress > 0.0f) {
|
||||
// If we're transitioning, let's use the actual value. The else case
|
||||
// can be wrong during transitions when waiting for the keyguard to unlock
|
||||
top = mTransitionToFullShadeQSPosition;
|
||||
} else {
|
||||
float notificationTop = getQSEdgePosition();
|
||||
top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
|
||||
: notificationTop);
|
||||
}
|
||||
bottom = getView().getBottom();
|
||||
left = getView().getLeft();
|
||||
right = getView().getRight();
|
||||
radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius,
|
||||
Math.min(top / (float) mScrimCornerRadius, 1f));
|
||||
} else if (qsPanelBottomY > 0) { // so bounds are empty on lockscreen
|
||||
top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding);
|
||||
bottom = mNotificationStackScrollLayoutController.getHeight();
|
||||
left = mNotificationStackScrollLayoutController.getLeft();
|
||||
right = mNotificationStackScrollLayoutController.getRight();
|
||||
}
|
||||
applyQSClippingBounds(left, top, right, bottom, visible);
|
||||
}
|
||||
|
||||
// Fancy clipping for quick settings
|
||||
if (mQs != null) {
|
||||
mQs.setFancyClipping(top, bottom, radius, visible);
|
||||
private void applyQSClippingBounds(int left, int top, int right, int bottom,
|
||||
boolean visible) {
|
||||
if (!mAnimateNextNotificationBounds || mKeyguardStatusAreaClipBounds.isEmpty()) {
|
||||
if (mQsClippingAnimation != null) {
|
||||
// update the end position of the animator
|
||||
mQsClippingAnimationEndBounds.set(left, top, right, bottom);
|
||||
} else {
|
||||
applyQSClippingImmediately(left, top, right, bottom, visible);
|
||||
}
|
||||
} else {
|
||||
mQsClippingAnimationEndBounds.set(left, top, right, bottom);
|
||||
final int startLeft = mKeyguardStatusAreaClipBounds.left;
|
||||
final int startTop = mKeyguardStatusAreaClipBounds.top;
|
||||
final int startRight = mKeyguardStatusAreaClipBounds.right;
|
||||
final int startBottom = mKeyguardStatusAreaClipBounds.bottom;
|
||||
mQsClippingAnimation = ValueAnimator.ofFloat(0.0f, 1.0f);
|
||||
mQsClippingAnimation.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
||||
mQsClippingAnimation.setDuration(
|
||||
StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
|
||||
mQsClippingAnimation.setStartDelay(mNotificationBoundsAnimationDelay);
|
||||
mQsClippingAnimation.addUpdateListener(animation -> {
|
||||
float fraction = animation.getAnimatedFraction();
|
||||
int animLeft = (int) MathUtils.lerp(startLeft,
|
||||
mQsClippingAnimationEndBounds.left, fraction);
|
||||
int animTop = (int) MathUtils.lerp(startTop,
|
||||
mQsClippingAnimationEndBounds.top, fraction);
|
||||
int animRight = (int) MathUtils.lerp(startRight,
|
||||
mQsClippingAnimationEndBounds.right, fraction);
|
||||
int animBottom = (int) MathUtils.lerp(startBottom,
|
||||
mQsClippingAnimationEndBounds.bottom, fraction);
|
||||
applyQSClippingImmediately(animLeft, animTop, animRight, animBottom,
|
||||
visible /* visible */);
|
||||
});
|
||||
mQsClippingAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mQsClippingAnimation = null;
|
||||
}
|
||||
});
|
||||
mQsClippingAnimation.start();
|
||||
}
|
||||
mAnimateNextNotificationBounds = false;
|
||||
mNotificationBoundsAnimationDelay = 0;
|
||||
}
|
||||
|
||||
private void applyQSClippingImmediately(int left, int top, int right, int bottom,
|
||||
boolean visible) {
|
||||
// Fancy clipping for quick settings
|
||||
int radius = mScrimCornerRadius;
|
||||
if (!mShouldUseSplitNotificationShade) {
|
||||
// The padding on this area is large enough that we can use a cheaper clipping strategy
|
||||
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
|
||||
mKeyguardStatusViewController.setClipBounds(visible
|
||||
? mKeyguardStatusAreaClipBounds : null);
|
||||
radius = (int) MathUtils.lerp(mScreenCornerRadius, mScrimCornerRadius,
|
||||
Math.min(top / (float) mScrimCornerRadius, 1f));
|
||||
}
|
||||
if (mQs != null) {
|
||||
mQs.setFancyClipping(top, bottom, radius, visible);
|
||||
}
|
||||
mScrimController.setNotificationsBounds(left, top, right, bottom);
|
||||
mScrimController.setScrimCornerRadius(radius);
|
||||
}
|
||||
|
||||
private float getQSEdgePosition() {
|
||||
// TODO: replace StackY with unified calculation
|
||||
return mAmbientState.getStackY() - mAmbientState.getScrollY();
|
||||
}
|
||||
|
||||
private int calculateQsBottomPosition(float qsExpansionFraction) {
|
||||
int qsBottomY = (int) getHeaderTranslation() + mQs.getQsMinExpansionHeight();
|
||||
if (qsExpansionFraction != 0.0) {
|
||||
qsBottomY = (int) MathUtils.lerp(
|
||||
qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
|
||||
if (mTransitioningToFullShadeProgress > 0.0f) {
|
||||
return mTransitionToFullShadeQSPosition;
|
||||
} else {
|
||||
int qsBottomY = (int) getHeaderTranslation() + mQs.getQsMinExpansionHeight();
|
||||
if (qsExpansionFraction != 0.0) {
|
||||
qsBottomY = (int) MathUtils.lerp(
|
||||
qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
|
||||
}
|
||||
// to account for shade overshooting animation, see setSectionPadding method
|
||||
if (mSectionPadding > 0) qsBottomY += mSectionPadding;
|
||||
return qsBottomY;
|
||||
}
|
||||
// to account for shade overshooting animation, see setSectionPadding method
|
||||
if (mSectionPadding > 0) qsBottomY += mSectionPadding;
|
||||
return qsBottomY;
|
||||
}
|
||||
|
||||
private String determineAccessibilityPaneTitle() {
|
||||
@@ -2157,7 +2305,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
// from a scrolled quick settings.
|
||||
return MathUtils.lerp((float) getKeyguardNotificationStaticPadding(),
|
||||
(float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
|
||||
getQsExpansionFraction());
|
||||
computeQsExpansionFraction());
|
||||
} else {
|
||||
return mQsExpansionHeight + mQsNotificationTopPadding;
|
||||
}
|
||||
@@ -2194,15 +2342,65 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateQSPulseExpansion() {
|
||||
if (mQs != null) {
|
||||
mQs.setShowCollapsedOnKeyguard(
|
||||
mQs.setPulseExpanding(
|
||||
mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()
|
||||
&& mNotificationStackScrollLayoutController.isPulseExpanding());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of pixels we have currently dragged down if we're transitioning to the full
|
||||
* shade. 0.0f means we're not transitioning yet.
|
||||
*/
|
||||
public void setTransitionToFullShadeAmount(float pxAmount, boolean animate, long delay) {
|
||||
mAnimateNextNotificationBounds = animate && !mShouldUseSplitNotificationShade;
|
||||
mNotificationBoundsAnimationDelay = delay;
|
||||
float progress = MathUtils.saturate(pxAmount / mView.getHeight());
|
||||
|
||||
float endPosition = 0;
|
||||
if (pxAmount > 0.0f) {
|
||||
if (mNotificationStackScrollLayoutController.getVisibleNotificationCount() == 0
|
||||
&& !mMediaDataManager.hasActiveMedia()) {
|
||||
// No notifications are visible, let's animate to the height of qs instead
|
||||
if (mQs != null) {
|
||||
// Let's interpolate to the header height
|
||||
endPosition = mQs.getHeader().getHeight();
|
||||
}
|
||||
} else {
|
||||
// Interpolating to the new bottom edge position!
|
||||
endPosition = getQSEdgePosition() - mOverStretchAmount;
|
||||
|
||||
// If we have media, we need to put the boundary below it, as the media header
|
||||
// still uses the space during the transition.
|
||||
endPosition +=
|
||||
mNotificationStackScrollLayoutController.getFullShadeTransitionInset();
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the overshoot amount such that we're reaching the target after our desired
|
||||
// distance, but only reach it fully once we drag a full shade length.
|
||||
float transitionProgress = 0;
|
||||
if (endPosition != 0 && progress != 0) {
|
||||
transitionProgress = Interpolators.getOvershootInterpolation(progress,
|
||||
mMaxOverscrollAmountForDragDown / endPosition,
|
||||
(float) mDistanceForQSFullShadeTransition / (float) mView.getHeight());
|
||||
}
|
||||
mTransitioningToFullShadeProgress = transitionProgress;
|
||||
|
||||
int position = (int) MathUtils.lerp((float) 0, endPosition,
|
||||
mTransitioningToFullShadeProgress);
|
||||
if (mTransitioningToFullShadeProgress > 0.0f) {
|
||||
// we want at least 1 pixel otherwise the panel won't be clipped
|
||||
position = Math.max(1, position);
|
||||
}
|
||||
float overStretchAmount = Math.max(position - endPosition, 0.0f);
|
||||
setOverStrechAmount(overStretchAmount);
|
||||
mTransitionToFullShadeQSPosition = position;
|
||||
updateQsExpansion();
|
||||
}
|
||||
|
||||
private void trackMovement(MotionEvent event) {
|
||||
if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
|
||||
}
|
||||
@@ -2626,7 +2824,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
if (!mKeyguardShowing) {
|
||||
return;
|
||||
}
|
||||
float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
|
||||
float alphaQsExpansion = 1 - Math.min(1, computeQsExpansionFraction() * 2);
|
||||
float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
|
||||
* mKeyguardStatusBarAnimateAlpha;
|
||||
newAlpha *= 1.0f - mKeyguardHeadsUpShowingAmount;
|
||||
@@ -2649,7 +2847,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
float expansionAlpha = MathUtils.map(
|
||||
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
|
||||
getExpandedFraction());
|
||||
float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
|
||||
float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction());
|
||||
alpha *= mBottomAreaShadeAlpha;
|
||||
mKeyguardBottomArea.setAffordanceAlpha(alpha);
|
||||
mKeyguardBottomArea.setImportantForAccessibility(
|
||||
@@ -2671,7 +2869,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
float expansionAlpha = MathUtils.map(
|
||||
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
|
||||
getExpandedFraction());
|
||||
float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
|
||||
float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction());
|
||||
mBigClockContainer.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@@ -3223,6 +3421,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mHeightListener.onQsHeightChanged();
|
||||
}
|
||||
});
|
||||
mLockscreenShadeTransitionController.setQS(mQs);
|
||||
mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView());
|
||||
updateQsExpansion();
|
||||
}
|
||||
@@ -3460,9 +3659,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
StatusBar statusBar,
|
||||
NotificationShelfController notificationShelfController) {
|
||||
setStatusBar(statusBar);
|
||||
mNotificationStackScrollLayoutController.setNotificationPanelController(this);
|
||||
mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
|
||||
mNotificationShelfController = notificationShelfController;
|
||||
mLockscreenShadeTransitionController.bindController(notificationShelfController);
|
||||
updateMaxDisplayedNotifications(true);
|
||||
}
|
||||
|
||||
@@ -3513,10 +3712,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
return new OnLayoutChangeListener();
|
||||
}
|
||||
|
||||
public void setEmptyDragAmount(float amount) {
|
||||
mExpansionCallback.setEmptyDragAmount(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TouchHandler createTouchHandler() {
|
||||
return new TouchHandler() {
|
||||
@@ -3985,7 +4180,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
mClockPositionResult.clockX,
|
||||
mClockPositionResult.clockYFullyDozing,
|
||||
mClockPositionResult.clockScale,
|
||||
false);
|
||||
false /* animate */);
|
||||
}
|
||||
|
||||
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
|
||||
@@ -4001,11 +4196,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
if (oldState == KEYGUARD && (goingToFullShade
|
||||
|| statusBarState == StatusBarState.SHADE_LOCKED)) {
|
||||
animateKeyguardStatusBarOut();
|
||||
long
|
||||
delay =
|
||||
mBarState == StatusBarState.SHADE_LOCKED ? 0
|
||||
: mKeyguardStateController.calculateGoingToFullShadeDelay();
|
||||
mQs.animateHeaderSlidingIn(delay);
|
||||
updateQSMinHeight();
|
||||
} else if (oldState == StatusBarState.SHADE_LOCKED
|
||||
&& statusBarState == KEYGUARD) {
|
||||
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||
@@ -4052,11 +4243,12 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private class ExpansionCallback implements PulseExpansionHandler.ExpansionCallback {
|
||||
public void setEmptyDragAmount(float amount) {
|
||||
mEmptyDragAmount = amount * 0.2f;
|
||||
positionClockAndNotifications();
|
||||
}
|
||||
/**
|
||||
* Sets the overstretch amount in raw pixels when dragging down.
|
||||
*/
|
||||
public void setOverStrechAmount(float amount) {
|
||||
mOverStretchAmount = amount;
|
||||
positionClockAndNotifications(true /* forceUpdate */);
|
||||
}
|
||||
|
||||
private class OnAttachStateChangeListener implements View.OnAttachStateChangeListener {
|
||||
@@ -4103,11 +4295,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
// Calculate quick setting heights.
|
||||
int oldMaxHeight = mQsMaxExpansionHeight;
|
||||
if (mQs != null) {
|
||||
float previousMin = mQsMinExpansionHeight;
|
||||
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
|
||||
if (mQsExpansionHeight == previousMin) {
|
||||
mQsExpansionHeight = mQsMinExpansionHeight;
|
||||
}
|
||||
updateQSMinHeight();
|
||||
mQsMaxExpansionHeight = mQs.getDesiredHeight();
|
||||
mNotificationStackScrollLayoutController.setMaxTopPadding(
|
||||
mQsMaxExpansionHeight + mQsNotificationTopPadding);
|
||||
@@ -4149,6 +4337,14 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateQSMinHeight() {
|
||||
float previousMin = mQsMinExpansionHeight;
|
||||
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
|
||||
if (mQsExpansionHeight == previousMin) {
|
||||
mQsExpansionHeight = mQsMinExpansionHeight;
|
||||
}
|
||||
}
|
||||
|
||||
private class DebugDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -34,15 +34,14 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.ExpandHelper;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.classifier.FalsingCollector;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.doze.DozeLog;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.DragDownHelper;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
@@ -73,7 +72,6 @@ public class NotificationShadeWindowViewController {
|
||||
private final DynamicPrivacyController mDynamicPrivacyController;
|
||||
private final KeyguardBypassController mBypassController;
|
||||
private final PluginManager mPluginManager;
|
||||
private final FalsingManager mFalsingManager;
|
||||
private final FalsingCollector mFalsingCollector;
|
||||
private final TunerService mTunerService;
|
||||
private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
|
||||
@@ -87,6 +85,7 @@ public class NotificationShadeWindowViewController {
|
||||
private final ShadeController mShadeController;
|
||||
private final NotificationShadeDepthController mDepthController;
|
||||
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
|
||||
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
|
||||
private GestureDetector mGestureDetector;
|
||||
@@ -119,7 +118,7 @@ public class NotificationShadeWindowViewController {
|
||||
PulseExpansionHandler pulseExpansionHandler,
|
||||
DynamicPrivacyController dynamicPrivacyController,
|
||||
KeyguardBypassController bypassController,
|
||||
FalsingManager falsingManager,
|
||||
LockscreenShadeTransitionController transitionController,
|
||||
FalsingCollector falsingCollector,
|
||||
PluginManager pluginManager,
|
||||
TunerService tunerService,
|
||||
@@ -143,7 +142,7 @@ public class NotificationShadeWindowViewController {
|
||||
mPulseExpansionHandler = pulseExpansionHandler;
|
||||
mDynamicPrivacyController = dynamicPrivacyController;
|
||||
mBypassController = bypassController;
|
||||
mFalsingManager = falsingManager;
|
||||
mLockscreenShadeTransitionController = transitionController;
|
||||
mFalsingCollector = falsingCollector;
|
||||
mPluginManager = pluginManager;
|
||||
mTunerService = tunerService;
|
||||
@@ -406,11 +405,7 @@ public class NotificationShadeWindowViewController {
|
||||
}
|
||||
});
|
||||
|
||||
ExpandHelper.Callback expandHelperCallback = mStackScrollLayout.getExpandHelperCallback();
|
||||
DragDownHelper.DragDownCallback dragDownCallback = mStackScrollLayout.getDragDownCallback();
|
||||
setDragDownHelper(
|
||||
new DragDownHelper(mFalsingManager, expandHelperCallback, dragDownCallback,
|
||||
mFalsingCollector, mView, mView.getContext()));
|
||||
setDragDownHelper(mLockscreenShadeTransitionController.getTouchHelper());
|
||||
|
||||
mDepthController.setRoot(mView);
|
||||
mNotificationPanelViewController.addExpansionListener(mDepthController);
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.os.Handler;
|
||||
import android.os.Trace;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
@@ -42,10 +43,10 @@ import com.android.internal.util.function.TriConsumer;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.DejankUtils;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.animation.Interpolators;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
@@ -98,6 +99,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
public static final int OPAQUE = 2;
|
||||
private boolean mClipsQsScrim;
|
||||
|
||||
/**
|
||||
* The amount of progress we are currently in if we're transitioning to the full shade.
|
||||
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
|
||||
* shade.
|
||||
*/
|
||||
private float mTransitionToFullShadeProgress;
|
||||
|
||||
/**
|
||||
* If we're currently transitioning to the full shade.
|
||||
*/
|
||||
private boolean mTransitioningToFullShade;
|
||||
|
||||
@IntDef(prefix = {"VISIBILITY_"}, value = {
|
||||
TRANSPARENT,
|
||||
SEMI_TRANSPARENT,
|
||||
@@ -357,7 +370,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
+ mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: "
|
||||
+ mNotificationsAlpha);
|
||||
}
|
||||
applyExpansionToAlpha();
|
||||
applyStateToAlpha();
|
||||
|
||||
// Scrim might acquire focus when user is navigating with a D-pad or a keyboard.
|
||||
// We need to disable focus otherwise AOD would end up with a gray overlay.
|
||||
@@ -499,10 +512,37 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
if (!(relevantState && mExpansionAffectsAlpha)) {
|
||||
return;
|
||||
}
|
||||
applyAndDispatchExpansion();
|
||||
applyAndDispatchState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of progress we are currently in if we're transitioning to the full shade.
|
||||
* 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
|
||||
* shade.
|
||||
*/
|
||||
public void setTransitionToFullShadeProgress(float progress) {
|
||||
if (progress != mTransitionToFullShadeProgress) {
|
||||
mTransitionToFullShadeProgress = progress;
|
||||
setTransitionToFullShade(progress > 0.0f);
|
||||
applyAndDispatchState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if we're currently transitioning to the full shade
|
||||
*/
|
||||
private void setTransitionToFullShade(boolean transitioning) {
|
||||
if (transitioning != mTransitioningToFullShade) {
|
||||
mTransitioningToFullShade = transitioning;
|
||||
if (transitioning) {
|
||||
// Let's make sure the shade locked is ready
|
||||
ScrimState.SHADE_LOCKED.prepare(mState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set bounds for notifications background, all coordinates are absolute
|
||||
*/
|
||||
@@ -534,7 +574,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
if (!(relevantState && mExpansionAffectsAlpha)) {
|
||||
return;
|
||||
}
|
||||
applyAndDispatchExpansion();
|
||||
applyAndDispatchState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,6 +593,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
if (mScrimBehind != null) {
|
||||
mScrimBehind.enableBottomEdgeConcave(mClipsQsScrim);
|
||||
}
|
||||
if (mState != ScrimState.UNINITIALIZED) {
|
||||
// the clipScrimState has changed, let's reprepare ourselves
|
||||
mState.prepare(mState);
|
||||
applyAndDispatchState();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -583,7 +628,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
}
|
||||
}
|
||||
|
||||
private void applyExpansionToAlpha() {
|
||||
private void applyStateToAlpha() {
|
||||
if (!mExpansionAffectsAlpha) {
|
||||
return;
|
||||
}
|
||||
@@ -608,47 +653,40 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
mInFrontAlpha = 0;
|
||||
} else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
|
||||
|| mState == ScrimState.PULSING) {
|
||||
// Either darken of make the scrim transparent when you
|
||||
// pull down the shade
|
||||
float interpolatedFract = getInterpolatedFraction();
|
||||
float stateBehind = mClipsQsScrim ? mState.getNotifAlpha() : mState.getBehindAlpha();
|
||||
float backAlpha;
|
||||
if (mDarkenWhileDragging) {
|
||||
backAlpha = MathUtils.lerp(mDefaultScrimAlpha, stateBehind,
|
||||
interpolatedFract);
|
||||
} else {
|
||||
backAlpha = MathUtils.lerp(0 /* start */, stateBehind,
|
||||
interpolatedFract);
|
||||
Pair<Integer, Float> result = calculateBackStateForState(mState);
|
||||
int behindTint = result.first;
|
||||
float behindAlpha = result.second;
|
||||
if (mTransitionToFullShadeProgress > 0.0f) {
|
||||
Pair<Integer, Float> shadeResult = calculateBackStateForState(
|
||||
ScrimState.SHADE_LOCKED);
|
||||
behindAlpha = MathUtils.lerp(behindAlpha, shadeResult.second,
|
||||
mTransitionToFullShadeProgress);
|
||||
behindTint = ColorUtils.blendARGB(behindTint, shadeResult.first,
|
||||
mTransitionToFullShadeProgress);
|
||||
}
|
||||
mInFrontAlpha = mState.getFrontAlpha();
|
||||
int backTint;
|
||||
if (mClipsQsScrim) {
|
||||
backTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
|
||||
mState.getNotifTint(), interpolatedFract);
|
||||
} else {
|
||||
backTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
|
||||
mState.getBehindTint(), interpolatedFract);
|
||||
}
|
||||
if (mQsExpansion > 0) {
|
||||
backAlpha = MathUtils.lerp(backAlpha, mDefaultScrimAlpha, mQsExpansion);
|
||||
int stateTint = mClipsQsScrim ? ScrimState.SHADE_LOCKED.getNotifTint()
|
||||
: ScrimState.SHADE_LOCKED.getBehindTint();
|
||||
backTint = ColorUtils.blendARGB(backTint, stateTint, mQsExpansion);
|
||||
}
|
||||
if (mClipsQsScrim) {
|
||||
mNotificationsAlpha = backAlpha;
|
||||
mNotificationsTint = backTint;
|
||||
mNotificationsAlpha = behindAlpha;
|
||||
mNotificationsTint = behindTint;
|
||||
mBehindAlpha = 1;
|
||||
mBehindTint = Color.BLACK;
|
||||
} else {
|
||||
mBehindAlpha = backAlpha;
|
||||
mBehindAlpha = behindAlpha;
|
||||
if (mState == ScrimState.SHADE_LOCKED) {
|
||||
// going from KEYGUARD to SHADE_LOCKED state
|
||||
mNotificationsAlpha = getInterpolatedFraction();
|
||||
} else {
|
||||
mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion);
|
||||
}
|
||||
mBehindTint = backTint;
|
||||
if (mState == ScrimState.KEYGUARD && mTransitionToFullShadeProgress > 0.0f) {
|
||||
// Interpolate the notification alpha when transitioning!
|
||||
mNotificationsAlpha = MathUtils.lerp(
|
||||
mNotificationsAlpha,
|
||||
getInterpolatedFraction(),
|
||||
mTransitionToFullShadeProgress);
|
||||
}
|
||||
mNotificationsTint = mState.getNotifTint();
|
||||
mBehindTint = behindTint;
|
||||
}
|
||||
}
|
||||
if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha) || isNaN(mNotificationsAlpha)) {
|
||||
@@ -658,8 +696,39 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
}
|
||||
}
|
||||
|
||||
private void applyAndDispatchExpansion() {
|
||||
applyExpansionToAlpha();
|
||||
private Pair<Integer, Float> calculateBackStateForState(ScrimState state) {
|
||||
// Either darken of make the scrim transparent when you
|
||||
// pull down the shade
|
||||
float interpolatedFract = getInterpolatedFraction();
|
||||
float stateBehind = mClipsQsScrim ? state.getNotifAlpha() : state.getBehindAlpha();
|
||||
float behindAlpha;
|
||||
int behindTint;
|
||||
if (mDarkenWhileDragging) {
|
||||
behindAlpha = MathUtils.lerp(mDefaultScrimAlpha, stateBehind,
|
||||
interpolatedFract);
|
||||
} else {
|
||||
behindAlpha = MathUtils.lerp(0 /* start */, stateBehind,
|
||||
interpolatedFract);
|
||||
}
|
||||
if (mClipsQsScrim) {
|
||||
behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
|
||||
state.getNotifTint(), interpolatedFract);
|
||||
} else {
|
||||
behindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
|
||||
state.getBehindTint(), interpolatedFract);
|
||||
}
|
||||
if (mQsExpansion > 0) {
|
||||
behindAlpha = MathUtils.lerp(behindAlpha, mDefaultScrimAlpha, mQsExpansion);
|
||||
int stateTint = mClipsQsScrim ? ScrimState.SHADE_LOCKED.getNotifTint()
|
||||
: ScrimState.SHADE_LOCKED.getBehindTint();
|
||||
behindTint = ColorUtils.blendARGB(behindTint, stateTint, mQsExpansion);
|
||||
}
|
||||
return new Pair<>(behindTint, behindAlpha);
|
||||
}
|
||||
|
||||
|
||||
private void applyAndDispatchState() {
|
||||
applyStateToAlpha();
|
||||
if (mUpdatePending) {
|
||||
return;
|
||||
}
|
||||
@@ -1195,7 +1264,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
||||
public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
|
||||
mExpansionAffectsAlpha = expansionAffectsAlpha;
|
||||
if (expansionAffectsAlpha) {
|
||||
applyAndDispatchExpansion();
|
||||
applyAndDispatchState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
|
||||
/**
|
||||
@@ -77,15 +75,6 @@ public interface ShadeController {
|
||||
*/
|
||||
void runPostCollapseRunnables();
|
||||
|
||||
/**
|
||||
* If secure with redaction: Show bouncer, go to unlocked shade.
|
||||
*
|
||||
* <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
|
||||
*
|
||||
* @param startingChild The view to expand after going to the shade.
|
||||
*/
|
||||
void goToLockedShade(View startingChild);
|
||||
|
||||
/**
|
||||
* Close the shade if it was open
|
||||
*
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
|
||||
@@ -181,12 +180,6 @@ public class ShadeControllerImpl implements ShadeController {
|
||||
mStatusBarKeyguardViewManager.readyForKeyguardDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void goToLockedShade(View startingChild) {
|
||||
// TODO: Move this code out of StatusBar into ShadeController.
|
||||
getStatusBar().goToLockedShade(startingChild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collapsePanel() {
|
||||
if (!getNotificationPanelViewController().isFullyCollapsed()) {
|
||||
|
||||
@@ -194,6 +194,7 @@ import com.android.systemui.statusbar.KeyboardShortcuts;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LiftReveal;
|
||||
import com.android.systemui.statusbar.LightRevealScrim;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationPresenter;
|
||||
@@ -347,6 +348,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
ONLY_CORE_APPS = onlyCoreApps;
|
||||
}
|
||||
|
||||
private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
|
||||
public interface ExpansionChangedListener {
|
||||
void onExpansionChanged(float expansion, boolean expanded);
|
||||
}
|
||||
@@ -438,9 +441,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
|
||||
KeyguardIndicationController mKeyguardIndicationController;
|
||||
|
||||
// RemoteInputView to be activated after unlock
|
||||
private View mPendingRemoteInputView;
|
||||
|
||||
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
|
||||
|
||||
private View mReportRejectedTouch;
|
||||
@@ -650,12 +650,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
private final ScreenLifecycle mScreenLifecycle;
|
||||
private final WakefulnessLifecycle mWakefulnessLifecycle;
|
||||
|
||||
private final View.OnClickListener mGoToLockedShadeListener = v -> {
|
||||
if (mState == StatusBarState.KEYGUARD) {
|
||||
wakeUpIfDozing(SystemClock.uptimeMillis(), v, "SHADE_CLICK");
|
||||
goToLockedShade(null);
|
||||
}
|
||||
};
|
||||
private boolean mNoAnimationOnNextBarModeChange;
|
||||
private final SysuiStatusBarStateController mStatusBarStateController;
|
||||
|
||||
@@ -798,6 +792,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
OngoingCallController ongoingCallController,
|
||||
SystemStatusAnimationScheduler animationScheduler,
|
||||
StatusBarLocationPublisher locationPublisher,
|
||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||
FeatureFlags featureFlags,
|
||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
|
||||
super(context);
|
||||
@@ -882,6 +877,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mAnimationScheduler = animationScheduler;
|
||||
mStatusBarLocationPublisher = locationPublisher;
|
||||
mFeatureFlags = featureFlags;
|
||||
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||
lockscreenShadeTransitionController.setStatusbar(this);
|
||||
|
||||
mExpansionChangedListeners = new ArrayList<>();
|
||||
|
||||
@@ -1422,7 +1419,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mDozeScrimController, mScrimController, mNotificationShadeWindowController,
|
||||
mDynamicPrivacyController, mKeyguardStateController,
|
||||
mKeyguardIndicationController,
|
||||
this /* statusBar */, mShadeController, mCommandQueue, mInitController,
|
||||
this /* statusBar */, mShadeController,
|
||||
mLockscreenShadeTransitionController, mCommandQueue, mInitController,
|
||||
mNotificationInterruptStateProvider);
|
||||
|
||||
mNotificationShelfController.setOnActivatedListener(mPresenter);
|
||||
@@ -1502,7 +1500,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
private void inflateShelf() {
|
||||
mNotificationShelfController = mSuperStatusBarViewFactory
|
||||
.getNotificationShelfController(mStackScroller);
|
||||
mNotificationShelfController.setOnClickListener(mGoToLockedShadeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1675,7 +1672,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
|
||||
&& (mUserSetup || mUserSwitcherController == null
|
||||
|| !mUserSwitcherController.isSimpleUserSwitcher())
|
||||
&& ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0)
|
||||
&& !isShadeDisabled()
|
||||
&& ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
|
||||
&& !mDozing
|
||||
&& !ONLY_CORE_APPS;
|
||||
@@ -1683,6 +1680,10 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
|
||||
}
|
||||
|
||||
public boolean isShadeDisabled() {
|
||||
return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
|
||||
}
|
||||
|
||||
public void addQsTile(ComponentName tile) {
|
||||
if (mQSPanelController != null && mQSPanelController.getHost() != null) {
|
||||
mQSPanelController.getHost().addTile(tile);
|
||||
@@ -3333,7 +3334,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
public void showKeyguard() {
|
||||
mStatusBarStateController.setKeyguardRequested(true);
|
||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
|
||||
mPendingRemoteInputView = null;
|
||||
updateIsKeyguard();
|
||||
mAssistManagerLazy.get().onLockscreenShown();
|
||||
}
|
||||
@@ -3392,11 +3392,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
|
||||
}
|
||||
updatePanelExpansionForKeyguard();
|
||||
if (mDraggedDownEntry != null) {
|
||||
mDraggedDownEntry.setUserLocked(false);
|
||||
mDraggedDownEntry.notifyHeightChanged(false /* needsAnimation */);
|
||||
mDraggedDownEntry = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePanelExpansionForKeyguard() {
|
||||
@@ -3524,11 +3519,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
|
||||
}
|
||||
long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
|
||||
mNotificationPanelViewController.animateToFullShade(delay);
|
||||
if (mDraggedDownEntry != null) {
|
||||
mDraggedDownEntry.setUserLocked(false);
|
||||
mDraggedDownEntry = null;
|
||||
}
|
||||
mLockscreenShadeTransitionController.onHideKeyguard(delay);
|
||||
|
||||
// Disable layout transitions in navbar for this transition because the load is just
|
||||
// too heavy for the CPU and GPU on any device.
|
||||
@@ -3719,6 +3710,22 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding.
|
||||
* @param performAction the action to perform when the bouncer is dismissed.
|
||||
* @param cancelAction the action to perform when unlock is aborted.
|
||||
*/
|
||||
public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
|
||||
Runnable cancelAction) {
|
||||
if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
|
||||
&& !mKeyguardViewMediator.isHiding()) {
|
||||
mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction,
|
||||
false /* afterKeyguardGone */);
|
||||
} else if (cancelAction != null) {
|
||||
cancelAction.run();
|
||||
}
|
||||
}
|
||||
|
||||
void instantCollapseNotificationPanel() {
|
||||
mNotificationPanelViewController.instantCollapse();
|
||||
mShadeController.runPostCollapseRunnables();
|
||||
@@ -3895,47 +3902,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
return mNotificationPanelViewController.getKeyguardBottomAreaView();
|
||||
}
|
||||
|
||||
/**
|
||||
* If secure with redaction: Show bouncer, go to unlocked shade.
|
||||
*
|
||||
* <p>If secure without redaction or no security: Go to {@link StatusBarState#SHADE_LOCKED}.</p>
|
||||
*
|
||||
* @param expandView The view to expand after going to the shade.
|
||||
*/
|
||||
void goToLockedShade(View expandView) {
|
||||
if ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int userId = mLockscreenUserManager.getCurrentUserId();
|
||||
ExpandableNotificationRow row = null;
|
||||
NotificationEntry entry = null;
|
||||
if (expandView instanceof ExpandableNotificationRow) {
|
||||
entry = ((ExpandableNotificationRow) expandView).getEntry();
|
||||
entry.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */);
|
||||
// Indicate that the group expansion is changing at this time -- this way the group
|
||||
// and children backgrounds / divider animations will look correct.
|
||||
entry.setGroupExpansionChanging(true);
|
||||
userId = entry.getSbn().getUserId();
|
||||
}
|
||||
boolean fullShadeNeedsBouncer = !mLockscreenUserManager.
|
||||
userAllowsPrivateNotificationsInPublic(mLockscreenUserManager.getCurrentUserId())
|
||||
|| !mLockscreenUserManager.shouldShowLockscreenNotifications()
|
||||
|| mFalsingCollector.shouldEnforceBouncer();
|
||||
if (mKeyguardBypassController.getBypassEnabled()) {
|
||||
fullShadeNeedsBouncer = false;
|
||||
}
|
||||
if (mLockscreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
|
||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
|
||||
showBouncerIfKeyguard();
|
||||
mDraggedDownEntry = entry;
|
||||
mPendingRemoteInputView = null;
|
||||
} else {
|
||||
mNotificationPanelViewController.animateToFullShade(0 /* delay */);
|
||||
mStatusBarStateController.setState(StatusBarState.SHADE_LOCKED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Propagation of the bouncer state, indicating that it's fully visible.
|
||||
*/
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationPresenter;
|
||||
@@ -112,6 +113,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
private final KeyguardIndicationController mKeyguardIndicationController;
|
||||
private final StatusBar mStatusBar;
|
||||
private final ShadeController mShadeController;
|
||||
private final LockscreenShadeTransitionController mShadeTransitionController;
|
||||
private final CommandQueue mCommandQueue;
|
||||
|
||||
private final AccessibilityManager mAccessibilityManager;
|
||||
@@ -138,6 +140,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
KeyguardIndicationController keyguardIndicationController,
|
||||
StatusBar statusBar,
|
||||
ShadeController shadeController,
|
||||
LockscreenShadeTransitionController shadeTransitionController,
|
||||
CommandQueue commandQueue,
|
||||
InitController initController,
|
||||
NotificationInterruptStateProvider notificationInterruptStateProvider) {
|
||||
@@ -149,6 +152,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
// TODO: use KeyguardStateController#isOccluded to remove this dependency
|
||||
mStatusBar = statusBar;
|
||||
mShadeController = shadeController;
|
||||
mShadeTransitionController = shadeTransitionController;
|
||||
mCommandQueue = commandQueue;
|
||||
mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
|
||||
mNotificationShadeWindowController = notificationShadeWindowController;
|
||||
@@ -394,7 +398,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
||||
mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
|
||||
if (nowExpanded) {
|
||||
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
|
||||
mShadeController.goToLockedShade(clickedEntry.getRow());
|
||||
mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
|
||||
} else if (clickedEntry.isSensitive()
|
||||
&& mDynamicPrivacyController.isInLockedDownShade()) {
|
||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
|
||||
|
||||
@@ -51,6 +51,7 @@ import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
@@ -213,6 +214,7 @@ public interface StatusBarPhoneModule {
|
||||
OngoingCallController ongoingCallController,
|
||||
SystemStatusAnimationScheduler animationScheduler,
|
||||
StatusBarLocationPublisher locationPublisher,
|
||||
LockscreenShadeTransitionController transitionController,
|
||||
FeatureFlags featureFlags,
|
||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
|
||||
return new StatusBar(
|
||||
@@ -299,6 +301,7 @@ public interface StatusBarPhoneModule {
|
||||
ongoingCallController,
|
||||
animationScheduler,
|
||||
locationPublisher,
|
||||
transitionController,
|
||||
featureFlags,
|
||||
keyguardUnlockAnimationController);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.android.systemui.statusbar.StatusBarState
|
||||
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.util.animation.UniqueObjectHostView
|
||||
import org.junit.Assert.assertNotNull
|
||||
@@ -79,6 +80,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
|
||||
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
|
||||
@Mock
|
||||
private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
||||
@Mock
|
||||
private lateinit var configurationController: ConfigurationController
|
||||
@Captor
|
||||
private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)>
|
||||
@Captor
|
||||
@@ -98,6 +101,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
|
||||
bypassController,
|
||||
mediaCarouselController,
|
||||
notificationLockscreenUserManager,
|
||||
configurationController,
|
||||
wakefulnessLifecycle,
|
||||
statusBarKeyguardViewManager)
|
||||
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
package com.android.systemui.statusbar
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import android.util.DisplayMetrics
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.ExpandHelper
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.classifier.FalsingCollector
|
||||
import com.android.systemui.media.MediaHierarchyManager
|
||||
import com.android.systemui.plugins.FalsingManager
|
||||
import com.android.systemui.plugins.qs.QS
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
|
||||
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
|
||||
import com.android.systemui.statusbar.notification.stack.AmbientState
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||
import com.android.systemui.statusbar.phone.LockscreenGestureLogger
|
||||
import com.android.systemui.statusbar.phone.NotificationPanelViewController
|
||||
import com.android.systemui.statusbar.phone.ScrimController
|
||||
import com.android.systemui.statusbar.phone.StatusBar
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.anyBoolean
|
||||
import org.mockito.ArgumentMatchers.anyFloat
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.ArgumentMatchers.anyLong
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito
|
||||
import org.mockito.Mockito.clearInvocations
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
private fun <T> anyObject(): T {
|
||||
return Mockito.anyObject<T>()
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
@RunWithLooper(setAsMainLooper = true)
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
|
||||
|
||||
lateinit var transitionController: LockscreenShadeTransitionController
|
||||
lateinit var row: ExpandableNotificationRow
|
||||
@Mock lateinit var statusbarStateController: SysuiStatusBarStateController
|
||||
@Mock lateinit var lockscreenGestureLogger: LockscreenGestureLogger
|
||||
@Mock lateinit var keyguardBypassController: KeyguardBypassController
|
||||
@Mock lateinit var lockScreenUserManager: NotificationLockscreenUserManager
|
||||
@Mock lateinit var falsingCollector: FalsingCollector
|
||||
@Mock lateinit var ambientState: AmbientState
|
||||
@Mock lateinit var displayMetrics: DisplayMetrics
|
||||
@Mock lateinit var mediaHierarchyManager: MediaHierarchyManager
|
||||
@Mock lateinit var scrimController: ScrimController
|
||||
@Mock lateinit var configurationController: ConfigurationController
|
||||
@Mock lateinit var falsingManager: FalsingManager
|
||||
@Mock lateinit var notificationPanelController: NotificationPanelViewController
|
||||
@Mock lateinit var nsslController: NotificationStackScrollLayoutController
|
||||
@Mock lateinit var featureFlags: FeatureFlags
|
||||
@Mock lateinit var stackscroller: NotificationStackScrollLayout
|
||||
@Mock lateinit var expandHelperCallback: ExpandHelper.Callback
|
||||
@Mock lateinit var statusbar: StatusBar
|
||||
@Mock lateinit var qS: QS
|
||||
@JvmField @Rule val mockito = MockitoJUnit.rule()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val helper = NotificationTestHelper(
|
||||
mContext,
|
||||
mDependency,
|
||||
TestableLooper.get(this))
|
||||
row = helper.createRow()
|
||||
transitionController = LockscreenShadeTransitionController(
|
||||
statusBarStateController = statusbarStateController,
|
||||
lockscreenGestureLogger = lockscreenGestureLogger,
|
||||
keyguardBypassController = keyguardBypassController,
|
||||
lockScreenUserManager = lockScreenUserManager,
|
||||
falsingCollector = falsingCollector,
|
||||
ambientState = ambientState,
|
||||
displayMetrics = displayMetrics,
|
||||
mediaHierarchyManager = mediaHierarchyManager,
|
||||
scrimController = scrimController,
|
||||
featureFlags = featureFlags,
|
||||
context = context,
|
||||
configurationController = configurationController,
|
||||
falsingManager = falsingManager
|
||||
)
|
||||
whenever(nsslController.view).thenReturn(stackscroller)
|
||||
whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback)
|
||||
transitionController.notificationPanelController = notificationPanelController
|
||||
transitionController.statusbar = statusbar
|
||||
transitionController.qS = qS
|
||||
transitionController.setStackScroller(nsslController)
|
||||
whenever(statusbarStateController.state).thenReturn(StatusBarState.KEYGUARD)
|
||||
whenever(nsslController.isInLockedDownShade).thenReturn(false)
|
||||
whenever(qS.isFullyCollapsed).thenReturn(true)
|
||||
whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
|
||||
true)
|
||||
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true)
|
||||
whenever(lockScreenUserManager.isLockscreenPublicMode(anyInt())).thenReturn(true)
|
||||
whenever(falsingCollector.shouldEnforceBouncer()).thenReturn(false)
|
||||
whenever(keyguardBypassController.bypassEnabled).thenReturn(false)
|
||||
clearInvocations(statusbar)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
transitionController.dragDownAnimator?.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCantDragDownWhenQSExpanded() {
|
||||
assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
|
||||
whenever(qS.isFullyCollapsed).thenReturn(false)
|
||||
assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCanDragDownInLockedDownShade() {
|
||||
whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
|
||||
assertFalse("Can drag down in shade locked", transitionController.canDragDown())
|
||||
whenever(nsslController.isInLockedDownShade).thenReturn(true)
|
||||
assertTrue("Can't drag down in locked down shade", transitionController.canDragDown())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGoingToLockedShade() {
|
||||
transitionController.goToLockedShade(null)
|
||||
verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGoToLockedShadeOnlyOnKeyguard() {
|
||||
whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
|
||||
transitionController.goToLockedShade(null)
|
||||
whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE)
|
||||
transitionController.goToLockedShade(null)
|
||||
whenever(statusbarStateController.state).thenReturn(StatusBarState.FULLSCREEN_USER_SWITCHER)
|
||||
transitionController.goToLockedShade(null)
|
||||
verify(statusbarStateController, never()).setState(anyInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDontGoWhenShadeDisabled() {
|
||||
whenever(statusbar.isShadeDisabled).thenReturn(true)
|
||||
transitionController.goToLockedShade(null)
|
||||
verify(statusbarStateController, never()).setState(anyInt())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUserExpandsViewOnGoingToFullShade() {
|
||||
assertFalse("Row shouldn't be user expanded yet", row.isUserExpanded)
|
||||
transitionController.goToLockedShade(row)
|
||||
assertTrue("Row wasn't user expanded on drag down", row.isUserExpanded)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
|
||||
whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
|
||||
false)
|
||||
transitionController.goToLockedShade(null)
|
||||
verify(statusbarStateController, never()).setState(anyInt())
|
||||
verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
|
||||
verify(statusbar).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTriggeringBouncerNoNotificationsOnLockscreen() {
|
||||
whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
|
||||
transitionController.goToLockedShade(null)
|
||||
verify(statusbarStateController, never()).setState(anyInt())
|
||||
verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
|
||||
verify(statusbar).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGoToLockedShadeCreatesQSAnimation() {
|
||||
transitionController.goToLockedShade(null)
|
||||
verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
|
||||
verify(notificationPanelController).animateToFullShade(anyLong())
|
||||
assertNotNull(transitionController.dragDownAnimator)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGoToLockedShadeDoesntCreateQSAnimation() {
|
||||
transitionController.goToLockedShade(null, needsQSAnimation = false)
|
||||
verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
|
||||
verify(notificationPanelController).animateToFullShade(anyLong())
|
||||
assertNull(transitionController.dragDownAnimator)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDragDownAmountDoesntCallOutInLockedDownShade() {
|
||||
whenever(nsslController.isInLockedDownShade).thenReturn(true)
|
||||
transitionController.dragDownAmount = 10f
|
||||
verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat())
|
||||
verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(),
|
||||
anyBoolean(), anyLong())
|
||||
verify(qS, never()).setTransitionToFullShadeAmount(anyFloat(), anyBoolean())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDragDownAmountCallsOut() {
|
||||
transitionController.dragDownAmount = 10f
|
||||
verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
|
||||
verify(scrimController).setTransitionToFullShadeProgress(anyFloat())
|
||||
verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(),
|
||||
anyBoolean(), anyLong())
|
||||
verify(qS).setTransitionToFullShadeAmount(anyFloat(), anyBoolean())
|
||||
}
|
||||
}
|
||||
@@ -142,7 +142,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
|
||||
mNotificationSectionsManager,
|
||||
mGroupMembershipManger,
|
||||
mGroupExpansionManager,
|
||||
mStatusBarStateController,
|
||||
mAmbientState,
|
||||
mFeatureFlags);
|
||||
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
|
||||
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
@@ -121,6 +122,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
|
||||
@Mock private NotificationEntryManager mEntryManager;
|
||||
@Mock private IStatusBarService mIStatusBarService;
|
||||
@Mock private UiEventLogger mUiEventLogger;
|
||||
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
@Mock private ForegroundServiceDismissalFeatureController mFgFeatureController;
|
||||
@Mock private ForegroundServiceSectionController mFgServicesSectionController;
|
||||
@Mock private ForegroundServiceDungeonView mForegroundServiceDungeonView;
|
||||
@@ -173,6 +175,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
|
||||
mNotifPipeline,
|
||||
mNotifCollection,
|
||||
mEntryManager,
|
||||
mLockscreenShadeTransitionController,
|
||||
mIStatusBarService,
|
||||
mUiEventLogger,
|
||||
mFgFeatureController,
|
||||
|
||||
@@ -82,6 +82,7 @@ import com.android.systemui.qs.QSDetailDisplayer;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShelfController;
|
||||
@@ -225,6 +226,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
@Mock
|
||||
private NotificationShadeDepthController mNotificationShadeDepthController;
|
||||
@Mock
|
||||
private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
@Mock
|
||||
private AuthController mAuthController;
|
||||
@Mock
|
||||
private ScrimController mScrimController;
|
||||
@@ -311,7 +314,9 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
mKeyguardBypassController, mHeadsUpManager,
|
||||
mock(NotificationRoundnessManager.class),
|
||||
mStatusBarStateController,
|
||||
new FalsingManagerFake(), new FalsingCollectorFake());
|
||||
new FalsingManagerFake(),
|
||||
mLockscreenShadeTransitionController,
|
||||
new FalsingCollectorFake());
|
||||
when(mKeyguardStatusViewComponentFactory.build(any()))
|
||||
.thenReturn(mKeyguardStatusViewComponent);
|
||||
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
|
||||
@@ -327,7 +332,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
mResources,
|
||||
mLayoutInflater,
|
||||
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
|
||||
new FalsingManagerFake(), new FalsingCollectorFake(), mShadeController,
|
||||
new FalsingManagerFake(), new FalsingCollectorFake(),
|
||||
mNotificationLockscreenUserManager, mNotificationEntryManager,
|
||||
mKeyguardStateController, mStatusBarStateController, mDozeLog,
|
||||
mDozeParameters, mCommandQueue, mVibratorHelper,
|
||||
@@ -341,6 +346,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
mKeyguardQsUserSwitchComponentFactory,
|
||||
mKeyguardUserSwitcherComponentFactory,
|
||||
mKeyguardStatusBarViewComponentFactory,
|
||||
mLockscreenShadeTransitionController,
|
||||
mQSDetailDisplayer,
|
||||
mGroupManager,
|
||||
mNotificationAreaController,
|
||||
|
||||
@@ -31,12 +31,12 @@ import com.android.systemui.R;
|
||||
import com.android.systemui.SystemUIFactory;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.classifier.FalsingCollectorFake;
|
||||
import com.android.systemui.classifier.FalsingManagerFake;
|
||||
import com.android.systemui.dock.DockManager;
|
||||
import com.android.systemui.doze.DozeLog;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.DragDownHelper;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||
@@ -89,6 +89,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
||||
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
|
||||
@Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
|
||||
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -112,7 +113,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
||||
mPulseExpansionHandler,
|
||||
mDynamicPrivacyController,
|
||||
mBypassController,
|
||||
new FalsingManagerFake(),
|
||||
mLockscreenShadeTransitionController,
|
||||
new FalsingCollectorFake(),
|
||||
mPluginManager,
|
||||
mTunerService,
|
||||
|
||||
@@ -41,6 +41,7 @@ import android.graphics.Color;
|
||||
import android.os.Handler;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.util.MathUtils;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -1121,6 +1122,32 @@ public class ScrimControllerTest extends SysuiTestCase {
|
||||
assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.8f, /* expansion */ 0.2f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationTransparency_followsTransitionToFullShade() {
|
||||
mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
|
||||
mScrimController.setPanelExpansion(1.0f);
|
||||
finishAnimationsImmediately();
|
||||
float shadeLockedAlpha = mNotificationsScrim.getViewAlpha();
|
||||
mScrimController.transitionTo(ScrimState.KEYGUARD);
|
||||
mScrimController.setPanelExpansion(1.0f);
|
||||
finishAnimationsImmediately();
|
||||
float keyguardAlpha = mNotificationsScrim.getViewAlpha();
|
||||
|
||||
mScrimController.setClipsQsScrim(true);
|
||||
float progress = 0.5f;
|
||||
mScrimController.setTransitionToFullShadeProgress(progress);
|
||||
assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
|
||||
mNotificationsScrim.getViewAlpha(), 0.2);
|
||||
progress = 0.0f;
|
||||
mScrimController.setTransitionToFullShadeProgress(progress);
|
||||
assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
|
||||
mNotificationsScrim.getViewAlpha(), 0.2);
|
||||
progress = 1.0f;
|
||||
mScrimController.setTransitionToFullShadeProgress(progress);
|
||||
assertEquals(MathUtils.lerp(keyguardAlpha, shadeLockedAlpha, progress),
|
||||
mNotificationsScrim.getViewAlpha(), 0.2);
|
||||
}
|
||||
|
||||
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
|
||||
mScrimController.setPanelExpansion(expansion);
|
||||
finishAnimationsImmediately();
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||
@@ -127,7 +128,8 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
|
||||
mock(NotificationShadeWindowController.class), mock(DynamicPrivacyController.class),
|
||||
mock(KeyguardStateController.class),
|
||||
mock(KeyguardIndicationController.class), mStatusBar,
|
||||
mock(ShadeControllerImpl.class), mCommandQueue, mInitController,
|
||||
mock(ShadeControllerImpl.class), mock(LockscreenShadeTransitionController.class),
|
||||
mCommandQueue, mInitController,
|
||||
mNotificationInterruptStateProvider);
|
||||
mInitController.executePostInitTasks();
|
||||
ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
|
||||
|
||||
@@ -101,6 +101,7 @@ import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.FeatureFlags;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||
import com.android.systemui.statusbar.NotificationListener;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||
@@ -267,6 +268,7 @@ public class StatusBarTest extends SysuiTestCase {
|
||||
@Mock private OngoingCallController mOngoingCallController;
|
||||
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
|
||||
@Mock private StatusBarLocationPublisher mLocationPublisher;
|
||||
@Mock private LockscreenShadeTransitionController mLockscreenTransitionController;
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
@Mock private IWallpaperManager mWallpaperManager;
|
||||
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||
@@ -437,6 +439,7 @@ public class StatusBarTest extends SysuiTestCase {
|
||||
mOngoingCallController,
|
||||
mAnimationScheduler,
|
||||
mLocationPublisher,
|
||||
mLockscreenTransitionController,
|
||||
mFeatureFlags,
|
||||
mKeyguardUnlockAnimationController);
|
||||
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
|
||||
|
||||
Reference in New Issue
Block a user