summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2015-05-06 17:51:52 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-06 17:51:53 +0000
commitb65cd17b0508a5a7afdd92e69437825071a1631b (patch)
treec727a8fe013d5eb6135bd6e4f453e9ee262a35ad /media
parent6223ec129b256526d8c30920271b2ee3960bcf1f (diff)
parent4bcdba848449b33d7022de527c526943aff1f5fd (diff)
downloadframeworks_base-b65cd17b0508a5a7afdd92e69437825071a1631b.zip
frameworks_base-b65cd17b0508a5a7afdd92e69437825071a1631b.tar.gz
frameworks_base-b65cd17b0508a5a7afdd92e69437825071a1631b.tar.bz2
Merge "Implement audio routing callbacks" into mnc-dev
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/AudioDevicePort.java10
-rw-r--r--media/java/android/media/AudioDevicesManager.java17
-rw-r--r--media/java/android/media/AudioManager.java12
-rw-r--r--media/java/android/media/AudioMixPort.java19
-rw-r--r--media/java/android/media/AudioPort.java8
-rw-r--r--media/java/android/media/AudioRecord.java58
-rw-r--r--media/java/android/media/AudioSystem.java6
-rw-r--r--media/java/android/media/AudioTrack.java53
8 files changed, 146 insertions, 37 deletions
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 82da27d..c078260 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -83,6 +83,16 @@ public class AudioDevicePort extends AudioPort {
if (o == null || !(o instanceof AudioDevicePort)) {
return false;
}
+ AudioDevicePort other = (AudioDevicePort)o;
+ if (mType != other.type()) {
+ return false;
+ }
+ if (mAddress == null && other.address() != null) {
+ return false;
+ }
+ if (!mAddress.equals(other.address())) {
+ return false;
+ }
return super.equals(o);
}
diff --git a/media/java/android/media/AudioDevicesManager.java b/media/java/android/media/AudioDevicesManager.java
index ca238d7..8b83c17 100644
--- a/media/java/android/media/AudioDevicesManager.java
+++ b/media/java/android/media/AudioDevicesManager.java
@@ -96,7 +96,7 @@ public class AudioDevicesManager {
* @param flags A set of bitflags specifying the criteria to test.
* @see {@link LIST_DEVICES_OUTPUTS} and {@link LIST_DEVICES_INPUTS}
**/
- private boolean checkFlags(AudioDevicePort port, int flags) {
+ private static boolean checkFlags(AudioDevicePort port, int flags) {
return port.role() == AudioPort.ROLE_SINK && (flags & LIST_DEVICES_OUTPUTS) != 0 ||
port.role() == AudioPort.ROLE_SOURCE && (flags & LIST_DEVICES_INPUTS) != 0;
}
@@ -110,8 +110,21 @@ public class AudioDevicesManager {
* @return A (possibly zero-length) array of AudioDeviceInfo objects.
*/
public AudioDeviceInfo[] listDevices(int flags) {
+ return listDevicesStatic(flags);
+ }
+
+ /**
+ * Generates a list of AudioDeviceInfo objects corresponding to the audio devices currently
+ * connected to the system and meeting the criteria specified in the <code>flags</code>
+ * parameter.
+ * @param flags A set of bitflags specifying the criteria to test.
+ * @see {@link LIST_DEVICES_OUTPUTS}, {@link LIST_DEVICES_INPUTS} and {@link LIST_DEVICES_ALL}.
+ * @return A (possibly zero-length) array of AudioDeviceInfo objects.
+ * @hide
+ */
+ public static AudioDeviceInfo[] listDevicesStatic(int flags) {
ArrayList<AudioDevicePort> ports = new ArrayList<AudioDevicePort>();
- int status = mAudioManager.listAudioDevicePorts(ports);
+ int status = AudioManager.listAudioDevicePorts(ports);
if (status != AudioManager.SUCCESS) {
// fail and bail!
return new AudioDeviceInfo[0];
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6eaf812..19900d0 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3401,7 +3401,7 @@ public class AudioManager {
* @param ports An AudioPort ArrayList where the list will be returned.
* @hide
*/
- public int listAudioPorts(ArrayList<AudioPort> ports) {
+ public static int listAudioPorts(ArrayList<AudioPort> ports) {
return updateAudioPortCache(ports, null);
}
@@ -3410,7 +3410,7 @@ public class AudioManager {
* @see listAudioPorts(ArrayList<AudioPort>)
* @hide
*/
- public int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
+ public static int listAudioDevicePorts(ArrayList<AudioDevicePort> devices) {
ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
int status = updateAudioPortCache(ports, null);
if (status == SUCCESS) {
@@ -3447,7 +3447,7 @@ public class AudioManager {
* patch[0] contains the newly created patch
* @hide
*/
- public int createAudioPatch(AudioPatch[] patch,
+ public static int createAudioPatch(AudioPatch[] patch,
AudioPortConfig[] sources,
AudioPortConfig[] sinks) {
return AudioSystem.createAudioPatch(patch, sources, sinks);
@@ -3464,7 +3464,7 @@ public class AudioManager {
* - {@link #ERROR} if patch cannot be released for any other reason.
* @hide
*/
- public int releaseAudioPatch(AudioPatch patch) {
+ public static int releaseAudioPatch(AudioPatch patch) {
return AudioSystem.releaseAudioPatch(patch);
}
@@ -3473,7 +3473,7 @@ public class AudioManager {
* @param patches An AudioPatch array where the list will be returned.
* @hide
*/
- public int listAudioPatches(ArrayList<AudioPatch> patches) {
+ public static int listAudioPatches(ArrayList<AudioPatch> patches) {
return updateAudioPortCache(null, patches);
}
@@ -3482,7 +3482,7 @@ public class AudioManager {
* AudioGain.buildConfig()
* @hide
*/
- public int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
+ public static int setAudioPortGain(AudioPort port, AudioGainConfig gain) {
if (port == null || gain == null) {
return ERROR_BAD_VALUE;
}
diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java
index 9fac8d1..ab55c8d 100644
--- a/media/java/android/media/AudioMixPort.java
+++ b/media/java/android/media/AudioMixPort.java
@@ -20,16 +20,21 @@ package android.media;
* The AudioMixPort is a specialized type of AudioPort
* describing an audio mix or stream at an input or output stream of the audio
* framework.
+ * In addition to base audio port attributes, the mix descriptor contains:
+ * - the unique audio I/O handle assigned by AudioFlinger to this mix.
* @see AudioPort
* @hide
*/
public class AudioMixPort extends AudioPort {
- AudioMixPort(AudioHandle handle, int role, String deviceName,
+ private final int mIoHandle;
+
+ AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName,
int[] samplingRates, int[] channelMasks,
int[] formats, AudioGain[] gains) {
super(handle, role, deviceName, samplingRates, channelMasks, formats, gains);
+ mIoHandle = ioHandle;
}
/**
@@ -41,11 +46,23 @@ public class AudioMixPort extends AudioPort {
return new AudioMixPortConfig(this, samplingRate, channelMask, format, gain);
}
+ /**
+ * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER)
+ */
+ public int ioHandle() {
+ return mIoHandle;
+ }
+
@Override
public boolean equals(Object o) {
if (o == null || !(o instanceof AudioMixPort)) {
return false;
}
+ AudioMixPort other = (AudioMixPort)o;
+ if (mIoHandle != other.ioHandle()) {
+ return false;
+ }
+
return super.equals(o);
}
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index 88e784a..7328d7a 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -93,6 +93,14 @@ public class AudioPort {
}
/**
+ * Get the system unique device ID.
+ */
+ public int id() {
+ return mHandle.id();
+ }
+
+
+ /**
* Get the audio port role
*/
public int role() {
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 472da02..11671d8 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -116,11 +116,6 @@ public class AudioRecord
*/
private static final int NATIVE_EVENT_NEW_POS = 3;
- /**
- * Event id denotes when the routing changes.
- */
- private final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
-
private final static String TAG = "android.media.AudioRecord";
/** @hide */
@@ -161,6 +156,12 @@ public class AudioRecord
@SuppressWarnings("unused")
private long mNativeCallbackCookie;
+ /**
+ * Accessed by native methods: provides access to the JNIDeviceCallback instance.
+ */
+ @SuppressWarnings("unused")
+ private long mNativeDeviceCallback;
+
//---------------------------------------------------------
// Member variables
@@ -1205,6 +1206,17 @@ public class AudioRecord
* Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord.
*/
public AudioDeviceInfo getRoutedDevice() {
+ int deviceId = native_getRoutedDeviceId();
+ if (deviceId == 0) {
+ return null;
+ }
+ AudioDeviceInfo[] devices =
+ AudioDevicesManager.listDevicesStatic(AudioDevicesManager.LIST_DEVICES_INPUTS);
+ for (int i = 0; i < devices.length; i++) {
+ if (devices[i].getId() == deviceId) {
+ return devices[i];
+ }
+ }
return null;
}
@@ -1224,6 +1236,9 @@ public class AudioRecord
android.os.Handler handler) {
if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
synchronized (mRoutingChangeListeners) {
+ if (mRoutingChangeListeners.size() == 0) {
+ native_enableDeviceCallback();
+ }
mRoutingChangeListeners.put(
listener, new NativeRoutingEventHandlerDelegate(this, listener, handler));
}
@@ -1238,6 +1253,9 @@ public class AudioRecord
synchronized (mRoutingChangeListeners) {
if (mRoutingChangeListeners.containsKey(listener)) {
mRoutingChangeListeners.remove(listener);
+ if (mRoutingChangeListeners.size() == 0) {
+ native_disableDeviceCallback();
+ }
}
}
}
@@ -1271,7 +1289,7 @@ public class AudioRecord
return;
}
switch(msg.what) {
- case NATIVE_EVENT_ROUTING_CHANGE:
+ case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
if (listener != null) {
listener.onAudioRecordRouting(record);
}
@@ -1299,10 +1317,11 @@ public class AudioRecord
synchronized (mRoutingChangeListeners) {
values = mRoutingChangeListeners.values();
}
+ AudioManager.resetAudioPortGeneration();
for(NativeRoutingEventHandlerDelegate delegate : values) {
Handler handler = delegate.getHandler();
if (handler != null) {
- handler.sendEmptyMessage(NATIVE_EVENT_ROUTING_CHANGE);
+ handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
}
}
}
@@ -1341,10 +1360,14 @@ public class AudioRecord
return false;
}
- mPreferredDevice = deviceInfo;
- int preferredDeviceId = mPreferredDevice != null ? deviceInfo.getId() : 0;
-
- return native_setInputDevice(preferredDeviceId);
+ int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
+ boolean status = native_setInputDevice(preferredDeviceId);
+ if (status == true) {
+ synchronized (this) {
+ mPreferredDevice = deviceInfo;
+ }
+ }
+ return status;
}
/**
@@ -1352,7 +1375,9 @@ public class AudioRecord
* is not guarenteed to correspond to the actual device being used for recording.
*/
public AudioDeviceInfo getPreferredInputDevice() {
- return mPreferredDevice;
+ synchronized (this) {
+ return mPreferredDevice;
+ }
}
//---------------------------------------------------------
@@ -1435,6 +1460,11 @@ public class AudioRecord
return;
}
+ if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
+ recorder.broadcastRoutingChange();
+ return;
+ }
+
if (recorder.mEventHandler != null) {
Message m =
recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj);
@@ -1486,7 +1516,9 @@ public class AudioRecord
int sampleRateInHz, int channelCount, int audioFormat);
private native final boolean native_setInputDevice(int deviceId);
-
+ private native final int native_getRoutedDeviceId();
+ private native final void native_enableDeviceCallback();
+ private native final void native_disableDeviceCallback();
//---------------------------------------------------------
// Utility methods
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 3dae543..ee12374 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -721,5 +721,11 @@ public class AudioSystem
(1 << STREAM_RING) |
(1 << STREAM_NOTIFICATION) |
(1 << STREAM_SYSTEM);
+
+ /**
+ * Event posted by AudioTrack and AudioRecord JNI (JNIDeviceCallback) when routing changes.
+ * Keep in sync with core/jni/android_media_DeviceCallback.h.
+ */
+ final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index cb05cc5..a66a1e5 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -178,12 +178,6 @@ public class AudioTrack
*/
private static final int NATIVE_EVENT_NEW_POS = 4;
- /**
- * Event id denotes when the routing changes.
- */
- private final static int NATIVE_EVENT_ROUTING_CHANGE = 1000;
-
-
private final static String TAG = "android.media.AudioTrack";
@@ -2057,11 +2051,14 @@ public class AudioTrack
if (deviceInfo != null && !deviceInfo.isSink()) {
return false;
}
-
- mPreferredDevice = deviceInfo;
- int preferredDeviceId = mPreferredDevice != null ? deviceInfo.getId() : 0;
-
- return native_setOutputDevice(preferredDeviceId);
+ int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
+ boolean status = native_setOutputDevice(preferredDeviceId);
+ if (status == true) {
+ synchronized (this) {
+ mPreferredDevice = deviceInfo;
+ }
+ }
+ return status;
}
/**
@@ -2069,7 +2066,9 @@ public class AudioTrack
* is not guaranteed to correspond to the actual device being used for playback.
*/
public AudioDeviceInfo getPreferredOutputDevice() {
- return mPreferredDevice;
+ synchronized (this) {
+ return mPreferredDevice;
+ }
}
//--------------------------------------------------------------------------
@@ -2079,6 +2078,17 @@ public class AudioTrack
* Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioTrack.
*/
public AudioDeviceInfo getRoutedDevice() {
+ int deviceId = native_getRoutedDeviceId();
+ if (deviceId == 0) {
+ return null;
+ }
+ AudioDeviceInfo[] devices =
+ AudioDevicesManager.listDevicesStatic(AudioDevicesManager.LIST_DEVICES_OUTPUTS);
+ for (int i = 0; i < devices.length; i++) {
+ if (devices[i].getId() == deviceId) {
+ return devices[i];
+ }
+ }
return null;
}
@@ -2098,6 +2108,9 @@ public class AudioTrack
android.os.Handler handler) {
if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
synchronized (mRoutingChangeListeners) {
+ if (mRoutingChangeListeners.size() == 0) {
+ native_enableDeviceCallback();
+ }
mRoutingChangeListeners.put(
listener, new NativeRoutingEventHandlerDelegate(this, listener, handler));
}
@@ -2113,6 +2126,9 @@ public class AudioTrack
if (mRoutingChangeListeners.containsKey(listener)) {
mRoutingChangeListeners.remove(listener);
}
+ if (mRoutingChangeListeners.size() == 0) {
+ native_disableDeviceCallback();
+ }
}
}
@@ -2124,10 +2140,11 @@ public class AudioTrack
synchronized (mRoutingChangeListeners) {
values = mRoutingChangeListeners.values();
}
+ AudioManager.resetAudioPortGeneration();
for(NativeRoutingEventHandlerDelegate delegate : values) {
Handler handler = delegate.getHandler();
if (handler != null) {
- handler.sendEmptyMessage(NATIVE_EVENT_ROUTING_CHANGE);
+ handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
}
}
}
@@ -2240,7 +2257,7 @@ public class AudioTrack
return;
}
switch(msg.what) {
- case NATIVE_EVENT_ROUTING_CHANGE:
+ case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
if (listener != null) {
listener.onAudioTrackRouting(track);
}
@@ -2273,6 +2290,10 @@ public class AudioTrack
return;
}
+ if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
+ track.broadcastRoutingChange();
+ return;
+ }
NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate;
if (delegate != null) {
Handler handler = delegate.getHandler();
@@ -2281,7 +2302,6 @@ public class AudioTrack
handler.sendMessage(m);
}
}
-
}
@@ -2362,6 +2382,9 @@ public class AudioTrack
private native final int native_setAuxEffectSendLevel(float level);
private native final boolean native_setOutputDevice(int deviceId);
+ private native final int native_getRoutedDeviceId();
+ private native final void native_enableDeviceCallback();
+ private native final void native_disableDeviceCallback();
//---------------------------------------------------------
// Utility methods