Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a00883db authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

AudioService: Track client app recording activity

Update RecordActivityMonitor to use events sent from clients
about their recording activity and coalesce them with
configuration update events sent from audioserver (APM). This
allows providing a high-level view on the recording
configurations consistent with client expectations.

For recorders that are managed entrirely on the server side
(AAudio MMAP) all events do contain configs. These recorders
do not have an associated death handler and need to be cleared
on audioserver restart.

Clearing client-managed trackers on audioserver restart is not
needed anymore. Clients will either continue
recording (AudioRecord handles IAudioRecord re-instantation) or
stop recording and notify AudioService about that.

Bug: 123312504
Test: android.media.cts.AudioRecordingConfigurationTest
      AudioRecordTest#testAudioRecordInfoCallback
      MediaRecorderTest#testAudioRecordInfoCallback
      manual testing using Oboe and Solo test apps

Change-Id: I4718f983c2d90e9c3e7480719a24bd187df7f80a
parent a23242a4
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"

#include <audiomanager/AudioManager.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
#include <media/MicrophoneInfo.h>
@@ -353,7 +354,15 @@ android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
static jint
android_media_AudioSystem_newAudioPlayerId(JNIEnv *env, jobject thiz)
{
    return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_PLAYER);
    int id = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_CLIENT);
    return id != AUDIO_UNIQUE_ID_ALLOCATE ? id : PLAYER_PIID_INVALID;
}

static jint
android_media_AudioSystem_newAudioRecorderId(JNIEnv *env, jobject thiz)
{
    int id = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_CLIENT);
    return id != AUDIO_UNIQUE_ID_ALLOCATE ? id : RECORD_RIID_INVALID;
}

static jint
@@ -470,9 +479,10 @@ android_media_AudioSystem_recording_callback(int event,

    env->CallStaticVoidMethod(clazz,
                              gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
                              event, (jint) clientInfo->uid, clientInfo->session,
                              clientInfo->source, clientInfo->port_id, clientInfo->silenced,
                              recParamArray, jClientEffects, jEffects, source);
                              event, (jint) clientInfo->riid, (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);
@@ -2246,6 +2256,7 @@ static const JNINativeMethod gMethods[] = {
    {"isSourceActive",      "(I)Z",     (void *)android_media_AudioSystem_isSourceActive},
    {"newAudioSessionId",   "()I",      (void *)android_media_AudioSystem_newAudioSessionId},
    {"newAudioPlayerId",    "()I",      (void *)android_media_AudioSystem_newAudioPlayerId},
    {"newAudioRecorderId",  "()I",      (void *)android_media_AudioSystem_newAudioRecorderId},
    {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;I)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
    {"getDeviceConnectionState", "(ILjava/lang/String;)I",  (void *)android_media_AudioSystem_getDeviceConnectionState},
    {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;I)I", (void *)android_media_AudioSystem_handleDeviceConfigChange},
@@ -2440,7 +2451,7 @@ int register_android_media_AudioSystem(JNIEnv *env)
                    "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
    gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
            GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
                    "recordingCallbackFromNative", "(IIIIIZ[I[Landroid/media/audiofx/AudioEffect$Descriptor;[Landroid/media/audiofx/AudioEffect$Descriptor;I)V");
                    "recordingCallbackFromNative", "(IIIIIIZ[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);
+17 −2
Original line number Diff line number Diff line
@@ -3766,9 +3766,24 @@ public class AudioManager {
     * with frameworks/av/include/media/AudioPolicy.h
     */
    /** @hide */
    public final static int RECORD_CONFIG_EVENT_START = 1;
    public static final int RECORD_CONFIG_EVENT_NONE = -1;
    /** @hide */
    public final static int RECORD_CONFIG_EVENT_STOP = 0;
    public static final int RECORD_CONFIG_EVENT_START = 0;
    /** @hide */
    public static final int RECORD_CONFIG_EVENT_STOP = 1;
    /** @hide */
    public static final int RECORD_CONFIG_EVENT_UPDATE = 2;
    /** @hide */
    public static final int RECORD_CONFIG_EVENT_DEATH = 3;
    /**
     * keep in sync with frameworks/native/include/audiomanager/AudioManager.h
     */
    /** @hide */
    public static final int RECORD_RIID_INVALID = -1;
    /** @hide */
    public static final int RECORDER_STATE_STARTED = 0;
    /** @hide */
    public static final int RECORDER_STATE_STOPPED = 1;

    /**
     * All operations on this list are sync'd on mRecordCallbackLock.
+3 −2
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ public final class AudioRecordingConfiguration implements Parcelable {
        return new AudioRecordingConfiguration( /*anonymized uid*/ -1,
                in.mClientSessionId, in.mClientSource, in.mClientFormat,
                in.mDeviceFormat, in.mPatchHandle, "" /*empty package name*/,
                in.mClientPortId, in.mClientSilenced, in.mDeviceSource, in.mClientEffects,
                /*anonymized portId*/ -1, in.mClientSilenced, in.mDeviceSource, in.mClientEffects,
                in.mDeviceEffects);
    }

@@ -270,11 +270,12 @@ public final class AudioRecordingConfiguration implements Parcelable {
    }

    /**
     * @hide
     * Returns the system unique ID assigned for the AudioRecord object corresponding to this
     * AudioRecordingConfiguration client.
     * @return the port ID.
     */
    int getClientPortId() {
    public int getClientPortId() {
        return mClientPortId;
    }

+19 −6
Original line number Diff line number Diff line
@@ -220,6 +220,11 @@ public class AudioSystem
     */
    public static native int newAudioPlayerId();

    /**
     * Returns a new unused audio recorder ID
     */
    public static native int newAudioRecorderId();


    /*
     * Sets a group generic audio configuration parameters. The use of these parameters
@@ -347,6 +352,7 @@ public class AudioSystem
        /**
         * Callback for recording activity notifications events
         * @param event
         * @param riid recording identifier
         * @param uid uid of the client app performing the recording
         * @param session
         * @param source
@@ -361,7 +367,7 @@ public class AudioSystem
         *          6: patch handle
         * @param packName package name of the client app performing the recording. NOT SUPPORTED
         */
        void onRecordingConfigurationChanged(int event, int uid, int session, int source,
        void onRecordingConfigurationChanged(int event, int riid, int uid, int session, int source,
                        int portId, boolean silenced, int[] recordingFormat,
                        AudioEffect.Descriptor[] clienteffects, AudioEffect.Descriptor[] effects,
                        int activeSource, String packName);
@@ -379,16 +385,23 @@ public class AudioSystem
    /**
     * Callback from native for recording configuration updates.
     * @param event
     * @param riid
     * @param uid
     * @param session
     * @param source
     * @param portId
     * @param silenced
     * @param recordingFormat see
     *     {@link AudioRecordingCallback#onRecordingConfigurationChanged(int, int, int, int, int, \
     boolean, int[], AudioEffect.Descriptor[], AudioEffect.Descriptor[], int, String)}
     int, boolean, int[], AudioEffect.Descriptor[], AudioEffect.Descriptor[], int, String)}
     *     for the description of the record format.
     * @param cleintEffects
     * @param effects
     * @param activeSource
     */
    @UnsupportedAppUsage
    private static void recordingCallbackFromNative(int event, int uid, int session, int source,
                          int portId, boolean silenced, int[] recordingFormat,
    private static void recordingCallbackFromNative(int event, int riid, int uid, int session,
                          int source, int portId, boolean silenced, int[] recordingFormat,
                          AudioEffect.Descriptor[] clientEffects, AudioEffect.Descriptor[] effects,
                          int activeSource) {
        AudioRecordingCallback cb = null;
@@ -401,7 +414,7 @@ public class AudioSystem

        if (cb != null) {
            // TODO receive package name from native
            cb.onRecordingConfigurationChanged(event, uid, session, source, portId, silenced,
            cb.onRecordingConfigurationChanged(event, riid, uid, session, source, portId, silenced,
                                        recordingFormat, clientEffects, effects, activeSource, "");
        }
    }
+4 −0
Original line number Diff line number Diff line
@@ -60,6 +60,10 @@ interface IAudioService {

    oneway void releasePlayer(in int piid);

    int trackRecorder(in IBinder recorder);

    oneway void recorderEvent(in int riid, in int event);

    // Java-only methods below.

    oneway void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
Loading