Merge "Add flag to enable SettingsBackupAgent to collect B&R agent metrics." into main
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0268b5b..a4d8a5c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6767,19 +6767,6 @@
}
/**
- * Construct a RemoteViews for the ambient version of the notification.
- *
- * @hide
- */
- public RemoteViews makeAmbientNotification() {
- RemoteViews headsUpContentView = createHeadsUpContentView(false /* increasedHeight */);
- if (headsUpContentView != null) {
- return headsUpContentView;
- }
- return createContentView();
- }
-
- /**
* Adapt the Notification header if this view is used as an expanded view.
*
* @hide
diff --git a/core/java/android/view/LetterboxScrollProcessor.java b/core/java/android/view/LetterboxScrollProcessor.java
index 1364a82..8c1b0f8 100644
--- a/core/java/android/view/LetterboxScrollProcessor.java
+++ b/core/java/android/view/LetterboxScrollProcessor.java
@@ -78,6 +78,11 @@
@Nullable
@VisibleForTesting(visibility = PACKAGE)
public List<MotionEvent> processMotionEvent(@NonNull MotionEvent motionEvent) {
+ if (!motionEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
+ // This is a non-pointer event that doesn't correspond to any location on the screen.
+ // Ignore it.
+ return null;
+ }
mProcessedEvents.clear();
final Rect appBounds = getAppBounds();
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index f690bd3..92f9e60 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -20,9 +20,13 @@
import android.annotation.Nullable;
import android.app.AlertDialog;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
@@ -58,6 +62,7 @@
import android.widget.ScrollView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
+import android.widget.flags.Flags;
import com.android.internal.R;
@@ -66,6 +71,12 @@
public class AlertController {
public static final int MICRO = 1;
+ private static boolean sUseWearMaterial3Style;
+
+ @ChangeId
+ @EnabledSince(targetSdkVersion = 36)
+ private static final long WEAR_MATERIAL3_ALERTDIALOG = 379365266L;
+
private final Context mContext;
private final DialogInterface mDialogInterface;
protected final Window mWindow;
@@ -210,7 +221,8 @@
mHandler = new ButtonHandler(di);
final TypedArray a = context.obtainStyledAttributes(null,
- R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
+ R.styleable.AlertDialog, getAlertDialogDefStyleAttr(context),
+ getAlertDialogDefStyleRes());
mAlertDialogLayout = a.getResourceId(
R.styleable.AlertDialog_layout, R.layout.alert_dialog);
@@ -236,6 +248,28 @@
window.requestFeature(Window.FEATURE_NO_TITLE);
}
+ private int getAlertDialogDefStyleAttr(Context context) {
+ sUseWearMaterial3Style = useWearMaterial3Style(context);
+ if (sUseWearMaterial3Style) {
+ return 0;
+ }
+ return R.attr.alertDialogStyle;
+ }
+
+ private int getAlertDialogDefStyleRes() {
+ if (sUseWearMaterial3Style) {
+ return com.android.internal.R.style.AlertDialog_DeviceDefault_WearMaterial3;
+ }
+ return 0;
+ }
+
+ private static boolean useWearMaterial3Style(Context context) {
+ return Flags.useWearMaterial3Ui()
+ && CompatChanges.isChangeEnabled(WEAR_MATERIAL3_ALERTDIALOG)
+ && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
+ && context.getThemeResId() == com.android.internal.R.style.Theme_DeviceDefault;
+ }
+
static boolean canTextInput(View v) {
if (v.onCheckIsTextEditor()) {
return true;
diff --git a/core/res/res/layout-watch-v36/alert_dialog_material.xml b/core/res/res/layout-watch-v36/alert_dialog_wear_material3.xml
similarity index 100%
rename from core/res/res/layout-watch-v36/alert_dialog_material.xml
rename to core/res/res/layout-watch-v36/alert_dialog_wear_material3.xml
diff --git a/core/res/res/values-watch-v36/styles_material.xml b/core/res/res/values-watch-v36/styles_material.xml
index 20f4095..fc9f669 100644
--- a/core/res/res/values-watch-v36/styles_material.xml
+++ b/core/res/res/values-watch-v36/styles_material.xml
@@ -57,6 +57,10 @@
</style>
<!-- AlertDialog Styles -->
+ <style name="AlertDialog.DeviceDefault.WearMaterial3">
+ <item name="layout">@layout/alert_dialog_wear_material3</item>
+ </style>
+
<style name="Widget.DeviceDefault.Button.ButtonBar.AlertDialog.WearMaterial3" parent="Widget.DeviceDefault.Button">
<item name="android:textSize">0sp</item>
<item name="android:gravity">center</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 748f4b3..380b297 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5824,5 +5824,8 @@
<!-- Style for Wear Material3 Button. Will only be used for sdk 36 or above. -->
<java-symbol type="style" name="Widget.DeviceDefault.Button.WearMaterial3" />
+ <!-- Style for Wear Material3 AlertDialog. Will only be used for sdk 36 or above. -->
+ <java-symbol type="style" name="AlertDialog.DeviceDefault.WearMaterial3" />
+
<java-symbol type="bool" name="config_allowNormalBrightnessForDozePolicy" />
</resources>
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 8f9730a..6fdd73a 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -50,6 +50,7 @@
android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
android:label="@string/action_bar_label"
android:exported="true"
+ android:enableOnBackInvokedCallback="false"
android:permission="android.permission.MODIFY_PHONE_STATE"
android:theme="@style/AppTheme"
android:configChanges="keyboardHidden|orientation|screenSize">
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 68443a7..e029f3a 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -81,10 +81,12 @@
android:exported="false" />
<activity android:name=".PackageInstallerActivity"
- android:exported="false" />
+ android:exported="false"
+ android:enableOnBackInvokedCallback="false" />
<activity android:name=".InstallInstalling"
- android:exported="false" />
+ android:exported="false"
+ android:enableOnBackInvokedCallback="false" />
<receiver android:name=".common.InstallEventReceiver"
android:permission="android.permission.INSTALL_PACKAGES"
@@ -138,6 +140,7 @@
<activity android:name=".UninstallUninstalling"
android:excludeFromRecents="true"
+ android:enableOnBackInvokedCallback="false"
android:exported="false" />
<receiver android:name=".UninstallFinish"
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt
index a3709c1..366d54b 100644
--- a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceStateProviders.kt
@@ -136,6 +136,13 @@
/** Returns the preference widget object associated with given key. */
abstract fun <T> findPreference(key: String): T?
+ /**
+ * Returns the preference widget object associated with given key.
+ *
+ * @throws NullPointerException if preference is not found
+ */
+ abstract fun <T : Any> requirePreference(key: String): T
+
/** Notifies that preference state of given key is changed and updates preference widget UI. */
abstract fun notifyPreferenceChange(key: String)
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
index 7cec59c..153089e 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceScreenBindingHelper.kt
@@ -60,6 +60,8 @@
override fun <T> findPreference(key: String) =
preferenceScreen.findPreference(key) as T?
+ override fun <T : Any> requirePreference(key: String) = findPreference<T>(key)!!
+
override fun notifyPreferenceChange(key: String) =
notifyChange(key, CHANGE_REASON_STATE)
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 0d654d9..e6d9dc1 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -156,13 +156,6 @@
}
flag {
- name: "notifications_improved_hun_animation"
- namespace: "systemui"
- description: "Adds a translateY animation, and other improvements to match the motion specs of the HUN Intro + Outro animations."
- bug: "243302608"
-}
-
-flag {
name: "notification_content_alpha_optimization"
namespace: "systemui"
description: "Only reset alpha values of needed content views"
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index cf0ba51..7a8d20a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-@file:Suppress("NOTHING_TO_INLINE")
-
package com.android.compose.animation.scene
import androidx.compose.foundation.gestures.Orientation
@@ -97,68 +95,11 @@
internal val positionalThreshold
get() = with(layoutImpl.density) { 56.dp.toPx() }
- /**
- * Whether we should immediately intercept a gesture.
- *
- * Note: if this returns true, then [onDragStarted] will be called with overSlop equal to 0f,
- * indicating that the transition should be intercepted.
- */
- internal fun shouldImmediatelyIntercept(pointersDown: PointersInfo.PointersDown?): Boolean {
- // We don't intercept the touch if we are not currently driving the transition.
- val dragController = dragController
- if (dragController?.isDrivingTransition != true) {
- return false
- }
-
- val swipeAnimation = dragController.swipeAnimation
-
- // Only intercept the current transition if one of the 2 swipes results is also a transition
- // between the same pair of contents.
- val swipes = computeSwipes(pointersDown)
- val fromContent = layoutImpl.content(swipeAnimation.currentContent)
- val (upOrLeft, downOrRight) = swipes.computeSwipesResults(fromContent)
- val currentScene = layoutImpl.state.currentScene
- val contentTransition = swipeAnimation.contentTransition
- return (upOrLeft != null &&
- contentTransition.isTransitioningBetween(
- fromContent.key,
- upOrLeft.toContent(currentScene),
- )) ||
- (downOrRight != null &&
- contentTransition.isTransitioningBetween(
- fromContent.key,
- downOrRight.toContent(currentScene),
- ))
- }
-
override fun onDragStarted(
pointersDown: PointersInfo.PointersDown?,
overSlop: Float,
): DragController {
- if (overSlop == 0f) {
- val oldDragController = dragController
- check(oldDragController != null && oldDragController.isDrivingTransition) {
- val isActive = oldDragController?.isDrivingTransition
- "onDragStarted(overSlop=0f) requires an active dragController, but was $isActive"
- }
-
- // This [transition] was already driving the animation: simply take over it.
- // Stop animating and start from the current offset.
- val oldSwipeAnimation = oldDragController.swipeAnimation
-
- // We need to recompute the swipe results since this is a new gesture, and the
- // fromScene.userActions may have changed.
- val swipes = oldDragController.swipes
- swipes.updateSwipesResults(
- fromContent = layoutImpl.content(oldSwipeAnimation.fromContent)
- )
-
- // A new gesture should always create a new SwipeAnimation. This way there cannot be
- // different gestures controlling the same transition.
- val swipeAnimation = createSwipeAnimation(oldSwipeAnimation)
- return updateDragController(swipes, swipeAnimation)
- }
-
+ check(overSlop != 0f)
val swipes = computeSwipes(pointersDown)
val fromContent = layoutImpl.contentForUserActions()
@@ -196,7 +137,7 @@
return createSwipeAnimation(layoutImpl, result, isUpOrLeft, orientation)
}
- internal fun resolveSwipeSource(startedPosition: Offset): SwipeSource.Resolved? {
+ private fun resolveSwipeSource(startedPosition: Offset): SwipeSource.Resolved? {
return layoutImpl.swipeSourceDetector.source(
layoutSize = layoutImpl.lastSize,
position = startedPosition.round(),
@@ -291,71 +232,25 @@
return 0f
}
- val toContent = swipeAnimation.toContent
val distance = swipeAnimation.distance()
val previousOffset = swipeAnimation.dragOffset
val desiredOffset = previousOffset + delta
+ val desiredProgress = swipeAnimation.computeProgress(desiredOffset)
- fun hasReachedToSceneUpOrLeft() =
- distance < 0 &&
- desiredOffset <= distance &&
- swipes.upOrLeftResult?.toContent(layoutState.currentScene) == toContent
+ // Note: the distance could be negative if fromContent is above or to the left of
+ // toContent.
+ val newOffset =
+ when {
+ distance == DistanceUnspecified ||
+ swipeAnimation.contentTransition.isWithinProgressRange(desiredProgress) ->
+ desiredOffset
+ distance > 0f -> desiredOffset.fastCoerceIn(0f, distance)
+ else -> desiredOffset.fastCoerceIn(distance, 0f)
+ }
- fun hasReachedToSceneDownOrRight() =
- distance > 0 &&
- desiredOffset >= distance &&
- swipes.downOrRightResult?.toContent(layoutState.currentScene) == toContent
+ val consumedDelta = newOffset - previousOffset
- // Considering accelerated swipe: Change fromContent in the case where the user quickly
- // swiped multiple times in the same direction to accelerate the transition from A => B then
- // B => C.
- //
- // TODO(b/290184746): the second drag needs to pass B to work. Add support for flinging
- // twice before B has been reached
- val hasReachedToContent =
- swipeAnimation.currentContent == toContent &&
- (hasReachedToSceneUpOrLeft() || hasReachedToSceneDownOrRight())
-
- val fromContent: ContentKey
- val currentTransitionOffset: Float
- val newOffset: Float
- val consumedDelta: Float
- if (hasReachedToContent) {
- // The new transition will start from the current toContent.
- fromContent = toContent
-
- // The current transition is completed (we have reached the full swipe distance).
- currentTransitionOffset = distance
-
- // The next transition will start with the remaining offset.
- newOffset = desiredOffset - distance
- consumedDelta = delta
- } else {
- fromContent = swipeAnimation.fromContent
- val desiredProgress = swipeAnimation.computeProgress(desiredOffset)
-
- // Note: the distance could be negative if fromContent is above or to the left of
- // toContent.
- currentTransitionOffset =
- when {
- distance == DistanceUnspecified ||
- swipeAnimation.contentTransition.isWithinProgressRange(desiredProgress) ->
- desiredOffset
-
- distance > 0f -> desiredOffset.fastCoerceIn(0f, distance)
- else -> desiredOffset.fastCoerceIn(distance, 0f)
- }
-
- // If there is a new transition, we will use the same offset
- newOffset = currentTransitionOffset
- consumedDelta = newOffset - previousOffset
- }
-
- swipeAnimation.dragOffset = currentTransitionOffset
-
- if (hasReachedToContent) {
- swipes.updateSwipesResults(draggableHandler.layoutImpl.content(fromContent))
- }
+ swipeAnimation.dragOffset = newOffset
val result = swipes.findUserActionResult(directionOffset = newOffset)
if (result == null) {
@@ -372,13 +267,12 @@
val needNewTransition =
!currentTransitionIrreversible &&
- (hasReachedToContent ||
- result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
+ (result.toContent(layoutState.currentScene) != swipeAnimation.toContent ||
result.transitionKey != swipeAnimation.contentTransition.key)
if (needNewTransition) {
// Make sure the current transition will finish to the right current scene.
- swipeAnimation.currentContent = fromContent
+ swipeAnimation.currentContent = swipeAnimation.fromContent
val newSwipeAnimation = draggableHandler.createSwipeAnimation(swipes, result)
newSwipeAnimation.dragOffset = newOffset
@@ -499,7 +393,9 @@
var upOrLeftResult: UserActionResult? = null
var downOrRightResult: UserActionResult? = null
- fun computeSwipesResults(fromContent: Content): Pair<UserActionResult?, UserActionResult?> {
+ private fun computeSwipesResults(
+ fromContent: Content
+ ): Pair<UserActionResult?, UserActionResult?> {
val upOrLeftResult = fromContent.findActionResultBestMatch(swipe = upOrLeft)
val downOrRightResult = fromContent.findActionResultBestMatch(swipe = downOrRight)
return upOrLeftResult to downOrRightResult
@@ -564,48 +460,9 @@
.shouldEnableSwipes(draggableHandler.orientation)
}
- var isIntercepting = false
-
return PriorityNestedScrollConnection(
orientation = draggableHandler.orientation,
- canStartPreScroll = { offsetAvailable, offsetBeforeStart, _ ->
- val pointersDown: PointersInfo.PointersDown? =
- when (val info = pointersInfoOwner.pointersInfo()) {
- PointersInfo.MouseWheel -> {
- // Do not support mouse wheel interactions
- return@PriorityNestedScrollConnection false
- }
-
- is PointersInfo.PointersDown -> info
- null -> null
- }
-
- canChangeScene =
- if (isExternalOverscrollGesture()) false else offsetBeforeStart == 0f
-
- val canInterceptSwipeTransition =
- canChangeScene &&
- offsetAvailable != 0f &&
- draggableHandler.shouldImmediatelyIntercept(pointersDown)
- if (!canInterceptSwipeTransition) return@PriorityNestedScrollConnection false
-
- val layoutImpl = draggableHandler.layoutImpl
- val threshold = layoutImpl.transitionInterceptionThreshold
- val hasSnappedToIdle = layoutImpl.state.snapToIdleIfClose(threshold)
- if (hasSnappedToIdle) {
- // If the current swipe transition is closed to 0f or 1f, then we want to
- // interrupt the transition (snapping it to Idle) and scroll the list.
- return@PriorityNestedScrollConnection false
- }
-
- lastPointersDown = pointersDown
-
- // If the current swipe transition is *not* closed to 0f or 1f, then we want the
- // scroll events to intercept the current transition to continue the scene
- // transition.
- isIntercepting = true
- true
- },
+ canStartPreScroll = { _, _, _ -> false },
canStartPostScroll = { offsetAvailable, offsetBeforeStart, _ ->
val behavior: NestedScrollBehavior =
when {
@@ -629,29 +486,22 @@
}
lastPointersDown = pointersDown
- val canStart =
- when (behavior) {
- NestedScrollBehavior.EdgeNoPreview -> {
- canChangeScene = isZeroOffset
- isZeroOffset && shouldEnableSwipes()
- }
-
- NestedScrollBehavior.EdgeWithPreview -> {
- canChangeScene = isZeroOffset
- shouldEnableSwipes()
- }
-
- NestedScrollBehavior.EdgeAlways -> {
- canChangeScene = true
- shouldEnableSwipes()
- }
+ when (behavior) {
+ NestedScrollBehavior.EdgeNoPreview -> {
+ canChangeScene = isZeroOffset
+ isZeroOffset && shouldEnableSwipes()
}
- if (canStart) {
- isIntercepting = false
- }
+ NestedScrollBehavior.EdgeWithPreview -> {
+ canChangeScene = isZeroOffset
+ shouldEnableSwipes()
+ }
- canStart
+ NestedScrollBehavior.EdgeAlways -> {
+ canChangeScene = true
+ shouldEnableSwipes()
+ }
+ }
},
canStartPostFling = { velocityAvailable ->
val behavior: NestedScrollBehavior =
@@ -676,19 +526,14 @@
}
lastPointersDown = pointersDown
- val canStart = behavior.canStartOnPostFling && shouldEnableSwipes()
- if (canStart) {
- isIntercepting = false
- }
-
- canStart
+ behavior.canStartOnPostFling && shouldEnableSwipes()
},
onStart = { firstScroll ->
scrollController(
dragController =
draggableHandler.onDragStarted(
pointersDown = lastPointersDown,
- overSlop = if (isIntercepting) 0f else firstScroll,
+ overSlop = firstScroll,
),
canChangeScene = canChangeScene,
pointersInfoOwner = pointersInfoOwner,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
index 501fbb0..f5f01d4 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -80,7 +80,6 @@
@Stable
internal fun Modifier.multiPointerDraggable(
orientation: Orientation,
- startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
onDragStarted: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
onFirstPointerDown: () -> Unit = {},
swipeDetector: SwipeDetector = DefaultSwipeDetector,
@@ -89,7 +88,6 @@
this.then(
MultiPointerDraggableElement(
orientation,
- startDragImmediately,
onDragStarted,
onFirstPointerDown,
swipeDetector,
@@ -99,7 +97,6 @@
private data class MultiPointerDraggableElement(
private val orientation: Orientation,
- private val startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
private val onDragStarted:
(pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
private val onFirstPointerDown: () -> Unit,
@@ -109,7 +106,6 @@
override fun create(): MultiPointerDraggableNode =
MultiPointerDraggableNode(
orientation = orientation,
- startDragImmediately = startDragImmediately,
onDragStarted = onDragStarted,
onFirstPointerDown = onFirstPointerDown,
swipeDetector = swipeDetector,
@@ -118,7 +114,6 @@
override fun update(node: MultiPointerDraggableNode) {
node.orientation = orientation
- node.startDragImmediately = startDragImmediately
node.onDragStarted = onDragStarted
node.onFirstPointerDown = onFirstPointerDown
node.swipeDetector = swipeDetector
@@ -127,7 +122,6 @@
internal class MultiPointerDraggableNode(
orientation: Orientation,
- var startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
var onDragStarted: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
var onFirstPointerDown: () -> Unit,
swipeDetector: SwipeDetector = DefaultSwipeDetector,
@@ -293,7 +287,6 @@
try {
detectDragGestures(
orientation = orientation,
- startDragImmediately = startDragImmediately,
onDragStart = { pointersDown, overSlop ->
onDragStarted(pointersDown, overSlop)
},
@@ -434,13 +427,11 @@
* Detect drag gestures in the given [orientation].
*
* This function is a mix of [androidx.compose.foundation.gestures.awaitDownAndSlop] and
- * [androidx.compose.foundation.gestures.detectVerticalDragGestures] to add support for:
- * 1) starting the gesture immediately without requiring a drag >= touch slope;
- * 2) passing the number of pointers down to [onDragStart].
+ * [androidx.compose.foundation.gestures.detectVerticalDragGestures] to add support for passing
+ * the number of pointers down to [onDragStart].
*/
private suspend fun AwaitPointerEventScope.detectDragGestures(
orientation: Orientation,
- startDragImmediately: (pointersDown: PointersInfo.PointersDown) -> Boolean,
onDragStart: (pointersDown: PointersInfo.PointersDown, overSlop: Float) -> DragController,
onDrag: (controller: DragController, dragAmount: Float) -> Unit,
onDragEnd: (controller: DragController) -> Unit,
@@ -466,71 +457,49 @@
.first()
var overSlop = 0f
- var lastPointersDown: PointersInfo.PointersDown =
+ val onSlopReached = { change: PointerInputChange, over: Float ->
+ if (swipeDetector.detectSwipe(change)) {
+ change.consume()
+ overSlop = over
+ }
+ }
+
+ // TODO(b/291055080): Replace by await[Orientation]PointerSlopOrCancellation once it
+ // is public.
+ val drag =
+ when (orientation) {
+ Orientation.Horizontal ->
+ awaitHorizontalTouchSlopOrCancellation(consumablePointer.id, onSlopReached)
+ Orientation.Vertical ->
+ awaitVerticalTouchSlopOrCancellation(consumablePointer.id, onSlopReached)
+ } ?: return
+
+ val lastPointersDown =
checkNotNull(pointersInfo()) {
"We should have pointers down, last event: $currentEvent"
}
as PointersInfo.PointersDown
-
- val drag =
- if (startDragImmediately(lastPointersDown)) {
- consumablePointer.consume()
- consumablePointer
- } else {
- val onSlopReached = { change: PointerInputChange, over: Float ->
- if (swipeDetector.detectSwipe(change)) {
- change.consume()
- overSlop = over
- }
+ // Make sure that overSlop is not 0f. This can happen when the user drags by exactly
+ // the touch slop. However, the overSlop we pass to onDragStarted() is used to
+ // compute the direction we are dragging in, so overSlop should never be 0f.
+ if (overSlop == 0f) {
+ // If the user drags in the opposite direction, the delta becomes zero because
+ // we return to the original point. Therefore, we should use the previous event
+ // to calculate the direction.
+ val delta = (drag.position - drag.previousPosition).toFloat()
+ check(delta != 0f) {
+ buildString {
+ append("delta is equal to 0 ")
+ append("touchSlop ${currentValueOf(LocalViewConfiguration).touchSlop} ")
+ append("consumablePointer.position ${consumablePointer.position} ")
+ append("drag.position ${drag.position} ")
+ append("drag.previousPosition ${drag.previousPosition}")
}
-
- // TODO(b/291055080): Replace by await[Orientation]PointerSlopOrCancellation once it
- // is public.
- val drag =
- when (orientation) {
- Orientation.Horizontal ->
- awaitHorizontalTouchSlopOrCancellation(
- consumablePointer.id,
- onSlopReached,
- )
- Orientation.Vertical ->
- awaitVerticalTouchSlopOrCancellation(
- consumablePointer.id,
- onSlopReached,
- )
- } ?: return
-
- lastPointersDown =
- checkNotNull(pointersInfo()) {
- "We should have pointers down, last event: $currentEvent"
- }
- as PointersInfo.PointersDown
- // Make sure that overSlop is not 0f. This can happen when the user drags by exactly
- // the touch slop. However, the overSlop we pass to onDragStarted() is used to
- // compute the direction we are dragging in, so overSlop should never be 0f unless
- // we intercept an ongoing swipe transition (i.e. startDragImmediately() returned
- // true).
- if (overSlop == 0f) {
- // If the user drags in the opposite direction, the delta becomes zero because
- // we return to the original point. Therefore, we should use the previous event
- // to calculate the direction.
- val delta = (drag.position - drag.previousPosition).toFloat()
- check(delta != 0f) {
- buildString {
- append("delta is equal to 0 ")
- append("touchSlop ${currentValueOf(LocalViewConfiguration).touchSlop} ")
- append("consumablePointer.position ${consumablePointer.position} ")
- append("drag.position ${drag.position} ")
- append("drag.previousPosition ${drag.previousPosition}")
- }
- }
- overSlop = delta.sign
- }
- drag
}
+ overSlop = delta.sign
+ }
val controller = onDragStart(lastPointersDown, overSlop)
-
val successful: Boolean
try {
onDrag(controller, overSlop)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
index 5ab306a..6ef8b86 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -149,7 +149,6 @@
delegate(
MultiPointerDraggableNode(
orientation = draggableHandler.orientation,
- startDragImmediately = ::startDragImmediately,
onDragStarted = draggableHandler::onDragStarted,
onFirstPointerDown = ::onFirstPointerDown,
swipeDetector = swipeDetector,
@@ -198,21 +197,6 @@
) = multiPointerDraggableNode.onPointerEvent(pointerEvent, pass, bounds)
override fun onCancelPointerInput() = multiPointerDraggableNode.onCancelPointerInput()
-
- private fun startDragImmediately(pointersDown: PointersInfo.PointersDown): Boolean {
- // Immediately start the drag if the user can't swipe in the other direction and the gesture
- // handler can intercept it.
- return !canOppositeSwipe() && draggableHandler.shouldImmediatelyIntercept(pointersDown)
- }
-
- private fun canOppositeSwipe(): Boolean {
- val oppositeOrientation =
- when (draggableHandler.orientation) {
- Orientation.Vertical -> Orientation.Horizontal
- Orientation.Horizontal -> Orientation.Vertical
- }
- return draggableHandler.contentForSwipes().shouldEnableSwipes(oppositeOrientation)
- }
}
/** Find the [ScrollBehaviorOwner] for the current orientation. */
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index a1077cf..394568d 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -234,12 +234,6 @@
)
}
- fun onDragStartedImmediately(
- pointersInfo: PointersInfo.PointersDown = pointersDown()
- ): DragController {
- return onDragStarted(draggableHandler, pointersInfo, overSlop = 0f)
- }
-
fun onDragStarted(
draggableHandler: DraggableHandler,
pointersInfo: PointersInfo.PointersDown = pointersDown(),
@@ -602,82 +596,6 @@
}
@Test
- fun onAcceleratedScroll_scrollToThirdScene() = runGestureTest {
- // Drag A -> B with progress 0.2
- val dragController1 = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
- assertTransition(
- currentScene = SceneA,
- fromScene = SceneA,
- toScene = SceneB,
- progress = 0.2f,
- )
-
- // Start animation A -> B with progress 0.2 -> 1.0
- dragController1.onDragStoppedAnimateLater(velocity = -velocityThreshold)
- assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
-
- // While at A -> B do a 100% screen drag (progress 1.2). This should go past B and change
- // the transition to B -> C with progress 0.2
- val dragController2 = onDragStartedImmediately()
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 1f))
- assertTransition(
- currentScene = SceneB,
- fromScene = SceneB,
- toScene = SceneC,
- progress = 0.2f,
- )
-
- // After the drag stopped scene C should be committed
- dragController2.onDragStoppedAnimateNow(
- velocity = -velocityThreshold,
- onAnimationStart = {
- assertTransition(currentScene = SceneC, fromScene = SceneB, toScene = SceneC)
- },
- expectedConsumedVelocity = -velocityThreshold,
- )
- assertIdle(currentScene = SceneC)
- }
-
- @Test
- fun onAcceleratedScrollBothTargetsBecomeNull_settlesToIdle() = runGestureTest {
- val dragController1 = onDragStarted(overSlop = up(fractionOfScreen = 0.2f))
- dragController1.onDragDelta(pixels = up(fractionOfScreen = 0.2f))
- dragController1.onDragStoppedAnimateLater(velocity = -velocityThreshold)
- assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
-
- mutableUserActionsA = emptyMap()
- mutableUserActionsB = emptyMap()
-
- // start acceleratedScroll and scroll over to B -> null
- val dragController2 = onDragStartedImmediately()
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
-
- // here onDragStopped is already triggered, but subsequent onDelta/onDragStopped calls may
- // still be called. Make sure that they don't crash or change the scene
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
- dragController2.onDragStoppedAnimateNow(
- velocity = 0f,
- onAnimationStart = {
- assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
- },
- expectedConsumedVelocity = 0f,
- )
-
- advanceUntilIdle()
- assertIdle(SceneB)
-
- // These events can still come in after the animation has settled
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.5f), expectedConsumed = 0f)
- dragController2.onDragStoppedAnimateNow(
- velocity = 0f,
- onAnimationStart = { assertIdle(SceneB) },
- expectedConsumedVelocity = 0f,
- )
- assertIdle(SceneB)
- }
-
- @Test
fun onDragTargetsChanged_targetStaysTheSame() = runGestureTest {
val dragController1 = onDragStarted(overSlop = up(fractionOfScreen = 0.1f))
assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.1f)
@@ -711,9 +629,8 @@
dragController1.onDragStoppedAnimateLater(velocity = down(fractionOfScreen = 0.1f))
// now target changed to C for new drag that started before previous drag settled to Idle
- val dragController2 = onDragStartedImmediately()
- dragController2.onDragDelta(pixels = up(fractionOfScreen = 0.1f))
- assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.3f)
+ onDragStarted(overSlop = up(fractionOfScreen = 0.1f))
+ assertTransition(fromScene = SceneA, toScene = SceneC, progress = 0.1f)
}
@Test
@@ -728,7 +645,7 @@
assertThat(isUserInputOngoing).isFalse()
// Start a new gesture while the offset is animating
- onDragStartedImmediately()
+ onDragStarted(overSlop = up(fractionOfScreen = 0.1f))
assertThat(isUserInputOngoing).isTrue()
}
@@ -812,36 +729,6 @@
}
@Test
- fun scrollAndFling_scrollLessThanInterceptable_goToIdleOnCurrentScene() = runGestureTest {
- val firstScroll = (transitionInterceptionThreshold - 0.0001f) * SCREEN_SIZE
- val secondScroll = 1f
-
- preScrollAfterSceneTransition(firstScroll = firstScroll, secondScroll = secondScroll)
-
- assertIdle(SceneA)
- }
-
- @Test
- fun scrollAndFling_scrollMinInterceptable_interceptPreScrollEvents() = runGestureTest {
- val firstScroll = (transitionInterceptionThreshold + 0.0001f) * SCREEN_SIZE
- val secondScroll = 1f
-
- preScrollAfterSceneTransition(firstScroll = firstScroll, secondScroll = secondScroll)
-
- assertTransition(progress = (firstScroll + secondScroll) / SCREEN_SIZE)
- }
-
- @Test
- fun scrollAndFling_scrollMaxInterceptable_interceptPreScrollEvents() = runGestureTest {
- val firstScroll = -(1f - transitionInterceptionThreshold - 0.0001f) * SCREEN_SIZE
- val secondScroll = -1f
-
- preScrollAfterSceneTransition(firstScroll = firstScroll, secondScroll = secondScroll)
-
- assertTransition(progress = -(firstScroll + secondScroll) / SCREEN_SIZE)
- }
-
- @Test
fun scrollAndFling_scrollMoreThanInterceptable_goToIdleOnNextScene() = runGestureTest {
val firstScroll = -(1f - transitionInterceptionThreshold + 0.0001f) * SCREEN_SIZE
val secondScroll = -0.01f
@@ -1025,7 +912,7 @@
// now we can intercept the scroll events
nestedScroll.scroll(available = -offsetY10)
- assertThat(progress).isEqualTo(0.2f)
+ assertThat(progress).isEqualTo(0.1f)
// this should be ignored, we are scrolling now!
dragController.onDragStoppedAnimateNow(
@@ -1036,10 +923,10 @@
assertTransition(currentScene = SceneA)
nestedScroll.scroll(available = -offsetY10)
- assertThat(progress).isEqualTo(0.3f)
+ assertThat(progress).isEqualTo(0.2f)
nestedScroll.scroll(available = -offsetY10)
- assertThat(progress).isEqualTo(0.4f)
+ assertThat(progress).isEqualTo(0.3f)
nestedScroll.preFling(available = Velocity(0f, -velocityThreshold))
assertTransition(currentScene = SceneB)
@@ -1050,57 +937,6 @@
}
@Test
- fun interceptTransition() = runGestureTest {
- // Start at scene C.
- navigateToSceneC()
-
- // Swipe up from the middle to transition to scene B.
- val middle = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f))
- onDragStarted(pointersInfo = middle, overSlop = up(0.1f))
- assertTransition(
- currentScene = SceneC,
- fromScene = SceneC,
- toScene = SceneB,
- progress = 0.1f,
- isUserInputOngoing = true,
- )
-
- val firstTransition = transitionState
-
- // During the current gesture, start a new gesture, still in the middle of the screen. We
- // should intercept it. Because it is intercepted, the overSlop passed to onDragStarted()
- // should be 0f.
- assertThat(draggableHandler.shouldImmediatelyIntercept(middle)).isTrue()
- onDragStartedImmediately(pointersInfo = middle)
-
- // We should have intercepted the transition, so the transition should be the same object.
- assertTransition(
- currentScene = SceneC,
- fromScene = SceneC,
- toScene = SceneB,
- progress = 0.1f,
- isUserInputOngoing = true,
- )
- // We should have a new transition
- assertThat(transitionState).isNotSameInstanceAs(firstTransition)
-
- // Start a new gesture from the bottom of the screen. Because swiping up from the bottom of
- // C leads to scene A (and not B), the previous transitions is *not* intercepted and we
- // instead animate from C to A.
- val bottom = pointersDown(startedPosition = Offset(SCREEN_SIZE / 2, SCREEN_SIZE))
- assertThat(draggableHandler.shouldImmediatelyIntercept(bottom)).isFalse()
- onDragStarted(pointersInfo = bottom, overSlop = up(0.1f))
-
- assertTransition(
- currentScene = SceneC,
- fromScene = SceneC,
- toScene = SceneA,
- isUserInputOngoing = true,
- )
- assertThat(transitionState).isNotSameInstanceAs(firstTransition)
- }
-
- @Test
fun freezeAndAnimateToCurrentState() = runGestureTest {
// Start at scene C.
navigateToSceneC()
@@ -1110,9 +946,6 @@
onDragStarted(pointersInfo = middle, overSlop = up(0.1f))
assertTransition(fromScene = SceneC, toScene = SceneB, isUserInputOngoing = true)
- // The current transition can be intercepted.
- assertThat(draggableHandler.shouldImmediatelyIntercept(middle)).isTrue()
-
// Freeze the transition.
val transition = transitionState as Transition
transition.freezeAndAnimateToCurrentState()
@@ -1123,19 +956,6 @@
}
@Test
- fun interruptedTransitionCanNotBeImmediatelyIntercepted() = runGestureTest {
- assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isFalse()
- onDragStarted(overSlop = up(0.1f))
- assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isTrue()
-
- layoutState.startTransitionImmediately(
- animationScope = testScope.backgroundScope,
- transition(SceneA, SceneB),
- )
- assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isFalse()
- }
-
- @Test
fun blockTransition() = runGestureTest {
assertIdle(SceneA)
@@ -1154,30 +974,6 @@
}
@Test
- fun blockInterceptedTransition() = runGestureTest {
- assertIdle(SceneA)
-
- // Swipe up to B.
- val dragController1 = onDragStarted(overSlop = up(0.1f))
- assertTransition(currentScene = SceneA, fromScene = SceneA, toScene = SceneB)
- dragController1.onDragStoppedAnimateLater(velocity = -velocityThreshold)
- assertTransition(currentScene = SceneB, fromScene = SceneA, toScene = SceneB)
-
- // Intercept the transition and swipe down back to scene A.
- assertThat(draggableHandler.shouldImmediatelyIntercept(pointersDown = null)).isTrue()
- val dragController2 = onDragStartedImmediately()
-
- // Block the transition when the user release their finger.
- canChangeScene = { false }
- dragController2.onDragStoppedAnimateNow(
- velocity = velocityThreshold,
- onAnimationStart = { assertTransition(fromScene = SceneA, toScene = SceneB) },
- expectedConsumedVelocity = velocityThreshold,
- )
- assertIdle(SceneB)
- }
-
- @Test
fun scrollFromIdleWithNoTargetScene_shouldUseOverscrollSpecIfAvailable() = runGestureTest {
layoutState.transitions = transitions {
overscroll(SceneC, Orientation.Vertical) { fade(TestElements.Foo) }
@@ -1531,25 +1327,6 @@
}
@Test
- fun interceptingTransitionKeepsDistance() = runGestureTest {
- var swipeDistance = 75f
- layoutState.transitions = transitions {
- from(SceneA, to = SceneB) { distance = UserActionDistance { _, _, _ -> swipeDistance } }
- }
-
- // Start transition.
- val controller = onDragStarted(overSlop = -50f)
- assertTransition(fromScene = SceneA, toScene = SceneB, progress = 50f / 75f)
-
- // Intercept the transition and change the swipe distance. The original distance and
- // progress should be the same.
- swipeDistance = 50f
- controller.onDragStoppedAnimateLater(0f)
- onDragStartedImmediately()
- assertTransition(fromScene = SceneA, toScene = SceneB, progress = 50f / 75f)
- }
-
- @Test
fun requireFullDistanceSwipe() = runGestureTest {
mutableUserActionsA +=
Swipe.Up to UserActionResult(SceneB, requiresFullDistanceSwipe = true)
@@ -1579,19 +1356,6 @@
}
@Test
- fun interceptingTransitionReplacesCurrentTransition() = runGestureTest {
- val controller = onDragStarted(overSlop = up(fractionOfScreen = 0.5f))
- val transition = assertThat(layoutState.transitionState).isSceneTransition()
- controller.onDragStoppedAnimateLater(velocity = 0f)
-
- // Intercept the transition.
- onDragStartedImmediately()
- val newTransition = assertThat(layoutState.transitionState).isSceneTransition()
- assertThat(newTransition).isNotSameInstanceAs(transition)
- assertThat(newTransition.replacedTransition).isSameInstanceAs(transition)
- }
-
- @Test
fun showOverlay() = runGestureTest {
mutableUserActionsA = mapOf(Swipe.Down to UserActionResult.ShowOverlay(OverlayA))
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
index cb3e433..4153350 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MultiPointerDraggableTest.kt
@@ -101,7 +101,6 @@
.thenIf(enabled) {
Modifier.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
onDragStarted = { _, _ ->
started = true
SimpleDragController(
@@ -169,8 +168,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- // We want to start a drag gesture immediately
- startDragImmediately = { true },
onDragStarted = { _, _ ->
started = true
SimpleDragController(
@@ -242,7 +239,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
onDragStarted = { _, _ ->
started = true
SimpleDragController(
@@ -361,7 +357,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
onDragStarted = { _, _ ->
started = true
SimpleDragController(
@@ -466,7 +461,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
onDragStarted = { _, _ ->
verticalStarted = true
SimpleDragController(
@@ -478,7 +472,6 @@
)
.multiPointerDraggable(
orientation = Orientation.Horizontal,
- startDragImmediately = { false },
onDragStarted = { _, _ ->
horizontalStarted = true
SimpleDragController(
@@ -570,7 +563,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
swipeDetector =
object : SwipeDetector {
override fun detectSwipe(change: PointerInputChange): Boolean {
@@ -636,7 +628,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
swipeDetector =
object : SwipeDetector {
override fun detectSwipe(change: PointerInputChange): Boolean {
@@ -738,7 +729,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
onDragStarted = { _, _ ->
SimpleDragController(
onDrag = { consumedOnDrag = it },
@@ -809,7 +799,6 @@
.nestedScrollDispatcher()
.multiPointerDraggable(
orientation = Orientation.Vertical,
- startDragImmediately = { false },
onDragStarted = { _, _ ->
SimpleDragController(
onDrag = { /* do nothing */ },
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 2b7e950..dcac294 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -3,7 +3,6 @@
import android.annotation.DimenRes
import android.content.pm.PackageManager
import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
@@ -30,7 +29,6 @@
import com.android.systemui.statusbar.notification.headsup.AvalancheController
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.google.common.truth.Expect
import com.google.common.truth.Truth.assertThat
@@ -154,22 +152,6 @@
@Test
@DisableSceneContainer
- fun resetViewStates_defaultHun_yTranslationIsInset() {
- whenever(notificationRow.isPinned).thenReturn(true)
- whenever(notificationRow.isHeadsUp).thenReturn(true)
- resetViewStates_hunYTranslationIs(stackScrollAlgorithm.mHeadsUpInset)
- }
-
- @Test
- @DisableSceneContainer
- fun resetViewStates_defaultHunWithStackMargin_changesHunYTranslation() {
- whenever(notificationRow.isPinned).thenReturn(true)
- whenever(notificationRow.isHeadsUp).thenReturn(true)
- resetViewStates_stackMargin_changesHunYTranslation()
- }
-
- @Test
- @DisableSceneContainer
fun resetViewStates_defaultHunWhenShadeIsOpening_yTranslationIsInset() {
whenever(notificationRow.isPinned).thenReturn(true)
whenever(notificationRow.isHeadsUp).thenReturn(true)
@@ -183,24 +165,7 @@
@Test
@DisableSceneContainer
- @DisableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_hunAnimatingAway_yTranslationIsInset() {
- whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true)
- resetViewStates_hunYTranslationIs(stackScrollAlgorithm.mHeadsUpInset)
- }
-
- @Test
- @DisableSceneContainer
- @DisableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_hunAnimatingAway_StackMarginChangesHunYTranslation() {
- whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true)
- resetViewStates_stackMargin_changesHunYTranslation()
- }
-
- @Test
- @DisableSceneContainer
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_defaultHun_newHeadsUpAnim_yTranslationIsInset() {
+ fun resetViewStates_defaultHun_yTranslationIsInset() {
whenever(notificationRow.isPinned).thenReturn(true)
whenever(notificationRow.isHeadsUp).thenReturn(true)
resetViewStates_hunYTranslationIs(stackScrollAlgorithm.mHeadsUpInset)
@@ -208,8 +173,7 @@
@Test
@DisableSceneContainer
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_defaultHunWithStackMargin_newHeadsUpAnim_changesHunYTranslation() {
+ fun resetViewStates_defaultHunWithStackMargin_changesHunYTranslation() {
whenever(notificationRow.isPinned).thenReturn(true)
whenever(notificationRow.isHeadsUp).thenReturn(true)
resetViewStates_stackMargin_changesHunYTranslation()
@@ -399,8 +363,7 @@
@Test
@DisableSceneContainer
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_defaultHun_showingQS_newHeadsUpAnim_hunTranslatedToMax() {
+ fun resetViewStates_defaultHun_showingQS_hunTranslatedToMax() {
// Given: the shade is open and scrolled to the bottom to show the QuickSettings
val maxHunTranslation = 2000f
ambientState.maxHeadsUpTranslation = maxHunTranslation
@@ -416,8 +379,7 @@
@Test
@DisableSceneContainer
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_hunAnimatingAway_showingQS_newHeadsUpAnim_hunTranslatedToBottomOfScreen() {
+ fun resetViewStates_hunAnimatingAway_showingQS_hunTranslatedToBottomOfScreen() {
// Given: the shade is open and scrolled to the bottom to show the QuickSettings
val bottomOfScreen = 2600f
val maxHunTranslation = 2000f
@@ -437,8 +399,7 @@
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_hunAnimatingAway_newHeadsUpAnim_hunTranslatedToTopOfScreen() {
+ fun resetViewStates_hunAnimatingAway_hunTranslatedToTopOfScreen() {
val topMargin = 100f
ambientState.maxHeadsUpTranslation = 2000f
ambientState.stackTopMargin = topMargin.toInt()
@@ -461,7 +422,6 @@
@Test
@DisableSceneContainer
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun resetViewStates_hunAnimatingAwayWhileDozing_yTranslationIsInset() {
whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true)
@@ -472,7 +432,6 @@
@Test
@DisableSceneContainer
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun resetViewStates_hunAnimatingAwayWhileDozing_hasStackMargin_changesHunYTranslation() {
whenever(notificationRow.isHeadsUpAnimatingAway).thenReturn(true)
@@ -494,18 +453,6 @@
}
@Test
- @DisableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
- fun resetViewStates_hunsOverlappingAndBottomHunAnimatingAway_bottomHunClipped() {
- val topHun = mockExpandableNotificationRow()
- val bottomHun = mockExpandableNotificationRow()
- whenever(topHun.isHeadsUp).thenReturn(true)
- whenever(topHun.isPinned).thenReturn(true)
- whenever(bottomHun.isHeadsUpAnimatingAway).thenReturn(true)
-
- resetViewStates_hunsOverlapping_bottomHunClipped(topHun, bottomHun)
- }
-
- @Test
@EnableSceneContainer
fun resetViewStates_emptyShadeView_isCenteredVertically_withSceneContainer() {
stackScrollAlgorithm.initView(context)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
index 798465e..e4dd29a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/StackStateAnimatorTest.kt
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.notification.stack
-import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -24,7 +23,6 @@
import com.android.systemui.animation.AnimatorTestRule
import com.android.systemui.res.R
import com.android.systemui.statusbar.notification.row.ExpandableView
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent
import com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_HEADS_UP_APPEAR
import com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_HEADS_UP_DISAPPEAR
@@ -60,11 +58,12 @@
private val viewState: ExpandableViewState =
ExpandableViewState().apply { height = VIEW_HEIGHT }
private val runnableCaptor: ArgumentCaptor<Runnable> = argumentCaptor()
+
@Before
fun setUp() {
overrideResource(
R.dimen.go_to_full_shade_appearing_translation,
- FULL_SHADE_APPEAR_TRANSLATION
+ FULL_SHADE_APPEAR_TRANSLATION,
)
overrideResource(R.dimen.heads_up_appear_y_above_screen, HEADS_UP_ABOVE_SCREEN)
@@ -74,7 +73,6 @@
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun startAnimationForEvents_headsUpFromTop_startsHeadsUpAppearAnim() {
val topMargin = 50f
val expectedStartY = -topMargin - stackStateAnimator.mHeadsUpAppearStartAboveScreen
@@ -90,12 +88,11 @@
/* delay= */ 0L,
/* duration= */ ANIMATION_DURATION_HEADS_UP_APPEAR.toLong(),
/* isHeadsUpAppear= */ true,
- /* onEndRunnable= */ null
+ /* onEndRunnable= */ null,
)
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun startAnimationForEvents_headsUpFromBottom_startsHeadsUpAppearAnim() {
val screenHeight = 2000f
val expectedStartY = screenHeight + stackStateAnimator.mHeadsUpAppearStartAboveScreen
@@ -114,12 +111,11 @@
/* delay= */ 0L,
/* duration= */ ANIMATION_DURATION_HEADS_UP_APPEAR.toLong(),
/* isHeadsUpAppear= */ true,
- /* onEndRunnable= */ null
+ /* onEndRunnable= */ null,
)
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun startAnimationForEvents_startsHeadsUpDisappearAnim() {
val disappearDuration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR.toLong()
val event = AnimationEvent(view, AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt
index 9f5a311..f91c5dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt
@@ -242,10 +242,10 @@
private fun updateBubblesVisibility(statusBarVisible: Boolean) {
if (displayId != Display.DEFAULT_DISPLAY) {
+ // Bubbles are currently only supported on the default display.
return
}
bubblesOptional.ifPresent { bubbles: Bubbles ->
- // TODO(b/373311537): per display implementation of Bubbles
bubbles.onStatusBarVisibilityChanged(statusBarVisible)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index 3b48b39..d0d2258 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -4,7 +4,6 @@
import android.view.View
import androidx.annotation.FloatRange
import com.android.systemui.res.R
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation
import com.android.systemui.statusbar.notification.stack.AnimationProperties
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import kotlin.math.abs
@@ -39,15 +38,11 @@
/** Current top corner in pixel, based on [topRoundness] and [maxRadius] */
val topCornerRadius: Float
- get() =
- if (NotificationsImprovedHunAnimation.isEnabled) roundableState.topCornerRadius
- else topRoundness * maxRadius
+ get() = roundableState.topCornerRadius
/** Current bottom corner in pixel, based on [bottomRoundness] and [maxRadius] */
val bottomCornerRadius: Float
- get() =
- if (NotificationsImprovedHunAnimation.isEnabled) roundableState.bottomCornerRadius
- else bottomRoundness * maxRadius
+ get() = roundableState.bottomCornerRadius
/** Get and update the current radii */
val updatedRadii: FloatArray
@@ -123,7 +118,7 @@
return requestTopRoundness(
value = value,
sourceType = sourceType,
- animate = roundableState.targetView.isShown
+ animate = roundableState.targetView.isShown,
)
}
@@ -190,7 +185,7 @@
return requestBottomRoundness(
value = value,
sourceType = sourceType,
- animate = roundableState.targetView.isShown
+ animate = roundableState.targetView.isShown,
)
}
@@ -289,11 +284,7 @@
*
* This method reuses the previous [radii] for performance reasons.
*/
- fun updateRadii(
- topCornerRadius: Float,
- bottomCornerRadius: Float,
- radii: FloatArray,
- ) {
+ fun updateRadii(topCornerRadius: Float, bottomCornerRadius: Float, radii: FloatArray) {
if (radii.size != 8) error("Unexpected radiiBuffer size ${radii.size}")
if (radii[0] != topCornerRadius || radii[4] != bottomCornerRadius) {
@@ -312,11 +303,7 @@
*/
class RoundableState
@JvmOverloads
-constructor(
- internal val targetView: View,
- private val roundable: Roundable,
- maxRadius: Float,
-) {
+constructor(internal val targetView: View, private val roundable: Roundable, maxRadius: Float) {
internal var maxRadius = maxRadius
private set
@@ -387,18 +374,12 @@
internal fun isBottomAnimating() = PropertyAnimator.isAnimating(targetView, bottomAnimatable)
/** Set the current top roundness */
- internal fun setTopRoundness(
- value: Float,
- animated: Boolean,
- ) {
+ internal fun setTopRoundness(value: Float, animated: Boolean) {
PropertyAnimator.setProperty(targetView, topAnimatable, value, DURATION, animated)
}
/** Set the current bottom roundness */
- internal fun setBottomRoundness(
- value: Float,
- animated: Boolean,
- ) {
+ internal fun setBottomRoundness(value: Float, animated: Boolean) {
PropertyAnimator.setProperty(targetView, bottomAnimatable, value, DURATION, animated)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index d538f52..5c51ada 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -46,7 +46,6 @@
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.shared.NotificationHeadsUpCycling;
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.util.DumpUtilsKt;
@@ -407,12 +406,7 @@
mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
targetValue);
- if (NotificationsImprovedHunAnimation.isEnabled()
- || NotificationHeadsUpCycling.isEnabled()) {
- mAppearAnimator.setInterpolator(mCurrentAppearInterpolator);
- } else {
- mAppearAnimator.setInterpolator(Interpolators.LINEAR);
- }
+ mAppearAnimator.setInterpolator(mCurrentAppearInterpolator);
mAppearAnimator.setDuration(
(long) (duration * Math.abs(mAppearAnimationFraction - targetValue)));
mAppearAnimator.addUpdateListener(animation -> {
@@ -531,10 +525,7 @@
* @param clipSide Which side if view we want to clip from
*/
private void updateAppearRect(ClipSide clipSide) {
- float interpolatedFraction =
- NotificationsImprovedHunAnimation.isEnabled()
- || NotificationHeadsUpCycling.isEnabled() ? mAppearAnimationFraction
- : mCurrentAppearInterpolator.getInterpolation(mAppearAnimationFraction);
+ float interpolatedFraction = mAppearAnimationFraction;
mAppearAnimationTranslation = (1.0f - interpolatedFraction) * mAnimationTranslationY;
final int fullHeight = getActualHeight();
float height = fullHeight * interpolatedFraction;
@@ -566,14 +557,6 @@
updateAppearRect(ClipSide.BOTTOM);
}
- private float getInterpolatedAppearAnimationFraction() {
-
- if (mAppearAnimationFraction >= 0) {
- return mCurrentAppearInterpolator.getInterpolation(mAppearAnimationFraction);
- }
- return 1.0f;
- }
-
private void updateAppearAnimationAlpha() {
updateAppearAnimationContentAlpha(
mAppearAnimationFraction,
@@ -643,26 +626,6 @@
super.applyRoundnessAndInvalidate();
}
- @Override
- public float getTopCornerRadius() {
- if (NotificationsImprovedHunAnimation.isEnabled()) {
- return super.getTopCornerRadius();
- }
-
- float fraction = getInterpolatedAppearAnimationFraction();
- return MathUtils.lerp(0, super.getTopCornerRadius(), fraction);
- }
-
- @Override
- public float getBottomCornerRadius() {
- if (NotificationsImprovedHunAnimation.isEnabled()) {
- return super.getBottomCornerRadius();
- }
-
- float fraction = getInterpolatedAppearAnimationFraction();
- return MathUtils.lerp(0, super.getBottomCornerRadius(), fraction);
- }
-
private void applyBackgroundRoundness(float topRadius, float bottomRadius) {
mBackgroundNormal.setRadius(topRadius, bottomRadius);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index a323c26..80cf818 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -30,7 +30,6 @@
import com.android.systemui.res.R;
import com.android.systemui.statusbar.notification.RoundableState;
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.util.DumpUtilsKt;
@@ -123,15 +122,6 @@
return EMPTY_PATH;
}
float bottomRadius = mAlwaysRoundBothCorners ? getMaxRadius() : getBottomCornerRadius();
- if (!NotificationsImprovedHunAnimation.isEnabled() && (topRadius + bottomRadius > height)) {
- float overShoot = topRadius + bottomRadius - height;
- float currentTopRoundness = getTopRoundness();
- float currentBottomRoundness = getBottomRoundness();
- topRadius -= overShoot * currentTopRoundness
- / (currentTopRoundness + currentBottomRoundness);
- bottomRadius -= overShoot * currentBottomRoundness
- / (currentTopRoundness + currentBottomRoundness);
- }
getRoundedRectPath(left, top, right, bottom, topRadius, bottomRadius, mTmpPath);
return mTmpPath;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsImprovedHunAnimation.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsImprovedHunAnimation.kt
deleted file mode 100644
index 16d35fe..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsImprovedHunAnimation.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2023 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.notification.shared
-
-import com.android.systemui.Flags
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-
-/** Helper for reading or using the notifications improved hun animation flag state. */
-@Suppress("NOTHING_TO_INLINE")
-object NotificationsImprovedHunAnimation {
- /** The aconfig flag name */
- const val FLAG_NAME = Flags.FLAG_NOTIFICATIONS_IMPROVED_HUN_ANIMATION
-
- /** A token used for dependency declaration */
- val token: FlagToken
- get() = FlagToken(FLAG_NAME, isEnabled)
-
- /** Is the refactor enabled */
- @JvmStatic
- inline val isEnabled
- get() = Flags.notificationsImprovedHunAnimation()
-
- /**
- * Called to ensure code is only run when the flag is enabled. This protects users from the
- * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
- * build to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun isUnexpectedlyInLegacyMode() =
- RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
-
- /**
- * Called to ensure code is only run when the flag is disabled. This will throw an exception if
- * the flag is enabled to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 223475e..c7b3fd7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -118,7 +118,6 @@
import com.android.systemui.statusbar.notification.shared.NotificationContentAlphaOptimization;
import com.android.systemui.statusbar.notification.shared.NotificationHeadsUpCycling;
import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun;
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation;
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor;
import com.android.systemui.statusbar.notification.stack.shared.model.AccessibilityScrollEvent;
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds;
@@ -3459,11 +3458,8 @@
}
AnimationEvent event = new AnimationEvent(row, type);
event.headsUpFromBottom = onBottom;
- if (NotificationsImprovedHunAnimation.isEnabled()) {
- // TODO(b/283084712) remove this with the flag and update the HUN filters at
- // creation
- event.filter.animateHeight = false;
- }
+ // TODO(b/283084712) remove this and update the HUN filters at creation
+ event.filter.animateHeight = false;
mAnimationEvents.add(event);
if (SPEW) {
Log.v(TAG, "Generating HUN animation event: "
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index b251b07..1653029 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -41,7 +41,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.shared.NotificationHeadsUpCycling;
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation;
import java.util.ArrayList;
import java.util.List;
@@ -1065,8 +1064,7 @@
headsUpTranslation);
childState.setYTranslation(inSpaceTranslation + extraTranslation);
cyclingInHunHeight = -1;
- } else
- if (NotificationsImprovedHunAnimation.isEnabled() && !ambientState.isDozing()) {
+ } else if (!ambientState.isDozing()) {
if (shouldHunAppearFromBottom(ambientState, childState)) {
// move to the bottom of the screen
childState.setYTranslation(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 058233f..4686bef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -37,8 +37,6 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
-import com.android.systemui.statusbar.notification.shared.NotificationHeadsUpCycling;
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation;
import java.util.ArrayList;
import java.util.HashSet;
@@ -179,10 +177,7 @@
mHeadsUpDisappearChildren.clear();
mNewEvents.clear();
mNewAddChildren.clear();
- if (NotificationsImprovedHunAnimation.isEnabled()
- || NotificationHeadsUpCycling.isEnabled()) {
- mAnimationProperties.resetCustomInterpolators();
- }
+ mAnimationProperties.resetCustomInterpolators();
}
private void initAnimationProperties(ExpandableView child,
@@ -498,8 +493,7 @@
}
changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_CYCLING,
/* isHeadsUpAppear= */ true, onAnimationEnd);
- } else if (NotificationsImprovedHunAnimation.isEnabled()
- && (event.animationType == ANIMATION_TYPE_HEADS_UP_APPEAR)) {
+ } else if (event.animationType == ANIMATION_TYPE_HEADS_UP_APPEAR) {
mHeadsUpAppearChildren.add(changingView);
mTmpState.copyFrom(changingView.getViewState());
@@ -602,30 +596,6 @@
endRunnable.run();
}
needsCustomAnimation |= needsAnimation;
- } else if (event.animationType == ANIMATION_TYPE_HEADS_UP_APPEAR) {
- NotificationsImprovedHunAnimation.assertInLegacyMode();
- // This item is added, initialize its properties.
- ExpandableViewState viewState = changingView.getViewState();
- mTmpState.copyFrom(viewState);
- if (event.headsUpFromBottom) {
- mTmpState.setYTranslation(mHeadsUpAppearHeightBottom);
- } else {
- Runnable onAnimationEnd = null;
- if (loggable) {
- String finalKey = key;
- onAnimationEnd = () -> mLogger.appearAnimationEnded(finalKey);
- }
- changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR,
- true /* isHeadsUpAppear */, onAnimationEnd);
- }
- mHeadsUpAppearChildren.add(changingView);
- // this only captures HEADS_UP_APPEAR animations, but HUNs can appear with normal
- // ADD animations, which would not be logged here.
- if (loggable) {
- mLogger.logHUNViewAppearing(key);
- }
-
- mTmpState.applyToView(changingView);
} else if (event.animationType == ANIMATION_TYPE_HEADS_UP_DISAPPEAR
|| event.animationType == ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK) {
mHeadsUpDisappearChildren.add(changingView);
@@ -636,14 +606,10 @@
// transiently
mHostLayout.addTransientView(changingView, 0);
changingView.setTransientContainer(mHostLayout);
- if (NotificationsImprovedHunAnimation.isEnabled()) {
- // StackScrollAlgorithm cannot find this view because it has been removed
- // from the NSSL. To correctly translate the view to the top or bottom of
- // the screen (where it animated from), we need to update its translation.
- mTmpState.setYTranslation(
- getHeadsUpYTranslationStart(event.headsUpFromBottom)
- );
- }
+ // StackScrollAlgorithm cannot find this view because it has been removed
+ // from the NSSL. To correctly translate the view to the top or bottom of
+ // the screen (where it animated from), we need to update its translation.
+ mTmpState.setYTranslation(getHeadsUpYTranslationStart(event.headsUpFromBottom));
endRunnable = changingView::removeFromTransientContainer;
}
@@ -697,14 +663,12 @@
startAnimation, postAnimation,
getGlobalAnimationFinishedListener(), ExpandableView.ClipSide.BOTTOM);
mAnimationProperties.delay += removeAnimationDelay;
- if (NotificationsImprovedHunAnimation.isEnabled()) {
- mAnimationProperties.duration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR;
- mAnimationProperties.setCustomInterpolator(View.TRANSLATION_Y,
- Interpolators.FAST_OUT_SLOW_IN_REVERSE);
- mAnimationProperties.getAnimationFilter().animateY = true;
- mTmpState.animateTo(changingView, mAnimationProperties);
- mAnimationProperties.resetCustomInterpolators();
- }
+ mAnimationProperties.duration = ANIMATION_DURATION_HEADS_UP_DISAPPEAR;
+ mAnimationProperties.setCustomInterpolator(View.TRANSLATION_Y,
+ Interpolators.FAST_OUT_SLOW_IN_REVERSE);
+ mAnimationProperties.getAnimationFilter().animateY = true;
+ mTmpState.animateTo(changingView, mAnimationProperties);
+ mAnimationProperties.resetCustomInterpolators();
} else if (endRunnable != null) {
endRunnable.run();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt
index 382b307..2371ccc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/RoundableTest.kt
@@ -1,11 +1,9 @@
package com.android.systemui.statusbar.notification
-import android.platform.test.annotations.EnableFlags
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.shared.NotificationsImprovedHunAnimation
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import org.junit.Assert.assertEquals
@@ -148,7 +146,6 @@
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun getCornerRadii_radius_maxed_to_height() {
whenever(targetView.height).thenReturn(10)
roundable.requestRoundness(1f, 1f, SOURCE1)
@@ -157,7 +154,6 @@
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun getCornerRadii_topRadius_maxed_to_height() {
whenever(targetView.height).thenReturn(5)
roundable.requestRoundness(1f, 0f, SOURCE1)
@@ -166,7 +162,6 @@
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun getCornerRadii_bottomRadius_maxed_to_height() {
whenever(targetView.height).thenReturn(5)
roundable.requestRoundness(0f, 1f, SOURCE1)
@@ -175,7 +170,6 @@
}
@Test
- @EnableFlags(NotificationsImprovedHunAnimation.FLAG_NAME)
fun getCornerRadii_radii_kept() {
whenever(targetView.height).thenReturn(100)
roundable.requestRoundness(1f, 1f, SOURCE1)
@@ -188,16 +182,9 @@
assertEquals("bottomCornerRadius", bottom, roundable.bottomCornerRadius)
}
- class FakeRoundable(
- targetView: View,
- radius: Float = MAX_RADIUS,
- ) : Roundable {
+ class FakeRoundable(targetView: View, radius: Float = MAX_RADIUS) : Roundable {
override val roundableState =
- RoundableState(
- targetView = targetView,
- roundable = this,
- maxRadius = radius,
- )
+ RoundableState(targetView = targetView, roundable = this, maxRadius = radius)
override val clipHeight: Int
get() = roundableState.targetView.height
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index ca4b5d4..6ccfaf3 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -41,6 +41,7 @@
<activity android:name=".PlatformVpnConfirmDialog"
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight"
android:noHistory="true"
+ android:enableOnBackInvokedCallback="false"
android:excludeFromRecents="true"
android:exported="true">
</activity>
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f86474f..70febcd 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -22,6 +22,7 @@
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_END;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE;
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
+import static android.content.pm.Flags.appCompatOption16kb;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
@@ -2025,6 +2026,16 @@
runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
}
+ if (appCompatOption16kb()) {
+ boolean is16KbDevice = Os.sysconf(OsConstants._SC_PAGESIZE) == 16384;
+ if (is16KbDevice
+ && mService.mContext
+ .getPackageManager()
+ .isPageSizeCompatEnabled(app.info.packageName)) {
+ runtimeFlags |= Zygote.ENABLE_PAGE_SIZE_APP_COMPAT;
+ }
+ }
+
String invokeWith = null;
if (debuggableFlag) {
// Debuggable apps may include a wrapper script with their library directory.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 776bf53..9956d85 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4613,6 +4613,17 @@
} else if (fromOrientation != requestedOrientation) {
return false;
}
+
+ // If another activity above the activity which has starting window, allows to steal the
+ // starting window if the above activity isn't drawn.
+ if (task.getChildCount() >= 3
+ && fromActivity.mStartingData.mAssociatedTask == null) {
+ final ActivityRecord aboveFrom = task.getActivityAbove(fromActivity);
+ if (aboveFrom != null && aboveFrom != this && !aboveFrom.mReportedDrawn) {
+ return false;
+ }
+ }
+
// In this case, the starting icon has already been displayed, so start
// letting windows get shown immediately without any more transitions.
if (fromActivity.mVisible) {
@@ -4636,6 +4647,16 @@
tStartingWindow.mToken = this;
tStartingWindow.mActivityRecord = this;
+ if (mStartingData.mRemoveAfterTransaction == AFTER_TRANSACTION_REMOVE_DIRECTLY) {
+ // The removal of starting window should wait for window drawn of current
+ // activity.
+ final WindowState mainWin = findMainWindow(false /* includeStartingApp */);
+ if (mainWin == null || !mainWin.isDrawn()) {
+ mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_IDLE;
+ mStartingData.mPrepareRemoveAnimation = false;
+ }
+ }
+
ProtoLog.v(WM_DEBUG_ADD_REMOVE,
"Removing starting %s from %s", tStartingWindow, fromActivity);
mTransitionController.collect(tStartingWindow);