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

Commit a011e35b authored by Eric Laurent's avatar Eric Laurent
Browse files

implemented synchronous audio capture

Added the infrastructure to support the synchronization of playback and
capture actions on specific events.
The first requirement for this feature is to synchronize the audio capture
start with the full rendering of a given audio content.
The applications can further be extended to other use cases
(synchronized playback start...) by adding new synchronization events and
new synchronous control methods on player or recorders.

Also added a method to query the audio session from a ToneGenerator.

Change-Id: I51f1167290d9cafdf2fbcdf9e4785156973af44c
parent b4c0c4b8
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <utils/threads.h>

#include <system/audio.h>
#include <media/AudioSystem.h>

namespace android {

@@ -215,8 +216,11 @@ public:

    /* After it's created the track is not active. Call start() to
     * make it active. If set, the callback will start being called.
     * if event is not AudioSystem::SYNC_EVENT_NONE, the capture start will be delayed until
     * the specified event occurs on the specified trigger session.
     */
            status_t    start();
            status_t    start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
                              int triggerSession = 0);

    /* Stop a track. If set, the callback will cease being called and
     * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+15 −0
Original line number Diff line number Diff line
@@ -145,6 +145,21 @@ public:
        uint32_t latency;
    };

    // Events used to synchronize actions between audio sessions.
    // For instance SYNC_EVENT_PRESENTATION_COMPLETE can be used to delay recording start until playback
    // is complete on another audio session.
    // See definitions in MediaSyncEvent.java
    enum sync_event_t {
        SYNC_EVENT_SAME = -1,             // used internally to indicate restart with same event
        SYNC_EVENT_NONE = 0,
        SYNC_EVENT_PRESENTATION_COMPLETE,

        //
        // Define new events here: SYNC_EVENT_START, SYNC_EVENT_STOP, SYNC_EVENT_TIME ...
        //
        SYNC_EVENT_CNT,
    };

    //
    // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
    //
+1 −2
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
#include <binder/IInterface.h>
#include <binder/IMemory.h>


namespace android {

// ----------------------------------------------------------------------------
@@ -39,7 +38,7 @@ public:
     * make it active. If set, the callback will start being called.
     * tid identifies the client callback thread, or 0 if not needed.
     */
    virtual status_t    start(pid_t tid) = 0;
    virtual status_t    start(pid_t tid, int event, int triggerSession) = 0;

    /* Stop a track. If set, the callback will cease being called and
     * obtainBuffer will return an error. Buffers that are already released
+3 −0
Original line number Diff line number Diff line
@@ -159,6 +159,9 @@ public:

    bool isInited() { return (mState == TONE_IDLE)?false:true;}

    // returns the audio session this ToneGenerator belongs to or 0 if an error occured.
    int getSessionId() { return (mpAudioTrack == NULL) ? 0 : mpAudioTrack->getSessionId(); }

private:

    enum tone_state {
+7 −5
Original line number Diff line number Diff line
@@ -279,12 +279,12 @@ audio_source_t AudioRecord::inputSource() const

// -------------------------------------------------------------------------

status_t AudioRecord::start()
status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
{
    status_t ret = NO_ERROR;
    sp<ClientRecordThread> t = mClientRecordThread;

    ALOGV("start");
    ALOGV("start, sync event %d trigger session %d", event, triggerSession);

    if (t != 0) {
        if (t->exitPending()) {
@@ -322,7 +322,7 @@ status_t AudioRecord::start()
        if (!(cblk->flags & CBLK_INVALID_MSK)) {
            cblk->lock.unlock();
            ALOGV("mAudioRecord->start(tid=%d)", tid);
            ret = mAudioRecord->start(tid);
            ret = mAudioRecord->start(tid, event, triggerSession);
            cblk->lock.lock();
            if (ret == DEAD_OBJECT) {
                android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -541,7 +541,8 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
                    ALOGW(   "obtainBuffer timed out (is the CPU pegged?) "
                            "user=%08x, server=%08x", cblk->user, cblk->server);
                    cblk->lock.unlock();
                    result = mAudioRecord->start(0);    // callback thread hasn't changed
                    // callback thread or sync event hasn't changed
                    result = mAudioRecord->start(0, AudioSystem::SYNC_EVENT_SAME, 0);
                    cblk->lock.lock();
                    if (result == DEAD_OBJECT) {
                        android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -779,7 +780,8 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
        result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
                mFrameCount, getInput_l());
        if (result == NO_ERROR) {
            result = mAudioRecord->start(0);    // callback thread hasn't changed
            // callback thread or sync event hasn't changed
            result = mAudioRecord->start(0, AudioSystem::SYNC_EVENT_SAME, 0);
        }
        if (result != NO_ERROR) {
            mActive = false;
Loading