Merge changes from topic "lockscreen_shade_transition" into sc-dev
* changes: Implemented Lockscreen to shade transition Convert DragDownHelper to Kotlin
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.animation;
|
package com.android.systemui.animation;
|
||||||
|
|
||||||
|
import android.util.MathUtils;
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
import android.view.animation.AccelerateInterpolator;
|
import android.view.animation.AccelerateInterpolator;
|
||||||
import android.view.animation.BounceInterpolator;
|
import android.view.animation.BounceInterpolator;
|
||||||
@@ -71,6 +72,27 @@ public class Interpolators {
|
|||||||
public static final Interpolator TOUCH_RESPONSE_REVERSE =
|
public static final Interpolator TOUCH_RESPONSE_REVERSE =
|
||||||
new PathInterpolator(0.9f, 0f, 0.7f, 1f);
|
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.
|
* Interpolate alpha for notifications background scrim during shade expansion.
|
||||||
* @param fraction Shade expansion fraction
|
* @param fraction Shade expansion fraction
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public interface QS extends FragmentBase {
|
|||||||
|
|
||||||
String ACTION = "com.android.systemui.action.PLUGIN_QS";
|
String ACTION = "com.android.systemui.action.PLUGIN_QS";
|
||||||
|
|
||||||
int VERSION = 8;
|
int VERSION = 9;
|
||||||
|
|
||||||
String TAG = "QS";
|
String TAG = "QS";
|
||||||
|
|
||||||
@@ -50,8 +50,13 @@ public interface QS extends FragmentBase {
|
|||||||
void setListening(boolean listening);
|
void setListening(boolean listening);
|
||||||
boolean isShowingDetail();
|
boolean isShowingDetail();
|
||||||
void closeDetail();
|
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 animateHeaderSlidingOut();
|
||||||
void setQsExpansion(float qsExpansionFraction, float headerTranslation);
|
void setQsExpansion(float qsExpansionFraction, float headerTranslation);
|
||||||
void setHeaderListening(boolean listening);
|
void setHeaderListening(boolean listening);
|
||||||
@@ -78,11 +83,24 @@ public interface QS extends FragmentBase {
|
|||||||
*/
|
*/
|
||||||
void setTranslateWhileExpanding(boolean shouldTranslate);
|
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.
|
* A rounded corner clipping that makes QS feel as if it were behind everything.
|
||||||
*/
|
*/
|
||||||
void setFancyClipping(int top, int bottom, int cornerRadius, boolean visible);
|
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)
|
@ProvidesInterface(version = HeightListener.VERSION)
|
||||||
interface HeightListener {
|
interface HeightListener {
|
||||||
int VERSION = 1;
|
int VERSION = 1;
|
||||||
|
|||||||
@@ -21,8 +21,7 @@
|
|||||||
android:id="@+id/keyguard_bottom_area"
|
android:id="@+id/keyguard_bottom_area"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:outlineProvider="none"
|
android:outlineProvider="none" > <!-- Put it above the status bar header -->
|
||||||
android:elevation="5dp" > <!-- Put it above the status bar header -->
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/keyguard_indication_area"
|
android:id="@+id/keyguard_indication_area"
|
||||||
@@ -58,12 +57,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout
|
|
||||||
android:id="@+id/preview_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
||||||
<com.android.systemui.statusbar.KeyguardAffordanceView
|
<com.android.systemui.statusbar.KeyguardAffordanceView
|
||||||
android:id="@+id/camera_button"
|
android:id="@+id/camera_button"
|
||||||
android:layout_height="@dimen/keyguard_affordance_height"
|
android:layout_height="@dimen/keyguard_affordance_height"
|
||||||
|
|||||||
@@ -37,6 +37,25 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="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
|
<com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@@ -49,6 +68,18 @@
|
|||||||
layout="@layout/keyguard_status_view"
|
layout="@layout/keyguard_status_view"
|
||||||
android:visibility="gone"/>
|
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" />
|
<include layout="@layout/dock_info_overlay" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
@@ -101,22 +132,9 @@
|
|||||||
|
|
||||||
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
|
</com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>
|
||||||
|
|
||||||
<include layout="@layout/dock_info_bottom_area_overlay" />
|
<FrameLayout
|
||||||
|
android:id="@+id/preview_container"
|
||||||
<include
|
android:layout_width="match_parent"
|
||||||
layout="@layout/keyguard_bottom_area"
|
android:layout_height="match_parent">
|
||||||
android:visibility="gone" />
|
</FrameLayout>
|
||||||
|
|
||||||
<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" />
|
|
||||||
</com.android.systemui.statusbar.phone.NotificationPanelView>
|
</com.android.systemui.statusbar.phone.NotificationPanelView>
|
||||||
|
|||||||
@@ -51,14 +51,6 @@
|
|||||||
sysui:ignoreRightInset="true"
|
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
|
<com.android.systemui.statusbar.LightRevealScrim
|
||||||
android:id="@+id/light_reveal_scrim"
|
android:id="@+id/light_reveal_scrim"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -1409,6 +1409,26 @@
|
|||||||
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
<dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
|
||||||
<dimen name="media_output_dialog_title_anim_y_delta">12.5dp</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_widget_radius">28dp</dimen>
|
||||||
<dimen name="people_space_image_radius">20dp</dimen>
|
<dimen name="people_space_image_radius">20dp</dimen>
|
||||||
<dimen name="people_space_messages_count_radius">12dp</dimen>
|
<dimen name="people_space_messages_count_radius">12dp</dimen>
|
||||||
|
|||||||
@@ -197,6 +197,13 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
|
|||||||
animate);
|
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.
|
* 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.animation.Interpolators;
|
||||||
import com.android.systemui.statusbar.StatusBarState;
|
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.notification.stack.StackStateAnimator;
|
||||||
import com.android.systemui.statusbar.phone.DozeParameters;
|
import com.android.systemui.statusbar.phone.DozeParameters;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
@@ -37,6 +40,8 @@ public class KeyguardVisibilityHelper {
|
|||||||
private final DozeParameters mDozeParameters;
|
private final DozeParameters mDozeParameters;
|
||||||
private boolean mKeyguardViewVisibilityAnimating;
|
private boolean mKeyguardViewVisibilityAnimating;
|
||||||
private boolean mLastOccludedState = false;
|
private boolean mLastOccludedState = false;
|
||||||
|
private boolean mAnimatingScreenOff;
|
||||||
|
private final AnimationProperties mAnimationProperties = new AnimationProperties();
|
||||||
|
|
||||||
public KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController,
|
public KeyguardVisibilityHelper(View view, KeyguardStateController keyguardStateController,
|
||||||
DozeParameters dozeParameters) {
|
DozeParameters dozeParameters) {
|
||||||
@@ -89,12 +94,21 @@ public class KeyguardVisibilityHelper {
|
|||||||
} else if (statusBarState == KEYGUARD) {
|
} else if (statusBarState == KEYGUARD) {
|
||||||
if (keyguardFadingAway) {
|
if (keyguardFadingAway) {
|
||||||
mKeyguardViewVisibilityAnimating = true;
|
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()
|
mView.animate()
|
||||||
.alpha(0)
|
.alpha(0)
|
||||||
.translationYBy(-mView.getHeight() * 0.05f)
|
|
||||||
.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
|
.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
|
||||||
.setDuration(125)
|
.setDuration(duration)
|
||||||
.setStartDelay(0)
|
.setStartDelay(delay)
|
||||||
.withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
|
.withEndAction(mAnimateKeyguardStatusViewInvisibleEndRunnable)
|
||||||
.start();
|
.start();
|
||||||
} else if (mLastOccludedState && !isOccluded) {
|
} else if (mLastOccludedState && !isOccluded) {
|
||||||
@@ -110,20 +124,30 @@ public class KeyguardVisibilityHelper {
|
|||||||
.start();
|
.start();
|
||||||
} else if (mDozeParameters.shouldControlUnlockedScreenOff()) {
|
} else if (mDozeParameters.shouldControlUnlockedScreenOff()) {
|
||||||
mKeyguardViewVisibilityAnimating = true;
|
mKeyguardViewVisibilityAnimating = true;
|
||||||
|
mAnimatingScreenOff = true;
|
||||||
|
|
||||||
mView.setVisibility(View.VISIBLE);
|
mView.setVisibility(View.VISIBLE);
|
||||||
mView.setAlpha(0f);
|
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()
|
mView.animate()
|
||||||
.setStartDelay((int) (StackStateAnimator.ANIMATION_DURATION_WAKEUP * .6f))
|
.setStartDelay(delay)
|
||||||
.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
|
.setDuration(duration)
|
||||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
||||||
.alpha(1f)
|
.alpha(1f)
|
||||||
.translationY(curTranslationY)
|
|
||||||
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
|
.withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
|
||||||
.start();
|
.start();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mView.setVisibility(View.VISIBLE);
|
mView.setVisibility(View.VISIBLE);
|
||||||
mView.setAlpha(1f);
|
mView.setAlpha(1f);
|
||||||
@@ -148,5 +172,13 @@ public class KeyguardVisibilityHelper {
|
|||||||
|
|
||||||
private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
|
private final Runnable mAnimateKeyguardStatusViewVisibleEndRunnable = () -> {
|
||||||
mKeyguardViewVisibilityAnimating = false;
|
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;
|
final boolean hasUdfps = mAuthController.getUdfpsSensorLocation() != null;
|
||||||
mHasUdfpsOrFaceAuthFeatures = hasFaceAuth || hasUdfps;
|
mHasUdfpsOrFaceAuthFeatures = hasFaceAuth || hasUdfps;
|
||||||
if (!mHasUdfpsOrFaceAuthFeatures) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,12 @@ class KeyguardMediaController @Inject constructor(
|
|||||||
mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
|
mediaHost.init(MediaHierarchyManager.LOCATION_LOCKSCREEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the media player visible?
|
||||||
|
*/
|
||||||
|
var visible = false
|
||||||
|
private set
|
||||||
|
|
||||||
var visibilityChangedListener: ((Boolean) -> Unit)? = null
|
var visibilityChangedListener: ((Boolean) -> Unit)? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,11 +112,11 @@ class KeyguardMediaController @Inject constructor(
|
|||||||
val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
|
val keyguardOrUserSwitcher = (statusBarStateController.state == StatusBarState.KEYGUARD ||
|
||||||
statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
|
statusBarStateController.state == StatusBarState.FULLSCREEN_USER_SWITCHER)
|
||||||
// mediaHost.visible required for proper animations handling
|
// mediaHost.visible required for proper animations handling
|
||||||
val shouldBeVisible = mediaHost.visible &&
|
visible = mediaHost.visible &&
|
||||||
!bypassController.bypassEnabled &&
|
!bypassController.bypassEnabled &&
|
||||||
keyguardOrUserSwitcher &&
|
keyguardOrUserSwitcher &&
|
||||||
notifLockscreenUserManager.shouldShowLockscreenNotifications()
|
notifLockscreenUserManager.shouldShowLockscreenNotifications()
|
||||||
if (shouldBeVisible) {
|
if (visible) {
|
||||||
showMediaPlayer()
|
showMediaPlayer()
|
||||||
} else {
|
} else {
|
||||||
hideMediaPlayer()
|
hideMediaPlayer()
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.util.MathUtils
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroupOverlay
|
import android.view.ViewGroupOverlay
|
||||||
|
import com.android.systemui.R
|
||||||
import com.android.systemui.animation.Interpolators
|
import com.android.systemui.animation.Interpolators
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.keyguard.WakefulnessLifecycle
|
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.SysuiStatusBarStateController
|
||||||
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
|
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
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.statusbar.policy.KeyguardStateController
|
||||||
import com.android.systemui.util.animation.UniqueObjectHostView
|
import com.android.systemui.util.animation.UniqueObjectHostView
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -74,6 +76,7 @@ class MediaHierarchyManager @Inject constructor(
|
|||||||
private val bypassController: KeyguardBypassController,
|
private val bypassController: KeyguardBypassController,
|
||||||
private val mediaCarouselController: MediaCarouselController,
|
private val mediaCarouselController: MediaCarouselController,
|
||||||
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
|
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
|
||||||
|
configurationController: ConfigurationController,
|
||||||
wakefulnessLifecycle: WakefulnessLifecycle,
|
wakefulnessLifecycle: WakefulnessLifecycle,
|
||||||
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
||||||
) {
|
) {
|
||||||
@@ -182,6 +185,58 @@ class MediaHierarchyManager @Inject constructor(
|
|||||||
mediaCarouselController.mediaCarouselScrollHandler.visibleToUser = isVisibleToUser()
|
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,
|
* 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.
|
* we wouldn't want to transition in that case.
|
||||||
@@ -242,6 +297,12 @@ class MediaHierarchyManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
updateConfiguration()
|
||||||
|
configurationController.addCallback(object : ConfigurationController.ConfigurationListener {
|
||||||
|
override fun onDensityOrFontScaleChanged() {
|
||||||
|
updateConfiguration()
|
||||||
|
}
|
||||||
|
})
|
||||||
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
|
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
|
||||||
override fun onStatePreChange(oldState: Int, newState: Int) {
|
override fun onStatePreChange(oldState: Int, newState: Int) {
|
||||||
// We're updating the location before the state change happens, since we want the
|
// 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
|
* 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.
|
* 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) {
|
if (progress >= 0) {
|
||||||
return progress
|
return progress
|
||||||
}
|
}
|
||||||
|
if (isTransitioningToFullShade) {
|
||||||
|
return fullShadeTransitionProgress
|
||||||
|
}
|
||||||
return -1.0f
|
return -1.0f
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,6 +714,7 @@ class MediaHierarchyManager @Inject constructor(
|
|||||||
val location = when {
|
val location = when {
|
||||||
qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
|
qsExpansion > 0.0f && !onLockscreen -> LOCATION_QS
|
||||||
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
|
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
|
||||||
|
onLockscreen && isTransitioningToFullShade -> LOCATION_QQS
|
||||||
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
|
onLockscreen && allowedOnLockscreen -> LOCATION_LOCKSCREEN
|
||||||
else -> LOCATION_QQS
|
else -> LOCATION_QQS
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,17 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean mTranslateWhileExpanding;
|
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
|
@Inject
|
||||||
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
|
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) {
|
private void setEditLocation(View view) {
|
||||||
View edit = view.findViewById(android.R.id.edit);
|
View edit = view.findViewById(android.R.id.edit);
|
||||||
int[] loc = edit.getLocationOnScreen();
|
int[] loc = edit.getLocationOnScreen();
|
||||||
@@ -335,14 +351,22 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setShowCollapsedOnKeyguard(boolean showCollapsedOnKeyguard) {
|
public void setPulseExpanding(boolean pulseExpanding) {
|
||||||
if (showCollapsedOnKeyguard != mShowCollapsedOnKeyguard) {
|
if (pulseExpanding != mPulseExpanding) {
|
||||||
mShowCollapsedOnKeyguard = showCollapsedOnKeyguard;
|
mPulseExpanding = pulseExpanding;
|
||||||
|
updateShowCollapsedOnKeyguard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateShowCollapsedOnKeyguard() {
|
||||||
|
boolean showCollapsed = mPulseExpanding || mTransitioningToFullShade;
|
||||||
|
if (showCollapsed != mShowCollapsedOnKeyguard) {
|
||||||
|
mShowCollapsedOnKeyguard = showCollapsed;
|
||||||
updateQsState();
|
updateQsState();
|
||||||
if (mQSAnimator != null) {
|
if (mQSAnimator != null) {
|
||||||
mQSAnimator.setShowCollapsedOnKeyguard(showCollapsedOnKeyguard);
|
mQSAnimator.setShowCollapsedOnKeyguard(showCollapsed);
|
||||||
}
|
}
|
||||||
if (!showCollapsedOnKeyguard && isKeyguardShowing()) {
|
if (!showCollapsed && isKeyguardShowing()) {
|
||||||
setQsExpansion(mLastQSExpansion, 0);
|
setQsExpansion(mLastQSExpansion, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -411,13 +435,24 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setQsExpansion(float expansion, float headerTranslation) {
|
public void setTransitionToFullShadeAmount(float pxAmount, boolean animated) {
|
||||||
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
|
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) {
|
if (mQSAnimator != null) {
|
||||||
final boolean showQSOnLockscreen = expansion > 0;
|
final boolean showQSOnLockscreen = expansion > 0;
|
||||||
final boolean showQSUnlocked = headerTranslation == 0 || !mTranslateWhileExpanding;
|
final boolean showQSUnlocked = headerTranslation == 0 || !mTranslateWhileExpanding;
|
||||||
mQSAnimator.startAlphaAnimation(showQSOnLockscreen || showQSUnlocked);
|
mQSAnimator.startAlphaAnimation(showQSOnLockscreen || showQSUnlocked
|
||||||
|
|| mTransitioningToFullShade);
|
||||||
}
|
}
|
||||||
mContainer.setExpansion(expansion);
|
mContainer.setExpansion(expansion);
|
||||||
final float translationScaleY = (mTranslateWhileExpanding
|
final float translationScaleY = (mTranslateWhileExpanding
|
||||||
@@ -541,18 +576,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
&& !isKeyguardShowing();
|
&& !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
|
@Override
|
||||||
public void animateHeaderSlidingOut() {
|
public void animateHeaderSlidingOut() {
|
||||||
if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut");
|
if (DEBUG) Log.d(TAG, "animateHeaderSlidingOut");
|
||||||
|
|||||||
@@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 The Android Open Source Project
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.systemui.statusbar;
|
|
||||||
|
|
||||||
import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN;
|
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorListenerAdapter;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.animation.ValueAnimator;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewConfiguration;
|
|
||||||
|
|
||||||
import com.android.systemui.ExpandHelper;
|
|
||||||
import com.android.systemui.Gefingerpoken;
|
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
import com.android.systemui.classifier.FalsingCollector;
|
|
||||||
import com.android.systemui.plugins.FalsingManager;
|
|
||||||
import com.android.systemui.statusbar.notification.row.ExpandableView;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
public class DragDownHelper implements Gefingerpoken {
|
|
||||||
|
|
||||||
private static final float RUBBERBAND_FACTOR_EXPANDABLE = 0.5f;
|
|
||||||
private static final float RUBBERBAND_FACTOR_STATIC = 0.15f;
|
|
||||||
|
|
||||||
private static final int SPRING_BACK_ANIMATION_LENGTH_MS = 375;
|
|
||||||
|
|
||||||
private int mMinDragDistance;
|
|
||||||
private final FalsingManager mFalsingManager;
|
|
||||||
private ExpandHelper.Callback mCallback;
|
|
||||||
private float mInitialTouchX;
|
|
||||||
private float mInitialTouchY;
|
|
||||||
private boolean mDraggingDown;
|
|
||||||
private final float mTouchSlop;
|
|
||||||
private final float mSlopMultiplier;
|
|
||||||
private DragDownCallback mDragDownCallback;
|
|
||||||
private View mHost;
|
|
||||||
private final int[] mTemp2 = new int[2];
|
|
||||||
private boolean mDraggedFarEnough;
|
|
||||||
private ExpandableView mStartingChild;
|
|
||||||
private float mLastHeight;
|
|
||||||
private FalsingCollector mFalsingCollector;
|
|
||||||
|
|
||||||
public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
|
|
||||||
DragDownCallback dragDownCallback, FalsingManager falsingManager,
|
|
||||||
FalsingCollector falsingCollector) {
|
|
||||||
mMinDragDistance = context.getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.keyguard_drag_down_min_distance);
|
|
||||||
mFalsingManager = falsingManager;
|
|
||||||
final ViewConfiguration configuration = ViewConfiguration.get(context);
|
|
||||||
mTouchSlop = configuration.getScaledTouchSlop();
|
|
||||||
mSlopMultiplier = configuration.getScaledAmbiguousGestureMultiplier();
|
|
||||||
mCallback = callback;
|
|
||||||
mDragDownCallback = dragDownCallback;
|
|
||||||
mHost = host;
|
|
||||||
mFalsingCollector = falsingCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onInterceptTouchEvent(MotionEvent event) {
|
|
||||||
final float x = event.getX();
|
|
||||||
final float y = event.getY();
|
|
||||||
|
|
||||||
switch (event.getActionMasked()) {
|
|
||||||
case MotionEvent.ACTION_DOWN:
|
|
||||||
mDraggedFarEnough = false;
|
|
||||||
mDraggingDown = false;
|
|
||||||
mStartingChild = null;
|
|
||||||
mInitialTouchY = y;
|
|
||||||
mInitialTouchX = x;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
final float h = y - mInitialTouchY;
|
|
||||||
// Adjust the touch slop if another gesture may be being performed.
|
|
||||||
final float touchSlop =
|
|
||||||
event.getClassification() == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE
|
|
||||||
? mTouchSlop * mSlopMultiplier
|
|
||||||
: mTouchSlop;
|
|
||||||
if (h > touchSlop && h > Math.abs(x - mInitialTouchX)) {
|
|
||||||
mFalsingCollector.onNotificationStartDraggingDown();
|
|
||||||
mDraggingDown = true;
|
|
||||||
captureStartingChild(mInitialTouchX, mInitialTouchY);
|
|
||||||
mInitialTouchY = y;
|
|
||||||
mInitialTouchX = x;
|
|
||||||
mDragDownCallback.onTouchSlopExceeded();
|
|
||||||
return mStartingChild != null || mDragDownCallback.isDragDownAnywhereEnabled();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
|
||||||
if (!mDraggingDown) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final float x = event.getX();
|
|
||||||
final float y = event.getY();
|
|
||||||
|
|
||||||
switch (event.getActionMasked()) {
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
mLastHeight = y - mInitialTouchY;
|
|
||||||
captureStartingChild(mInitialTouchX, mInitialTouchY);
|
|
||||||
if (mStartingChild != null) {
|
|
||||||
handleExpansion(mLastHeight, mStartingChild);
|
|
||||||
} else {
|
|
||||||
mDragDownCallback.setEmptyDragAmount(mLastHeight);
|
|
||||||
}
|
|
||||||
if (mLastHeight > mMinDragDistance) {
|
|
||||||
if (!mDraggedFarEnough) {
|
|
||||||
mDraggedFarEnough = true;
|
|
||||||
mDragDownCallback.onCrossedThreshold(true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (mDraggedFarEnough) {
|
|
||||||
mDraggedFarEnough = false;
|
|
||||||
mDragDownCallback.onCrossedThreshold(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case MotionEvent.ACTION_UP:
|
|
||||||
if (!mFalsingManager.isUnlockingDisabled() && mDragDownCallback.canDragDown()
|
|
||||||
&& !isFalseTouch()) {
|
|
||||||
mDragDownCallback.onDraggedDown(mStartingChild, (int) (y - mInitialTouchY));
|
|
||||||
if (mStartingChild == null) {
|
|
||||||
cancelExpansion();
|
|
||||||
} else {
|
|
||||||
mCallback.setUserLockedChild(mStartingChild, false);
|
|
||||||
mStartingChild = null;
|
|
||||||
}
|
|
||||||
mDraggingDown = false;
|
|
||||||
} else {
|
|
||||||
stopDragging();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MotionEvent.ACTION_CANCEL:
|
|
||||||
stopDragging();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isFalseTouch() {
|
|
||||||
if (!mDragDownCallback.isFalsingCheckNeeded()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return mFalsingManager.isFalseTouch(NOTIFICATION_DRAG_DOWN) || !mDraggedFarEnough;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void captureStartingChild(float x, float y) {
|
|
||||||
if (mStartingChild == null) {
|
|
||||||
mStartingChild = findView(x, y);
|
|
||||||
if (mStartingChild != null) {
|
|
||||||
if (mDragDownCallback.isDragDownEnabledForView(mStartingChild)) {
|
|
||||||
mCallback.setUserLockedChild(mStartingChild, true);
|
|
||||||
} else {
|
|
||||||
mStartingChild = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleExpansion(float heightDelta, ExpandableView child) {
|
|
||||||
if (heightDelta < 0) {
|
|
||||||
heightDelta = 0;
|
|
||||||
}
|
|
||||||
boolean expandable = child.isContentExpandable();
|
|
||||||
float rubberbandFactor = expandable
|
|
||||||
? RUBBERBAND_FACTOR_EXPANDABLE
|
|
||||||
: RUBBERBAND_FACTOR_STATIC;
|
|
||||||
float rubberband = heightDelta * rubberbandFactor;
|
|
||||||
if (expandable
|
|
||||||
&& (rubberband + child.getCollapsedHeight()) > child.getMaxContentHeight()) {
|
|
||||||
float overshoot =
|
|
||||||
(rubberband + child.getCollapsedHeight()) - child.getMaxContentHeight();
|
|
||||||
overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
|
|
||||||
rubberband -= overshoot;
|
|
||||||
}
|
|
||||||
child.setActualHeight((int) (child.getCollapsedHeight() + rubberband));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelExpansion(final ExpandableView child) {
|
|
||||||
if (child.getActualHeight() == child.getCollapsedHeight()) {
|
|
||||||
mCallback.setUserLockedChild(child, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
|
|
||||||
child.getActualHeight(), child.getCollapsedHeight());
|
|
||||||
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
|
||||||
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
|
|
||||||
anim.addListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
mCallback.setUserLockedChild(child, false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
anim.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cancelExpansion() {
|
|
||||||
ValueAnimator anim = ValueAnimator.ofFloat(mLastHeight, 0);
|
|
||||||
anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
|
||||||
anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
|
|
||||||
anim.addUpdateListener(animation -> {
|
|
||||||
mDragDownCallback.setEmptyDragAmount((Float) animation.getAnimatedValue());
|
|
||||||
});
|
|
||||||
anim.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void stopDragging() {
|
|
||||||
mFalsingCollector.onNotificationStopDraggingDown();
|
|
||||||
if (mStartingChild != null) {
|
|
||||||
cancelExpansion(mStartingChild);
|
|
||||||
mStartingChild = null;
|
|
||||||
} else {
|
|
||||||
cancelExpansion();
|
|
||||||
}
|
|
||||||
mDraggingDown = false;
|
|
||||||
mDragDownCallback.onDragDownReset();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExpandableView findView(float x, float y) {
|
|
||||||
mHost.getLocationOnScreen(mTemp2);
|
|
||||||
x += mTemp2[0];
|
|
||||||
y += mTemp2[1];
|
|
||||||
return mCallback.getChildAtRawPosition(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDraggingDown() {
|
|
||||||
return mDraggingDown;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDragDownEnabled() {
|
|
||||||
return mDragDownCallback.isDragDownEnabledForView(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface DragDownCallback {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the interaction is accepted, false if it should be cancelled
|
|
||||||
*/
|
|
||||||
boolean canDragDown();
|
|
||||||
|
|
||||||
/** Call when a view has been dragged. */
|
|
||||||
void onDraggedDown(View startingChild, int dragLengthY);
|
|
||||||
void onDragDownReset();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has dragged either above or below the threshold
|
|
||||||
* @param above whether he dragged above it
|
|
||||||
*/
|
|
||||||
void onCrossedThreshold(boolean above);
|
|
||||||
void onTouchSlopExceeded();
|
|
||||||
void setEmptyDragAmount(float amount);
|
|
||||||
boolean isFalsingCheckNeeded();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is dragging down enabled on a given view
|
|
||||||
* @param view The view to check or {@code null} to check if it's enabled at all
|
|
||||||
*/
|
|
||||||
boolean isDragDownEnabledForView(ExpandableView view);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return if drag down is enabled anywhere, not just on selected views.
|
|
||||||
*/
|
|
||||||
boolean isDragDownAnywhereEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,667 @@
|
|||||||
|
package com.android.systemui.statusbar
|
||||||
|
|
||||||
|
import android.animation.Animator
|
||||||
|
import android.animation.AnimatorListenerAdapter
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.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.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 falsingCollector: FalsingCollector,
|
||||||
|
private val dragDownCallback: LockscreenShadeTransitionController,
|
||||||
|
context: Context
|
||||||
|
) : Gefingerpoken {
|
||||||
|
|
||||||
|
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 var touchSlop = 0f
|
||||||
|
private var slopMultiplier = 0f
|
||||||
|
private val temp2 = IntArray(2)
|
||||||
|
private var draggedFarEnough = false
|
||||||
|
private var startingChild: ExpandableView? = null
|
||||||
|
private var lastHeight = 0f
|
||||||
|
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)
|
||||||
|
touchSlop = configuration.scaledTouchSlop.toFloat()
|
||||||
|
slopMultiplier = configuration.scaledAmbiguousGestureMultiplier
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
val x = event.x
|
||||||
|
val y = event.y
|
||||||
|
when (event.actionMasked) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
draggedFarEnough = false
|
||||||
|
isDraggingDown = false
|
||||||
|
startingChild = null
|
||||||
|
initialTouchY = y
|
||||||
|
initialTouchX = x
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
val h = y - initialTouchY
|
||||||
|
// Adjust the touch slop if another gesture may be being performed.
|
||||||
|
val touchSlop = if (event.classification
|
||||||
|
== MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE)
|
||||||
|
touchSlop * slopMultiplier
|
||||||
|
else
|
||||||
|
touchSlop
|
||||||
|
if (h > touchSlop && h > Math.abs(x - initialTouchX)) {
|
||||||
|
falsingCollector.onNotificationStartDraggingDown()
|
||||||
|
isDraggingDown = true
|
||||||
|
captureStartingChild(initialTouchX, initialTouchY)
|
||||||
|
initialTouchY = y
|
||||||
|
initialTouchX = x
|
||||||
|
dragDownCallback.onDragDownStarted()
|
||||||
|
dragDownAmountOnStart = dragDownCallback.dragDownAmount
|
||||||
|
return startingChild != null || dragDownCallback.isDragDownAnywhereEnabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
if (!isDraggingDown) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val x = event.x
|
||||||
|
val y = event.y
|
||||||
|
when (event.actionMasked) {
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
lastHeight = y - initialTouchY
|
||||||
|
captureStartingChild(initialTouchX, initialTouchY)
|
||||||
|
dragDownCallback.dragDownAmount = lastHeight + dragDownAmountOnStart
|
||||||
|
if (startingChild != null) {
|
||||||
|
handleExpansion(lastHeight, startingChild!!)
|
||||||
|
}
|
||||||
|
if (lastHeight > minDragDistance) {
|
||||||
|
if (!draggedFarEnough) {
|
||||||
|
draggedFarEnough = true
|
||||||
|
dragDownCallback.onCrossedThreshold(true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (draggedFarEnough) {
|
||||||
|
draggedFarEnough = false
|
||||||
|
dragDownCallback.onCrossedThreshold(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_UP -> if (!falsingManager.isUnlockingDisabled && !isFalseTouch &&
|
||||||
|
dragDownCallback.canDragDown()) {
|
||||||
|
dragDownCallback.onDraggedDown(startingChild, (y - initialTouchY).toInt())
|
||||||
|
if (startingChild != null) {
|
||||||
|
expandCallback.setUserLockedChild(startingChild, false)
|
||||||
|
startingChild = null
|
||||||
|
}
|
||||||
|
isDraggingDown = false
|
||||||
|
} else {
|
||||||
|
stopDragging()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_CANCEL -> {
|
||||||
|
stopDragging()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun captureStartingChild(x: Float, y: Float) {
|
||||||
|
if (startingChild == null) {
|
||||||
|
startingChild = findView(x, y)
|
||||||
|
if (startingChild != null) {
|
||||||
|
if (dragDownCallback.isDragDownEnabledForView(startingChild)) {
|
||||||
|
expandCallback.setUserLockedChild(startingChild, true)
|
||||||
|
} else {
|
||||||
|
startingChild = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleExpansion(heightDelta: Float, child: ExpandableView) {
|
||||||
|
var hDelta = heightDelta
|
||||||
|
if (hDelta < 0) {
|
||||||
|
hDelta = 0f
|
||||||
|
}
|
||||||
|
val expandable = child.isContentExpandable
|
||||||
|
val rubberbandFactor = if (expandable) {
|
||||||
|
RUBBERBAND_FACTOR_EXPANDABLE
|
||||||
|
} else {
|
||||||
|
RUBBERBAND_FACTOR_STATIC
|
||||||
|
}
|
||||||
|
var rubberband = hDelta * rubberbandFactor
|
||||||
|
if (expandable && rubberband + child.collapsedHeight > child.maxContentHeight) {
|
||||||
|
var overshoot = rubberband + child.collapsedHeight - child.maxContentHeight
|
||||||
|
overshoot *= 1 - RUBBERBAND_FACTOR_STATIC
|
||||||
|
rubberband -= overshoot
|
||||||
|
}
|
||||||
|
child.actualHeight = (child.collapsedHeight + rubberband).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cancelChildExpansion(child: ExpandableView) {
|
||||||
|
if (child.actualHeight == child.collapsedHeight) {
|
||||||
|
expandCallback.setUserLockedChild(child, false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val anim = ObjectAnimator.ofInt(child, "actualHeight",
|
||||||
|
child.actualHeight, child.collapsedHeight)
|
||||||
|
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||||
|
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS
|
||||||
|
anim.addListener(object : AnimatorListenerAdapter() {
|
||||||
|
override fun onAnimationEnd(animation: Animator) {
|
||||||
|
expandCallback.setUserLockedChild(child, false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
anim.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopDragging() {
|
||||||
|
falsingCollector.onNotificationStopDraggingDown()
|
||||||
|
if (startingChild != null) {
|
||||||
|
cancelChildExpansion(startingChild!!)
|
||||||
|
startingChild = null
|
||||||
|
}
|
||||||
|
isDraggingDown = false
|
||||||
|
dragDownCallback.onDragDownReset()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findView(x: Float, y: Float): ExpandableView? {
|
||||||
|
host.getLocationOnScreen(temp2)
|
||||||
|
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.notification.stack.NotificationStackScrollLayoutController
|
||||||
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||||
import com.android.systemui.statusbar.phone.ShadeController
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
@@ -59,6 +58,7 @@ constructor(
|
|||||||
private val roundnessManager: NotificationRoundnessManager,
|
private val roundnessManager: NotificationRoundnessManager,
|
||||||
private val statusBarStateController: StatusBarStateController,
|
private val statusBarStateController: StatusBarStateController,
|
||||||
private val falsingManager: FalsingManager,
|
private val falsingManager: FalsingManager,
|
||||||
|
private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
|
||||||
private val falsingCollector: FalsingCollector
|
private val falsingCollector: FalsingCollector
|
||||||
) : Gefingerpoken {
|
) : Gefingerpoken {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -66,7 +66,6 @@ constructor(
|
|||||||
private val SPRING_BACK_ANIMATION_LENGTH_MS = 375
|
private val SPRING_BACK_ANIMATION_LENGTH_MS = 375
|
||||||
}
|
}
|
||||||
private val mPowerManager: PowerManager?
|
private val mPowerManager: PowerManager?
|
||||||
private lateinit var shadeController: ShadeController
|
|
||||||
|
|
||||||
private val mMinDragDistance: Int
|
private val mMinDragDistance: Int
|
||||||
private var mInitialTouchX: Float = 0.0f
|
private var mInitialTouchX: Float = 0.0f
|
||||||
@@ -95,7 +94,7 @@ constructor(
|
|||||||
var leavingLockscreen: Boolean = false
|
var leavingLockscreen: Boolean = false
|
||||||
private set
|
private set
|
||||||
private val mTouchSlop: Float
|
private val mTouchSlop: Float
|
||||||
private lateinit var expansionCallback: ExpansionCallback
|
private lateinit var overStretchHandler: OverStretchHandler
|
||||||
private lateinit var stackScrollerController: NotificationStackScrollLayoutController
|
private lateinit var stackScrollerController: NotificationStackScrollLayoutController
|
||||||
private val mTemp2 = IntArray(2)
|
private val mTemp2 = IntArray(2)
|
||||||
private var mDraggedFarEnough: Boolean = false
|
private var mDraggedFarEnough: Boolean = false
|
||||||
@@ -103,7 +102,7 @@ constructor(
|
|||||||
private var mPulsing: Boolean = false
|
private var mPulsing: Boolean = false
|
||||||
var isWakingToShadeLocked: Boolean = false
|
var isWakingToShadeLocked: Boolean = false
|
||||||
private set
|
private set
|
||||||
private var mEmptyDragAmount: Float = 0.0f
|
private var overStretchAmount: Float = 0.0f
|
||||||
private var mWakeUpHeight: Float = 0.0f
|
private var mWakeUpHeight: Float = 0.0f
|
||||||
private var mReachedWakeUpHeight: Boolean = false
|
private var mReachedWakeUpHeight: Boolean = false
|
||||||
private var velocityTracker: VelocityTracker? = null
|
private var velocityTracker: VelocityTracker? = null
|
||||||
@@ -215,6 +214,7 @@ constructor(
|
|||||||
|
|
||||||
private fun finishExpansion() {
|
private fun finishExpansion() {
|
||||||
resetClock()
|
resetClock()
|
||||||
|
val startingChild = mStartingChild
|
||||||
if (mStartingChild != null) {
|
if (mStartingChild != null) {
|
||||||
setUserLocked(mStartingChild!!, false)
|
setUserLocked(mStartingChild!!, false)
|
||||||
mStartingChild = null
|
mStartingChild = null
|
||||||
@@ -225,7 +225,8 @@ constructor(
|
|||||||
mPowerManager!!.wakeUp(SystemClock.uptimeMillis(), WAKE_REASON_GESTURE,
|
mPowerManager!!.wakeUp(SystemClock.uptimeMillis(), WAKE_REASON_GESTURE,
|
||||||
"com.android.systemui:PULSEDRAG")
|
"com.android.systemui:PULSEDRAG")
|
||||||
}
|
}
|
||||||
shadeController.goToLockedShade(mStartingChild)
|
lockscreenShadeTransitionController.goToLockedShade(startingChild,
|
||||||
|
needsQSAnimation = false)
|
||||||
leavingLockscreen = true
|
leavingLockscreen = true
|
||||||
isExpanding = false
|
isExpanding = false
|
||||||
if (mStartingChild is ExpandableNotificationRow) {
|
if (mStartingChild is ExpandableNotificationRow) {
|
||||||
@@ -252,8 +253,8 @@ constructor(
|
|||||||
true /* increaseSpeed */)
|
true /* increaseSpeed */)
|
||||||
expansionHeight = max(mWakeUpHeight, expansionHeight)
|
expansionHeight = max(mWakeUpHeight, expansionHeight)
|
||||||
}
|
}
|
||||||
val emptyDragAmount = wakeUpCoordinator.setPulseHeight(expansionHeight)
|
val dragDownAmount = wakeUpCoordinator.setPulseHeight(expansionHeight)
|
||||||
setEmptyDragAmount(emptyDragAmount * RUBBERBAND_FACTOR_STATIC)
|
setOverStretchAmount(dragDownAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun captureStartingChild(x: Float, y: Float) {
|
private fun captureStartingChild(x: Float, y: Float) {
|
||||||
@@ -265,9 +266,9 @@ constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setEmptyDragAmount(amount: Float) {
|
private fun setOverStretchAmount(amount: Float) {
|
||||||
mEmptyDragAmount = amount
|
overStretchAmount = amount
|
||||||
expansionCallback.setEmptyDragAmount(amount)
|
overStretchHandler.setOverStretchAmount(amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reset(child: ExpandableView) {
|
private fun reset(child: ExpandableView) {
|
||||||
@@ -294,10 +295,12 @@ constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resetClock() {
|
private fun resetClock() {
|
||||||
val anim = ValueAnimator.ofFloat(mEmptyDragAmount, 0f)
|
val anim = ValueAnimator.ofFloat(overStretchAmount, 0f)
|
||||||
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
anim.interpolator = Interpolators.FAST_OUT_SLOW_IN
|
||||||
anim.duration = SPRING_BACK_ANIMATION_LENGTH_MS.toLong()
|
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()
|
anim.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,11 +332,9 @@ constructor(
|
|||||||
|
|
||||||
fun setUp(
|
fun setUp(
|
||||||
stackScrollerController: NotificationStackScrollLayoutController,
|
stackScrollerController: NotificationStackScrollLayoutController,
|
||||||
expansionCallback: ExpansionCallback,
|
overStrechHandler: OverStretchHandler
|
||||||
shadeController: ShadeController
|
|
||||||
) {
|
) {
|
||||||
this.expansionCallback = expansionCallback
|
this.overStretchHandler = overStrechHandler
|
||||||
this.shadeController = shadeController
|
|
||||||
this.stackScrollerController = stackScrollerController
|
this.stackScrollerController = stackScrollerController
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +346,11 @@ constructor(
|
|||||||
isWakingToShadeLocked = false
|
isWakingToShadeLocked = false
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ExpansionCallback {
|
interface OverStretchHandler {
|
||||||
fun setEmptyDragAmount(amount: Float)
|
|
||||||
|
/**
|
||||||
|
* 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. */
|
/** Height of the notifications panel without top padding when expansion completes. */
|
||||||
private float mStackEndHeight;
|
private float mStackEndHeight;
|
||||||
|
private float mTransitionToFullShadeAmount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Height of the notifications panel without top padding when expansion completes.
|
* @return Height of the notifications panel without top padding when expansion completes.
|
||||||
@@ -594,6 +595,21 @@ public class AmbientState {
|
|||||||
mTrackedHeadsUpRow = row;
|
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
|
* Returns the currently tracked heads up row, if there is one and it is currently above the
|
||||||
* shelf (still appearing).
|
* shelf (still appearing).
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ import android.os.Bundle;
|
|||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.MathUtils;
|
import android.util.MathUtils;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@@ -71,17 +70,14 @@ import android.widget.ScrollView;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.graphics.ColorUtils;
|
import com.android.internal.graphics.ColorUtils;
|
||||||
import com.android.internal.jank.InteractionJankMonitor;
|
import com.android.internal.jank.InteractionJankMonitor;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
|
||||||
import com.android.keyguard.KeyguardSliceView;
|
import com.android.keyguard.KeyguardSliceView;
|
||||||
import com.android.settingslib.Utils;
|
import com.android.settingslib.Utils;
|
||||||
import com.android.systemui.Dependency;
|
|
||||||
import com.android.systemui.Dumpable;
|
import com.android.systemui.Dumpable;
|
||||||
import com.android.systemui.ExpandHelper;
|
import com.android.systemui.ExpandHelper;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.animation.Interpolators;
|
import com.android.systemui.animation.Interpolators;
|
||||||
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
|
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
|
|
||||||
import com.android.systemui.statusbar.EmptyShadeView;
|
import com.android.systemui.statusbar.EmptyShadeView;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
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.NotificationShelfController;
|
||||||
import com.android.systemui.statusbar.RemoteInputController;
|
import com.android.systemui.statusbar.RemoteInputController;
|
||||||
import com.android.systemui.statusbar.StatusBarState;
|
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.ExpandAnimationParameters;
|
||||||
import com.android.systemui.statusbar.notification.FakeShadowView;
|
import com.android.systemui.statusbar.notification.FakeShadowView;
|
||||||
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
|
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.notification.row.StackScrollerDecorView;
|
||||||
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
|
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
|
||||||
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
|
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.ShadeController;
|
||||||
import com.android.systemui.statusbar.phone.StatusBar;
|
import com.android.systemui.statusbar.phone.StatusBar;
|
||||||
import com.android.systemui.statusbar.policy.HeadsUpUtil;
|
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 static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1;
|
||||||
private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
|
private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider;
|
||||||
private final SysuiStatusBarStateController mStatusbarStateController;
|
|
||||||
|
|
||||||
private ExpandHelper mExpandHelper;
|
private ExpandHelper mExpandHelper;
|
||||||
private NotificationSwipeHelper mSwipeHelper;
|
private NotificationSwipeHelper mSwipeHelper;
|
||||||
@@ -433,13 +424,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
private ShadeController mShadeController;
|
private ShadeController mShadeController;
|
||||||
private Runnable mOnStackYChanged;
|
private Runnable mOnStackYChanged;
|
||||||
|
|
||||||
private final DisplayMetrics mDisplayMetrics = Dependency.get(DisplayMetrics.class);
|
|
||||||
private final LockscreenGestureLogger mLockscreenGestureLogger =
|
|
||||||
Dependency.get(LockscreenGestureLogger.class);
|
|
||||||
protected boolean mClearAllEnabled;
|
protected boolean mClearAllEnabled;
|
||||||
|
|
||||||
private Interpolator mHideXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
|
private Interpolator mHideXInterpolator = Interpolators.FAST_OUT_SLOW_IN;
|
||||||
private NotificationPanelViewController mNotificationPanelController;
|
|
||||||
|
|
||||||
private final NotificationSectionsManager mSectionsManager;
|
private final NotificationSectionsManager mSectionsManager;
|
||||||
private ForegroundServiceDungeonView mFgsSectionView;
|
private ForegroundServiceDungeonView mFgsSectionView;
|
||||||
@@ -449,6 +436,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
private boolean mWillExpand;
|
private boolean mWillExpand;
|
||||||
private int mGapHeight;
|
private int mGapHeight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The extra inset during the full shade transition
|
||||||
|
*/
|
||||||
|
private float mExtraTopInsetForFullShadeTransition;
|
||||||
|
|
||||||
private int mWaterfallTopInset;
|
private int mWaterfallTopInset;
|
||||||
private NotificationStackScrollLayoutController mController;
|
private NotificationStackScrollLayoutController mController;
|
||||||
|
|
||||||
@@ -496,7 +488,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
NotificationSectionsManager notificationSectionsManager,
|
NotificationSectionsManager notificationSectionsManager,
|
||||||
GroupMembershipManager groupMembershipManager,
|
GroupMembershipManager groupMembershipManager,
|
||||||
GroupExpansionManager groupExpansionManager,
|
GroupExpansionManager groupExpansionManager,
|
||||||
SysuiStatusBarStateController statusbarStateController,
|
|
||||||
AmbientState ambientState,
|
AmbientState ambientState,
|
||||||
FeatureFlags featureFlags) {
|
FeatureFlags featureFlags) {
|
||||||
super(context, attrs, 0, 0);
|
super(context, attrs, 0, 0);
|
||||||
@@ -535,7 +526,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
|
mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
|
||||||
mGroupMembershipManager = groupMembershipManager;
|
mGroupMembershipManager = groupMembershipManager;
|
||||||
mGroupExpansionManager = groupExpansionManager;
|
mGroupExpansionManager = groupExpansionManager;
|
||||||
mStatusbarStateController = statusbarStateController;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) {
|
void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) {
|
||||||
@@ -1142,8 +1132,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
*/
|
*/
|
||||||
private void updateStackPosition() {
|
private void updateStackPosition() {
|
||||||
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
|
// Consider interpolating from an mExpansionStartY for use on lockscreen and AOD
|
||||||
|
float endTopPosition = mTopPadding + mExtraTopInsetForFullShadeTransition;
|
||||||
final float fraction = mAmbientState.getExpansionFraction();
|
final float fraction = mAmbientState.getExpansionFraction();
|
||||||
final float stackY = MathUtils.lerp(0, mTopPadding, fraction);
|
final float stackY = MathUtils.lerp(0, endTopPosition, fraction);
|
||||||
mAmbientState.setStackY(stackY);
|
mAmbientState.setStackY(stackY);
|
||||||
if (mOnStackYChanged != null) {
|
if (mOnStackYChanged != null) {
|
||||||
mOnStackYChanged.run();
|
mOnStackYChanged.run();
|
||||||
@@ -4278,6 +4269,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
+ mGapHeight;
|
+ mGapHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the padding after the media header on the lockscreen
|
||||||
|
*/
|
||||||
|
public int getPaddingAfterMedia() {
|
||||||
|
return mGapHeight + mPaddingBetweenElements;
|
||||||
|
}
|
||||||
|
|
||||||
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||||
public int getEmptyShadeViewHeight() {
|
public int getEmptyShadeViewHeight() {
|
||||||
return mEmptyShadeView.getHeight();
|
return mEmptyShadeView.getHeight();
|
||||||
@@ -4933,12 +4931,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
getChildCount() - offsetFromEnd);
|
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
|
* Set how far the wake up is when waking up from pulsing. This is a height and will adjust the
|
||||||
* notification positions accordingly.
|
* notification positions accordingly.
|
||||||
@@ -5154,6 +5146,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
|||||||
mShadeController = shadeController;
|
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
|
* 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() {
|
void resetCheckSnoozeLeavebehind() {
|
||||||
setCheckForLeaveBehind(true);
|
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)
|
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
|
||||||
private final HeadsUpTouchHelper.Callback mHeadsUpCallback = new HeadsUpTouchHelper.Callback() {
|
private final HeadsUpTouchHelper.Callback mHeadsUpCallback = new HeadsUpTouchHelper.Callback() {
|
||||||
@Override
|
@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.notification.stack.NotificationStackScrollLayout.canChildBeDismissed;
|
||||||
import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
|
import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
|
||||||
|
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
@@ -38,6 +39,7 @@ import android.provider.Settings;
|
|||||||
import android.service.notification.NotificationListenerService;
|
import android.service.notification.NotificationListenerService;
|
||||||
import android.service.notification.StatusBarNotification;
|
import android.service.notification.StatusBarNotification;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.MathUtils;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -59,6 +61,7 @@ import com.android.systemui.ExpandHelper;
|
|||||||
import com.android.systemui.Gefingerpoken;
|
import com.android.systemui.Gefingerpoken;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.SwipeHelper;
|
import com.android.systemui.SwipeHelper;
|
||||||
|
import com.android.systemui.animation.Interpolators;
|
||||||
import com.android.systemui.classifier.Classifier;
|
import com.android.systemui.classifier.Classifier;
|
||||||
import com.android.systemui.classifier.FalsingCollector;
|
import com.android.systemui.classifier.FalsingCollector;
|
||||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
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.NotificationSwipeActionHelper;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
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.HeadsUpManagerPhone;
|
||||||
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
|
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
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.ScrimController;
|
||||||
import com.android.systemui.statusbar.phone.ShadeController;
|
import com.android.systemui.statusbar.phone.ShadeController;
|
||||||
import com.android.systemui.statusbar.phone.StatusBar;
|
import com.android.systemui.statusbar.phone.StatusBar;
|
||||||
@@ -168,6 +171,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
// TODO: StatusBar should be encapsulated behind a Controller
|
// TODO: StatusBar should be encapsulated behind a Controller
|
||||||
private final StatusBar mStatusBar;
|
private final StatusBar mStatusBar;
|
||||||
private final SectionHeaderController mSilentHeaderController;
|
private final SectionHeaderController mSilentHeaderController;
|
||||||
|
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
|
|
||||||
private NotificationStackScrollLayout mView;
|
private NotificationStackScrollLayout mView;
|
||||||
private boolean mFadeNotificationsOnDismiss;
|
private boolean mFadeNotificationsOnDismiss;
|
||||||
@@ -181,6 +185,9 @@ public class NotificationStackScrollLayoutController {
|
|||||||
|
|
||||||
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
|
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
|
||||||
|
|
||||||
|
private int mTotalDistanceForFullShadeTransition;
|
||||||
|
private int mTotalExtraMediaInsetFullShadeTransition;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
|
final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
|
||||||
new View.OnAttachStateChangeListener() {
|
new View.OnAttachStateChangeListener() {
|
||||||
@@ -240,8 +247,20 @@ public class NotificationStackScrollLayoutController {
|
|||||||
public void onThemeChanged() {
|
public void onThemeChanged() {
|
||||||
updateFooter();
|
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 =
|
private final StatusBarStateController.StateListener mStateListener =
|
||||||
new StatusBarStateController.StateListener() {
|
new StatusBarStateController.StateListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -571,6 +590,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
NotifPipeline notifPipeline,
|
NotifPipeline notifPipeline,
|
||||||
NotifCollection notifCollection,
|
NotifCollection notifCollection,
|
||||||
NotificationEntryManager notificationEntryManager,
|
NotificationEntryManager notificationEntryManager,
|
||||||
|
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||||
IStatusBarService iStatusBarService,
|
IStatusBarService iStatusBarService,
|
||||||
UiEventLogger uiEventLogger,
|
UiEventLogger uiEventLogger,
|
||||||
ForegroundServiceDismissalFeatureController fgFeatureController,
|
ForegroundServiceDismissalFeatureController fgFeatureController,
|
||||||
@@ -592,6 +612,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mZenModeController = zenModeController;
|
mZenModeController = zenModeController;
|
||||||
mLockscreenUserManager = lockscreenUserManager;
|
mLockscreenUserManager = lockscreenUserManager;
|
||||||
mMetricsLogger = metricsLogger;
|
mMetricsLogger = metricsLogger;
|
||||||
|
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||||
mFalsingCollector = falsingCollector;
|
mFalsingCollector = falsingCollector;
|
||||||
mFalsingManager = falsingManager;
|
mFalsingManager = falsingManager;
|
||||||
mResources = resources;
|
mResources = resources;
|
||||||
@@ -624,6 +645,7 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mRemoteInputManager = remoteInputManager;
|
mRemoteInputManager = remoteInputManager;
|
||||||
mVisualStabilityManager = visualStabilityManager;
|
mVisualStabilityManager = visualStabilityManager;
|
||||||
mShadeController = shadeController;
|
mShadeController = shadeController;
|
||||||
|
updateResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void attach(NotificationStackScrollLayout view) {
|
public void attach(NotificationStackScrollLayout view) {
|
||||||
@@ -676,6 +698,8 @@ public class NotificationStackScrollLayoutController {
|
|||||||
|
|
||||||
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
|
mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming);
|
||||||
|
|
||||||
|
mLockscreenShadeTransitionController.setStackScroller(this);
|
||||||
|
|
||||||
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
|
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
|
||||||
|
|
||||||
mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly
|
mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly
|
||||||
@@ -705,7 +729,6 @@ public class NotificationStackScrollLayoutController {
|
|||||||
Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
|
Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
|
||||||
|
|
||||||
mKeyguardMediaController.setVisibilityChangedListener(visible -> {
|
mKeyguardMediaController.setVisibilityChangedListener(visible -> {
|
||||||
mView.setKeyguardMediaControllorVisible(visible);
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
mView.generateAddAnimation(
|
mView.generateAddAnimation(
|
||||||
mKeyguardMediaController.getSinglePaneContainer(),
|
mKeyguardMediaController.getSinglePaneContainer(),
|
||||||
@@ -1203,11 +1226,6 @@ public class NotificationStackScrollLayoutController {
|
|||||||
mView.runAfterAnimationFinished(r);
|
mView.runAfterAnimationFinished(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNotificationPanelController(
|
|
||||||
NotificationPanelViewController notificationPanelViewController) {
|
|
||||||
mView.setNotificationPanelController(notificationPanelViewController);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setShelfController(NotificationShelfController notificationShelfController) {
|
public void setShelfController(NotificationShelfController notificationShelfController) {
|
||||||
mView.setShelfController(notificationShelfController);
|
mView.setShelfController(notificationShelfController);
|
||||||
}
|
}
|
||||||
@@ -1275,7 +1293,10 @@ public class NotificationStackScrollLayoutController {
|
|||||||
NotificationLogger.getNotificationLocation(entry)));
|
NotificationLogger.getNotificationLocation(entry)));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasActiveNotifications() {
|
/**
|
||||||
|
* @return if the shade has currently any active notifications.
|
||||||
|
*/
|
||||||
|
public boolean hasActiveNotifications() {
|
||||||
if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
|
if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
|
||||||
return !mNotifPipeline.getShadeList().isEmpty();
|
return !mNotifPipeline.getShadeList().isEmpty();
|
||||||
} else {
|
} 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() {
|
public boolean isInLockedDownShade() {
|
||||||
return mDynamicPrivacyController.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
|
* Enum for UiEvent logged from this class
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -257,7 +257,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
|
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext),
|
||||||
new ActivityIntentHelper(mContext));
|
new ActivityIntentHelper(mContext));
|
||||||
mPreviewContainer = findViewById(R.id.preview_container);
|
|
||||||
mOverlayContainer = findViewById(R.id.overlay_container);
|
mOverlayContainer = findViewById(R.id.overlay_container);
|
||||||
mRightAffordanceView = findViewById(R.id.camera_button);
|
mRightAffordanceView = findViewById(R.id.camera_button);
|
||||||
mLeftAffordanceView = findViewById(R.id.left_button);
|
mLeftAffordanceView = findViewById(R.id.left_button);
|
||||||
@@ -274,7 +273,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
mKeyguardStateController.addCallback(this);
|
mKeyguardStateController.addCallback(this);
|
||||||
setClipChildren(false);
|
setClipChildren(false);
|
||||||
setClipToPadding(false);
|
setClipToPadding(false);
|
||||||
inflateCameraPreview();
|
|
||||||
mRightAffordanceView.setOnClickListener(this);
|
mRightAffordanceView.setOnClickListener(this);
|
||||||
mLeftAffordanceView.setOnClickListener(this);
|
mLeftAffordanceView.setOnClickListener(this);
|
||||||
initAccessibility();
|
initAccessibility();
|
||||||
@@ -282,13 +280,21 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
mFlashlightController = Dependency.get(FlashlightController.class);
|
mFlashlightController = Dependency.get(FlashlightController.class);
|
||||||
mAccessibilityController = Dependency.get(AccessibilityController.class);
|
mAccessibilityController = Dependency.get(AccessibilityController.class);
|
||||||
mActivityIntentHelper = new ActivityIntentHelper(getContext());
|
mActivityIntentHelper = new ActivityIntentHelper(getContext());
|
||||||
updateLeftAffordance();
|
|
||||||
|
|
||||||
mIndicationPadding = getResources().getDimensionPixelSize(
|
mIndicationPadding = getResources().getDimensionPixelSize(
|
||||||
R.dimen.keyguard_indication_area_padding);
|
R.dimen.keyguard_indication_area_padding);
|
||||||
updateWalletVisibility();
|
updateWalletVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the container where the previews are rendered.
|
||||||
|
*/
|
||||||
|
public void setPreviewContainer(ViewGroup previewContainer) {
|
||||||
|
mPreviewContainer = previewContainer;
|
||||||
|
inflateCameraPreview();
|
||||||
|
updateLeftAffordance();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
@@ -689,6 +695,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void inflateCameraPreview() {
|
private void inflateCameraPreview() {
|
||||||
|
if (mPreviewContainer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
View previewBefore = mCameraPreview;
|
View previewBefore = mCameraPreview;
|
||||||
boolean visibleBefore = false;
|
boolean visibleBefore = false;
|
||||||
if (previewBefore != null) {
|
if (previewBefore != null) {
|
||||||
@@ -706,6 +715,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateLeftPreview() {
|
private void updateLeftPreview() {
|
||||||
|
if (mPreviewContainer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
View previewBefore = mLeftPreview;
|
View previewBefore = mLeftPreview;
|
||||||
if (previewBefore != null) {
|
if (previewBefore != null) {
|
||||||
mPreviewContainer.removeView(previewBefore);
|
mPreviewContainer.removeView(previewBefore);
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public class KeyguardClockPositionAlgorithm {
|
|||||||
*/
|
*/
|
||||||
private float mQsExpansion;
|
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
|
* 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 notificationStackHeight, float panelExpansion, int parentHeight,
|
||||||
int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
|
int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
|
||||||
int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
|
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) {
|
float qsExpansion, int cutoutTopInset, boolean isSplitShade) {
|
||||||
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
|
mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(mContainerTopPadding,
|
||||||
userSwitchHeight);
|
userSwitchHeight);
|
||||||
@@ -196,7 +196,7 @@ public class KeyguardClockPositionAlgorithm {
|
|||||||
mHasCustomClock = hasCustomClock;
|
mHasCustomClock = hasCustomClock;
|
||||||
mHasVisibleNotifs = hasVisibleNotifs;
|
mHasVisibleNotifs = hasVisibleNotifs;
|
||||||
mDarkAmount = dark;
|
mDarkAmount = dark;
|
||||||
mEmptyDragAmount = emptyDragAmount;
|
mOverStretchAmount = overStrechAmount;
|
||||||
mBypassEnabled = bypassEnabled;
|
mBypassEnabled = bypassEnabled;
|
||||||
mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
|
mUnlockedStackScrollerPadding = unlockedStackScrollerPadding;
|
||||||
mQsExpansion = qsExpansion;
|
mQsExpansion = qsExpansion;
|
||||||
@@ -301,7 +301,7 @@ public class KeyguardClockPositionAlgorithm {
|
|||||||
}
|
}
|
||||||
clockYDark = clockY + burnInPreventionOffsetY() + shift;
|
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) {
|
private int getUserSwitcherY(float panelExpansion) {
|
||||||
@@ -312,7 +312,7 @@ public class KeyguardClockPositionAlgorithm {
|
|||||||
float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
|
float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
|
||||||
float userSwitchY = MathUtils.lerp(userSwitchYBouncer, userSwitchYRegular, shadeExpansion);
|
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.GestureRecorder;
|
||||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
import com.android.systemui.statusbar.NotificationShelfController;
|
import com.android.systemui.statusbar.NotificationShelfController;
|
||||||
@@ -208,7 +209,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
|
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
|
||||||
@VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
|
@VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
|
||||||
new StatusBarStateListener();
|
new StatusBarStateListener();
|
||||||
private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
|
|
||||||
private final BiometricUnlockController mBiometricUnlockController;
|
private final BiometricUnlockController mBiometricUnlockController;
|
||||||
private final NotificationPanelView mView;
|
private final NotificationPanelView mView;
|
||||||
private final VibratorHelper mVibratorHelper;
|
private final VibratorHelper mVibratorHelper;
|
||||||
@@ -313,10 +313,12 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
// Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow card.
|
// 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
|
// If there are exactly 1 + mMaxKeyguardNotifications, then still shows all notifications
|
||||||
private final int mMaxKeyguardNotifications;
|
private final int mMaxKeyguardNotifications;
|
||||||
|
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
private boolean mShouldUseSplitNotificationShade;
|
private boolean mShouldUseSplitNotificationShade;
|
||||||
// Current max allowed keyguard notifications determined by measuring the panel
|
// Current max allowed keyguard notifications determined by measuring the panel
|
||||||
private int mMaxAllowedKeyguardNotifications;
|
private int mMaxAllowedKeyguardNotifications;
|
||||||
|
|
||||||
|
private ViewGroup mPreviewContainer;
|
||||||
private KeyguardAffordanceHelper mAffordanceHelper;
|
private KeyguardAffordanceHelper mAffordanceHelper;
|
||||||
private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
|
private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
|
||||||
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
|
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
|
||||||
@@ -366,7 +368,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private int mStatusBarMinHeight;
|
private int mStatusBarMinHeight;
|
||||||
private int mStatusBarHeaderHeightKeyguard;
|
private int mStatusBarHeaderHeightKeyguard;
|
||||||
private int mNotificationsHeaderCollideDistance;
|
private int mNotificationsHeaderCollideDistance;
|
||||||
private float mEmptyDragAmount;
|
private float mOverStretchAmount;
|
||||||
private float mDownX;
|
private float mDownX;
|
||||||
private float mDownY;
|
private float mDownY;
|
||||||
private int mDisplayCutoutTopInset = 0; // in pixels
|
private int mDisplayCutoutTopInset = 0; // in pixels
|
||||||
@@ -482,7 +484,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private final CommandQueue mCommandQueue;
|
private final CommandQueue mCommandQueue;
|
||||||
private final NotificationLockscreenUserManager mLockscreenUserManager;
|
private final NotificationLockscreenUserManager mLockscreenUserManager;
|
||||||
private final UserManager mUserManager;
|
private final UserManager mUserManager;
|
||||||
private final ShadeController mShadeController;
|
|
||||||
private final MediaDataManager mMediaDataManager;
|
private final MediaDataManager mMediaDataManager;
|
||||||
private NotificationShadeDepthController mDepthController;
|
private NotificationShadeDepthController mDepthController;
|
||||||
private int mDisplayId;
|
private int mDisplayId;
|
||||||
@@ -505,6 +506,39 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private Runnable mExpandAfterLayoutRunnable;
|
private Runnable mExpandAfterLayoutRunnable;
|
||||||
private float mSectionPadding;
|
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
|
* Is this a collapse that started on the panel where we should allow the panel to intercept
|
||||||
*/
|
*/
|
||||||
@@ -522,6 +556,16 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
private boolean mDelayShowingKeyguardStatusBar;
|
private boolean mDelayShowingKeyguardStatusBar;
|
||||||
|
|
||||||
private boolean mAnimatingQS;
|
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 final Rect mKeyguardStatusAreaClipBounds = new Rect();
|
||||||
private int mOldLayoutDirection;
|
private int mOldLayoutDirection;
|
||||||
private NotificationShelfController mNotificationShelfController;
|
private NotificationShelfController mNotificationShelfController;
|
||||||
@@ -571,7 +615,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
|
NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
|
||||||
DynamicPrivacyController dynamicPrivacyController,
|
DynamicPrivacyController dynamicPrivacyController,
|
||||||
KeyguardBypassController bypassController, FalsingManager falsingManager,
|
KeyguardBypassController bypassController, FalsingManager falsingManager,
|
||||||
FalsingCollector falsingCollector, ShadeController shadeController,
|
FalsingCollector falsingCollector,
|
||||||
NotificationLockscreenUserManager notificationLockscreenUserManager,
|
NotificationLockscreenUserManager notificationLockscreenUserManager,
|
||||||
NotificationEntryManager notificationEntryManager,
|
NotificationEntryManager notificationEntryManager,
|
||||||
KeyguardStateController keyguardStateController,
|
KeyguardStateController keyguardStateController,
|
||||||
@@ -593,6 +637,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
KeyguardQsUserSwitchComponent.Factory keyguardQsUserSwitchComponentFactory,
|
KeyguardQsUserSwitchComponent.Factory keyguardQsUserSwitchComponentFactory,
|
||||||
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
KeyguardUserSwitcherComponent.Factory keyguardUserSwitcherComponentFactory,
|
||||||
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
|
KeyguardStatusBarViewComponent.Factory keyguardStatusBarViewComponentFactory,
|
||||||
|
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||||
QSDetailDisplayer qsDetailDisplayer,
|
QSDetailDisplayer qsDetailDisplayer,
|
||||||
NotificationGroupManagerLegacy groupManager,
|
NotificationGroupManagerLegacy groupManager,
|
||||||
NotificationIconAreaController notificationIconAreaController,
|
NotificationIconAreaController notificationIconAreaController,
|
||||||
@@ -681,6 +726,8 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||||
|
lockscreenShadeTransitionController.setNotificationPanelController(this);
|
||||||
mKeyguardStateController.addCallback(keyguardMonitorCallback);
|
mKeyguardStateController.addCallback(keyguardMonitorCallback);
|
||||||
DynamicPrivacyControlListener
|
DynamicPrivacyControlListener
|
||||||
dynamicPrivacyControlListener =
|
dynamicPrivacyControlListener =
|
||||||
@@ -694,7 +741,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
});
|
});
|
||||||
mBottomAreaShadeAlphaAnimator.setDuration(160);
|
mBottomAreaShadeAlphaAnimator.setDuration(160);
|
||||||
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
|
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
|
||||||
mShadeController = shadeController;
|
|
||||||
mLockscreenUserManager = notificationLockscreenUserManager;
|
mLockscreenUserManager = notificationLockscreenUserManager;
|
||||||
mEntryManager = notificationEntryManager;
|
mEntryManager = notificationEntryManager;
|
||||||
mConversationNotificationManager = conversationNotificationManager;
|
mConversationNotificationManager = conversationNotificationManager;
|
||||||
@@ -753,14 +799,22 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mOnEmptySpaceClickListener);
|
mOnEmptySpaceClickListener);
|
||||||
addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
|
addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
|
||||||
mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area);
|
mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area);
|
||||||
|
mPreviewContainer = mView.findViewById(R.id.preview_container);
|
||||||
|
mKeyguardBottomArea.setPreviewContainer(mPreviewContainer);
|
||||||
mLastOrientation = mResources.getConfiguration().orientation;
|
mLastOrientation = mResources.getConfiguration().orientation;
|
||||||
|
|
||||||
initBottomArea();
|
initBottomArea();
|
||||||
|
|
||||||
mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController);
|
mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController);
|
||||||
mQsFrame = mView.findViewById(R.id.qs_frame);
|
mQsFrame = mView.findViewById(R.id.qs_frame);
|
||||||
mPulseExpansionHandler.setUp(
|
mPulseExpansionHandler.setUp(mNotificationStackScrollLayoutController,
|
||||||
mNotificationStackScrollLayoutController, mExpansionCallback, mShadeController);
|
amount -> {
|
||||||
|
float progress = amount / mView.getHeight();
|
||||||
|
float overstretch = Interpolators.getOvershootInterpolation(progress,
|
||||||
|
(float) mMaxOverscrollAmountForDragDown / mView.getHeight(),
|
||||||
|
0.2f);
|
||||||
|
setOverStrechAmount(overstretch);
|
||||||
|
});
|
||||||
mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
|
mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onFullyHiddenChanged(boolean isFullyHidden) {
|
public void onFullyHiddenChanged(boolean isFullyHidden) {
|
||||||
@@ -816,6 +870,10 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
com.android.internal.R.dimen.status_bar_height);
|
com.android.internal.R.dimen.status_bar_height);
|
||||||
mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
|
mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
|
||||||
R.dimen.heads_up_status_bar_padding);
|
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(
|
mScrimCornerRadius = mResources.getDimensionPixelSize(
|
||||||
R.dimen.notification_scrim_corner_radius);
|
R.dimen.notification_scrim_corner_radius);
|
||||||
mScreenCornerRadius = mResources.getDimensionPixelSize(
|
mScreenCornerRadius = mResources.getDimensionPixelSize(
|
||||||
@@ -993,6 +1051,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate(
|
mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate(
|
||||||
R.layout.keyguard_bottom_area, mView, false);
|
R.layout.keyguard_bottom_area, mView, false);
|
||||||
mKeyguardBottomArea.initFrom(oldBottomArea);
|
mKeyguardBottomArea.initFrom(oldBottomArea);
|
||||||
|
mKeyguardBottomArea.setPreviewContainer(mPreviewContainer);
|
||||||
mView.addView(mKeyguardBottomArea, index);
|
mView.addView(mKeyguardBottomArea, index);
|
||||||
initBottomArea();
|
initBottomArea();
|
||||||
mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
|
mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
|
||||||
@@ -1114,58 +1173,28 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
* showing.
|
* showing.
|
||||||
*/
|
*/
|
||||||
private void positionClockAndNotifications() {
|
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 animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
|
||||||
boolean animateClock = animate || mAnimateNextPositionUpdate;
|
|
||||||
int stackScrollerPadding;
|
int stackScrollerPadding;
|
||||||
if (mBarState != KEYGUARD) {
|
boolean onKeyguard = isOnKeyguard();
|
||||||
|
if (onKeyguard || forceClockUpdate) {
|
||||||
|
updateClockAppearance();
|
||||||
|
}
|
||||||
|
if (!onKeyguard) {
|
||||||
stackScrollerPadding = getUnlockedStackScrollerPadding();
|
stackScrollerPadding = getUnlockedStackScrollerPadding();
|
||||||
} else {
|
} 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;
|
stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
mNotificationStackScrollLayoutController.setIntrinsicPadding(stackScrollerPadding);
|
mNotificationStackScrollLayoutController.setIntrinsicPadding(stackScrollerPadding);
|
||||||
mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
|
mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
|
||||||
|
|
||||||
@@ -1175,6 +1204,60 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mAnimateNextPositionUpdate = false;
|
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
|
* @return the padding of the stackscroller when unlocked
|
||||||
*/
|
*/
|
||||||
@@ -1606,7 +1689,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
|
|
||||||
private boolean flingExpandsQs(float vel) {
|
private boolean flingExpandsQs(float vel) {
|
||||||
if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
|
if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
|
||||||
return getQsExpansionFraction() > 0.5f;
|
return computeQsExpansionFraction() > 0.5f;
|
||||||
} else {
|
} else {
|
||||||
return vel > 0;
|
return vel > 0;
|
||||||
}
|
}
|
||||||
@@ -1619,7 +1702,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
return !mQsTouchAboveFalsingThreshold;
|
return !mQsTouchAboveFalsingThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float getQsExpansionFraction() {
|
private float computeQsExpansionFraction() {
|
||||||
return Math.min(
|
return Math.min(
|
||||||
1f, (mQsExpansionHeight - mQsMinExpansionHeight) / (mQsMaxExpansionHeight
|
1f, (mQsExpansionHeight - mQsMinExpansionHeight) / (mQsMaxExpansionHeight
|
||||||
- mQsMinExpansionHeight));
|
- mQsMinExpansionHeight));
|
||||||
@@ -1844,7 +1927,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mQsTracking = false;
|
mQsTracking = false;
|
||||||
mTrackingPointer = -1;
|
mTrackingPointer = -1;
|
||||||
trackMovement(event);
|
trackMovement(event);
|
||||||
float fraction = getQsExpansionFraction();
|
float fraction = computeQsExpansionFraction();
|
||||||
if (fraction != 0f || y >= mInitialTouchY) {
|
if (fraction != 0f || y >= mInitialTouchY) {
|
||||||
flingQsWithCurrentVelocity(y,
|
flingQsWithCurrentVelocity(y,
|
||||||
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
|
event.getActionMasked() == MotionEvent.ACTION_CANCEL);
|
||||||
@@ -2050,18 +2133,19 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
|
|
||||||
protected void updateQsExpansion() {
|
protected void updateQsExpansion() {
|
||||||
if (mQs == null) return;
|
if (mQs == null) return;
|
||||||
float qsExpansionFraction = getQsExpansionFraction();
|
float qsExpansionFraction = computeQsExpansionFraction();
|
||||||
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
|
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
|
||||||
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
|
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
|
||||||
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
|
int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
|
||||||
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
|
mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
|
||||||
|
setQSClippingBounds();
|
||||||
mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
|
mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
|
||||||
mDepthController.setQsPanelExpansion(qsExpansionFraction);
|
mDepthController.setQsPanelExpansion(qsExpansionFraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Runnable mOnStackYChanged = () -> {
|
private Runnable mOnStackYChanged = () -> {
|
||||||
if (mQs != null) {
|
if (mQs != null) {
|
||||||
setNotificationBounds();
|
setQSClippingBounds();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2069,57 +2153,121 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
|
* Updates scrim bounds, QS clipping, and KSV clipping as well based on the bounds of the shade
|
||||||
* and QS state.
|
* and QS state.
|
||||||
*/
|
*/
|
||||||
private void setNotificationBounds() {
|
private void setQSClippingBounds() {
|
||||||
int top = 0;
|
int top = 0;
|
||||||
int bottom = 0;
|
int bottom = 0;
|
||||||
int left = 0;
|
int left = 0;
|
||||||
int right = 0;
|
int right = 0;
|
||||||
|
|
||||||
final int qsPanelBottomY = calculateQsBottomPosition(getQsExpansionFraction());
|
final int qsPanelBottomY = calculateQsBottomPosition(computeQsExpansionFraction());
|
||||||
final boolean visible = (getQsExpansionFraction() > 0 || qsPanelBottomY > 0)
|
final boolean visible = (computeQsExpansionFraction() > 0 || qsPanelBottomY > 0)
|
||||||
&& !mShouldUseSplitNotificationShade;
|
&& !mShouldUseSplitNotificationShade;
|
||||||
final float notificationTop = mAmbientState.getStackY() - mAmbientState.getScrollY();
|
|
||||||
setQsExpansionEnabled(mAmbientState.getScrollY() == 0);
|
setQsExpansionEnabled(mAmbientState.getScrollY() == 0);
|
||||||
|
|
||||||
int radius = mScrimCornerRadius;
|
|
||||||
if (!mShouldUseSplitNotificationShade) {
|
if (!mShouldUseSplitNotificationShade) {
|
||||||
top = (int) (isOnKeyguard() ? Math.min(qsPanelBottomY, notificationTop)
|
if (mTransitioningToFullShadeProgress > 0.0f) {
|
||||||
: notificationTop);
|
// 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();
|
bottom = getView().getBottom();
|
||||||
left = getView().getLeft();
|
left = getView().getLeft();
|
||||||
right = getView().getRight();
|
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
|
} else if (qsPanelBottomY > 0) { // so bounds are empty on lockscreen
|
||||||
top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding);
|
top = Math.min(qsPanelBottomY, mSplitShadeNotificationsTopPadding);
|
||||||
bottom = mNotificationStackScrollLayoutController.getHeight();
|
bottom = mNotificationStackScrollLayoutController.getHeight();
|
||||||
left = mNotificationStackScrollLayoutController.getLeft();
|
left = mNotificationStackScrollLayoutController.getLeft();
|
||||||
right = mNotificationStackScrollLayoutController.getRight();
|
right = mNotificationStackScrollLayoutController.getRight();
|
||||||
}
|
}
|
||||||
|
applyQSClippingBounds(left, top, right, bottom, visible);
|
||||||
|
}
|
||||||
|
|
||||||
// Fancy clipping for quick settings
|
private void applyQSClippingBounds(int left, int top, int right, int bottom,
|
||||||
if (mQs != null) {
|
boolean visible) {
|
||||||
mQs.setFancyClipping(top, bottom, radius, 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) {
|
if (!mShouldUseSplitNotificationShade) {
|
||||||
// The padding on this area is large enough that we can use a cheaper clipping strategy
|
// The padding on this area is large enough that we can use a cheaper clipping strategy
|
||||||
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
|
mKeyguardStatusAreaClipBounds.set(left, top, right, bottom);
|
||||||
mKeyguardStatusViewController.setClipBounds(visible
|
mKeyguardStatusViewController.setClipBounds(visible
|
||||||
? mKeyguardStatusAreaClipBounds : null);
|
? 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.setNotificationsBounds(left, top, right, bottom);
|
||||||
mScrimController.setScrimCornerRadius(radius);
|
mScrimController.setScrimCornerRadius(radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float getQSEdgePosition() {
|
||||||
|
// TODO: replace StackY with unified calculation
|
||||||
|
return mAmbientState.getStackY() - mAmbientState.getScrollY();
|
||||||
|
}
|
||||||
|
|
||||||
private int calculateQsBottomPosition(float qsExpansionFraction) {
|
private int calculateQsBottomPosition(float qsExpansionFraction) {
|
||||||
int qsBottomY = (int) getHeaderTranslation() + mQs.getQsMinExpansionHeight();
|
if (mTransitioningToFullShadeProgress > 0.0f) {
|
||||||
if (qsExpansionFraction != 0.0) {
|
return mTransitionToFullShadeQSPosition;
|
||||||
qsBottomY = (int) MathUtils.lerp(
|
} else {
|
||||||
qsBottomY, mQs.getDesiredHeight(), qsExpansionFraction);
|
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() {
|
private String determineAccessibilityPaneTitle() {
|
||||||
@@ -2163,7 +2311,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
// from a scrolled quick settings.
|
// from a scrolled quick settings.
|
||||||
return MathUtils.lerp((float) getKeyguardNotificationStaticPadding(),
|
return MathUtils.lerp((float) getKeyguardNotificationStaticPadding(),
|
||||||
(float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
|
(float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
|
||||||
getQsExpansionFraction());
|
computeQsExpansionFraction());
|
||||||
} else {
|
} else {
|
||||||
return mQsExpansionHeight + mQsNotificationTopPadding;
|
return mQsExpansionHeight + mQsNotificationTopPadding;
|
||||||
}
|
}
|
||||||
@@ -2200,15 +2348,65 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateQSPulseExpansion() {
|
private void updateQSPulseExpansion() {
|
||||||
if (mQs != null) {
|
if (mQs != null) {
|
||||||
mQs.setShowCollapsedOnKeyguard(
|
mQs.setPulseExpanding(
|
||||||
mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()
|
mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()
|
||||||
&& mNotificationStackScrollLayoutController.isPulseExpanding());
|
&& 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) {
|
private void trackMovement(MotionEvent event) {
|
||||||
if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
|
if (mQsVelocityTracker != null) mQsVelocityTracker.addMovement(event);
|
||||||
}
|
}
|
||||||
@@ -2632,7 +2830,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
if (!mKeyguardShowing) {
|
if (!mKeyguardShowing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
|
float alphaQsExpansion = 1 - Math.min(1, computeQsExpansionFraction() * 2);
|
||||||
float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
|
float newAlpha = Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
|
||||||
* mKeyguardStatusBarAnimateAlpha;
|
* mKeyguardStatusBarAnimateAlpha;
|
||||||
newAlpha *= 1.0f - mKeyguardHeadsUpShowingAmount;
|
newAlpha *= 1.0f - mKeyguardHeadsUpShowingAmount;
|
||||||
@@ -2655,7 +2853,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
float expansionAlpha = MathUtils.map(
|
float expansionAlpha = MathUtils.map(
|
||||||
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
|
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
|
||||||
getExpandedFraction());
|
getExpandedFraction());
|
||||||
float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
|
float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction());
|
||||||
alpha *= mBottomAreaShadeAlpha;
|
alpha *= mBottomAreaShadeAlpha;
|
||||||
mKeyguardBottomArea.setAffordanceAlpha(alpha);
|
mKeyguardBottomArea.setAffordanceAlpha(alpha);
|
||||||
mKeyguardBottomArea.setImportantForAccessibility(
|
mKeyguardBottomArea.setImportantForAccessibility(
|
||||||
@@ -2677,7 +2875,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
float expansionAlpha = MathUtils.map(
|
float expansionAlpha = MathUtils.map(
|
||||||
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
|
isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f,
|
||||||
getExpandedFraction());
|
getExpandedFraction());
|
||||||
float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction());
|
float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction());
|
||||||
mBigClockContainer.setAlpha(alpha);
|
mBigClockContainer.setAlpha(alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3229,6 +3427,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mHeightListener.onQsHeightChanged();
|
mHeightListener.onQsHeightChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
mLockscreenShadeTransitionController.setQS(mQs);
|
||||||
mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView());
|
mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView());
|
||||||
updateQsExpansion();
|
updateQsExpansion();
|
||||||
}
|
}
|
||||||
@@ -3466,9 +3665,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
StatusBar statusBar,
|
StatusBar statusBar,
|
||||||
NotificationShelfController notificationShelfController) {
|
NotificationShelfController notificationShelfController) {
|
||||||
setStatusBar(statusBar);
|
setStatusBar(statusBar);
|
||||||
mNotificationStackScrollLayoutController.setNotificationPanelController(this);
|
|
||||||
mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
|
mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
|
||||||
mNotificationShelfController = notificationShelfController;
|
mNotificationShelfController = notificationShelfController;
|
||||||
|
mLockscreenShadeTransitionController.bindController(notificationShelfController);
|
||||||
updateMaxDisplayedNotifications(true);
|
updateMaxDisplayedNotifications(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3519,10 +3718,6 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
return new OnLayoutChangeListener();
|
return new OnLayoutChangeListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEmptyDragAmount(float amount) {
|
|
||||||
mExpansionCallback.setEmptyDragAmount(amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected TouchHandler createTouchHandler() {
|
protected TouchHandler createTouchHandler() {
|
||||||
return new TouchHandler() {
|
return new TouchHandler() {
|
||||||
@@ -3991,7 +4186,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
mClockPositionResult.clockX,
|
mClockPositionResult.clockX,
|
||||||
mClockPositionResult.clockYFullyDozing,
|
mClockPositionResult.clockYFullyDozing,
|
||||||
mClockPositionResult.clockScale,
|
mClockPositionResult.clockScale,
|
||||||
false);
|
false /* animate */);
|
||||||
}
|
}
|
||||||
|
|
||||||
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
|
mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
|
||||||
@@ -4007,11 +4202,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
if (oldState == KEYGUARD && (goingToFullShade
|
if (oldState == KEYGUARD && (goingToFullShade
|
||||||
|| statusBarState == StatusBarState.SHADE_LOCKED)) {
|
|| statusBarState == StatusBarState.SHADE_LOCKED)) {
|
||||||
animateKeyguardStatusBarOut();
|
animateKeyguardStatusBarOut();
|
||||||
long
|
updateQSMinHeight();
|
||||||
delay =
|
|
||||||
mBarState == StatusBarState.SHADE_LOCKED ? 0
|
|
||||||
: mKeyguardStateController.calculateGoingToFullShadeDelay();
|
|
||||||
mQs.animateHeaderSlidingIn(delay);
|
|
||||||
} else if (oldState == StatusBarState.SHADE_LOCKED
|
} else if (oldState == StatusBarState.SHADE_LOCKED
|
||||||
&& statusBarState == KEYGUARD) {
|
&& statusBarState == KEYGUARD) {
|
||||||
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
|
||||||
@@ -4058,11 +4249,12 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExpansionCallback implements PulseExpansionHandler.ExpansionCallback {
|
/**
|
||||||
public void setEmptyDragAmount(float amount) {
|
* Sets the overstretch amount in raw pixels when dragging down.
|
||||||
mEmptyDragAmount = amount * 0.2f;
|
*/
|
||||||
positionClockAndNotifications();
|
public void setOverStrechAmount(float amount) {
|
||||||
}
|
mOverStretchAmount = amount;
|
||||||
|
positionClockAndNotifications(true /* forceUpdate */);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OnAttachStateChangeListener implements View.OnAttachStateChangeListener {
|
private class OnAttachStateChangeListener implements View.OnAttachStateChangeListener {
|
||||||
@@ -4109,11 +4301,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
// Calculate quick setting heights.
|
// Calculate quick setting heights.
|
||||||
int oldMaxHeight = mQsMaxExpansionHeight;
|
int oldMaxHeight = mQsMaxExpansionHeight;
|
||||||
if (mQs != null) {
|
if (mQs != null) {
|
||||||
float previousMin = mQsMinExpansionHeight;
|
updateQSMinHeight();
|
||||||
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
|
|
||||||
if (mQsExpansionHeight == previousMin) {
|
|
||||||
mQsExpansionHeight = mQsMinExpansionHeight;
|
|
||||||
}
|
|
||||||
mQsMaxExpansionHeight = mQs.getDesiredHeight();
|
mQsMaxExpansionHeight = mQs.getDesiredHeight();
|
||||||
mNotificationStackScrollLayoutController.setMaxTopPadding(
|
mNotificationStackScrollLayoutController.setMaxTopPadding(
|
||||||
mQsMaxExpansionHeight + mQsNotificationTopPadding);
|
mQsMaxExpansionHeight + mQsNotificationTopPadding);
|
||||||
@@ -4155,6 +4343,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 {
|
private class DebugDrawable extends Drawable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -34,15 +34,14 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.systemui.ExpandHelper;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.classifier.FalsingCollector;
|
import com.android.systemui.classifier.FalsingCollector;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
import com.android.systemui.doze.DozeLog;
|
import com.android.systemui.doze.DozeLog;
|
||||||
import com.android.systemui.plugins.FalsingManager;
|
|
||||||
import com.android.systemui.shared.plugins.PluginManager;
|
import com.android.systemui.shared.plugins.PluginManager;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.DragDownHelper;
|
import com.android.systemui.statusbar.DragDownHelper;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||||
@@ -73,7 +72,6 @@ public class NotificationShadeWindowViewController {
|
|||||||
private final DynamicPrivacyController mDynamicPrivacyController;
|
private final DynamicPrivacyController mDynamicPrivacyController;
|
||||||
private final KeyguardBypassController mBypassController;
|
private final KeyguardBypassController mBypassController;
|
||||||
private final PluginManager mPluginManager;
|
private final PluginManager mPluginManager;
|
||||||
private final FalsingManager mFalsingManager;
|
|
||||||
private final FalsingCollector mFalsingCollector;
|
private final FalsingCollector mFalsingCollector;
|
||||||
private final TunerService mTunerService;
|
private final TunerService mTunerService;
|
||||||
private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
|
private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
|
||||||
@@ -87,6 +85,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
private final ShadeController mShadeController;
|
private final ShadeController mShadeController;
|
||||||
private final NotificationShadeDepthController mDepthController;
|
private final NotificationShadeDepthController mDepthController;
|
||||||
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
|
private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
|
||||||
|
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||||
|
|
||||||
private GestureDetector mGestureDetector;
|
private GestureDetector mGestureDetector;
|
||||||
@@ -119,7 +118,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
PulseExpansionHandler pulseExpansionHandler,
|
PulseExpansionHandler pulseExpansionHandler,
|
||||||
DynamicPrivacyController dynamicPrivacyController,
|
DynamicPrivacyController dynamicPrivacyController,
|
||||||
KeyguardBypassController bypassController,
|
KeyguardBypassController bypassController,
|
||||||
FalsingManager falsingManager,
|
LockscreenShadeTransitionController transitionController,
|
||||||
FalsingCollector falsingCollector,
|
FalsingCollector falsingCollector,
|
||||||
PluginManager pluginManager,
|
PluginManager pluginManager,
|
||||||
TunerService tunerService,
|
TunerService tunerService,
|
||||||
@@ -143,7 +142,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
mPulseExpansionHandler = pulseExpansionHandler;
|
mPulseExpansionHandler = pulseExpansionHandler;
|
||||||
mDynamicPrivacyController = dynamicPrivacyController;
|
mDynamicPrivacyController = dynamicPrivacyController;
|
||||||
mBypassController = bypassController;
|
mBypassController = bypassController;
|
||||||
mFalsingManager = falsingManager;
|
mLockscreenShadeTransitionController = transitionController;
|
||||||
mFalsingCollector = falsingCollector;
|
mFalsingCollector = falsingCollector;
|
||||||
mPluginManager = pluginManager;
|
mPluginManager = pluginManager;
|
||||||
mTunerService = tunerService;
|
mTunerService = tunerService;
|
||||||
@@ -406,12 +405,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ExpandHelper.Callback expandHelperCallback = mStackScrollLayout.getExpandHelperCallback();
|
setDragDownHelper(mLockscreenShadeTransitionController.getTouchHelper());
|
||||||
DragDownHelper.DragDownCallback dragDownCallback = mStackScrollLayout.getDragDownCallback();
|
|
||||||
setDragDownHelper(
|
|
||||||
new DragDownHelper(
|
|
||||||
mView.getContext(), mView, expandHelperCallback,
|
|
||||||
dragDownCallback, mFalsingManager, mFalsingCollector));
|
|
||||||
|
|
||||||
mDepthController.setRoot(mView);
|
mDepthController.setRoot(mView);
|
||||||
mNotificationPanelViewController.addExpansionListener(mDepthController);
|
mNotificationPanelViewController.addExpansionListener(mDepthController);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import android.os.Handler;
|
|||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.MathUtils;
|
import android.util.MathUtils;
|
||||||
|
import android.util.Pair;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
import android.view.animation.DecelerateInterpolator;
|
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.KeyguardUpdateMonitor;
|
||||||
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||||
import com.android.settingslib.Utils;
|
import com.android.settingslib.Utils;
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
import com.android.systemui.DejankUtils;
|
import com.android.systemui.DejankUtils;
|
||||||
import com.android.systemui.Dumpable;
|
import com.android.systemui.Dumpable;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.animation.Interpolators;
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
@@ -98,6 +99,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
public static final int OPAQUE = 2;
|
public static final int OPAQUE = 2;
|
||||||
private boolean mClipsQsScrim;
|
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 = {
|
@IntDef(prefix = {"VISIBILITY_"}, value = {
|
||||||
TRANSPARENT,
|
TRANSPARENT,
|
||||||
SEMI_TRANSPARENT,
|
SEMI_TRANSPARENT,
|
||||||
@@ -357,7 +370,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
+ mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: "
|
+ mInFrontAlpha + ", back: " + mBehindAlpha + ", notif: "
|
||||||
+ mNotificationsAlpha);
|
+ mNotificationsAlpha);
|
||||||
}
|
}
|
||||||
applyExpansionToAlpha();
|
applyStateToAlpha();
|
||||||
|
|
||||||
// Scrim might acquire focus when user is navigating with a D-pad or a keyboard.
|
// 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.
|
// 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)) {
|
if (!(relevantState && mExpansionAffectsAlpha)) {
|
||||||
return;
|
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
|
* Set bounds for notifications background, all coordinates are absolute
|
||||||
*/
|
*/
|
||||||
@@ -534,7 +574,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
if (!(relevantState && mExpansionAffectsAlpha)) {
|
if (!(relevantState && mExpansionAffectsAlpha)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
applyAndDispatchExpansion();
|
applyAndDispatchState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,6 +593,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
if (mScrimBehind != null) {
|
if (mScrimBehind != null) {
|
||||||
mScrimBehind.enableBottomEdgeConcave(mClipsQsScrim);
|
mScrimBehind.enableBottomEdgeConcave(mClipsQsScrim);
|
||||||
}
|
}
|
||||||
|
if (mState != ScrimState.UNINITIALIZED) {
|
||||||
|
// the clipScrimState has changed, let's reprepare ourselves
|
||||||
|
mState.prepare(mState);
|
||||||
|
applyAndDispatchState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -583,7 +628,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyExpansionToAlpha() {
|
private void applyStateToAlpha() {
|
||||||
if (!mExpansionAffectsAlpha) {
|
if (!mExpansionAffectsAlpha) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -608,47 +653,40 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
mInFrontAlpha = 0;
|
mInFrontAlpha = 0;
|
||||||
} else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
|
} else if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED
|
||||||
|| mState == ScrimState.PULSING) {
|
|| mState == ScrimState.PULSING) {
|
||||||
// Either darken of make the scrim transparent when you
|
Pair<Integer, Float> result = calculateBackStateForState(mState);
|
||||||
// pull down the shade
|
int behindTint = result.first;
|
||||||
float interpolatedFract = getInterpolatedFraction();
|
float behindAlpha = result.second;
|
||||||
float stateBehind = mClipsQsScrim ? mState.getNotifAlpha() : mState.getBehindAlpha();
|
if (mTransitionToFullShadeProgress > 0.0f) {
|
||||||
float backAlpha;
|
Pair<Integer, Float> shadeResult = calculateBackStateForState(
|
||||||
if (mDarkenWhileDragging) {
|
ScrimState.SHADE_LOCKED);
|
||||||
backAlpha = MathUtils.lerp(mDefaultScrimAlpha, stateBehind,
|
behindAlpha = MathUtils.lerp(behindAlpha, shadeResult.second,
|
||||||
interpolatedFract);
|
mTransitionToFullShadeProgress);
|
||||||
} else {
|
behindTint = ColorUtils.blendARGB(behindTint, shadeResult.first,
|
||||||
backAlpha = MathUtils.lerp(0 /* start */, stateBehind,
|
mTransitionToFullShadeProgress);
|
||||||
interpolatedFract);
|
|
||||||
}
|
}
|
||||||
mInFrontAlpha = mState.getFrontAlpha();
|
mInFrontAlpha = mState.getFrontAlpha();
|
||||||
int backTint;
|
|
||||||
if (mClipsQsScrim) {
|
if (mClipsQsScrim) {
|
||||||
backTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getNotifTint(),
|
mNotificationsAlpha = behindAlpha;
|
||||||
mState.getNotifTint(), interpolatedFract);
|
mNotificationsTint = behindTint;
|
||||||
} 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;
|
|
||||||
mBehindAlpha = 1;
|
mBehindAlpha = 1;
|
||||||
mBehindTint = Color.BLACK;
|
mBehindTint = Color.BLACK;
|
||||||
} else {
|
} else {
|
||||||
mBehindAlpha = backAlpha;
|
mBehindAlpha = behindAlpha;
|
||||||
if (mState == ScrimState.SHADE_LOCKED) {
|
if (mState == ScrimState.SHADE_LOCKED) {
|
||||||
// going from KEYGUARD to SHADE_LOCKED state
|
// going from KEYGUARD to SHADE_LOCKED state
|
||||||
mNotificationsAlpha = getInterpolatedFraction();
|
mNotificationsAlpha = getInterpolatedFraction();
|
||||||
} else {
|
} else {
|
||||||
mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion);
|
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)) {
|
if (isNaN(mBehindAlpha) || isNaN(mInFrontAlpha) || isNaN(mNotificationsAlpha)) {
|
||||||
@@ -658,8 +696,39 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyAndDispatchExpansion() {
|
private Pair<Integer, Float> calculateBackStateForState(ScrimState state) {
|
||||||
applyExpansionToAlpha();
|
// 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) {
|
if (mUpdatePending) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1195,7 +1264,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
|
public void setExpansionAffectsAlpha(boolean expansionAffectsAlpha) {
|
||||||
mExpansionAffectsAlpha = expansionAffectsAlpha;
|
mExpansionAffectsAlpha = expansionAffectsAlpha;
|
||||||
if (expansionAffectsAlpha) {
|
if (expansionAffectsAlpha) {
|
||||||
applyAndDispatchExpansion();
|
applyAndDispatchState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.phone;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.android.systemui.statusbar.StatusBarState;
|
import com.android.systemui.statusbar.StatusBarState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,15 +75,6 @@ public interface ShadeController {
|
|||||||
*/
|
*/
|
||||||
void runPostCollapseRunnables();
|
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
|
* Close the shade if it was open
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
package com.android.systemui.statusbar.phone;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
@@ -181,12 +180,6 @@ public class ShadeControllerImpl implements ShadeController {
|
|||||||
mStatusBarKeyguardViewManager.readyForKeyguardDone();
|
mStatusBarKeyguardViewManager.readyForKeyguardDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void goToLockedShade(View startingChild) {
|
|
||||||
// TODO: Move this code out of StatusBar into ShadeController.
|
|
||||||
getStatusBar().goToLockedShade(startingChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean collapsePanel() {
|
public boolean collapsePanel() {
|
||||||
if (!getNotificationPanelViewController().isFullyCollapsed()) {
|
if (!getNotificationPanelViewController().isFullyCollapsed()) {
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ import com.android.systemui.statusbar.KeyboardShortcuts;
|
|||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
import com.android.systemui.statusbar.LiftReveal;
|
import com.android.systemui.statusbar.LiftReveal;
|
||||||
import com.android.systemui.statusbar.LightRevealScrim;
|
import com.android.systemui.statusbar.LightRevealScrim;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||||
import com.android.systemui.statusbar.NotificationPresenter;
|
import com.android.systemui.statusbar.NotificationPresenter;
|
||||||
@@ -347,6 +348,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
ONLY_CORE_APPS = onlyCoreApps;
|
ONLY_CORE_APPS = onlyCoreApps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
|
|
||||||
public interface ExpansionChangedListener {
|
public interface ExpansionChangedListener {
|
||||||
void onExpansionChanged(float expansion, boolean expanded);
|
void onExpansionChanged(float expansion, boolean expanded);
|
||||||
}
|
}
|
||||||
@@ -438,9 +441,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
|
|
||||||
KeyguardIndicationController mKeyguardIndicationController;
|
KeyguardIndicationController mKeyguardIndicationController;
|
||||||
|
|
||||||
// RemoteInputView to be activated after unlock
|
|
||||||
private View mPendingRemoteInputView;
|
|
||||||
|
|
||||||
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
|
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
|
||||||
|
|
||||||
private View mReportRejectedTouch;
|
private View mReportRejectedTouch;
|
||||||
@@ -650,12 +650,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
private final ScreenLifecycle mScreenLifecycle;
|
private final ScreenLifecycle mScreenLifecycle;
|
||||||
private final WakefulnessLifecycle mWakefulnessLifecycle;
|
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 boolean mNoAnimationOnNextBarModeChange;
|
||||||
private final SysuiStatusBarStateController mStatusBarStateController;
|
private final SysuiStatusBarStateController mStatusBarStateController;
|
||||||
|
|
||||||
@@ -798,6 +792,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
OngoingCallController ongoingCallController,
|
OngoingCallController ongoingCallController,
|
||||||
SystemStatusAnimationScheduler animationScheduler,
|
SystemStatusAnimationScheduler animationScheduler,
|
||||||
StatusBarLocationPublisher locationPublisher,
|
StatusBarLocationPublisher locationPublisher,
|
||||||
|
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||||
FeatureFlags featureFlags,
|
FeatureFlags featureFlags,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -882,6 +877,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
mAnimationScheduler = animationScheduler;
|
mAnimationScheduler = animationScheduler;
|
||||||
mStatusBarLocationPublisher = locationPublisher;
|
mStatusBarLocationPublisher = locationPublisher;
|
||||||
mFeatureFlags = featureFlags;
|
mFeatureFlags = featureFlags;
|
||||||
|
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||||
|
lockscreenShadeTransitionController.setStatusbar(this);
|
||||||
|
|
||||||
mExpansionChangedListeners = new ArrayList<>();
|
mExpansionChangedListeners = new ArrayList<>();
|
||||||
|
|
||||||
@@ -1422,7 +1419,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
mDozeScrimController, mScrimController, mNotificationShadeWindowController,
|
mDozeScrimController, mScrimController, mNotificationShadeWindowController,
|
||||||
mDynamicPrivacyController, mKeyguardStateController,
|
mDynamicPrivacyController, mKeyguardStateController,
|
||||||
mKeyguardIndicationController,
|
mKeyguardIndicationController,
|
||||||
this /* statusBar */, mShadeController, mCommandQueue, mInitController,
|
this /* statusBar */, mShadeController,
|
||||||
|
mLockscreenShadeTransitionController, mCommandQueue, mInitController,
|
||||||
mNotificationInterruptStateProvider);
|
mNotificationInterruptStateProvider);
|
||||||
|
|
||||||
mNotificationShelfController.setOnActivatedListener(mPresenter);
|
mNotificationShelfController.setOnActivatedListener(mPresenter);
|
||||||
@@ -1502,7 +1500,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
private void inflateShelf() {
|
private void inflateShelf() {
|
||||||
mNotificationShelfController = mSuperStatusBarViewFactory
|
mNotificationShelfController = mSuperStatusBarViewFactory
|
||||||
.getNotificationShelfController(mStackScroller);
|
.getNotificationShelfController(mStackScroller);
|
||||||
mNotificationShelfController.setOnClickListener(mGoToLockedShadeListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1675,7 +1672,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
|
final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
|
||||||
&& (mUserSetup || mUserSwitcherController == null
|
&& (mUserSetup || mUserSwitcherController == null
|
||||||
|| !mUserSwitcherController.isSimpleUserSwitcher())
|
|| !mUserSwitcherController.isSimpleUserSwitcher())
|
||||||
&& ((mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) == 0)
|
&& !isShadeDisabled()
|
||||||
&& ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
|
&& ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
|
||||||
&& !mDozing
|
&& !mDozing
|
||||||
&& !ONLY_CORE_APPS;
|
&& !ONLY_CORE_APPS;
|
||||||
@@ -1683,6 +1680,10 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
|
Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isShadeDisabled() {
|
||||||
|
return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public void addQsTile(ComponentName tile) {
|
public void addQsTile(ComponentName tile) {
|
||||||
if (mQSPanelController != null && mQSPanelController.getHost() != null) {
|
if (mQSPanelController != null && mQSPanelController.getHost() != null) {
|
||||||
mQSPanelController.getHost().addTile(tile);
|
mQSPanelController.getHost().addTile(tile);
|
||||||
@@ -3333,7 +3334,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
public void showKeyguard() {
|
public void showKeyguard() {
|
||||||
mStatusBarStateController.setKeyguardRequested(true);
|
mStatusBarStateController.setKeyguardRequested(true);
|
||||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
|
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
|
||||||
mPendingRemoteInputView = null;
|
|
||||||
updateIsKeyguard();
|
updateIsKeyguard();
|
||||||
mAssistManagerLazy.get().onLockscreenShown();
|
mAssistManagerLazy.get().onLockscreenShown();
|
||||||
}
|
}
|
||||||
@@ -3392,11 +3392,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
|
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
|
||||||
}
|
}
|
||||||
updatePanelExpansionForKeyguard();
|
updatePanelExpansionForKeyguard();
|
||||||
if (mDraggedDownEntry != null) {
|
|
||||||
mDraggedDownEntry.setUserLocked(false);
|
|
||||||
mDraggedDownEntry.notifyHeightChanged(false /* needsAnimation */);
|
|
||||||
mDraggedDownEntry = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePanelExpansionForKeyguard() {
|
private void updatePanelExpansionForKeyguard() {
|
||||||
@@ -3524,11 +3519,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
|
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
|
||||||
}
|
}
|
||||||
long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
|
long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
|
||||||
mNotificationPanelViewController.animateToFullShade(delay);
|
mLockscreenShadeTransitionController.onHideKeyguard(delay);
|
||||||
if (mDraggedDownEntry != null) {
|
|
||||||
mDraggedDownEntry.setUserLocked(false);
|
|
||||||
mDraggedDownEntry = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable layout transitions in navbar for this transition because the load is just
|
// Disable layout transitions in navbar for this transition because the load is just
|
||||||
// too heavy for the CPU and GPU on any device.
|
// 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() {
|
void instantCollapseNotificationPanel() {
|
||||||
mNotificationPanelViewController.instantCollapse();
|
mNotificationPanelViewController.instantCollapse();
|
||||||
mShadeController.runPostCollapseRunnables();
|
mShadeController.runPostCollapseRunnables();
|
||||||
@@ -3895,47 +3902,6 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
return mNotificationPanelViewController.getKeyguardBottomAreaView();
|
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.
|
* 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.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||||
import com.android.systemui.statusbar.NotificationPresenter;
|
import com.android.systemui.statusbar.NotificationPresenter;
|
||||||
@@ -112,6 +113,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
|||||||
private final KeyguardIndicationController mKeyguardIndicationController;
|
private final KeyguardIndicationController mKeyguardIndicationController;
|
||||||
private final StatusBar mStatusBar;
|
private final StatusBar mStatusBar;
|
||||||
private final ShadeController mShadeController;
|
private final ShadeController mShadeController;
|
||||||
|
private final LockscreenShadeTransitionController mShadeTransitionController;
|
||||||
private final CommandQueue mCommandQueue;
|
private final CommandQueue mCommandQueue;
|
||||||
|
|
||||||
private final AccessibilityManager mAccessibilityManager;
|
private final AccessibilityManager mAccessibilityManager;
|
||||||
@@ -138,6 +140,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
|||||||
KeyguardIndicationController keyguardIndicationController,
|
KeyguardIndicationController keyguardIndicationController,
|
||||||
StatusBar statusBar,
|
StatusBar statusBar,
|
||||||
ShadeController shadeController,
|
ShadeController shadeController,
|
||||||
|
LockscreenShadeTransitionController shadeTransitionController,
|
||||||
CommandQueue commandQueue,
|
CommandQueue commandQueue,
|
||||||
InitController initController,
|
InitController initController,
|
||||||
NotificationInterruptStateProvider notificationInterruptStateProvider) {
|
NotificationInterruptStateProvider notificationInterruptStateProvider) {
|
||||||
@@ -149,6 +152,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
|||||||
// TODO: use KeyguardStateController#isOccluded to remove this dependency
|
// TODO: use KeyguardStateController#isOccluded to remove this dependency
|
||||||
mStatusBar = statusBar;
|
mStatusBar = statusBar;
|
||||||
mShadeController = shadeController;
|
mShadeController = shadeController;
|
||||||
|
mShadeTransitionController = shadeTransitionController;
|
||||||
mCommandQueue = commandQueue;
|
mCommandQueue = commandQueue;
|
||||||
mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
|
mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
|
||||||
mNotificationShadeWindowController = notificationShadeWindowController;
|
mNotificationShadeWindowController = notificationShadeWindowController;
|
||||||
@@ -394,7 +398,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
|
|||||||
mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
|
mHeadsUpManager.setExpanded(clickedEntry, nowExpanded);
|
||||||
if (nowExpanded) {
|
if (nowExpanded) {
|
||||||
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
|
if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
|
||||||
mShadeController.goToLockedShade(clickedEntry.getRow());
|
mShadeTransitionController.goToLockedShade(clickedEntry.getRow());
|
||||||
} else if (clickedEntry.isSensitive()
|
} else if (clickedEntry.isSensitive()
|
||||||
&& mDynamicPrivacyController.isInLockedDownShade()) {
|
&& mDynamicPrivacyController.isInLockedDownShade()) {
|
||||||
mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
|
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.CommandQueue;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
@@ -213,6 +214,7 @@ public interface StatusBarPhoneModule {
|
|||||||
OngoingCallController ongoingCallController,
|
OngoingCallController ongoingCallController,
|
||||||
SystemStatusAnimationScheduler animationScheduler,
|
SystemStatusAnimationScheduler animationScheduler,
|
||||||
StatusBarLocationPublisher locationPublisher,
|
StatusBarLocationPublisher locationPublisher,
|
||||||
|
LockscreenShadeTransitionController transitionController,
|
||||||
FeatureFlags featureFlags,
|
FeatureFlags featureFlags,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
|
||||||
return new StatusBar(
|
return new StatusBar(
|
||||||
@@ -299,6 +301,7 @@ public interface StatusBarPhoneModule {
|
|||||||
ongoingCallController,
|
ongoingCallController,
|
||||||
animationScheduler,
|
animationScheduler,
|
||||||
locationPublisher,
|
locationPublisher,
|
||||||
|
transitionController,
|
||||||
featureFlags,
|
featureFlags,
|
||||||
keyguardUnlockAnimationController);
|
keyguardUnlockAnimationController);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import com.android.systemui.statusbar.StatusBarState
|
|||||||
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
|
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.statusbar.policy.KeyguardStateController
|
||||||
import com.android.systemui.util.animation.UniqueObjectHostView
|
import com.android.systemui.util.animation.UniqueObjectHostView
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
@@ -79,6 +80,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
|
|||||||
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
|
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
||||||
|
@Mock
|
||||||
|
private lateinit var configurationController: ConfigurationController
|
||||||
@Captor
|
@Captor
|
||||||
private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)>
|
private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)>
|
||||||
@Captor
|
@Captor
|
||||||
@@ -98,6 +101,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
|
|||||||
bypassController,
|
bypassController,
|
||||||
mediaCarouselController,
|
mediaCarouselController,
|
||||||
notificationLockscreenUserManager,
|
notificationLockscreenUserManager,
|
||||||
|
configurationController,
|
||||||
wakefulnessLifecycle,
|
wakefulnessLifecycle,
|
||||||
statusBarKeyguardViewManager)
|
statusBarKeyguardViewManager)
|
||||||
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
|
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,
|
mNotificationSectionsManager,
|
||||||
mGroupMembershipManger,
|
mGroupMembershipManger,
|
||||||
mGroupExpansionManager,
|
mGroupExpansionManager,
|
||||||
mStatusBarStateController,
|
|
||||||
mAmbientState,
|
mAmbientState,
|
||||||
mFeatureFlags);
|
mFeatureFlags);
|
||||||
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
|
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.NotificationMenuRowPlugin.OnMenuEventListener;
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
@@ -121,6 +122,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
|
|||||||
@Mock private NotificationEntryManager mEntryManager;
|
@Mock private NotificationEntryManager mEntryManager;
|
||||||
@Mock private IStatusBarService mIStatusBarService;
|
@Mock private IStatusBarService mIStatusBarService;
|
||||||
@Mock private UiEventLogger mUiEventLogger;
|
@Mock private UiEventLogger mUiEventLogger;
|
||||||
|
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
@Mock private ForegroundServiceDismissalFeatureController mFgFeatureController;
|
@Mock private ForegroundServiceDismissalFeatureController mFgFeatureController;
|
||||||
@Mock private ForegroundServiceSectionController mFgServicesSectionController;
|
@Mock private ForegroundServiceSectionController mFgServicesSectionController;
|
||||||
@Mock private ForegroundServiceDungeonView mForegroundServiceDungeonView;
|
@Mock private ForegroundServiceDungeonView mForegroundServiceDungeonView;
|
||||||
@@ -173,6 +175,7 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase {
|
|||||||
mNotifPipeline,
|
mNotifPipeline,
|
||||||
mNotifCollection,
|
mNotifCollection,
|
||||||
mEntryManager,
|
mEntryManager,
|
||||||
|
mLockscreenShadeTransitionController,
|
||||||
mIStatusBarService,
|
mIStatusBarService,
|
||||||
mUiEventLogger,
|
mUiEventLogger,
|
||||||
mFgFeatureController,
|
mFgFeatureController,
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ import com.android.systemui.qs.QSDetailDisplayer;
|
|||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
import com.android.systemui.statusbar.NotificationShelfController;
|
import com.android.systemui.statusbar.NotificationShelfController;
|
||||||
@@ -226,6 +227,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private NotificationShadeDepthController mNotificationShadeDepthController;
|
private NotificationShadeDepthController mNotificationShadeDepthController;
|
||||||
@Mock
|
@Mock
|
||||||
|
private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
|
@Mock
|
||||||
private AuthController mAuthController;
|
private AuthController mAuthController;
|
||||||
@Mock
|
@Mock
|
||||||
private ScrimController mScrimController;
|
private ScrimController mScrimController;
|
||||||
@@ -314,7 +317,9 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
|||||||
mKeyguardBypassController, mHeadsUpManager,
|
mKeyguardBypassController, mHeadsUpManager,
|
||||||
mock(NotificationRoundnessManager.class),
|
mock(NotificationRoundnessManager.class),
|
||||||
mStatusBarStateController,
|
mStatusBarStateController,
|
||||||
new FalsingManagerFake(), new FalsingCollectorFake());
|
new FalsingManagerFake(),
|
||||||
|
mLockscreenShadeTransitionController,
|
||||||
|
new FalsingCollectorFake());
|
||||||
when(mKeyguardStatusViewComponentFactory.build(any()))
|
when(mKeyguardStatusViewComponentFactory.build(any()))
|
||||||
.thenReturn(mKeyguardStatusViewComponent);
|
.thenReturn(mKeyguardStatusViewComponent);
|
||||||
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
|
when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
|
||||||
@@ -330,7 +335,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
|||||||
mResources,
|
mResources,
|
||||||
mLayoutInflater,
|
mLayoutInflater,
|
||||||
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
|
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
|
||||||
new FalsingManagerFake(), new FalsingCollectorFake(), mShadeController,
|
new FalsingManagerFake(), new FalsingCollectorFake(),
|
||||||
mNotificationLockscreenUserManager, mNotificationEntryManager,
|
mNotificationLockscreenUserManager, mNotificationEntryManager,
|
||||||
mKeyguardStateController, mStatusBarStateController, mDozeLog,
|
mKeyguardStateController, mStatusBarStateController, mDozeLog,
|
||||||
mDozeParameters, mCommandQueue, mVibratorHelper,
|
mDozeParameters, mCommandQueue, mVibratorHelper,
|
||||||
@@ -344,6 +349,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
|||||||
mKeyguardQsUserSwitchComponentFactory,
|
mKeyguardQsUserSwitchComponentFactory,
|
||||||
mKeyguardUserSwitcherComponentFactory,
|
mKeyguardUserSwitcherComponentFactory,
|
||||||
mKeyguardStatusBarViewComponentFactory,
|
mKeyguardStatusBarViewComponentFactory,
|
||||||
|
mLockscreenShadeTransitionController,
|
||||||
mQSDetailDisplayer,
|
mQSDetailDisplayer,
|
||||||
mGroupManager,
|
mGroupManager,
|
||||||
mNotificationAreaController,
|
mNotificationAreaController,
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.SystemUIFactory;
|
import com.android.systemui.SystemUIFactory;
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.classifier.FalsingCollectorFake;
|
import com.android.systemui.classifier.FalsingCollectorFake;
|
||||||
import com.android.systemui.classifier.FalsingManagerFake;
|
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
import com.android.systemui.doze.DozeLog;
|
import com.android.systemui.doze.DozeLog;
|
||||||
import com.android.systemui.shared.plugins.PluginManager;
|
import com.android.systemui.shared.plugins.PluginManager;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.DragDownHelper;
|
import com.android.systemui.statusbar.DragDownHelper;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
import com.android.systemui.statusbar.NotificationShadeDepthController;
|
||||||
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
import com.android.systemui.statusbar.NotificationShadeWindowController;
|
||||||
@@ -89,6 +89,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
|
@Mock private NotificationShadeWindowController mNotificationShadeWindowController;
|
||||||
@Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
|
@Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
|
||||||
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||||
|
@Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -112,7 +113,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
mPulseExpansionHandler,
|
mPulseExpansionHandler,
|
||||||
mDynamicPrivacyController,
|
mDynamicPrivacyController,
|
||||||
mBypassController,
|
mBypassController,
|
||||||
new FalsingManagerFake(),
|
mLockscreenShadeTransitionController,
|
||||||
new FalsingCollectorFake(),
|
new FalsingCollectorFake(),
|
||||||
mPluginManager,
|
mPluginManager,
|
||||||
mTunerService,
|
mTunerService,
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import android.graphics.Color;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
|
import android.util.MathUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -1121,6 +1122,32 @@ public class ScrimControllerTest extends SysuiTestCase {
|
|||||||
assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.8f, /* expansion */ 0.2f);
|
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) {
|
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
|
||||||
mScrimController.setPanelExpansion(expansion);
|
mScrimController.setPanelExpansion(expansion);
|
||||||
finishAnimationsImmediately();
|
finishAnimationsImmediately();
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import com.android.systemui.SysuiTestCase;
|
|||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||||
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
import com.android.systemui.statusbar.NotificationRemoteInputManager;
|
||||||
@@ -127,7 +128,8 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
|
|||||||
mock(NotificationShadeWindowController.class), mock(DynamicPrivacyController.class),
|
mock(NotificationShadeWindowController.class), mock(DynamicPrivacyController.class),
|
||||||
mock(KeyguardStateController.class),
|
mock(KeyguardStateController.class),
|
||||||
mock(KeyguardIndicationController.class), mStatusBar,
|
mock(KeyguardIndicationController.class), mStatusBar,
|
||||||
mock(ShadeControllerImpl.class), mCommandQueue, mInitController,
|
mock(ShadeControllerImpl.class), mock(LockscreenShadeTransitionController.class),
|
||||||
|
mCommandQueue, mInitController,
|
||||||
mNotificationInterruptStateProvider);
|
mNotificationInterruptStateProvider);
|
||||||
mInitController.executePostInitTasks();
|
mInitController.executePostInitTasks();
|
||||||
ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
|
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.CommandQueue;
|
||||||
import com.android.systemui.statusbar.FeatureFlags;
|
import com.android.systemui.statusbar.FeatureFlags;
|
||||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationListener;
|
import com.android.systemui.statusbar.NotificationListener;
|
||||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||||
import com.android.systemui.statusbar.NotificationMediaManager;
|
import com.android.systemui.statusbar.NotificationMediaManager;
|
||||||
@@ -267,6 +268,7 @@ public class StatusBarTest extends SysuiTestCase {
|
|||||||
@Mock private OngoingCallController mOngoingCallController;
|
@Mock private OngoingCallController mOngoingCallController;
|
||||||
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
|
@Mock private SystemStatusAnimationScheduler mAnimationScheduler;
|
||||||
@Mock private StatusBarLocationPublisher mLocationPublisher;
|
@Mock private StatusBarLocationPublisher mLocationPublisher;
|
||||||
|
@Mock private LockscreenShadeTransitionController mLockscreenTransitionController;
|
||||||
@Mock private FeatureFlags mFeatureFlags;
|
@Mock private FeatureFlags mFeatureFlags;
|
||||||
@Mock private IWallpaperManager mWallpaperManager;
|
@Mock private IWallpaperManager mWallpaperManager;
|
||||||
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||||
@@ -437,6 +439,7 @@ public class StatusBarTest extends SysuiTestCase {
|
|||||||
mOngoingCallController,
|
mOngoingCallController,
|
||||||
mAnimationScheduler,
|
mAnimationScheduler,
|
||||||
mLocationPublisher,
|
mLocationPublisher,
|
||||||
|
mLockscreenTransitionController,
|
||||||
mFeatureFlags,
|
mFeatureFlags,
|
||||||
mKeyguardUnlockAnimationController);
|
mKeyguardUnlockAnimationController);
|
||||||
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
|
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
|
||||||
|
|||||||
Reference in New Issue
Block a user