Skip to content

Commit cc94992

Browse files
committed
Selected automatically audio role flag from AccessibilityManager
1 parent 1ed7c54 commit cc94992

File tree

3 files changed

+96
-6
lines changed

3 files changed

+96
-6
lines changed

demos/main/src/main/assets/media.exolist.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,19 @@
725725
}
726726
]
727727
},
728+
{
729+
"name": "Audio description",
730+
"samples": [
731+
{
732+
"name": "DASH unified streaming - Audio description (ENG)",
733+
"uri": "https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel-desc-aud.ism/.mpd"
734+
},
735+
{
736+
"name": "HLS The Morning Show - Change: Season 2",
737+
"uri": "https://play-edge.itunes.apple.com/WebObjects/MZPlayLocal.woa/hls/subscription/playlist.m3u8?cc=CH&svcId=tvs.vds.4021&a=1568297173&isExternal=true&brandId=tvs.sbd.4000&id=518034010&l=en-GB&aec=UHD"
738+
}
739+
]
740+
},
728741
{
729742
"name": "Progressive",
730743
"samples": [

libraries/common/src/main/java/androidx/media3/common/TrackSelectionParameters.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public static class Builder {
9393
// Audio
9494
private ImmutableList<String> preferredAudioLanguages;
9595
private @C.RoleFlags int preferredAudioRoleFlags;
96+
private boolean usePreferredAudioRoleFlagsFromAccessibilityManager;
9697
private int maxAudioChannelCount;
9798
private int maxAudioBitrate;
9899
private ImmutableList<String> preferredAudioMimeTypes;
@@ -128,6 +129,7 @@ public Builder() {
128129
// Audio
129130
preferredAudioLanguages = ImmutableList.of();
130131
preferredAudioRoleFlags = 0;
132+
usePreferredAudioRoleFlagsFromAccessibilityManager = true;
131133
maxAudioChannelCount = Integer.MAX_VALUE;
132134
maxAudioBitrate = Integer.MAX_VALUE;
133135
preferredAudioMimeTypes = ImmutableList.of();
@@ -199,6 +201,9 @@ protected Builder(Bundle bundle) {
199201
preferredAudioLanguages = normalizeLanguageCodes(preferredAudioLanguages1);
200202
preferredAudioRoleFlags =
201203
bundle.getInt(FIELD_PREFERRED_AUDIO_ROLE_FLAGS, DEFAULT.preferredAudioRoleFlags);
204+
usePreferredAudioRoleFlagsFromAccessibilityManager = bundle.getBoolean(
205+
FIELD_USE_PREFERRED_AUDI_ROLE_FLAGS_FROM_ACCESSIBILITY_MANAGER,
206+
DEFAULT.usePreferredAudioRoleFlagsFromAccessibilityManager);
202207
maxAudioChannelCount =
203208
bundle.getInt(FIELD_MAX_AUDIO_CHANNEL_COUNT, DEFAULT.maxAudioChannelCount);
204209
maxAudioBitrate = bundle.getInt(FIELD_MAX_AUDIO_BITRATE, DEFAULT.maxAudioBitrate);
@@ -306,6 +311,7 @@ private void init(@UnknownInitialization Builder this, TrackSelectionParameters
306311
// Audio
307312
preferredAudioLanguages = parameters.preferredAudioLanguages;
308313
preferredAudioRoleFlags = parameters.preferredAudioRoleFlags;
314+
usePreferredAudioRoleFlagsFromAccessibilityManager = parameters.usePreferredAudioRoleFlagsFromAccessibilityManager;
309315
maxAudioChannelCount = parameters.maxAudioChannelCount;
310316
maxAudioBitrate = parameters.maxAudioBitrate;
311317
preferredAudioMimeTypes = parameters.preferredAudioMimeTypes;
@@ -595,6 +601,19 @@ public Builder setPreferredAudioLanguages(String... preferredAudioLanguages) {
595601
@CanIgnoreReturnValue
596602
public Builder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFlags) {
597603
this.preferredAudioRoleFlags = preferredAudioRoleFlags;
604+
this.usePreferredAudioRoleFlagsFromAccessibilityManager = false;
605+
return this;
606+
}
607+
608+
/**
609+
* Set preferred audio role flag from accessibility manager
610+
*
611+
* @return This builder.
612+
*/
613+
@CanIgnoreReturnValue
614+
public Builder setPreferredAudioRoleFlagsFromAccessibilityManager() {
615+
this.usePreferredAudioRoleFlagsFromAccessibilityManager = true;
616+
this.preferredAudioRoleFlags = 0;
598617
return this;
599618
}
600619

@@ -1203,6 +1222,8 @@ public static TrackSelectionParameters getDefaults(Context context) {
12031222
*/
12041223
public final @C.RoleFlags int preferredAudioRoleFlags;
12051224

1225+
public final boolean usePreferredAudioRoleFlagsFromAccessibilityManager;
1226+
12061227
/**
12071228
* Maximum allowed audio channel count. The default value is {@link Integer#MAX_VALUE} (i.e. no
12081229
* constraint).
@@ -1314,6 +1335,7 @@ protected TrackSelectionParameters(Builder builder) {
13141335
// Audio
13151336
this.preferredAudioLanguages = builder.preferredAudioLanguages;
13161337
this.preferredAudioRoleFlags = builder.preferredAudioRoleFlags;
1338+
this.usePreferredAudioRoleFlagsFromAccessibilityManager = builder.usePreferredAudioRoleFlagsFromAccessibilityManager;
13171339
this.maxAudioChannelCount = builder.maxAudioChannelCount;
13181340
this.maxAudioBitrate = builder.maxAudioBitrate;
13191341
this.preferredAudioMimeTypes = builder.preferredAudioMimeTypes;
@@ -1368,6 +1390,8 @@ public boolean equals(@Nullable Object obj) {
13681390
&& preferredVideoRoleFlags == other.preferredVideoRoleFlags
13691391
// Audio
13701392
&& preferredAudioLanguages.equals(other.preferredAudioLanguages)
1393+
&& usePreferredAudioRoleFlagsFromAccessibilityManager
1394+
== other.usePreferredAudioRoleFlagsFromAccessibilityManager
13711395
&& preferredAudioRoleFlags == other.preferredAudioRoleFlags
13721396
&& maxAudioChannelCount == other.maxAudioChannelCount
13731397
&& maxAudioBitrate == other.maxAudioBitrate
@@ -1411,6 +1435,7 @@ public int hashCode() {
14111435
// Audio
14121436
result = 31 * result + preferredAudioLanguages.hashCode();
14131437
result = 31 * result + preferredAudioRoleFlags;
1438+
result = 31 * result + (usePreferredAudioRoleFlagsFromAccessibilityManager ? 1 : 0);
14141439
result = 31 * result + maxAudioChannelCount;
14151440
result = 31 * result + maxAudioBitrate;
14161441
result = 31 * result + preferredAudioMimeTypes.hashCode();
@@ -1469,6 +1494,9 @@ public int hashCode() {
14691494
private static final String
14701495
FIELD_USE_PREFERRED_TEXT_LANGUAGES_AND_ROLE_FLAGS_FROM_CAPTIONING_MANAGER =
14711496
Util.intToStringMaxRadix(34);
1497+
private static final String
1498+
FIELD_USE_PREFERRED_AUDI_ROLE_FLAGS_FROM_ACCESSIBILITY_MANAGER =
1499+
Util.intToStringMaxRadix(35);
14721500

14731501
/**
14741502
* Defines a minimum field ID value for subclasses to use when implementing {@link #toBundle()}
@@ -1508,6 +1536,9 @@ public Bundle toBundle() {
15081536
bundle.putStringArray(
15091537
FIELD_PREFERRED_AUDIO_LANGUAGES, preferredAudioLanguages.toArray(new String[0]));
15101538
bundle.putInt(FIELD_PREFERRED_AUDIO_ROLE_FLAGS, preferredAudioRoleFlags);
1539+
bundle.putBoolean(
1540+
FIELD_USE_PREFERRED_AUDI_ROLE_FLAGS_FROM_ACCESSIBILITY_MANAGER,
1541+
usePreferredAudioRoleFlagsFromAccessibilityManager);
15111542
bundle.putInt(FIELD_MAX_AUDIO_CHANNEL_COUNT, maxAudioChannelCount);
15121543
bundle.putInt(FIELD_MAX_AUDIO_BITRATE, maxAudioBitrate);
15131544
bundle.putStringArray(

libraries/exoplayer/src/main/java/androidx/media3/exoplayer/trackselection/DefaultTrackSelector.java

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
package androidx.media3.exoplayer.trackselection;
1717

1818
import static android.os.Build.VERSION.SDK_INT;
19+
import static androidx.media3.common.C.ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND;
20+
import static androidx.media3.common.C.ROLE_FLAG_DESCRIBES_VIDEO;
1921
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_DISABLED;
2022
import static androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_REQUIRED;
2123
import static androidx.media3.common.util.Assertions.checkNotNull;
@@ -34,13 +36,15 @@
3436
import android.media.AudioFormat;
3537
import android.media.AudioManager;
3638
import android.media.Spatializer;
39+
import android.os.Build;
3740
import android.os.Bundle;
3841
import android.os.Handler;
3942
import android.os.Looper;
4043
import android.text.TextUtils;
4144
import android.util.Pair;
4245
import android.util.SparseArray;
4346
import android.util.SparseBooleanArray;
47+
import android.view.accessibility.AccessibilityManager;
4448
import android.view.accessibility.CaptioningManager;
4549
import androidx.annotation.GuardedBy;
4650
import androidx.annotation.IntDef;
@@ -402,6 +406,14 @@ public ParametersBuilder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAu
402406
return this;
403407
}
404408

409+
@SuppressWarnings("deprecation") // Intentionally returning deprecated type
410+
@CanIgnoreReturnValue
411+
@Override
412+
public ParametersBuilder setPreferredAudioRoleFlagsFromAccessibilityManager() {
413+
delegate.setPreferredAudioRoleFlagsFromAccessibilityManager();
414+
return this;
415+
}
416+
405417
@SuppressWarnings("deprecation") // Intentionally returning deprecated type
406418
@CanIgnoreReturnValue
407419
@Override
@@ -1225,6 +1237,13 @@ public Builder setPreferredAudioRoleFlags(@C.RoleFlags int preferredAudioRoleFla
12251237
return this;
12261238
}
12271239

1240+
@CanIgnoreReturnValue
1241+
@Override
1242+
public Builder setPreferredAudioRoleFlagsFromAccessibilityManager() {
1243+
super.setPreferredAudioRoleFlagsFromAccessibilityManager();
1244+
return this;
1245+
}
1246+
12281247
@CanIgnoreReturnValue
12291248
@Override
12301249
public Builder setMaxAudioChannelCount(int maxAudioChannelCount) {
@@ -2850,7 +2869,13 @@ protected Pair<ExoTrackSelection.Definition, Integer> selectAudioTrack(
28502869
break;
28512870
}
28522871
}
2872+
2873+
@RoleFlags int preferredRoleFlagFromAccessibilityManager = 0;
2874+
if (SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
2875+
preferredRoleFlagFromAccessibilityManager = getPreferredRoleFlagFromAccessibilityManager(context);
2876+
}
28532877
boolean hasVideoRendererWithMappedTracksFinal = hasVideoRendererWithMappedTracks;
2878+
@RoleFlags int preferredRoleFlagFromAccessibilityManagerFinal = preferredRoleFlagFromAccessibilityManager;
28542879
return selectTracksForType(
28552880
C.TRACK_TYPE_AUDIO,
28562881
mappedTrackInfo,
@@ -2863,7 +2888,8 @@ protected Pair<ExoTrackSelection.Definition, Integer> selectAudioTrack(
28632888
support,
28642889
hasVideoRendererWithMappedTracksFinal,
28652890
format -> isAudioFormatWithinAudioChannelCountConstraints(format, params),
2866-
rendererMixedMimeTypeAdaptationSupports[rendererIndex]),
2891+
rendererMixedMimeTypeAdaptationSupports[rendererIndex],
2892+
preferredRoleFlagFromAccessibilityManagerFinal),
28672893
AudioTrackInfo::compareSelections);
28682894
}
28692895

@@ -3530,6 +3556,21 @@ private static String getPreferredLanguageFromCaptioningManager(@Nullable Contex
35303556
return Util.getLocaleLanguageTag(preferredLocale);
35313557
}
35323558

3559+
@RequiresApi(api = Build.VERSION_CODES.TIRAMISU)
3560+
private static @RoleFlags int getPreferredRoleFlagFromAccessibilityManager(
3561+
@Nullable Context context) {
3562+
if (context == null) {
3563+
return 0;
3564+
}
3565+
AccessibilityManager accessibilityManager = (AccessibilityManager) context.getSystemService(
3566+
Context.ACCESSIBILITY_SERVICE);
3567+
if (accessibilityManager != null) {
3568+
return accessibilityManager.isAudioDescriptionRequested() ? ROLE_FLAG_DESCRIBES_VIDEO
3569+
| ROLE_FLAG_DESCRIBES_MUSIC_AND_SOUND : 0;
3570+
}
3571+
return 0;
3572+
}
3573+
35333574
/** Base class for track selection information of a {@link Format}. */
35343575
private abstract static class TrackInfo<T extends TrackInfo<T>> {
35353576
/** Factory for {@link TrackInfo} implementations for a given {@link TrackGroup}. */
@@ -3833,7 +3874,8 @@ public static ImmutableList<AudioTrackInfo> createForTrackGroup(
38333874
@Capabilities int[] formatSupport,
38343875
boolean hasMappedVideoTracks,
38353876
Predicate<Format> withinAudioChannelCountConstraints,
3836-
@AdaptiveSupport int mixedMimeTypeAdaptationSupport) {
3877+
@AdaptiveSupport int mixedMimeTypeAdaptationSupport,
3878+
@RoleFlags int preferredRoleFlagFromAccessibilityManager) {
38373879
ImmutableList.Builder<AudioTrackInfo> listBuilder = ImmutableList.builder();
38383880
for (int i = 0; i < trackGroup.length; i++) {
38393881
listBuilder.add(
@@ -3845,7 +3887,8 @@ public static ImmutableList<AudioTrackInfo> createForTrackGroup(
38453887
formatSupport[i],
38463888
hasMappedVideoTracks,
38473889
withinAudioChannelCountConstraints,
3848-
mixedMimeTypeAdaptationSupport));
3890+
mixedMimeTypeAdaptationSupport,
3891+
preferredRoleFlagFromAccessibilityManager));
38493892
}
38503893
return listBuilder.build();
38513894
}
@@ -3879,7 +3922,8 @@ public AudioTrackInfo(
38793922
@Capabilities int formatSupport,
38803923
boolean hasMappedVideoTracks,
38813924
Predicate<Format> withinAudioChannelCountConstraints,
3882-
@AdaptiveSupport int mixedMimeTypeAdaptationSupport) {
3925+
@AdaptiveSupport int mixedMimeTypeAdaptationSupport,
3926+
@RoleFlags int preferredRoleFlagFromAccessibilityManager) {
38833927
super(rendererIndex, trackGroup, trackIndex);
38843928
this.parameters = parameters;
38853929
@SuppressLint("WrongConstant")
@@ -3910,8 +3954,10 @@ public AudioTrackInfo(
39103954
}
39113955
preferredLanguageIndex = bestLanguageIndex;
39123956
preferredLanguageScore = bestLanguageScore;
3913-
preferredRoleFlagsScore =
3914-
getRoleFlagMatchScore(format.roleFlags, parameters.preferredAudioRoleFlags);
3957+
@RoleFlags int preferredAudioRoleFlags =
3958+
preferredRoleFlagFromAccessibilityManager == 0 ? parameters.preferredAudioRoleFlags
3959+
: preferredRoleFlagFromAccessibilityManager;
3960+
preferredRoleFlagsScore = getRoleFlagMatchScore(format.roleFlags, preferredAudioRoleFlags);
39153961
hasMainOrNoRoleFlag = format.roleFlags == 0 || (format.roleFlags & C.ROLE_FLAG_MAIN) != 0;
39163962
isDefaultSelectionFlag = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0;
39173963
isObjectBasedAudio = isObjectBasedAudio(format);

0 commit comments

Comments
 (0)