Audio record notification: report client/device configuration
Report client and device recording configuration during updates.
Support querying the AudioFormat in AudioRecordConfiguration.
Bug 22876530
Change-Id: I90b44db9bc3fda479452fc63221f8082f5b6a741
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 80f8a64..7d9e4a2 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -388,18 +388,43 @@
}
static void
-android_media_AudioSystem_recording_callback(int event, int session, int source)
+android_media_AudioSystem_recording_callback(int event, int session, int source,
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (env == NULL) {
return;
}
+ if (clientConfig == NULL || deviceConfig == NULL) {
+ ALOGE("Unexpected null client/device configurations in recording callback");
+ return;
+ }
+ // create an array for 2*3 integers to store the record configurations (client + device)
+ jintArray recParamArray = env->NewIntArray(6);
+ if (recParamArray == NULL) {
+ ALOGE("recording callback: Couldn't allocate int array for configuration data");
+ return;
+ }
+ jint recParamData[6];
+ recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
+ // FIXME this doesn't support index-based masks
+ recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
+ recParamData[2] = (jint) clientConfig->sample_rate;
+ recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
+ // FIXME this doesn't support index-based masks
+ recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
+ recParamData[5] = (jint) deviceConfig->sample_rate;
+ env->SetIntArrayRegion(recParamArray, 0, 6, recParamData);
+
+ // callback into java
jclass clazz = env->FindClass(kClassPathName);
env->CallStaticVoidMethod(clazz,
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
- event, session, source);
+ event, session, source, recParamArray);
env->DeleteLocalRef(clazz);
+
+ env->DeleteLocalRef(recParamArray);
}
static jint
@@ -1819,7 +1844,7 @@
"dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
- "recordingCallbackFromNative", "(III)V");
+ "recordingCallbackFromNative", "(III[I)V");
jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
diff --git a/media/java/android/media/AudioRecordConfiguration.java b/media/java/android/media/AudioRecordConfiguration.java
index 69df88f..61d239c 100644
--- a/media/java/android/media/AudioRecordConfiguration.java
+++ b/media/java/android/media/AudioRecordConfiguration.java
@@ -41,11 +41,12 @@
/**
* @hide
*/
- public AudioRecordConfiguration(int session, int source) {
+ public AudioRecordConfiguration(int session, int source,
+ AudioFormat clientFormat, AudioFormat deviceFormat) {
mSessionId = session;
mClientSource = source;
- mDeviceFormat = new AudioFormat.Builder().build();
- mClientFormat = new AudioFormat.Builder().build();
+ mDeviceFormat = deviceFormat;
+ mClientFormat = clientFormat;
mRecDevice = null;
}
@@ -129,13 +130,17 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mSessionId);
dest.writeInt(mClientSource);
+ mClientFormat.writeToParcel(dest, 0);
+ mDeviceFormat.writeToParcel(dest, 0);
+ //TODO marshall device info
}
private AudioRecordConfiguration(Parcel in) {
mSessionId = in.readInt();
mClientSource = in.readInt();
- mDeviceFormat = new AudioFormat.Builder().build();
- mClientFormat = new AudioFormat.Builder().build();
+ mClientFormat = AudioFormat.CREATOR.createFromParcel(in);
+ mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in);
+ //TODO unmarshall device info
mRecDevice = null;
}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index b3f73be..59782cb 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -273,7 +273,17 @@
*/
public interface AudioRecordingCallback
{
- void onRecordingConfigurationChanged(int event, int session, int source);
+ /**
+ * Callback for recording activity notifications events
+ * @param event
+ * @param session
+ * @param source
+ * @param recordingFormat an array of ints containing respectively the client and device
+ * recording configuration. Each set of parameters contains the following parameters
+ * in this order: format, channel mask, sample rate
+ */
+ void onRecordingConfigurationChanged(int event, int session, int source,
+ int[] recordingFormat);
}
private static AudioRecordingCallback sRecordingCallback;
@@ -285,13 +295,23 @@
}
}
- private static void recordingCallbackFromNative(int event, int session, int source) {
+ /**
+ * Callback from native for recording configuration updates.
+ * @param event
+ * @param session
+ * @param source
+ * @param recordingFormat see
+ * {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])} for
+ * the description of the record format.
+ */
+ private static void recordingCallbackFromNative(int event, int session, int source,
+ int[] recordingFormat) {
AudioRecordingCallback cb = null;
synchronized (AudioSystem.class) {
cb = sRecordingCallback;
}
if (cb != null) {
- cb.onRecordingConfigurationChanged(event, session, source);
+ cb.onRecordingConfigurationChanged(event, session, source, recordingFormat);
}
}
diff --git a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
index a6325a4..4b0a142 100644
--- a/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/RecordingActivityMonitor.java
@@ -16,6 +16,7 @@
package com.android.server.audio;
+import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecordConfiguration;
import android.media.AudioSystem;
@@ -48,11 +49,12 @@
/**
* Implementation of android.media.AudioSystem.AudioRecordingCallback
*/
- public void onRecordingConfigurationChanged(int event, int session, int source) {
+ public void onRecordingConfigurationChanged(int event, int session, int source,
+ int[] recordingFormat) {
if (MediaRecorder.isSystemOnlyAudioSource(source)) {
return;
}
- if (updateSnapshot(event, session, source)) {
+ if (updateSnapshot(event, session, source, recordingFormat)) {
final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
synchronized(mClients) {
while (clientIterator.hasNext()) {
@@ -110,15 +112,30 @@
* @param event
* @param session
* @param source
+ * @param recordingFormat see
+ * {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])}
+ * for the definition of the contents of the array
* @return true if the list of active recording sessions has been modified, false otherwise.
*/
- private boolean updateSnapshot(int event, int session, int source) {
+ private boolean updateSnapshot(int event, int session, int source, int[] recordingFormat) {
synchronized(mRecordConfigs) {
switch (event) {
case AudioManager.RECORD_CONFIG_EVENT_STOP:
// return failure if an unknown recording session stopped
return (mRecordConfigs.remove(new Integer(session)) != null);
case AudioManager.RECORD_CONFIG_EVENT_START:
+ final AudioFormat clientFormat = new AudioFormat.Builder()
+ .setEncoding(recordingFormat[0])
+ // FIXME this doesn't support index-based masks
+ .setChannelMask(recordingFormat[1])
+ .setSampleRate(recordingFormat[2])
+ .build();
+ final AudioFormat deviceFormat = new AudioFormat.Builder()
+ .setEncoding(recordingFormat[3])
+ // FIXME this doesn't support index-based masks
+ .setChannelMask(recordingFormat[4])
+ .setSampleRate(recordingFormat[5])
+ .build();
if (mRecordConfigs.containsKey(new Integer(session))) {
// start of session that's already tracked, not worth an update
// TO DO in the future when tracking record format: there might be a record
@@ -126,7 +143,8 @@
return false;
} else {
mRecordConfigs.put(new Integer(session),
- new AudioRecordConfiguration(session, source));
+ new AudioRecordConfiguration(session, source,
+ clientFormat, deviceFormat));
return true;
}
default: