Loading core/java/android/view/ViewConfiguration.java +12 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } /** Loading Loading @@ -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; } /** Loading Loading @@ -1285,6 +1293,10 @@ public class ViewConfiguration { return mRotaryEncoderHapticScrollFeedbackEnabled; } if ((source & InputDevice.SOURCE_TOUCHSCREEN) != 0) { return mViewTouchScreenHapticScrollFeedbackEnabled; } return false; } Loading core/java/android/view/flags/scroll_feedback_flags.aconfig +8 −1 Original line number Diff line number Diff line Loading @@ -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" } core/java/android/widget/AbsListView.java +21 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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, Loading @@ -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()); Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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, Loading core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -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> Loading core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -5490,8 +5490,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" /> Loading Loading
core/java/android/view/ViewConfiguration.java +12 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } /** Loading Loading @@ -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; } /** Loading Loading @@ -1285,6 +1293,10 @@ public class ViewConfiguration { return mRotaryEncoderHapticScrollFeedbackEnabled; } if ((source & InputDevice.SOURCE_TOUCHSCREEN) != 0) { return mViewTouchScreenHapticScrollFeedbackEnabled; } return false; } Loading
core/java/android/view/flags/scroll_feedback_flags.aconfig +8 −1 Original line number Diff line number Diff line Loading @@ -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" }
core/java/android/widget/AbsListView.java +21 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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) { Loading @@ -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, Loading @@ -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()); Loading Loading @@ -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); Loading Loading @@ -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); Loading @@ -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, Loading
core/res/res/values/config.xml +4 −0 Original line number Diff line number Diff line Loading @@ -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> Loading
core/res/res/values/symbols.xml +3 −0 Original line number Diff line number Diff line Loading @@ -5490,8 +5490,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" /> Loading