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:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user