diff options
4 files changed, 80 insertions, 11 deletions
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java index a8999ff31f8a..6c8949e51094 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java @@ -16,6 +16,7 @@ package com.android.systemui.plugins.qs; import android.content.Context; import android.view.View; +import android.view.ViewConfiguration; import android.widget.LinearLayout; import com.android.systemui.plugins.annotations.DependsOn; @@ -74,4 +75,9 @@ public abstract class QSTileView extends LinearLayout { /** Sets the index of this tile in its layout */ public abstract void setPosition(int position); + + /** Get the duration of a visuo-haptic long-press effect */ + public int getLongPressEffectDuration() { + return ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt index ec72a1422973..f1620d96b159 100644 --- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt +++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt @@ -214,6 +214,24 @@ class QSLongPressEffect( _actionType.value = null } + /** + * Reset the effect with a new effect duration. + * + * The effect will go back to an [IDLE] state where it can begin its logic with a new duration. + * + * @param[duration] New duration for the long-press effect + */ + fun resetWithDuration(duration: Int) { + // The effect can't reset if it is running + if (effectAnimator.isRunning) return + + effectAnimator.duration = duration.toLong() + _effectProgress.value = 0f + _actionType.value = null + waitJob?.cancel() + state = State.IDLE + } + enum class State { IDLE, /* The effect is idle waiting for touch input */ TIMEOUT_WAIT, /* The effect is waiting for a [PRESSED_TIMEOUT] period */ diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 63963ded2923..e1c543f8f025 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -37,7 +37,6 @@ import android.util.TypedValue import android.view.Gravity import android.view.LayoutInflater import android.view.View -import android.view.ViewConfiguration import android.view.ViewGroup import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityNodeInfo @@ -185,6 +184,8 @@ open class QSTileViewImpl @JvmOverloads constructor( private var initialLongPressProperties: QSLongPressProperties? = null private var finalLongPressProperties: QSLongPressProperties? = null private val colorEvaluator = ArgbEvaluator.getInstance() + val hasLongPressEffect: Boolean + get() = longPressEffect != null init { val typedValue = TypedValue() @@ -611,10 +612,9 @@ open class QSTileViewImpl @JvmOverloads constructor( // Long-press effects if (quickSettingsVisualHapticsLongpress()){ - if (state.handlesLongClick) { - // initialize the long-press effect and set it as the touch listener + if (state.handlesLongClick && maybeCreateAndInitializeLongPressEffect()) { + // set the valid long-press effect as the touch listener showRippleEffect = false - initializeLongPressEffect() setOnTouchListener(longPressEffect) QSLongPressEffectViewBinder.bind(this, longPressEffect) } else { @@ -751,7 +751,7 @@ open class QSTileViewImpl @JvmOverloads constructor( override fun onActivityLaunchAnimationEnd() = resetLongPressEffectProperties() fun updateLongPressEffectProperties(effectProgress: Float) { - if (!isLongClickable) return + if (!isLongClickable || longPressEffect == null) return setAllColors( colorEvaluator.evaluate( effectProgress, @@ -836,13 +836,25 @@ open class QSTileViewImpl @JvmOverloads constructor( icon.setTint(icon.mIcon as ImageView, lastIconTint) } - private fun initializeLongPressEffect() { + private fun maybeCreateAndInitializeLongPressEffect(): Boolean { + // Don't setup the effect if the long-press duration is invalid + val effectDuration = longPressEffectDuration + if (effectDuration <= 0) { + longPressEffect = null + return false + } + initializeLongPressProperties() - longPressEffect = - QSLongPressEffect( - vibratorHelper, - ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout(), - ) + if (longPressEffect == null) { + longPressEffect = + QSLongPressEffect( + vibratorHelper, + effectDuration, + ) + } else { + longPressEffect?.resetWithDuration(effectDuration) + } + return true } private fun initializeLongPressProperties() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt index e0fff9c10873..04e214ac7a04 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt @@ -18,6 +18,7 @@ package com.android.systemui.qs.tileimpl import android.content.Context import android.graphics.drawable.Drawable +import android.platform.test.annotations.EnableFlags import android.service.quicksettings.Tile import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -27,6 +28,7 @@ import android.view.View import android.view.accessibility.AccessibilityNodeInfo import android.widget.TextView import androidx.test.filters.SmallTest +import com.android.systemui.Flags.FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.plugins.qs.QSTile @@ -380,6 +382,34 @@ class QSTileViewImplTest : SysuiTestCase() { assertThat(tileView.stateDescription?.contains(unavailableString)).isTrue() } + @Test + @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) + fun onStateChange_longPressEffectActive_withInvalidDuration_doesNotCreateEffect() { + val state = QSTile.State() // A state that handles longPress + + // GIVEN an invalid long-press effect duration + tileView.constantLongPressEffectDuration = -1 + + // WHEN the state changes + tileView.changeState(state) + + // THEN the long-press effect is not created + assertThat(tileView.hasLongPressEffect).isFalse() + } + + @Test + @EnableFlags(FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS) + fun onStateChange_longPressEffectActive_withValidDuration_createsEffect() { + // GIVEN a test state that handles long-press and a valid long-press effect duration + val state = QSTile.State() + + // WHEN the state changes + tileView.changeState(state) + + // THEN the long-press effect created + assertThat(tileView.hasLongPressEffect).isTrue() + } + class FakeTileView( context: Context, collapsed: Boolean @@ -387,6 +417,9 @@ class QSTileViewImplTest : SysuiTestCase() { ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings), collapsed ) { + var constantLongPressEffectDuration = 500 + + override fun getLongPressEffectDuration(): Int = constantLongPressEffectDuration fun changeState(state: QSTile.State) { handleStateChanged(state) } |