Merge "Audio record notification: report audio device information" into nyc-dev

am: 768d81374b

* commit '768d81374ba50d215064ca11ed3ca34cf46d087c':
  Audio record notification: report audio device information
This commit is contained in:
Jean-Michel Trivi
2016-02-26 22:42:26 +00:00
committed by android-build-merger
6 changed files with 115 additions and 47 deletions

View File

@@ -389,7 +389,8 @@ 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,
const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
audio_patch_handle_t patchHandle)
{
JNIEnv *env = AndroidRuntime::getJNIEnv();
if (env == NULL) {
@@ -401,12 +402,14 @@ android_media_AudioSystem_recording_callback(int event, int session, int source,
}
// create an array for 2*3 integers to store the record configurations (client + device)
jintArray recParamArray = env->NewIntArray(6);
// plus 1 integer for the patch handle
const int REC_PARAM_SIZE = 7;
jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
if (recParamArray == NULL) {
ALOGE("recording callback: Couldn't allocate int array for configuration data");
return;
}
jint recParamData[6];
jint recParamData[REC_PARAM_SIZE];
recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
// FIXME this doesn't support index-based masks
recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
@@ -415,7 +418,8 @@ android_media_AudioSystem_recording_callback(int event, int session, int source,
// 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);
recParamData[6] = (jint) patchHandle;
env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
// callback into java
jclass clazz = env->FindClass(kClassPathName);

View File

@@ -897,6 +897,26 @@ public class AudioFormat implements Parcelable {
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AudioFormat that = (AudioFormat) o;
if (mPropertySetMask != that.mPropertySetMask) return false;
// return false if any of the properties is set and the values differ
return !((((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0)
&& (mEncoding != that.mEncoding))
|| (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE) != 0)
&& (mSampleRate != that.mSampleRate))
|| (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0)
&& (mChannelMask != that.mChannelMask))
|| (((mPropertySetMask & AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0)
&& (mChannelIndexMask != that.mChannelIndexMask)));
}
@Override
public int hashCode() {
return Objects.hash(mPropertySetMask, mSampleRate, mEncoding, mChannelMask,

View File

@@ -53,6 +53,13 @@ public class AudioPatch {
return mSinks;
}
/**
* Get the system unique patch ID.
*/
public int id() {
return mHandle.id();
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();

View File

@@ -18,7 +18,9 @@ package android.media;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import java.util.ArrayList;
import java.util.Objects;
/**
@@ -28,6 +30,7 @@ import java.util.Objects;
*
*/
public class AudioRecordConfiguration implements Parcelable {
private final static String TAG = new String("AudioRecordConfiguration");
private final int mSessionId;
@@ -36,30 +39,18 @@ public class AudioRecordConfiguration implements Parcelable {
private final AudioFormat mDeviceFormat;
private final AudioFormat mClientFormat;
private final AudioDeviceInfo mRecDevice;
/**
* @hide
*/
public AudioRecordConfiguration(int session, int source,
AudioFormat clientFormat, AudioFormat deviceFormat) {
mSessionId = session;
mClientSource = source;
mDeviceFormat = deviceFormat;
mClientFormat = clientFormat;
mRecDevice = null;
}
private final int mPatchHandle;
/**
* @hide
*/
public AudioRecordConfiguration(int session, int source, AudioFormat devFormat,
AudioFormat clientFormat, AudioDeviceInfo device) {
AudioFormat clientFormat, int patchHandle) {
mSessionId = session;
mClientSource = source;
mDeviceFormat = devFormat;
mClientFormat = clientFormat;
mRecDevice = device;
mPatchHandle = patchHandle;
}
/**
@@ -96,10 +87,38 @@ public class AudioRecordConfiguration implements Parcelable {
public AudioFormat getClientFormat() { return mClientFormat; }
/**
* Returns the audio input device used for this recording.
* @return the audio recording device
* Returns information about the audio input device used for this recording.
* @return the audio recording device or null if this information cannot be retrieved
*/
public AudioDeviceInfo getAudioDevice() { return mRecDevice; }
public AudioDeviceInfo getAudioDevice() {
// build the AudioDeviceInfo from the patch handle
ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>();
if (AudioManager.listAudioPatches(patches) != AudioManager.SUCCESS) {
Log.e(TAG, "Error retrieving list of audio patches");
return null;
}
for (int i = 0 ; i < patches.size() ; i++) {
final AudioPatch patch = patches.get(i);
if (patch.id() == mPatchHandle) {
final AudioPortConfig[] sources = patch.sources();
if ((sources != null) && (sources.length > 0)) {
// not supporting multiple sources, so just look at the first source
final int devId = sources[0].port().id();
final AudioDeviceInfo[] devices =
AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_INPUTS);
for (int j = 0; j < devices.length; j++) {
if (devices[j].getId() == devId) {
return devices[j];
}
}
}
// patch handle is unique, there won't be another with the same handle
break;
}
}
Log.e(TAG, "Couldn't find device for recording, did recording end already?");
return null;
}
public static final Parcelable.Creator<AudioRecordConfiguration> CREATOR
= new Parcelable.Creator<AudioRecordConfiguration>() {
@@ -132,7 +151,7 @@ public class AudioRecordConfiguration implements Parcelable {
dest.writeInt(mClientSource);
mClientFormat.writeToParcel(dest, 0);
mDeviceFormat.writeToParcel(dest, 0);
//TODO marshall device info
dest.writeInt(mPatchHandle);
}
private AudioRecordConfiguration(Parcel in) {
@@ -140,8 +159,7 @@ public class AudioRecordConfiguration implements Parcelable {
mClientSource = in.readInt();
mClientFormat = AudioFormat.CREATOR.createFromParcel(in);
mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in);
//TODO unmarshall device info
mRecDevice = null;
mPatchHandle = in.readInt();
}
@Override
@@ -149,8 +167,12 @@ public class AudioRecordConfiguration implements Parcelable {
if (this == o) return true;
if (o == null || !(o instanceof AudioRecordConfiguration)) return false;
final AudioRecordConfiguration that = (AudioRecordConfiguration) o;
return ((mSessionId == that.mSessionId)
&& (mClientSource == that.mClientSource));
AudioRecordConfiguration that = (AudioRecordConfiguration) o;
return ((mSessionId == that.mSessionId)
&& (mClientSource == that.mClientSource)
&& (mPatchHandle == that.mPatchHandle)
&& (mClientFormat.equals(that.mClientFormat))
&& (mDeviceFormat.equals(that.mDeviceFormat)));
}
}

View File

@@ -279,8 +279,14 @@ public class AudioSystem
* @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
* recording configurations (2*3 ints), followed by the patch handle:
* index 0: client format
* 1: client channel mask
* 2: client sample rate
* 3: device format
* 4: device channel mask
* 5: device sample rate
* 6: patch handle
*/
void onRecordingConfigurationChanged(int event, int session, int source,
int[] recordingFormat);

View File

@@ -50,11 +50,11 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
* Implementation of android.media.AudioSystem.AudioRecordingCallback
*/
public void onRecordingConfigurationChanged(int event, int session, int source,
int[] recordingFormat) {
int[] recordingInfo) {
if (MediaRecorder.isSystemOnlyAudioSource(source)) {
return;
}
if (updateSnapshot(event, session, source, recordingFormat)) {
if (updateSnapshot(event, session, source, recordingInfo)) {
final Iterator<RecMonitorClient> clientIterator = mClients.iterator();
synchronized(mClients) {
while (clientIterator.hasNext()) {
@@ -117,7 +117,7 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
* 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, int[] recordingFormat) {
private boolean updateSnapshot(int event, int session, int source, int[] recordingInfo) {
synchronized(mRecordConfigs) {
switch (event) {
case AudioManager.RECORD_CONFIG_EVENT_STOP:
@@ -125,26 +125,35 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
return (mRecordConfigs.remove(new Integer(session)) != null);
case AudioManager.RECORD_CONFIG_EVENT_START:
final AudioFormat clientFormat = new AudioFormat.Builder()
.setEncoding(recordingFormat[0])
.setEncoding(recordingInfo[0])
// FIXME this doesn't support index-based masks
.setChannelMask(recordingFormat[1])
.setSampleRate(recordingFormat[2])
.setChannelMask(recordingInfo[1])
.setSampleRate(recordingInfo[2])
.build();
final AudioFormat deviceFormat = new AudioFormat.Builder()
.setEncoding(recordingFormat[3])
.setEncoding(recordingInfo[3])
// FIXME this doesn't support index-based masks
.setChannelMask(recordingFormat[4])
.setSampleRate(recordingFormat[5])
.setChannelMask(recordingInfo[4])
.setSampleRate(recordingInfo[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
// format change during a recording that requires reporting
return false;
} else {
mRecordConfigs.put(new Integer(session),
final int patchHandle = recordingInfo[6];
final Integer sessionKey = new Integer(session);
if (mRecordConfigs.containsKey(sessionKey)) {
final AudioRecordConfiguration updatedConfig =
new AudioRecordConfiguration(session, source,
clientFormat, deviceFormat));
clientFormat, deviceFormat, patchHandle);
if (updatedConfig.equals(mRecordConfigs.get(sessionKey))) {
return false;
} else {
// config exists but has been modified
mRecordConfigs.remove(sessionKey);
mRecordConfigs.put(sessionKey, updatedConfig);
return true;
}
} else {
mRecordConfigs.put(sessionKey,
new AudioRecordConfiguration(session, source,
clientFormat, deviceFormat, patchHandle));
return true;
}
default: