Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -21197,6 +21197,7 @@ package android.media { method @NonNull public android.media.AudioTrack.Builder setAudioAttributes(@NonNull android.media.AudioAttributes) throws java.lang.IllegalArgumentException; method @NonNull public android.media.AudioTrack.Builder setAudioFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException; method @NonNull public android.media.AudioTrack.Builder setBufferSizeInBytes(@IntRange(from=0) int) throws java.lang.IllegalArgumentException; method @NonNull public android.media.AudioTrack.Builder setContext(@NonNull android.content.Context); method @NonNull public android.media.AudioTrack.Builder setEncapsulationMode(int); method @NonNull public android.media.AudioTrack.Builder setOffloadedPlayback(boolean); method @NonNull public android.media.AudioTrack.Builder setPerformanceMode(int); core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -3043,6 +3043,7 @@ package android.companion.virtual { field public static final int LOCK_STATE_DEFAULT = 0; // 0x0 field public static final int NAVIGATION_POLICY_DEFAULT_ALLOWED = 0; // 0x0 field public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; // 0x1 field public static final int POLICY_TYPE_AUDIO = 1; // 0x1 field public static final int POLICY_TYPE_SENSORS = 0; // 0x0 field public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1; // 0x1 } core/java/android/companion/virtual/VirtualDeviceManager.java +38 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.companion.virtual; import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; Loading Loading @@ -254,6 +256,42 @@ public final class VirtualDeviceManager { } } /** * Returns device-specific audio session id for audio playback. * * @param deviceId - id of the virtual audio device * @return Device specific session id to be used for audio playback (see * {@link android.media.AudioManager.generateAudioSessionId}) if virtual device has * {@link VirtualDeviceParams.POLICY_TYPE_AUDIO} set to * {@link VirtualDeviceParams.DEVICE_POLICY_CUSTOM} and Virtual Audio Device * is configured in context-aware mode. * Otherwise {@link AUDIO_SESSION_ID_GENERATE} constant is returned. * @hide */ public int getAudioPlaybackSessionId(int deviceId) { //TODO - Return session id rerouted to VirtualAudioDevice if the VirtualAudioDevice //is configured to operate in context-aware mode. return AUDIO_SESSION_ID_GENERATE; } /** * Returns device-specific audio session id for audio recording. * * @param deviceId - id of the virtual audio device * @return Device specific session id to be used for audio recording (see * {@link android.media.AudioManager.generateAudioSessionId}) if virtual device has * {@link VirtualDeviceParams.POLICY_TYPE_AUDIO} set to * {@link VirtualDeviceParams.DEVICE_POLICY_CUSTOM} and Virtual Audio Device * is configured in context-aware mode. * Otherwise {@link AUDIO_SESSION_ID_GENERATE} constant is returned. * @hide */ public int getAudioRecordingSessionId(int deviceId) { //TODO - Return session id corresponding to VirtualAudioDevice injection if the // VirtualAudioDevice is configured to operate in context-aware mode. return AUDIO_SESSION_ID_GENERATE; } /** * A virtual device has its own virtual display, audio output, microphone, and camera etc. The * creator of a virtual device can take the output from the virtual display and stream it over Loading core/java/android/companion/virtual/VirtualDeviceParams.java +16 −1 Original line number Diff line number Diff line Loading @@ -129,7 +129,7 @@ public final class VirtualDeviceParams implements Parcelable { * a given policy type. * @hide */ @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS}) @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO}) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface PolicyType {} Loading @@ -147,6 +147,21 @@ public final class VirtualDeviceParams implements Parcelable { */ public static final int POLICY_TYPE_SENSORS = 0; /** * Tells the audio framework whether to configure the players ({@link android.media.AudioTrack}, * {@link android.media.MediaPlayer}, {@link android.media.SoundPool} and recorders * {@link android.media.AudioRecord}) to use specific session ids re-routed to * VirtualAudioDevice. * * <ul> * <li>{@link #DEVICE_POLICY_DEFAULT}: fall back to default session id handling. * <li>{@link #DEVICE_POLICY_CUSTOM}: audio framework will assign device specific session * ids to players and recorders constructed within device context. The session ids are * used to re-route corresponding audio streams to VirtualAudioDevice. * <ul/> */ public static final int POLICY_TYPE_AUDIO = 1; /** @hide */ @IntDef(flag = true, prefix = "RECENTS_POLICY_", value = {RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS}) Loading media/java/android/media/AudioTrack.java +68 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,11 @@ package android.media; import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT; import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT; import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO; import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; import android.annotation.CallbackExecutor; import android.annotation.FloatRange; import android.annotation.IntDef; Loading @@ -25,7 +30,9 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.companion.virtual.VirtualDeviceManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioMixingRule; import android.media.audiopolicy.AudioPolicy; Loading Loading @@ -545,7 +552,7 @@ public class AudioTrack extends PlayerBase /** * Audio session ID */ private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; private int mSessionId = AUDIO_SESSION_ID_GENERATE; /** * HW_AV_SYNC track AV Sync Header */ Loading Loading @@ -645,7 +652,7 @@ public class AudioTrack extends PlayerBase int bufferSizeInBytes, int mode) throws IllegalArgumentException { this(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE); bufferSizeInBytes, mode, AUDIO_SESSION_ID_GENERATE); } /** Loading Loading @@ -749,12 +756,12 @@ public class AudioTrack extends PlayerBase public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId) throws IllegalArgumentException { this(attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/, ENCAPSULATION_MODE_NONE, null /* tunerConfiguration */); this(null /* context */, attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/, ENCAPSULATION_MODE_NONE, null /* tunerConfiguration */); } private AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId, boolean offload, int encapsulationMode, private AudioTrack(@Nullable Context context, AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId, boolean offload, int encapsulationMode, @Nullable TunerConfiguration tunerConfiguration) throws IllegalArgumentException { super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_JAM_AUDIOTRACK); Loading Loading @@ -817,7 +824,13 @@ public class AudioTrack extends PlayerBase int[] sampleRate = new int[] {mSampleRate}; int[] session = new int[1]; if (sessionId == AUDIO_SESSION_ID_GENERATE) { // If there's no specific session id requested, try to get one from context. session[0] = getSessionIdForContext(context); } else { session[0] = sessionId; } // native initialization int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes, sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat, Loading Loading @@ -1028,11 +1041,12 @@ public class AudioTrack extends PlayerBase * <br>Offload is false by default. */ public static class Builder { private Context mContext; private AudioAttributes mAttributes; private AudioFormat mFormat; private int mBufferSizeInBytes; private int mEncapsulationMode = ENCAPSULATION_MODE_NONE; private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; private int mSessionId = AUDIO_SESSION_ID_GENERATE; private int mMode = MODE_STREAM; private int mPerformanceMode = PERFORMANCE_MODE_NONE; private boolean mOffload = false; Loading @@ -1045,6 +1059,19 @@ public class AudioTrack extends PlayerBase public Builder() { } /** * Sets the context the track belongs to. This context will be used to pull information, * such as {@link android.content.AttributionSource} and device specific audio session ids, * which will be associated with the {@link AudioTrack}. However, the context itself will * not be retained by the {@link AudioTrack}. * @param context a non-null {@link Context} instance * @return the same Builder instance. */ public @NonNull Builder setContext(@NonNull Context context) { mContext = Objects.requireNonNull(context); return this; } /** * Sets the {@link AudioAttributes}. * @param attributes a non-null {@link AudioAttributes} instance that describes the audio Loading Loading @@ -1152,6 +1179,10 @@ public class AudioTrack extends PlayerBase /** * Sets the session ID the {@link AudioTrack} will be attached to. * * Note, that if there's a device specific session id asociated with the context, explicitly * setting a session id using this method will override it * (see {@link Builder#setContext(Context)}). * @param sessionId a strictly positive ID number retrieved from another * <code>AudioTrack</code> via {@link AudioTrack#getAudioSessionId()} or allocated by * {@link AudioManager} via {@link AudioManager#generateAudioSessionId()}, or Loading @@ -1161,7 +1192,7 @@ public class AudioTrack extends PlayerBase */ public @NonNull Builder setSessionId(@IntRange(from = 1) int sessionId) throws IllegalArgumentException { if ((sessionId != AudioManager.AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) { if ((sessionId != AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) { throw new IllegalArgumentException("Invalid audio session ID " + sessionId); } mSessionId = sessionId; Loading Loading @@ -1371,8 +1402,8 @@ public class AudioTrack extends PlayerBase try { final AudioTrack track = new AudioTrack( mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload, mEncapsulationMode, mTunerConfiguration); mContext, mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload, mEncapsulationMode, mTunerConfiguration); if (track.getState() == STATE_UNINITIALIZED) { // release is not necessary throw new UnsupportedOperationException("Cannot create AudioTrack"); Loading @@ -1384,6 +1415,32 @@ public class AudioTrack extends PlayerBase } } /** * Helper method to extract device specific audio session id from Context. * * @param context {@link Context} to use for extraction of device specific session id. * @return device specific session id. If context is null or doesn't have specific audio * session id associated, this method returns {@link AUDIO_SESSION_ID_GENERATE}. */ private static int getSessionIdForContext(@Nullable Context context) { if (context == null) { return AUDIO_SESSION_ID_GENERATE; } int deviceId = context.getDeviceId(); if (deviceId == DEVICE_ID_DEFAULT) { return AUDIO_SESSION_ID_GENERATE; } VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class); if (vdm == null || vdm.getDevicePolicy(deviceId, POLICY_TYPE_AUDIO) == DEVICE_POLICY_DEFAULT) { return AUDIO_SESSION_ID_GENERATE; } return vdm.getAudioPlaybackSessionId(deviceId); } /** * Sets an {@link AudioPolicy} to automatically unregister when the track is released. * Loading Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -21197,6 +21197,7 @@ package android.media { method @NonNull public android.media.AudioTrack.Builder setAudioAttributes(@NonNull android.media.AudioAttributes) throws java.lang.IllegalArgumentException; method @NonNull public android.media.AudioTrack.Builder setAudioFormat(@NonNull android.media.AudioFormat) throws java.lang.IllegalArgumentException; method @NonNull public android.media.AudioTrack.Builder setBufferSizeInBytes(@IntRange(from=0) int) throws java.lang.IllegalArgumentException; method @NonNull public android.media.AudioTrack.Builder setContext(@NonNull android.content.Context); method @NonNull public android.media.AudioTrack.Builder setEncapsulationMode(int); method @NonNull public android.media.AudioTrack.Builder setOffloadedPlayback(boolean); method @NonNull public android.media.AudioTrack.Builder setPerformanceMode(int);
core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -3043,6 +3043,7 @@ package android.companion.virtual { field public static final int LOCK_STATE_DEFAULT = 0; // 0x0 field public static final int NAVIGATION_POLICY_DEFAULT_ALLOWED = 0; // 0x0 field public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; // 0x1 field public static final int POLICY_TYPE_AUDIO = 1; // 0x1 field public static final int POLICY_TYPE_SENSORS = 0; // 0x0 field public static final int RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS = 1; // 0x1 }
core/java/android/companion/virtual/VirtualDeviceManager.java +38 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.companion.virtual; import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; Loading Loading @@ -254,6 +256,42 @@ public final class VirtualDeviceManager { } } /** * Returns device-specific audio session id for audio playback. * * @param deviceId - id of the virtual audio device * @return Device specific session id to be used for audio playback (see * {@link android.media.AudioManager.generateAudioSessionId}) if virtual device has * {@link VirtualDeviceParams.POLICY_TYPE_AUDIO} set to * {@link VirtualDeviceParams.DEVICE_POLICY_CUSTOM} and Virtual Audio Device * is configured in context-aware mode. * Otherwise {@link AUDIO_SESSION_ID_GENERATE} constant is returned. * @hide */ public int getAudioPlaybackSessionId(int deviceId) { //TODO - Return session id rerouted to VirtualAudioDevice if the VirtualAudioDevice //is configured to operate in context-aware mode. return AUDIO_SESSION_ID_GENERATE; } /** * Returns device-specific audio session id for audio recording. * * @param deviceId - id of the virtual audio device * @return Device specific session id to be used for audio recording (see * {@link android.media.AudioManager.generateAudioSessionId}) if virtual device has * {@link VirtualDeviceParams.POLICY_TYPE_AUDIO} set to * {@link VirtualDeviceParams.DEVICE_POLICY_CUSTOM} and Virtual Audio Device * is configured in context-aware mode. * Otherwise {@link AUDIO_SESSION_ID_GENERATE} constant is returned. * @hide */ public int getAudioRecordingSessionId(int deviceId) { //TODO - Return session id corresponding to VirtualAudioDevice injection if the // VirtualAudioDevice is configured to operate in context-aware mode. return AUDIO_SESSION_ID_GENERATE; } /** * A virtual device has its own virtual display, audio output, microphone, and camera etc. The * creator of a virtual device can take the output from the virtual display and stream it over Loading
core/java/android/companion/virtual/VirtualDeviceParams.java +16 −1 Original line number Diff line number Diff line Loading @@ -129,7 +129,7 @@ public final class VirtualDeviceParams implements Parcelable { * a given policy type. * @hide */ @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS}) @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO}) @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) public @interface PolicyType {} Loading @@ -147,6 +147,21 @@ public final class VirtualDeviceParams implements Parcelable { */ public static final int POLICY_TYPE_SENSORS = 0; /** * Tells the audio framework whether to configure the players ({@link android.media.AudioTrack}, * {@link android.media.MediaPlayer}, {@link android.media.SoundPool} and recorders * {@link android.media.AudioRecord}) to use specific session ids re-routed to * VirtualAudioDevice. * * <ul> * <li>{@link #DEVICE_POLICY_DEFAULT}: fall back to default session id handling. * <li>{@link #DEVICE_POLICY_CUSTOM}: audio framework will assign device specific session * ids to players and recorders constructed within device context. The session ids are * used to re-route corresponding audio streams to VirtualAudioDevice. * <ul/> */ public static final int POLICY_TYPE_AUDIO = 1; /** @hide */ @IntDef(flag = true, prefix = "RECENTS_POLICY_", value = {RECENTS_POLICY_ALLOW_IN_HOST_DEVICE_RECENTS}) Loading
media/java/android/media/AudioTrack.java +68 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,11 @@ package android.media; import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT; import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT; import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO; import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; import android.annotation.CallbackExecutor; import android.annotation.FloatRange; import android.annotation.IntDef; Loading @@ -25,7 +30,9 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.companion.virtual.VirtualDeviceManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioMixingRule; import android.media.audiopolicy.AudioPolicy; Loading Loading @@ -545,7 +552,7 @@ public class AudioTrack extends PlayerBase /** * Audio session ID */ private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; private int mSessionId = AUDIO_SESSION_ID_GENERATE; /** * HW_AV_SYNC track AV Sync Header */ Loading Loading @@ -645,7 +652,7 @@ public class AudioTrack extends PlayerBase int bufferSizeInBytes, int mode) throws IllegalArgumentException { this(streamType, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE); bufferSizeInBytes, mode, AUDIO_SESSION_ID_GENERATE); } /** Loading Loading @@ -749,12 +756,12 @@ public class AudioTrack extends PlayerBase public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId) throws IllegalArgumentException { this(attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/, ENCAPSULATION_MODE_NONE, null /* tunerConfiguration */); this(null /* context */, attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/, ENCAPSULATION_MODE_NONE, null /* tunerConfiguration */); } private AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId, boolean offload, int encapsulationMode, private AudioTrack(@Nullable Context context, AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes, int mode, int sessionId, boolean offload, int encapsulationMode, @Nullable TunerConfiguration tunerConfiguration) throws IllegalArgumentException { super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_JAM_AUDIOTRACK); Loading Loading @@ -817,7 +824,13 @@ public class AudioTrack extends PlayerBase int[] sampleRate = new int[] {mSampleRate}; int[] session = new int[1]; if (sessionId == AUDIO_SESSION_ID_GENERATE) { // If there's no specific session id requested, try to get one from context. session[0] = getSessionIdForContext(context); } else { session[0] = sessionId; } // native initialization int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes, sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat, Loading Loading @@ -1028,11 +1041,12 @@ public class AudioTrack extends PlayerBase * <br>Offload is false by default. */ public static class Builder { private Context mContext; private AudioAttributes mAttributes; private AudioFormat mFormat; private int mBufferSizeInBytes; private int mEncapsulationMode = ENCAPSULATION_MODE_NONE; private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; private int mSessionId = AUDIO_SESSION_ID_GENERATE; private int mMode = MODE_STREAM; private int mPerformanceMode = PERFORMANCE_MODE_NONE; private boolean mOffload = false; Loading @@ -1045,6 +1059,19 @@ public class AudioTrack extends PlayerBase public Builder() { } /** * Sets the context the track belongs to. This context will be used to pull information, * such as {@link android.content.AttributionSource} and device specific audio session ids, * which will be associated with the {@link AudioTrack}. However, the context itself will * not be retained by the {@link AudioTrack}. * @param context a non-null {@link Context} instance * @return the same Builder instance. */ public @NonNull Builder setContext(@NonNull Context context) { mContext = Objects.requireNonNull(context); return this; } /** * Sets the {@link AudioAttributes}. * @param attributes a non-null {@link AudioAttributes} instance that describes the audio Loading Loading @@ -1152,6 +1179,10 @@ public class AudioTrack extends PlayerBase /** * Sets the session ID the {@link AudioTrack} will be attached to. * * Note, that if there's a device specific session id asociated with the context, explicitly * setting a session id using this method will override it * (see {@link Builder#setContext(Context)}). * @param sessionId a strictly positive ID number retrieved from another * <code>AudioTrack</code> via {@link AudioTrack#getAudioSessionId()} or allocated by * {@link AudioManager} via {@link AudioManager#generateAudioSessionId()}, or Loading @@ -1161,7 +1192,7 @@ public class AudioTrack extends PlayerBase */ public @NonNull Builder setSessionId(@IntRange(from = 1) int sessionId) throws IllegalArgumentException { if ((sessionId != AudioManager.AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) { if ((sessionId != AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) { throw new IllegalArgumentException("Invalid audio session ID " + sessionId); } mSessionId = sessionId; Loading Loading @@ -1371,8 +1402,8 @@ public class AudioTrack extends PlayerBase try { final AudioTrack track = new AudioTrack( mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload, mEncapsulationMode, mTunerConfiguration); mContext, mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload, mEncapsulationMode, mTunerConfiguration); if (track.getState() == STATE_UNINITIALIZED) { // release is not necessary throw new UnsupportedOperationException("Cannot create AudioTrack"); Loading @@ -1384,6 +1415,32 @@ public class AudioTrack extends PlayerBase } } /** * Helper method to extract device specific audio session id from Context. * * @param context {@link Context} to use for extraction of device specific session id. * @return device specific session id. If context is null or doesn't have specific audio * session id associated, this method returns {@link AUDIO_SESSION_ID_GENERATE}. */ private static int getSessionIdForContext(@Nullable Context context) { if (context == null) { return AUDIO_SESSION_ID_GENERATE; } int deviceId = context.getDeviceId(); if (deviceId == DEVICE_ID_DEFAULT) { return AUDIO_SESSION_ID_GENERATE; } VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class); if (vdm == null || vdm.getDevicePolicy(deviceId, POLICY_TYPE_AUDIO) == DEVICE_POLICY_DEFAULT) { return AUDIO_SESSION_ID_GENERATE; } return vdm.getAudioPlaybackSessionId(deviceId); } /** * Sets an {@link AudioPolicy} to automatically unregister when the track is released. * Loading