From 667f84962ef390d9fc96cd911a5bbe5730d098c5 Mon Sep 17 00:00:00 2001 From: Jan Sebechlebsky Date: Wed, 5 Apr 2023 16:57:50 +0200 Subject: [PATCH] Support virtual device specific audio session in TTS. When TextToSpeech is constructed using context asociated with VirtualDevice instance configured with specific audio playback session id, this change will propagate the session id to TextToSpeech service. This allows re-routing TTS audio from TTS playback triggered from the apps running on virtual devices. More details in go/if-xr-vdm-tts Test: atest android.virtualdevice.cts.TextToSpeechTest Bug: 275634941 Change-Id: I548ab5570119ab22996176c242f8bf22b99e9281 --- .../java/android/speech/tts/TextToSpeech.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 21b14f4fe7db2..428a07f1ca7bd 100644 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -15,12 +15,17 @@ */ package android.speech.tts; +import static android.content.Context.DEVICE_ID_DEFAULT; +import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RawRes; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.companion.virtual.VirtualDevice; +import android.companion.virtual.VirtualDeviceManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.ContentResolver; @@ -791,9 +796,48 @@ public class TextToSpeech { mIsSystem = isSystem; + addDeviceSpecificSessionIdToParams(mContext, mParams); initTts(); } + /** + * Add {@link VirtualDevice} specific playback audio session associated with context to + * parameters {@link Bundle} if applicable. + * + * @param context - {@link Context} context instance to extract the device specific audio + * session id from. + * @param params - {@link Bundle} to add the device specific audio session id to. + */ + private static void addDeviceSpecificSessionIdToParams( + @NonNull Context context, @NonNull Bundle params) { + int audioSessionId = getDeviceSpecificPlaybackSessionId(context); + if (audioSessionId != AUDIO_SESSION_ID_GENERATE) { + params.putInt(Engine.KEY_PARAM_SESSION_ID, audioSessionId); + } + } + + /** + * Helper method to fetch {@link VirtualDevice} specific playback audio session id for given + * {@link Context} instance. + * + * @param context - {@link Context} to fetch the audio sesion id for. + * @return audio session id corresponding to {@link VirtualDevice} in case the context is + * associated with {@link VirtualDevice} configured with specific audio session id, + * {@link AudioManager#AUDIO_SESSION_ID_GENERATE} otherwise. + * @see android.companion.virtual.VirtualDeviceManager#getAudioPlaybackSessionId(int) + */ + private static int getDeviceSpecificPlaybackSessionId(@NonNull Context context) { + int deviceId = context.getDeviceId(); + if (deviceId == DEVICE_ID_DEFAULT) { + return AUDIO_SESSION_ID_GENERATE; + } + VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class); + if (vdm == null) { + return AUDIO_SESSION_ID_GENERATE; + } + return vdm.getAudioPlaybackSessionId(deviceId); + } + private R runActionNoReconnect(Action action, R errorResult, String method, boolean onlyEstablishedConnection) { return runAction(action, errorResult, method, false, onlyEstablishedConnection);