diff options
author | 2021-07-19 08:34:41 +0000 | |
---|---|---|
committer | 2021-07-19 08:34:41 +0000 | |
commit | 9028f4992c7d1a0b41b92dbce7781fa8c1d34da8 (patch) | |
tree | 585e0892df3634d8a2d6674b05fbe2060a42428a | |
parent | e8ad8b7ff455ef77e36018de4e59f53483b336c3 (diff) | |
parent | ba527220f1a73e1490e7b9c147cbd36b6cdfeed1 (diff) |
Merge "Add accessibility messages to privacy chip on tv." into sc-dev
-rw-r--r-- | packages/SystemUI/res/values/strings_tv.xml | 8 | ||||
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java | 87 |
2 files changed, 95 insertions, 0 deletions
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml index b51cb5619f0c..649e80ecc396 100644 --- a/packages/SystemUI/res/values/strings_tv.xml +++ b/packages/SystemUI/res/values/strings_tv.xml @@ -28,4 +28,12 @@ <string name="tv_notification_panel_title">Notifications</string> <string name="tv_notification_panel_no_notifications">No Notifications</string> + + <string name="mic_recording_announcement">Microphone is recording</string> + <string name="camera_recording_announcement">Camera is recording</string> + <string name="mic_and_camera_recording_announcement">Camera and Microphone are recording</string> + <string name="mic_stopped_recording_announcement">Microphone stopped recording</string> + <string name="camera_stopped_recording_announcement">Camera stopped recording</string> + <string name="mic_camera_stopped_recording_announcement">Camera and Microphone stopped recording</string> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java index e4f5cde37f1d..d94cd28c3bc6 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java +++ b/packages/SystemUI/src/com/android/systemui/privacy/television/TvOngoingPrivacyChip.java @@ -53,6 +53,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedList; import java.util.List; import javax.inject.Inject; @@ -88,6 +89,9 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl private static final int STATE_COLLAPSED = 3; private static final int STATE_DISAPPEARING = 4; + // Avoid multiple messages after rapid changes such as starting/stopping both camera and mic. + private static final int ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS = 500; + private static final int EXPANDED_DURATION_MS = 4000; public final int mAnimationDurationMs; @@ -113,6 +117,9 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl private final Handler mUiThreadHandler = new Handler(Looper.getMainLooper()); private final Runnable mCollapseRunnable = this::collapseChip; + private final Runnable mAccessibilityRunnable = this::makeAccessibilityAnnouncement; + private final List<PrivacyItem> mItemsBeforeLastAnnouncement = new LinkedList<>(); + @State private int mState = STATE_NOT_SHOWN; @@ -169,6 +176,8 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl } mPrivacyItems = updatedPrivacyItems; + + postAccessibilityAnnouncement(); updateChip(); } @@ -301,6 +310,7 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener( this); + postAccessibilityAnnouncement(); animateIconAppearance(); mChipDrawable.startInitialFadeIn(); } @@ -460,6 +470,83 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl } /** + * Schedules the accessibility announcement to be made after {@code + * ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS} (if possible). This is so that only one announcement is + * made instead of two separate ones if both the camera and the mic are started/stopped. + */ + private void postAccessibilityAnnouncement() { + mUiThreadHandler.removeCallbacks(mAccessibilityRunnable); + + if (mPrivacyItems.size() == 0) { + // Announce immediately since announcement cannot be made once the chip is gone. + makeAccessibilityAnnouncement(); + } else { + mUiThreadHandler.postDelayed(mAccessibilityRunnable, + ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS); + } + } + + private void makeAccessibilityAnnouncement() { + if (mIndicatorView == null) { + return; + } + + boolean cameraWasRecording = listContainsPrivacyType(mItemsBeforeLastAnnouncement, + PrivacyType.TYPE_CAMERA); + boolean cameraIsRecording = listContainsPrivacyType(mPrivacyItems, + PrivacyType.TYPE_CAMERA); + boolean micWasRecording = listContainsPrivacyType(mItemsBeforeLastAnnouncement, + PrivacyType.TYPE_MICROPHONE); + boolean micIsRecording = listContainsPrivacyType(mPrivacyItems, + PrivacyType.TYPE_MICROPHONE); + + int announcement = 0; + if (!cameraWasRecording && cameraIsRecording && !micWasRecording && micIsRecording) { + // Both started + announcement = R.string.mic_and_camera_recording_announcement; + } else if (cameraWasRecording && !cameraIsRecording && micWasRecording && !micIsRecording) { + // Both stopped + announcement = R.string.mic_camera_stopped_recording_announcement; + } else { + // Did the camera start or stop? + if (cameraWasRecording && !cameraIsRecording) { + announcement = R.string.camera_stopped_recording_announcement; + } else if (!cameraWasRecording && cameraIsRecording) { + announcement = R.string.camera_recording_announcement; + } + + // Announce camera changes now since we might need a second announcement about the mic. + if (announcement != 0) { + mIndicatorView.announceForAccessibility(mContext.getString(announcement)); + announcement = 0; + } + + // Did the mic start or stop? + if (micWasRecording && !micIsRecording) { + announcement = R.string.mic_stopped_recording_announcement; + } else if (!micWasRecording && micIsRecording) { + announcement = R.string.mic_recording_announcement; + } + } + + if (announcement != 0) { + mIndicatorView.announceForAccessibility(mContext.getString(announcement)); + } + + mItemsBeforeLastAnnouncement.clear(); + mItemsBeforeLastAnnouncement.addAll(mPrivacyItems); + } + + private boolean listContainsPrivacyType(List<PrivacyItem> list, PrivacyType privacyType) { + for (PrivacyItem item : list) { + if (item.getPrivacyType() == privacyType) { + return true; + } + } + return false; + } + + /** * Used in debug logs. */ private String stateToString(@State int state) { |