From e4201e8af4f8a45555c247f7ba66f7c5a6191d7b Mon Sep 17 00:00:00 2001 From: Jigar Thakkar Date: Thu, 20 Mar 2025 19:19:32 +0000 Subject: [PATCH] Fix accessibility labels for private space animations The change adds appropriate content descriptions to animations used within the private space setup flow based on the state of the animation. Bug: 403398693 Test: manual Change-Id: I6ac7a5d206083b651b48f9bcf28e3639bdce60b4 --- .../PrivateSpaceAccessibilityUtils.java | 66 +++++++++++++++++++ .../privatespace/PrivateSpaceEducation.java | 4 ++ .../PrivateSpaceSetLockFragment.java | 4 ++ .../privatespace/SetupSuccessFragment.java | 4 ++ 4 files changed, 78 insertions(+) create mode 100644 src/com/android/settings/privatespace/PrivateSpaceAccessibilityUtils.java diff --git a/src/com/android/settings/privatespace/PrivateSpaceAccessibilityUtils.java b/src/com/android/settings/privatespace/PrivateSpaceAccessibilityUtils.java new file mode 100644 index 00000000000..c9c976dd791 --- /dev/null +++ b/src/com/android/settings/privatespace/PrivateSpaceAccessibilityUtils.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.privatespace; + +import static com.android.settingslib.widget.preference.illustration.R.string.settingslib_action_label_pause; +import static com.android.settingslib.widget.preference.illustration.R.string.settingslib_action_label_resume; +import static com.android.settingslib.widget.preference.illustration.R.string.settingslib_illustration_content_description; + +import android.content.Context; +import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; + +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; + +import com.airbnb.lottie.LottieAnimationView; + +public class PrivateSpaceAccessibilityUtils { + + static void updateAccessibilityActionForAnimation(Context context, + LottieAnimationView animationView, boolean isAnimationPlaying) { + animationView.setContentDescription( + context.getString(settingslib_illustration_content_description)); + ViewCompat.setAccessibilityDelegate(animationView, new AccessibilityDelegateCompat() { + @Override + public void onInitializeAccessibilityNodeInfo( + View host, AccessibilityNodeInfoCompat info) { + super.onInitializeAccessibilityNodeInfo(host, info); + // Clearing the class name to ensure the animation is not called out as "button" + // inside the TalkBack flows + info.setClassName(""); + info.removeAction( + AccessibilityNodeInfoCompat.AccessibilityActionCompat.ACTION_CLICK); + + final AccessibilityNodeInfoCompat.AccessibilityActionCompat clickAction = + new AccessibilityNodeInfoCompat.AccessibilityActionCompat( + AccessibilityNodeInfo.ACTION_CLICK, + getActionLabelForAnimation(context, isAnimationPlaying)); + info.addAction(clickAction); + } + }); + } + + private static String getActionLabelForAnimation(Context context, boolean isAnimationPlaying) { + if (isAnimationPlaying) { + return context.getString(settingslib_action_label_pause); + } else { + return context.getString(settingslib_action_label_resume); + } + } +} diff --git a/src/com/android/settings/privatespace/PrivateSpaceEducation.java b/src/com/android/settings/privatespace/PrivateSpaceEducation.java index 093d7a5eed2..2e157780f24 100644 --- a/src/com/android/settings/privatespace/PrivateSpaceEducation.java +++ b/src/com/android/settings/privatespace/PrivateSpaceEducation.java @@ -76,6 +76,8 @@ public class PrivateSpaceEducation extends InstrumentedFragment { LottieAnimationView lottieAnimationView = rootView.findViewById(R.id.lottie_animation); LottieColorUtils.applyDynamicColors(getContext(), lottieAnimationView); lottieAnimationView.setOnClickListener(v -> handleAnimationClick(lottieAnimationView)); + PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), + lottieAnimationView, mIsAnimationPlaying); TextView infoTextView = rootView.findViewById(R.id.learn_more); Pattern pattern = Pattern.compile(infoTextView.getText().toString()); @@ -121,5 +123,7 @@ public class PrivateSpaceEducation extends InstrumentedFragment { lottieAnimationView.playAnimation(); } mIsAnimationPlaying = !mIsAnimationPlaying; + PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), + lottieAnimationView, mIsAnimationPlaying); } } diff --git a/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java b/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java index 47cf3baa76c..701f43b00ef 100644 --- a/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java +++ b/src/com/android/settings/privatespace/PrivateSpaceSetLockFragment.java @@ -94,6 +94,8 @@ public class PrivateSpaceSetLockFragment extends InstrumentedFragment { LottieAnimationView lottieAnimationView = rootView.findViewById(R.id.lottie_animation); LottieColorUtils.applyDynamicColors(getContext(), lottieAnimationView); lottieAnimationView.setOnClickListener(v -> handleAnimationClick(lottieAnimationView)); + PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), + lottieAnimationView, mIsAnimationPlaying); return rootView; } @@ -141,5 +143,7 @@ public class PrivateSpaceSetLockFragment extends InstrumentedFragment { lottieAnimationView.playAnimation(); } mIsAnimationPlaying = !mIsAnimationPlaying; + PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), + lottieAnimationView, mIsAnimationPlaying); } } diff --git a/src/com/android/settings/privatespace/SetupSuccessFragment.java b/src/com/android/settings/privatespace/SetupSuccessFragment.java index 538912e1c65..1b60d924490 100644 --- a/src/com/android/settings/privatespace/SetupSuccessFragment.java +++ b/src/com/android/settings/privatespace/SetupSuccessFragment.java @@ -83,6 +83,8 @@ public class SetupSuccessFragment extends InstrumentedFragment { LottieAnimationView lottieAnimationView = rootView.findViewById(R.id.lottie_animation); LottieColorUtils.applyDynamicColors(getContext(), lottieAnimationView); lottieAnimationView.setOnClickListener(v -> handleAnimationClick(lottieAnimationView)); + PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), + lottieAnimationView, mIsAnimationPlaying); return rootView; } @@ -152,5 +154,7 @@ public class SetupSuccessFragment extends InstrumentedFragment { lottieAnimationView.playAnimation(); } mIsAnimationPlaying = !mIsAnimationPlaying; + PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), + lottieAnimationView, mIsAnimationPlaying); } }