Merge "Add accessibility messages to privacy chip on tv." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9028f4992c
@@ -28,4 +28,12 @@
|
|||||||
|
|
||||||
<string name="tv_notification_panel_title">Notifications</string>
|
<string name="tv_notification_panel_title">Notifications</string>
|
||||||
<string name="tv_notification_panel_no_notifications">No 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>
|
</resources>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
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_COLLAPSED = 3;
|
||||||
private static final int STATE_DISAPPEARING = 4;
|
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;
|
private static final int EXPANDED_DURATION_MS = 4000;
|
||||||
public final int mAnimationDurationMs;
|
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 Handler mUiThreadHandler = new Handler(Looper.getMainLooper());
|
||||||
private final Runnable mCollapseRunnable = this::collapseChip;
|
private final Runnable mCollapseRunnable = this::collapseChip;
|
||||||
|
|
||||||
|
private final Runnable mAccessibilityRunnable = this::makeAccessibilityAnnouncement;
|
||||||
|
private final List<PrivacyItem> mItemsBeforeLastAnnouncement = new LinkedList<>();
|
||||||
|
|
||||||
@State
|
@State
|
||||||
private int mState = STATE_NOT_SHOWN;
|
private int mState = STATE_NOT_SHOWN;
|
||||||
|
|
||||||
@@ -169,6 +176,8 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
mPrivacyItems = updatedPrivacyItems;
|
mPrivacyItems = updatedPrivacyItems;
|
||||||
|
|
||||||
|
postAccessibilityAnnouncement();
|
||||||
updateChip();
|
updateChip();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,6 +310,7 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
|
|||||||
mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
|
mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
postAccessibilityAnnouncement();
|
||||||
animateIconAppearance();
|
animateIconAppearance();
|
||||||
mChipDrawable.startInitialFadeIn();
|
mChipDrawable.startInitialFadeIn();
|
||||||
}
|
}
|
||||||
@@ -459,6 +469,83 @@ public class TvOngoingPrivacyChip extends SystemUI implements PrivacyItemControl
|
|||||||
mViewAndWindowAdded = false;
|
mViewAndWindowAdded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Used in debug logs.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user