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>
237d2c6e8be2c9a4f3c1364d243856a345f17f851eJeff Tinker#include <mediadrm/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
2683d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco NelissenNuPlayerDrm::CryptoInfo *NuPlayerDrm::getSampleCryptoInfo(MetaDataBase &meta)
269cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania{
270cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    uint32_t type;
271cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    const void *crypteddata;
272cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    size_t cryptedsize;
273cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
2743d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (!meta.findData(kKeyEncryptedSizes, &type, &crypteddata, &cryptedsize)) {
275cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        return NULL;
276cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    }
277cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    size_t numSubSamples = cryptedsize / sizeof(size_t);
278cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
279cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    if (numSubSamples <= 0) {
280cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        ALOGE("getSampleCryptoInfo INVALID numSubSamples: %zu", numSubSamples);
281cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        return NULL;
282cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    }
283cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
284cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    const void *cleardata;
285cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    size_t clearsize;
2863d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (meta.findData(kKeyPlainSizes, &type, &cleardata, &clearsize)) {
287cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        if (clearsize != cryptedsize) {
288cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            // The two must be of the same length.
289cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            ALOGE("getSampleCryptoInfo mismatch cryptedsize: %zu != clearsize: %zu",
290cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania                    cryptedsize, clearsize);
291cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            return NULL;
292cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        }
293cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    }
294cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
295cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    const void *key;
296cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    size_t keysize;
2973d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (meta.findData(kKeyCryptoKey, &type, &key, &keysize)) {
298cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        if (keysize != kBlockSize) {
299e00e39229dedbd424438a3c8a9f88104aaf8bfc6Hassan Shojania            ALOGE("getSampleCryptoInfo Keys must be %d bytes in length: %zu",
300cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania                    kBlockSize, keysize);
301cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            // Keys must be 16 bytes in length.
302cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            return NULL;
303cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        }
304cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    }
305cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
306cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    const void *iv;
307cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    size_t ivsize;
3083d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (meta.findData(kKeyCryptoIV, &type, &iv, &ivsize)) {
309cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        if (ivsize != kBlockSize) {
310e00e39229dedbd424438a3c8a9f88104aaf8bfc6Hassan Shojania            ALOGE("getSampleCryptoInfo IV must be %d bytes in length: %zu",
311cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania                    kBlockSize, ivsize);
312cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            // IVs must be 16 bytes in length.
313cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            return NULL;
314cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        }
315cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    }
316cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
317cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    int32_t mode;
3183d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen    if (!meta.findInt32(kKeyCryptoMode, &mode)) {
319cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania        mode = CryptoPlugin::kMode_AES_CTR;
320cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    }
321cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
322cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania    return makeCryptoInfo(numSubSamples,
323cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            (uint8_t*) key,
324cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            (uint8_t*) iv,
325cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            (CryptoPlugin::Mode)mode,
326cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            (size_t*) cleardata,
327cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania            (size_t*) crypteddata);
328cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania}
329cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
330cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania}   // namespace android
331cefac14261a32fb856b0d1ab31541787112e306eHassan Shojania
332