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

Commit f1f400f4 authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez
Browse files

Checking that the long-press effect has a positve duration before

initializing and binding

The QSTile State reports the duration of the effect so it can be used by
the tile to initialize a visuo-haptic long-press effect. The effect gets
created and initialized only if the duration is positive.

Test: atest SystemUITests:QSTileViewImplTest
Flag: ACONFIG quick_settings_visual_haptics_longpress DEVELOPMENT
Bug: 329405539
Change-Id: I4c072a29a0a91b857ae408f8f79eab259c68970f
parent 6ad912ae
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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();
    }
}
+18 −0
Original line number Diff line number Diff line
@@ -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 */
+23 −11
Original line number Diff line number Diff line
@@ -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()
        if (longPressEffect == null) {
            longPressEffect =
                QSLongPressEffect(
                    vibratorHelper,
                ViewConfiguration.getLongPressTimeout() - ViewConfiguration.getTapTimeout(),
                    effectDuration,
                )
        } else {
            longPressEffect?.resetWithDuration(effectDuration)
        }
        return true
    }

    private fun initializeLongPressProperties() {
+33 −0
Original line number Diff line number Diff line
@@ -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)
        }