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