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

Commit d7ab7afa authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "Implement audio device callback" into mnc-dev

parents eb58c6d9 296fb13d
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -33,12 +33,31 @@ enum audio_io_config_event {
class AudioIoDescriptor : public RefBase {
public:
    AudioIoDescriptor() :
        mIoHandle(AUDIO_IO_HANDLE_NONE),
        mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE),
        mFrameCount(0), mLatency(0) {}
        mFrameCount(0), mLatency(0)
    {
        memset(&mPatch, 0, sizeof(struct audio_patch));
    }

    virtual ~AudioIoDescriptor() {}

    audio_port_handle_t getDeviceId() {
        if (mPatch.num_sources != 0 && mPatch.num_sinks != 0) {
            if (mPatch.sources[0].type == AUDIO_PORT_TYPE_MIX) {
                // this is an output mix
                // FIXME: the API only returns the first device in case of multiple device selection
                return mPatch.sinks[0].id;
            } else {
                // this is an input mix
                return mPatch.sources[0].id;
            }
        }
        return AUDIO_PORT_HANDLE_NONE;
    }

    audio_io_handle_t mIoHandle;
    struct audio_patch mPatch;
    uint32_t mSamplingRate;
    audio_format_t mFormat;
    audio_channel_mask_t mChannelMask;
+34 −0
Original line number Diff line number Diff line
@@ -394,6 +394,39 @@ public:
     * TODO Document this method.
     */
            audio_port_handle_t getInputDevice();

     /* Returns the ID of the audio device actually used by the input to which this AudioRecord
      * is attached.
      * A value of AUDIO_PORT_HANDLE_NONE indicates the AudioRecord is not attached to any input.
      *
      * Parameters:
      *  none.
      */
     audio_port_handle_t getRoutedDeviceId();

    /* Add an AudioDeviceCallback. The caller will be notified when the audio device
     * to which this AudioRecord is routed is updated.
     * Replaces any previously installed callback.
     * Parameters:
     *  callback:  The callback interface
     * Returns NO_ERROR if successful.
     *         INVALID_OPERATION if the same callback is already installed.
     *         NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable
     *         BAD_VALUE if the callback is NULL
     */
            status_t addAudioDeviceCallback(
                    const sp<AudioSystem::AudioDeviceCallback>& callback);

    /* remove an AudioDeviceCallback.
     * Parameters:
     *  callback:  The callback interface
     * Returns NO_ERROR if successful.
     *         INVALID_OPERATION if the callback is not installed
     *         BAD_VALUE if the callback is NULL
     */
            status_t removeAudioDeviceCallback(
                    const sp<AudioSystem::AudioDeviceCallback>& callback);

private:
    /* If nonContig is non-NULL, it is an output parameter that will be set to the number of
     * additional non-contiguous frames that are predicted to be available immediately,
@@ -588,6 +621,7 @@ private:
    // For Device Selection API
    //  a value of AUDIO_PORT_HANDLE_NONE indicated default (AudioPolicyManager) routing.
    audio_port_handle_t    mSelectedDeviceId;
    sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
};

}; // namespace android
+37 −6
Original line number Diff line number Diff line
@@ -332,8 +332,26 @@ public:

    };

    static status_t addAudioPortCallback(const sp<AudioPortCallback>& callBack);
    static status_t removeAudioPortCallback(const sp<AudioPortCallback>& callBack);
    static status_t addAudioPortCallback(const sp<AudioPortCallback>& callback);
    static status_t removeAudioPortCallback(const sp<AudioPortCallback>& callback);

    class AudioDeviceCallback : public RefBase
    {
    public:

                AudioDeviceCallback() {}
        virtual ~AudioDeviceCallback() {}

        virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo,
                                         audio_port_handle_t deviceId) = 0;
    };

    static status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
                                           audio_io_handle_t audioIo);
    static status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
                                              audio_io_handle_t audioIo);

    static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);

private:

@@ -359,10 +377,20 @@ private:
        // values for output/input parameters up-to-date in client process
        virtual void ioConfigChanged(audio_io_config_event event,
                                     const sp<AudioIoDescriptor>& ioDesc);


        status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
                                               audio_io_handle_t audioIo);
        status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback,
                                           audio_io_handle_t audioIo);

        audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo);

    private:
        Mutex                               mLock;
        DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> >   mIoDescriptors;

        DefaultKeyedVector<audio_io_handle_t, Vector < sp<AudioDeviceCallback> > >
                                                                        mAudioDeviceCallbacks;
        // cached values for recording getInputBufferSize() queries
        size_t                              mInBuffSize;    // zero indicates cache is invalid
        uint32_t                            mInSamplingRate;
@@ -377,8 +405,8 @@ private:
        AudioPolicyServiceClient() {
        }

        status_t addAudioPortCallback(const sp<AudioPortCallback>& callBack);
        status_t removeAudioPortCallback(const sp<AudioPortCallback>& callBack);
        status_t addAudioPortCallback(const sp<AudioPortCallback>& callback);
        status_t removeAudioPortCallback(const sp<AudioPortCallback>& callback);

        // DeathRecipient
        virtual void binderDied(const wp<IBinder>& who);
@@ -393,6 +421,9 @@ private:
        Vector <sp <AudioPortCallback> >    mAudioPortCallbacks;
    };

    static const sp<AudioFlingerClient> getAudioFlingerClient();
    static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle);

    static sp<AudioFlingerClient> gAudioFlingerClient;
    static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient;
    friend class AudioFlingerClient;
+34 −1
Original line number Diff line number Diff line
@@ -510,7 +510,7 @@ public:
     */
            status_t    setOutputDevice(audio_port_handle_t deviceId);

    /* Returns the ID of the audio device used for output of this AudioTrack.
    /* Returns the ID of the audio device selected for this AudioTrack.
     * A value of AUDIO_PORT_HANDLE_NONE indicates default (AudioPolicyManager) routing.
     *
     * Parameters:
@@ -518,6 +518,15 @@ public:
     */
     audio_port_handle_t getOutputDevice();

     /* Returns the ID of the audio device actually used by the output to which this AudioTrack is
      * attached.
      * A value of AUDIO_PORT_HANDLE_NONE indicates the audio track is not attached to any output.
      *
      * Parameters:
      *  none.
      */
     audio_port_handle_t getRoutedDeviceId();

    /* Returns the unique session ID associated with this track.
     *
     * Parameters:
@@ -664,6 +673,28 @@ public:
     */
            status_t    getTimestamp(AudioTimestamp& timestamp);

    /* Add an AudioDeviceCallback. The caller will be notified when the audio device to which this
     * AudioTrack is routed is updated.
     * Replaces any previously installed callback.
     * Parameters:
     *  callback:  The callback interface
     * Returns NO_ERROR if successful.
     *         INVALID_OPERATION if the same callback is already installed.
     *         NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable
     *         BAD_VALUE if the callback is NULL
     */
            status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);

    /* remove an AudioDeviceCallback.
     * Parameters:
     *  callback:  The callback interface
     * Returns NO_ERROR if successful.
     *         INVALID_OPERATION if the callback is not installed
     *         BAD_VALUE if the callback is NULL
     */
            status_t removeAudioDeviceCallback(
                    const sp<AudioSystem::AudioDeviceCallback>& callback);

protected:
    /* copying audio tracks is not allowed */
                        AudioTrack(const AudioTrack& other);
@@ -885,6 +916,8 @@ private:
    uint32_t                mSequence;              // incremented for each new IAudioTrack attempt
    int                     mClientUid;
    pid_t                   mClientPid;

    sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
};

class TimedAudioTrack : public AudioTrack
+70 −1
Original line number Diff line number Diff line
@@ -114,6 +114,10 @@ AudioRecord::~AudioRecord()
            mAudioRecordThread->requestExitAndWait();
            mAudioRecordThread.clear();
        }
        // No lock here: worst case we remove a NULL callback which will be a nop
        if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
        }
        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
        mAudioRecord.clear();
        mCblkMemory.clear();
@@ -304,6 +308,8 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
    mNewPosition = mProxy->getPosition() + mUpdatePeriod;
    int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);

    mActive = true;

    status_t status = NO_ERROR;
    if (!(flags & CBLK_INVALID)) {
        status = mAudioRecord->start(event, triggerSession);
@@ -316,9 +322,9 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
    }

    if (status != NO_ERROR) {
        mActive = false;
        ALOGE("start() status %d", status);
    } else {
        mActive = true;
        sp<AudioRecordThread> t = mAudioRecordThread;
        if (t != 0) {
            t->resume();
@@ -443,6 +449,11 @@ status_t AudioRecord::setInputDevice(audio_port_handle_t deviceId) {
    AutoMutex lock(mLock);
    if (mSelectedDeviceId != deviceId) {
        mSelectedDeviceId = deviceId;
        // stop capture so that audio policy manager does not reject the new instance start request
        // as only one capture can be active at a time.
        if (mAudioRecord != 0 && mActive) {
            mAudioRecord->stop();
        }
        android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
    }
    return NO_ERROR;
@@ -453,6 +464,14 @@ audio_port_handle_t AudioRecord::getInputDevice() {
    return mSelectedDeviceId;
}

audio_port_handle_t AudioRecord::getRoutedDeviceId() {
    AutoMutex lock(mLock);
    if (mInput == AUDIO_IO_HANDLE_NONE) {
        return AUDIO_PORT_HANDLE_NONE;
    }
    return AudioSystem::getDeviceIdForIo(mInput);
}

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

// must be called with mLock held
@@ -496,6 +515,10 @@ status_t AudioRecord::openRecord_l(size_t epoch, const String16& opPackageName)
        }
    }

    if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
    }

    audio_io_handle_t input;
    status_t status = AudioSystem::getInputForAttr(&mAttributes, &input,
                                        (audio_session_t)mSessionId,
@@ -628,6 +651,10 @@ status_t AudioRecord::openRecord_l(size_t epoch, const String16& opPackageName)
    mDeathNotifier = new DeathNotifier(this);
    IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);

    if (mDeviceCallback != 0) {
        AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput);
    }

    return NO_ERROR;
    }

@@ -1073,6 +1100,48 @@ status_t AudioRecord::restoreRecord_l(const char *from)
    return result;
}

status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
{
    if (callback == 0) {
        ALOGW("%s adding NULL callback!", __FUNCTION__);
        return BAD_VALUE;
    }
    AutoMutex lock(mLock);
    if (mDeviceCallback == callback) {
        ALOGW("%s adding same callback!", __FUNCTION__);
        return INVALID_OPERATION;
    }
    status_t status = NO_ERROR;
    if (mInput != AUDIO_IO_HANDLE_NONE) {
        if (mDeviceCallback != 0) {
            ALOGW("%s callback already present!", __FUNCTION__);
            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
        }
        status = AudioSystem::addAudioDeviceCallback(callback, mInput);
    }
    mDeviceCallback = callback;
    return status;
}

status_t AudioRecord::removeAudioDeviceCallback(
        const sp<AudioSystem::AudioDeviceCallback>& callback)
{
    if (callback == 0) {
        ALOGW("%s removing NULL callback!", __FUNCTION__);
        return BAD_VALUE;
    }
    AutoMutex lock(mLock);
    if (mDeviceCallback != callback) {
        ALOGW("%s removing different callback!", __FUNCTION__);
        return INVALID_OPERATION;
    }
    if (mInput != AUDIO_IO_HANDLE_NONE) {
        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
    }
    mDeviceCallback = 0;
    return NO_ERROR;
}

// =========================================================================

void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
Loading