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

Commit 7099ff7a authored by Alex Shabalin's avatar Alex Shabalin
Browse files

Prevent automatic Talkback "Detected text" announcement.

That announcement was pronounced because the focusable element
`id/device_container` had all its visible elements `id/title`
and `id/title_icon` marked with `importantForAccessibility=no`, so the
Talkback fell back to it's AI features to describe the element content.

1. Removed `importantForAccessibility="no"` by default from the title
element.
2. Set `focusable="true"` for the device container and
`focusable="false"` for title and subtitle to make screen reader
announce the device container as one entity as per
https://developer.android.com/guide/topics/ui/accessibility/principles#content-groups
3. When the seekbar is visible hide the rest of the content from the
accessibility tree with `updateContainerContentA11yImportance` method.

Flag: EXEMPT bugfix
Bug: b/374862206
Fix: b/374862206
Test: atest SystemUiRoboTests:MediaOutputAdapterLegacyTest,
    accessibility with Talkback.
Change-Id: Ifb3613af91ffb71e901e45903328b245e2a4b414
parent ca8ecbeb
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -268,6 +268,10 @@ public class MediaOutputAdapterLegacyTest extends SysuiTestCase {

        assertThat(mViewHolder.mSeekBar.getContentDescription()).isNotNull();
        assertThat(mViewHolder.mContainerLayout.isFocusable()).isFalse();
        assertThat(mViewHolder.mContainerLayout.getImportantForAccessibility()).isEqualTo(
                View.IMPORTANT_FOR_ACCESSIBILITY_NO);
        assertThat(mViewHolder.mTextContent.getImportantForAccessibility()).isEqualTo(
                View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
    }

    @Test
@@ -511,6 +515,11 @@ public class MediaOutputAdapterLegacyTest extends SysuiTestCase {
        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
        assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mContainerLayout.isFocusable()).isTrue();
        assertThat(mViewHolder.mContainerLayout.getImportantForAccessibility()).isEqualTo(
                View.IMPORTANT_FOR_ACCESSIBILITY_YES);
        assertThat(mViewHolder.mTextContent.getImportantForAccessibility()).isEqualTo(
                View.IMPORTANT_FOR_ACCESSIBILITY_YES);
        assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
        assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+4 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingHorizontal="@dimen/media_output_dialog_margin_horizontal"
    android:focusable="true"
    android:baselineAligned="false">
    <FrameLayout
        android:layout_weight="1"
@@ -77,6 +78,7 @@
        </FrameLayout>

        <LinearLayout
            android:id="@+id/text_content"
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_gravity="center_vertical|start"
@@ -86,7 +88,7 @@
            android:layout_marginStart="72dp">
            <TextView
                android:id="@+id/title"
                android:importantForAccessibility="no"
                android:focusable="false"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
@@ -96,6 +98,7 @@
                android:textSize="16sp"/>
            <TextView
                android:id="@+id/subtitle"
                android:focusable="false"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:marqueeRepeatLimit="marquee_forever"
+18 −13
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ public class MediaOutputAdapterLegacy extends MediaOutputAdapterBase {
        final ViewGroup mContainerLayout;
        final FrameLayout mItemLayout;
        final FrameLayout mIconAreaLayout;
        final ViewGroup mTextContent;
        final TextView mTitleText;
        final TextView mSubTitleText;
        final TextView mVolumeValueText;
@@ -152,6 +153,7 @@ public class MediaOutputAdapterLegacy extends MediaOutputAdapterBase {
            super(view, context);
            mContainerLayout = view.requireViewById(R.id.device_container);
            mItemLayout = view.requireViewById(R.id.item_layout);
            mTextContent = view.requireViewById(R.id.text_content);
            mTitleText = view.requireViewById(R.id.title);
            mSubTitleText = view.requireViewById(R.id.subtitle);
            mTitleIcon = view.requireViewById(R.id.title_icon);
@@ -180,7 +182,6 @@ public class MediaOutputAdapterLegacy extends MediaOutputAdapterBase {
            mEndClickIcon.setVisibility(View.GONE);
            mEndTouchArea.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
            mContainerLayout.setOnClickListener(null);
            mContainerLayout.setContentDescription(null);
            mTitleText.setTextColor(mController.getColorItemContent());
            mSubTitleText.setTextColor(mController.getColorItemContent());
            mVolumeValueText.setTextColor(mController.getColorItemContent());
@@ -188,7 +189,7 @@ public class MediaOutputAdapterLegacy extends MediaOutputAdapterBase {
            updateIconAreaClickListener(null);
            mSeekBar.setProgressTintList(
                    ColorStateList.valueOf(mController.getColorSeekbarProgress()));
            enableFocusPropertyForView(mContainerLayout);
            updateContainerContentA11yImportance(true  /* isImportant */);
            renderItem(mediaItem, position);
        }

@@ -256,10 +257,10 @@ public class MediaOutputAdapterLegacy extends MediaOutputAdapterBase {
            mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
            if (showSeekBar) {
                initSeekbar(device, isCurrentSeekbarInvisible);
                disableFocusPropertyForView(mContainerLayout);
                updateContainerContentA11yImportance(false /* isImportant */);
                mSeekBar.setContentDescription(contentDescription);
            } else {
                enableFocusPropertyForView(mContainerLayout);
                updateContainerContentA11yImportance(true /* isImportant */);
            }
        }

@@ -268,18 +269,22 @@ public class MediaOutputAdapterLegacy extends MediaOutputAdapterBase {
            boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;
            mSeekBar.setVisibility(View.VISIBLE);
            initGroupSeekbar(isCurrentSeekbarInvisible);
            disableFocusPropertyForView(mContainerLayout);
            updateContainerContentA11yImportance(false /* isImportant */);
            mSeekBar.setContentDescription(contentDescription);
        }

        private void disableFocusPropertyForView(View view) {
            view.setFocusable(false);
            view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
        }

        private void enableFocusPropertyForView(View view) {
            view.setFocusable(true);
            view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
        /**
         * Sets the a11y importance for the device container and it's text content. Making the
         * container not important for a11y is required when the seekbar is visible.
         */
        private void updateContainerContentA11yImportance(boolean isImportant) {
            mContainerLayout.setFocusable(isImportant);
            mContainerLayout.setImportantForAccessibility(
                    isImportant ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
                            : View.IMPORTANT_FOR_ACCESSIBILITY_NO);
            mTextContent.setImportantForAccessibility(
                    isImportant ? View.IMPORTANT_FOR_ACCESSIBILITY_YES
                            : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
        }

        void updateSubtitle(@Nullable String subtitle) {