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

Commit 3d00aa6d authored by Eric Laurent's avatar Eric Laurent
Browse files

soundpool: allocate shared memory heap by client

Current SoundPool implementation allocates the shared memory heap
containing decoded PCM samples in mediaserver process.
When mediaserver process crashes, the shared memory heaps allocated by
AudioCache cannot be mapped anymore in the new instance of mediaserver.
This causes a silent failure to end playback of new sounds because
AudioFlinger believes the new AudioTracks are opened in streaming mode
and not static mode: it sees a NULL shared memory pointer when the track
is created.

The fix consists in allocating the memory heap in the client process. Thus
the heap is not lost when mediaserver restarts. The global memory usage is
the same as this is shared memory.

Also added a way to detect that a shared memory is passed when the track is
created but cannot be mapped on mediaserver side.

Also fix a crash in SoundPool when ALOGV is enabled.

Bug: 10894793.
Change-Id: Ice6c66ec3b2a409d75dc903a508b6c6fbfb2e8a7
parent 402dfba6
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -49,8 +49,12 @@ public:
    virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;
    virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0;
    virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;
    virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;


    virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) = 0;
    virtual status_t         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels,
    virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat) = 0;
                                    audio_format_t* pFormat,
                                    const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
    virtual status_t         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
                                    int* pNumChannels, audio_format_t* pFormat,
                                    const sp<IMemoryHeap>& heap, size_t *pSize) = 0;
    virtual sp<IOMX>            getOMX() = 0;
    virtual sp<IOMX>            getOMX() = 0;
    virtual sp<ICrypto>         makeCrypto() = 0;
    virtual sp<ICrypto>         makeCrypto() = 0;
    virtual sp<IDrm>            makeDrm() = 0;
    virtual sp<IDrm>            makeDrm() = 0;
+3 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,8 @@
#include <utils/Vector.h>
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
#include <utils/KeyedVector.h>
#include <media/AudioTrack.h>
#include <media/AudioTrack.h>
#include <binder/MemoryHeapBase.h>
#include <binder/MemoryBase.h>


namespace android {
namespace android {


@@ -85,6 +87,7 @@ private:
    int64_t             mLength;
    int64_t             mLength;
    char*               mUrl;
    char*               mUrl;
    sp<IMemory>         mData;
    sp<IMemory>         mData;
    sp<MemoryHeapBase>  mHeap;
};
};


// stores pending events for stolen channels
// stores pending events for stolen channels
+6 −2
Original line number Original line Diff line number Diff line
@@ -223,8 +223,12 @@ public:
            bool            isLooping();
            bool            isLooping();
            status_t        setVolume(float leftVolume, float rightVolume);
            status_t        setVolume(float leftVolume, float rightVolume);
            void            notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
            void            notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
    static  sp<IMemory>     decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
    static  status_t        decode(const char* url, uint32_t *pSampleRate, int* pNumChannels,
    static  sp<IMemory>     decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
                                   audio_format_t* pFormat,
                                   const sp<IMemoryHeap>& heap, size_t *pSize);
    static  status_t        decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
                                   int* pNumChannels, audio_format_t* pFormat,
                                   const sp<IMemoryHeap>& heap, size_t *pSize);
            status_t        invoke(const Parcel& request, Parcel *reply);
            status_t        invoke(const Parcel& request, Parcel *reply);
            status_t        setMetadataFilter(const Parcel& filter);
            status_t        setMetadataFilter(const Parcel& filter);
            status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
            status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
+22 −5
Original line number Original line Diff line number Diff line
@@ -108,7 +108,12 @@ public:
        data.writeInt32(frameCount);
        data.writeInt32(frameCount);
        track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT;
        track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT;
        data.writeInt32(lFlags);
        data.writeInt32(lFlags);
        if (sharedBuffer != 0) {
            data.writeInt32(true);
            data.writeStrongBinder(sharedBuffer->asBinder());
            data.writeStrongBinder(sharedBuffer->asBinder());
        } else {
            data.writeInt32(false);
        }
        data.writeInt32((int32_t) output);
        data.writeInt32((int32_t) output);
        data.writeInt32((int32_t) tid);
        data.writeInt32((int32_t) tid);
        int lSessionId = 0;
        int lSessionId = 0;
@@ -738,15 +743,27 @@ status_t BnAudioFlinger::onTransact(
            audio_channel_mask_t channelMask = data.readInt32();
            audio_channel_mask_t channelMask = data.readInt32();
            size_t frameCount = data.readInt32();
            size_t frameCount = data.readInt32();
            track_flags_t flags = (track_flags_t) data.readInt32();
            track_flags_t flags = (track_flags_t) data.readInt32();
            sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
            bool haveSharedBuffer = data.readInt32() != 0;
            sp<IMemory> buffer;
            if (haveSharedBuffer) {
                buffer = interface_cast<IMemory>(data.readStrongBinder());
            }
            audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
            audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
            pid_t tid = (pid_t) data.readInt32();
            pid_t tid = (pid_t) data.readInt32();
            int sessionId = data.readInt32();
            int sessionId = data.readInt32();
            String8 name;
            String8 name;
            status_t status;
            status_t status;
            sp<IAudioTrack> track = createTrack(
            sp<IAudioTrack> track;
            if ((haveSharedBuffer && (buffer == 0)) ||
                    ((buffer != 0) && (buffer->pointer() == NULL))) {
                ALOGW("CREATE_TRACK: cannot retrieve shared memory");
                status = DEAD_OBJECT;
            } else {
                track = createTrack(
                        (audio_stream_type_t) streamType, sampleRate, format,
                        (audio_stream_type_t) streamType, sampleRate, format,
                    channelMask, frameCount, &flags, buffer, output, tid, &sessionId, name, &status);
                        channelMask, frameCount, &flags, buffer, output, tid,
                        &sessionId, name, &status);
            }
            reply->writeInt32(flags);
            reply->writeInt32(flags);
            reply->writeInt32(sessionId);
            reply->writeInt32(sessionId);
            reply->writeString8(name);
            reply->writeString8(name);
+51 −22
Original line number Original line Diff line number Diff line
@@ -86,30 +86,48 @@ public:
        return interface_cast<IMediaRecorder>(reply.readStrongBinder());
        return interface_cast<IMediaRecorder>(reply.readStrongBinder());
    }
    }


    virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
    virtual status_t decode(const char* url, uint32_t *pSampleRate, int* pNumChannels,
                               audio_format_t* pFormat,
                               const sp<IMemoryHeap>& heap, size_t *pSize)
    {
    {
        Parcel data, reply;
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        data.writeCString(url);
        data.writeCString(url);
        remote()->transact(DECODE_URL, data, &reply);
        data.writeStrongBinder(heap->asBinder());
        status_t status = remote()->transact(DECODE_URL, data, &reply);
        if (status == NO_ERROR) {
            status = (status_t)reply.readInt32();
            if (status == NO_ERROR) {
                *pSampleRate = uint32_t(reply.readInt32());
                *pSampleRate = uint32_t(reply.readInt32());
                *pNumChannels = reply.readInt32();
                *pNumChannels = reply.readInt32();
                *pFormat = (audio_format_t)reply.readInt32();
                *pFormat = (audio_format_t)reply.readInt32();
        return interface_cast<IMemory>(reply.readStrongBinder());
                *pSize = (size_t)reply.readInt32();
            }
        }
        return status;
    }
    }


    virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
    virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
                               int* pNumChannels, audio_format_t* pFormat,
                               const sp<IMemoryHeap>& heap, size_t *pSize)
    {
    {
        Parcel data, reply;
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
        data.writeFileDescriptor(fd);
        data.writeFileDescriptor(fd);
        data.writeInt64(offset);
        data.writeInt64(offset);
        data.writeInt64(length);
        data.writeInt64(length);
        remote()->transact(DECODE_FD, data, &reply);
        data.writeStrongBinder(heap->asBinder());
        status_t status = remote()->transact(DECODE_FD, data, &reply);
        if (status == NO_ERROR) {
            status = (status_t)reply.readInt32();
            if (status == NO_ERROR) {
                *pSampleRate = uint32_t(reply.readInt32());
                *pSampleRate = uint32_t(reply.readInt32());
                *pNumChannels = reply.readInt32();
                *pNumChannels = reply.readInt32();
                *pFormat = (audio_format_t)reply.readInt32();
                *pFormat = (audio_format_t)reply.readInt32();
        return interface_cast<IMemory>(reply.readStrongBinder());
                *pSize = (size_t)reply.readInt32();
            }
        }
        return status;
    }
    }


    virtual sp<IOMX> getOMX() {
    virtual sp<IOMX> getOMX() {
@@ -205,14 +223,19 @@ status_t BnMediaPlayerService::onTransact(
        case DECODE_URL: {
        case DECODE_URL: {
            CHECK_INTERFACE(IMediaPlayerService, data, reply);
            CHECK_INTERFACE(IMediaPlayerService, data, reply);
            const char* url = data.readCString();
            const char* url = data.readCString();
            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
            uint32_t sampleRate;
            uint32_t sampleRate;
            int numChannels;
            int numChannels;
            audio_format_t format;
            audio_format_t format;
            sp<IMemory> player = decode(url, &sampleRate, &numChannels, &format);
            size_t size;
            status_t status = decode(url, &sampleRate, &numChannels, &format, heap, &size);
            reply->writeInt32(status);
            if (status == NO_ERROR) {
                reply->writeInt32(sampleRate);
                reply->writeInt32(sampleRate);
                reply->writeInt32(numChannels);
                reply->writeInt32(numChannels);
                reply->writeInt32((int32_t)format);
                reply->writeInt32((int32_t)format);
            reply->writeStrongBinder(player->asBinder());
                reply->writeInt32((int32_t)size);
            }
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
        case DECODE_FD: {
        case DECODE_FD: {
@@ -220,14 +243,20 @@ status_t BnMediaPlayerService::onTransact(
            int fd = dup(data.readFileDescriptor());
            int fd = dup(data.readFileDescriptor());
            int64_t offset = data.readInt64();
            int64_t offset = data.readInt64();
            int64_t length = data.readInt64();
            int64_t length = data.readInt64();
            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
            uint32_t sampleRate;
            uint32_t sampleRate;
            int numChannels;
            int numChannels;
            audio_format_t format;
            audio_format_t format;
            sp<IMemory> player = decode(fd, offset, length, &sampleRate, &numChannels, &format);
            size_t size;
            status_t status = decode(fd, offset, length, &sampleRate, &numChannels, &format,
                                     heap, &size);
            reply->writeInt32(status);
            if (status == NO_ERROR) {
                reply->writeInt32(sampleRate);
                reply->writeInt32(sampleRate);
                reply->writeInt32(numChannels);
                reply->writeInt32(numChannels);
                reply->writeInt32((int32_t)format);
                reply->writeInt32((int32_t)format);
            reply->writeStrongBinder(player->asBinder());
                reply->writeInt32((int32_t)size);
            }
            return NO_ERROR;
            return NO_ERROR;
        } break;
        } break;
        case CREATE_MEDIA_RECORDER: {
        case CREATE_MEDIA_RECORDER: {
Loading