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

Commit 4c3f3ae4 authored by Kevin Chyn's avatar Kevin Chyn
Browse files

Use button instead of seekbar when touch exploration is enabled

When touch exploration (such as talkback) is enabled, it's much
more difficult to accidentally exit the rear display mode, since
it requires two taps in order to activate a button.

Flag: EXEMPT bugfix
Fixes: 399023818
Test: atest RearDisplayInnerDialogDelegateTest
Test: atest RearDisplayCoreSTartableTest
Change-Id: If10e1116080ac3d83d27c7685c3b2915a5e68f14
parent f4bf234d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@
        android:gravity="center_horizontal" />

    <TextView
        android:id="@+id/seekbar_instructions"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/rear_display_unfolded_front_screen_on_slide_to_cancel"
@@ -73,4 +74,13 @@
        android:background="@null"
        android:gravity="center_horizontal" />

    <Button
        android:id="@+id/cancel_button"
        android:text="@string/cancel"
        android:layout_width="@dimen/rear_display_animation_width_opened"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:visibility="gone"
        style="@style/Widget.Dialog.Button.BorderButton"/>

</LinearLayout>
+13 −0
Original line number Diff line number Diff line
@@ -19,14 +19,18 @@ package com.android.systemui.reardisplay
import android.content.Context
import android.hardware.devicestate.DeviceStateManager
import android.hardware.devicestate.feature.flags.Flags
import android.os.Handler
import android.view.accessibility.AccessibilityManager
import androidx.annotation.VisibleForTesting
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.display.domain.interactor.RearDisplayStateInteractor
import com.android.systemui.statusbar.phone.SystemUIDialog
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@@ -52,6 +56,8 @@ internal constructor(
    private val rearDisplayInnerDialogDelegateFactory: RearDisplayInnerDialogDelegate.Factory,
    @Application private val scope: CoroutineScope,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val accessibilityManager: AccessibilityManager,
    @Background private val handler: Handler,
) : CoreStartable, AutoCloseable {

    companion object {
@@ -77,6 +83,12 @@ internal constructor(
    override fun start() {
        if (Flags.deviceStateRdmV2()) {
            var dialog: SystemUIDialog? = null
            var touchExplorationEnabled = AtomicBoolean(false)

            accessibilityManager.addTouchExplorationStateChangeListener(
                { enabled -> touchExplorationEnabled.set(enabled) },
                handler,
            )

            keyguardUpdateMonitor.registerCallback(keyguardCallback)

@@ -99,6 +111,7 @@ internal constructor(
                                            rearDisplayInnerDialogDelegateFactory.create(
                                                rearDisplayContext,
                                                deviceStateManager::cancelStateRequest,
                                                touchExplorationEnabled.get(),
                                            )
                                        dialog = delegate.createDialog().apply { show() }
                                    }
+26 −0
Original line number Diff line number Diff line
@@ -20,7 +20,10 @@ import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import android.widget.Button
import android.widget.SeekBar
import android.widget.TextView
import com.android.systemui.haptics.slider.HapticSlider
import com.android.systemui.haptics.slider.HapticSliderPlugin
import com.android.systemui.haptics.slider.HapticSliderViewBinder
@@ -45,6 +48,7 @@ class RearDisplayInnerDialogDelegate
internal constructor(
    private val systemUIDialogFactory: SystemUIDialog.Factory,
    @Assisted private val rearDisplayContext: Context,
    @Assisted private val touchExplorationEnabled: Boolean,
    private val vibratorHelper: VibratorHelper,
    private val msdlPlayer: MSDLPlayer,
    private val systemClock: SystemClock,
@@ -82,6 +86,7 @@ internal constructor(
        fun create(
            rearDisplayContext: Context,
            onCanceledRunnable: Runnable,
            touchExplorationEnabled: Boolean,
        ): RearDisplayInnerDialogDelegate
    }

@@ -95,11 +100,32 @@ internal constructor(

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(dialog: SystemUIDialog, savedInstanceState: Bundle?) {

        dialog.apply {
            setContentView(R.layout.activity_rear_display_enabled)
            setCanceledOnTouchOutside(false)

            requireViewById<Button>(R.id.cancel_button).let { it ->
                if (!touchExplorationEnabled) {
                    return@let
                }

                it.visibility = View.VISIBLE
                it.setOnClickListener { onCanceledRunnable.run() }
            }

            requireViewById<TextView>(R.id.seekbar_instructions).let { it ->
                if (touchExplorationEnabled) {
                    it.visibility = View.GONE
                }
            }

            requireViewById<SeekBar>(R.id.seekbar).let { it ->
                if (touchExplorationEnabled) {
                    it.visibility = View.GONE
                    return@let
                }

                // Create and bind the HapticSliderPlugin
                val hapticSliderPlugin =
                    HapticSliderPlugin(
+5 −1
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package com.android.systemui.reardisplay

import android.hardware.devicestate.feature.flags.Flags.FLAG_DEVICE_STATE_RDM_V2
import android.hardware.display.rearDisplay
import android.os.fakeExecutorHandler
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.Display
import android.view.accessibility.accessibilityManager
import androidx.test.filters.SmallTest
import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
@@ -62,6 +64,8 @@ class RearDisplayCoreStartableTest : SysuiTestCase() {
            kosmos.rearDisplayInnerDialogDelegateFactory,
            kosmos.testScope,
            kosmos.keyguardUpdateMonitor,
            kosmos.accessibilityManager,
            kosmos.fakeExecutorHandler,
        )

    @Before
@@ -69,7 +73,7 @@ class RearDisplayCoreStartableTest : SysuiTestCase() {
        whenever(kosmos.rearDisplay.flags).thenReturn(Display.FLAG_REAR)
        whenever(kosmos.rearDisplay.displayAdjustments)
            .thenReturn(mContext.display.displayAdjustments)
        whenever(kosmos.rearDisplayInnerDialogDelegateFactory.create(any(), any()))
        whenever(kosmos.rearDisplayInnerDialogDelegateFactory.create(any(), any(), any()))
            .thenReturn(mockDelegate)
        whenever(mockDelegate.createDialog()).thenReturn(mockDialog)
    }
+39 −0
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package com.android.systemui.reardisplay

import android.testing.TestableLooper
import android.view.View
import android.widget.Button
import android.widget.SeekBar
import android.widget.TextView
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.haptics.msdl.msdlPlayer
@@ -28,6 +31,7 @@ import com.android.systemui.res.R
import com.android.systemui.statusbar.phone.systemUIDialogDotFactory
import com.android.systemui.testKosmos
import com.android.systemui.util.time.systemClock
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import org.junit.Test
@@ -49,6 +53,7 @@ class RearDisplayInnerDialogDelegateTest : SysuiTestCase() {
            RearDisplayInnerDialogDelegate(
                kosmos.systemUIDialogDotFactory,
                mContext,
                false /* touchExplorationEnabled */,
                kosmos.vibratorHelper,
                kosmos.msdlPlayer,
                kosmos.systemClock,
@@ -68,6 +73,7 @@ class RearDisplayInnerDialogDelegateTest : SysuiTestCase() {
        RearDisplayInnerDialogDelegate(
                kosmos.systemUIDialogDotFactory,
                mContext,
                false /* touchExplorationEnabled */,
                kosmos.vibratorHelper,
                kosmos.msdlPlayer,
                kosmos.systemClock,
@@ -78,6 +84,9 @@ class RearDisplayInnerDialogDelegateTest : SysuiTestCase() {
            .apply {
                show()
                val seekbar = findViewById<SeekBar>(R.id.seekbar)
                assertThat(seekbar.visibility).isEqualTo(View.VISIBLE)
                assertThat(findViewById<TextView>(R.id.seekbar_instructions).visibility)
                    .isEqualTo(View.VISIBLE)
                seekbar.progress = 50
                seekbar.progress = 100
                verify(mockCallback).run()
@@ -90,6 +99,7 @@ class RearDisplayInnerDialogDelegateTest : SysuiTestCase() {
        RearDisplayInnerDialogDelegate(
                kosmos.systemUIDialogDotFactory,
                mContext,
                false /* touchExplorationEnabled */,
                kosmos.vibratorHelper,
                kosmos.msdlPlayer,
                kosmos.systemClock,
@@ -118,4 +128,33 @@ class RearDisplayInnerDialogDelegateTest : SysuiTestCase() {
        // Progress is reset
        verify(mockSeekbar).setProgress(eq(0))
    }

    @Test
    fun testTouchExplorationEnabled() {
        val mockCallback = mock<Runnable>()

        RearDisplayInnerDialogDelegate(
                kosmos.systemUIDialogDotFactory,
                mContext,
                true /* touchExplorationEnabled */,
                kosmos.vibratorHelper,
                kosmos.msdlPlayer,
                kosmos.systemClock,
            ) {
                mockCallback.run()
            }
            .createDialog()
            .apply {
                show()
                assertThat(findViewById<SeekBar>(R.id.seekbar).visibility).isEqualTo(View.GONE)
                assertThat(findViewById<TextView>(R.id.seekbar_instructions).visibility)
                    .isEqualTo(View.GONE)

                val cancelButton = findViewById<Button>(R.id.cancel_button)
                assertThat(cancelButton.visibility).isEqualTo(View.VISIBLE)

                cancelButton.performClick()
                verify(mockCallback).run()
            }
    }
}