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

Commit 8a21c019 authored by Pawin Vongmasa's avatar Pawin Vongmasa
Browse files

Modify ACodec to allow using Treble.

ACodec will connect to the Treble version of Omx if the property
"debug.treble_omx" is set to true ("1", "y", "yes", "true" or "on").

Also, fix some bugs found so far.

Test: Compiles
Bug: 31399200
Change-Id: I52b27b5f99bc1d6797d3b83b8be794ed2de9956a
parent 12eb3158
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -41,6 +41,14 @@ class MemoryDealer;
struct DescribeColorFormat2Params;
struct DataConverter;

// Treble shared memory
namespace hidl { namespace memory { namespace V1_0 {
struct IAllocator;
struct IMemory;
}}};
typedef hidl::memory::V1_0::IAllocator TAllocator;
typedef hidl::memory::V1_0::IMemory TMemory;

struct ACodec : public AHierarchicalStateMachine, public CodecBase {
    ACodec();

@@ -86,6 +94,12 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase {

    static status_t getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE map[]);

    // Read the flag from "media.use_treble_omx", save it locally, and return
    // it.
    bool updateTrebleFlag();
    // Return the saved flag.
    bool getTrebleFlag() const;

protected:
    virtual ~ACodec();

@@ -218,6 +232,8 @@ private:
    sp<IOMX> mOMX;
    sp<IOMXNode> mOMXNode;
    int32_t mNodeGeneration;
    bool mTrebleFlag;
    sp<TAllocator> mAllocator[2];
    sp<MemoryDealer> mDealer[2];

    bool mUsingNativeWindow;
+1 −1
Original line number Diff line number Diff line
@@ -166,7 +166,7 @@ OMXBuffer& OMXBuffer::operator=(OMXBuffer&& source) {
    mMem = std::move(source.mMem);
    mGraphicBuffer = std::move(source.mGraphicBuffer);
    mNativeHandle = std::move(source.mNativeHandle);
    mHidlMemory = source.mHidlMemory; // TODO(b/34093434): Use move when available
    mHidlMemory = std::move(source.mHidlMemory);
    return *this;
}

+152 −28
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
#include <media/hardware/HardwareAPI.h>
#include <media/OMXBuffer.h>

#include <hidlmemory/mapping.h>

#include <OMX_AudioExt.h>
#include <OMX_VideoExt.h>
#include <OMX_Component.h>
@@ -59,6 +61,10 @@
#include "include/SharedMemoryBuffer.h"
#include "omx/OMXUtils.h"

#include <android/hidl/memory/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include "omx/hal/1.0/utils/WOmxNode.h"

namespace android {

using binder::Status;
@@ -282,7 +288,9 @@ private:

////////////////////////////////////////////////////////////////////////////////

struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
struct ACodec::DeathNotifier :
        public IBinder::DeathRecipient,
        public ::android::hardware::hidl_death_recipient {
    explicit DeathNotifier(const sp<AMessage> &notify)
        : mNotify(notify) {
    }
@@ -291,6 +299,12 @@ struct ACodec::DeathNotifier : public IBinder::DeathRecipient {
        mNotify->post();
    }

    virtual void serviceDied(
            uint64_t /* cookie */,
            const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
        mNotify->post();
    }

protected:
    virtual ~DeathNotifier() {}

@@ -560,6 +574,8 @@ ACodec::ACodec()
    memset(&mLastNativeWindowCrop, 0, sizeof(mLastNativeWindowCrop));

    changeState(mUninitializedState);

    updateTrebleFlag();
}

ACodec::~ACodec() {
@@ -811,7 +827,11 @@ status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {
status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);

    if (getTrebleFlag()) {
        CHECK(mAllocator[portIndex] == NULL);
    } else {
        CHECK(mDealer[portIndex] == NULL);
    }
    CHECK(mBuffers[portIndex].isEmpty());

    status_t err;
@@ -874,14 +894,26 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
                return NO_MEMORY;
            }

            size_t totalSize = def.nBufferCountActual * (alignedSize + alignedConvSize);
            if (mode != IOMX::kPortModePresetSecureBuffer) {
                if (getTrebleFlag()) {
                    mAllocator[portIndex] = TAllocator::getService("ashmem");
                    if (mAllocator[portIndex] == nullptr) {
                        ALOGE("hidl allocator on port %d is null",
                                (int)portIndex);
                        return NO_MEMORY;
                    }
                } else {
                    size_t totalSize = def.nBufferCountActual *
                            (alignedSize + alignedConvSize);
                    mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
                }
            }

            const sp<AMessage> &format =
                    portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
            for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
                hidl_memory hidlMemToken;
                sp<TMemory> hidlMem;
                sp<IMemory> mem;

                BufferInfo info;
@@ -902,31 +934,87 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
                            ? new SecureBuffer(format, ptr, bufSize)
                            : new SecureBuffer(format, native_handle, bufSize);
                    info.mCodecData = info.mData;
                } else {
                    if (getTrebleFlag()) {
                        bool success;
                        auto transStatus = mAllocator[portIndex]->allocate(
                                bufSize,
                                [&success, &hidlMemToken](
                                        bool s,
                                        hidl_memory const& m) {
                                    success = s;
                                    hidlMemToken = m;
                                });

                        if (!transStatus.isOk()) {
                            ALOGE("hidl's AshmemAllocator failed at the "
                                    "transport: %s",
                                    transStatus.description().c_str());
                            return NO_MEMORY;
                        }
                        if (!success) {
                            return NO_MEMORY;
                        }
                        hidlMem = mapMemory(hidlMemToken);

                        err = mOMXNode->useBuffer(
                                portIndex, hidlMemToken, &info.mBufferID);
                    } else {
                        mem = mDealer[portIndex]->allocate(bufSize);
                        if (mem == NULL || mem->pointer() == NULL) {
                            return NO_MEMORY;
                        }

                    err = mOMXNode->useBuffer(portIndex, mem, &info.mBufferID);
                        err = mOMXNode->useBuffer(
                                portIndex, mem, &info.mBufferID);
                    }

                    if (mode == IOMX::kPortModeDynamicANWBuffer) {
                        ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
                        VideoNativeMetadata* metaData = (VideoNativeMetadata*)(
                                getTrebleFlag() ?
                                (void*)hidlMem->getPointer() : mem->pointer());
                        metaData->nFenceFd = -1;
                    }

                    info.mCodecData = new SharedMemoryBuffer(format, mem);
                    if (getTrebleFlag()) {
                        info.mCodecData = new SharedMemoryBuffer(
                                format, hidlMem);
                        info.mCodecRef = hidlMem;
                    } else {
                        info.mCodecData = new SharedMemoryBuffer(
                                format, mem);
                        info.mCodecRef = mem;
                    }

                    // if we require conversion, allocate conversion buffer for client use;
                    // otherwise, reuse codec buffer
                    if (mConverter[portIndex] != NULL) {
                        CHECK_GT(conversionBufferSize, (size_t)0);
                        mem = mDealer[portIndex]->allocate(conversionBufferSize);
                        if (getTrebleFlag()) {
                            bool success;
                            mAllocator[portIndex]->allocate(
                                    conversionBufferSize,
                                    [&success, &hidlMemToken](
                                            bool s,
                                            hidl_memory const& m) {
                                        success = s;
                                        hidlMemToken = m;
                                    });
                            if (!success) {
                                return NO_MEMORY;
                            }
                            hidlMem = mapMemory(hidlMemToken);
                            info.mData = new SharedMemoryBuffer(format, hidlMem);
                            info.mMemRef = hidlMem;
                        } else {
                            mem = mDealer[portIndex]->allocate(
                                    conversionBufferSize);
                            if (mem == NULL|| mem->pointer() == NULL) {
                                return NO_MEMORY;
                            }
                            info.mData = new SharedMemoryBuffer(format, mem);
                            info.mMemRef = mem;
                        }
                    } else {
                        info.mData = info.mCodecData;
                        info.mMemRef = info.mCodecRef;
@@ -1458,8 +1546,11 @@ status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
        }
    }

    // clear mDealer even on an error
    if (getTrebleFlag()) {
        mAllocator[portIndex].clear();
    } else {
        mDealer[portIndex].clear();
    }
    return err;
}

@@ -6041,9 +6132,17 @@ void ACodec::UninitializedState::stateEntered() {

    if (mDeathNotifier != NULL) {
        if (mCodec->mOMXNode != NULL) {
            if (mCodec->getTrebleFlag()) {
                auto tOmxNode =
                        (static_cast<
                        ::android::hardware::media::omx::V1_0::utils::
                        LWOmxNode*>(mCodec->mOMXNode.get()))->mBase;
                tOmxNode->unlinkToDeath(mDeathNotifier);
            } else {
                sp<IBinder> binder = IInterface::asBinder(mCodec->mOMXNode);
                binder->unlinkToDeath(mDeathNotifier);
            }
        }
        mDeathNotifier.clear();
    }

@@ -6130,7 +6229,8 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
    CHECK(mCodec->mOMXNode == NULL);

    OMXClient client;
    if (client.connect() != OK) {
    if ((mCodec->updateTrebleFlag() ?
            client.connectTreble() : client.connect()) != OK) {
        mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
        return false;
    }
@@ -6202,11 +6302,19 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
    }

    mDeathNotifier = new DeathNotifier(notify);
    if (mCodec->getTrebleFlag()) {
        auto tOmxNode = (static_cast<::android::hardware::media::omx::V1_0::
                utils::LWOmxNode*>(omxNode.get()))->mBase;
        if (!tOmxNode->linkToDeath(mDeathNotifier, 0)) {
            mDeathNotifier.clear();
        }
    } else {
        if (IInterface::asBinder(omxNode)->linkToDeath(mDeathNotifier) != OK) {
            // This was a local binder, if it dies so do we, we won't care
            // about any notifications in the afterlife.
            mDeathNotifier.clear();
        }
    }

    notify = new AMessage(kWhatOMXMessageList, mCodec);
    notify->setInt32("generation", ++mCodec->mNodeGeneration);
@@ -7180,9 +7288,13 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
                    ALOGE("disabled port should be empty, but has %zu buffers",
                            mCodec->mBuffers[kPortIndexOutput].size());
                    err = FAILED_TRANSACTION;
                } else {
                    if (mCodec->getTrebleFlag()) {
                        mCodec->mAllocator[kPortIndexOutput].clear();
                    } else {
                        mCodec->mDealer[kPortIndexOutput].clear();
                    }
                }

                if (err == OK) {
                    err = mCodec->mOMXNode->sendCommand(
@@ -7564,7 +7676,8 @@ status_t ACodec::queryCapabilities(
    }

    OMXClient client;
    status_t err = client.connect();
    status_t err = getTrebleFlag() ?
            client.connectTreble() : client.connect();
    if (err != OK) {
        return err;
    }
@@ -7780,4 +7893,15 @@ status_t ACodec::getOMXChannelMapping(size_t numChannels, OMX_AUDIO_CHANNELTYPE
    return OK;
}

bool ACodec::updateTrebleFlag() {
    mTrebleFlag = bool(property_get_bool("debug.treble_omx", 0));
    ALOGV("updateTrebleFlag() returns %s",
            mTrebleFlag ? "true" : "false");
    return mTrebleFlag;
}

bool ACodec::getTrebleFlag() const {
    return mTrebleFlag;
}

}  // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -114,6 +114,8 @@ LOCAL_SHARED_LIBRARIES += \
        libdl \
        libRScpp \
        libhidlbase \
        libhidlmemory \
        android.hidl.memory@1.0 \
        android.hardware.media.omx@1.0 \
        android.hardware.media.omx@1.0-utils \

+5 −0
Original line number Diff line number Diff line
@@ -34,6 +34,11 @@ SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<IMem
      mMemory(mem) {
}

SharedMemoryBuffer::SharedMemoryBuffer(const sp<AMessage> &format, const sp<TMemory> &mem)
    : MediaCodecBuffer(format, new ABuffer(mem->getPointer(), mem->getSize())),
      mTMemory(mem) {
}

SecureBuffer::SecureBuffer(const sp<AMessage> &format, const void *ptr, size_t size)
    : MediaCodecBuffer(format, new ABuffer(nullptr, size)),
      mPointer(ptr) {
Loading