Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 541f71a7 authored by Yeabkal Wubshit's avatar Yeabkal Wubshit Committed by Android (Google) Code Review
Browse files

Merge "Add scroll haptics for AbsListView and ScrollView" into main

parents 4391aaa1 cbb08ee3
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ java_defaults {
        ":telecom_flags_core_java_lib{.generated_srcjars}",
        ":telecom_flags_core_java_lib{.generated_srcjars}",
        ":android.companion.virtual.flags-aconfig-java{.generated_srcjars}",
        ":android.companion.virtual.flags-aconfig-java{.generated_srcjars}",
        ":android.view.inputmethod.flags-aconfig-java{.generated_srcjars}",
        ":android.view.inputmethod.flags-aconfig-java{.generated_srcjars}",
        ":android.widget.flags-aconfig-java{.generated_srcjars}",
    ],
    ],
    // Add aconfig-annotations-lib as a dependency for the optimization
    // Add aconfig-annotations-lib as a dependency for the optimization
    libs: ["aconfig-annotations-lib"],
    libs: ["aconfig-annotations-lib"],
@@ -185,3 +186,17 @@ java_aconfig_library {
    aconfig_declarations: "android.view.flags-aconfig",
    aconfig_declarations: "android.view.flags-aconfig",
    defaults: ["framework-minus-apex-aconfig-java-defaults"],
    defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
}

// Widget
aconfig_declarations {
    name: "android.widget.flags-aconfig",
    package: "android.widget.flags",
    srcs: ["core/java/android/widget/flags/*.aconfig"],
}

java_aconfig_library {
    name: "android.widget.flags-aconfig-java",
    aconfig_declarations: "android.widget.flags-aconfig",
    defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+22 −8
Original line number Original line Diff line number Diff line
@@ -53,6 +53,7 @@ import android.view.ActionMode;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.HapticFeedbackConstants;
import android.view.HapticScrollFeedbackProvider;
import android.view.InputDevice;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
@@ -91,6 +92,7 @@ import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.SurroundingText;
import android.view.inputmethod.SurroundingText;
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty.EnumEntry;
import android.view.inspector.InspectableProperty.EnumEntry;
import android.widget.flags.Flags;
import android.widget.RemoteViews.InteractionHandler;
import android.widget.RemoteViews.InteractionHandler;


import com.android.internal.R;
import com.android.internal.R;
@@ -918,6 +920,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te


    private DifferentialMotionFlingHelper mDifferentialMotionFlingHelper;
    private DifferentialMotionFlingHelper mDifferentialMotionFlingHelper;


    private HapticScrollFeedbackProvider mHapticScrollFeedbackProvider;

    public AbsListView(Context context) {
    public AbsListView(Context context) {
        super(context);
        super(context);
        setupDeviceConfigProperties();
        setupDeviceConfigProperties();
@@ -4502,10 +4506,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                final float axisValue = (axis == -1) ? 0 : event.getAxisValue(axis);
                final float axisValue = (axis == -1) ? 0 : event.getAxisValue(axis);
                final int delta = Math.round(axisValue * mVerticalScrollFactor);
                final int delta = Math.round(axisValue * mVerticalScrollFactor);
                if (delta != 0) {
                if (delta != 0) {
                    // Tracks whether or not we should attempt fling for this event.
                    // Fling should not be attempted if the view is already at the limit of scroll,
                    // since it conflicts with EdgeEffect.
                    boolean shouldAttemptFling = true;
                    // If we're moving down, we want the top item. If we're moving up, bottom item.
                    // If we're moving down, we want the top item. If we're moving up, bottom item.
                    final int motionIndex = delta > 0 ? 0 : getChildCount() - 1;
                    final int motionIndex = delta > 0 ? 0 : getChildCount() - 1;


@@ -4518,10 +4518,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    final int overscrollMode = getOverScrollMode();
                    final int overscrollMode = getOverScrollMode();


                    if (!trackMotionScroll(delta, delta)) {
                    if (!trackMotionScroll(delta, delta)) {
                        if (shouldAttemptFling) {
                        if (Flags.platformWidgetHapticScrollFeedback()) {
                            initHapticScrollFeedbackProviderIfNotExists();
                            mHapticScrollFeedbackProvider.onScrollProgress(event, axis, delta);
                        }
                        initDifferentialFlingHelperIfNotExists();
                        initDifferentialFlingHelperIfNotExists();
                        mDifferentialMotionFlingHelper.onMotionEvent(event, axis);
                        mDifferentialMotionFlingHelper.onMotionEvent(event, axis);
                        }
                        return true;
                        return true;
                    } else if (!event.isFromSource(InputDevice.SOURCE_MOUSE) && motionView != null
                    } else if (!event.isFromSource(InputDevice.SOURCE_MOUSE) && motionView != null
                            && (overscrollMode == OVER_SCROLL_ALWAYS
                            && (overscrollMode == OVER_SCROLL_ALWAYS
@@ -4530,7 +4532,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                        int motionViewRealTop = motionView.getTop();
                        int motionViewRealTop = motionView.getTop();
                        float overscroll = (delta - (motionViewRealTop - motionViewPrevTop))
                        float overscroll = (delta - (motionViewRealTop - motionViewPrevTop))
                                / ((float) getHeight());
                                / ((float) getHeight());
                        if (delta > 0) {
                        boolean hitTopLimit = delta > 0;
                        if (Flags.platformWidgetHapticScrollFeedback()) {
                            initHapticScrollFeedbackProviderIfNotExists();
                            mHapticScrollFeedbackProvider.onScrollLimit(
                                    event, axis, /* isStart= */ hitTopLimit);
                        }
                        if (hitTopLimit) {
                            mEdgeGlowTop.onPullDistance(overscroll, 0.5f);
                            mEdgeGlowTop.onPullDistance(overscroll, 0.5f);
                            mEdgeGlowTop.onRelease();
                            mEdgeGlowTop.onRelease();
                        } else {
                        } else {
@@ -4696,6 +4704,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        }
        }
    }
    }


    private void initHapticScrollFeedbackProviderIfNotExists() {
        if (mHapticScrollFeedbackProvider == null) {
            mHapticScrollFeedbackProvider = new HapticScrollFeedbackProvider(this);
        }
    }

    private void recycleVelocityTracker() {
    private void recycleVelocityTracker() {
        if (mVelocityTracker != null) {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker.recycle();
+24 −4
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.StrictMode;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Log;
import android.view.FocusFinder;
import android.view.FocusFinder;
import android.view.HapticScrollFeedbackProvider;
import android.view.InputDevice;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent;
@@ -47,6 +48,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.animation.AnimationUtils;
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty;
import android.widget.flags.Flags;


import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
@@ -206,6 +208,8 @@ public class ScrollView extends FrameLayout {


    private DifferentialMotionFlingHelper mDifferentialMotionFlingHelper;
    private DifferentialMotionFlingHelper mDifferentialMotionFlingHelper;


    private HapticScrollFeedbackProvider mHapticScrollFeedbackProvider;

    /**
    /**
     * Sentinel value for no current active pointer.
     * Sentinel value for no current active pointer.
     * Used by {@link #mActivePointerId}.
     * Used by {@link #mActivePointerId}.
@@ -604,6 +608,12 @@ public class ScrollView extends FrameLayout {
        }
        }
    }
    }


    private void initHapticScrollFeedbackProviderIfNotExists() {
        if (mHapticScrollFeedbackProvider == null) {
            mHapticScrollFeedbackProvider = new HapticScrollFeedbackProvider(this);
        }
    }

    private void recycleVelocityTracker() {
    private void recycleVelocityTracker() {
        if (mVelocityTracker != null) {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker.recycle();
@@ -967,7 +977,7 @@ public class ScrollView extends FrameLayout {
                    // Tracks whether or not we should attempt fling for this event.
                    // Tracks whether or not we should attempt fling for this event.
                    // Fling should not be attempted if the view is already at the limit of scroll,
                    // Fling should not be attempted if the view is already at the limit of scroll,
                    // since it conflicts with EdgeEffect.
                    // since it conflicts with EdgeEffect.
                    boolean shouldAttemptFling = true;
                    boolean hitLimit = false;
                    final int range = getScrollRange();
                    final int range = getScrollRange();
                    int oldScrollY = mScrollY;
                    int oldScrollY = mScrollY;
                    int newScrollY = oldScrollY - delta;
                    int newScrollY = oldScrollY - delta;
@@ -986,7 +996,7 @@ public class ScrollView extends FrameLayout {
                            absorbed = true;
                            absorbed = true;
                        }
                        }
                        newScrollY = 0;
                        newScrollY = 0;
                        shouldAttemptFling = false;
                        hitLimit = true;
                    } else if (newScrollY > range) {
                    } else if (newScrollY > range) {
                        if (canOverscroll) {
                        if (canOverscroll) {
                            mEdgeGlowBottom.onPullDistance(
                            mEdgeGlowBottom.onPullDistance(
@@ -996,11 +1006,21 @@ public class ScrollView extends FrameLayout {
                            absorbed = true;
                            absorbed = true;
                        }
                        }
                        newScrollY = range;
                        newScrollY = range;
                        shouldAttemptFling = false;
                        hitLimit = true;
                    }
                    }
                    if (newScrollY != oldScrollY) {
                    if (newScrollY != oldScrollY) {
                        super.scrollTo(mScrollX, newScrollY);
                        super.scrollTo(mScrollX, newScrollY);
                        if (shouldAttemptFling) {
                        if (hitLimit) {
                            if (Flags.platformWidgetHapticScrollFeedback()) {
                                initHapticScrollFeedbackProviderIfNotExists();
                                mHapticScrollFeedbackProvider.onScrollLimit(
                                        event, axis, /* isStart= */ newScrollY == 0);
                            }
                        } else {
                            if (Flags.platformWidgetHapticScrollFeedback()) {
                                initHapticScrollFeedbackProviderIfNotExists();
                                mHapticScrollFeedbackProvider.onScrollProgress(event, axis, delta);
                            }
                            initDifferentialFlingHelperIfNotExists();
                            initDifferentialFlingHelperIfNotExists();
                            mDifferentialMotionFlingHelper.onMotionEvent(event, axis);
                            mDifferentialMotionFlingHelper.onMotionEvent(event, axis);
                        }
                        }
+8 −0
Original line number Original line Diff line number Diff line
package: "android.widget.flags"

flag {
    namespace: "widget"
    name: "platform_widget_haptic_scroll_feedback"
    description: "Enables haptic scroll feedback in platform widgets"
    bug: "287914819"
}
 No newline at end of file