diff options
Diffstat (limited to 'drm')
74 files changed, 2224 insertions, 682 deletions
diff --git a/drm/common/Android.bp b/drm/common/Android.bp index 1552c3f340..272684c29d 100644 --- a/drm/common/Android.bp +++ b/drm/common/Android.bp @@ -35,7 +35,7 @@ cc_library_static { cflags: ["-Wall", "-Werror"], - static_libs: ["libbinder"], + shared_libs: ["libbinder"], export_include_dirs: ["include"], } diff --git a/drm/common/DrmEngineBase.cpp b/drm/common/DrmEngineBase.cpp index f734905b78..aec5959d82 100644 --- a/drm/common/DrmEngineBase.cpp +++ b/drm/common/DrmEngineBase.cpp @@ -79,12 +79,12 @@ int DrmEngineBase::checkRightsStatus(int uniqueId, const String8& path, int acti } status_t DrmEngineBase::consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) { return onConsumeRights(uniqueId, decryptHandle, action, reserve); } status_t DrmEngineBase::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position) { return onSetPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); } @@ -120,7 +120,7 @@ DrmSupportInfo* DrmEngineBase::getSupportInfo(int uniqueId) { } status_t DrmEngineBase::openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, int fd, off64_t offset, off64_t length, const char* mime) { if (!mime || mime[0] == '\0') { @@ -131,7 +131,7 @@ status_t DrmEngineBase::openDecryptSession( } status_t DrmEngineBase::openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, const char* uri, const char* mime) { if (!mime || mime[0] == '\0') { return onOpenDecryptSession(uniqueId, decryptHandle, uri); @@ -139,33 +139,33 @@ status_t DrmEngineBase::openDecryptSession( return onOpenDecryptSession(uniqueId, decryptHandle, uri, mime); } -status_t DrmEngineBase::openDecryptSession(int uniqueId, DecryptHandle* decryptHandle, +status_t DrmEngineBase::openDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle, const DrmBuffer& buf, const String8& mimeType) { return onOpenDecryptSession(uniqueId, decryptHandle, buf, mimeType); } -status_t DrmEngineBase::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +status_t DrmEngineBase::closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) { return onCloseDecryptSession(uniqueId, decryptHandle); } status_t DrmEngineBase::initializeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { return onInitializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo); } status_t DrmEngineBase::decrypt( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { return onDecrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); } status_t DrmEngineBase::finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) { return onFinalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); } ssize_t DrmEngineBase::pread( - int uniqueId, DecryptHandle* decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { + int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { return onPread(uniqueId, decryptHandle, buffer, numBytes, offset); } diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp index 44f98dd3ce..a6d33b0fa4 100644 --- a/drm/common/IDrmManagerService.cpp +++ b/drm/common/IDrmManagerService.cpp @@ -39,7 +39,7 @@ using namespace android; static void writeDecryptHandleToParcelData( - const DecryptHandle* handle, Parcel* data) { + const sp<DecryptHandle>& handle, Parcel* data) { data->writeInt32(handle->decryptId); data->writeString8(handle->mimeType); data->writeInt32(handle->decryptApiType); @@ -67,7 +67,7 @@ static void writeDecryptHandleToParcelData( } static void readDecryptHandleFromParcelData( - DecryptHandle* handle, const Parcel& data) { + sp<DecryptHandle>& handle, const Parcel& data) { if (0 == data.dataAvail()) { return; } @@ -99,7 +99,7 @@ static void readDecryptHandleFromParcelData( } } -static void clearDecryptHandle(DecryptHandle* handle) { +static void clearDecryptHandle(sp<DecryptHandle> &handle) { if (handle == NULL) { return; } @@ -414,7 +414,7 @@ int BpDrmManagerService::checkRightsStatus(int uniqueId, const String8& path, in } status_t BpDrmManagerService::consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) { ALOGV("consumeRights"); Parcel data, reply; @@ -431,7 +431,7 @@ status_t BpDrmManagerService::consumeRights( } status_t BpDrmManagerService::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position) { ALOGV("setPlaybackStatus"); Parcel data, reply; @@ -603,7 +603,7 @@ status_t BpDrmManagerService::getAllSupportInfo( return reply.readInt32(); } -DecryptHandle* BpDrmManagerService::openDecryptSession( +sp<DecryptHandle> BpDrmManagerService::openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) { ALOGV("Entering BpDrmManagerService::openDecryptSession"); Parcel data, reply; @@ -621,7 +621,7 @@ DecryptHandle* BpDrmManagerService::openDecryptSession( remote()->transact(OPEN_DECRYPT_SESSION, data, &reply); - DecryptHandle* handle = NULL; + sp<DecryptHandle> handle; if (0 != reply.dataAvail()) { handle = new DecryptHandle(); readDecryptHandleFromParcelData(handle, reply); @@ -629,7 +629,7 @@ DecryptHandle* BpDrmManagerService::openDecryptSession( return handle; } -DecryptHandle* BpDrmManagerService::openDecryptSession( +sp<DecryptHandle> BpDrmManagerService::openDecryptSession( int uniqueId, const char* uri, const char* mime) { ALOGV("Entering BpDrmManagerService::openDecryptSession: mime=%s", mime? mime: "NULL"); @@ -646,7 +646,7 @@ DecryptHandle* BpDrmManagerService::openDecryptSession( remote()->transact(OPEN_DECRYPT_SESSION_FROM_URI, data, &reply); - DecryptHandle* handle = NULL; + sp<DecryptHandle> handle; if (0 != reply.dataAvail()) { handle = new DecryptHandle(); readDecryptHandleFromParcelData(handle, reply); @@ -656,7 +656,7 @@ DecryptHandle* BpDrmManagerService::openDecryptSession( return handle; } -DecryptHandle* BpDrmManagerService::openDecryptSession( +sp<DecryptHandle> BpDrmManagerService::openDecryptSession( int uniqueId, const DrmBuffer& buf, const String8& mimeType) { ALOGV("Entering BpDrmManagerService::openDecryptSession"); Parcel data, reply; @@ -673,7 +673,7 @@ DecryptHandle* BpDrmManagerService::openDecryptSession( remote()->transact(OPEN_DECRYPT_SESSION_FOR_STREAMING, data, &reply); - DecryptHandle* handle = NULL; + sp<DecryptHandle> handle; if (0 != reply.dataAvail()) { handle = new DecryptHandle(); readDecryptHandleFromParcelData(handle, reply); @@ -683,7 +683,7 @@ DecryptHandle* BpDrmManagerService::openDecryptSession( return handle; } -status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +status_t BpDrmManagerService::closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) { ALOGV("closeDecryptSession"); Parcel data, reply; @@ -698,7 +698,7 @@ status_t BpDrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* d } status_t BpDrmManagerService::initializeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { ALOGV("initializeDecryptUnit"); Parcel data, reply; @@ -718,7 +718,7 @@ status_t BpDrmManagerService::initializeDecryptUnit( } status_t BpDrmManagerService::decrypt( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { ALOGV("decrypt"); Parcel data, reply; @@ -754,7 +754,7 @@ status_t BpDrmManagerService::decrypt( } status_t BpDrmManagerService::finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) { ALOGV("finalizeDecryptUnit"); Parcel data, reply; @@ -770,7 +770,7 @@ status_t BpDrmManagerService::finalizeDecryptUnit( } ssize_t BpDrmManagerService::pread( - int uniqueId, DecryptHandle* decryptHandle, void* buffer, + int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { ALOGV("read"); Parcel data, reply; @@ -1128,16 +1128,16 @@ status_t BnDrmManagerService::onTransact( const int uniqueId = data.readInt32(); - DecryptHandle handle; - readDecryptHandleFromParcelData(&handle, data); + sp<DecryptHandle> handle = new DecryptHandle(); + readDecryptHandleFromParcelData(handle, data); const int action = data.readInt32(); const bool reserve = static_cast<bool>(data.readInt32()); const status_t status - = consumeRights(uniqueId, &handle, action, reserve); + = consumeRights(uniqueId, handle, action, reserve); reply->writeInt32(status); - clearDecryptHandle(&handle); + clearDecryptHandle(handle); return DRM_NO_ERROR; } @@ -1148,16 +1148,16 @@ status_t BnDrmManagerService::onTransact( const int uniqueId = data.readInt32(); - DecryptHandle handle; - readDecryptHandleFromParcelData(&handle, data); + sp<DecryptHandle> handle = new DecryptHandle(); + readDecryptHandleFromParcelData(handle, data); const int playbackStatus = data.readInt32(); const int64_t position = data.readInt64(); const status_t status - = setPlaybackStatus(uniqueId, &handle, playbackStatus, position); + = setPlaybackStatus(uniqueId, handle, playbackStatus, position); reply->writeInt32(status); - clearDecryptHandle(&handle); + clearDecryptHandle(handle); return DRM_NO_ERROR; } @@ -1329,13 +1329,13 @@ status_t BnDrmManagerService::onTransact( const off64_t length = data.readInt64(); const String8 mime = data.readString8(); - DecryptHandle* handle + sp<DecryptHandle> handle = openDecryptSession(uniqueId, fd, offset, length, mime.string()); - if (NULL != handle) { - writeDecryptHandleToParcelData(handle, reply); + if (NULL != handle.get()) { + writeDecryptHandleToParcelData(handle.get(), reply); clearDecryptHandle(handle); - delete handle; handle = NULL; + handle.clear(); } return DRM_NO_ERROR; } @@ -1349,13 +1349,13 @@ status_t BnDrmManagerService::onTransact( const String8 uri = data.readString8(); const String8 mime = data.readString8(); - DecryptHandle* handle = openDecryptSession(uniqueId, uri.string(), mime.string()); + sp<DecryptHandle> handle = openDecryptSession(uniqueId, uri.string(), mime.string()); - if (NULL != handle) { - writeDecryptHandleToParcelData(handle, reply); + if (NULL != handle.get()) { + writeDecryptHandleToParcelData(handle.get(), reply); clearDecryptHandle(handle); - delete handle; handle = NULL; + handle.clear(); } else { ALOGV("NULL decryptHandle is returned"); } @@ -1373,13 +1373,12 @@ status_t BnDrmManagerService::onTransact( bufferSize); const String8 mimeType(data.readString8()); - DecryptHandle* handle = openDecryptSession(uniqueId, buf, mimeType); + sp<DecryptHandle> handle = openDecryptSession(uniqueId, buf, mimeType); if (handle != NULL) { writeDecryptHandleToParcelData(handle, reply); clearDecryptHandle(handle); - delete handle; - handle = NULL; + handle.clear(); } else { ALOGV("NULL decryptHandle is returned"); } @@ -1393,7 +1392,7 @@ status_t BnDrmManagerService::onTransact( const int uniqueId = data.readInt32(); - DecryptHandle* handle = new DecryptHandle(); + sp<DecryptHandle> handle = new DecryptHandle(); readDecryptHandleFromParcelData(handle, data); const status_t status = closeDecryptSession(uniqueId, handle); @@ -1408,8 +1407,8 @@ status_t BnDrmManagerService::onTransact( const int uniqueId = data.readInt32(); - DecryptHandle handle; - readDecryptHandleFromParcelData(&handle, data); + sp<DecryptHandle> handle = new DecryptHandle(); + readDecryptHandleFromParcelData(handle, data); const int decryptUnitId = data.readInt32(); @@ -1417,17 +1416,17 @@ status_t BnDrmManagerService::onTransact( const uint32_t bufferSize = data.readInt32(); if (bufferSize > data.dataAvail()) { reply->writeInt32(BAD_VALUE); - clearDecryptHandle(&handle); + clearDecryptHandle(handle); return DRM_NO_ERROR; } DrmBuffer* headerInfo = NULL; headerInfo = new DrmBuffer((char *)data.readInplace(bufferSize), bufferSize); const status_t status - = initializeDecryptUnit(uniqueId, &handle, decryptUnitId, headerInfo); + = initializeDecryptUnit(uniqueId, handle, decryptUnitId, headerInfo); reply->writeInt32(status); - clearDecryptHandle(&handle); + clearDecryptHandle(handle); delete headerInfo; headerInfo = NULL; return DRM_NO_ERROR; } @@ -1439,8 +1438,8 @@ status_t BnDrmManagerService::onTransact( const int uniqueId = data.readInt32(); - DecryptHandle handle; - readDecryptHandleFromParcelData(&handle, data); + sp<DecryptHandle> handle = new DecryptHandle; + readDecryptHandleFromParcelData(handle, data); const int decryptUnitId = data.readInt32(); const uint32_t decBufferSize = data.readInt32(); @@ -1450,7 +1449,7 @@ status_t BnDrmManagerService::onTransact( decBufferSize > MAX_BINDER_TRANSACTION_SIZE) { reply->writeInt32(BAD_VALUE); reply->writeInt32(0); - clearDecryptHandle(&handle); + clearDecryptHandle(handle); return DRM_NO_ERROR; } @@ -1470,7 +1469,7 @@ status_t BnDrmManagerService::onTransact( } const status_t status - = decrypt(uniqueId, &handle, decryptUnitId, encBuffer, &decBuffer, IV); + = decrypt(uniqueId, handle, decryptUnitId, encBuffer, &decBuffer, IV); reply->writeInt32(status); @@ -1480,7 +1479,7 @@ status_t BnDrmManagerService::onTransact( reply->write(decBuffer->data, size); } - clearDecryptHandle(&handle); + clearDecryptHandle(handle); delete encBuffer; encBuffer = NULL; delete decBuffer; decBuffer = NULL; delete [] buffer; buffer = NULL; @@ -1495,13 +1494,13 @@ status_t BnDrmManagerService::onTransact( const int uniqueId = data.readInt32(); - DecryptHandle handle; - readDecryptHandleFromParcelData(&handle, data); + sp<DecryptHandle> handle = new DecryptHandle(); + readDecryptHandleFromParcelData(handle, data); - const status_t status = finalizeDecryptUnit(uniqueId, &handle, data.readInt32()); + const status_t status = finalizeDecryptUnit(uniqueId, handle, data.readInt32()); reply->writeInt32(status); - clearDecryptHandle(&handle); + clearDecryptHandle(handle); return DRM_NO_ERROR; } @@ -1512,8 +1511,8 @@ status_t BnDrmManagerService::onTransact( const int uniqueId = data.readInt32(); - DecryptHandle handle; - readDecryptHandleFromParcelData(&handle, data); + sp<DecryptHandle> handle = new DecryptHandle(); + readDecryptHandleFromParcelData(handle, data); const uint32_t numBytes = data.readInt32(); if (numBytes > MAX_BINDER_TRANSACTION_SIZE) { @@ -1524,13 +1523,13 @@ status_t BnDrmManagerService::onTransact( const off64_t offset = data.readInt64(); - ssize_t result = pread(uniqueId, &handle, buffer, numBytes, offset); + ssize_t result = pread(uniqueId, handle, buffer, numBytes, offset); reply->writeInt32(result); if (0 < result) { reply->write(buffer, result); } - clearDecryptHandle(&handle); + clearDecryptHandle(handle); delete [] buffer, buffer = NULL; return DRM_NO_ERROR; } diff --git a/drm/common/include/DrmEngineBase.h b/drm/common/include/DrmEngineBase.h index 417107f1bd..73f11a4d2b 100644 --- a/drm/common/include/DrmEngineBase.h +++ b/drm/common/include/DrmEngineBase.h @@ -59,10 +59,11 @@ public: int checkRightsStatus(int uniqueId, const String8& path, int action); - status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); + status_t consumeRights(int uniqueId, sp<DecryptHandle>& decryptHandle, int action, + bool reserve); status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position); bool validateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -80,27 +81,28 @@ public: DrmSupportInfo* getSupportInfo(int uniqueId); status_t openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, int fd, off64_t offset, off64_t length, const char* mime); status_t openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, const char* uri, const char* mime); - status_t openDecryptSession(int uniqueId, DecryptHandle* decryptHandle, + status_t openDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle, const DrmBuffer& buf, const String8& mimeType); - status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle); + status_t closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle); - status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); - status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + status_t decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV); - status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); + status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, + int decryptUnitId); - ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, + ssize_t pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); protected: @@ -265,7 +267,7 @@ protected: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - virtual status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, + virtual status_t onConsumeRights(int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) = 0; /** @@ -280,7 +282,8 @@ protected: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ virtual status_t onSetPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) = 0; + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, + int64_t position) = 0; /** * Validates whether an action on the DRM content is allowed or not. @@ -381,7 +384,7 @@ protected: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, int fd, off64_t offset, off64_t length) = 0; /** @@ -398,7 +401,7 @@ protected: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t onOpenDecryptSession( - int /* uniqueId */, DecryptHandle* /* decryptHandle */, + int /* uniqueId */, sp<DecryptHandle>& /* decryptHandle */, int /* fd */, off64_t /* offset */, off64_t /* length */, const char* /* mime */) { @@ -415,7 +418,7 @@ protected: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, const char* uri) = 0; /** @@ -430,7 +433,7 @@ protected: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t onOpenDecryptSession( - int /* uniqueId */, DecryptHandle* /* decryptHandle */, + int /* uniqueId */, sp<DecryptHandle>& /* decryptHandle */, const char* /* uri */, const char* /* mime */) { return DRM_ERROR_CANNOT_HANDLE; @@ -447,7 +450,7 @@ protected: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t onOpenDecryptSession(int /* uniqueId */, - DecryptHandle* /* decryptHandle */, + sp<DecryptHandle>& /* decryptHandle */, const DrmBuffer& /* buf */, const String8& /* mimeType */) { return DRM_ERROR_CANNOT_HANDLE; @@ -461,7 +464,7 @@ protected: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - virtual status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0; + virtual status_t onCloseDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) = 0; /** * Initialize decryption for the given unit of the protected content @@ -473,7 +476,7 @@ protected: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - virtual status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + virtual status_t onInitializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) = 0; /** @@ -493,7 +496,7 @@ protected: * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, * DRM_ERROR_DECRYPT for failure. */ - virtual status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + virtual status_t onDecrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0; /** @@ -506,7 +509,7 @@ protected: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ virtual status_t onFinalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0; + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) = 0; /** * Reads the specified number of bytes from an open DRM file. @@ -519,7 +522,7 @@ protected: * * @return Number of bytes read. Returns -1 for Failure. */ - virtual ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle, + virtual ssize_t onPread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) = 0; }; diff --git a/drm/common/include/IDrmEngine.h b/drm/common/include/IDrmEngine.h index acc8ed9433..1837a116d2 100644 --- a/drm/common/include/IDrmEngine.h +++ b/drm/common/include/IDrmEngine.h @@ -210,7 +210,7 @@ public: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ virtual status_t consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0; + int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) = 0; /** * Informs the DRM Engine about the playback actions performed on the DRM files. @@ -223,7 +223,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - virtual status_t setPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle, + virtual status_t setPlaybackStatus(int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position) = 0; /** @@ -327,7 +327,7 @@ public: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, int fd, off64_t offset, off64_t length, const char* mime) = 0; /** @@ -342,7 +342,7 @@ public: * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ virtual status_t openDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, + int uniqueId, sp<DecryptHandle>& decryptHandle, const char* uri, const char* mime) = 0; /** @@ -355,7 +355,7 @@ public: * @return * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ - virtual status_t openDecryptSession(int uniqueId, DecryptHandle* decryptHandle, + virtual status_t openDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle, const DrmBuffer& buf, const String8& mimeType) = 0; /** @@ -366,7 +366,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0; + virtual status_t closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) = 0; /** * Initialize decryption for the given unit of the protected content @@ -378,7 +378,7 @@ public: * @return status_t * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ - virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + virtual status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) = 0; /** @@ -398,7 +398,7 @@ public: * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, * DRM_ERROR_DECRYPT for failure. */ - virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + virtual status_t decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0; /** @@ -411,7 +411,7 @@ public: * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ virtual status_t finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0; + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) = 0; /** * Reads the specified number of bytes from an open DRM file. @@ -424,7 +424,7 @@ public: * * @return Number of bytes read. Returns -1 for Failure. */ - virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, + virtual ssize_t pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) = 0; }; diff --git a/drm/common/include/IDrmManagerService.h b/drm/common/include/IDrmManagerService.h index 0376b492d8..836ae0a428 100644 --- a/drm/common/include/IDrmManagerService.h +++ b/drm/common/include/IDrmManagerService.h @@ -115,10 +115,11 @@ public: virtual int checkRightsStatus(int uniqueId, const String8& path, int action) = 0; virtual status_t consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) = 0; + int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) = 0; virtual status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) = 0; + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, + int64_t position) = 0; virtual bool validateAction( int uniqueId, const String8& path, @@ -138,28 +139,28 @@ public: virtual status_t getAllSupportInfo( int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) = 0; - virtual DecryptHandle* openDecryptSession( + virtual sp<DecryptHandle> openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) = 0; - virtual DecryptHandle* openDecryptSession( + virtual sp<DecryptHandle> openDecryptSession( int uniqueId, const char* uri, const char* mime) = 0; - virtual DecryptHandle* openDecryptSession( + virtual sp<DecryptHandle> openDecryptSession( int uniqueId, const DrmBuffer& buf, const String8& mimeType) = 0; - virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) = 0; + virtual status_t closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) = 0; - virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + virtual status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) = 0; - virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + virtual status_t decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) = 0; virtual status_t finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) = 0; + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) = 0; - virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, + virtual ssize_t pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes,off64_t offset) = 0; }; @@ -203,10 +204,10 @@ public: virtual int checkRightsStatus(int uniqueId, const String8& path, int action); virtual status_t consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); + int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve); virtual status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position); virtual bool validateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -225,28 +226,28 @@ public: virtual status_t getAllSupportInfo( int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray); - virtual DecryptHandle* openDecryptSession( + virtual sp<DecryptHandle> openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char* mime); - virtual DecryptHandle* openDecryptSession( + virtual sp<DecryptHandle> openDecryptSession( int uniqueId, const char* uri, const char* mime); - virtual DecryptHandle* openDecryptSession( + virtual sp<DecryptHandle> openDecryptSession( int uniqueId, const DrmBuffer& buf, const String8& mimeType); - virtual status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle); + virtual status_t closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle); - virtual status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + virtual status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); - virtual status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + virtual status_t decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV); virtual status_t finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId); - virtual ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, + virtual ssize_t pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); }; diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp index bf04a893a6..afbcb3940e 100644 --- a/drm/drmserver/DrmManager.cpp +++ b/drm/drmserver/DrmManager.cpp @@ -267,7 +267,7 @@ int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) } status_t DrmManager::consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) { status_t result = DRM_ERROR_UNKNOWN; Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { @@ -278,7 +278,7 @@ status_t DrmManager::consumeRights( } status_t DrmManager::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position) { status_t result = DRM_ERROR_UNKNOWN; Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { @@ -396,15 +396,15 @@ status_t DrmManager::getAllSupportInfo( return DRM_NO_ERROR; } -DecryptHandle* DrmManager::openDecryptSession( +sp<DecryptHandle> DrmManager::openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) { Mutex::Autolock _l(mDecryptLock); status_t result = DRM_ERROR_CANNOT_HANDLE; Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); - DecryptHandle* handle = new DecryptHandle(); - if (NULL != handle) { + sp<DecryptHandle> handle = new DecryptHandle(); + if (NULL != handle.get()) { handle->decryptId = mDecryptSessionId + 1; for (size_t index = 0; index < plugInIdList.size(); index++) { @@ -420,19 +420,19 @@ DecryptHandle* DrmManager::openDecryptSession( } } if (DRM_NO_ERROR != result) { - delete handle; handle = NULL; + handle.clear(); } return handle; } -DecryptHandle* DrmManager::openDecryptSession( +sp<DecryptHandle> DrmManager::openDecryptSession( int uniqueId, const char* uri, const char* mime) { Mutex::Autolock _l(mDecryptLock); status_t result = DRM_ERROR_CANNOT_HANDLE; Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); - DecryptHandle* handle = new DecryptHandle(); - if (NULL != handle) { + sp<DecryptHandle> handle = new DecryptHandle(); + if (NULL != handle.get()) { handle->decryptId = mDecryptSessionId + 1; for (size_t index = 0; index < plugInIdList.size(); index++) { @@ -448,20 +448,20 @@ DecryptHandle* DrmManager::openDecryptSession( } } if (DRM_NO_ERROR != result) { - delete handle; handle = NULL; + handle.clear(); ALOGV("DrmManager::openDecryptSession: no capable plug-in found"); } return handle; } -DecryptHandle* DrmManager::openDecryptSession( +sp<DecryptHandle> DrmManager::openDecryptSession( int uniqueId, const DrmBuffer& buf, const String8& mimeType) { Mutex::Autolock _l(mDecryptLock); status_t result = DRM_ERROR_CANNOT_HANDLE; Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); - DecryptHandle* handle = new DecryptHandle(); - if (NULL != handle) { + sp<DecryptHandle> handle = new DecryptHandle(); + if (NULL != handle.get()) { handle->decryptId = mDecryptSessionId + 1; for (size_t index = 0; index < plugInIdList.size(); index++) { @@ -477,20 +477,19 @@ DecryptHandle* DrmManager::openDecryptSession( } } if (DRM_NO_ERROR != result) { - delete handle; - handle = NULL; + handle.clear(); ALOGV("DrmManager::openDecryptSession: no capable plug-in found"); } return handle; } -status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +status_t DrmManager::closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) { Mutex::Autolock _l(mDecryptLock); status_t result = DRM_ERROR_UNKNOWN; if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); result = drmEngine->closeDecryptSession(uniqueId, decryptHandle); - if (DRM_NO_ERROR == result) { + if (DRM_NO_ERROR == result && NULL != decryptHandle.get()) { mDecryptSessionMap.removeItem(decryptHandle->decryptId); } } @@ -498,7 +497,8 @@ status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHan } status_t DrmManager::initializeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, + const DrmBuffer* headerInfo) { status_t result = DRM_ERROR_UNKNOWN; Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { @@ -508,7 +508,7 @@ status_t DrmManager::initializeDecryptUnit( return result; } -status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, +status_t DrmManager::decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { status_t result = DRM_ERROR_UNKNOWN; @@ -522,7 +522,7 @@ status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int dec } status_t DrmManager::finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) { status_t result = DRM_ERROR_UNKNOWN; Mutex::Autolock _l(mDecryptLock); if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { @@ -532,7 +532,7 @@ status_t DrmManager::finalizeDecryptUnit( return result; } -ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle, +ssize_t DrmManager::pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { ssize_t result = DECRYPT_FILE_ERROR; diff --git a/drm/drmserver/DrmManager.h b/drm/drmserver/DrmManager.h index e7cdd36b76..26222bca3f 100644 --- a/drm/drmserver/DrmManager.h +++ b/drm/drmserver/DrmManager.h @@ -89,10 +89,11 @@ public: int checkRightsStatus(int uniqueId, const String8& path, int action); - status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); + status_t consumeRights(int uniqueId, sp<DecryptHandle>& decryptHandle, int action, + bool reserve); status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position); bool validateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -109,25 +110,26 @@ public: status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray); - DecryptHandle* openDecryptSession( + sp<DecryptHandle> openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char* mime); - DecryptHandle* openDecryptSession(int uniqueId, const char* uri, const char* mime); + sp<DecryptHandle> openDecryptSession(int uniqueId, const char* uri, const char* mime); - DecryptHandle* openDecryptSession(int uniqueId, const DrmBuffer& buf, + sp<DecryptHandle> openDecryptSession(int uniqueId, const DrmBuffer& buf, const String8& mimeType); - status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle); + status_t closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle); - status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); - status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + status_t decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV); - status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); + status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, + int decryptUnitId); - ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, + ssize_t pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); void onInfo(const DrmInfoEvent& event); diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp index dad599b42e..2600a2c23e 100644 --- a/drm/drmserver/DrmManagerService.cpp +++ b/drm/drmserver/DrmManagerService.cpp @@ -58,22 +58,26 @@ const char *DrmManagerService::get_perm_label(drm_perm_t perm) { return drm_perm_labels[index]; } -bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm) { +bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, const char* ssid, drm_perm_t perm) { if (selinux_enabled <= 0) { return true; } - char *sctx; + char *sctx = NULL; const char *selinux_class = "drmservice"; const char *str_perm = get_perm_label(perm); - if (getpidcon(spid, &sctx) != 0) { - ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid); - return false; + if (ssid == NULL) { + android_errorWriteLog(0x534e4554, "121035042"); + + if (getpidcon(spid, &sctx) != 0) { + ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid); + return false; + } } - bool allowed = (selinux_check_access(sctx, drmserver_context, selinux_class, - str_perm, NULL) == 0); + bool allowed = (selinux_check_access(ssid ? ssid : sctx, drmserver_context, + selinux_class, str_perm, NULL) == 0); freecon(sctx); return allowed; @@ -86,10 +90,11 @@ bool DrmManagerService::isProtectedCallAllowed(drm_perm_t perm) { IPCThreadState* ipcState = IPCThreadState::self(); uid_t uid = ipcState->getCallingUid(); pid_t spid = ipcState->getCallingPid(); + const char* ssid = ipcState->getCallingSid(); for (unsigned int i = 0; i < trustedUids.size(); ++i) { if (trustedUids[i] == uid) { - return selinuxIsProtectedCallAllowed(spid, perm); + return selinuxIsProtectedCallAllowed(spid, ssid, perm); } } return false; @@ -97,7 +102,9 @@ bool DrmManagerService::isProtectedCallAllowed(drm_perm_t perm) { void DrmManagerService::instantiate() { ALOGV("instantiate"); - defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService()); + sp<DrmManagerService> service = new DrmManagerService(); + service->setRequestingSid(true); + defaultServiceManager()->addService(String16("drm.drmManager"), service); if (0 >= trustedUids.size()) { // TODO @@ -206,7 +213,7 @@ int DrmManagerService::checkRightsStatus( } status_t DrmManagerService::consumeRights( - int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) { ALOGV("Entering consumeRights"); if (!isProtectedCallAllowed(CONSUME_RIGHTS)) { return DRM_ERROR_NO_PERMISSION; @@ -215,7 +222,7 @@ status_t DrmManagerService::consumeRights( } status_t DrmManagerService::setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position) { ALOGV("Entering setPlaybackStatus"); if (!isProtectedCallAllowed(SET_PLAYBACK_STATUS)) { return DRM_ERROR_NO_PERMISSION; @@ -262,7 +269,7 @@ status_t DrmManagerService::getAllSupportInfo( return mDrmManager->getAllSupportInfo(uniqueId, length, drmSupportInfoArray); } -DecryptHandle* DrmManagerService::openDecryptSession( +sp<DecryptHandle> DrmManagerService::openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) { ALOGV("Entering DrmManagerService::openDecryptSession"); if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) { @@ -272,7 +279,7 @@ DecryptHandle* DrmManagerService::openDecryptSession( return NULL; } -DecryptHandle* DrmManagerService::openDecryptSession( +sp<DecryptHandle> DrmManagerService::openDecryptSession( int uniqueId, const char* uri, const char* mime) { ALOGV("Entering DrmManagerService::openDecryptSession with uri"); if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) { @@ -282,7 +289,7 @@ DecryptHandle* DrmManagerService::openDecryptSession( return NULL; } -DecryptHandle* DrmManagerService::openDecryptSession( +sp<DecryptHandle> DrmManagerService::openDecryptSession( int uniqueId, const DrmBuffer& buf, const String8& mimeType) { ALOGV("Entering DrmManagerService::openDecryptSession for streaming"); if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) { @@ -292,7 +299,7 @@ DecryptHandle* DrmManagerService::openDecryptSession( return NULL; } -status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +status_t DrmManagerService::closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) { ALOGV("Entering closeDecryptSession"); if (!isProtectedCallAllowed(CLOSE_DECRYPT_SESSION)) { return DRM_ERROR_NO_PERMISSION; @@ -300,7 +307,7 @@ status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* dec return mDrmManager->closeDecryptSession(uniqueId, decryptHandle); } -status_t DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, +status_t DrmManagerService::initializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { ALOGV("Entering initializeDecryptUnit"); if (!isProtectedCallAllowed(INITIALIZE_DECRYPT_UNIT)) { @@ -310,7 +317,7 @@ status_t DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* d } status_t DrmManagerService::decrypt( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { ALOGV("Entering decrypt"); if (!isProtectedCallAllowed(DECRYPT)) { @@ -320,7 +327,7 @@ status_t DrmManagerService::decrypt( } status_t DrmManagerService::finalizeDecryptUnit( - int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) { ALOGV("Entering finalizeDecryptUnit"); if (!isProtectedCallAllowed(FINALIZE_DECRYPT_UNIT)) { return DRM_ERROR_NO_PERMISSION; @@ -328,7 +335,7 @@ status_t DrmManagerService::finalizeDecryptUnit( return mDrmManager->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); } -ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle, +ssize_t DrmManagerService::pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { ALOGV("Entering pread"); if (!isProtectedCallAllowed(PREAD)) { diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h index 45cee2e203..2e27a3c393 100644 --- a/drm/drmserver/DrmManagerService.h +++ b/drm/drmserver/DrmManagerService.h @@ -60,7 +60,7 @@ private: static const char *get_perm_label(drm_perm_t perm); - static bool selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm); + static bool selinuxIsProtectedCallAllowed(pid_t spid, const char* ssid, drm_perm_t perm); static bool isProtectedCallAllowed(drm_perm_t perm); @@ -95,10 +95,11 @@ public: int checkRightsStatus(int uniqueId, const String8& path,int action); - status_t consumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); + status_t consumeRights(int uniqueId, sp<DecryptHandle>& decryptHandle, int action, + bool reserve); status_t setPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position); bool validateAction(int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -115,26 +116,27 @@ public: status_t getAllSupportInfo(int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray); - DecryptHandle* openDecryptSession( + sp<DecryptHandle> openDecryptSession( int uniqueId, int fd, off64_t offset, off64_t length, const char *mime); - DecryptHandle* openDecryptSession( + sp<DecryptHandle> openDecryptSession( int uniqueId, const char* uri, const char* mime); - DecryptHandle* openDecryptSession(int uniqueId, const DrmBuffer& buf, + sp<DecryptHandle> openDecryptSession(int uniqueId, const DrmBuffer& buf, const String8& mimeType); - status_t closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle); + status_t closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle); - status_t initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + status_t initializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); - status_t decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + status_t decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV); - status_t finalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); + status_t finalizeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, + int decryptUnitId); - ssize_t pread(int uniqueId, DecryptHandle* decryptHandle, + ssize_t pread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); virtual status_t dump(int fd, const Vector<String16>& args); diff --git a/drm/libdrmframework/Android.bp b/drm/libdrmframework/Android.bp index 43ba72bcb3..940c17d2b8 100644 --- a/drm/libdrmframework/Android.bp +++ b/drm/libdrmframework/Android.bp @@ -39,4 +39,3 @@ cc_library_shared { cflags: ["-Werror"], } -subdirs = ["plugins/*"] diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp index c047eb13b1..b0a441b556 100644 --- a/drm/libdrmframework/DrmManagerClientImpl.cpp +++ b/drm/libdrmframework/DrmManagerClientImpl.cpp @@ -183,7 +183,7 @@ status_t DrmManagerClientImpl::consumeRights( status_t status = DRM_ERROR_UNKNOWN; if (NULL != decryptHandle.get()) { status = getDrmManagerService()->consumeRights( - uniqueId, decryptHandle.get(), action, reserve); + uniqueId, decryptHandle, action, reserve); } return status; } @@ -194,7 +194,7 @@ status_t DrmManagerClientImpl::setPlaybackStatus( status_t status = DRM_ERROR_UNKNOWN; if (NULL != decryptHandle.get()) { status = getDrmManagerService()->setPlaybackStatus( - uniqueId, decryptHandle.get(), playbackStatus, position); + uniqueId, decryptHandle, playbackStatus, position); } return status; } @@ -267,7 +267,7 @@ sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession( sp<DecryptHandle> DrmManagerClientImpl::openDecryptSession( int uniqueId, const char* uri, const char* mime) { - DecryptHandle* handle = NULL; + sp<DecryptHandle> handle; if (NULL != uri) { handle = getDrmManagerService()->openDecryptSession(uniqueId, uri, mime); } @@ -284,7 +284,7 @@ status_t DrmManagerClientImpl::closeDecryptSession( status_t status = DRM_ERROR_UNKNOWN; if (NULL != decryptHandle.get()) { status = getDrmManagerService()->closeDecryptSession( - uniqueId, decryptHandle.get()); + uniqueId, decryptHandle); } return status; } @@ -295,7 +295,7 @@ status_t DrmManagerClientImpl::initializeDecryptUnit( status_t status = DRM_ERROR_UNKNOWN; if ((NULL != decryptHandle.get()) && (NULL != headerInfo)) { status = getDrmManagerService()->initializeDecryptUnit( - uniqueId, decryptHandle.get(), decryptUnitId, headerInfo); + uniqueId, decryptHandle, decryptUnitId, headerInfo); } return status; } @@ -308,7 +308,7 @@ status_t DrmManagerClientImpl::decrypt( if ((NULL != decryptHandle.get()) && (NULL != encBuffer) && (NULL != decBuffer) && (NULL != *decBuffer)) { status = getDrmManagerService()->decrypt( - uniqueId, decryptHandle.get(), decryptUnitId, + uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); } return status; @@ -319,7 +319,7 @@ status_t DrmManagerClientImpl::finalizeDecryptUnit( status_t status = DRM_ERROR_UNKNOWN; if (NULL != decryptHandle.get()) { status = getDrmManagerService()->finalizeDecryptUnit( - uniqueId, decryptHandle.get(), decryptUnitId); + uniqueId, decryptHandle, decryptUnitId); } return status; } @@ -329,7 +329,7 @@ ssize_t DrmManagerClientImpl::pread(int uniqueId, sp<DecryptHandle> &decryptHand ssize_t retCode = INVALID_VALUE; if ((NULL != decryptHandle.get()) && (NULL != buffer) && (0 < numBytes)) { retCode = getDrmManagerService()->pread( - uniqueId, decryptHandle.get(), buffer, numBytes, offset); + uniqueId, decryptHandle, buffer, numBytes, offset); } return retCode; } diff --git a/drm/libdrmframework/plugins/common/Android.bp b/drm/libdrmframework/plugins/common/Android.bp deleted file mode 100644 index 213e57f859..0000000000 --- a/drm/libdrmframework/plugins/common/Android.bp +++ /dev/null @@ -1 +0,0 @@ -subdirs = ["util"] diff --git a/drm/libdrmframework/plugins/forward-lock/Android.bp b/drm/libdrmframework/plugins/forward-lock/Android.bp deleted file mode 100644 index f884c14986..0000000000 --- a/drm/libdrmframework/plugins/forward-lock/Android.bp +++ /dev/null @@ -1,4 +0,0 @@ -subdirs = [ - "FwdLockEngine", - "internal-format", -] diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp index 28a78aa21a..bb9d7ec791 100644 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp @@ -29,8 +29,7 @@ cc_library_shared { srcs: ["src/FwdLockEngine.cpp"], shared_libs: [ - "libicui18n", - "libicuuc", + "libandroidicu", "libutils", "liblog", "libdl", diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h index a571b3aa1f..b62ddb9296 100644 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h @@ -198,7 +198,7 @@ int onCheckRightsStatus(int uniqueId, * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ status_t onConsumeRights(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int action, bool reserve); @@ -215,12 +215,12 @@ status_t onConsumeRights(int uniqueId, */ #ifdef USE_64BIT_DRM_API status_t onSetPlaybackStatus(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position); #else status_t onSetPlaybackStatus(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int playbackStatus, int position); #endif @@ -330,11 +330,11 @@ DrmSupportInfo* onGetSupportInfo(int uniqueId); */ #ifdef USE_64BIT_DRM_API status_t onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int fd, off64_t offset, off64_t length); #else status_t onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int fd, int offset, int length); #endif @@ -348,7 +348,7 @@ status_t onOpenDecryptSession(int uniqueId, * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ status_t onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, const char* uri); /** @@ -360,7 +360,7 @@ status_t onOpenDecryptSession(int uniqueId, * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure */ status_t onCloseDecryptSession(int uniqueId, - DecryptHandle* decryptHandle); + sp<DecryptHandle>& decryptHandle); /** * Initialize decryption for the given unit of the protected content. @@ -373,7 +373,7 @@ status_t onCloseDecryptSession(int uniqueId, * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ status_t onInitializeDecryptUnit(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); @@ -394,7 +394,7 @@ status_t onInitializeDecryptUnit(int uniqueId, * DRM_ERROR_DECRYPT for failure. */ status_t onDecrypt(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer); @@ -416,7 +416,7 @@ status_t onDecrypt(int uniqueId, * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, * DRM_ERROR_DECRYPT for failure. */ -status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, +status_t onDecrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV); @@ -430,7 +430,7 @@ status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success */ status_t onFinalizeDecryptUnit(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int decryptUnitId); /** @@ -445,7 +445,7 @@ status_t onFinalizeDecryptUnit(int uniqueId, * @retval -1 Failure. */ ssize_t onRead(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, void* pBuffer, int numBytes); @@ -463,12 +463,12 @@ ssize_t onRead(int uniqueId, */ #ifdef USE_64BIT_DRM_API off64_t onLseek(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, off64_t offset, int whence); #else off_t onLseek(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, off_t offset, int whence); #endif @@ -486,13 +486,13 @@ off_t onLseek(int uniqueId, */ #ifdef USE_64BIT_DRM_API ssize_t onPread(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); #else ssize_t onPread(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off_t offset); diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp index 73eea89249..769de0c801 100644 --- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp @@ -294,7 +294,7 @@ int FwdLockEngine::onCheckRightsStatus(int uniqueId, } status_t FwdLockEngine::onConsumeRights(int /* uniqueId */, - DecryptHandle* /* decryptHandle */, + sp<DecryptHandle>& /* decryptHandle */, int /* action */, bool /* reserve */) { // No rights consumption @@ -372,11 +372,13 @@ status_t FwdLockEngine::onRemoveAllRights(int /* uniqueId */) { } #ifdef USE_64BIT_DRM_API -status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, DecryptHandle* /* decryptHandle */, - int /* playbackStatus */, int64_t /* position */) { +status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, + sp<DecryptHandle>& /* decryptHandle */, int /* playbackStatus */, + int64_t /* position */) { #else -status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, DecryptHandle* /* decryptHandle */, - int /* playbackStatus */, int /* position */) { +status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, + sp<DecryptHandle>& /* decryptHandle */, + int /* playbackStatus */, int /* position */) { #endif // Not used LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus"); @@ -470,13 +472,13 @@ DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int /* uniqueId */, #ifdef USE_64BIT_DRM_API status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int fd, off64_t offset, off64_t /* length */) { #else status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, int fd, int offset, int /* length */) { @@ -487,7 +489,7 @@ status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */, LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession"); if ((-1 < fd) && - (NULL != decryptHandle) && + (NULL != decryptHandle.get()) && (!decodeSessionMap.isCreated(decryptHandle->decryptId))) { fileDesc = dup(fd); } else { @@ -533,12 +535,12 @@ status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */, } status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, const char* uri) { status_t result = DRM_ERROR_CANNOT_HANDLE; const char fileTag [] = "file://"; - if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) { + if (NULL != decryptHandle.get() && NULL != uri && strlen(uri) > sizeof(fileTag)) { String8 uriTag = String8(uri); uriTag.toLower(); @@ -562,11 +564,11 @@ status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, } status_t FwdLockEngine::onCloseDecryptSession(int /* uniqueId */, - DecryptHandle* decryptHandle) { + sp<DecryptHandle>& decryptHandle) { status_t result = DRM_ERROR_UNKNOWN; LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession"); - if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { + if (NULL != decryptHandle.get() && decodeSessionMap.isCreated(decryptHandle->decryptId)) { DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); if (NULL != session && session->fileDesc > -1) { FwdLockFile_detach(session->fileDesc); @@ -576,7 +578,7 @@ status_t FwdLockEngine::onCloseDecryptSession(int /* uniqueId */, } } - if (NULL != decryptHandle) { + if (NULL != decryptHandle.get()) { if (NULL != decryptHandle->decryptInfo) { delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL; @@ -584,9 +586,7 @@ status_t FwdLockEngine::onCloseDecryptSession(int /* uniqueId */, decryptHandle->copyControlVector.clear(); decryptHandle->extendedData.clear(); - - delete decryptHandle; - decryptHandle = NULL; + decryptHandle.clear(); } LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit"); @@ -594,7 +594,7 @@ status_t FwdLockEngine::onCloseDecryptSession(int /* uniqueId */, } status_t FwdLockEngine::onInitializeDecryptUnit(int /* uniqueId */, - DecryptHandle* /* decryptHandle */, + sp<DecryptHandle>& /* decryptHandle */, int /* decryptUnitId */, const DrmBuffer* /* headerInfo */) { ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme"); @@ -603,7 +603,7 @@ status_t FwdLockEngine::onInitializeDecryptUnit(int /* uniqueId */, status_t FwdLockEngine::onDecrypt( int /* uniqueId */, - DecryptHandle* /* decryptHandle */, + sp<DecryptHandle>& /* decryptHandle */, int /* decryptUnitId */, const DrmBuffer* /* encBuffer */, DrmBuffer** /* decBuffer */, @@ -613,7 +613,7 @@ status_t FwdLockEngine::onDecrypt( } status_t FwdLockEngine::onDecrypt(int /* uniqueId */, - DecryptHandle* /* decryptHandle */, + sp<DecryptHandle>& /* decryptHandle */, int /* decryptUnitId */, const DrmBuffer* /* encBuffer */, DrmBuffer** /* decBuffer */) { @@ -622,19 +622,19 @@ status_t FwdLockEngine::onDecrypt(int /* uniqueId */, } status_t FwdLockEngine::onFinalizeDecryptUnit(int /* uniqueId */, - DecryptHandle* /* decryptHandle */, + sp<DecryptHandle>& /* decryptHandle */, int /* decryptUnitId */) { ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme"); return DRM_ERROR_UNKNOWN; } ssize_t FwdLockEngine::onRead(int /* uniqueId */, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, void* buffer, int numBytes) { ssize_t size = -1; - if (NULL != decryptHandle && + if (NULL != decryptHandle.get() && decodeSessionMap.isCreated(decryptHandle->decryptId) && NULL != buffer && numBytes > -1) { @@ -654,15 +654,15 @@ ssize_t FwdLockEngine::onRead(int /* uniqueId */, } #ifdef USE_64BIT_DRM_API -off64_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle, +off64_t FwdLockEngine::onLseek(int /* uniqueId */, sp<DecryptHandle>& decryptHandle, off64_t offset, int whence) { #else -off_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle, +off_t FwdLockEngine::onLseek(int /* uniqueId */, sp<DecryptHandle>& decryptHandle, off_t offset, int whence) { #endif off_t offval = -1; - if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { + if (NULL != decryptHandle.get() && decodeSessionMap.isCreated(decryptHandle->decryptId)) { DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); if (NULL != session && session->fileDesc > -1) { offval = FwdLockFile_lseek(session->fileDesc, offset, whence); @@ -675,13 +675,13 @@ off_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle, #ifdef USE_64BIT_DRM_API ssize_t FwdLockEngine::onPread(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset) { #else ssize_t FwdLockEngine::onPread(int uniqueId, - DecryptHandle* decryptHandle, + sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off_t offset) { @@ -690,7 +690,7 @@ ssize_t FwdLockEngine::onPread(int uniqueId, DecodeSession* decoderSession = NULL; - if ((NULL != decryptHandle) && + if ((NULL != decryptHandle.get()) && (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) && (NULL != buffer) && (numBytes > -1) && diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/Android.bp b/drm/libdrmframework/plugins/forward-lock/internal-format/Android.bp deleted file mode 100644 index 9f58e264fd..0000000000 --- a/drm/libdrmframework/plugins/forward-lock/internal-format/Android.bp +++ /dev/null @@ -1,5 +0,0 @@ -subdirs = [ - "common", - "converter", - "decoder", -] diff --git a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h index 7b66dc7dbd..4ab52729a3 100644 --- a/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h +++ b/drm/libdrmframework/plugins/passthru/include/DrmPassthruPlugIn.h @@ -53,10 +53,11 @@ protected: int onCheckRightsStatus(int uniqueId, const String8& path, int action); - status_t onConsumeRights(int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve); + status_t onConsumeRights(int uniqueId, sp<DecryptHandle>& decryptHandle, + int action, bool reserve); status_t onSetPlaybackStatus( - int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position); + int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position); bool onValidateAction( int uniqueId, const String8& path, int action, const ActionDescription& description); @@ -74,26 +75,25 @@ protected: DrmSupportInfo* onGetSupportInfo(int uniqueId); status_t onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length); + int uniqueId, sp<DecryptHandle>& decryptHandle, int fd, off64_t offset, + off64_t length); status_t onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, const char* uri); + int uniqueId, sp<DecryptHandle>& decryptHandle, const char* uri); - status_t onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle); + status_t onCloseDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle); - status_t onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, + status_t onInitializeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo); - status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, + status_t onDecrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV); - status_t onFinalizeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId); + status_t onFinalizeDecryptUnit(int uniqueId, sp<DecryptHandle>& decryptHandle, + int decryptUnitId); - ssize_t onPread(int uniqueId, DecryptHandle* decryptHandle, + ssize_t onPread(int uniqueId, sp<DecryptHandle>& decryptHandle, void* buffer, ssize_t numBytes, off64_t offset); - -private: - DecryptHandle* openDecryptSessionImpl(); }; }; diff --git a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp index d7f2d287c0..0fa34786db 100644 --- a/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp +++ b/drm/libdrmframework/plugins/passthru/src/DrmPassthruPlugIn.cpp @@ -183,13 +183,13 @@ int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& /*path*/ } status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, - DecryptHandle* /*decryptHandle*/, int /*action*/, bool /*reserve*/) { + sp<DecryptHandle>& /*decryptHandle*/, int /*action*/, bool /*reserve*/) { ALOGV("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId); return DRM_NO_ERROR; } status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, - DecryptHandle* /*decryptHandle*/, int /*playbackStatus*/, int64_t /*position*/) { + sp<DecryptHandle>& /*decryptHandle*/, int /*playbackStatus*/, int64_t /*position*/) { ALOGV("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId); return DRM_NO_ERROR; } @@ -236,7 +236,8 @@ DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int / } status_t DrmPassthruPlugIn::onOpenDecryptSession( - int uniqueId, DecryptHandle* decryptHandle, int /*fd*/, off64_t /*offset*/, off64_t /*length*/) { + int uniqueId, sp<DecryptHandle>& decryptHandle, int /*fd*/, off64_t /*offset*/, + off64_t /*length*/) { ALOGV("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId); #ifdef ENABLE_PASSTHRU_DECRYPTION @@ -246,36 +247,38 @@ status_t DrmPassthruPlugIn::onOpenDecryptSession( decryptHandle->decryptInfo = NULL; return DRM_NO_ERROR; #else - (void)(decryptHandle); // unused + (void)(decryptHandle.get()); // unused #endif return DRM_ERROR_CANNOT_HANDLE; } status_t DrmPassthruPlugIn::onOpenDecryptSession( - int /*uniqueId*/, DecryptHandle* /*decryptHandle*/, const char* /*uri*/) { + int /*uniqueId*/, sp<DecryptHandle>& /*decryptHandle*/, const char* /*uri*/) { return DRM_ERROR_CANNOT_HANDLE; } -status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { +status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) { ALOGV("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId); - if (NULL != decryptHandle) { + if (NULL != decryptHandle.get()) { if (NULL != decryptHandle->decryptInfo) { delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL; } - delete decryptHandle; decryptHandle = NULL; + decryptHandle.clear(); } return DRM_NO_ERROR; } -status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* /*decryptHandle*/, - int /*decryptUnitId*/, const DrmBuffer* /*headerInfo*/) { +status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, + sp<DecryptHandle>& /*decryptHandle*/, + int /*decryptUnitId*/, const DrmBuffer* /*headerInfo*/) { ALOGV("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId); return DRM_NO_ERROR; } -status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* /*decryptHandle*/, - int /*decryptUnitId*/, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* /*IV*/) { +status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, sp<DecryptHandle>& /*decryptHandle*/, + int /*decryptUnitId*/, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, + DrmBuffer* /*IV*/) { ALOGV("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId); /** * As a workaround implementation passthru would copy the given @@ -296,12 +299,12 @@ status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* /*decryptHand } status_t DrmPassthruPlugIn::onFinalizeDecryptUnit( - int uniqueId, DecryptHandle* /*decryptHandle*/, int /*decryptUnitId*/) { + int uniqueId, sp<DecryptHandle>& /*decryptHandle*/, int /*decryptUnitId*/) { ALOGV("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId); return DRM_NO_ERROR; } -ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* /*decryptHandle*/, +ssize_t DrmPassthruPlugIn::onPread(int uniqueId, sp<DecryptHandle>& /*decryptHandle*/, void* /*buffer*/, ssize_t /*numBytes*/, off64_t /*offset*/) { ALOGV("DrmPassthruPlugIn::onPread() : %d", uniqueId); return 0; diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp index 4991e50e8e..d6db1d4e2b 100644 --- a/drm/libmediadrm/Android.bp +++ b/drm/libmediadrm/Android.bp @@ -27,11 +27,11 @@ cc_library { "libmediadrmmetrics_lite", "libmediametrics", "libmediautils", - "libprotobuf-cpp-lite", "libstagefright_foundation", "libutils", "android.hardware.drm@1.0", "android.hardware.drm@1.1", + "android.hardware.drm@1.2", "libhidlallocatorutils", "libhidlbase", "libhidltransport", @@ -59,20 +59,18 @@ cc_library_shared { shared_libs: [ "android.hardware.drm@1.0", "android.hardware.drm@1.1", - "libbase", + "android.hardware.drm@1.2", "libbinder", "libhidlbase", "liblog", "libmediametrics", "libprotobuf-cpp-lite", - "libstagefright_foundation", "libutils", ], cflags: [ // Suppress unused parameter and no error options. These cause problems // with the when using the map type in a proto definition. "-Wno-unused-parameter", - "-Wno-error", ], } @@ -92,6 +90,7 @@ cc_library_shared { shared_libs: [ "android.hardware.drm@1.0", "android.hardware.drm@1.1", + "android.hardware.drm@1.2", "libbase", "libbinder", "libhidlbase", @@ -105,7 +104,6 @@ cc_library_shared { // Suppress unused parameter and no error options. These cause problems // when using the map type in a proto definition. "-Wno-unused-parameter", - "-Wno-error", ], } diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp index 3035c5a250..d62ccd6be1 100644 --- a/drm/libmediadrm/CryptoHal.cpp +++ b/drm/libmediadrm/CryptoHal.cpp @@ -30,16 +30,16 @@ #include <media/stagefright/MediaErrors.h> #include <mediadrm/CryptoHal.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::hardware::drm::V1_0::BufferType; -using ::android::hardware::drm::V1_0::DestinationBuffer; -using ::android::hardware::drm::V1_0::ICryptoFactory; -using ::android::hardware::drm::V1_0::ICryptoPlugin; -using ::android::hardware::drm::V1_0::Mode; -using ::android::hardware::drm::V1_0::Pattern; -using ::android::hardware::drm::V1_0::SharedBuffer; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_0::SubSample; using ::android::hardware::hidl_array; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_memory; @@ -50,6 +50,7 @@ using ::android::hardware::Void; using ::android::hidl::manager::V1_0::IServiceManager; using ::android::sp; +typedef drm::V1_2::Status Status_V1_2; namespace android { @@ -76,6 +77,18 @@ static status_t toStatusT(Status status) { } } +static status_t toStatusT_1_2(Status_V1_2 status) { + switch (status) { + case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE: + return ERROR_DRM_SESSION_LOST_STATE;; + case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: + return ERROR_DRM_FRAME_TOO_LARGE; + case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: + return ERROR_DRM_INSUFFICIENT_SECURITY; + default: + return toStatusT(static_cast<Status>(status)); + } +} static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) { hidl_vec<uint8_t> vec; @@ -196,6 +209,9 @@ status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data, 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); + } } } @@ -216,6 +232,7 @@ status_t CryptoHal::destroyPlugin() { } mPlugin.clear(); + mPluginV1_2.clear(); return OK; } @@ -284,7 +301,7 @@ status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, :: ssize_t offset; size_t size; - if (memory == NULL && buffer == NULL) { + if (memory == NULL || buffer == NULL) { return UNEXPECTED_NULL; } @@ -389,21 +406,33 @@ ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], status_t err = UNKNOWN_ERROR; uint32_t bytesWritten = 0; - Return<void> 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); - } - ); + Return<void> hResult; - if (!hResult.isOk()) { - err = DEAD_OBJECT; + 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_1_2(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; } diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp index cf08610173..919f4ee1df 100644 --- a/drm/libmediadrm/DrmHal.cpp +++ b/drm/libmediadrm/DrmHal.cpp @@ -23,8 +23,8 @@ #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> -#include <android/hardware/drm/1.0/types.h> -#include <android/hidl/manager/1.0/IServiceManager.h> +#include <android/hardware/drm/1.2/types.h> +#include <android/hidl/manager/1.2/IServiceManager.h> #include <hidl/ServiceManagement.h> #include <media/EventMetric.h> @@ -40,15 +40,17 @@ #include <mediadrm/DrmSessionManager.h> using drm::V1_0::KeyedVector; -using drm::V1_0::KeyStatusType; +using drm::V1_0::KeyRequestType; using drm::V1_0::KeyType; using drm::V1_0::KeyValue; -using drm::V1_1::HdcpLevel;; using drm::V1_0::SecureStop; -using drm::V1_1::SecureStopRelease; using drm::V1_0::SecureStopId; -using drm::V1_1::SecurityLevel; using drm::V1_0::Status; +using drm::V1_1::HdcpLevel; +using drm::V1_1::SecureStopRelease; +using drm::V1_1::SecurityLevel; +using drm::V1_2::KeySetId; +using drm::V1_2::KeyStatusType; using ::android::hardware::drm::V1_1::DrmMetricGroup; using ::android::hardware::hidl_array; using ::android::hardware::hidl_string; @@ -59,6 +61,10 @@ using ::android::hidl::manager::V1_0::IServiceManager; using ::android::os::PersistableBundle; using ::android::sp; +typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1; +typedef drm::V1_2::Status Status_V1_2; +typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2; + namespace { // This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant @@ -139,26 +145,55 @@ static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) { } } -static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) { +static SecurityLevel toHidlSecurityLevel(DrmPlugin::SecurityLevel level) { switch(level) { - case HdcpLevel::HDCP_NONE: + case DrmPlugin::kSecurityLevelSwSecureCrypto: + return SecurityLevel::SW_SECURE_CRYPTO; + case DrmPlugin::kSecurityLevelSwSecureDecode: + return SecurityLevel::SW_SECURE_DECODE; + case DrmPlugin::kSecurityLevelHwSecureCrypto: + return SecurityLevel::HW_SECURE_CRYPTO; + case DrmPlugin::kSecurityLevelHwSecureDecode: + return SecurityLevel::HW_SECURE_DECODE; + case DrmPlugin::kSecurityLevelHwSecureAll: + return SecurityLevel::HW_SECURE_ALL; + default: + return SecurityLevel::UNKNOWN; + } +} + +static DrmPlugin::OfflineLicenseState toOfflineLicenseState( + OfflineLicenseState licenseState) { + switch(licenseState) { + case OfflineLicenseState::USABLE: + return DrmPlugin::kOfflineLicenseStateUsable; + case OfflineLicenseState::INACTIVE: + return DrmPlugin::kOfflineLicenseStateReleased; + default: + return DrmPlugin::kOfflineLicenseStateUnknown; + } +} + +static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel_V1_2 level) { + switch(level) { + case HdcpLevel_V1_2::HDCP_NONE: return DrmPlugin::kHdcpNone; - case HdcpLevel::HDCP_V1: + case HdcpLevel_V1_2::HDCP_V1: return DrmPlugin::kHdcpV1; - case HdcpLevel::HDCP_V2: + case HdcpLevel_V1_2::HDCP_V2: return DrmPlugin::kHdcpV2; - case HdcpLevel::HDCP_V2_1: + case HdcpLevel_V1_2::HDCP_V2_1: return DrmPlugin::kHdcpV2_1; - case HdcpLevel::HDCP_V2_2: + case HdcpLevel_V1_2::HDCP_V2_2: return DrmPlugin::kHdcpV2_2; - case HdcpLevel::HDCP_NO_OUTPUT: + case HdcpLevel_V1_2::HDCP_V2_3: + return DrmPlugin::kHdcpV2_3; + case HdcpLevel_V1_2::HDCP_NO_OUTPUT: return DrmPlugin::kHdcpNoOutput; default: return DrmPlugin::kHdcpLevelUnknown; } } - - static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>& keyedVector) { std::vector<KeyValue> stdKeyedVector; @@ -199,6 +234,15 @@ static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>& return secureStopIds; } +static List<Vector<uint8_t>> toKeySetIds(const hidl_vec<KeySetId>& + hKeySetIds) { + List<Vector<uint8_t>> keySetIds; + for (size_t i = 0; i < hKeySetIds.size(); i++) { + keySetIds.push_back(toVector(hKeySetIds[i])); + } + return keySetIds; +} + static status_t toStatusT(Status status) { switch (status) { case Status::OK: @@ -217,7 +261,7 @@ static status_t toStatusT(Status status) { return ERROR_DRM_CANNOT_HANDLE; break; case Status::ERROR_DRM_INVALID_STATE: - return ERROR_DRM_TAMPER_DETECTED; + return ERROR_DRM_INVALID_STATE; break; case Status::BAD_VALUE: return BAD_VALUE; @@ -238,6 +282,19 @@ static status_t toStatusT(Status status) { } } +static status_t toStatusT_1_2(Status_V1_2 status) { + switch (status) { + case Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION: + return ERROR_DRM_RESOURCE_CONTENTION; + case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: + return ERROR_DRM_FRAME_TOO_LARGE; + case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: + return ERROR_DRM_INSUFFICIENT_SECURITY; + default: + return toStatusT(static_cast<Status>(status)); + } +} + Mutex DrmHal::mLock; @@ -297,39 +354,51 @@ void DrmHal::cleanup() { setListener(NULL); mInitCheck = NO_INIT; - - if (mPlugin != NULL) { + if (mPluginV1_2 != NULL) { + if (!mPluginV1_2->setListener(NULL).isOk()) { + mInitCheck = DEAD_OBJECT; + } + } else if (mPlugin != NULL) { if (!mPlugin->setListener(NULL).isOk()) { mInitCheck = DEAD_OBJECT; } } mPlugin.clear(); mPluginV1_1.clear(); + mPluginV1_2.clear(); } Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() { Vector<sp<IDrmFactory>> factories; - auto manager = hardware::defaultServiceManager(); + auto manager = hardware::defaultServiceManager1_2(); if (manager != NULL) { - manager->listByInterface(drm::V1_0::IDrmFactory::descriptor, + manager->listManifestByInterface(drm::V1_0::IDrmFactory::descriptor, [&factories](const hidl_vec<hidl_string> ®istered) { for (const auto &instance : registered) { auto factory = drm::V1_0::IDrmFactory::getService(instance); if (factory != NULL) { - ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str()); factories.push_back(factory); } } } ); - manager->listByInterface(drm::V1_1::IDrmFactory::descriptor, + manager->listManifestByInterface(drm::V1_1::IDrmFactory::descriptor, [&factories](const hidl_vec<hidl_string> ®istered) { for (const auto &instance : registered) { auto factory = drm::V1_1::IDrmFactory::getService(instance); if (factory != NULL) { - ALOGD("found drm@1.1 IDrmFactory %s", instance.c_str()); + factories.push_back(factory); + } + } + } + ); + manager->listByInterface(drm::V1_2::IDrmFactory::descriptor, + [&factories](const hidl_vec<hidl_string> ®istered) { + for (const auto &instance : registered) { + auto factory = drm::V1_2::IDrmFactory::getService(instance); + if (factory != NULL) { factories.push_back(factory); } } @@ -448,6 +517,17 @@ Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId, } Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId, + const hidl_vec<KeyStatus_V1_0>& keyStatusList_V1_0, bool hasNewUsableKey) { + std::vector<KeyStatus> keyStatusVec; + for (const auto &keyStatus_V1_0 : keyStatusList_V1_0) { + keyStatusVec.push_back({keyStatus_V1_0.keyId, + static_cast<KeyStatusType>(keyStatus_V1_0.type)}); + } + hidl_vec<KeyStatus> keyStatusList_V1_2(keyStatusVec); + return sendKeysChange_1_2(sessionId, keyStatusList_V1_2, hasNewUsableKey); +} + +Return<void> DrmHal::sendKeysChange_1_2(const hidl_vec<uint8_t>& sessionId, const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) { mEventLock.lock(); @@ -477,6 +557,9 @@ Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId, case KeyStatusType::STATUSPENDING: type = DrmPlugin::kKeyStatusType_StatusPending; break; + case KeyStatusType::USABLEINFUTURE: + type = DrmPlugin::kKeyStatusType_UsableInFuture; + break; case KeyStatusType::INTERNALERROR: default: type = DrmPlugin::kKeyStatusType_InternalError; @@ -501,32 +584,80 @@ Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId, return Void(); } -bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { - Mutex::Autolock autoLock(mLock); +Return<void> DrmHal::sendSessionLostState( + const hidl_vec<uint8_t>& sessionId) { + + mEventLock.lock(); + sp<IDrmClient> listener = mListener; + mEventLock.unlock(); + + if (listener != NULL) { + Parcel obj; + writeByteArray(obj, sessionId); + Mutex::Autolock lock(mNotifyLock); + listener->notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj); + } + return Void(); +} + +status_t DrmHal::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory, + const uint8_t uuid[16], + const String8 &mimeType, + DrmPlugin::SecurityLevel level, + bool *isSupported) { + *isSupported = false; + + // handle default value cases + if (level == DrmPlugin::kSecurityLevelUnknown) { + if (mimeType == "") { + // isCryptoSchemeSupported(uuid) + *isSupported = true; + } else { + // isCryptoSchemeSupported(uuid, mimeType) + *isSupported = factory->isContentTypeSupported(mimeType.string()); + } + return OK; + } else if (mimeType == "") { + return BAD_VALUE; + } - for (size_t i = 0; i < mFactories.size(); i++) { + sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory); + if (factoryV1_2 == NULL) { + return ERROR_UNSUPPORTED; + } else { + *isSupported = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, + mimeType.string(), toHidlSecurityLevel(level)); + return OK; + } +} + +status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], + const String8 &mimeType, + DrmPlugin::SecurityLevel level, + bool *isSupported) { + Mutex::Autolock autoLock(mLock); + *isSupported = false; + for (ssize_t i = mFactories.size() - 1; i >= 0; i--) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { - if (mimeType != "") { - if (mFactories[i]->isContentTypeSupported(mimeType.string())) { - return true; - } - } else { - return true; - } + return matchMimeTypeAndSecurityLevel(mFactories[i], + uuid, mimeType, level, isSupported); } } - return false; + return OK; } status_t DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) { Mutex::Autolock autoLock(mLock); - for (size_t i = 0; i < mFactories.size(); i++) { + for (ssize_t i = mFactories.size() - 1; i >= 0; i--) { if (mFactories[i]->isCryptoSchemeSupported(uuid)) { - mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName); - if (mPlugin != NULL) { + auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName); + if (plugin != NULL) { + mPlugin = plugin; mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin); + mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin); + break; } } } @@ -534,13 +665,22 @@ status_t DrmHal::createPlugin(const uint8_t uuid[16], if (mPlugin == NULL) { mInitCheck = ERROR_UNSUPPORTED; } else { - if (!mPlugin->setListener(this).isOk()) { + mInitCheck = OK; + if (mPluginV1_2 != NULL) { + if (!mPluginV1_2->setListener(this).isOk()) { + mInitCheck = DEAD_OBJECT; + } + } else if (!mPlugin->setListener(this).isOk()) { mInitCheck = DEAD_OBJECT; - } else { - mInitCheck = OK; + } + if (mInitCheck != OK) { + mPlugin.clear(); + mPluginV1_1.clear(); + mPluginV1_2.clear(); } } + return mInitCheck; } @@ -554,30 +694,15 @@ status_t DrmHal::openSession(DrmPlugin::SecurityLevel level, Mutex::Autolock autoLock(mLock); INIT_CHECK(); - SecurityLevel hSecurityLevel; + SecurityLevel hSecurityLevel = toHidlSecurityLevel(level); bool setSecurityLevel = true; - switch(level) { - case DrmPlugin::kSecurityLevelSwSecureCrypto: - hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO; - break; - case DrmPlugin::kSecurityLevelSwSecureDecode: - hSecurityLevel = SecurityLevel::SW_SECURE_DECODE; - break; - case DrmPlugin::kSecurityLevelHwSecureCrypto: - hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO; - break; - case DrmPlugin::kSecurityLevelHwSecureDecode: - hSecurityLevel = SecurityLevel::HW_SECURE_DECODE; - break; - case DrmPlugin::kSecurityLevelHwSecureAll: - hSecurityLevel = SecurityLevel::HW_SECURE_ALL; - break; - case DrmPlugin::kSecurityLevelMax: + if (level == DrmPlugin::kSecurityLevelMax) { setSecurityLevel = false; - break; - default: - return ERROR_DRM_CANNOT_HANDLE; + } else { + if (hSecurityLevel == SecurityLevel::UNKNOWN) { + return ERROR_DRM_CANNOT_HANDLE; + } } status_t err = UNKNOWN_ERROR; @@ -657,6 +782,39 @@ status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) { return DEAD_OBJECT; } +static DrmPlugin::KeyRequestType toKeyRequestType( + KeyRequestType keyRequestType) { + switch (keyRequestType) { + case KeyRequestType::INITIAL: + return DrmPlugin::kKeyRequestType_Initial; + break; + case KeyRequestType::RENEWAL: + return DrmPlugin::kKeyRequestType_Renewal; + break; + case KeyRequestType::RELEASE: + return DrmPlugin::kKeyRequestType_Release; + break; + default: + return DrmPlugin::kKeyRequestType_Unknown; + break; + } +} + +static DrmPlugin::KeyRequestType toKeyRequestType_1_1( + KeyRequestType_V1_1 keyRequestType) { + switch (keyRequestType) { + case KeyRequestType_V1_1::NONE: + return DrmPlugin::kKeyRequestType_None; + break; + case KeyRequestType_V1_1::UPDATE: + return DrmPlugin::kKeyRequestType_Update; + break; + default: + return toKeyRequestType(static_cast<KeyRequestType>(keyRequestType)); + break; + } +} + status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId, Vector<uint8_t> const &initData, String8 const &mimeType, DrmPlugin::KeyType keyType, KeyedVector<String8, @@ -683,73 +841,51 @@ status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId, ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters); status_t err = UNKNOWN_ERROR; + Return<void> hResult; - if (mPluginV1_1 != NULL) { - Return<void> hResult = - mPluginV1_1->getKeyRequest_1_1( + if (mPluginV1_2 != NULL) { + hResult = mPluginV1_2->getKeyRequest_1_2( + toHidlVec(sessionId), toHidlVec(initData), + toHidlString(mimeType), hKeyType, hOptionalParameters, + [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest, + KeyRequestType_V1_1 hKeyRequestType, + const hidl_string& hDefaultUrl) { + if (status == Status_V1_2::OK) { + request = toVector(hRequest); + defaultUrl = toString8(hDefaultUrl); + *keyRequestType = toKeyRequestType_1_1(hKeyRequestType); + } + err = toStatusT_1_2(status); + }); + } else if (mPluginV1_1 != NULL) { + hResult = mPluginV1_1->getKeyRequest_1_1( toHidlVec(sessionId), toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, [&](Status status, const hidl_vec<uint8_t>& hRequest, - drm::V1_1::KeyRequestType hKeyRequestType, - const hidl_string& hDefaultUrl) { - - if (status == Status::OK) { - request = toVector(hRequest); - defaultUrl = toString8(hDefaultUrl); - - switch (hKeyRequestType) { - case drm::V1_1::KeyRequestType::INITIAL: - *keyRequestType = DrmPlugin::kKeyRequestType_Initial; - break; - case drm::V1_1::KeyRequestType::RENEWAL: - *keyRequestType = DrmPlugin::kKeyRequestType_Renewal; - break; - case drm::V1_1::KeyRequestType::RELEASE: - *keyRequestType = DrmPlugin::kKeyRequestType_Release; - break; - case drm::V1_1::KeyRequestType::NONE: - *keyRequestType = DrmPlugin::kKeyRequestType_None; - break; - case drm::V1_1::KeyRequestType::UPDATE: - *keyRequestType = DrmPlugin::kKeyRequestType_Update; - break; - default: - *keyRequestType = DrmPlugin::kKeyRequestType_Unknown; - break; - } - err = toStatusT(status); - } - }); - return hResult.isOk() ? err : DEAD_OBJECT; - } - - Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId), - toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters, - [&](Status status, const hidl_vec<uint8_t>& hRequest, - drm::V1_0::KeyRequestType hKeyRequestType, - const hidl_string& hDefaultUrl) { - - if (status == Status::OK) { - request = toVector(hRequest); - defaultUrl = toString8(hDefaultUrl); - - switch (hKeyRequestType) { - case drm::V1_0::KeyRequestType::INITIAL: - *keyRequestType = DrmPlugin::kKeyRequestType_Initial; - break; - case drm::V1_0::KeyRequestType::RENEWAL: - *keyRequestType = DrmPlugin::kKeyRequestType_Renewal; - break; - case drm::V1_0::KeyRequestType::RELEASE: - *keyRequestType = DrmPlugin::kKeyRequestType_Release; - break; - default: - *keyRequestType = DrmPlugin::kKeyRequestType_Unknown; - break; + KeyRequestType_V1_1 hKeyRequestType, + const hidl_string& hDefaultUrl) { + if (status == Status::OK) { + request = toVector(hRequest); + defaultUrl = toString8(hDefaultUrl); + *keyRequestType = toKeyRequestType_1_1(hKeyRequestType); } err = toStatusT(status); - } - }); + }); + } else { + hResult = mPlugin->getKeyRequest( + toHidlVec(sessionId), toHidlVec(initData), + toHidlString(mimeType), hKeyType, hOptionalParameters, + [&](Status status, const hidl_vec<uint8_t>& hRequest, + KeyRequestType hKeyRequestType, + const hidl_string& hDefaultUrl) { + if (status == Status::OK) { + request = toVector(hRequest); + defaultUrl = toString8(hDefaultUrl); + *keyRequestType = toKeyRequestType(hKeyRequestType); + } + err = toStatusT(status); + }); + } err = hResult.isOk() ? err : DEAD_OBJECT; keyRequestTimer.SetAttribute(err); @@ -831,18 +967,33 @@ status_t DrmHal::getProvisionRequest(String8 const &certType, INIT_CHECK(); status_t err = UNKNOWN_ERROR; - - Return<void> hResult = mPlugin->getProvisionRequest( - toHidlString(certType), toHidlString(certAuthority), - [&](Status status, const hidl_vec<uint8_t>& hRequest, - const hidl_string& hDefaultUrl) { - if (status == Status::OK) { - request = toVector(hRequest); - defaultUrl = toString8(hDefaultUrl); + Return<void> hResult; + + if (mPluginV1_2 != NULL) { + Return<void> hResult = mPluginV1_2->getProvisionRequest_1_2( + toHidlString(certType), toHidlString(certAuthority), + [&](Status_V1_2 status, const hidl_vec<uint8_t>& hRequest, + const hidl_string& hDefaultUrl) { + if (status == Status_V1_2::OK) { + request = toVector(hRequest); + defaultUrl = toString8(hDefaultUrl); + } + err = toStatusT_1_2(status); } - err = toStatusT(status); - } - ); + ); + } else { + Return<void> hResult = mPlugin->getProvisionRequest( + toHidlString(certType), toHidlString(certAuthority), + [&](Status status, const hidl_vec<uint8_t>& hRequest, + const hidl_string& hDefaultUrl) { + if (status == Status::OK) { + request = toVector(hRequest); + defaultUrl = toString8(hDefaultUrl); + } + err = toStatusT(status); + } + ); + } err = hResult.isOk() ? err : DEAD_OBJECT; mMetrics.mGetProvisionRequestCounter.Increment(err); @@ -988,22 +1139,31 @@ status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected, } status_t err = UNKNOWN_ERROR; - if (mPluginV1_1 == NULL) { - return ERROR_DRM_CANNOT_HANDLE; - } - *connected = DrmPlugin::kHdcpLevelUnknown; *max = DrmPlugin::kHdcpLevelUnknown; - Return<void> hResult = mPluginV1_1->getHdcpLevels( - [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) { - if (status == Status::OK) { - *connected = toHdcpLevel(hConnected); - *max = toHdcpLevel(hMax); - } - err = toStatusT(status); - } - ); + Return<void> hResult; + if (mPluginV1_2 != NULL) { + hResult = mPluginV1_2->getHdcpLevels_1_2( + [&](Status_V1_2 status, const HdcpLevel_V1_2& hConnected, const HdcpLevel_V1_2& hMax) { + if (status == Status_V1_2::OK) { + *connected = toHdcpLevel(hConnected); + *max = toHdcpLevel(hMax); + } + err = toStatusT_1_2(status); + }); + } else if (mPluginV1_1 != NULL) { + hResult = mPluginV1_1->getHdcpLevels( + [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) { + if (status == Status::OK) { + *connected = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hConnected)); + *max = toHdcpLevel(static_cast<HdcpLevel_V1_2>(hMax)); + } + err = toStatusT(status); + }); + } else { + return ERROR_DRM_CANNOT_HANDLE; + } return hResult.isOk() ? err : DEAD_OBJECT; } @@ -1065,6 +1225,73 @@ status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId, return hResult.isOk() ? err : DEAD_OBJECT; } +status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPluginV1_2 == NULL) { + return ERROR_UNSUPPORTED; + } + + status_t err = UNKNOWN_ERROR; + + Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds( + [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) { + if (status == Status::OK) { + keySetIds = toKeySetIds(hKeySetIds); + } + err = toStatusT(status); + } + ); + + return hResult.isOk() ? err : DEAD_OBJECT; +} + +status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const &keySetId) { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPluginV1_2 == NULL) { + return ERROR_UNSUPPORTED; + } + + Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId)); + return status.isOk() ? toStatusT(status) : DEAD_OBJECT; +} + +status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const &keySetId, + DrmPlugin::OfflineLicenseState *licenseState) const { + Mutex::Autolock autoLock(mLock); + + if (mInitCheck != OK) { + return mInitCheck; + } + + if (mPluginV1_2 == NULL) { + return ERROR_UNSUPPORTED; + } + *licenseState = DrmPlugin::kOfflineLicenseStateUnknown; + + status_t err = UNKNOWN_ERROR; + + Return<void> hResult = mPluginV1_2->getOfflineLicenseState(toHidlVec(keySetId), + [&](Status status, OfflineLicenseState hLicenseState) { + if (status == Status::OK) { + *licenseState = toOfflineLicenseState(hLicenseState); + } + err = toStatusT(status); + } + ); + + return hResult.isOk() ? err : DEAD_OBJECT; +} + status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const { Mutex::Autolock autoLock(mLock); return getPropertyStringInternal(name, value); @@ -1343,22 +1570,22 @@ void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec) void DrmHal::reportFrameworkMetrics() const { - MediaAnalyticsItem item("mediadrm"); - item.generateSessionID(); - item.setPkgName(mMetrics.GetAppPackageName().c_str()); + std::unique_ptr<MediaAnalyticsItem> item(MediaAnalyticsItem::create("mediadrm")); + item->generateSessionID(); + item->setPkgName(mMetrics.GetAppPackageName().c_str()); String8 vendor; String8 description; status_t result = getPropertyStringInternal(String8("vendor"), vendor); if (result != OK) { ALOGE("Failed to get vendor from drm plugin: %d", result); } else { - item.setCString("vendor", vendor.c_str()); + item->setCString("vendor", vendor.c_str()); } result = getPropertyStringInternal(String8("description"), description); if (result != OK) { ALOGE("Failed to get description from drm plugin: %d", result); } else { - item.setCString("description", description.c_str()); + item->setCString("description", description.c_str()); } std::string serializedMetrics; @@ -1369,9 +1596,9 @@ void DrmHal::reportFrameworkMetrics() const std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(), serializedMetrics.size()); if (!b64EncodedMetrics.empty()) { - item.setCString("serialized_metrics", b64EncodedMetrics.c_str()); + item->setCString("serialized_metrics", b64EncodedMetrics.c_str()); } - if (!item.selfrecord()) { + if (!item->selfrecord()) { ALOGE("Failed to self record framework metrics"); } } diff --git a/drm/libmediadrm/DrmMetrics.cpp b/drm/libmediadrm/DrmMetrics.cpp index 4fed707017..308080275b 100644 --- a/drm/libmediadrm/DrmMetrics.cpp +++ b/drm/libmediadrm/DrmMetrics.cpp @@ -32,7 +32,7 @@ using ::android::drm_metrics::DrmFrameworkMetrics; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::drm::V1_0::EventType; -using ::android::hardware::drm::V1_0::KeyStatusType; +using ::android::hardware::drm::V1_2::KeyStatusType; using ::android::hardware::drm::V1_1::DrmMetricGroup; using ::android::os::PersistableBundle; diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp index 509961fb10..51274d16c1 100644 --- a/drm/libmediadrm/IDrm.cpp +++ b/drm/libmediadrm/IDrm.cpp @@ -61,7 +61,10 @@ enum { GET_NUMBER_OF_SESSIONS, GET_SECURITY_LEVEL, REMOVE_SECURE_STOP, - GET_SECURE_STOP_IDS + GET_SECURE_STOP_IDS, + GET_OFFLINE_LICENSE_KEYSET_IDS, + REMOVE_OFFLINE_LICENSE, + GET_OFFLINE_LICENSE_STATE }; struct BpDrm : public BpInterface<IDrm> { @@ -80,18 +83,22 @@ struct BpDrm : public BpInterface<IDrm> { return reply.readInt32(); } - virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) { + virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType, + DrmPlugin::SecurityLevel level, bool *isSupported) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); data.write(uuid, 16); data.writeString8(mimeType); + data.writeInt32(level); + status_t status = remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); if (status != OK) { ALOGE("isCryptoSchemeSupported: binder call failed: %d", status); - return false; + return status; } + *isSupported = static_cast<bool>(reply.readInt32()); - return reply.readInt32() != 0; + return reply.readInt32(); } virtual status_t createPlugin(const uint8_t uuid[16], @@ -120,11 +127,11 @@ struct BpDrm : public BpInterface<IDrm> { return reply.readInt32(); } - virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel, + virtual status_t openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t> &sessionId) { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); - data.writeInt32(securityLevel); + data.writeInt32(level); status_t status = remote()->transact(OPEN_SESSION, data, &reply); if (status != OK) { @@ -376,6 +383,52 @@ struct BpDrm : public BpInterface<IDrm> { return reply.readInt32(); } + virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t> > &keySetIds) const { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + status_t status = remote()->transact(GET_OFFLINE_LICENSE_KEYSET_IDS, data, &reply); + if (status != OK) { + return status; + } + + keySetIds.clear(); + uint32_t count = reply.readInt32(); + for (size_t i = 0; i < count; i++) { + Vector<uint8_t> keySetId; + readVector(reply, keySetId); + keySetIds.push_back(keySetId); + } + return reply.readInt32(); + } + + virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, keySetId); + status_t status = remote()->transact(REMOVE_OFFLINE_LICENSE, data, &reply); + if (status != OK) { + return status; + } + return reply.readInt32(); + } + + virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId, + DrmPlugin::OfflineLicenseState *licenseState) const { + Parcel data, reply; + data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); + + writeVector(data, keySetId); + status_t status = remote()->transact(GET_OFFLINE_LICENSE_STATE, data, &reply); + if (status != OK) { + *licenseState = DrmPlugin::OfflineLicenseState::kOfflineLicenseStateUnknown; + return status; + } + *licenseState = static_cast<DrmPlugin::OfflineLicenseState>(reply.readInt32()); + return reply.readInt32(); + } + virtual status_t getPropertyString(String8 const &name, String8 &value) const { Parcel data, reply; data.writeInterfaceToken(IDrm::getInterfaceDescriptor()); @@ -719,7 +772,12 @@ status_t BnDrm::onTransact( uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); String8 mimeType = data.readString8(); - reply->writeInt32(isCryptoSchemeSupported(uuid, mimeType)); + DrmPlugin::SecurityLevel level = + static_cast<DrmPlugin::SecurityLevel>(data.readInt32()); + bool isSupported = false; + status_t result = isCryptoSchemeSupported(uuid, mimeType, level, &isSupported); + reply->writeInt32(isSupported); + reply->writeInt32(result); return OK; } @@ -980,6 +1038,45 @@ status_t BnDrm::onTransact( return OK; } + case GET_OFFLINE_LICENSE_KEYSET_IDS: + { + CHECK_INTERFACE(IDrm, data, reply); + List<Vector<uint8_t> > keySetIds; + status_t result = getOfflineLicenseKeySetIds(keySetIds); + size_t count = keySetIds.size(); + reply->writeInt32(count); + List<Vector<uint8_t> >::iterator iter = keySetIds.begin(); + while(iter != keySetIds.end()) { + size_t size = iter->size(); + reply->writeInt32(size); + reply->write(iter->array(), iter->size()); + iter++; + } + reply->writeInt32(result); + return OK; + } + + case REMOVE_OFFLINE_LICENSE: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector<uint8_t> keySetId; + readVector(data, keySetId); + reply->writeInt32(removeOfflineLicense(keySetId)); + return OK; + } + + case GET_OFFLINE_LICENSE_STATE: + { + CHECK_INTERFACE(IDrm, data, reply); + Vector<uint8_t> keySetId; + readVector(data, keySetId); + DrmPlugin::OfflineLicenseState state; + status_t result = getOfflineLicenseState(keySetId, &state); + reply->writeInt32(static_cast<DrmPlugin::OfflineLicenseState>(state)); + reply->writeInt32(result); + return OK; + } + case GET_PROPERTY_STRING: { CHECK_INTERFACE(IDrm, data, reply); diff --git a/drm/libmediadrm/PluginMetricsReporting.cpp b/drm/libmediadrm/PluginMetricsReporting.cpp index 5cb48bf678..8cd6f969cc 100644 --- a/drm/libmediadrm/PluginMetricsReporting.cpp +++ b/drm/libmediadrm/PluginMetricsReporting.cpp @@ -34,17 +34,17 @@ constexpr char kSerializedMetricsField[] = "serialized_metrics"; status_t reportVendorMetrics(const std::string& metrics, const String8& name, const String8& appPackageName) { - MediaAnalyticsItem analyticsItem(name.c_str()); - analyticsItem.generateSessionID(); + std::unique_ptr<MediaAnalyticsItem> analyticsItem(MediaAnalyticsItem::create(name.c_str())); + analyticsItem->generateSessionID(); std::string app_package_name(appPackageName.c_str(), appPackageName.size()); - analyticsItem.setPkgName(app_package_name); + analyticsItem->setPkgName(app_package_name); if (metrics.size() > 0) { - analyticsItem.setCString(kSerializedMetricsField, metrics.c_str()); + analyticsItem->setCString(kSerializedMetricsField, metrics.c_str()); } - if (!analyticsItem.selfrecord()) { - ALOGE("selfrecord() returned false. sessioId %" PRId64, analyticsItem.getSessionID()); + if (!analyticsItem->selfrecord()) { + ALOGE("selfrecord() returned false. sessioId %" PRId64, analyticsItem->getSessionID()); } return OK; diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp index 66c906f2e9..9e0115e635 100644 --- a/drm/libmediadrm/tests/Android.bp +++ b/drm/libmediadrm/tests/Android.bp @@ -17,6 +17,7 @@ cc_test { shared_libs: [ "android.hardware.drm@1.0", "android.hardware.drm@1.1", + "android.hardware.drm@1.2", "libbinder", "libhidlbase", "liblog", @@ -33,7 +34,6 @@ cc_test { // Suppress unused parameter and no error options. These cause problems // when using the map type in a proto definition. "-Wno-unused-parameter", - "-Wno-error", ] } diff --git a/drm/libmediadrm/tests/DrmMetrics_test.cpp b/drm/libmediadrm/tests/DrmMetrics_test.cpp index 64aa9d0c99..5c8a1b0064 100644 --- a/drm/libmediadrm/tests/DrmMetrics_test.cpp +++ b/drm/libmediadrm/tests/DrmMetrics_test.cpp @@ -30,7 +30,7 @@ using ::android::drm_metrics::DrmFrameworkMetrics; using ::android::hardware::hidl_vec; using ::android::hardware::drm::V1_0::EventType; -using ::android::hardware::drm::V1_0::KeyStatusType; +using ::android::hardware::drm::V1_2::KeyStatusType; using ::android::hardware::drm::V1_0::Status; using ::android::hardware::drm::V1_1::DrmMetricGroup; using ::android::os::PersistableBundle; diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp index 1558e8b8da..bf352243ca 100644 --- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp +++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.cpp @@ -65,7 +65,20 @@ status_t ClearKeyCasFactory::createPlugin( *plugin = new ClearKeyCasPlugin(appData, callback); return OK; } -/////////////////////////////////////////////////////////////////////////////// + +status_t ClearKeyCasFactory::createPlugin( + int32_t CA_system_id, + void *appData, + CasPluginCallbackExt callback, + CasPlugin **plugin) { + if (!isSystemIdSupported(CA_system_id)) { + return BAD_VALUE; + } + + *plugin = new ClearKeyCasPlugin(appData, callback); + return OK; +} +//////////////////////////////////////////////////////////////////////////////// bool ClearKeyDescramblerFactory::isSystemIdSupported( int32_t CA_system_id) const { return CA_system_id == sClearKeySystemId; @@ -84,7 +97,13 @@ status_t ClearKeyDescramblerFactory::createPlugin( /////////////////////////////////////////////////////////////////////////////// ClearKeyCasPlugin::ClearKeyCasPlugin( void *appData, CasPluginCallback callback) - : mCallback(callback), mAppData(appData) { + : mCallback(callback), mCallbackExt(NULL), mAppData(appData) { + ALOGV("CTOR"); +} + +ClearKeyCasPlugin::ClearKeyCasPlugin( + void *appData, CasPluginCallbackExt callback) + : mCallback(NULL), mCallbackExt(callback), mAppData(appData) { ALOGV("CTOR"); } @@ -167,8 +186,27 @@ status_t ClearKeyCasPlugin::sendEvent( // Echo the received event to the callback. // Clear key plugin doesn't use any event, echo'ing for testing only. if (mCallback != NULL) { - mCallback((void*)mAppData, event, arg, (uint8_t*)eventData.data(), eventData.size()); + mCallback((void*)mAppData, event, arg, (uint8_t*)eventData.data(), + eventData.size()); + } else if (mCallbackExt != NULL) { + mCallbackExt((void*)mAppData, event, arg, (uint8_t*)eventData.data(), + eventData.size(), NULL); + } + return OK; +} + +status_t ClearKeyCasPlugin::sendSessionEvent( + const CasSessionId &sessionId, int32_t event, + int arg, const CasData &eventData) { + ALOGV("sendSessionEvent: sessionId=%s, event=%d, arg=%d", + sessionIdToString(sessionId).string(), event, arg); + // Echo the received event to the callback. + // Clear key plugin doesn't use any event, echo'ing for testing only. + if (mCallbackExt != NULL) { + mCallbackExt((void*)mAppData, event, arg, (uint8_t*)eventData.data(), + eventData.size(), &sessionId); } + return OK; } diff --git a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h index 389e1728d7..f48d5b1d13 100644 --- a/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h +++ b/drm/mediacas/plugins/clearkey/ClearKeyCasPlugin.h @@ -47,6 +47,11 @@ public: void *appData, CasPluginCallback callback, CasPlugin **plugin) override; + virtual status_t createPlugin( + int32_t CA_system_id, + void *appData, + CasPluginCallbackExt callback, + CasPlugin **plugin) override; }; class ClearKeyDescramblerFactory : public DescramblerFactory { @@ -63,6 +68,7 @@ public: class ClearKeyCasPlugin : public CasPlugin { public: ClearKeyCasPlugin(void *appData, CasPluginCallback callback); + ClearKeyCasPlugin(void *appData, CasPluginCallbackExt callback); virtual ~ClearKeyCasPlugin(); virtual status_t setPrivateData( @@ -85,6 +91,10 @@ public: virtual status_t sendEvent( int32_t event, int32_t arg, const CasData &eventData) override; + virtual status_t sendSessionEvent( + const CasSessionId &sessionId, + int32_t event, int32_t arg, const CasData &eventData) override; + virtual status_t provision(const String8 &str) override; virtual status_t refreshEntitlements( @@ -94,6 +104,7 @@ private: Mutex mKeyFetcherLock; std::unique_ptr<KeyFetcher> mKeyFetcher; CasPluginCallback mCallback; + CasPluginCallbackExt mCallbackExt; void* mAppData; }; diff --git a/drm/mediacas/plugins/mock/MockCasPlugin.cpp b/drm/mediacas/plugins/mock/MockCasPlugin.cpp index 8404a83935..2964791413 100644 --- a/drm/mediacas/plugins/mock/MockCasPlugin.cpp +++ b/drm/mediacas/plugins/mock/MockCasPlugin.cpp @@ -60,6 +60,19 @@ status_t MockCasFactory::createPlugin( return OK; } +status_t MockCasFactory::createPlugin( + int32_t CA_system_id, + void* /*appData*/, + CasPluginCallbackExt /*callback*/, + CasPlugin **plugin) { + if (!isSystemIdSupported(CA_system_id)) { + return BAD_VALUE; + } + + *plugin = new MockCasPlugin(); + return OK; +} + /////////////////////////////////////////////////////////////////////////////// bool MockDescramblerFactory::isSystemIdSupported(int32_t CA_system_id) const { @@ -170,6 +183,16 @@ status_t MockCasPlugin::sendEvent( return OK; } +status_t MockCasPlugin::sendSessionEvent( + const CasSessionId &sessionId, int32_t event, + int /*arg*/, const CasData& /*eventData*/) { + ALOGV("sendSessionEvent: sessionId=%s, event=%d", + arrayToString(sessionId).string(), event); + Mutex::Autolock lock(mLock); + + return OK; +} + status_t MockCasPlugin::provision(const String8 &str) { ALOGV("provision: provisionString=%s", str.string()); Mutex::Autolock lock(mLock); diff --git a/drm/mediacas/plugins/mock/MockCasPlugin.h b/drm/mediacas/plugins/mock/MockCasPlugin.h index 81069906ed..74b540cc82 100644 --- a/drm/mediacas/plugins/mock/MockCasPlugin.h +++ b/drm/mediacas/plugins/mock/MockCasPlugin.h @@ -42,6 +42,11 @@ public: void *appData, CasPluginCallback callback, CasPlugin **plugin) override; + virtual status_t createPlugin( + int32_t CA_system_id, + void *appData, + CasPluginCallbackExt callback, + CasPlugin **plugin) override; }; class MockDescramblerFactory : public DescramblerFactory { @@ -80,7 +85,11 @@ public: virtual status_t sendEvent( int32_t event, int32_t arg, const CasData &eventData) override; - virtual status_t provision(const String8 &str) override; + virtual status_t sendSessionEvent( + const CasSessionId &sessionId, + int32_t event, int32_t arg, const CasData &eventData) override; + + virtual status_t provision(const String8 &str) override; virtual status_t refreshEntitlements( int32_t refreshType, const CasData &refreshData) override; diff --git a/drm/mediadrm/Android.bp b/drm/mediadrm/Android.bp deleted file mode 100644 index b9f07f1ecd..0000000000 --- a/drm/mediadrm/Android.bp +++ /dev/null @@ -1 +0,0 @@ -subdirs = ["plugins/*"] diff --git a/drm/mediadrm/plugins/clearkey/common/Utils.cpp b/drm/mediadrm/plugins/clearkey/common/Utils.cpp index 93c643b636..d48b0a8c91 100644 --- a/drm/mediadrm/plugins/clearkey/common/Utils.cpp +++ b/drm/mediadrm/plugins/clearkey/common/Utils.cpp @@ -27,4 +27,18 @@ bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) { return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0; } +std::string ByteArrayToHexString(const uint8_t* in_buffer, size_t length) { + static const char kHexChars[] = "0123456789ABCDEF"; + + // Each input byte creates two output hex characters. + std::string out_buffer(length * 2, '\0'); + + for (size_t i = 0; i < length; ++i) { + char byte = in_buffer[i]; + out_buffer[(i * 2)] = kHexChars[(byte >> 4) & 0xf]; + out_buffer[(i * 2) + 1] = kHexChars[byte & 0xf]; + } + return out_buffer; +} + } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/common/include/Utils.h b/drm/mediadrm/plugins/clearkey/common/include/Utils.h index 25431247e0..aa571c0874 100644 --- a/drm/mediadrm/plugins/clearkey/common/include/Utils.h +++ b/drm/mediadrm/plugins/clearkey/common/include/Utils.h @@ -17,14 +17,16 @@ #ifndef CLEARKEY_UTILS_H_ #define CLEARKEY_UTILS_H_ +#include <string> #include <utils/Vector.h> +namespace android { // Add a comparison operator for this Vector specialization so that it can be // used as a key in a KeyedVector. -namespace android { - bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs); +std::string ByteArrayToHexString(const uint8_t* in_buffer, size_t length); + } // namespace android #define UNUSED(x) (void)(x); diff --git a/drm/mediadrm/plugins/clearkey/default/Android.bp b/drm/mediadrm/plugins/clearkey/default/Android.bp index 7ba57088cc..9803d32d96 100644 --- a/drm/mediadrm/plugins/clearkey/default/Android.bp +++ b/drm/mediadrm/plugins/clearkey/default/Android.bp @@ -61,7 +61,3 @@ cc_library_shared { }, } -//######################################################################## -// Build unit tests - -subdirs = ["tests"] diff --git a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp index 2fce07902e..0ac879c239 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp @@ -26,7 +26,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::drm::V1_0::SubSample; @@ -79,7 +79,7 @@ Status AesCtrDecryptor::decrypt( } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp index 341d4f645d..e91e918b1d 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp +++ b/drm/mediadrm/plugins/clearkey/hidl/Android.bp @@ -14,8 +14,8 @@ // limitations under the License. // -cc_binary { - name: "android.hardware.drm@1.1-service.clearkey", +cc_defaults { + name: "clearkey_service_defaults", vendor: true, srcs: [ @@ -25,23 +25,24 @@ cc_binary { "CreatePluginFactories.cpp", "CryptoFactory.cpp", "CryptoPlugin.cpp", + "DeviceFiles.cpp", "DrmFactory.cpp", "DrmPlugin.cpp", "InitDataParser.cpp", "JsonWebKey.cpp", + "MemoryFileSystem.cpp", "Session.cpp", "SessionLibrary.cpp", - "service.cpp", ], relative_install_path: "hw", cflags: ["-Wall", "-Werror"], - init_rc: ["android.hardware.drm@1.1-service.clearkey.rc"], shared_libs: [ "android.hardware.drm@1.0", "android.hardware.drm@1.1", + "android.hardware.drm@1.2", "libbase", "libbinder", "libcrypto", @@ -49,11 +50,13 @@ cc_binary { "libhidlmemory", "libhidltransport", "liblog", + "libprotobuf-cpp-lite", "libutils", ], static_libs: [ "libclearkeycommon", + "libclearkeydevicefiles-protos", "libjsmn", ], @@ -65,4 +68,26 @@ cc_binary { integer_overflow: true, }, } +cc_library_static { + name: "libclearkeydevicefiles-protos", + vendor: true, + proto: { + export_proto_headers: true, + type: "lite", + }, + srcs: ["protos/DeviceFiles.proto"], +} +cc_binary { + name: "android.hardware.drm@1.2-service.clearkey", + defaults: ["clearkey_service_defaults"], + srcs: ["service.cpp"], + init_rc: ["android.hardware.drm@1.2-service.clearkey.rc"], +} +cc_binary { + name: "android.hardware.drm@1.2-service-lazy.clearkey", + overrides: ["android.hardware.drm@1.2-service.clearkey"], + defaults: ["clearkey_service_defaults"], + srcs: ["serviceLazy.cpp"], + init_rc: ["android.hardware.drm@1.2-service-lazy.clearkey.rc"], +} diff --git a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp index c2ed7513f4..657a42f2e3 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp @@ -21,7 +21,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { sp<Buffer> decodeBase64(const std::string &s) { @@ -169,7 +169,7 @@ void encodeBase64Url(const void *_data, size_t size, std::string *out) { } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp index e58f58a379..75f8395a16 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp @@ -21,7 +21,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { Buffer::Buffer(size_t capacity) @@ -47,7 +47,7 @@ Buffer::~Buffer() { } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp index 1ba5c6a9ec..1410d77319 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp @@ -22,7 +22,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { extern "C" { @@ -38,7 +38,7 @@ ICryptoFactory* createCryptoFactory() { } // extern "C" } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp index 0848cef1f2..2a48db6ca9 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp @@ -27,7 +27,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { Return<bool> CryptoFactory::isCryptoSchemeSupported( @@ -60,7 +60,7 @@ Return<void> CryptoFactory::createPlugin( } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp index cd2224db97..3ecf6d5acd 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp @@ -27,7 +27,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::drm::V1_0::BufferType; @@ -42,10 +42,40 @@ Return<void> CryptoPlugin::setSharedBufferBase( return Void(); } +Return<void> CryptoPlugin::decrypt( + bool secure, + const hidl_array<uint8_t, 16>& keyId, + const hidl_array<uint8_t, 16>& iv, + Mode mode, + const Pattern& pattern, + const hidl_vec<SubSample>& subSamples, + const SharedBuffer& source, + uint64_t offset, + const DestinationBuffer& destination, + decrypt_cb _hidl_cb) { + + Status status = Status::ERROR_DRM_UNKNOWN; + hidl_string detailedError; + uint32_t bytesWritten = 0; + + Return<void> hResult = decrypt_1_2( + secure, keyId, iv, mode, pattern, subSamples, source, offset, destination, + [&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) { + status = toStatus_1_0(hStatus); + bytesWritten = hBytesWritten; + detailedError = hDetailedError; + } + ); + + status = hResult.isOk() ? status : Status::ERROR_DRM_CANNOT_HANDLE; + _hidl_cb(status, bytesWritten, detailedError); + return Void(); +} + // Returns negative values for error code and positive values for the size of // decrypted data. In theory, the output size can be larger than the input // size, but in practice this will never happen for AES-CTR. -Return<void> CryptoPlugin::decrypt( +Return<void> CryptoPlugin::decrypt_1_2( bool secure, const hidl_array<uint8_t, KEY_ID_SIZE>& keyId, const hidl_array<uint8_t, KEY_IV_SIZE>& iv, @@ -55,17 +85,17 @@ Return<void> CryptoPlugin::decrypt( const SharedBuffer& source, uint64_t offset, const DestinationBuffer& destination, - decrypt_cb _hidl_cb) { + decrypt_1_2_cb _hidl_cb) { UNUSED(pattern); if (secure) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Secure decryption is not supported with ClearKey."); return Void(); } if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set"); return Void(); } @@ -73,24 +103,24 @@ Return<void> CryptoPlugin::decrypt( if (destination.type == BufferType::SHARED_MEMORY) { const SharedBuffer& dest = destination.nonsecureMemory; if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set"); return Void(); } } else { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination type not supported"); return Void(); } sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId]; if (sourceBase == nullptr) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); return Void(); } if (source.offset + offset + source.size > sourceBase->getSize()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); return Void(); } @@ -102,18 +132,19 @@ Return<void> CryptoPlugin::decrypt( const SharedBuffer& destBuffer = destination.nonsecureMemory; sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId]; if (destBase == nullptr) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); return Void(); } base = static_cast<uint8_t *>(static_cast<void *>(destBase->getPointer())); if (destBuffer.offset + destBuffer.size > destBase->getSize()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); + _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size"); return Void(); } destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset); + // Calculate the output buffer size and determine if any subsamples are // encrypted. size_t destSize = 0; @@ -121,11 +152,11 @@ Return<void> CryptoPlugin::decrypt( for (size_t i = 0; i < subSamples.size(); i++) { const SubSample &subSample = subSamples[i]; if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize)) { - _hidl_cb(Status::BAD_VALUE, 0, "subsample clear size overflow"); + _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample clear size overflow"); return Void(); } if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize)) { - _hidl_cb(Status::BAD_VALUE, 0, "subsample encrypted size overflow"); + _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample encrypted size overflow"); return Void(); } if (subSample.numBytesOfEncryptedData > 0) { @@ -134,13 +165,13 @@ Return<void> CryptoPlugin::decrypt( } if (destSize > destBuffer.size) { - _hidl_cb(Status::BAD_VALUE, 0, "subsample sum too large"); + _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample sum too large"); return Void(); } if (mode == Mode::UNENCRYPTED) { if (haveEncryptedSubsamples) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Encrypted subsamples found in allegedly unencrypted data."); return Void(); } @@ -156,22 +187,21 @@ Return<void> CryptoPlugin::decrypt( } } - _hidl_cb(Status::OK, static_cast<ssize_t>(offset), ""); + _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(offset), ""); return Void(); } else if (mode == Mode::AES_CTR) { size_t bytesDecrypted; - Status res = mSession->decrypt(keyId.data(), iv.data(), srcPtr, + Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr, static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted); - if (res == Status::OK) { - _hidl_cb(Status::OK, static_cast<ssize_t>(bytesDecrypted), ""); + if (res == Status_V1_2::OK) { + _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(bytesDecrypted), ""); return Void(); } else { - _hidl_cb(Status::ERROR_DRM_DECRYPT, static_cast<ssize_t>(res), - "Decryption Error"); + _hidl_cb(res, 0, "Decryption Error"); return Void(); } } else { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Selected encryption mode is not supported by the ClearKey DRM Plugin."); return Void(); } @@ -191,7 +221,7 @@ Return<Status> CryptoPlugin::setMediaDrmSession( } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp new file mode 100644 index 0000000000..2415b6fe5e --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp @@ -0,0 +1,252 @@ +// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine Master +// License Agreement. + +#include <utils/Log.h> + +#include <string> +#include <sys/stat.h> + +#include "DeviceFiles.h" +#include "Utils.h" + +#include <openssl/sha.h> + +// Protobuf generated classes. +using android::hardware::drm::V1_2::clearkey::OfflineFile; +using android::hardware::drm::V1_2::clearkey::HashedFile; +using android::hardware::drm::V1_2::clearkey::License; +using android::hardware::drm::V1_2::clearkey::License_LicenseState_ACTIVE; +using android::hardware::drm::V1_2::clearkey::License_LicenseState_RELEASING; + +namespace { +const char kLicenseFileNameExt[] = ".lic"; + +bool Hash(const std::string& data, std::string* hash) { + if (!hash) return false; + + hash->resize(SHA256_DIGEST_LENGTH); + + const unsigned char* input = reinterpret_cast<const unsigned char*>(data.data()); + unsigned char* output = reinterpret_cast<unsigned char*>(&(*hash)[0]); + SHA256(input, data.size(), output); + return true; +} + +} // namespace + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace clearkey { + +bool DeviceFiles::StoreLicense( + const std::string& keySetId, LicenseState state, + const std::string& licenseResponse) { + + OfflineFile file; + file.set_type(OfflineFile::LICENSE); + file.set_version(OfflineFile::VERSION_1); + + License* license = file.mutable_license(); + switch (state) { + case kLicenseStateActive: + license->set_state(License_LicenseState_ACTIVE); + license->set_license(licenseResponse); + break; + case kLicenseStateReleasing: + license->set_state(License_LicenseState_RELEASING); + license->set_license(licenseResponse); + break; + default: + ALOGW("StoreLicense: Unknown license state: %u", state); + return false; + } + + std::string serializedFile; + file.SerializeToString(&serializedFile); + + return StoreFileWithHash(keySetId + kLicenseFileNameExt, serializedFile); +} + +bool DeviceFiles::StoreFileWithHash(const std::string& fileName, + const std::string& serializedFile) { + std::string hash; + if (!Hash(serializedFile, &hash)) { + ALOGE("StoreFileWithHash: Failed to compute hash"); + return false; + } + + HashedFile hashFile; + hashFile.set_file(serializedFile); + hashFile.set_hash(hash); + + std::string serializedHashFile; + hashFile.SerializeToString(&serializedHashFile); + + return StoreFileRaw(fileName, serializedHashFile); +} + +bool DeviceFiles::StoreFileRaw(const std::string& fileName, const std::string& serializedHashFile) { + MemoryFileSystem::MemoryFile memFile; + memFile.setFileName(fileName); + memFile.setContent(serializedHashFile); + memFile.setFileSize(serializedHashFile.size()); + size_t len = mFileHandle.Write(fileName, memFile); + + if (len != static_cast<size_t>(serializedHashFile.size())) { + ALOGE("StoreFileRaw: Failed to write %s", fileName.c_str()); + ALOGD("StoreFileRaw: expected=%zd, actual=%zu", serializedHashFile.size(), len); + return false; + } + + ALOGD("StoreFileRaw: wrote %zu bytes to %s", serializedHashFile.size(), fileName.c_str()); + return true; +} + +bool DeviceFiles::RetrieveLicense( + const std::string& keySetId, LicenseState* state, std::string* offlineLicense) { + + OfflineFile file; + if (!RetrieveHashedFile(keySetId + kLicenseFileNameExt, &file)) { + return false; + } + + if (file.type() != OfflineFile::LICENSE) { + ALOGE("RetrieveLicense: Invalid file type"); + return false; + } + + if (file.version() != OfflineFile::VERSION_1) { + ALOGE("RetrieveLicense: Invalid file version"); + return false; + } + + if (!file.has_license()) { + ALOGE("RetrieveLicense: License not present"); + return false; + } + + License license = file.license(); + switch (license.state()) { + case License_LicenseState_ACTIVE: + *state = kLicenseStateActive; + break; + case License_LicenseState_RELEASING: + *state = kLicenseStateReleasing; + break; + default: + ALOGW("RetrieveLicense: Unrecognized license state: %u", + kLicenseStateUnknown); + *state = kLicenseStateUnknown; + break; + } + *offlineLicense = license.license(); + return true; +} + +bool DeviceFiles::DeleteLicense(const std::string& keySetId) { + return mFileHandle.RemoveFile(keySetId + kLicenseFileNameExt); +} + +bool DeviceFiles::DeleteAllLicenses() { + return mFileHandle.RemoveAllFiles(); +} + +bool DeviceFiles::LicenseExists(const std::string& keySetId) { + return mFileHandle.FileExists(keySetId + kLicenseFileNameExt); +} + +std::vector<std::string> DeviceFiles::ListLicenses() const { + std::vector<std::string> licenses = mFileHandle.ListFiles(); + for (size_t i = 0; i < licenses.size(); i++) { + std::string& license = licenses[i]; + license = license.substr(0, license.size() - strlen(kLicenseFileNameExt)); + } + return licenses; +} + +bool DeviceFiles::RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile) { + if (!deSerializedFile) { + ALOGE("RetrieveHashedFile: invalid file parameter"); + return false; + } + + if (!FileExists(fileName)) { + ALOGE("RetrieveHashedFile: %s does not exist", fileName.c_str()); + return false; + } + + ssize_t bytes = GetFileSize(fileName); + if (bytes <= 0) { + ALOGE("RetrieveHashedFile: invalid file size: %s", fileName.c_str()); + // Remove the corrupted file so the caller will not get the same error + // when trying to access the file repeatedly, causing the system to stall. + RemoveFile(fileName); + return false; + } + + std::string serializedHashFile; + serializedHashFile.resize(bytes); + bytes = mFileHandle.Read(fileName, &serializedHashFile); + + if (bytes != static_cast<ssize_t>(serializedHashFile.size())) { + ALOGE("RetrieveHashedFile: Failed to read from %s", fileName.c_str()); + ALOGV("RetrieveHashedFile: expected: %zd, actual: %zd", serializedHashFile.size(), bytes); + // Remove the corrupted file so the caller will not get the same error + // when trying to access the file repeatedly, causing the system to stall. + RemoveFile(fileName); + return false; + } + + ALOGV("RetrieveHashedFile: read %zd from %s", bytes, fileName.c_str()); + + HashedFile hashFile; + if (!hashFile.ParseFromString(serializedHashFile)) { + ALOGE("RetrieveHashedFile: Unable to parse hash file"); + // Remove corrupt file. + RemoveFile(fileName); + return false; + } + + std::string hash; + if (!Hash(hashFile.file(), &hash)) { + ALOGE("RetrieveHashedFile: Hash computation failed"); + return false; + } + + if (hash != hashFile.hash()) { + ALOGE("RetrieveHashedFile: Hash mismatch"); + // Remove corrupt file. + RemoveFile(fileName); + return false; + } + + if (!deSerializedFile->ParseFromString(hashFile.file())) { + ALOGE("RetrieveHashedFile: Unable to parse file"); + // Remove corrupt file. + RemoveFile(fileName); + return false; + } + + return true; +} + +bool DeviceFiles::FileExists(const std::string& fileName) const { + return mFileHandle.FileExists(fileName); +} + +bool DeviceFiles::RemoveFile(const std::string& fileName) { + return mFileHandle.RemoveFile(fileName); +} + +ssize_t DeviceFiles::GetFileSize(const std::string& fileName) const { + return mFileHandle.GetFileSize(fileName); +} + +} // namespace clearkey +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp index 77557f9da9..9fb5bbefa5 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp @@ -30,10 +30,11 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::drm::V1_0::Status; +using ::android::hardware::drm::V1_1::SecurityLevel; using ::android::hardware::Void; Return<bool> DrmFactory::isCryptoSchemeSupported( @@ -41,6 +42,13 @@ Return<bool> DrmFactory::isCryptoSchemeSupported( return clearkeydrm::isClearKeyUUID(uuid.data()); } +Return<bool> DrmFactory::isCryptoSchemeSupported_1_2(const hidl_array<uint8_t, 16>& uuid, + const hidl_string &mimeType, + SecurityLevel level) { + return isCryptoSchemeSupported(uuid) && isContentTypeSupported(mimeType) && + level == SecurityLevel::SW_SECURE_CRYPTO; +} + Return<bool> DrmFactory::isContentTypeSupported(const hidl_string &mimeType) { // This should match the mimeTypes handed by InitDataParser. return mimeType == kIsoBmffVideoMimeType || @@ -71,7 +79,7 @@ Return<void> DrmFactory::createPlugin( } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp index 30f745913a..7cb5a38f35 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp @@ -25,11 +25,15 @@ #include "ClearKeyDrmProperties.h" #include "Session.h" #include "TypeConvert.h" +#include "Utils.h" namespace { +const std::string kKeySetIdPrefix("ckid"); +const int kKeySetIdLength = 16; const int kSecureStopIdStart = 100; +const std::string kOfflineLicense("\"type\":\"persistent-license\""); const std::string kStreaming("Streaming"); -const std::string kOffline("Offline"); +const std::string kTemporaryLicense("\"type\":\"temporary\""); const std::string kTrue("True"); const std::string kQueryKeyLicenseType("LicenseType"); @@ -54,18 +58,31 @@ std::vector<uint8_t> uint32ToVector(uint32_t value) { namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { +KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) { + switch (keyRequestType) { + case KeyRequestType_V1_1::NONE: + case KeyRequestType_V1_1::UPDATE: + return KeyRequestType::UNKNOWN; + default: + return static_cast<KeyRequestType>(keyRequestType); + } +} + DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary) : mSessionLibrary(sessionLibrary), mOpenSessionOkCount(0), mCloseSessionOkCount(0), mCloseSessionNotOpenedCount(0), - mNextSecureStopId(kSecureStopIdStart) { + mNextSecureStopId(kSecureStopIdStart), + mMockError(Status_V1_2::OK) { mPlayPolicy.clear(); initProperties(); mSecureStops.clear(); + mReleaseKeysMap.clear(); + std::srand(std::time(nullptr)); } void DrmPlugin::initProperties() { @@ -75,6 +92,7 @@ void DrmPlugin::initProperties() { mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue; mStringProperties[kAlgorithmsKey] = kAlgorithmsValue; mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue; + mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue; std::vector<uint8_t> valueVector; valueVector.clear(); @@ -103,6 +121,7 @@ void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) { Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) { sp<Session> session = mSessionLibrary->createSession(); + processMockError(session); std::vector<uint8_t> sessionId = session->sessionId(); Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO); @@ -114,6 +133,7 @@ Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) { Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel, openSession_1_1_cb _hidl_cb) { sp<Session> session = mSessionLibrary->createSession(); + processMockError(session); std::vector<uint8_t> sessionId = session->sessionId(); Status status = setSecurityLevel(sessionId, securityLevel); @@ -129,6 +149,10 @@ Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) { sp<Session> session = mSessionLibrary->findSession(toVector(sessionId)); if (session.get()) { + if (session->getMockError() != Status_V1_2::OK) { + sendSessionLostState(sessionId); + return Status::ERROR_DRM_INVALID_STATE; + } mCloseSessionOkCount++; mSessionLibrary->destroySession(session); return Status::OK; @@ -137,35 +161,75 @@ Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) { return Status::ERROR_DRM_SESSION_NOT_OPENED; } -Status DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope, +Status_V1_2 DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope, const hidl_vec<uint8_t>& initData, const hidl_string& mimeType, KeyType keyType, const hidl_vec<KeyValue>& optionalParameters, std::vector<uint8_t> *request, - KeyRequestType *keyRequestType, + KeyRequestType_V1_1 *keyRequestType, std::string *defaultUrl) { UNUSED(optionalParameters); + // GetKeyRequestOfflineKeyTypeNotSupported() in vts 1.0 and 1.1 expects + // KeyType::OFFLINE to return ERROR_DRM_CANNOT_HANDLE in clearkey plugin. + // Those tests pass in an empty initData, we use the empty initData to + // signal such specific use case. + if (keyType == KeyType::OFFLINE && 0 == initData.size()) { + return Status_V1_2::ERROR_DRM_CANNOT_HANDLE; + } + *defaultUrl = ""; - *keyRequestType = KeyRequestType::UNKNOWN; + *keyRequestType = KeyRequestType_V1_1::UNKNOWN; *request = std::vector<uint8_t>(); - if (scope.size() == 0) { - return Status::BAD_VALUE; + if (scope.size() == 0 || + (keyType != KeyType::STREAMING && + keyType != KeyType::OFFLINE && + keyType != KeyType::RELEASE)) { + return Status_V1_2::BAD_VALUE; } - if (keyType != KeyType::STREAMING) { - return Status::ERROR_DRM_CANNOT_HANDLE; - } + const std::vector<uint8_t> scopeId = toVector(scope); + sp<Session> session; + if (keyType == KeyType::STREAMING || keyType == KeyType::OFFLINE) { + std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end()); + session = mSessionLibrary->findSession(sessionId); + if (!session.get()) { + return Status_V1_2::ERROR_DRM_SESSION_NOT_OPENED; + } else if (session->getMockError() != Status_V1_2::OK) { + return session->getMockError(); + } - sp<Session> session = mSessionLibrary->findSession(toVector(scope)); - if (!session.get()) { - return Status::ERROR_DRM_SESSION_NOT_OPENED; + *keyRequestType = KeyRequestType_V1_1::INITIAL; } - Status status = session->getKeyRequest(initData, mimeType, request); - *keyRequestType = KeyRequestType::INITIAL; + Status_V1_2 status = static_cast<Status_V1_2>( + session->getKeyRequest(initData, mimeType, keyType, request)); + + if (keyType == KeyType::RELEASE) { + std::vector<uint8_t> keySetId(scopeId.begin(), scopeId.end()); + std::string requestString(request->begin(), request->end()); + if (requestString.find(kOfflineLicense) != std::string::npos) { + std::string emptyResponse; + std::string keySetIdString(keySetId.begin(), keySetId.end()); + if (!mFileHandle.StoreLicense(keySetIdString, + DeviceFiles::kLicenseStateReleasing, + emptyResponse)) { + ALOGE("Problem releasing offline license"); + return Status_V1_2::ERROR_DRM_UNKNOWN; + } + if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) { + sp<Session> session = mSessionLibrary->createSession(); + mReleaseKeysMap[keySetIdString] = session->sessionId(); + } else { + ALOGI("key is in use, ignore release request"); + } + } else { + ALOGE("Offline license not found, nothing to release"); + } + *keyRequestType = KeyRequestType_V1_1::RELEASE; + } return status; } @@ -178,15 +242,15 @@ Return<void> DrmPlugin::getKeyRequest( getKeyRequest_cb _hidl_cb) { UNUSED(optionalParameters); - KeyRequestType keyRequestType = KeyRequestType::UNKNOWN; + KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN; std::string defaultUrl(""); std::vector<uint8_t> request; - Status status = getKeyRequestCommon( + Status_V1_2 status = getKeyRequestCommon( scope, initData, mimeType, keyType, optionalParameters, &request, &keyRequestType, &defaultUrl); - _hidl_cb(status, toHidlVec(request), - static_cast<drm::V1_0::KeyRequestType>(keyRequestType), + _hidl_cb(toStatus_1_0(status), toHidlVec(request), + toKeyRequestType_V1_0(keyRequestType), hidl_string(defaultUrl)); return Void(); } @@ -200,10 +264,31 @@ Return<void> DrmPlugin::getKeyRequest_1_1( getKeyRequest_1_1_cb _hidl_cb) { UNUSED(optionalParameters); - KeyRequestType keyRequestType = KeyRequestType::UNKNOWN; + KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN; + std::string defaultUrl(""); + std::vector<uint8_t> request; + Status_V1_2 status = getKeyRequestCommon( + scope, initData, mimeType, keyType, optionalParameters, + &request, &keyRequestType, &defaultUrl); + + _hidl_cb(toStatus_1_0(status), toHidlVec(request), + keyRequestType, hidl_string(defaultUrl)); + return Void(); +} + +Return<void> DrmPlugin::getKeyRequest_1_2( + const hidl_vec<uint8_t>& scope, + const hidl_vec<uint8_t>& initData, + const hidl_string& mimeType, + KeyType keyType, + const hidl_vec<KeyValue>& optionalParameters, + getKeyRequest_1_2_cb _hidl_cb) { + UNUSED(optionalParameters); + + KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN; std::string defaultUrl(""); std::vector<uint8_t> request; - Status status = getKeyRequestCommon( + Status_V1_2 status = getKeyRequestCommon( scope, initData, mimeType, keyType, optionalParameters, &request, &keyRequestType, &defaultUrl); @@ -227,6 +312,30 @@ void DrmPlugin::setPlayPolicy() { mPlayPolicy.push_back(policy); } +bool DrmPlugin::makeKeySetId(std::string* keySetId) { + if (!keySetId) { + ALOGE("keySetId destination not provided"); + return false; + } + std::vector<uint8_t> ksid(kKeySetIdPrefix.begin(), kKeySetIdPrefix.end()); + ksid.resize(kKeySetIdLength); + std::vector<uint8_t> randomData((kKeySetIdLength - kKeySetIdPrefix.size()) / 2, 0); + + while (keySetId->empty()) { + for (auto itr = randomData.begin(); itr != randomData.end(); ++itr) { + *itr = std::rand() % 0xff; + } + *keySetId = kKeySetIdPrefix + ByteArrayToHexString( + reinterpret_cast<const uint8_t*>(randomData.data()), randomData.size()); + if (mFileHandle.LicenseExists(*keySetId)) { + // collision, regenerate + ALOGV("Retry generating KeySetId"); + keySetId->clear(); + } + } + return true; +} + Return<void> DrmPlugin::provideKeyResponse( const hidl_vec<uint8_t>& scope, const hidl_vec<uint8_t>& response, @@ -237,28 +346,124 @@ Return<void> DrmPlugin::provideKeyResponse( return Void(); } - sp<Session> session = mSessionLibrary->findSession(toVector(scope)); + std::string responseString( + reinterpret_cast<const char*>(response.data()), response.size()); + const std::vector<uint8_t> scopeId = toVector(scope); + std::vector<uint8_t> sessionId; + std::string keySetId; + + Status status = Status::OK; + bool isOfflineLicense = responseString.find(kOfflineLicense) != std::string::npos; + bool isRelease = (memcmp(scopeId.data(), kKeySetIdPrefix.data(), kKeySetIdPrefix.size()) == 0); + if (isRelease) { + keySetId.assign(scopeId.begin(), scopeId.end()); + + auto iter = mReleaseKeysMap.find(std::string(keySetId.begin(), keySetId.end())); + if (iter != mReleaseKeysMap.end()) { + sessionId.assign(iter->second.begin(), iter->second.end()); + } + } else { + sessionId.assign(scopeId.begin(), scopeId.end()); + // non offline license returns empty keySetId + keySetId.clear(); + } + + sp<Session> session = mSessionLibrary->findSession(sessionId); if (!session.get()) { _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>()); return Void(); } - setPlayPolicy(); - std::vector<uint8_t> keySetId; - Status status = session->provideKeyResponse(response); + + status = session->provideKeyResponse(response); if (status == Status::OK) { - // This is for testing AMediaDrm_setOnEventListener only. - sendEvent(EventType::VENDOR_DEFINED, 0, scope); - keySetId.clear(); - } + if (isOfflineLicense) { + if (isRelease) { + mFileHandle.DeleteLicense(keySetId); + } else { + if (!makeKeySetId(&keySetId)) { + _hidl_cb(Status::ERROR_DRM_UNKNOWN, hidl_vec<uint8_t>()); + return Void(); + } + + bool ok = mFileHandle.StoreLicense( + keySetId, + DeviceFiles::kLicenseStateActive, + std::string(response.begin(), response.end())); + if (!ok) { + ALOGE("Failed to store offline license"); + } + } + } + + // Test calling AMediaDrm listeners. + sendEvent(EventType::VENDOR_DEFINED, sessionId, sessionId); + + sendExpirationUpdate(sessionId, 100); + + std::vector<KeyStatus_V1_2> keysStatus; + KeyStatus_V1_2 keyStatus; + + std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC }; + keyStatus.keyId = keyId1; + keyStatus.type = V1_2::KeyStatusType::USABLE; + keysStatus.push_back(keyStatus); + + std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF }; + keyStatus.keyId = keyId2; + keyStatus.type = V1_2::KeyStatusType::EXPIRED; + keysStatus.push_back(keyStatus); + + std::vector<uint8_t> keyId3 = { 0x0, 0x1, 0x2 }; + keyStatus.keyId = keyId3; + keyStatus.type = V1_2::KeyStatusType::USABLEINFUTURE; + keysStatus.push_back(keyStatus); + + sendKeysChange_1_2(sessionId, keysStatus, true); - installSecureStop(scope); + installSecureStop(sessionId); + } else { + ALOGE("provideKeyResponse returns error=%d", status); + } - // Returns status and empty keySetId - _hidl_cb(status, toHidlVec(keySetId)); + std::vector<uint8_t> keySetIdVec(keySetId.begin(), keySetId.end()); + _hidl_cb(status, toHidlVec(keySetIdVec)); return Void(); } +Return<Status> DrmPlugin::restoreKeys( + const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& keySetId) { + if (sessionId.size() == 0 || keySetId.size() == 0) { + return Status::BAD_VALUE; + } + + DeviceFiles::LicenseState licenseState; + std::string offlineLicense; + Status status = Status::OK; + if (!mFileHandle.RetrieveLicense(std::string(keySetId.begin(), keySetId.end()), + &licenseState, &offlineLicense)) { + ALOGE("Failed to restore offline license"); + return Status::ERROR_DRM_NO_LICENSE; + } + + if (DeviceFiles::kLicenseStateUnknown == licenseState || + DeviceFiles::kLicenseStateReleasing == licenseState) { + ALOGE("Invalid license state=%d", licenseState); + return Status::ERROR_DRM_NO_LICENSE; + } + + sp<Session> session = mSessionLibrary->findSession(toVector(sessionId)); + if (!session.get()) { + return Status::ERROR_DRM_SESSION_NOT_OPENED; + } + status = session->provideKeyResponse(std::vector<uint8_t>(offlineLicense.begin(), + offlineLicense.end())); + if (status != Status::OK) { + ALOGE("Failed to restore keys"); + } + return status; +} + Return<void> DrmPlugin::getPropertyString( const hidl_string& propertyName, getPropertyString_cb _hidl_cb) { std::string name(propertyName.c_str()); @@ -274,6 +479,8 @@ Return<void> DrmPlugin::getPropertyString( value = mStringProperties[kAlgorithmsKey]; } else if (name == kListenerTestSupportKey) { value = mStringProperties[kListenerTestSupportKey]; + } else if (name == kDrmErrorTestKey) { + value = mStringProperties[kDrmErrorTestKey]; } else { ALOGE("App requested unknown string property %s", name.c_str()); _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, ""); @@ -318,6 +525,20 @@ Return<Status> DrmPlugin::setPropertyString( return Status::BAD_VALUE; } + if (name == kDrmErrorTestKey) { + if (value == kResourceContentionValue) { + mMockError = Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION; + } else if (value == kLostStateValue) { + mMockError = Status_V1_2::ERROR_DRM_SESSION_LOST_STATE; + } else if (value == kFrameTooLargeValue) { + mMockError = Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE; + } else if (value == kInvalidStateValue) { + mMockError = Status_V1_2::ERROR_DRM_INVALID_STATE; + } else { + mMockError = Status_V1_2::ERROR_DRM_UNKNOWN; + } + } + mStringProperties[key] = std::string(value.c_str()); return Status::OK; } @@ -328,6 +549,9 @@ Return<Status> DrmPlugin::setPropertyByteArray( if (name == kDeviceIdKey) { ALOGD("Cannot set immutable property: %s", name.c_str()); return Status::BAD_VALUE; + } else if (name == kClientIdKey) { + mByteArrayProperties[kClientIdKey] = toVector(value); + return Status::OK; } // Setting of undefined properties is not supported @@ -465,6 +689,60 @@ Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) { return Void(); } +Return<void> DrmPlugin::getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) { + std::vector<std::string> licenseNames = mFileHandle.ListLicenses(); + std::vector<KeySetId> keySetIds; + if (mMockError != Status_V1_2::OK) { + _hidl_cb(toStatus_1_0(mMockError), keySetIds); + return Void(); + } + for (const auto& name : licenseNames) { + std::vector<uint8_t> keySetId(name.begin(), name.end()); + keySetIds.push_back(keySetId); + } + _hidl_cb(Status::OK, keySetIds); + return Void(); +} + + +Return<Status> DrmPlugin::removeOfflineLicense(const KeySetId& keySetId) { + if (mMockError != Status_V1_2::OK) { + return toStatus_1_0(mMockError); + } + std::string licenseName(keySetId.begin(), keySetId.end()); + if (mFileHandle.DeleteLicense(licenseName)) { + return Status::OK; + } + return Status::BAD_VALUE; +} + +Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId, + getOfflineLicenseState_cb _hidl_cb) { + std::string licenseName(keySetId.begin(), keySetId.end()); + DeviceFiles::LicenseState state; + std::string license; + OfflineLicenseState hLicenseState; + if (mMockError != Status_V1_2::OK) { + _hidl_cb(toStatus_1_0(mMockError), OfflineLicenseState::UNKNOWN); + } else if (mFileHandle.RetrieveLicense(licenseName, &state, &license)) { + switch (state) { + case DeviceFiles::kLicenseStateActive: + hLicenseState = OfflineLicenseState::USABLE; + break; + case DeviceFiles::kLicenseStateReleasing: + hLicenseState = OfflineLicenseState::INACTIVE; + break; + case DeviceFiles::kLicenseStateUnknown: + hLicenseState = OfflineLicenseState::UNKNOWN; + break; + } + _hidl_cb(Status::OK, hLicenseState); + } else { + _hidl_cb(Status::BAD_VALUE, OfflineLicenseState::UNKNOWN); + } + return Void(); +} + Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) { std::vector<SecureStop> stops; for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) { @@ -572,7 +850,7 @@ Return<Status> DrmPlugin::removeAllSecureStops() { } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp index e2bb6517ea..b988ce03ca 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp @@ -31,7 +31,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { namespace { @@ -45,21 +45,22 @@ std::vector<uint8_t> StrToVector(const std::string& str) { } Status InitDataParser::parse(const std::vector<uint8_t>& initData, - const std::string& type, + const std::string& mimeType, + V1_0::KeyType keyType, std::vector<uint8_t>* licenseRequest) { // Build a list of the key IDs std::vector<const uint8_t*> keyIds; - if (type == kIsoBmffVideoMimeType || - type == kIsoBmffAudioMimeType || - type == kCencInitDataFormat) { + if (mimeType == kIsoBmffVideoMimeType.c_str() || + mimeType == kIsoBmffAudioMimeType.c_str() || + mimeType == kCencInitDataFormat.c_str()) { Status res = parsePssh(initData, &keyIds); if (res != Status::OK) { return res; } - } else if (type == kWebmVideoMimeType || - type == kWebmAudioMimeType || - type == kWebmInitDataFormat) { + } else if (mimeType == kWebmVideoMimeType.c_str() || + mimeType == kWebmAudioMimeType.c_str() || + mimeType == kWebmInitDataFormat.c_str()) { // WebM "init data" is just a single key ID if (initData.size() != kKeyIdSize) { return Status::ERROR_DRM_CANNOT_HANDLE; @@ -69,8 +70,12 @@ Status InitDataParser::parse(const std::vector<uint8_t>& initData, return Status::ERROR_DRM_CANNOT_HANDLE; } + if (keyType == V1_0::KeyType::RELEASE) { + // restore key + } + // Build the request - std::string requestJson = generateRequest(keyIds); + std::string requestJson = generateRequest(keyType, keyIds); std::vector<uint8_t> requestJsonVec = StrToVector(requestJson); licenseRequest->clear(); @@ -131,9 +136,11 @@ Status InitDataParser::parsePssh(const std::vector<uint8_t>& initData, return Status::OK; } -std::string InitDataParser::generateRequest(const std::vector<const uint8_t*>& keyIds) { +std::string InitDataParser::generateRequest(V1_0::KeyType keyType, + const std::vector<const uint8_t*>& keyIds) { const std::string kRequestPrefix("{\"kids\":["); - const std::string kRequestSuffix("],\"type\":\"temporary\"}"); + const std::string kTemporarySession("],\"type\":\"temporary\"}"); + const std::string kPersistentSession("],\"type\":\"persistent-license\"}"); std::string request(kRequestPrefix); std::string encodedId; @@ -147,7 +154,12 @@ std::string InitDataParser::generateRequest(const std::vector<const uint8_t*>& k request.append(encodedId); request.push_back('\"'); } - request.append(kRequestSuffix); + if (keyType == V1_0::KeyType::STREAMING) { + request.append(kTemporarySession); + } else if (keyType == V1_0::KeyType::OFFLINE || + keyType == V1_0::KeyType::RELEASE) { + request.append(kPersistentSession); + } // Android's Base64 encoder produces padding. EME forbids padding. const char kBase64Padding = '='; @@ -157,7 +169,7 @@ std::string InitDataParser::generateRequest(const std::vector<const uint8_t*>& k } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp index cccb41ecc4..d93777d9d9 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp @@ -22,18 +22,21 @@ #include "Base64.h" namespace { +const std::string kBase64Padding("="); const std::string kKeysTag("keys"); const std::string kKeyTypeTag("kty"); -const std::string kSymmetricKeyValue("oct"); const std::string kKeyTag("k"); const std::string kKeyIdTag("kid"); -const std::string kBase64Padding("="); +const std::string kMediaSessionType("type"); +const std::string kPersistentLicenseSession("persistent-license"); +const std::string kSymmetricKeyValue("oct"); +const std::string kTemporaryLicenseSession("temporary"); } namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { JsonWebKey::JsonWebKey() { @@ -268,7 +271,7 @@ bool JsonWebKey::parseJsonWebKeySet(const std::string& jsonWebKeySet, } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp new file mode 100644 index 0000000000..2dcd00fb27 --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp @@ -0,0 +1,92 @@ +// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine Master +// License Agreement. + +#include <utils/Log.h> +#include <string> + +#include "MemoryFileSystem.h" +#include "Utils.h" + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace clearkey { + +std::string MemoryFileSystem::GetFileName(const std::string& path) { + size_t index = path.find_last_of("/"); + if (index != std::string::npos) { + return path.substr(index+1); + } else { + return path; + } +} + +bool MemoryFileSystem::FileExists(const std::string& fileName) const { + auto result = mMemoryFileSystem.find(fileName); + return result != mMemoryFileSystem.end(); +} + +ssize_t MemoryFileSystem::GetFileSize(const std::string& fileName) const { + auto result = mMemoryFileSystem.find(fileName); + if (result != mMemoryFileSystem.end()) { + return static_cast<ssize_t>(result->second.getFileSize()); + } else { + ALOGE("Failed to get size for %s", fileName.c_str()); + return -1; + } +} + +std::vector<std::string> MemoryFileSystem::ListFiles() const { + std::vector<std::string> list; + for (const auto& filename : mMemoryFileSystem) { + list.push_back(filename.first); + } + return list; +} + +size_t MemoryFileSystem::Read(const std::string& path, std::string* buffer) { + std::string key = GetFileName(path); + auto result = mMemoryFileSystem.find(key); + if (result != mMemoryFileSystem.end()) { + std::string serializedHashFile = result->second.getContent(); + buffer->assign(serializedHashFile); + return buffer->size(); + } else { + ALOGE("Failed to read from %s", path.c_str()); + return -1; + } +} + +size_t MemoryFileSystem::Write(const std::string& path, const MemoryFile& memoryFile) { + std::string key = GetFileName(path); + auto result = mMemoryFileSystem.find(key); + if (result != mMemoryFileSystem.end()) { + mMemoryFileSystem.erase(key); + } + mMemoryFileSystem.insert(std::pair<std::string, MemoryFile>(key, memoryFile)); + return memoryFile.getFileSize(); +} + +bool MemoryFileSystem::RemoveFile(const std::string& fileName) { + auto result = mMemoryFileSystem.find(fileName); + if (result != mMemoryFileSystem.end()) { + mMemoryFileSystem.erase(result); + return true; + } else { + ALOGE("Cannot find license to remove: %s", fileName.c_str()); + return false; + } +} + +bool MemoryFileSystem::RemoveAllFiles() { + mMemoryFileSystem.clear(); + return mMemoryFileSystem.empty(); +} + +} // namespace clearkey +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp index 07c9269c68..a9d7016075 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp @@ -28,7 +28,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::drm::V1_0::KeyValue; @@ -42,9 +42,10 @@ using android::Mutex; Status Session::getKeyRequest( const std::vector<uint8_t>& initData, const std::string& mimeType, + V1_0::KeyType keyType, std::vector<uint8_t>* keyRequest) const { InitDataParser parser; - return parser.parse(initData, mimeType, keyRequest); + return parser.parse(initData, mimeType, keyType, keyRequest); } Status Session::provideKeyResponse(const std::vector<uint8_t>& response) { @@ -67,29 +68,34 @@ Status Session::provideKeyResponse(const std::vector<uint8_t>& response) { } } -Status Session::decrypt( +Status_V1_2 Session::decrypt( const KeyId keyId, const Iv iv, const uint8_t* srcPtr, uint8_t* destPtr, const std::vector<SubSample> subSamples, size_t* bytesDecryptedOut) { Mutex::Autolock lock(mMapLock); + if (getMockError() != Status_V1_2::OK) { + return getMockError(); + } + std::vector<uint8_t> keyIdVector; keyIdVector.clear(); keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize); std::map<std::vector<uint8_t>, std::vector<uint8_t> >::iterator itr; itr = mKeyMap.find(keyIdVector); if (itr == mKeyMap.end()) { - return Status::ERROR_DRM_NO_LICENSE; + return Status_V1_2::ERROR_DRM_NO_LICENSE; } AesCtrDecryptor decryptor; - return decryptor.decrypt( + Status status = decryptor.decrypt( itr->second /*key*/, iv, srcPtr, destPtr, subSamples, subSamples.size(), bytesDecryptedOut); + return static_cast<Status_V1_2>(status); } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp index b4319e6a45..99fb30fd28 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::hidl_string; @@ -59,7 +59,8 @@ sp<Session> SessionLibrary::createSession() { mSessions.insert(std::pair<std::vector<uint8_t>, sp<Session> >(sessionId, new Session(sessionId))); - std::map<std::vector<uint8_t>, sp<Session> >::iterator itr = mSessions.find(sessionId); + std::map<std::vector<uint8_t>, sp<Session> >::iterator itr = + mSessions.find(sessionId); if (itr != mSessions.end()) { return itr->second; } else { @@ -70,7 +71,8 @@ sp<Session> SessionLibrary::createSession() { sp<Session> SessionLibrary::findSession( const std::vector<uint8_t>& sessionId) { Mutex::Autolock lock(mSessionsLock); - std::map<std::vector<uint8_t>, sp<Session> >::iterator itr = mSessions.find(sessionId); + std::map<std::vector<uint8_t>, sp<Session> >::iterator itr = + mSessions.find(sessionId); if (itr != mSessions.end()) { return itr->second; } else { @@ -84,7 +86,7 @@ void SessionLibrary::destroySession(const sp<Session>& session) { } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc deleted file mode 100644 index ffe856a55d..0000000000 --- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.1-service.clearkey.rc +++ /dev/null @@ -1,6 +0,0 @@ -service vendor.drm-clearkey-hal-1-1 /vendor/bin/hw/android.hardware.drm@1.1-service.clearkey - class hal - user media - group media mediadrm - ioprio rt 4 - writepid /dev/cpuset/foreground/tasks diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc new file mode 100644 index 0000000000..9afd3d7979 --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc @@ -0,0 +1,14 @@ +service vendor.drm-clearkey-hal-1-2 /vendor/bin/hw/android.hardware.drm@1.2-service-lazy.clearkey + interface android.hardware.drm@1.0::ICryptoFactory clearkey + interface android.hardware.drm@1.0::IDrmFactory clearkey + interface android.hardware.drm@1.1::ICryptoFactory clearkey + interface android.hardware.drm@1.1::IDrmFactory clearkey + interface android.hardware.drm@1.2::ICryptoFactory clearkey + interface android.hardware.drm@1.2::IDrmFactory clearkey + disabled + oneshot + class hal + user media + group media mediadrm + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc new file mode 100644 index 0000000000..5ba669dc50 --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc @@ -0,0 +1,12 @@ +service vendor.drm-clearkey-hal-1-2 /vendor/bin/hw/android.hardware.drm@1.2-service.clearkey + interface android.hardware.drm@1.0::ICryptoFactory clearkey + interface android.hardware.drm@1.0::IDrmFactory clearkey + interface android.hardware.drm@1.1::ICryptoFactory clearkey + interface android.hardware.drm@1.1::IDrmFactory clearkey + interface android.hardware.drm@1.2::ICryptoFactory clearkey + interface android.hardware.drm@1.2::IDrmFactory clearkey + class hal + user media + group media mediadrm + ioprio rt 4 + writepid /dev/cpuset/foreground/tasks diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h index 0c7ef20fdf..721f4c015c 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h @@ -22,7 +22,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::drm::V1_0::Status; @@ -42,7 +42,7 @@ private: }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h index 4a385bdb6e..ec30cc1024 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h @@ -25,7 +25,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::sp; @@ -38,7 +38,7 @@ void encodeBase64(const void *data, size_t size, std::string *out); void encodeBase64Url(const void *data, size_t size, std::string *out); } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h index 5bbb28aa14..c497e379be 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h @@ -25,7 +25,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::sp; @@ -54,7 +54,7 @@ private: }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h index d65b25c37f..b83ce69d4e 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h @@ -22,30 +22,40 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { static const std::string kVendorKey("vendor"); static const std::string kVendorValue("Google"); static const std::string kVersionKey("version"); -static const std::string kVersionValue("1.1"); +static const std::string kVersionValue("1.2"); static const std::string kPluginDescriptionKey("description"); static const std::string kPluginDescriptionValue("ClearKey CDM"); static const std::string kAlgorithmsKey("algorithms"); static const std::string kAlgorithmsValue(""); static const std::string kListenerTestSupportKey("listenerTestSupport"); static const std::string kListenerTestSupportValue("true"); +static const std::string kDrmErrorTestKey("drmErrorTest"); +static const std::string kDrmErrorTestValue(""); +static const std::string kResourceContentionValue("resourceContention"); +static const std::string kLostStateValue("lostState"); +static const std::string kFrameTooLargeValue("frameTooLarge"); +static const std::string kInvalidStateValue("invalidState"); static const std::string kDeviceIdKey("deviceId"); static const uint8_t kTestDeviceIdData[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; + +// settable byte array property +static const std::string kClientIdKey("clientId"); + // TODO stub out metrics for nw static const std::string kMetricsKey("metrics"); static const uint8_t kMetricsData[] = { 0 }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h index 46cb5e4dd5..03c434eaa3 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h @@ -17,17 +17,18 @@ #ifndef CLEARKEY_MACROS_H_ #define CLEARKEY_MACROS_H_ -#include <android/hardware/drm/1.0/types.h> +#include <android/hardware/drm/1.2/types.h> #include <map> namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::drm::V1_0::KeyValue; +using ::android::hardware::drm::V1_1::SecurityLevel; using ::android::hardware::hidl_vec; const uint8_t kBlockSize = 16; //AES_BLOCK_SIZE; @@ -47,7 +48,7 @@ typedef std::map<std::vector<uint8_t>, std::vector<uint8_t> > KeyMap; void operator=(const TypeName&) = delete; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h index 99520277f2..6368f3dabb 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h @@ -17,17 +17,17 @@ #ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_ #define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_ -#include <android/hardware/drm/1.1/ICryptoFactory.h> -#include <android/hardware/drm/1.1/IDrmFactory.h> +#include <android/hardware/drm/1.2/ICryptoFactory.h> +#include <android/hardware/drm/1.2/IDrmFactory.h> namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { -using ::android::hardware::drm::V1_1::ICryptoFactory; -using ::android::hardware::drm::V1_1::IDrmFactory; +using ::android::hardware::drm::V1_2::ICryptoFactory; +using ::android::hardware::drm::V1_2::IDrmFactory; extern "C" { IDrmFactory* createDrmFactory(); @@ -35,7 +35,7 @@ extern "C" { } } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h index 175ab761fa..203bb2d316 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h @@ -18,17 +18,17 @@ #define CLEARKEY_CRYPTO_FACTORY_H_ #include <android/hardware/drm/1.0/ICryptoPlugin.h> -#include <android/hardware/drm/1.1/ICryptoFactory.h> +#include <android/hardware/drm/1.2/ICryptoFactory.h> #include "ClearKeyTypes.h" namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { -using ::android::hardware::drm::V1_1::ICryptoFactory; +using ::android::hardware::drm::V1_2::ICryptoFactory; using ::android::hardware::drm::V1_0::ICryptoPlugin; using ::android::hardware::hidl_array; using ::android::hardware::hidl_string; @@ -52,7 +52,7 @@ private: }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h index 6a738066d0..8680f0ca54 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h @@ -17,7 +17,7 @@ #ifndef CLEARKEY_CRYPTO_PLUGIN_H_ #define CLEARKEY_CRYPTO_PLUGIN_H_ -#include <android/hardware/drm/1.0/ICryptoPlugin.h> +#include <android/hardware/drm/1.2/ICryptoPlugin.h> #include <android/hidl/memory/1.0/IMemory.h> #include "ClearKeyTypes.h" @@ -32,16 +32,17 @@ namespace { namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { -using ::android::hardware::drm::V1_0::DestinationBuffer; -using ::android::hardware::drm::V1_0::ICryptoPlugin; -using ::android::hardware::drm::V1_0::Mode; -using ::android::hardware::drm::V1_0::Pattern; -using ::android::hardware::drm::V1_0::SharedBuffer; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_0::SubSample; +namespace drm = ::android::hardware::drm; +using drm::V1_0::DestinationBuffer; +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::hardware::hidl_array; using ::android::hardware::hidl_memory; using ::android::hardware::hidl_string; @@ -51,7 +52,9 @@ using ::android::hardware::Void; using ::android::hidl::memory::V1_0::IMemory; using ::android::sp; -struct CryptoPlugin : public ICryptoPlugin { +typedef drm::V1_2::Status Status_V1_2; + +struct CryptoPlugin : public drm::V1_2::ICryptoPlugin { explicit CryptoPlugin(const hidl_vec<uint8_t>& sessionId) { mInitStatus = setMediaDrmSession(sessionId); } @@ -80,6 +83,18 @@ struct CryptoPlugin : public ICryptoPlugin { const DestinationBuffer& destination, decrypt_cb _hidl_cb); + Return<void> decrypt_1_2( + bool secure, + const hidl_array<uint8_t, KEY_ID_SIZE>& keyId, + const hidl_array<uint8_t, KEY_IV_SIZE>& iv, + Mode mode, + const Pattern& pattern, + const hidl_vec<SubSample>& subSamples, + const SharedBuffer& source, + uint64_t offset, + const DestinationBuffer& destination, + decrypt_1_2_cb _hidl_cb); + Return<void> setSharedBufferBase(const hidl_memory& base, uint32_t bufferId); @@ -96,7 +111,7 @@ private: }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h new file mode 100644 index 0000000000..554ae598fe --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h @@ -0,0 +1,71 @@ +// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine Master +// License Agreement. +// +#ifndef CLEARKEY_DEVICE_FILES_H_ +#define CLEARKEY_DEVICE_FILES_H_ + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> + +#include <set> +#include <string> +#include <vector> + +#include "protos/DeviceFiles.pb.h" +#include "ClearKeyTypes.h" +#include "MemoryFileSystem.h" + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace clearkey { + +class DeviceFiles { + public: + typedef enum { + kLicenseStateUnknown, + kLicenseStateActive, + kLicenseStateReleasing, + } LicenseState; + + DeviceFiles() {}; + virtual ~DeviceFiles() {}; + + virtual bool StoreLicense(const std::string& keySetId, LicenseState state, + const std::string& keyResponse); + + virtual bool RetrieveLicense( + const std::string& key_set_id, LicenseState* state, std::string* offlineLicense); + + virtual bool LicenseExists(const std::string& keySetId); + + virtual std::vector<std::string> ListLicenses() const; + + virtual bool DeleteLicense(const std::string& keySetId); + + virtual bool DeleteAllLicenses(); + + private: + bool FileExists(const std::string& path) const; + ssize_t GetFileSize(const std::string& fileName) const; + bool RemoveFile(const std::string& fileName); + + bool RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile); + bool StoreFileRaw(const std::string& fileName, const std::string& serializedFile); + bool StoreFileWithHash(const std::string& fileName, const std::string& serializedFile); + + MemoryFileSystem mFileHandle; + + CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DeviceFiles); +}; + +} // namespace clearkey +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android + +#endif // CLEARKEY_DEVICE_FILES_H_ diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h index 6f581955b5..4ca856d63e 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h @@ -17,15 +17,15 @@ #ifndef CLEARKEY_DRM_FACTORY_H_ #define CLEARKEY_DRM_FACTORY_H_ -#include <android/hardware/drm/1.1/IDrmPlugin.h> -#include <android/hardware/drm/1.1/IDrmFactory.h> +#include <android/hardware/drm/1.2/IDrmPlugin.h> +#include <android/hardware/drm/1.2/IDrmFactory.h> #include "ClearKeyTypes.h" namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::hidl_array; @@ -39,6 +39,10 @@ struct DrmFactory : public IDrmFactory { Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid) override; + Return<bool> isCryptoSchemeSupported_1_2(const hidl_array<uint8_t, 16>& uuid, + const hidl_string& mimeType, + SecurityLevel level) override; + Return<bool> isContentTypeSupported(const hidl_string &mimeType) override; @@ -52,7 +56,7 @@ private: }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h index fb0695aaef..f294d4d736 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h @@ -17,32 +17,42 @@ #ifndef CLEARKEY_DRM_PLUGIN_H_ #define CLEARKEY_DRM_PLUGIN_H_ -#include <android/hardware/drm/1.1/IDrmPlugin.h> +#include <android/hardware/drm/1.2/IDrmPlugin.h> +#include <android/hardware/drm/1.2/IDrmPluginListener.h> -#include <stdio.h> #include <map> +#include <stdio.h> + +#include <utils/List.h> +#include "DeviceFiles.h" #include "SessionLibrary.h" #include "Utils.h" namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { -using ::android::hardware::drm::V1_0::EventType; -using ::android::hardware::drm::V1_0::IDrmPluginListener; -using ::android::hardware::drm::V1_0::KeyStatus; -using ::android::hardware::drm::V1_0::KeyType; -using ::android::hardware::drm::V1_0::KeyValue; -using ::android::hardware::drm::V1_0::SecureStop; -using ::android::hardware::drm::V1_0::SecureStopId; -using ::android::hardware::drm::V1_0::SessionId; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_1::DrmMetricGroup; -using ::android::hardware::drm::V1_1::IDrmPlugin; -using ::android::hardware::drm::V1_1::KeyRequestType; +namespace drm = ::android::hardware::drm; +using drm::V1_0::EventType; +using drm::V1_0::IDrmPluginListener; +using drm::V1_0::KeyRequestType; +using drm::V1_0::KeyStatus; +using drm::V1_0::KeyType; +using drm::V1_0::KeyValue; +using drm::V1_0::SecureStop; +using drm::V1_0::SecureStopId; +using drm::V1_0::SessionId; +using drm::V1_0::Status; +using drm::V1_1::DrmMetricGroup; +using drm::V1_1::HdcpLevel; +using drm::V1_1::SecureStopRelease; +using drm::V1_1::SecurityLevel; +using drm::V1_2::IDrmPlugin; +using drm::V1_2::KeySetId; +using drm::V1_2::OfflineLicenseState; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; @@ -50,10 +60,16 @@ using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; +typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1; +typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2; +typedef drm::V1_2::KeyStatus KeyStatus_V1_2; +typedef drm::V1_2::Status Status_V1_2; +typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2; + struct DrmPlugin : public IDrmPlugin { explicit DrmPlugin(SessionLibrary* sessionLibrary); - virtual ~DrmPlugin() {} + virtual ~DrmPlugin() { mFileHandle.DeleteAllLicenses(); } Return<void> openSession(openSession_cb _hidl_cb) override; Return<void> openSession_1_1(SecurityLevel securityLevel, @@ -77,6 +93,14 @@ struct DrmPlugin : public IDrmPlugin { const hidl_vec<KeyValue>& optionalParameters, getKeyRequest_1_1_cb _hidl_cb) override; + Return<void> getKeyRequest_1_2( + const hidl_vec<uint8_t>& scope, + const hidl_vec<uint8_t>& initData, + const hidl_string& mimeType, + KeyType keyType, + const hidl_vec<KeyValue>& optionalParameters, + getKeyRequest_1_2_cb _hidl_cb) override; + Return<void> provideKeyResponse( const hidl_vec<uint8_t>& scope, const hidl_vec<uint8_t>& response, @@ -91,13 +115,7 @@ struct DrmPlugin : public IDrmPlugin { Return<Status> restoreKeys( const hidl_vec<uint8_t>& sessionId, - const hidl_vec<uint8_t>& keySetId) { - - if (sessionId.size() == 0 || keySetId.size() == 0) { - return Status::BAD_VALUE; - } - return Status::ERROR_DRM_CANNOT_HANDLE; - } + const hidl_vec<uint8_t>& keySetId) override; Return<void> queryKeyStatus( const hidl_vec<uint8_t>& sessionId, @@ -115,6 +133,18 @@ struct DrmPlugin : public IDrmPlugin { return Void(); } + Return<void> getProvisionRequest_1_2( + const hidl_string& certificateType, + const hidl_string& certificateAuthority, + getProvisionRequest_1_2_cb _hidl_cb) { + UNUSED(certificateType); + UNUSED(certificateAuthority); + + hidl_string defaultUrl; + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl); + return Void(); + } + Return<void> provideProvisionResponse( const hidl_vec<uint8_t>& response, provideProvisionResponse_cb _hidl_cb) { @@ -134,6 +164,13 @@ struct DrmPlugin : public IDrmPlugin { return Void(); } + Return<void> getHdcpLevels_1_2(getHdcpLevels_1_2_cb _hidl_cb) { + HdcpLevel_V1_2 connectedLevel = HdcpLevel_V1_2::HDCP_NONE; + HdcpLevel_V1_2 maxLevel = HdcpLevel_V1_2::HDCP_NO_OUTPUT; + _hidl_cb(Status_V1_2::OK, connectedLevel, maxLevel); + return Void(); + } + Return<void> getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) override; Return<void> getSecurityLevel(const hidl_vec<uint8_t>& sessionId, @@ -141,6 +178,13 @@ struct DrmPlugin : public IDrmPlugin { Return<void> getMetrics(getMetrics_cb _hidl_cb) override; + Return<void> getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) override; + + Return<Status> removeOfflineLicense(const KeySetId &keySetId) override; + + Return<void> getOfflineLicenseState(const KeySetId &keySetId, + getOfflineLicenseState_cb _hidl_cb) override; + Return<void> getPropertyString( const hidl_string& name, getPropertyString_cb _hidl_cb) override; @@ -248,12 +292,17 @@ struct DrmPlugin : public IDrmPlugin { Return<void> setListener(const sp<IDrmPluginListener>& listener) { mListener = listener; + mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener); return Void(); }; - Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId, + Return<void> sendEvent( + EventType eventType, + const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) { - if (mListener != NULL) { + if (mListenerV1_2 != NULL) { + mListenerV1_2->sendEvent(eventType, sessionId, data); + } else if (mListener != NULL) { mListener->sendEvent(eventType, sessionId, data); } else { ALOGE("Null event listener, event not sent"); @@ -261,8 +310,12 @@ struct DrmPlugin : public IDrmPlugin { return Void(); } - Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) { - if (mListener != NULL) { + Return<void> sendExpirationUpdate( + const hidl_vec<uint8_t>& sessionId, + int64_t expiryTimeInMS) { + if (mListenerV1_2 != NULL) { + mListenerV1_2->sendExpirationUpdate(sessionId, expiryTimeInMS); + } else if (mListener != NULL) { mListener->sendExpirationUpdate(sessionId, expiryTimeInMS); } else { ALOGE("Null event listener, event not sent"); @@ -270,9 +323,12 @@ struct DrmPlugin : public IDrmPlugin { return Void(); } - Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId, + Return<void> sendKeysChange( + const hidl_vec<uint8_t>& sessionId, const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) { - if (mListener != NULL) { + if (mListenerV1_2 != NULL) { + mListenerV1_2->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey); + } else if (mListener != NULL) { mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey); } else { ALOGE("Null event listener, event not sent"); @@ -280,6 +336,23 @@ struct DrmPlugin : public IDrmPlugin { return Void(); } + Return<void> sendKeysChange_1_2( + const hidl_vec<uint8_t>& sessionId, + const hidl_vec<KeyStatus_V1_2>& keyStatusList, bool hasNewUsableKey) { + if (mListenerV1_2 != NULL) { + mListenerV1_2->sendKeysChange_1_2(sessionId, keyStatusList, hasNewUsableKey); + } + return Void(); + } + + Return<void> sendSessionLostState( + const hidl_vec<uint8_t>& sessionId) { + if (mListenerV1_2 != NULL) { + mListenerV1_2->sendSessionLostState(sessionId); + } + return Void(); + } + Return<void> getSecureStops(getSecureStops_cb _hidl_cb); Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId, @@ -300,18 +373,19 @@ struct DrmPlugin : public IDrmPlugin { private: void initProperties(); void installSecureStop(const hidl_vec<uint8_t>& sessionId); + bool makeKeySetId(std::string* keySetId); void setPlayPolicy(); Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId, SecurityLevel level); - Status getKeyRequestCommon(const hidl_vec<uint8_t>& scope, + Status_V1_2 getKeyRequestCommon(const hidl_vec<uint8_t>& scope, const hidl_vec<uint8_t>& initData, const hidl_string& mimeType, KeyType keyType, const hidl_vec<KeyValue>& optionalParameters, std::vector<uint8_t> *request, - KeyRequestType *getKeyRequestType, + KeyRequestType_V1_1 *getKeyRequestType, std::string *defaultUrl); struct ClearkeySecureStop { @@ -323,19 +397,31 @@ private: std::vector<KeyValue> mPlayPolicy; std::map<std::string, std::string> mStringProperties; std::map<std::string, std::vector<uint8_t> > mByteArrayProperties; + std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap; std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel; sp<IDrmPluginListener> mListener; + sp<IDrmPluginListener_V1_2> mListenerV1_2; SessionLibrary *mSessionLibrary; int64_t mOpenSessionOkCount; int64_t mCloseSessionOkCount; int64_t mCloseSessionNotOpenedCount; uint32_t mNextSecureStopId; + // set by property to mock error scenarios + Status_V1_2 mMockError; + + void processMockError(const sp<Session> &session) { + session->setMockError(mMockError); + mMockError = Status_V1_2::OK; + } + + DeviceFiles mFileHandle; + CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin); }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h index 3189c4aeb2..889f51164b 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::drm::V1_0::Status; @@ -34,7 +34,8 @@ public: InitDataParser() {} Status parse(const std::vector<uint8_t>& initData, - const std::string& type, + const std::string& mimeType, + V1_0::KeyType keyType, std::vector<uint8_t>* licenseRequest); private: @@ -43,12 +44,12 @@ private: Status parsePssh(const std::vector<uint8_t>& initData, std::vector<const uint8_t*>* keyIds); - std::string generateRequest( + std::string generateRequest(V1_0::KeyType keyType, const std::vector<const uint8_t*>& keyIds); }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h index 4ab034cd74..e57470cd0d 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h @@ -23,7 +23,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { class JsonWebKey { @@ -54,7 +54,7 @@ class JsonWebKey { }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h new file mode 100644 index 0000000000..bcd9fd631a --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h @@ -0,0 +1,68 @@ +// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine Master +// License Agreement. +// +#ifndef CLEARKEY_MEMORY_FILE_SYSTEM_H_ +#define CLEARKEY_MEMORY_FILE_SYSTEM_H_ + +#include <map> +#include <string> + +#include "ClearKeyTypes.h" + +namespace android { +namespace hardware { +namespace drm { +namespace V1_2 { +namespace clearkey { + +// Using android file system requires clearkey plugin to update +// its sepolicy. However, we are unable to update sepolicy for +// older vendor partitions. To provide backward compatibility, +// clearkey plugin implements a very simple file system in memory. +// This memory file system does not support directory structure. +class MemoryFileSystem { + public: + struct MemoryFile { + std::string fileName; // excludes path + std::string content; + size_t fileSize; + + std::string getContent() const { return content; } + size_t getFileSize() const { return fileSize; } + void setContent(const std::string& file) { content = file; } + void setFileName(const std::string& name) { fileName = name; } + void setFileSize(size_t size) { + content.resize(size); fileSize = size; + } + }; + + MemoryFileSystem() {}; + virtual ~MemoryFileSystem() {}; + + bool FileExists(const std::string& fileName) const; + ssize_t GetFileSize(const std::string& fileName) const; + std::vector<std::string> ListFiles() const; + size_t Read(const std::string& pathName, std::string* buffer); + bool RemoveAllFiles(); + bool RemoveFile(const std::string& fileName); + size_t Write(const std::string& pathName, const MemoryFile& memoryFile); + + private: + // License file name is made up of a unique keySetId, therefore, + // the filename can be used as the key to locate licenses in the + // memory file system. + std::map<std::string, MemoryFile> mMemoryFileSystem; + + std::string GetFileName(const std::string& path); + + CLEARKEY_DISALLOW_COPY_AND_ASSIGN(MemoryFileSystem); +}; + +} // namespace clearkey +} // namespace V1_2 +} // namespace drm +} // namespace hardware +} // namespace android + +#endif // CLEARKEY_MEMORY_FILE_SYSTEM_H_ diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h index cddfca5eba..a159e5ae76 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h @@ -27,43 +27,53 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_0::SubSample; +namespace drm = ::android::hardware::drm; +using drm::V1_0::Status; +using drm::V1_0::SubSample; + +typedef drm::V1_2::Status Status_V1_2; class Session : public RefBase { public: explicit Session(const std::vector<uint8_t>& sessionId) - : mSessionId(sessionId) {} + : mSessionId(sessionId), mMockError(Status_V1_2::OK) {} virtual ~Session() {} const std::vector<uint8_t>& sessionId() const { return mSessionId; } Status getKeyRequest( - const std::vector<uint8_t>& mimeType, - const std::string& initDataType, + const std::vector<uint8_t>& initDataType, + const std::string& mimeType, + V1_0::KeyType keyType, std::vector<uint8_t>* keyRequest) const; Status provideKeyResponse( const std::vector<uint8_t>& response); - Status decrypt( + Status_V1_2 decrypt( const KeyId keyId, const Iv iv, const uint8_t* srcPtr, uint8_t* dstPtr, const std::vector<SubSample> subSamples, size_t* bytesDecryptedOut); + void setMockError(Status_V1_2 error) {mMockError = error;} + Status_V1_2 getMockError() const {return mMockError;} + private: CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Session); const std::vector<uint8_t> mSessionId; KeyMap mKeyMap; Mutex mMapLock; + + // For mocking error return scenarios + Status_V1_2 mMockError; }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h index 326a0c100d..1e567b8d09 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h @@ -26,7 +26,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::sp; @@ -58,7 +58,7 @@ private: }; } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h index cc06329b84..b0f8607729 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h +++ b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h @@ -24,7 +24,7 @@ namespace android { namespace hardware { namespace drm { -namespace V1_1 { +namespace V1_2 { namespace clearkey { using ::android::hardware::hidl_array; @@ -68,8 +68,19 @@ template<typename T, size_t SIZE> std::vector<T> toVector( return vec; } +inline Status toStatus_1_0(Status_V1_2 status) { + switch (status) { + case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: + case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: + case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE: + return Status::ERROR_DRM_UNKNOWN; + default: + return static_cast<Status>(status); + } +} + } // namespace clearkey -} // namespace V1_1 +} // namespace V1_2 } // namespace drm } // namespace hardware } // namespace android diff --git a/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto b/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto new file mode 100644 index 0000000000..3e11f0b3fa --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto @@ -0,0 +1,47 @@ +// ---------------------------------------------------------------------------- +// device_files.proto +// ---------------------------------------------------------------------------- +// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine Master +// License Agreement. +// +// Description: +// Format of various files stored at the device. +// +syntax = "proto2"; + +package android.hardware.drm.V1_2.clearkey; + +// need this if we are using libprotobuf-cpp-2.3.0-lite +option optimize_for = LITE_RUNTIME; + +message License { + enum LicenseState { + ACTIVE = 1; + RELEASING = 2; + } + + optional LicenseState state = 1; + optional bytes license = 2; +} + +message OfflineFile { + enum FileType { + LICENSE = 1; + } + + enum FileVersion { + VERSION_1 = 1; + } + + optional FileType type = 1; + optional FileVersion version = 2 [default = VERSION_1]; + optional License license = 3; + +} + +message HashedFile { + optional bytes file = 1; + // A raw (not hex-encoded) SHA256, taken over the bytes of 'file'. + optional bytes hash = 2; +} diff --git a/drm/mediadrm/plugins/clearkey/hidl/service.cpp b/drm/mediadrm/plugins/clearkey/hidl/service.cpp index 6a97b720d2..b39ea018e4 100644 --- a/drm/mediadrm/plugins/clearkey/hidl/service.cpp +++ b/drm/mediadrm/plugins/clearkey/hidl/service.cpp @@ -13,32 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#define LOG_TAG "android.hardware.drm@1.1-service.clearkey" - #include <CryptoFactory.h> #include <DrmFactory.h> #include <android-base/logging.h> #include <binder/ProcessState.h> +#include <hidl/HidlLazyUtils.h> #include <hidl/HidlTransportSupport.h> using ::android::hardware::configureRpcThreadpool; using ::android::hardware::joinRpcThreadpool; using ::android::sp; -using android::hardware::drm::V1_1::ICryptoFactory; -using android::hardware::drm::V1_1::IDrmFactory; -using android::hardware::drm::V1_1::clearkey::CryptoFactory; -using android::hardware::drm::V1_1::clearkey::DrmFactory; - +using android::hardware::drm::V1_2::ICryptoFactory; +using android::hardware::drm::V1_2::IDrmFactory; +using android::hardware::drm::V1_2::clearkey::CryptoFactory; +using android::hardware::drm::V1_2::clearkey::DrmFactory; int main(int /* argc */, char** /* argv */) { - ALOGD("android.hardware.drm@1.1-service.clearkey starting..."); - - // The DRM HAL may communicate to other vendor components via - // /dev/vndbinder - android::ProcessState::initWithDriver("/dev/vndbinder"); - sp<IDrmFactory> drmFactory = new DrmFactory; sp<ICryptoFactory> cryptoFactory = new CryptoFactory; diff --git a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp new file mode 100644 index 0000000000..99fd883b16 --- /dev/null +++ b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <CryptoFactory.h> +#include <DrmFactory.h> + +#include <android-base/logging.h> +#include <binder/ProcessState.h> +#include <hidl/HidlLazyUtils.h> +#include <hidl/HidlTransportSupport.h> + +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::sp; + +using android::hardware::drm::V1_2::ICryptoFactory; +using android::hardware::drm::V1_2::IDrmFactory; +using android::hardware::drm::V1_2::clearkey::CryptoFactory; +using android::hardware::drm::V1_2::clearkey::DrmFactory; +using android::hardware::LazyServiceRegistrar; + +int main(int /* argc */, char** /* argv */) { + sp<IDrmFactory> drmFactory = new DrmFactory; + sp<ICryptoFactory> cryptoFactory = new CryptoFactory; + + configureRpcThreadpool(8, true /* callerWillJoin */); + + // Setup hwbinder service + LazyServiceRegistrar serviceRegistrar; + + // Setup hwbinder service + CHECK_EQ(serviceRegistrar.registerService(drmFactory, "clearkey"), android::NO_ERROR) + << "Failed to register Clearkey Factory HAL"; + CHECK_EQ(serviceRegistrar.registerService(cryptoFactory, "clearkey"), android::NO_ERROR) + << "Failed to register Clearkey Crypto HAL"; + + joinRpcThreadpool(); +} |
