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

Commit d1fc3670 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "MediaCodec: realloc & copy for non-secure buffers at secure session &...

Merge "MediaCodec: realloc & copy for non-secure buffers at secure session & vice versa" into tm-dev am: 17634b9b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18578433



Change-Id: Idf4d9bfbd4324a0fe74b3728d80249f46a94b4ef
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 8468834d 17634b9b
Loading
Loading
Loading
Loading
+110 −32
Original line number Diff line number Diff line
@@ -730,6 +730,7 @@ status_t JMediaCodec::getOutputFrame(
            switch (c2Buffer->data().type()) {
                case C2BufferData::LINEAR: {
                    std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
                    context->mCodecNames.push_back(mNameAtCreation.c_str());
                    context->mBuffer = c2Buffer;
                    ScopedLocalRef<jobject> linearBlock{env, env->NewObject(
                            gLinearBlockInfo.clazz, gLinearBlockInfo.ctorId)};
@@ -769,6 +770,7 @@ status_t JMediaCodec::getOutputFrame(
        } else {
            if (!mGraphicOutput) {
                std::unique_ptr<JMediaCodecLinearBlock> context{new JMediaCodecLinearBlock};
                context->mCodecNames.push_back(mNameAtCreation.c_str());
                context->mLegacyBuffer = buffer;
                ScopedLocalRef<jobject> linearBlock{env, env->NewObject(
                        gLinearBlockInfo.clazz, gLinearBlockInfo.ctorId)};
@@ -812,7 +814,6 @@ status_t JMediaCodec::getOutputFrame(
    return OK;
}


status_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
    AString name;

@@ -2286,6 +2287,108 @@ static status_t ConvertKeyValueListsToAMessage(
    return OK;
}

static bool obtain(
        JMediaCodecLinearBlock *context,
        int capacity,
        const std::vector<std::string> &names,
        bool secure) {
    if (secure) {
        // Start at 1MB, which is an arbitrary starting point that can
        // increase when needed.
        constexpr size_t kInitialDealerCapacity = 1048576;
        thread_local sp<MemoryDealer> sDealer = new MemoryDealer(
                kInitialDealerCapacity, "JNI(1MB)");
        context->mMemory = sDealer->allocate(capacity);
        if (context->mMemory == nullptr) {
            size_t newDealerCapacity = sDealer->getMemoryHeap()->getSize() * 2;
            while (capacity * 2 > newDealerCapacity) {
                newDealerCapacity *= 2;
            }
            ALOGI("LinearBlock.native_obtain: "
                  "Dealer capacity increasing from %zuMB to %zuMB",
                  sDealer->getMemoryHeap()->getSize() / 1048576,
                  newDealerCapacity / 1048576);
            sDealer = new MemoryDealer(
                    newDealerCapacity,
                    AStringPrintf("JNI(%zuMB)", newDealerCapacity).c_str());
            context->mMemory = sDealer->allocate(capacity);
        }
        context->mHidlMemory = hardware::fromHeap(context->mMemory->getMemory(
                    &context->mHidlMemoryOffset, &context->mHidlMemorySize));
    } else {
        context->mBlock = MediaCodec::FetchLinearBlock(capacity, names);
        if (!context->mBlock) {
            return false;
        }
    }
    context->mCodecNames = names;
    return true;
}

static void extractMemoryFromContext(
        JMediaCodecLinearBlock *context,
        jint offset,
        jint size,
        sp<hardware::HidlMemory> *memory) {
    *memory = context->toHidlMemory();
    if (*memory == nullptr) {
        if (!context->mBlock) {
            ALOGW("extractMemoryFromContext: the buffer is missing both IMemory and C2Block");
            return;
        }
        ALOGD("extractMemoryFromContext: realloc & copying from C2Block to IMemory (cap=%zu)",
              context->capacity());
        if (!obtain(context, context->capacity(),
                    context->mCodecNames, true /* secure */)) {
            ALOGW("extractMemoryFromContext: failed to obtain secure block");
            return;
        }
        C2WriteView view = context->mBlock->map().get();
        if (view.error() != C2_OK) {
            ALOGW("extractMemoryFromContext: failed to map C2Block (%d)", view.error());
            return;
        }
        uint8_t *memoryPtr = static_cast<uint8_t *>(context->mMemory->unsecurePointer());
        memcpy(memoryPtr + offset, view.base() + offset, size);
        context->mBlock.reset();
        context->mReadWriteMapping.reset();
        *memory = context->toHidlMemory();
    }
}

static void extractBufferFromContext(
        JMediaCodecLinearBlock *context,
        jint offset,
        jint size,
        std::shared_ptr<C2Buffer> *buffer) {
    *buffer = context->toC2Buffer(offset, size);
    if (*buffer == nullptr) {
        if (!context->mMemory) {
            ALOGW("extractBufferFromContext: the buffer is missing both IMemory and C2Block");
            return;
        }
        ALOGD("extractBufferFromContext: realloc & copying from IMemory to C2Block (cap=%zu)",
              context->capacity());
        if (obtain(context, context->capacity(),
                   context->mCodecNames, false /* secure */)) {
            ALOGW("extractBufferFromContext: failed to obtain non-secure block");
            return;
        }
        C2WriteView view = context->mBlock->map().get();
        if (view.error() != C2_OK) {
            ALOGW("extractBufferFromContext: failed to map C2Block (%d)", view.error());
            return;
        }
        uint8_t *memoryPtr = static_cast<uint8_t *>(context->mMemory->unsecurePointer());
        memcpy(view.base() + offset, memoryPtr + offset, size);
        context->mMemory.clear();
        context->mHidlMemory.clear();
        context->mHidlMemorySize = 0;
        context->mHidlMemoryOffset = 0;
        *buffer = context->toC2Buffer(offset, size);
    }
}

static void android_media_MediaCodec_native_queueLinearBlock(
        JNIEnv *env, jobject thiz, jint index, jobject bufferObj,
        jint offset, jint size, jobject cryptoInfoObj,
@@ -2314,12 +2417,10 @@ static void android_media_MediaCodec_native_queueLinearBlock(
            JMediaCodecLinearBlock *context =
                (JMediaCodecLinearBlock *)env->GetLongField(bufferObj, gLinearBlockInfo.contextId);
            if (codec->hasCryptoOrDescrambler()) {
                memory = context->toHidlMemory();
                // TODO: copy if memory is null
                extractMemoryFromContext(context, offset, size, &memory);
                offset += context->mHidlMemoryOffset;
            } else {
                buffer = context->toC2Buffer(offset, size);
                // TODO: copy if buffer is null
                extractBufferFromContext(context, offset, size, &buffer);
            }
        }
        env->MonitorExit(lock.get());
@@ -2354,6 +2455,7 @@ static void android_media_MediaCodec_native_queueLinearBlock(
                flags,
                tunings,
                &errorDetailMsg);
        ALOGI_IF(err != OK, "queueEncryptedLinearBlock returned err = %d", err);
    } else {
        if (!buffer) {
            ALOGI("queueLinearBlock: no C2Buffer found");
@@ -3300,34 +3402,10 @@ static void android_media_MediaCodec_LinearBlock_native_obtain(
            hasNonSecure = true;
        }
    }
    if (hasSecure && !hasNonSecure) {
        constexpr size_t kInitialDealerCapacity = 1048576;  // 1MB
        thread_local sp<MemoryDealer> sDealer = new MemoryDealer(
                kInitialDealerCapacity, "JNI(1MB)");
        context->mMemory = sDealer->allocate(capacity);
        if (context->mMemory == nullptr) {
            size_t newDealerCapacity = sDealer->getMemoryHeap()->getSize() * 2;
            while (capacity * 2 > newDealerCapacity) {
                newDealerCapacity *= 2;
            }
            ALOGI("LinearBlock.native_obtain: "
                  "Dealer capacity increasing from %zuMB to %zuMB",
                  sDealer->getMemoryHeap()->getSize() / 1048576,
                  newDealerCapacity / 1048576);
            sDealer = new MemoryDealer(
                    newDealerCapacity,
                    AStringPrintf("JNI(%zuMB)", newDealerCapacity).c_str());
            context->mMemory = sDealer->allocate(capacity);
        }
        context->mHidlMemory = hardware::fromHeap(context->mMemory->getMemory(
                    &context->mHidlMemoryOffset, &context->mHidlMemorySize));
    } else {
        context->mBlock = MediaCodec::FetchLinearBlock(capacity, names);
        if (!context->mBlock) {
    if (!obtain(context.get(), capacity, names, (hasSecure && !hasNonSecure) /* secure */)) {
        jniThrowException(env, "java/io/IOException", nullptr);
        return;
    }
    }
    env->CallVoidMethod(
            thiz,
            gLinearBlockInfo.setInternalStateId,
+14 −2
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
namespace android {

struct JMediaCodecLinearBlock {
    std::vector<std::string> mCodecNames;

    std::shared_ptr<C2Buffer> mBuffer;
    std::shared_ptr<C2ReadView> mReadonlyMapping;

@@ -40,7 +42,7 @@ struct JMediaCodecLinearBlock {

    std::once_flag mCopyWarningFlag;

    std::shared_ptr<C2Buffer> toC2Buffer(size_t offset, size_t size) {
    std::shared_ptr<C2Buffer> toC2Buffer(size_t offset, size_t size) const {
        if (mBuffer) {
            if (mBuffer->data().type() != C2BufferData::LINEAR) {
                return nullptr;
@@ -64,12 +66,22 @@ struct JMediaCodecLinearBlock {
        return nullptr;
    }

    sp<hardware::HidlMemory> toHidlMemory() {
    sp<hardware::HidlMemory> toHidlMemory() const {
        if (mHidlMemory) {
            return mHidlMemory;
        }
        return nullptr;
    }

    size_t capacity() const {
        if (mBlock) {
            return mBlock->capacity();
        }
        if (mMemory) {
            return mMemory->size();
        }
        return 0;
    }
};

}  // namespace android