1cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania/* 2cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * Copyright (C) 2017 The Android Open Source Project 3cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * 4cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * Licensed under the Apache License, Version 2.0 (the "License"); 5cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * you may not use this file except in compliance with the License. 6cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * You may obtain a copy of the License at 7cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * 8cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * http://www.apache.org/licenses/LICENSE-2.0 9cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * 10cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * Unless required by applicable law or agreed to in writing, software 11cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * distributed under the License is distributed on an "AS IS" BASIS, 12cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * See the License for the specific language governing permissions and 14cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania * limitations under the License. 15cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania */ 16cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 17cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania//#define LOG_NDEBUG 0 18cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania#define LOG_TAG "NuPlayerDrm" 19cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 20cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania#include "NuPlayerDrm.h" 21cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 22cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania#include <binder/IServiceManager.h> 23cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania#include <media/IMediaDrmService.h> 24cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania#include <utils/Log.h> 25cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 26cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 27cefac14261a32fb856b0d1ab31541787112e306eHassan Shojanianamespace android { 28cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 29cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania// static helpers - internal 30cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 31cefac14261a32fb856b0d1ab31541787112e306eHassan Shojaniasp<IDrm> NuPlayerDrm::CreateDrm(status_t *pstatus) 32cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 33cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status_t &status = *pstatus; 34cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IServiceManager> sm = defaultServiceManager(); 35cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IBinder> binder = sm->getService(String16("media.drm")); 36cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGV("CreateDrm binder %p", (binder != NULL ? binder.get() : 0)); 37cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 38cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder); 39cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (service == NULL) { 40cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("CreateDrm failed at IMediaDrmService"); 41cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 42cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 43cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 44cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IDrm> drm = service->makeDrm(); 45cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (drm == NULL) { 46cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("CreateDrm failed at makeDrm"); 47cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 48cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 49cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 50cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // this is before plugin creation so NO_INIT is fine 51cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status = drm->initCheck(); 52cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (status != OK && status != NO_INIT) { 53cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("CreateDrm failed drm->initCheck(): %d", status); 54cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 55cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 56cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return drm; 57cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 58cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 59cefac14261a32fb856b0d1ab31541787112e306eHassan Shojaniasp<ICrypto> NuPlayerDrm::createCrypto(status_t *pstatus) 60cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 61cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status_t &status = *pstatus; 62cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IServiceManager> sm = defaultServiceManager(); 63cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IBinder> binder = sm->getService(String16("media.drm")); 64cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 65cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder); 66cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (service == NULL) { 67cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status = UNKNOWN_ERROR; 68cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("CreateCrypto failed at IMediaDrmService"); 69cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 70cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 71cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 72cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<ICrypto> crypto = service->makeCrypto(); 73cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (crypto == NULL) { 74cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status = UNKNOWN_ERROR; 75cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("createCrypto failed"); 76cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 77cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 78cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 79cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // this is before plugin creation so NO_INIT is fine 80cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status = crypto->initCheck(); 81cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (status != OK && status != NO_INIT) { 82cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("createCrypto failed crypto->initCheck(): %d", status); 83cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 84cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 85cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 86cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return crypto; 87cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 88cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 89cefac14261a32fb856b0d1ab31541787112e306eHassan ShojaniaVector<DrmUUID> NuPlayerDrm::parsePSSH(const void *pssh, size_t psshsize) 90cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 91cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania Vector<DrmUUID> drmSchemes, empty; 92cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const int DATALEN_SIZE = 4; 93cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 94cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // the format of the buffer is 1 or more of: 95cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // { 96cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // 16 byte uuid 97cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // 4 byte data length N 98cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // N bytes of data 99cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // } 100cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // Determine the number of entries in the source data. 101cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // Since we got the data from stagefright, we trust it is valid and properly formatted. 102cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 103cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const uint8_t *data = (const uint8_t*)pssh; 104cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t len = psshsize; 105cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t numentries = 0; 106cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania while (len > 0) { 107cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (len < DrmUUID::UUID_SIZE) { 108cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("ParsePSSH: invalid PSSH data"); 109cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return empty; 110cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 111cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 112cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const uint8_t *uuidPtr = data; 113cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 114cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // skip uuid 115cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania data += DrmUUID::UUID_SIZE; 116cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania len -= DrmUUID::UUID_SIZE; 117cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 118cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // get data length 119cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (len < DATALEN_SIZE) { 120cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("ParsePSSH: invalid PSSH data"); 121cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return empty; 122cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 123cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 124cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania uint32_t datalen = *((uint32_t*)data); 125cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania data += DATALEN_SIZE; 126cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania len -= DATALEN_SIZE; 127cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 128cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (len < datalen) { 129cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("ParsePSSH: invalid PSSH data"); 130cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return empty; 131cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 132cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 133cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // skip the data 134cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania data += datalen; 135cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania len -= datalen; 136cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 137cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania DrmUUID _uuid(uuidPtr); 138cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania drmSchemes.add(_uuid); 139cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 140cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGV("ParsePSSH[%zu]: %s: %s", numentries, 141cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania _uuid.toHexString().string(), 142cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania DrmUUID::arrayToHex(data, datalen).string() 143cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ); 144cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 145cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania numentries++; 146cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 147cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 148cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return drmSchemes; 149cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 150cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 151cefac14261a32fb856b0d1ab31541787112e306eHassan ShojaniaVector<DrmUUID> NuPlayerDrm::getSupportedDrmSchemes(const void *pssh, size_t psshsize) 152cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 153cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania Vector<DrmUUID> psshDRMs = parsePSSH(pssh, psshsize); 154cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 155cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania Vector<DrmUUID> supportedDRMs; 156cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // temporary DRM object for crypto Scheme enquiry (without creating a plugin) 157cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status_t status = OK; 158cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<IDrm> drm = CreateDrm(&status); 159cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (drm != NULL) { 160cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania for (size_t i = 0; i < psshDRMs.size(); i++) { 161cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania DrmUUID uuid = psshDRMs[i]; 162cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (drm->isCryptoSchemeSupported(uuid.ptr(), String8())) 163cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania supportedDRMs.add(uuid); 164cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 165cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 166cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania drm.clear(); 167cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } else { 168cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("getSupportedDrmSchemes: Can't create Drm obj: %d", status); 169cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 170cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 171cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGV("getSupportedDrmSchemes: psshDRMs: %zu supportedDRMs: %zu", 172cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania psshDRMs.size(), supportedDRMs.size()); 173cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 174cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return supportedDRMs; 175cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 176cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 177cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania// static helpers - public 178cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 179cefac14261a32fb856b0d1ab31541787112e306eHassan Shojaniasp<ICrypto> NuPlayerDrm::createCryptoAndPlugin(const uint8_t uuid[16], 180cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const Vector<uint8_t> &drmSessionId, status_t &status) 181cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 182cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // Extra check 183cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (drmSessionId.isEmpty()) { 184cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status = INVALID_OPERATION; 185cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("createCryptoAndPlugin: Failed. Empty drmSessionId. status: %d", status); 186cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 187cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 188cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 189cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status = OK; 190cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sp<ICrypto> crypto = createCrypto(&status); 191cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (crypto == NULL) { 192cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("createCryptoAndPlugin: createCrypto failed. status: %d", status); 193cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 194cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 195cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGV("createCryptoAndPlugin: createCrypto succeeded"); 196cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 197cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania status = crypto->createPlugin(uuid, drmSessionId.array(), drmSessionId.size()); 198cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (status != OK) { 199cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("createCryptoAndPlugin: createCryptoPlugin failed. status: %d", status); 200cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // crypto will clean itself when leaving the current scope 201cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 202cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 203cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 204cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return crypto; 205cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 206cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 207cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania// Parcel has only private copy constructor so passing it in rather than returning 208dd4ce1877814d6fb005e89021272feb3ccfb81d0Hassan Shojaniavoid NuPlayerDrm::retrieveDrmInfo(const void *pssh, size_t psshsize, Parcel *parcel) 209cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 210cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // 1) PSSH bytes 211cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania parcel->writeUint32(psshsize); 212cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania parcel->writeByteArray(psshsize, (const uint8_t*)pssh); 213cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 214cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO PSSH: size: %zu %s", psshsize, 215cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania DrmUUID::arrayToHex((uint8_t*)pssh, psshsize).string()); 216cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 217cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // 2) supportedDRMs 218cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania Vector<DrmUUID> supportedDRMs = getSupportedDrmSchemes(pssh, psshsize); 219cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania parcel->writeUint32(supportedDRMs.size()); 220cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania for (size_t i = 0; i < supportedDRMs.size(); i++) { 221cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania DrmUUID uuid = supportedDRMs[i]; 222cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania parcel->writeByteArray(DrmUUID::UUID_SIZE, uuid.ptr()); 223cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 224cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO supportedScheme[%zu] %s", i, 225cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania uuid.toHexString().string()); 226cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 227cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 228cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 229cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania//////////////////////////////////////////////////////////////////////////////////////////// 230cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania/// Helpers for NuPlayerDecoder 231cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania//////////////////////////////////////////////////////////////////////////////////////////// 232cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 233cefac14261a32fb856b0d1ab31541787112e306eHassan ShojaniaNuPlayerDrm::CryptoInfo *NuPlayerDrm::makeCryptoInfo( 234cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania int numSubSamples, 235cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania uint8_t key[kBlockSize], 236cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania uint8_t iv[kBlockSize], 237cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania CryptoPlugin::Mode mode, 238cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t *clearbytes, 239cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t *encryptedbytes) 240cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 241cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // size needed to store all the crypto data 242cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t cryptosize = sizeof(CryptoInfo) + 243cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania sizeof(CryptoPlugin::SubSample) * numSubSamples; 244cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania CryptoInfo *ret = (CryptoInfo*) malloc(cryptosize); 245cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (ret == NULL) { 246cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("couldn't allocate %zu bytes", cryptosize); 247cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 248cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 249cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ret->numSubSamples = numSubSamples; 250cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania memcpy(ret->key, key, kBlockSize); 251cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania memcpy(ret->iv, iv, kBlockSize); 252cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ret->mode = mode; 253cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ret->pattern.mEncryptBlocks = 0; 254cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ret->pattern.mSkipBlocks = 0; 255cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ret->subSamples = (CryptoPlugin::SubSample*)(ret + 1); 256cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania CryptoPlugin::SubSample *subSamples = ret->subSamples; 257cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 258cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania for (int i = 0; i < numSubSamples; i++) { 259cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania subSamples[i].mNumBytesOfClearData = (clearbytes == NULL) ? 0 : clearbytes[i]; 260cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania subSamples[i].mNumBytesOfEncryptedData = (encryptedbytes == NULL) ? 261cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 0 : 262cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania encryptedbytes[i]; 263cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 264cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 265cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return ret; 266cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 267cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 268cefac14261a32fb856b0d1ab31541787112e306eHassan ShojaniaNuPlayerDrm::CryptoInfo *NuPlayerDrm::getSampleCryptoInfo(sp<MetaData> meta) 269cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{ 270cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania uint32_t type; 271cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const void *crypteddata; 272cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t cryptedsize; 273cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 274cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (meta == NULL) { 275cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("getSampleCryptoInfo: Unexpected. No meta data for sample."); 276cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 277cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 278cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 279cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (!meta->findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) { 280cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 281cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 282cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t numSubSamples = cryptedsize / sizeof(size_t); 283cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 284cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (numSubSamples <= 0) { 285cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("getSampleCryptoInfo INVALID numSubSamples: %zu", numSubSamples); 286cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 287cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 288cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 289cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const void *cleardata; 290cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t clearsize; 291cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (meta->findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) { 292cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (clearsize != cryptedsize) { 293cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // The two must be of the same length. 294cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania ALOGE("getSampleCryptoInfo mismatch cryptedsize: %zu != clearsize: %zu", 295cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania cryptedsize, clearsize); 296cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 297cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 298cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 299cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 300cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const void *key; 301cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t keysize; 302cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (meta->findData(kKeyCryptoKey, &type, &key, &keysize)) { 303cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (keysize != kBlockSize) { 304e00e39229dedbd424438a3c8a9f88104aaf8bfc6Hassan Shojania ALOGE("getSampleCryptoInfo Keys must be %d bytes in length: %zu", 305cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania kBlockSize, keysize); 306cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // Keys must be 16 bytes in length. 307cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 308cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 309cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 310cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 311cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania const void *iv; 312cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania size_t ivsize; 313cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (meta->findData(kKeyCryptoIV, &type, &iv, &ivsize)) { 314cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (ivsize != kBlockSize) { 315e00e39229dedbd424438a3c8a9f88104aaf8bfc6Hassan Shojania ALOGE("getSampleCryptoInfo IV must be %d bytes in length: %zu", 316cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania kBlockSize, ivsize); 317cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania // IVs must be 16 bytes in length. 318cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return NULL; 319cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 320cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 321cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 322cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania int32_t mode; 323cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania if (!meta->findInt32(kKeyCryptoMode, &mode)) { 324cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania mode = CryptoPlugin::kMode_AES_CTR; 325cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania } 326cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 327cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania return makeCryptoInfo(numSubSamples, 328cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania (uint8_t*) key, 329cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania (uint8_t*) iv, 330cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania (CryptoPlugin::Mode)mode, 331cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania (size_t*) cleardata, 332cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania (size_t*) crypteddata); 333cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} 334cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 335cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania} // namespace android 336cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania 337