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

Commit cbb08ee3 authored by Yeabkal Wubshit's avatar Yeabkal Wubshit
Browse files

Add scroll haptics for AbsListView and ScrollView

Bug: 287914819
Test: manual
Change-Id: I25a930b3305e6ddb34574abecf054241d93ad2e2
parent 0aaed5a6
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ java_defaults {
        ":telecom_flags_core_java_lib{.generated_srcjars}",
        ":android.companion.virtual.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
    libs: ["aconfig-annotations-lib"],
@@ -185,3 +186,17 @@ java_aconfig_library {
    aconfig_declarations: "android.view.flags-aconfig",
    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 Diff line number Diff line
@@ -53,6 +53,7 @@ import android.view.ActionMode;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.HapticScrollFeedbackProvider;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -91,6 +92,7 @@ import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.SurroundingText;
import android.view.inspector.InspectableProperty;
import android.view.inspector.InspectableProperty.EnumEntry;
import android.widget.flags.Flags;
import android.widget.RemoteViews.InteractionHandler;

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

    private DifferentialMotionFlingHelper mDifferentialMotionFlingHelper;

    private HapticScrollFeedbackProvider mHapticScrollFeedbackProvider;

    public AbsListView(Context context) {
        super(context);
        setupDeviceConfigProperties();
@@ -4502,10 +4506,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                final float axisValue = (axis == -1) ? 0 : event.getAxisValue(axis);
                final int delta = Math.round(axisValue * mVerticalScrollFactor);
                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.
                    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();

                    if (!trackMotionScroll(delta, delta)) {
                        if (shouldAttemptFling) {
                        if (Flags.platformWidgetHapticScrollFeedback()) {
                            initHapticScrollFeedbackProviderIfNotExists();
                            mHapticScrollFeedbackProvider.onScrollProgress(event, axis, delta);
                        }
                        initDifferentialFlingHelperIfNotExists();
                        mDifferentialMotionFlingHelper.onMotionEvent(event, axis);
                        }
                        return true;
                    } else if (!event.isFromSource(InputDevice.SOURCE_MOUSE) && motionView != null
                            && (overscrollMode == OVER_SCROLL_ALWAYS
@@ -4530,7 +4532,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                        int motionViewRealTop = motionView.getTop();
                        float overscroll = (delta - (motionViewRealTop - motionViewPrevTop))
                                / ((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.onRelease();
                        } 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() {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
+24 −4
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.StrictMode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.FocusFinder;
import android.view.HapticScrollFeedbackProvider;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -47,6 +48,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.view.inspector.InspectableProperty;
import android.widget.flags.Flags;

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

    private DifferentialMotionFlingHelper mDifferentialMotionFlingHelper;

    private HapticScrollFeedbackProvider mHapticScrollFeedbackProvider;

    /**
     * Sentinel value for no current active pointer.
     * 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() {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
@@ -967,7 +977,7 @@ public class ScrollView extends FrameLayout {
                    // 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;
                    boolean hitLimit = false;
                    final int range = getScrollRange();
                    int oldScrollY = mScrollY;
                    int newScrollY = oldScrollY - delta;
@@ -986,7 +996,7 @@ public class ScrollView extends FrameLayout {
                            absorbed = true;
                        }
                        newScrollY = 0;
                        shouldAttemptFling = false;
                        hitLimit = true;
                    } else if (newScrollY > range) {
                        if (canOverscroll) {
                            mEdgeGlowBottom.onPullDistance(
@@ -996,11 +1006,21 @@ public class ScrollView extends FrameLayout {
                            absorbed = true;
                        }
                        newScrollY = range;
                        shouldAttemptFling = false;
                        hitLimit = true;
                    }
                    if (newScrollY != oldScrollY) {
                        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();
                            mDifferentialMotionFlingHelper.onMotionEvent(event, axis);
                        }
+8 −0
Original line number 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