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

Commit 35ec76ef authored by Kyle Zhang's avatar Kyle Zhang Committed by Android (Google) Code Review
Browse files

Merge "Add aidl interface support for Drm Framework"

parents 064ca69f 6605add7
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -28,7 +28,11 @@ cc_library {
        "DrmSessionManager.cpp",
        "DrmSessionManager.cpp",
        "SharedLibrary.cpp",
        "SharedLibrary.cpp",
        "DrmHal.cpp",
        "DrmHal.cpp",
        "DrmHalHidl.cpp",
        "DrmHalAidl.cpp",
        "CryptoHal.cpp",
        "CryptoHal.cpp",
        "CryptoHalHidl.cpp",
        "CryptoHalAidl.cpp",
        "DrmUtils.cpp",
        "DrmUtils.cpp",
    ],
    ],


@@ -63,10 +67,12 @@ cc_library {
        "android.hardware.drm@1.4",
        "android.hardware.drm@1.4",
        "libhidlallocatorutils",
        "libhidlallocatorutils",
        "libhidlbase",
        "libhidlbase",
        "android.hardware.drm-V1-ndk",
    ],
    ],


    static_libs: [
    static_libs: [
        "resourcemanager_aidl_interface-ndk",
        "resourcemanager_aidl_interface-ndk",
        "libaidlcommonsupport",
    ],
    ],


    export_shared_lib_headers: [
    export_shared_lib_headers: [
+59 −348
Original line number Original line Diff line number Diff line
@@ -16,389 +16,100 @@


//#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0
#define LOG_TAG "CryptoHal"
#define LOG_TAG "CryptoHal"
#include <utils/Log.h>

#include <android/hardware/drm/1.0/types.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <hidl/ServiceManagement.h>
#include <hidlmemory/FrameworkUtils.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
#include <mediadrm/CryptoHal.h>
#include <mediadrm/CryptoHal.h>
#include <mediadrm/CryptoHalHidl.h>
#include <mediadrm/CryptoHalAidl.h>
#include <mediadrm/DrmUtils.h>
#include <mediadrm/DrmUtils.h>


using drm::V1_0::BufferType;
using drm::V1_0::DestinationBuffer;
using drm::V1_0::ICryptoFactory;
using drm::V1_0::ICryptoPlugin;
using drm::V1_0::Mode;
using drm::V1_0::Pattern;
using drm::V1_0::SharedBuffer;
using drm::V1_0::Status;
using drm::V1_0::SubSample;

using ::android::DrmUtils::toStatusT;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::HidlMemory;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

typedef drm::V1_2::Status Status_V1_2;

namespace android {
namespace android {


static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
CryptoHal::CryptoHal() {
    hidl_vec<uint8_t> vec;
    mCryptoHalAidl = sp<CryptoHalAidl>::make();
    vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
    mCryptoHalHidl = sp<CryptoHalHidl>::make();
    return vec;
}

static hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) {
    hidl_vec<uint8_t> vec;
    vec.resize(size);
    memcpy(vec.data(), ptr, size);
    return vec;
}

static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) {
    if (!ptr) {
        return hidl_array<uint8_t, 16>();
    }
    return hidl_array<uint8_t, 16>(ptr);
}


static String8 toString8(hidl_string hString) {
    return String8(hString.c_str());
}


CryptoHal::CryptoHal()
    : mFactories(makeCryptoFactories()),
      mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT),
      mHeapSeqNum(0) {
}

CryptoHal::~CryptoHal() {
}

Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() {
    Vector<sp<ICryptoFactory>> factories;

    auto manager = hardware::defaultServiceManager1_2();
    if (manager != NULL) {
        manager->listManifestByInterface(drm::V1_0::ICryptoFactory::descriptor,
                [&factories](const hidl_vec<hidl_string> &registered) {
                    for (const auto &instance : registered) {
                        auto factory = drm::V1_0::ICryptoFactory::getService(instance);
                        if (factory != NULL) {
                            ALOGD("found drm@1.0 ICryptoFactory %s", instance.c_str());
                            factories.push_back(factory);
                        }
                    }
                }
            );
        manager->listManifestByInterface(drm::V1_1::ICryptoFactory::descriptor,
                [&factories](const hidl_vec<hidl_string> &registered) {
                    for (const auto &instance : registered) {
                        auto factory = drm::V1_1::ICryptoFactory::getService(instance);
                        if (factory != NULL) {
                            ALOGD("found drm@1.1 ICryptoFactory %s", instance.c_str());
                            factories.push_back(factory);
                        }
                    }
                }
            );
    }

    if (factories.size() == 0) {
        // must be in passthrough mode, load the default passthrough service
        auto passthrough = ICryptoFactory::getService();
        if (passthrough != NULL) {
            ALOGI("makeCryptoFactories: using default passthrough crypto instance");
            factories.push_back(passthrough);
        } else {
            ALOGE("Failed to find any crypto factories");
        }
    }
    return factories;
}

sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const sp<ICryptoFactory>& factory,
        const uint8_t uuid[16], const void *initData, size_t initDataSize) {

    sp<ICryptoPlugin> plugin;
    Return<void> hResult = factory->createPlugin(toHidlArray16(uuid),
            toHidlVec(initData, initDataSize),
            [&](Status status, const sp<ICryptoPlugin>& hPlugin) {
                if (status != Status::OK) {
                    ALOGE("Failed to make crypto plugin");
                    return;
                }
                plugin = hPlugin;
            }
        );
    if (!hResult.isOk()) {
        mInitCheck = DEAD_OBJECT;
    }
    return plugin;
}
}


CryptoHal::~CryptoHal() {}


status_t CryptoHal::initCheck() const {
status_t CryptoHal::initCheck() const {
    return mInitCheck;
    if (mCryptoHalAidl->initCheck() == OK || mCryptoHalHidl->initCheck() == OK) return OK;
    if (mCryptoHalAidl->initCheck() == NO_INIT || mCryptoHalHidl->initCheck() == NO_INIT)
        return NO_INIT;
    return mCryptoHalHidl->initCheck();
}
}



bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) {
bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) {
    Mutex::Autolock autoLock(mLock);
    return mCryptoHalAidl->isCryptoSchemeSupported(uuid) ||

           mCryptoHalHidl->isCryptoSchemeSupported(uuid);
    for (size_t i = 0; i < mFactories.size(); i++) {
        if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
            return true;
        }
    }
    return false;
}
}


status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data,
status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void* data, size_t size) {
        size_t size) {
    if (mCryptoHalAidl->createPlugin(uuid, data, size) != OK)
    Mutex::Autolock autoLock(mLock);
        return mCryptoHalHidl->createPlugin(uuid, data, size);

    return OK;
    for (size_t i = 0; i < mFactories.size(); i++) {
        if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
            mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size);
            if (mPlugin != NULL) {
                mPluginV1_2 = drm::V1_2::ICryptoPlugin::castFrom(mPlugin);
            }
        }
    }

    if (mInitCheck == NO_INIT) {
        mInitCheck = mPlugin == NULL ? ERROR_UNSUPPORTED : OK;
    }

    return mInitCheck;
}
}


status_t CryptoHal::destroyPlugin() {
status_t CryptoHal::destroyPlugin() {
    Mutex::Autolock autoLock(mLock);
    // This requires plugin to be created.

    if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->destroyPlugin();
    if (mInitCheck != OK) {
    return mCryptoHalHidl->destroyPlugin();
        return mInitCheck;
    }

    mPlugin.clear();
    mPluginV1_2.clear();
    return OK;
}
}


bool CryptoHal::requiresSecureDecoderComponent(const char* mime) const {
bool CryptoHal::requiresSecureDecoderComponent(const char* mime) const {
    Mutex::Autolock autoLock(mLock);
    // This requires plugin to be created.

    if (mCryptoHalAidl->initCheck() == OK)
    if (mInitCheck != OK) {
        return mCryptoHalAidl->requiresSecureDecoderComponent(mime);
        return false;
    return mCryptoHalHidl->requiresSecureDecoderComponent(mime);
    }

    Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime));
    if (!hResult.isOk()) {
        return false;
    }
    return hResult;
}


/**
 * If the heap base isn't set, get the heap base from the HidlMemory
 * and send it to the HAL so it can map a remote heap of the same
 * size.  Once the heap base is established, shared memory buffers
 * are sent by providing an offset into the heap and a buffer size.
 */
int32_t CryptoHal::setHeapBase(const sp<HidlMemory>& heap) {
    if (heap == NULL || mHeapSeqNum < 0) {
        ALOGE("setHeapBase(): heap %p mHeapSeqNum %d", heap.get(), mHeapSeqNum);
        return -1;
    }

    Mutex::Autolock autoLock(mLock);

    int32_t seqNum = mHeapSeqNum++;
    uint32_t bufferId = static_cast<uint32_t>(seqNum);
    mHeapSizes.add(seqNum, heap->size());
    Return<void> hResult = mPlugin->setSharedBufferBase(*heap, bufferId);
    ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
    return seqNum;
}

void CryptoHal::clearHeapBase(int32_t seqNum) {
    Mutex::Autolock autoLock(mLock);

    /*
     * Clear the remote shared memory mapping by setting the shared
     * buffer base to a null hidl_memory.
     *
     * TODO: Add a releaseSharedBuffer method in a future DRM HAL
     * API version to make this explicit.
     */
    ssize_t index = mHeapSizes.indexOfKey(seqNum);
    if (index >= 0) {
        if (mPlugin != NULL) {
            uint32_t bufferId = static_cast<uint32_t>(seqNum);
            Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId);
            ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed");
        }
        mHeapSizes.removeItem(seqNum);
    }
}

status_t CryptoHal::checkSharedBuffer(const ::SharedBuffer &buffer) {
    int32_t seqNum = static_cast<int32_t>(buffer.bufferId);
    // memory must be in one of the heaps that have been set
    if (mHeapSizes.indexOfKey(seqNum) < 0) {
        return UNKNOWN_ERROR;
    }

    // memory must be within the address space of the heap
    size_t heapSize = mHeapSizes.valueFor(seqNum);
    if (heapSize < buffer.offset + buffer.size ||
            SIZE_MAX - buffer.offset < buffer.size) {
        android_errorWriteLog(0x534e4554, "76221123");
        return UNKNOWN_ERROR;
    }

    return OK;
}

ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
        CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
        const ::SharedBuffer &hSource, size_t offset,
        const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
        const ::DestinationBuffer &hDestination, AString *errorDetailMsg) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    Mode hMode;
    switch(mode) {
    case CryptoPlugin::kMode_Unencrypted:
        hMode = Mode::UNENCRYPTED ;
        break;
    case CryptoPlugin::kMode_AES_CTR:
        hMode = Mode::AES_CTR;
        break;
    case CryptoPlugin::kMode_AES_WV:
        hMode = Mode::AES_CBC_CTS;
        break;
    case CryptoPlugin::kMode_AES_CBC:
        hMode = Mode::AES_CBC;
        break;
    default:
        return UNKNOWN_ERROR;
    }

    Pattern hPattern;
    hPattern.encryptBlocks = pattern.mEncryptBlocks;
    hPattern.skipBlocks = pattern.mSkipBlocks;

    std::vector<SubSample> stdSubSamples;
    for (size_t i = 0; i < numSubSamples; i++) {
        SubSample subSample;
        subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData;
        subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData;
        stdSubSamples.push_back(subSample);
    }
    auto hSubSamples = hidl_vec<SubSample>(stdSubSamples);

    bool secure;
    if (hDestination.type == BufferType::SHARED_MEMORY) {
        status_t status = checkSharedBuffer(hDestination.nonsecureMemory);
        if (status != OK) {
            return status;
        }
        secure = false;
    } else if (hDestination.type == BufferType::NATIVE_HANDLE) {
        secure = true;
    } else {
        android_errorWriteLog(0x534e4554, "70526702");
        return UNKNOWN_ERROR;
    }

    status_t status = checkSharedBuffer(hSource);
    if (status != OK) {
        return status;
    }

    status_t err = UNKNOWN_ERROR;
    uint32_t bytesWritten = 0;

    Return<void> hResult;

    mLock.unlock();
    if (mPluginV1_2 != NULL) {
        hResult = mPluginV1_2->decrypt_1_2(secure, toHidlArray16(keyId), toHidlArray16(iv),
                hMode, hPattern, hSubSamples, hSource, offset, hDestination,
                [&](Status_V1_2 status, uint32_t hBytesWritten, hidl_string hDetailedError) {
                    if (status == Status_V1_2::OK) {
                        bytesWritten = hBytesWritten;
                        *errorDetailMsg = toString8(hDetailedError);
                    }
                    err = toStatusT(status);
                }
            );
    } else {
        hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv),
                hMode, hPattern, hSubSamples, hSource, offset, hDestination,
                [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) {
                    if (status == Status::OK) {
                        bytesWritten = hBytesWritten;
                        *errorDetailMsg = toString8(hDetailedError);
                    }
                    err = toStatusT(status);
                }
            );
    }

    err = hResult.isOk() ? err : DEAD_OBJECT;
    if (err == OK) {
        return bytesWritten;
    }
    return err;
}
}


void CryptoHal::notifyResolution(uint32_t width, uint32_t height) {
void CryptoHal::notifyResolution(uint32_t width, uint32_t height) {
    Mutex::Autolock autoLock(mLock);
    // This requires plugin to be created.

    if (mCryptoHalAidl->initCheck() == OK) {
    if (mInitCheck != OK) {
        mCryptoHalAidl->notifyResolution(width, height);
        return;
        return;
    }
    }


    auto hResult = mPlugin->notifyResolution(width, height);
    mCryptoHalHidl->notifyResolution(width, height);
    ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
}
}


status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
    Mutex::Autolock autoLock(mLock);
    // This requires plugin to be created.

    if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId);
    if (mInitCheck != OK) {
    return mCryptoHalHidl->setMediaDrmSession(sessionId);
        return mInitCheck;
}

ssize_t CryptoHal::decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode,
                           const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source,
                           size_t offset, const CryptoPlugin::SubSample* subSamples,
                           size_t numSubSamples, const ::DestinationBuffer& destination,
                           AString* errorDetailMsg) {
    // This requires plugin to be created.
    if (mCryptoHalAidl->initCheck() == OK)
        return mCryptoHalAidl->decrypt(key, iv, mode, pattern, source, offset, subSamples,
                                       numSubSamples, destination, errorDetailMsg);
    return mCryptoHalHidl->decrypt(key, iv, mode, pattern, source, offset, subSamples,
                                   numSubSamples, destination, errorDetailMsg);
}

int32_t CryptoHal::setHeap(const sp<HidlMemory>& heap) {
    // This requires plugin to be created.
    if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setHeap(heap);
    return mCryptoHalHidl->setHeap(heap);
}

void CryptoHal::unsetHeap(int32_t seqNum) {
    // This requires plugin to be created.
    if (mCryptoHalAidl->initCheck() == OK) {
        mCryptoHalAidl->unsetHeap(seqNum);
        return;
    }
    }


    auto err = mPlugin->setMediaDrmSession(toHidlVec(sessionId));
    mCryptoHalHidl->unsetHeap(seqNum);
    return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
}
}


status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
status_t CryptoHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
    Mutex::Autolock autoLock(mLock);
    // This requires plugin to be created.
    return DrmUtils::GetLogMessages<drm::V1_4::ICryptoPlugin>(mPlugin, logs);
    if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->getLogMessages(logs);
    return mCryptoHalHidl->getLogMessages(logs);
}
}

}  // namespace android
}  // namespace android
 No newline at end of file
+409 −0

File added.

Preview size limit exceeded, changes collapsed.

+395 −0

File added.

Preview size limit exceeded, changes collapsed.

+174 −1458

File changed.

Preview size limit exceeded, changes collapsed.

Loading