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