Add APIs to add and to remove listeners for
AudioDescriptionStateChange.
Test: atest AccessibilityManagerTest
Bug: 160823970
Change-Id: Ifd5cc3366b4d19b8be20c3fa1ef83437b422bf4b
diff --git a/core/api/current.txt b/core/api/current.txt
index 93f1003..7f93f05 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -51145,6 +51145,7 @@
method public void addAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
method public boolean addAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
method public void addAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, @Nullable android.os.Handler);
+ method public void addAudioDescriptionByDefaultStateChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.view.accessibility.AccessibilityManager.AudioDescriptionByDefaultStateChangeListener);
method public boolean addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
method public void addTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, @Nullable android.os.Handler);
method @ColorInt public int getAccessibilityFocusColor();
@@ -51161,6 +51162,7 @@
method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
method public boolean removeAccessibilityServicesStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
method public boolean removeAccessibilityStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
+ method public boolean removeAudioDescriptionByDefaultStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.AudioDescriptionByDefaultStateChangeListener);
method public boolean removeTouchExplorationStateChangeListener(@NonNull android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
field public static final int FLAG_CONTENT_CONTROLS = 4; // 0x4
@@ -51176,6 +51178,10 @@
method public void onAccessibilityStateChanged(boolean);
}
+ public static interface AccessibilityManager.AudioDescriptionByDefaultStateChangeListener {
+ method public void onAudioDescriptionByDefaultStateChanged(boolean);
+ }
+
public static interface AccessibilityManager.TouchExplorationStateChangeListener {
method public void onTouchExplorationStateChanged(boolean);
}
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index dc61727..078b767 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -273,6 +273,9 @@
private final ArrayMap<AccessibilityServicesStateChangeListener, Executor>
mServicesStateChangeListeners = new ArrayMap<>();
+ private final ArrayMap<AudioDescriptionByDefaultStateChangeListener, Executor>
+ mAudioDescriptionByDefaultStateChangeListeners = new ArrayMap<>();
+
/**
* Map from a view's accessibility id to the list of request preparers set for that view
*/
@@ -353,6 +356,21 @@
}
/**
+ * Listener for the audio description by default state. To listen for
+ * changes to the audio description by default state on the device,
+ * implement this interface and register it with the system by calling
+ * {@link #addAudioDescriptionByDefaultStateChangeListener}.
+ */
+ public interface AudioDescriptionByDefaultStateChangeListener {
+ /**
+ * Called when the audio description enabled state changes.
+ *
+ * @param enabled Whether audio description by default is enabled.
+ */
+ void onAudioDescriptionByDefaultStateChanged(boolean enabled);
+ }
+
+ /**
* Policy to inject behavior into the accessibility manager.
*
* @hide
@@ -1159,6 +1177,35 @@
}
/**
+ * Registers a {@link AudioDescriptionByDefaultStateChangeListener}
+ * for changes in the audio description by default state of the system.
+ * The value could be read via {@link #isAudioDescriptionRequested}.
+ *
+ * @param executor The executor on which the listener should be called back.
+ * @param listener The listener.
+ */
+ public void addAudioDescriptionByDefaultStateChangeListener(
+ @NonNull Executor executor,
+ @NonNull AudioDescriptionByDefaultStateChangeListener listener) {
+ synchronized (mLock) {
+ mAudioDescriptionByDefaultStateChangeListeners.put(listener, executor);
+ }
+ }
+
+ /**
+ * Unregisters a {@link AudioDescriptionByDefaultStateChangeListener}.
+ *
+ * @param listener The listener.
+ * @return True if listener was previously registered.
+ */
+ public boolean removeAudioDescriptionByDefaultStateChangeListener(
+ @NonNull AudioDescriptionByDefaultStateChangeListener listener) {
+ synchronized (mLock) {
+ return (mAudioDescriptionByDefaultStateChangeListeners.remove(listener) != null);
+ }
+ }
+
+ /**
* Sets the {@link AccessibilityPolicy} controlling this manager.
*
* @param policy The policy.
@@ -1303,7 +1350,7 @@
final boolean wasEnabled = isEnabled();
final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled;
final boolean wasHighTextContrastEnabled = mIsHighTextContrastEnabled;
-
+ final boolean wasAudioDescriptionByDefaultRequested = mIsAudioDescriptionByDefaultRequested;
// Ensure listeners get current state from isZzzEnabled() calls.
mIsEnabled = enabled;
@@ -1323,6 +1370,11 @@
notifyHighTextContrastStateChanged();
}
+ if (wasAudioDescriptionByDefaultRequested
+ != audioDescriptionEnabled) {
+ notifyAudioDescriptionbyDefaultStateChanged();
+ }
+
updateAccessibilityTracingState(stateFlags);
}
@@ -1688,15 +1740,20 @@
/**
* Determines if users want to select sound track with audio description by default.
- *
+ * <p>
* Audio description, also referred to as a video description, described video, or
* more precisely called a visual description, is a form of narration used to provide
* information surrounding key visual elements in a media work for the benefit of
* blind and visually impaired consumers.
- *
+ * </p>
+ * <p>
* The method provides the preference value to content provider apps to select the
* default sound track during playing a video or movie.
- *
+ * </p>
+ * <p>
+ * Add listener to detect the state change via
+ * {@link #addAudioDescriptionByDefaultStateChangeListener}
+ * </p>
* @return {@code true} if the audio description is enabled, {@code false} otherwise.
*/
public boolean isAudioDescriptionRequested() {
@@ -1804,6 +1861,29 @@
}
/**
+ * Notifies the registered {@link AudioDescriptionStateChangeListener}s.
+ */
+ private void notifyAudioDescriptionbyDefaultStateChanged() {
+ final boolean isAudioDescriptionByDefaultRequested;
+ final ArrayMap<AudioDescriptionByDefaultStateChangeListener, Executor> listeners;
+ synchronized (mLock) {
+ if (mAudioDescriptionByDefaultStateChangeListeners.isEmpty()) {
+ return;
+ }
+ isAudioDescriptionByDefaultRequested = mIsAudioDescriptionByDefaultRequested;
+ listeners = new ArrayMap<>(mAudioDescriptionByDefaultStateChangeListeners);
+ }
+
+ final int numListeners = listeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ final AudioDescriptionByDefaultStateChangeListener listener = listeners.keyAt(i);
+ listeners.valueAt(i).execute(() ->
+ listener.onAudioDescriptionByDefaultStateChanged(
+ isAudioDescriptionByDefaultRequested));
+ }
+ }
+
+ /**
* Update mAccessibilityTracingState.
*/
private void updateAccessibilityTracingState(int stateFlag) {