AudioRecordingConfiguration: report more info about active use case
Report more information in onRecordingConfigChanged() callback and
AudioRecordingConfiguration:
- For client:
- Port ID (package private)
- Enabled effects
- Silenced by policy
- For stream:
- Active effects
- Active audio source
Bug: 111438757
Test: CTS tests for AudioRecordingConfiguration
Change-Id: I84952614ee5d9ede23afd5836c68da7a20e79a2e
This commit is contained in:
@@ -23455,10 +23455,14 @@ package android.media {
|
||||
public final class AudioRecordingConfiguration implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.media.AudioDeviceInfo getAudioDevice();
|
||||
method public int getAudioSource();
|
||||
method public int getClientAudioSessionId();
|
||||
method public int getClientAudioSource();
|
||||
method public java.util.List<android.media.audiofx.AudioEffect.Descriptor> getClientEffects();
|
||||
method public android.media.AudioFormat getClientFormat();
|
||||
method public java.util.List<android.media.audiofx.AudioEffect.Descriptor> getEffects();
|
||||
method public android.media.AudioFormat getFormat();
|
||||
method public boolean isClientSilenced();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.media.AudioRecordingConfiguration> CREATOR;
|
||||
}
|
||||
|
||||
@@ -639,6 +639,11 @@ package android.media {
|
||||
method public static boolean isEncodingLinearPcm(int);
|
||||
}
|
||||
|
||||
public final class AudioRecordingConfiguration implements android.os.Parcelable {
|
||||
ctor public AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, java.lang.String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]);
|
||||
ctor public AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, java.lang.String);
|
||||
}
|
||||
|
||||
public final class BufferingParams implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getInitialMarkMs();
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <nativehelper/ScopedLocalRef.h>
|
||||
#include <system/audio.h>
|
||||
#include <system/audio_policy.h>
|
||||
#include "android_media_AudioEffectDescriptor.h"
|
||||
#include "android_media_AudioFormat.h"
|
||||
#include "android_media_AudioErrors.h"
|
||||
#include "android_media_MicrophoneInfo.h"
|
||||
@@ -427,9 +428,14 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
|
||||
}
|
||||
|
||||
static void
|
||||
android_media_AudioSystem_recording_callback(int event, const record_client_info_t *clientInfo,
|
||||
const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
|
||||
audio_patch_handle_t patchHandle)
|
||||
android_media_AudioSystem_recording_callback(int event,
|
||||
const record_client_info_t *clientInfo,
|
||||
const audio_config_base_t *clientConfig,
|
||||
std::vector<effect_descriptor_t> clientEffects,
|
||||
const audio_config_base_t *deviceConfig,
|
||||
std::vector<effect_descriptor_t> effects __unused,
|
||||
audio_patch_handle_t patchHandle,
|
||||
audio_source_t source)
|
||||
{
|
||||
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
||||
if (env == NULL) {
|
||||
@@ -460,14 +466,24 @@ android_media_AudioSystem_recording_callback(int event, const record_client_info
|
||||
recParamData[6] = (jint) patchHandle;
|
||||
env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
|
||||
|
||||
jobjectArray jClientEffects;
|
||||
convertAudioEffectDescriptorVectorFromNative(env, &jClientEffects, clientEffects);
|
||||
|
||||
jobjectArray jEffects;
|
||||
convertAudioEffectDescriptorVectorFromNative(env, &jEffects, effects);
|
||||
|
||||
// callback into java
|
||||
jclass clazz = env->FindClass(kClassPathName);
|
||||
env->CallStaticVoidMethod(clazz,
|
||||
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
|
||||
event, (jint) clientInfo->uid, clientInfo->session, clientInfo->source, recParamArray);
|
||||
env->DeleteLocalRef(clazz);
|
||||
|
||||
env->CallStaticVoidMethod(clazz,
|
||||
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
|
||||
event, (jint) clientInfo->uid, clientInfo->session,
|
||||
clientInfo->source, clientInfo->port_id, clientInfo->silenced,
|
||||
recParamArray, jClientEffects, jEffects, source);
|
||||
env->DeleteLocalRef(clazz);
|
||||
env->DeleteLocalRef(recParamArray);
|
||||
env->DeleteLocalRef(jClientEffects);
|
||||
env->DeleteLocalRef(jEffects);
|
||||
}
|
||||
|
||||
static jint
|
||||
@@ -2260,7 +2276,7 @@ int register_android_media_AudioSystem(JNIEnv *env)
|
||||
"dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
|
||||
gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
|
||||
GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
|
||||
"recordingCallbackFromNative", "(IIII[I)V");
|
||||
"recordingCallbackFromNative", "(IIIIIZ[I[Landroid/media/audiofx/AudioEffect$Descriptor;[Landroid/media/audiofx/AudioEffect$Descriptor;I)V");
|
||||
|
||||
jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
|
||||
gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
|
||||
|
||||
@@ -18,7 +18,9 @@ package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.TestApi;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
@@ -27,6 +29,8 @@ import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -48,7 +52,7 @@ import java.util.Objects;
|
||||
public final class AudioRecordingConfiguration implements Parcelable {
|
||||
private final static String TAG = new String("AudioRecordingConfiguration");
|
||||
|
||||
private final int mSessionId;
|
||||
private final int mClientSessionId;
|
||||
|
||||
private final int mClientSource;
|
||||
|
||||
@@ -60,18 +64,50 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
|
||||
private final int mPatchHandle;
|
||||
|
||||
private final int mClientPortId;
|
||||
|
||||
private boolean mClientSilenced;
|
||||
|
||||
private final int mDeviceSource;
|
||||
|
||||
private final AudioEffect.Descriptor[] mClientEffects;
|
||||
|
||||
private final AudioEffect.Descriptor[] mDeviceEffects;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public AudioRecordingConfiguration(int uid, int session, int source, AudioFormat clientFormat,
|
||||
AudioFormat devFormat, int patchHandle, String packageName) {
|
||||
AudioFormat devFormat, int patchHandle, String packageName, int clientPortId,
|
||||
boolean clientSilenced, int deviceSource,
|
||||
AudioEffect.Descriptor[] clientEffects, AudioEffect.Descriptor[] deviceEffects) {
|
||||
mClientUid = uid;
|
||||
mSessionId = session;
|
||||
mClientSessionId = session;
|
||||
mClientSource = source;
|
||||
mClientFormat = clientFormat;
|
||||
mDeviceFormat = devFormat;
|
||||
mPatchHandle = patchHandle;
|
||||
mClientPackageName = packageName;
|
||||
mClientPortId = clientPortId;
|
||||
mClientSilenced = clientSilenced;
|
||||
mDeviceSource = deviceSource;
|
||||
mClientEffects = clientEffects;
|
||||
mDeviceEffects = deviceEffects;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public AudioRecordingConfiguration(int uid, int session, int source,
|
||||
AudioFormat clientFormat, AudioFormat devFormat,
|
||||
int patchHandle, String packageName) {
|
||||
this(uid, session, source, clientFormat,
|
||||
devFormat, patchHandle, packageName, 0 /*clientPortId*/,
|
||||
false /*clientSilenced*/, MediaRecorder.AudioSource.DEFAULT /*deviceSource*/,
|
||||
new AudioEffect.Descriptor[0] /*clientEffects*/,
|
||||
new AudioEffect.Descriptor[0] /*deviceEffects*/);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,13 +123,26 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
public static String toLogFriendlyString(AudioRecordingConfiguration arc) {
|
||||
return new String("session:" + arc.mSessionId
|
||||
+ " -- source:" + MediaRecorder.toLogFriendlyAudioSource(arc.mClientSource)
|
||||
String clientEffects = new String();
|
||||
for (AudioEffect.Descriptor desc : arc.mClientEffects) {
|
||||
clientEffects += "'" + desc.name + "' ";
|
||||
}
|
||||
String deviceEffects = new String();
|
||||
for (AudioEffect.Descriptor desc : arc.mDeviceEffects) {
|
||||
deviceEffects += "'" + desc.name + "' ";
|
||||
}
|
||||
|
||||
return new String("session:" + arc.mClientSessionId
|
||||
+ " -- source client=" + MediaRecorder.toLogFriendlyAudioSource(arc.mClientSource)
|
||||
+ ", dev=" + arc.mDeviceFormat.toLogFriendlyString()
|
||||
+ " -- uid:" + arc.mClientUid
|
||||
+ " -- patch:" + arc.mPatchHandle
|
||||
+ " -- pack:" + arc.mClientPackageName
|
||||
+ " -- format client=" + arc.mClientFormat.toLogFriendlyString()
|
||||
+ ", dev=" + arc.mDeviceFormat.toLogFriendlyString());
|
||||
+ ", dev=" + arc.mDeviceFormat.toLogFriendlyString()
|
||||
+ " -- silenced:" + arc.mClientSilenced
|
||||
+ " -- effects client=" + clientEffects
|
||||
+ ", dev=" + deviceEffects);
|
||||
}
|
||||
|
||||
// Note that this method is called server side, so no "privileged" information is ever sent
|
||||
@@ -106,8 +155,10 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
*/
|
||||
public static AudioRecordingConfiguration anonymizedCopy(AudioRecordingConfiguration in) {
|
||||
return new AudioRecordingConfiguration( /*anonymized uid*/ -1,
|
||||
in.mSessionId, in.mClientSource, in.mClientFormat,
|
||||
in.mDeviceFormat, in.mPatchHandle, "" /*empty package name*/);
|
||||
in.mClientSessionId, in.mClientSource, in.mClientFormat,
|
||||
in.mDeviceFormat, in.mPatchHandle, "" /*empty package name*/,
|
||||
in.mClientPortId, in.mClientSilenced, in.mDeviceSource, in.mClientEffects,
|
||||
in.mDeviceEffects);
|
||||
}
|
||||
|
||||
// matches the sources that return false in MediaRecorder.isSystemOnlyAudioSource(source)
|
||||
@@ -129,16 +180,8 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
// documented return values match the sources that return false
|
||||
// in MediaRecorder.isSystemOnlyAudioSource(source)
|
||||
/**
|
||||
* Returns the audio source being used for the recording.
|
||||
* @return one of {@link MediaRecorder.AudioSource#DEFAULT},
|
||||
* {@link MediaRecorder.AudioSource#MIC},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_UPLINK},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_DOWNLINK},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_CALL},
|
||||
* {@link MediaRecorder.AudioSource#CAMCORDER},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_RECOGNITION},
|
||||
* {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION},
|
||||
* {@link MediaRecorder.AudioSource#UNPROCESSED}.
|
||||
* Returns the audio source selected by the client.
|
||||
* @return the audio source selected by the client.
|
||||
*/
|
||||
public @AudioSource int getClientAudioSource() { return mClientSource; }
|
||||
|
||||
@@ -146,7 +189,9 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
* Returns the session number of the recording, see {@link AudioRecord#getAudioSessionId()}.
|
||||
* @return the session number.
|
||||
*/
|
||||
public int getClientAudioSessionId() { return mSessionId; }
|
||||
public int getClientAudioSessionId() {
|
||||
return mClientSessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the audio format at which audio is recorded on this Android device.
|
||||
@@ -223,6 +268,54 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the system unique ID assigned for the AudioRecord object corresponding to this
|
||||
* AudioRecordingConfiguration client.
|
||||
* @return the port ID.
|
||||
*/
|
||||
int getClientPortId() {
|
||||
return mClientPortId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the audio returned to the client is currently being silenced by the
|
||||
* audio framework due to concurrent capture policy (e.g the capturing application does not have
|
||||
* an active foreground process or service anymore).
|
||||
* @return true if captured audio is silenced, false otherwise .
|
||||
*/
|
||||
public boolean isClientSilenced() {
|
||||
return mClientSilenced;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the audio source currently used to configure the capture path. It can be different
|
||||
* from the source returned by {@link #getClientAudioSource()} if another capture is active.
|
||||
* @return the audio source active on the capture path.
|
||||
*/
|
||||
public @AudioSource int getAudioSource() {
|
||||
return mDeviceSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of {@link AudioEffect.Descriptor} for all effects currently enabled on
|
||||
* the audio capture client (e.g. {@link AudioRecord} or {@link MediaRecorder}).
|
||||
* @return List of {@link AudioEffect.Descriptor} containing all effects enabled for the client.
|
||||
*/
|
||||
public @NonNull List<AudioEffect.Descriptor> getClientEffects() {
|
||||
return new ArrayList<AudioEffect.Descriptor>(Arrays.asList(mClientEffects));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of {@link AudioEffect.Descriptor} for all effects currently enabled on
|
||||
* the capture stream.
|
||||
* @return List of {@link AudioEffect.Descriptor} containing all effects enabled on the
|
||||
* capture stream. This can be different from the list returned by {@link #getClientEffects()}
|
||||
* if another capture is active.
|
||||
*/
|
||||
public @NonNull List<AudioEffect.Descriptor> getEffects() {
|
||||
return new ArrayList<AudioEffect.Descriptor>(Arrays.asList(mDeviceEffects));
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<AudioRecordingConfiguration> CREATOR
|
||||
= new Parcelable.Creator<AudioRecordingConfiguration>() {
|
||||
/**
|
||||
@@ -240,7 +333,7 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mSessionId, mClientSource);
|
||||
return Objects.hash(mClientSessionId, mClientSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -250,23 +343,45 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mSessionId);
|
||||
dest.writeInt(mClientSessionId);
|
||||
dest.writeInt(mClientSource);
|
||||
mClientFormat.writeToParcel(dest, 0);
|
||||
mDeviceFormat.writeToParcel(dest, 0);
|
||||
dest.writeInt(mPatchHandle);
|
||||
dest.writeString(mClientPackageName);
|
||||
dest.writeInt(mClientUid);
|
||||
dest.writeInt(mClientPortId);
|
||||
dest.writeBoolean(mClientSilenced);
|
||||
dest.writeInt(mDeviceSource);
|
||||
dest.writeInt(mClientEffects.length);
|
||||
for (int i = 0; i < mClientEffects.length; i++) {
|
||||
mClientEffects[i].writeToParcel(dest, 0);
|
||||
}
|
||||
dest.writeInt(mDeviceEffects.length);
|
||||
for (int i = 0; i < mDeviceEffects.length; i++) {
|
||||
mDeviceEffects[i].writeToParcel(dest, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private AudioRecordingConfiguration(Parcel in) {
|
||||
mSessionId = in.readInt();
|
||||
mClientSessionId = in.readInt();
|
||||
mClientSource = in.readInt();
|
||||
mClientFormat = AudioFormat.CREATOR.createFromParcel(in);
|
||||
mDeviceFormat = AudioFormat.CREATOR.createFromParcel(in);
|
||||
mPatchHandle = in.readInt();
|
||||
mClientPackageName = in.readString();
|
||||
mClientUid = in.readInt();
|
||||
mClientPortId = in.readInt();
|
||||
mClientSilenced = in.readBoolean();
|
||||
mDeviceSource = in.readInt();
|
||||
mClientEffects = AudioEffect.Descriptor.CREATOR.newArray(in.readInt());
|
||||
for (int i = 0; i < mClientEffects.length; i++) {
|
||||
mClientEffects[i] = AudioEffect.Descriptor.CREATOR.createFromParcel(in);
|
||||
}
|
||||
mDeviceEffects = AudioEffect.Descriptor.CREATOR.newArray(in.readInt());
|
||||
for (int i = 0; i < mClientEffects.length; i++) {
|
||||
mDeviceEffects[i] = AudioEffect.Descriptor.CREATOR.createFromParcel(in);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -277,11 +392,16 @@ public final class AudioRecordingConfiguration implements Parcelable {
|
||||
AudioRecordingConfiguration that = (AudioRecordingConfiguration) o;
|
||||
|
||||
return ((mClientUid == that.mClientUid)
|
||||
&& (mSessionId == that.mSessionId)
|
||||
&& (mClientSessionId == that.mClientSessionId)
|
||||
&& (mClientSource == that.mClientSource)
|
||||
&& (mPatchHandle == that.mPatchHandle)
|
||||
&& (mClientFormat.equals(that.mClientFormat))
|
||||
&& (mDeviceFormat.equals(that.mDeviceFormat))
|
||||
&& (mClientPackageName.equals(that.mClientPackageName)));
|
||||
&& (mClientPackageName.equals(that.mClientPackageName))
|
||||
&& (mClientPortId == that.mClientPortId)
|
||||
&& (mClientSilenced == that.mClientSilenced)
|
||||
&& (mDeviceSource == that.mDeviceSource)
|
||||
&& (mClientEffects.equals(that.mClientEffects))
|
||||
&& (mDeviceEffects.equals(that.mDeviceEffects)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.media.audiopolicy.AudioMix;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
@@ -334,7 +335,9 @@ public class AudioSystem
|
||||
* @param packName package name of the client app performing the recording. NOT SUPPORTED
|
||||
*/
|
||||
void onRecordingConfigurationChanged(int event, int uid, int session, int source,
|
||||
int[] recordingFormat, String packName);
|
||||
int portId, boolean silenced, int[] recordingFormat,
|
||||
AudioEffect.Descriptor[] clienteffects, AudioEffect.Descriptor[] effects,
|
||||
int activeSource, String packName);
|
||||
}
|
||||
|
||||
private static AudioRecordingCallback sRecordingCallback;
|
||||
@@ -352,19 +355,27 @@ public class AudioSystem
|
||||
* @param session
|
||||
* @param source
|
||||
* @param recordingFormat see
|
||||
* {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int, int[])}
|
||||
* {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int, int,\
|
||||
boolean, int[], AudioEffect.Descriptor[], AudioEffect.Descriptor[], int, String)}
|
||||
* for the description of the record format.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
private static void recordingCallbackFromNative(int event, int uid, int session, int source,
|
||||
int[] recordingFormat) {
|
||||
int portId, boolean silenced, int[] recordingFormat,
|
||||
AudioEffect.Descriptor[] clientEffects, AudioEffect.Descriptor[] effects,
|
||||
int activeSource) {
|
||||
AudioRecordingCallback cb = null;
|
||||
synchronized (AudioSystem.class) {
|
||||
cb = sRecordingCallback;
|
||||
}
|
||||
|
||||
String clientEffectName = clientEffects.length == 0 ? "None" : clientEffects[0].name;
|
||||
String effectName = effects.length == 0 ? "None" : effects[0].name;
|
||||
|
||||
if (cb != null) {
|
||||
// TODO receive package name from native
|
||||
cb.onRecordingConfigurationChanged(event, uid, session, source, recordingFormat, "");
|
||||
cb.onRecordingConfigurationChanged(event, uid, session, source, portId, silenced,
|
||||
recordingFormat, clientEffects, effects, activeSource, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioFormat;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioPlaybackConfiguration;
|
||||
import android.media.AudioRecordingConfiguration;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.IRecordingConfigDispatcher;
|
||||
import android.media.MediaRecorder;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
@@ -64,12 +64,19 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
|
||||
* Implementation of android.media.AudioSystem.AudioRecordingCallback
|
||||
*/
|
||||
public void onRecordingConfigurationChanged(int event, int uid, int session, int source,
|
||||
int[] recordingInfo, String packName) {
|
||||
int portId, boolean silenced, int[] recordingInfo,
|
||||
AudioEffect.Descriptor[] clientEffects,
|
||||
AudioEffect.Descriptor[] effects,
|
||||
int activeSource, String packName) {
|
||||
if (MediaRecorder.isSystemOnlyAudioSource(source)) {
|
||||
return;
|
||||
}
|
||||
String clientEffectName = clientEffects.length == 0 ? "None" : clientEffects[0].name;
|
||||
String effectName = effects.length == 0 ? "None" : effects[0].name;
|
||||
|
||||
final List<AudioRecordingConfiguration> configsSystem =
|
||||
updateSnapshot(event, uid, session, source, recordingInfo);
|
||||
updateSnapshot(event, uid, session, source, recordingInfo,
|
||||
portId, silenced, activeSource, clientEffects, effects);
|
||||
if (configsSystem != null){
|
||||
synchronized (mClients) {
|
||||
// list of recording configurations for "public consumption". It is only computed if
|
||||
@@ -179,13 +186,20 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
|
||||
* @param session
|
||||
* @param source
|
||||
* @param recordingFormat see
|
||||
* {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int[])}
|
||||
* {@link AudioSystem.AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int,\
|
||||
int, int, boolean, int[], AudioEffect.Descriptor[], AudioEffect.Descriptor[], int, String)}
|
||||
* for the definition of the contents of the array
|
||||
* @param portId
|
||||
* @param silenced
|
||||
* @param activeSource
|
||||
* @param clientEffects
|
||||
* @param effects
|
||||
* @return null if the list of active recording sessions has not been modified, a list
|
||||
* with the current active configurations otherwise.
|
||||
*/
|
||||
private List<AudioRecordingConfiguration> updateSnapshot(int event, int uid, int session,
|
||||
int source, int[] recordingInfo) {
|
||||
int source, int[] recordingInfo, int portId, boolean silenced, int activeSource,
|
||||
AudioEffect.Descriptor[] clientEffects, AudioEffect.Descriptor[] effects) {
|
||||
final boolean configChanged;
|
||||
final ArrayList<AudioRecordingConfiguration> configs;
|
||||
synchronized(mRecordConfigs) {
|
||||
@@ -211,7 +225,7 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
|
||||
.setSampleRate(recordingInfo[5])
|
||||
.build();
|
||||
final int patchHandle = recordingInfo[6];
|
||||
final Integer sessionKey = new Integer(session);
|
||||
final Integer portIdKey = new Integer(portId);
|
||||
|
||||
final String[] packages = mPackMan.getPackagesForUid(uid);
|
||||
final String packageName;
|
||||
@@ -222,19 +236,20 @@ public final class RecordingActivityMonitor implements AudioSystem.AudioRecordin
|
||||
}
|
||||
final AudioRecordingConfiguration updatedConfig =
|
||||
new AudioRecordingConfiguration(uid, session, source,
|
||||
clientFormat, deviceFormat, patchHandle, packageName);
|
||||
clientFormat, deviceFormat, patchHandle, packageName,
|
||||
portId, silenced, activeSource, clientEffects, effects);
|
||||
|
||||
if (mRecordConfigs.containsKey(sessionKey)) {
|
||||
if (updatedConfig.equals(mRecordConfigs.get(sessionKey))) {
|
||||
if (mRecordConfigs.containsKey(portIdKey)) {
|
||||
if (updatedConfig.equals(mRecordConfigs.get(portIdKey))) {
|
||||
configChanged = false;
|
||||
} else {
|
||||
// config exists but has been modified
|
||||
mRecordConfigs.remove(sessionKey);
|
||||
mRecordConfigs.put(sessionKey, updatedConfig);
|
||||
mRecordConfigs.remove(portIdKey);
|
||||
mRecordConfigs.put(portIdKey, updatedConfig);
|
||||
configChanged = true;
|
||||
}
|
||||
} else {
|
||||
mRecordConfigs.put(sessionKey, updatedConfig);
|
||||
mRecordConfigs.put(portIdKey, updatedConfig);
|
||||
configChanged = true;
|
||||
}
|
||||
if (configChanged) {
|
||||
|
||||
Reference in New Issue
Block a user