[Media] Update player's a11y content description based on whether guts

is open or not.

Note: I was hoping that just setting the content description to null if
guts was open would work. When I tried that, it *did* announce "Hide this
control" if I tapped on the player via TalkBack, but it *did not* announce
anything if I used navigation swiping until I was selecting the media
player. So, this code just always sets the description.

Bug: 229574744
Test: manual
Test: MediaControlPanelTest
Change-Id: Ifa69521289a4b7a5cd7a35f092a76827a560e3b1
This commit is contained in:
Caitlin Cassidy
2022-05-05 19:54:30 +00:00
parent 7ee5bcf827
commit b5c0f6c60c
2 changed files with 112 additions and 6 deletions

View File

@@ -448,6 +448,7 @@ public class MediaControlPanel {
bindOutputSwitcherChip(data);
bindGutsMenuForPlayer(data);
bindPlayerContentDescription(data);
bindScrubbingTime(data);
bindActionButtons(data);
@@ -541,12 +542,6 @@ public class MediaControlPanel {
}
private boolean bindSongMetadata(MediaData data) {
// Accessibility label
mMediaViewHolder.getPlayer().setContentDescription(
mContext.getString(
R.string.controls_media_playing_item_description,
data.getSong(), data.getArtist(), data.getApp()));
TextView titleText = mMediaViewHolder.getTitleText();
TextView artistText = mMediaViewHolder.getArtistText();
return mMetadataAnimationHandler.setNext(
@@ -568,6 +563,26 @@ public class MediaControlPanel {
});
}
private void bindPlayerContentDescription(MediaData data) {
if (mMediaViewHolder == null) {
return;
}
CharSequence contentDescription;
if (mMediaViewController.isGutsVisible()) {
contentDescription = mMediaViewHolder.getGutsViewHolder().getGutsText().getText();
} else if (data != null) {
contentDescription = mContext.getString(
R.string.controls_media_playing_item_description,
data.getSong(),
data.getArtist(),
data.getApp());
} else {
contentDescription = null;
}
mMediaViewHolder.getPlayer().setContentDescription(contentDescription);
}
private void bindArtworkAndColors(MediaData data, boolean updateBackground) {
final int reqId = mArtworkNextBindRequestId++;
if (updateBackground) {
@@ -1175,6 +1190,9 @@ public class MediaControlPanel {
mRecommendationViewHolder.marquee(false, mMediaViewController.GUTS_ANIMATION_DURATION);
}
mMediaViewController.closeGuts(immediate);
if (mMediaViewHolder != null) {
bindPlayerContentDescription(mMediaData);
}
}
private void closeGuts() {
@@ -1188,6 +1206,9 @@ public class MediaControlPanel {
mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION);
}
mMediaViewController.openGuts();
if (mMediaViewHolder != null) {
bindPlayerContentDescription(mMediaData);
}
mLogger.logLongPressOpen(mUid, mPackageName, mInstanceId);
}

View File

@@ -1121,6 +1121,91 @@ public class MediaControlPanelTest : SysuiTestCase() {
verify(mediaCarouselController).removePlayer(eq(mediaKey), eq(false), eq(false))
}
@Test
fun player_gutsOpen_contentDescriptionIsForGuts() {
whenever(mediaViewController.isGutsVisible).thenReturn(true)
player.attachPlayer(viewHolder)
val gutsTextString = "gutsText"
whenever(gutsText.text).thenReturn(gutsTextString)
player.bindPlayer(mediaData, KEY)
val descriptionCaptor = ArgumentCaptor.forClass(CharSequence::class.java)
verify(viewHolder.player).contentDescription = descriptionCaptor.capture()
val description = descriptionCaptor.value.toString()
assertThat(description).isEqualTo(gutsTextString)
}
@Test
fun player_gutsClosed_contentDescriptionIsForPlayer() {
whenever(mediaViewController.isGutsVisible).thenReturn(false)
player.attachPlayer(viewHolder)
val app = "appName"
player.bindPlayer(mediaData.copy(app = app), KEY)
val descriptionCaptor = ArgumentCaptor.forClass(CharSequence::class.java)
verify(viewHolder.player).contentDescription = descriptionCaptor.capture()
val description = descriptionCaptor.value.toString()
assertThat(description).contains(mediaData.song!!)
assertThat(description).contains(mediaData.artist!!)
assertThat(description).contains(app)
}
@Test
fun player_gutsChangesFromOpenToClosed_contentDescriptionUpdated() {
// Start out open
whenever(mediaViewController.isGutsVisible).thenReturn(true)
whenever(gutsText.text).thenReturn("gutsText")
player.attachPlayer(viewHolder)
val app = "appName"
player.bindPlayer(mediaData.copy(app = app), KEY)
// Update to closed by long pressing
val captor = ArgumentCaptor.forClass(View.OnLongClickListener::class.java)
verify(viewHolder.player).onLongClickListener = captor.capture()
reset(viewHolder.player)
whenever(mediaViewController.isGutsVisible).thenReturn(false)
captor.value.onLongClick(viewHolder.player)
// Then content description is now the player content description
val descriptionCaptor = ArgumentCaptor.forClass(CharSequence::class.java)
verify(viewHolder.player).contentDescription = descriptionCaptor.capture()
val description = descriptionCaptor.value.toString()
assertThat(description).contains(mediaData.song!!)
assertThat(description).contains(mediaData.artist!!)
assertThat(description).contains(app)
}
@Test
fun player_gutsChangesFromClosedToOpen_contentDescriptionUpdated() {
// Start out closed
whenever(mediaViewController.isGutsVisible).thenReturn(false)
val gutsTextString = "gutsText"
whenever(gutsText.text).thenReturn(gutsTextString)
player.attachPlayer(viewHolder)
player.bindPlayer(mediaData.copy(app = "appName"), KEY)
// Update to open by long pressing
val captor = ArgumentCaptor.forClass(View.OnLongClickListener::class.java)
verify(viewHolder.player).onLongClickListener = captor.capture()
reset(viewHolder.player)
whenever(mediaViewController.isGutsVisible).thenReturn(true)
captor.value.onLongClick(viewHolder.player)
// Then content description is now the guts content description
val descriptionCaptor = ArgumentCaptor.forClass(CharSequence::class.java)
verify(viewHolder.player).contentDescription = descriptionCaptor.capture()
val description = descriptionCaptor.value.toString()
assertThat(description).isEqualTo(gutsTextString)
}
/* ***** END guts tests for the player ***** */
/* ***** Guts tests for the recommendations ***** */