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