DrmManager.cpp revision fc4f5aad4af1e2d8eea5e7d7f69d1cad4704cbb7
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "DrmManager(Native)"
19#include "utils/Log.h"
20
21#include <utils/String8.h>
22#include <drm/DrmInfo.h>
23#include <drm/DrmInfoEvent.h>
24#include <drm/DrmRights.h>
25#include <drm/DrmConstraints.h>
26#include <drm/DrmMetadata.h>
27#include <drm/DrmInfoStatus.h>
28#include <drm/DrmInfoRequest.h>
29#include <drm/DrmSupportInfo.h>
30#include <drm/DrmConvertedStatus.h>
31#include <IDrmEngine.h>
32
33#include "DrmManager.h"
34#include "ReadWriteUtils.h"
35
36#define DECRYPT_FILE_ERROR -1
37
38using namespace android;
39
40Vector<int> DrmManager::mUniqueIdVector;
41const String8 DrmManager::EMPTY_STRING("");
42
43DrmManager::DrmManager() :
44    mDecryptSessionId(0),
45    mConvertId(0) {
46
47}
48
49DrmManager::~DrmManager() {
50
51}
52
53int DrmManager::addUniqueId(int uniqueId) {
54    if (0 == uniqueId) {
55        int temp = 0;
56        bool foundUniqueId = false;
57        srand(time(NULL));
58
59        while (!foundUniqueId) {
60            const int size = mUniqueIdVector.size();
61            temp = rand() % 100;
62
63            int index = 0;
64            for (; index < size; ++index) {
65                if (mUniqueIdVector.itemAt(index) == temp) {
66                    foundUniqueId = false;
67                    break;
68                }
69            }
70            if (index == size) {
71                foundUniqueId = true;
72            }
73        }
74        uniqueId = temp;
75    }
76    mUniqueIdVector.push(uniqueId);
77    return uniqueId;
78}
79
80void DrmManager::removeUniqueId(int uniqueId) {
81    for (unsigned int i = 0; i < mUniqueIdVector.size(); i++) {
82        if (uniqueId == mUniqueIdVector.itemAt(i)) {
83            mUniqueIdVector.removeAt(i);
84            break;
85        }
86    }
87}
88
89status_t DrmManager::loadPlugIns() {
90    String8 pluginDirPath("/system/lib/drm");
91    return loadPlugIns(pluginDirPath);
92}
93
94status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
95    if (mSupportInfoToPlugInIdMap.isEmpty()) {
96        mPlugInManager.loadPlugIns(plugInDirPath);
97        Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
98        for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
99            String8 plugInPath = plugInPathList[i];
100            DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
101            if (NULL != info) {
102                mSupportInfoToPlugInIdMap.add(*info, plugInPath);
103            }
104        }
105    }
106    return DRM_NO_ERROR;
107}
108
109status_t DrmManager::unloadPlugIns() {
110    mConvertSessionMap.clear();
111    mDecryptSessionMap.clear();
112    mPlugInManager.unloadPlugIns();
113    mSupportInfoToPlugInIdMap.clear();
114    return DRM_NO_ERROR;
115}
116
117status_t DrmManager::setDrmServiceListener(
118            int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
119    Mutex::Autolock _l(mLock);
120    mServiceListeners.add(uniqueId, drmServiceListener);
121    return DRM_NO_ERROR;
122}
123
124void DrmManager::addClient(int uniqueId) {
125    if (!mSupportInfoToPlugInIdMap.isEmpty()) {
126        Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
127        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
128            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
129            rDrmEngine.initialize(uniqueId);
130            rDrmEngine.setOnInfoListener(uniqueId, this);
131        }
132    }
133}
134
135void DrmManager::removeClient(int uniqueId) {
136    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
137    for (unsigned int index = 0; index < plugInIdList.size(); index++) {
138        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
139        rDrmEngine.terminate(uniqueId);
140    }
141}
142
143DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
144    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
145    if (EMPTY_STRING != plugInId) {
146        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
147        return rDrmEngine.getConstraints(uniqueId, path, action);
148    }
149    return NULL;
150}
151
152DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
153    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
154    if (EMPTY_STRING != plugInId) {
155        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
156        return rDrmEngine.getMetadata(uniqueId, path);
157    }
158    return NULL;
159}
160
161status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) {
162    mPlugInManager.loadPlugIn(absolutePath);
163
164    IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(absolutePath);
165    rDrmEngine.initialize(uniqueId);
166    rDrmEngine.setOnInfoListener(uniqueId, this);
167
168    DrmSupportInfo* info = rDrmEngine.getSupportInfo(0);
169    mSupportInfoToPlugInIdMap.add(*info, absolutePath);
170
171    return DRM_NO_ERROR;
172}
173
174bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
175    const String8 plugInId = getSupportedPlugInId(mimeType);
176    bool result = (EMPTY_STRING != plugInId) ? true : false;
177
178    if (0 < path.length()) {
179        if (result) {
180            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
181            result = rDrmEngine.canHandle(uniqueId, path);
182        } else {
183            result = canHandle(uniqueId, path);
184        }
185    }
186    return result;
187}
188
189DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
190    const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType());
191    if (EMPTY_STRING != plugInId) {
192        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
193        return rDrmEngine.processDrmInfo(uniqueId, drmInfo);
194    }
195    return NULL;
196}
197
198bool DrmManager::canHandle(int uniqueId, const String8& path) {
199    bool result = false;
200    Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
201
202    for (unsigned int i = 0; i < plugInPathList.size(); ++i) {
203        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]);
204        result = rDrmEngine.canHandle(uniqueId, path);
205
206        if (result) {
207            break;
208        }
209    }
210    return result;
211}
212
213DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
214    const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType());
215    if (EMPTY_STRING != plugInId) {
216        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
217        return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
218    }
219    return NULL;
220}
221
222status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
223            const String8& rightsPath, const String8& contentPath) {
224    const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType());
225    status_t result = DRM_ERROR_UNKNOWN;
226    if (EMPTY_STRING != plugInId) {
227        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
228        result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
229    }
230    return result;
231}
232
233String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) {
234    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
235    if (EMPTY_STRING != plugInId) {
236        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
237        return rDrmEngine.getOriginalMimeType(uniqueId, path);
238    }
239    return EMPTY_STRING;
240}
241
242int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
243    const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
244    if (EMPTY_STRING != plugInId) {
245        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
246        return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
247    }
248    return DrmObjectType::UNKNOWN;
249}
250
251int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
252    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
253    if (EMPTY_STRING != plugInId) {
254        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
255        return rDrmEngine.checkRightsStatus(uniqueId, path, action);
256    }
257    return RightsStatus::RIGHTS_INVALID;
258}
259
260status_t DrmManager::consumeRights(
261    int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
262    status_t result = DRM_ERROR_UNKNOWN;
263    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
264        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
265        result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve);
266    }
267    return result;
268}
269
270status_t DrmManager::setPlaybackStatus(
271    int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
272    status_t result = DRM_ERROR_UNKNOWN;
273    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
274        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
275        result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
276    }
277    return result;
278}
279
280bool DrmManager::validateAction(
281    int uniqueId, const String8& path, int action, const ActionDescription& description) {
282    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
283    if (EMPTY_STRING != plugInId) {
284        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
285        return rDrmEngine.validateAction(uniqueId, path, action, description);
286    }
287    return false;
288}
289
290status_t DrmManager::removeRights(int uniqueId, const String8& path) {
291    const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
292    status_t result = DRM_ERROR_UNKNOWN;
293    if (EMPTY_STRING != plugInId) {
294        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
295        result = rDrmEngine.removeRights(uniqueId, path);
296    }
297    return result;
298}
299
300status_t DrmManager::removeAllRights(int uniqueId) {
301    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
302    status_t result = DRM_ERROR_UNKNOWN;
303    for (unsigned int index = 0; index < plugInIdList.size(); index++) {
304        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
305        result = rDrmEngine.removeAllRights(uniqueId);
306        if (DRM_NO_ERROR != result) {
307            break;
308        }
309    }
310    return result;
311}
312
313int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
314    int convertId = -1;
315
316    const String8 plugInId = getSupportedPlugInId(mimeType);
317    if (EMPTY_STRING != plugInId) {
318        IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
319
320        if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) {
321            Mutex::Autolock _l(mConvertLock);
322            ++mConvertId;
323            convertId = mConvertId;
324            mConvertSessionMap.add(convertId, &rDrmEngine);
325        }
326    }
327    return convertId;
328}
329
330DrmConvertedStatus* DrmManager::convertData(
331            int uniqueId, int convertId, const DrmBuffer* inputData) {
332    DrmConvertedStatus *drmConvertedStatus = NULL;
333
334    if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
335        IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
336        drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData);
337    }
338    return drmConvertedStatus;
339}
340
341DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) {
342    DrmConvertedStatus *drmConvertedStatus = NULL;
343
344    if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
345        IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
346        drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId);
347        mConvertSessionMap.removeItem(convertId);
348    }
349    return drmConvertedStatus;
350}
351
352status_t DrmManager::getAllSupportInfo(
353                    int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) {
354    Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
355    int size = plugInPathList.size();
356    int validPlugins = 0;
357
358    if (0 < size) {
359        Vector<DrmSupportInfo> drmSupportInfoList;
360
361        for (int i = 0; i < size; ++i) {
362            String8 plugInPath = plugInPathList[i];
363            DrmSupportInfo* drmSupportInfo
364                = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
365            if (NULL != drmSupportInfo) {
366                drmSupportInfoList.add(*drmSupportInfo);
367                delete drmSupportInfo; drmSupportInfo = NULL;
368            }
369        }
370
371        validPlugins = drmSupportInfoList.size();
372        if (0 < validPlugins) {
373            *drmSupportInfoArray = new DrmSupportInfo[validPlugins];
374            for (int i = 0; i < validPlugins; ++i) {
375                (*drmSupportInfoArray)[i] = drmSupportInfoList[i];
376            }
377        }
378    }
379    *length = validPlugins;
380    return DRM_NO_ERROR;
381}
382
383DecryptHandle* DrmManager::openDecryptSession(int uniqueId, int fd, off64_t offset, off64_t length) {
384    Mutex::Autolock _l(mDecryptLock);
385    status_t result = DRM_ERROR_CANNOT_HANDLE;
386    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
387
388    DecryptHandle* handle = new DecryptHandle();
389    if (NULL != handle) {
390        handle->decryptId = mDecryptSessionId + 1;
391
392        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
393            String8 plugInId = plugInIdList.itemAt(index);
394            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
395            result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length);
396
397            if (DRM_NO_ERROR == result) {
398                ++mDecryptSessionId;
399                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
400                break;
401            }
402        }
403    }
404    if (DRM_NO_ERROR != result) {
405        delete handle; handle = NULL;
406    }
407    return handle;
408}
409
410DecryptHandle* DrmManager::openDecryptSession(int uniqueId, const char* uri) {
411    Mutex::Autolock _l(mDecryptLock);
412    status_t result = DRM_ERROR_CANNOT_HANDLE;
413    Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
414
415    DecryptHandle* handle = new DecryptHandle();
416    if (NULL != handle) {
417        handle->decryptId = mDecryptSessionId + 1;
418
419        for (unsigned int index = 0; index < plugInIdList.size(); index++) {
420            String8 plugInId = plugInIdList.itemAt(index);
421            IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
422            result = rDrmEngine.openDecryptSession(uniqueId, handle, uri);
423
424            if (DRM_NO_ERROR == result) {
425                ++mDecryptSessionId;
426                mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
427                break;
428            }
429        }
430    }
431    if (DRM_NO_ERROR != result) {
432        delete handle; handle = NULL;
433        LOGE("DrmManager::openDecryptSession: no capable plug-in found");
434    }
435    return handle;
436}
437
438status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
439    Mutex::Autolock _l(mDecryptLock);
440    status_t result = DRM_ERROR_UNKNOWN;
441    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
442        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
443        result = drmEngine->closeDecryptSession(uniqueId, decryptHandle);
444        if (DRM_NO_ERROR == result) {
445            mDecryptSessionMap.removeItem(decryptHandle->decryptId);
446        }
447    }
448    return result;
449}
450
451status_t DrmManager::initializeDecryptUnit(
452    int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) {
453    status_t result = DRM_ERROR_UNKNOWN;
454    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
455        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
456        result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
457    }
458    return result;
459}
460
461status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
462            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
463    status_t result = DRM_ERROR_UNKNOWN;
464    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
465        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
466        result = drmEngine->decrypt(
467                uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
468    }
469    return result;
470}
471
472status_t DrmManager::finalizeDecryptUnit(
473            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
474    status_t result = DRM_ERROR_UNKNOWN;
475    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
476        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
477        result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
478    }
479    return result;
480}
481
482ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle,
483            void* buffer, ssize_t numBytes, off64_t offset) {
484    ssize_t result = DECRYPT_FILE_ERROR;
485
486    if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
487        IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
488        result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
489    }
490    return result;
491}
492
493String8 DrmManager::getSupportedPlugInId(
494            int uniqueId, const String8& path, const String8& mimeType) {
495    String8 plugInId("");
496
497    if (EMPTY_STRING != mimeType) {
498        plugInId = getSupportedPlugInId(mimeType);
499    } else {
500        plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
501    }
502    return plugInId;
503}
504
505String8 DrmManager::getSupportedPlugInId(const String8& mimeType) {
506    String8 plugInId("");
507
508    if (EMPTY_STRING != mimeType) {
509        for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
510            const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
511
512            if (drmSupportInfo.isSupportedMimeType(mimeType)) {
513                plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
514                break;
515            }
516        }
517    }
518    return plugInId;
519}
520
521String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
522    String8 plugInId("");
523    const String8 fileSuffix = path.getPathExtension();
524
525    for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
526        const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
527
528        if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) {
529            String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
530            IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key);
531
532            if (drmEngine.canHandle(uniqueId, path)) {
533                plugInId = key;
534                break;
535            }
536        }
537    }
538    return plugInId;
539}
540
541void DrmManager::onInfo(const DrmInfoEvent& event) {
542    Mutex::Autolock _l(mLock);
543    for (unsigned int index = 0; index < mServiceListeners.size(); index++) {
544        int uniqueId = mServiceListeners.keyAt(index);
545
546        if (uniqueId == event.getUniqueId()) {
547            sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId);
548            serviceListener->notify(event);
549        }
550    }
551}
552
553