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

Commit 22e8ab52 authored by Marvin Escobar Barajas's avatar Marvin Escobar Barajas
Browse files

Add scroll haptics for touchscreen scrolling in AbsListView

Adds haptics for touchscreen scrolling using the HapticScrollFeedbackProvider implementation.
This is the first step towards integrating HapticScrollFeedbackProvider
across multiple widgets in Platform and Jetpack per go/wear-dd-sfbp-integration.

BUG: 331830899
Test: Added as a todo
Flag: android.view.flags.enable_touch_scroll_feedback
Change-Id: Ib331ae01fcb565436a3ef399f97d031f685024ef
parent b3bd1650
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -373,6 +373,7 @@ public class ViewConfiguration {
    private final int mMaximumDrawingCacheSize;
    private final int mOverscrollDistance;
    private final int mOverflingDistance;
    private final boolean mViewTouchScreenHapticScrollFeedbackEnabled;
    @UnsupportedAppUsage
    private final boolean mFadingMarqueeEnabled;
    private final long mGlobalActionsKeyTimeout;
@@ -437,6 +438,7 @@ public class ViewConfiguration {
        mSmartSelectionInitializedTimeout = SMART_SELECTION_INITIALIZED_TIMEOUT_IN_MILLISECOND;
        mSmartSelectionInitializingTimeout = SMART_SELECTION_INITIALIZING_TIMEOUT_IN_MILLISECOND;
        mPreferKeepClearForFocusEnabled = false;
        mViewTouchScreenHapticScrollFeedbackEnabled = false;
    }

    /**
@@ -588,6 +590,12 @@ public class ViewConfiguration {
        mViewBasedRotaryEncoderScrollHapticsEnabledConfig =
                res.getBoolean(
                        com.android.internal.R.bool.config_viewBasedRotaryEncoderHapticsEnabled);
        mViewTouchScreenHapticScrollFeedbackEnabled =
                Flags.enableTouchScrollFeedback()
                        ? res.getBoolean(
                        com.android.internal.R.bool
                                .config_viewTouchScreenHapticScrollFeedbackEnabled)
                        : false;
    }

    /**
@@ -1285,6 +1293,10 @@ public class ViewConfiguration {
            return mRotaryEncoderHapticScrollFeedbackEnabled;
        }

        if ((source & InputDevice.SOURCE_TOUCHSCREEN) != 0) {
            return mViewTouchScreenHapticScrollFeedbackEnabled;
        }

        return false;
    }

+8 −1
Original line number Diff line number Diff line
@@ -15,3 +15,10 @@ flag {
    description: "If enabled, the rotary encoder scroll haptic implementation in the View class will be used, and the HapticScrollFeedbackProvider logic for rotary encoder haptic will be muted."
    bug: "299587011"
}

flag {
    namespace: "toolkit"
    name: "enable_touch_scroll_feedback"
    description: "Enables touchscreen haptic scroll feedback"
    bug: "331830899"
}
+21 −7
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.widget;

import static android.view.flags.Flags.enableTouchScrollFeedback;
import static android.view.flags.Flags.scrollFeedbackApi;
import static android.view.flags.Flags.viewVelocityApi;

import android.annotation.ColorInt;
@@ -82,7 +84,6 @@ import android.view.animation.LinearInterpolator;
import android.view.autofill.AutofillId;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureSession;
import android.view.flags.Flags;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
@@ -3703,7 +3704,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                // If it's non-null, we're already in a scroll.
                mScrollStrictSpan = StrictMode.enterCriticalSpan("AbsListView-scroll");
            }

            if (y != mLastY) {
                // We may be here after stopping a fling and continuing to scroll.
                // If so, we haven't disallowed intercepting touch events yet.
@@ -3735,8 +3735,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                boolean atEdge = false;
                if (incrementalDeltaY != 0) {
                    atEdge = trackMotionScroll(deltaY, incrementalDeltaY);
                }

                    // TODO: b/360198915 - Add unit testing for using ScrollFeedbackProvider
                    if (enableTouchScrollFeedback()) {
                        initHapticScrollFeedbackProviderIfNotExists();
                        mHapticScrollFeedbackProvider.onScrollProgress(
                                vtev.getDeviceId(), vtev.getSource(), MotionEvent.AXIS_Y,
                                incrementalDeltaY);
                    }
                }
                // Check to see if we have bumped into the scroll limit
                motionView = this.getChildAt(motionIndex);
                if (motionView != null) {
@@ -3745,7 +3752,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    final int motionViewRealTop = motionView.getTop();
                    if (atEdge) {
                        // Apply overscroll

                        int overscroll = -incrementalDeltaY -
                                (motionViewRealTop - motionViewPrevTop);
                        if (dispatchNestedScroll(0, overscroll - incrementalDeltaY, 0, overscroll,
@@ -3772,6 +3778,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                                    mDirection = 0; // Reset when entering overscroll.
                                    mTouchMode = TOUCH_MODE_OVERSCROLL;
                                }

                                if (enableTouchScrollFeedback()) {
                                    initHapticScrollFeedbackProviderIfNotExists();
                                    mHapticScrollFeedbackProvider.onScrollLimit(
                                            vtev.getDeviceId(), vtev.getSource(),
                                            MotionEvent.AXIS_Y,
                                            /* isStart= */ incrementalDeltaY > 0);
                                }

                                if (incrementalDeltaY > 0) {
                                    mEdgeGlowTop.onPullDistance((float) -overscroll / getHeight(),
                                            (float) x / getWidth());
@@ -3981,7 +3996,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
        if (mFastScroll != null && mFastScroll.onTouchEvent(ev)) {
            return true;
        }

        initVelocityTrackerIfNotExists();
        final MotionEvent vtev = MotionEvent.obtain(ev);

@@ -4520,7 +4534,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                    final int overscrollMode = getOverScrollMode();

                    if (!trackMotionScroll(delta, delta)) {
                        if (Flags.scrollFeedbackApi()) {
                        if (scrollFeedbackApi()) {
                            initHapticScrollFeedbackProviderIfNotExists();
                            mHapticScrollFeedbackProvider.onScrollProgress(
                                    event.getDeviceId(), event.getSource(), axis, delta);
@@ -4536,7 +4550,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
                        float overscroll = (delta - (motionViewRealTop - motionViewPrevTop))
                                / ((float) getHeight());
                        boolean hitTopLimit = delta > 0;
                        if (Flags.scrollFeedbackApi()) {
                        if (scrollFeedbackApi()) {
                            initHapticScrollFeedbackProviderIfNotExists();
                            mHapticScrollFeedbackProvider.onScrollLimit(
                                    event.getDeviceId(), event.getSource(), axis,
+4 −0
Original line number Diff line number Diff line
@@ -7030,6 +7030,10 @@
         {@link InputDevice#SOURCE_ROTARY_ENCODER}s. -->
    <bool name="config_viewBasedRotaryEncoderHapticsEnabled">false</bool>

    <!-- Whether the scroll haptic feedback implementation is enabled for
    {@link InputDevice#SOURCE_TOUCHSCREEN}s. -->
    <bool name="config_viewTouchScreenHapticScrollFeedbackEnabled">false</bool>

    <!-- Whether the media player is shown on the quick settings -->
    <bool name="config_quickSettingsShowMediaPlayer">true</bool>

+3 −0
Original line number Diff line number Diff line
@@ -5488,8 +5488,11 @@
  <java-symbol type="bool" name="config_tvExternalInputLoggingDisplayNameFilterEnabled" />
  <java-symbol type="array" name="config_tvExternalInputLoggingDeviceOnScreenDisplayNames" />
  <java-symbol type="array" name="config_tvExternalInputLoggingDeviceBrandNames" />

  <!-- Scroll Feedback Configs -->
  <java-symbol type="bool" name="config_viewRotaryEncoderHapticScrollFedbackEnabled" />
  <java-symbol type="bool" name="config_viewBasedRotaryEncoderHapticsEnabled" />
  <java-symbol type="bool" name="config_viewTouchScreenHapticScrollFeedbackEnabled" />

  <java-symbol type="bool" name="config_quickSettingsShowMediaPlayer" />