Merge "Audio record notification: report client/device configuration" into nyc-dev

This commit is contained in:
Jean-Michel Trivi
2016-02-24 17:08:32 +00:00
committed by Android (Google) Code Review
4 changed files with 83 additions and 15 deletions

View File

@@ -388,18 +388,43 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
}
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 @@ int register_android_media_AudioSystem(JNIEnv *env)
"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);

View File

@@ -41,11 +41,12 @@ public class AudioRecordConfiguration implements Parcelable {
/**
* @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 class AudioRecordConfiguration implements Parcelable {
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;
}

View File

@@ -273,7 +273,17 @@ public class AudioSystem
*/
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 @@ public class AudioSystem
}
}
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);
}
}

View File

@@ -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 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
/**
* 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 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
* @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 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
return false;
} else {
mRecordConfigs.put(new Integer(session),
new AudioRecordConfiguration(session, source));
new AudioRecordConfiguration(session, source,
clientFormat, deviceFormat));
return true;
}
default: