From 638f61a57ad80b82c33801be21ad0ee4786c86f0 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Fri, 8 Apr 2022 13:17:00 -0400 Subject: [PATCH] Use larger frame of settings button for clicks That way, the tappable area is of the minimum size. Additionally, set the accessibility class name of the SettingsButton (now an ImageView) to be Button, so the description matches the other buttons in the FooterActions. Test: manual Test: Accessibility Scanner Test: FooterActionsControllerTest Fixes: 227536054 Change-Id: If412d7a5bdb53c363728f06e404fd70725b8c15a --- .../res-keyguard/layout/footer_actions.xml | 3 +++ .../systemui/qs/FooterActionsController.kt | 8 +++----- .../android/systemui/qs/FooterActionsView.kt | 11 ++++------- .../statusbar/phone/SettingsButton.java | 12 ++++++++++-- .../qs/FooterActionsControllerTest.kt | 19 +++++++++++++++++-- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/packages/SystemUI/res-keyguard/layout/footer_actions.xml b/packages/SystemUI/res-keyguard/layout/footer_actions.xml index 7cab0c9c8d232..a7e61029bfdb1 100644 --- a/packages/SystemUI/res-keyguard/layout/footer_actions.xml +++ b/packages/SystemUI/res-keyguard/layout/footer_actions.xml @@ -73,6 +73,9 @@ android:layout_height="@dimen/qs_footer_icon_size" android:layout_gravity="center" android:background="@android:color/transparent" + android:focusable="false" + android:clickable="false" + android:importantForAccessibility="yes" android:contentDescription="@string/accessibility_quick_settings_settings" android:scaleType="centerInside" android:src="@drawable/ic_settings" diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt index 3f394e7b5309d..d701f33c4c666 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -38,7 +38,6 @@ import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED import com.android.systemui.qs.dagger.QSScope import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.phone.MultiUserSwitchController -import com.android.systemui.statusbar.phone.SettingsButton import com.android.systemui.statusbar.policy.DeviceProvisionedController import com.android.systemui.statusbar.policy.UserInfoController import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener @@ -89,8 +88,7 @@ internal class FooterActionsController @Inject constructor( updateVisibility() } - private val settingsButton: SettingsButton = view.findViewById(R.id.settings_button) - private val settingsButtonContainer: View? = view.findViewById(R.id.settings_button_container) + private val settingsButtonContainer: View = view.findViewById(R.id.settings_button_container) private val securityFootersContainer: ViewGroup? = view.findViewById(R.id.security_footers_container) private val powerMenuLite: View = view.findViewById(R.id.pm_lite) @@ -121,7 +119,7 @@ internal class FooterActionsController @Inject constructor( if (!visible || falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return@OnClickListener } - if (v === settingsButton) { + if (v === settingsButtonContainer) { if (!deviceProvisionedController.isCurrentUserSetup) { // If user isn't setup just unlock the device and dump them back at SUW. activityStarter.postQSRunnableDismissingKeyguard {} @@ -166,7 +164,7 @@ internal class FooterActionsController @Inject constructor( } else { powerMenuLite.visibility = View.GONE } - settingsButton.setOnClickListener(onClickListener) + settingsButtonContainer.setOnClickListener(onClickListener) multiUserSetting.isListening = true val securityFooter = securityFooterController.view diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt index 9413a907fc13f..3417d4977fa43 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt @@ -29,7 +29,6 @@ import com.android.settingslib.Utils import com.android.settingslib.drawable.UserIconDrawable import com.android.systemui.R import com.android.systemui.statusbar.phone.MultiUserSwitch -import com.android.systemui.statusbar.phone.SettingsButton /** * Quick Settings bottom buttons placed in footer (aka utility bar) - always visible in expanded QS, @@ -38,7 +37,6 @@ import com.android.systemui.statusbar.phone.SettingsButton */ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) { private lateinit var settingsContainer: View - private lateinit var settingsButton: SettingsButton private lateinit var multiUserSwitch: MultiUserSwitch private lateinit var multiUserAvatar: ImageView @@ -47,15 +45,14 @@ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout( override fun onFinishInflate() { super.onFinishInflate() - settingsButton = findViewById(R.id.settings_button) settingsContainer = findViewById(R.id.settings_button_container) multiUserSwitch = findViewById(R.id.multi_user_switch) multiUserAvatar = multiUserSwitch.findViewById(R.id.multi_user_avatar) // RenderThread is doing more harm than good when touching the header (to expand quick // settings), so disable it for this view - if (settingsButton.background is RippleDrawable) { - (settingsButton.background as RippleDrawable).setForceSoftware(true) + if (settingsContainer.background is RippleDrawable) { + (settingsContainer.background as RippleDrawable).setForceSoftware(true) } importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES } @@ -82,7 +79,7 @@ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout( private fun updateClickabilities() { multiUserSwitch.isClickable = multiUserSwitch.visibility == VISIBLE - settingsButton.isClickable = settingsButton.visibility == VISIBLE + settingsContainer.isClickable = settingsContainer.visibility == VISIBLE } private fun updateVisibilities( @@ -91,7 +88,7 @@ class FooterActionsView(context: Context?, attrs: AttributeSet?) : LinearLayout( settingsContainer.visibility = if (qsDisabled) GONE else VISIBLE multiUserSwitch.visibility = if (multiUserEnabled) VISIBLE else GONE val isDemo = UserManager.isDeviceInDemoMode(context) - settingsButton.visibility = if (isDemo) INVISIBLE else VISIBLE + settingsContainer.visibility = if (isDemo) INVISIBLE else VISIBLE } fun onUserInfoChanged(picture: Drawable?, isGuestUser: Boolean) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java index bf5467716910a..5e5317d764fe3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java @@ -24,13 +24,15 @@ import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import android.widget.Button; -import com.android.keyguard.AlphaOptimizedImageButton; import com.android.systemui.animation.Interpolators; +import com.android.systemui.statusbar.AlphaOptimizedImageView; -public class SettingsButton extends AlphaOptimizedImageButton { +public class SettingsButton extends AlphaOptimizedImageView { private static final boolean TUNER_ENABLE_AVAILABLE = false; @@ -170,6 +172,12 @@ public class SettingsButton extends AlphaOptimizedImageButton { mAnimator.start(); } + @Override + public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfoInternal(info); + info.setClassName(Button.class.getName()); + } + private final Runnable mLongPressCallback = new Runnable() { @Override public void run() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt index 35d0024b3bf10..642e29b364d34 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt @@ -1,5 +1,6 @@ package com.android.systemui.qs +import android.content.Intent import android.os.Handler import android.os.UserManager import android.provider.Settings @@ -14,6 +15,7 @@ import com.android.internal.logging.MetricsLogger import com.android.internal.logging.UiEventLogger import com.android.internal.logging.testing.FakeMetricsLogger import com.android.systemui.R +import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.classifier.FalsingManagerFake import com.android.systemui.globalactions.GlobalActionsDialogLite import com.android.systemui.plugins.ActivityStarter @@ -136,12 +138,25 @@ class FooterActionsControllerTest : LeakCheckedTest() { .log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS) } + @Test + fun testSettings() { + val captor = ArgumentCaptor.forClass(Intent::class.java) + whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(true) + view.findViewById(R.id.settings_button_container).performClick() + + verify(activityStarter) + .startActivity(capture(captor), anyBoolean(), any()) + + assertThat(captor.value.action).isEqualTo(Settings.ACTION_SETTINGS) + } + @Test fun testSettings_UserNotSetup() { whenever(deviceProvisionedController.isCurrentUserSetup).thenReturn(false) - view.findViewById(R.id.settings_button).performClick() + view.findViewById(R.id.settings_button_container).performClick() // Verify Settings wasn't launched. - verify(activityStarter, Mockito.never()).startActivity(any(), anyBoolean()) + verify(activityStarter, never()) + .startActivity(any(), anyBoolean(), any()) } @Test