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 
20 #include <cutils/properties.h>
21 #include <utils/String8.h>
22 #include <utils/Log.h>
23 
24 #include <binder/IPCThreadState.h>
25 #include <drm/DrmInfo.h>
26 
27 #include <drm/DrmInfoEvent.h>
28 #include <drm/DrmRights.h>
29 #include <drm/DrmConstraints.h>
30 #include <drm/DrmMetadata.h>
31 #include <drm/DrmInfoStatus.h>
32 #include <drm/DrmInfoRequest.h>
33 #include <drm/DrmSupportInfo.h>
34 #include <drm/DrmConvertedStatus.h>
35 #include <media/MediaMetricsItem.h>
36 #include <IDrmEngine.h>
37 
38 #include "DrmManager.h"
39 #include "ReadWriteUtils.h"
40 
41 #include <algorithm>
42 
43 #define DECRYPT_FILE_ERROR (-1)
44 
45 using namespace android;
46 
47 const String8 DrmManager::EMPTY_STRING("");
48 
49 const std::map<const char*, size_t> DrmManager::kMethodIdMap {
50     {"getConstraints"     , DrmManagerMethodId::GET_CONSTRAINTS       },
51     {"getMetadata"        , DrmManagerMethodId::GET_METADATA          },
52     {"canHandle"          , DrmManagerMethodId::CAN_HANDLE            },
53     {"processDrmInfo"     , DrmManagerMethodId::PROCESS_DRM_INFO      },
54     {"acquireDrmInfo"     , DrmManagerMethodId::ACQUIRE_DRM_INFO      },
55     {"saveRights"         , DrmManagerMethodId::SAVE_RIGHTS           },
56     {"getOriginalMimeType", DrmManagerMethodId::GET_ORIGINAL_MIME_TYPE},
57     {"getDrmObjectType"   , DrmManagerMethodId::GET_DRM_OBJECT_TYPE   },
58     {"checkRightsStatus"  , DrmManagerMethodId::CHECK_RIGHTS_STATUS   },
59     {"removeRights"       , DrmManagerMethodId::REMOVE_RIGHTS         },
60     {"removeAllRights"    , DrmManagerMethodId::REMOVE_ALL_RIGHTS     },
61     {"openConvertSession" , DrmManagerMethodId::OPEN_CONVERT_SESSION  },
62     {"openDecryptSession" , DrmManagerMethodId::OPEN_DECRYPT_SESSION  }
63 };
64 
DrmManager()65 DrmManager::DrmManager() :
66     mDecryptSessionId(0),
67     mConvertId(0) {
68     srand(time(NULL));
69     memset(mUniqueIdArray, 0, sizeof(bool) * kMaxNumUniqueIds);
70 }
71 
~DrmManager()72 DrmManager::~DrmManager() {
73     if (mMetricsLooper != NULL) {
74         mMetricsLooper->stop();
75     }
76     flushEngineMetrics();
77 }
78 
initMetricsLooper()79 void DrmManager::initMetricsLooper() {
80     if (mMetricsLooper != NULL) {
81         return;
82     }
83     mMetricsLooper = new ALooper;
84     mMetricsLooper->setName("DrmManagerMetricsLooper");
85     mMetricsLooper->start();
86     mMetricsLooper->registerHandler(this);
87 
88     sp<AMessage> msg = new AMessage(kWhatFlushMetrics, this);
89     msg->post(getMetricsFlushPeriodUs());
90 }
91 
onMessageReceived(const sp<AMessage> & msg)92 void DrmManager::onMessageReceived(const sp<AMessage> &msg) {
93     switch (msg->what()) {
94         case kWhatFlushMetrics:
95         {
96             flushEngineMetrics();
97             msg->post(getMetricsFlushPeriodUs());
98             break;
99         }
100         default:
101         {
102             ALOGW("Unrecognized message type: %zd", msg->what());
103         }
104     }
105 }
106 
getMetricsFlushPeriodUs()107 int64_t DrmManager::getMetricsFlushPeriodUs() {
108     return 1000 * 1000 * std::max(1ll, property_get_int64("drmmanager.metrics.period", 86400));
109 }
110 
recordEngineMetrics(const char func[],const String8 & plugInId8,const String8 & mimeType)111 void DrmManager::recordEngineMetrics(
112         const char func[], const String8& plugInId8, const String8& mimeType) {
113     IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId8);
114     std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
115 
116     uid_t callingUid = IPCThreadState::self()->getCallingUid();
117     std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
118     ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
119 
120     Mutex::Autolock _l(mMetricsLock);
121     auto& metrics = mPluginMetrics[std::make_pair(callingUid, plugInId)];
122     if (metrics.mPluginId.empty()) {
123         metrics.mPluginId = plugInId;
124         metrics.mCallingUid = callingUid;
125         if (NULL != info) {
126             metrics.mDescription = info->getDescription().c_str();
127         }
128     }
129 
130     if (!mimeType.isEmpty()) {
131         metrics.mMimeTypes.insert(mimeType.c_str());
132     } else if (NULL != info) {
133         DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
134         while (mimeIter.hasNext()) {
135             metrics.mMimeTypes.insert(mimeIter.next().c_str());
136         }
137     }
138 
139     size_t methodId = kMethodIdMap.at(func);
140     if (methodId < metrics.mMethodCounts.size()) {
141         metrics.mMethodCounts[methodId]++;
142     }
143 }
144 
flushEngineMetrics()145 void DrmManager::flushEngineMetrics() {
146     using namespace std::string_literals;
147     Mutex::Autolock _l(mMetricsLock);
148     for (auto kv : mPluginMetrics) {
149         DrmManagerMetrics& metrics = kv.second;
150         std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
151         item->setUid(metrics.mCallingUid);
152         item->setCString("plugin_id", metrics.mPluginId.c_str());
153         item->setCString("description", metrics.mDescription.c_str());
154 
155         std::vector<std::string> mimeTypes(metrics.mMimeTypes.begin(), metrics.mMimeTypes.end());
156         std::string mimeTypesStr(mimeTypes.empty() ? "" : mimeTypes[0]);
157         for (size_t i = 1; i < mimeTypes.size() ; i++) {
158             mimeTypesStr.append(",").append(mimeTypes[i]);
159         }
160         item->setCString("mime_types", mimeTypesStr.c_str());
161 
162         for (size_t i = 0; i < metrics.mMethodCounts.size() ; i++) {
163             item->setInt64(("method"s + std::to_string(i)).c_str(), metrics.mMethodCounts[i]);
164         }
165 
166         if (!item->selfrecord()) {
167             ALOGE("Failed to record metrics");
168         }
169     }
170     mPluginMetrics.clear();
171 }
172 
addUniqueId(bool isNative)173 int DrmManager::addUniqueId(bool isNative) {
174     Mutex::Autolock _l(mLock);
175 
176     int uniqueId = -1;
177     int random = rand();
178 
179     for (size_t index = 0; index < kMaxNumUniqueIds; ++index) {
180         int temp = (random + index) % kMaxNumUniqueIds;
181         if (!mUniqueIdArray[temp]) {
182             uniqueId = temp;
183             mUniqueIdArray[uniqueId] = true;
184 
185             if (isNative) {
186                 // set a flag to differentiate DrmManagerClient
187                 // created from native side and java side
188                 uniqueId |= 0x1000;
189             }
190             break;
191         }
192     }
193 
194     // -1 indicates that no unique id can be allocated.
195     return uniqueId;
196 }
197 
removeUniqueId(int uniqueId)198 void DrmManager::removeUniqueId(int uniqueId) {
199     Mutex::Autolock _l(mLock);
200     if (uniqueId & 0x1000) {
201         // clear the flag for the native side.
202         uniqueId &= ~(0x1000);
203     }
204 
205     if (uniqueId >= 0 && uniqueId < kMaxNumUniqueIds) {
206         mUniqueIdArray[uniqueId] = false;
207     }
208 }
209 
loadPlugIns()210 status_t DrmManager::loadPlugIns() {
211     String8 pluginDirPath("/system/lib/drm");
212     loadPlugIns(pluginDirPath);
213     return DRM_NO_ERROR;
214 }
215 
loadPlugIns(const String8 & plugInDirPath)216 status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
217     mPlugInManager.loadPlugIns(plugInDirPath);
218     Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
219     for (size_t i = 0; i < plugInPathList.size(); ++i) {
220         String8 plugInPath = plugInPathList[i];
221         DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
222         if (NULL != info) {
223             if (mSupportInfoToPlugInIdMap.indexOfKey(*info) < 0) {
224                 mSupportInfoToPlugInIdMap.add(*info, plugInPath);
225             }
226             delete info;
227         }
228     }
229     return DRM_NO_ERROR;
230 }
231 
unloadPlugIns()232 status_t DrmManager::unloadPlugIns() {
233     Mutex::Autolock _l(mLock);
234     mConvertSessionMap.clear();
235     mDecryptSessionMap.clear();
236     mPlugInManager.unloadPlugIns();
237     mSupportInfoToPlugInIdMap.clear();
238     return DRM_NO_ERROR;
239 }
240 
setDrmServiceListener(int uniqueId,const sp<IDrmServiceListener> & drmServiceListener)241 status_t DrmManager::setDrmServiceListener(
242             int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
243     Mutex::Autolock _l(mListenerLock);
244     if (NULL != drmServiceListener.get()) {
245         mServiceListeners.add(uniqueId, drmServiceListener);
246     } else {
247         mServiceListeners.removeItem(uniqueId);
248     }
249     return DRM_NO_ERROR;
250 }
251 
addClient(int uniqueId)252 void DrmManager::addClient(int uniqueId) {
253     Mutex::Autolock _l(mLock);
254     if (!mSupportInfoToPlugInIdMap.isEmpty()) {
255         Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
256         for (size_t index = 0; index < plugInIdList.size(); index++) {
257             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
258             rDrmEngine.initialize(uniqueId);
259             rDrmEngine.setOnInfoListener(uniqueId, this);
260         }
261     }
262 }
263 
removeClient(int uniqueId)264 void DrmManager::removeClient(int uniqueId) {
265     Mutex::Autolock _l(mLock);
266     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
267     for (size_t index = 0; index < plugInIdList.size(); index++) {
268         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
269         rDrmEngine.terminate(uniqueId);
270     }
271 }
272 
getConstraints(int uniqueId,const String8 * path,const int action)273 DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
274     Mutex::Autolock _l(mLock);
275     DrmConstraints *constraints = NULL;
276     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
277     if (EMPTY_STRING != plugInId) {
278         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
279         constraints = rDrmEngine.getConstraints(uniqueId, path, action);
280     }
281     if (NULL != constraints) {
282         recordEngineMetrics(__func__, plugInId);
283     }
284     return constraints;
285 }
286 
getMetadata(int uniqueId,const String8 * path)287 DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
288     Mutex::Autolock _l(mLock);
289     DrmMetadata *meta = NULL;
290     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
291     if (EMPTY_STRING != plugInId) {
292         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
293         meta = rDrmEngine.getMetadata(uniqueId, path);
294     }
295     if (NULL != meta) {
296         recordEngineMetrics(__func__, plugInId);
297     }
298     return meta;
299 }
300 
canHandle(int uniqueId,const String8 & path,const String8 & mimeType)301 bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
302     Mutex::Autolock _l(mLock);
303     const String8 plugInId = getSupportedPlugInId(mimeType);
304     bool result = (EMPTY_STRING != plugInId) ? true : false;
305 
306     if (result) {
307         recordEngineMetrics(__func__, plugInId, mimeType);
308     }
309 
310     if (0 < path.length()) {
311         if (result) {
312             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
313             result = rDrmEngine.canHandle(uniqueId, path);
314         } else {
315             String8 extension = path.getPathExtension();
316             if (String8("") != extension) {
317                 result = canHandle(uniqueId, path);
318             }
319         }
320     }
321     return result;
322 }
323 
processDrmInfo(int uniqueId,const DrmInfo * drmInfo)324 DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
325     Mutex::Autolock _l(mLock);
326     DrmInfoStatus *infoStatus = NULL;
327     const String8 mimeType = drmInfo->getMimeType();
328     const String8 plugInId = getSupportedPlugInId(mimeType);
329     if (EMPTY_STRING != plugInId) {
330         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
331         infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
332     }
333     if (NULL != infoStatus) {
334         recordEngineMetrics(__func__, plugInId, mimeType);
335     }
336     return infoStatus;
337 }
338 
canHandle(int uniqueId,const String8 & path)339 bool DrmManager::canHandle(int uniqueId, const String8& path) {
340     bool result = false;
341     Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
342 
343     for (size_t i = 0; i < plugInPathList.size(); ++i) {
344         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]);
345         result = rDrmEngine.canHandle(uniqueId, path);
346 
347         if (result) {
348             recordEngineMetrics(__func__, plugInPathList[i]);
349             break;
350         }
351     }
352     return result;
353 }
354 
acquireDrmInfo(int uniqueId,const DrmInfoRequest * drmInfoRequest)355 DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
356     Mutex::Autolock _l(mLock);
357     DrmInfo *info = NULL;
358     const String8 mimeType = drmInfoRequest->getMimeType();
359     const String8 plugInId = getSupportedPlugInId(mimeType);
360     if (EMPTY_STRING != plugInId) {
361         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
362         info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
363     }
364     if (NULL != info) {
365         recordEngineMetrics(__func__, plugInId, mimeType);
366     }
367     return info;
368 }
369 
saveRights(int uniqueId,const DrmRights & drmRights,const String8 & rightsPath,const String8 & contentPath)370 status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
371             const String8& rightsPath, const String8& contentPath) {
372     Mutex::Autolock _l(mLock);
373     const String8 mimeType = drmRights.getMimeType();
374     const String8 plugInId = getSupportedPlugInId(mimeType);
375     status_t result = DRM_ERROR_UNKNOWN;
376     if (EMPTY_STRING != plugInId) {
377         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
378         result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
379     }
380     if (DRM_NO_ERROR == result) {
381         recordEngineMetrics(__func__, plugInId, mimeType);
382     }
383     return result;
384 }
385 
getOriginalMimeType(int uniqueId,const String8 & path,int fd)386 String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path, int fd) {
387     Mutex::Autolock _l(mLock);
388     String8 mimeType(EMPTY_STRING);
389     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
390     if (EMPTY_STRING != plugInId) {
391         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
392         mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
393     }
394     if (!mimeType.isEmpty()) {
395         recordEngineMetrics(__func__, plugInId, mimeType);
396     }
397     return mimeType;
398 }
399 
getDrmObjectType(int uniqueId,const String8 & path,const String8 & mimeType)400 int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
401     Mutex::Autolock _l(mLock);
402     int type = DrmObjectType::UNKNOWN;
403     const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
404     if (EMPTY_STRING != plugInId) {
405         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
406         type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
407     }
408     if (DrmObjectType::UNKNOWN != type) {
409         recordEngineMetrics(__func__, plugInId, mimeType);
410     }
411     return type;
412 }
413 
checkRightsStatus(int uniqueId,const String8 & path,int action)414 int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
415     Mutex::Autolock _l(mLock);
416     int rightsStatus = RightsStatus::RIGHTS_INVALID;
417     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
418     if (EMPTY_STRING != plugInId) {
419         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
420         rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
421     }
422     if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
423         recordEngineMetrics(__func__, plugInId);
424     }
425     return rightsStatus;
426 }
427 
consumeRights(int uniqueId,sp<DecryptHandle> & decryptHandle,int action,bool reserve)428 status_t DrmManager::consumeRights(
429     int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) {
430     status_t result = DRM_ERROR_UNKNOWN;
431     Mutex::Autolock _l(mDecryptLock);
432     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
433         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
434         result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve);
435     }
436     return result;
437 }
438 
setPlaybackStatus(int uniqueId,sp<DecryptHandle> & decryptHandle,int playbackStatus,int64_t position)439 status_t DrmManager::setPlaybackStatus(
440     int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position) {
441     status_t result = DRM_ERROR_UNKNOWN;
442     Mutex::Autolock _l(mDecryptLock);
443     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
444         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
445         result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
446     }
447     return result;
448 }
449 
validateAction(int uniqueId,const String8 & path,int action,const ActionDescription & description)450 bool DrmManager::validateAction(
451     int uniqueId, const String8& path, int action, const ActionDescription& description) {
452     Mutex::Autolock _l(mLock);
453     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
454     if (EMPTY_STRING != plugInId) {
455         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
456         return rDrmEngine.validateAction(uniqueId, path, action, description);
457     }
458     return false;
459 }
460 
removeRights(int uniqueId,const String8 & path)461 status_t DrmManager::removeRights(int uniqueId, const String8& path) {
462     Mutex::Autolock _l(mLock);
463     const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
464     status_t result = DRM_ERROR_UNKNOWN;
465     if (EMPTY_STRING != plugInId) {
466         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
467         result = rDrmEngine.removeRights(uniqueId, path);
468     }
469     if (DRM_NO_ERROR == result) {
470         recordEngineMetrics(__func__, plugInId);
471     }
472     return result;
473 }
474 
removeAllRights(int uniqueId)475 status_t DrmManager::removeAllRights(int uniqueId) {
476     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
477     status_t result = DRM_ERROR_UNKNOWN;
478     for (size_t index = 0; index < plugInIdList.size(); index++) {
479         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
480         result = rDrmEngine.removeAllRights(uniqueId);
481         if (DRM_NO_ERROR != result) {
482             break;
483         }
484         recordEngineMetrics(__func__, plugInIdList[index]);
485     }
486     return result;
487 }
488 
openConvertSession(int uniqueId,const String8 & mimeType)489 int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
490     Mutex::Autolock _l(mConvertLock);
491     int convertId = -1;
492 
493     const String8 plugInId = getSupportedPlugInId(mimeType);
494     if (EMPTY_STRING != plugInId) {
495         IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
496 
497         if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) {
498             ++mConvertId;
499             convertId = mConvertId;
500             mConvertSessionMap.add(convertId, &rDrmEngine);
501             recordEngineMetrics(__func__, plugInId, mimeType);
502         }
503     }
504     return convertId;
505 }
506 
convertData(int uniqueId,int convertId,const DrmBuffer * inputData)507 DrmConvertedStatus* DrmManager::convertData(
508             int uniqueId, int convertId, const DrmBuffer* inputData) {
509     DrmConvertedStatus *drmConvertedStatus = NULL;
510 
511     Mutex::Autolock _l(mConvertLock);
512     if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
513         IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
514         drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData);
515     }
516     return drmConvertedStatus;
517 }
518 
closeConvertSession(int uniqueId,int convertId)519 DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) {
520     Mutex::Autolock _l(mConvertLock);
521     DrmConvertedStatus *drmConvertedStatus = NULL;
522 
523     if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
524         IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
525         drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId);
526         mConvertSessionMap.removeItem(convertId);
527     }
528     return drmConvertedStatus;
529 }
530 
getAllSupportInfo(int,int * length,DrmSupportInfo ** drmSupportInfoArray)531 status_t DrmManager::getAllSupportInfo(
532                     int /* uniqueId */, int* length, DrmSupportInfo** drmSupportInfoArray) {
533     Mutex::Autolock _l(mLock);
534     Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
535     int size = plugInPathList.size();
536     int validPlugins = 0;
537 
538     if (0 < size) {
539         Vector<DrmSupportInfo> drmSupportInfoList;
540 
541         for (int i = 0; i < size; ++i) {
542             String8 plugInPath = plugInPathList[i];
543             DrmSupportInfo* drmSupportInfo
544                 = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
545             if (NULL != drmSupportInfo) {
546                 drmSupportInfoList.add(*drmSupportInfo);
547                 delete drmSupportInfo; drmSupportInfo = NULL;
548             }
549         }
550 
551         validPlugins = drmSupportInfoList.size();
552         if (0 < validPlugins) {
553             *drmSupportInfoArray = new DrmSupportInfo[validPlugins];
554             for (int i = 0; i < validPlugins; ++i) {
555                 (*drmSupportInfoArray)[i] = drmSupportInfoList[i];
556             }
557         }
558     }
559     *length = validPlugins;
560     return DRM_NO_ERROR;
561 }
562 
openDecryptSession(int uniqueId,int fd,off64_t offset,off64_t length,const char * mime)563 sp<DecryptHandle> DrmManager::openDecryptSession(
564         int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
565 
566     Mutex::Autolock _l(mDecryptLock);
567     status_t result = DRM_ERROR_CANNOT_HANDLE;
568     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
569 
570     sp<DecryptHandle> handle = new DecryptHandle();
571     if (NULL != handle.get()) {
572         handle->decryptId = mDecryptSessionId + 1;
573 
574         for (size_t index = 0; index < plugInIdList.size(); index++) {
575             const String8& plugInId = plugInIdList.itemAt(index);
576             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
577             result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length, mime);
578 
579             if (DRM_NO_ERROR == result) {
580                 ++mDecryptSessionId;
581                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
582                 recordEngineMetrics(__func__, plugInId, String8(mime));
583                 break;
584             }
585         }
586     }
587     if (DRM_NO_ERROR != result) {
588         handle.clear();
589     }
590     return handle;
591 }
592 
openDecryptSession(int uniqueId,const char * uri,const char * mime)593 sp<DecryptHandle> DrmManager::openDecryptSession(
594         int uniqueId, const char* uri, const char* mime) {
595     Mutex::Autolock _l(mDecryptLock);
596     status_t result = DRM_ERROR_CANNOT_HANDLE;
597     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
598 
599     sp<DecryptHandle> handle = new DecryptHandle();
600     if (NULL != handle.get()) {
601         handle->decryptId = mDecryptSessionId + 1;
602 
603         for (size_t index = 0; index < plugInIdList.size(); index++) {
604             const String8& plugInId = plugInIdList.itemAt(index);
605             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
606             result = rDrmEngine.openDecryptSession(uniqueId, handle, uri, mime);
607 
608             if (DRM_NO_ERROR == result) {
609                 ++mDecryptSessionId;
610                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
611                 recordEngineMetrics(__func__, plugInId, String8(mime));
612                 break;
613             }
614         }
615     }
616     if (DRM_NO_ERROR != result) {
617         handle.clear();
618         ALOGV("DrmManager::openDecryptSession: no capable plug-in found");
619     }
620     return handle;
621 }
622 
openDecryptSession(int uniqueId,const DrmBuffer & buf,const String8 & mimeType)623 sp<DecryptHandle> DrmManager::openDecryptSession(
624         int uniqueId, const DrmBuffer& buf, const String8& mimeType) {
625     Mutex::Autolock _l(mDecryptLock);
626     status_t result = DRM_ERROR_CANNOT_HANDLE;
627     Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
628 
629     sp<DecryptHandle> handle = new DecryptHandle();
630     if (NULL != handle.get()) {
631         handle->decryptId = mDecryptSessionId + 1;
632 
633         for (size_t index = 0; index < plugInIdList.size(); index++) {
634             const String8& plugInId = plugInIdList.itemAt(index);
635             IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
636             result = rDrmEngine.openDecryptSession(uniqueId, handle, buf, mimeType);
637 
638             if (DRM_NO_ERROR == result) {
639                 ++mDecryptSessionId;
640                 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
641                 recordEngineMetrics(__func__, plugInId, mimeType);
642                 break;
643             }
644         }
645     }
646     if (DRM_NO_ERROR != result) {
647         handle.clear();
648         ALOGV("DrmManager::openDecryptSession: no capable plug-in found");
649     }
650     return handle;
651 }
652 
closeDecryptSession(int uniqueId,sp<DecryptHandle> & decryptHandle)653 status_t DrmManager::closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) {
654     Mutex::Autolock _l(mDecryptLock);
655     status_t result = DRM_ERROR_UNKNOWN;
656     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
657         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
658         result = drmEngine->closeDecryptSession(uniqueId, decryptHandle);
659         if (DRM_NO_ERROR == result && NULL != decryptHandle.get()) {
660             mDecryptSessionMap.removeItem(decryptHandle->decryptId);
661         }
662     }
663     return result;
664 }
665 
initializeDecryptUnit(int uniqueId,sp<DecryptHandle> & decryptHandle,int decryptUnitId,const DrmBuffer * headerInfo)666 status_t DrmManager::initializeDecryptUnit(
667         int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId,
668         const DrmBuffer* headerInfo) {
669     status_t result = DRM_ERROR_UNKNOWN;
670     Mutex::Autolock _l(mDecryptLock);
671     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
672         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
673         result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
674     }
675     return result;
676 }
677 
decrypt(int uniqueId,sp<DecryptHandle> & decryptHandle,int decryptUnitId,const DrmBuffer * encBuffer,DrmBuffer ** decBuffer,DrmBuffer * IV)678 status_t DrmManager::decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId,
679             const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
680     status_t result = DRM_ERROR_UNKNOWN;
681 
682     Mutex::Autolock _l(mDecryptLock);
683     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
684         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
685         result = drmEngine->decrypt(
686                 uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
687     }
688     return result;
689 }
690 
finalizeDecryptUnit(int uniqueId,sp<DecryptHandle> & decryptHandle,int decryptUnitId)691 status_t DrmManager::finalizeDecryptUnit(
692             int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) {
693     status_t result = DRM_ERROR_UNKNOWN;
694     Mutex::Autolock _l(mDecryptLock);
695     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
696         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
697         result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
698     }
699     return result;
700 }
701 
pread(int uniqueId,sp<DecryptHandle> & decryptHandle,void * buffer,ssize_t numBytes,off64_t offset)702 ssize_t DrmManager::pread(int uniqueId, sp<DecryptHandle>& decryptHandle,
703             void* buffer, ssize_t numBytes, off64_t offset) {
704     ssize_t result = DECRYPT_FILE_ERROR;
705 
706     Mutex::Autolock _l(mDecryptLock);
707     if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
708         IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
709         result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
710     }
711     return result;
712 }
713 
getSupportedPlugInId(int uniqueId,const String8 & path,const String8 & mimeType)714 String8 DrmManager::getSupportedPlugInId(
715             int uniqueId, const String8& path, const String8& mimeType) {
716     String8 plugInId("");
717 
718     if (EMPTY_STRING != mimeType) {
719         plugInId = getSupportedPlugInId(mimeType);
720     } else {
721         plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
722     }
723     return plugInId;
724 }
725 
getSupportedPlugInId(const String8 & mimeType)726 String8 DrmManager::getSupportedPlugInId(const String8& mimeType) {
727     String8 plugInId("");
728 
729     if (EMPTY_STRING != mimeType) {
730         for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
731             const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
732 
733             if (drmSupportInfo.isSupportedMimeType(mimeType)) {
734                 plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
735                 break;
736             }
737         }
738     }
739     return plugInId;
740 }
741 
getSupportedPlugInIdFromPath(int uniqueId,const String8 & path)742 String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
743     String8 plugInId("");
744     const String8 fileSuffix = path.getPathExtension();
745 
746     for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
747         const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
748 
749         if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) {
750             String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
751             IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key);
752 
753             if (drmEngine.canHandle(uniqueId, path)) {
754                 plugInId = key;
755                 break;
756             }
757         }
758     }
759     return plugInId;
760 }
761 
onInfo(const DrmInfoEvent & event)762 void DrmManager::onInfo(const DrmInfoEvent& event) {
763     Mutex::Autolock _l(mListenerLock);
764     for (size_t index = 0; index < mServiceListeners.size(); index++) {
765         int uniqueId = mServiceListeners.keyAt(index);
766 
767         if (uniqueId == event.getUniqueId()) {
768             sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId);
769             serviceListener->notify(event);
770         }
771     }
772 }
773 
774