From 2ac2afeac989ea1dc326b0db996d6c6c8e00cc29 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Tue, 21 Aug 2012 11:16:55 -0700 Subject: [PATCH] Add support for controlling remote submix audio routing Add method in AudioManager to control remote submix through AudioService. AudioService controls remote submxi: enabling/disabling remote submix will: - make the sink audio device available/unavailable - make the audio source available/unavailable - force/unforce media streams to be routed to WFD Change-Id: I05d9cc7c3e8a720318ec1385737cbd46a21a3207 --- media/java/android/media/AudioManager.java | 15 ++++++++- media/java/android/media/AudioService.java | 34 +++++++++++++++++++++ media/java/android/media/AudioSystem.java | 4 ++- media/java/android/media/IAudioService.aidl | 2 ++ media/java/android/media/MediaRecorder.java | 13 +++++++- 5 files changed, 65 insertions(+), 3 deletions(-) diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index b5613f3ccdd5f..ea00ec832bf7e 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1164,7 +1164,7 @@ public class AudioManager { /** * Indicates if current platform supports use of SCO for off call use cases. * Application wanted to use bluetooth SCO audio when the phone is not in call - * must first call thsi method to make sure that the platform supports this + * must first call this method to make sure that the platform supports this * feature. * @return true if bluetooth SCO can be used for audio when not in call * false otherwise @@ -1299,6 +1299,19 @@ public class AudioManager { } } + /** + * @hide + * Signals whether remote submix audio rerouting is enabled. + */ + public void setRemoteSubmixOn(boolean on, int address) { + IAudioService service = getService(); + try { + service.setRemoteSubmixOn(on, address); + } catch (RemoteException e) { + Log.e(TAG, "Dead object in setRemoteSubmixOn", e); + } + } + /** * Sets audio routing to the wired headset on or off. * diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index aea8a88ada4e1..e5c2a4debb7db 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -151,6 +151,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished { private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 21; private static final int MSG_SET_A2DP_CONNECTION_STATE = 22; // end of messages handled under wakelock + private static final int MSG_SET_RSX_CONNECTION_STATE = 23; // change remote submix connection + private static final int MSG_SET_FORCE_RSX_USE = 24; // force remote submix audio routing // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be // persisted @@ -2109,6 +2111,33 @@ public class AudioService extends IAudioService.Stub implements OnFinished { } }; + /** see AudioManager.setRemoteSubmixOn(boolean on) */ + public void setRemoteSubmixOn(boolean on, int address) { + sendMsg(mAudioHandler, MSG_SET_RSX_CONNECTION_STATE, + SENDMSG_REPLACE /* replace with QUEUE when multiple addresses are supported */, + on ? 1 : 0 /*arg1*/, + address /*arg2*/, + null/*obj*/, 0/*delay*/); + + // Note that we are currently forcing use of remote submix as soon as corresponding device + // is made available + sendMsg(mAudioHandler, MSG_SET_FORCE_RSX_USE, SENDMSG_REPLACE, + AudioSystem.FOR_MEDIA, + on ? AudioSystem.FORCE_REMOTE_SUBMIX : AudioSystem.FORCE_NONE, + null/*obj*/, 0/*delay*/); + } + + private void onSetRsxConnectionState(int available, int address) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, + available == 1 ? + AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE, + String.valueOf(address) /*device_address*/); + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, + available == 1 ? + AudioSystem.DEVICE_STATE_AVAILABLE : AudioSystem.DEVICE_STATE_UNAVAILABLE, + String.valueOf(address) /*device_address*/); + } + /////////////////////////////////////////////////////////////////////////// // Internal methods /////////////////////////////////////////////////////////////////////////// @@ -3072,6 +3101,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished { case MSG_SET_FORCE_USE: case MSG_SET_FORCE_BT_A2DP_USE: + case MSG_SET_FORCE_RSX_USE: setForceUse(msg.arg1, msg.arg2); break; @@ -3134,6 +3164,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished { onRegisterVolumeObserverForRcc(msg.arg1 /* rccId */, (IRemoteVolumeObserver)msg.obj /* rvo */); break; + + case MSG_SET_RSX_CONNECTION_STATE: + onSetRsxConnectionState(msg.arg1/*available*/, msg.arg2/*address*/); + break; } } } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index f3a85581d3888..129e84fb3ad5a 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -214,6 +214,7 @@ public class AudioSystem public static final int DEVICE_OUT_REMOTE_SUBMIX = 0x8000; public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT; + public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | DEVICE_OUT_SPEAKER | DEVICE_OUT_WIRED_HEADSET | @@ -352,7 +353,8 @@ public class AudioSystem public static final int FORCE_ANALOG_DOCK = 8; public static final int FORCE_DIGITAL_DOCK = 9; public static final int FORCE_NO_BT_A2DP = 10; - private static final int NUM_FORCE_CONFIG = 11; + public static final int FORCE_REMOTE_SUBMIX = 11; + private static final int NUM_FORCE_CONFIG = 12; public static final int FORCE_DEFAULT = FORCE_NONE; // usage for setForceUse, must match AudioSystem::force_use diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index 854eb3f0663ba..7ae61cd3e924b 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -108,6 +108,8 @@ interface IAudioService { boolean isBluetoothA2dpOn(); + oneway void setRemoteSubmixOn(boolean on, int address); + int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb, IAudioFocusDispatcher l, String clientId, String callingPackageName); diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 2d1be02f8c415..48bea52ff58a3 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -177,6 +177,12 @@ public class MediaRecorder * is applied. */ public static final int VOICE_COMMUNICATION = 7; + + /** + * @hide + * Audio source for remote submix. + */ + public static final int REMOTE_SUBMIX_SOURCE = 8; } /** @@ -291,7 +297,12 @@ public class MediaRecorder * Gets the maximum value for audio sources. * @see android.media.MediaRecorder.AudioSource */ - public static final int getAudioSourceMax() { return AudioSource.VOICE_COMMUNICATION; } + public static final int getAudioSourceMax() { + // FIXME disable selection of the remote submxi source selection once test code + // doesn't rely on it + return AudioSource.REMOTE_SUBMIX_SOURCE; + //return AudioSource.VOICE_COMMUNICATION; + } /** * Sets the video source to be used for recording. If this method is not