blob: cf0861017356040b8a8b2c157588b16445cbbf9b [file] [log] [blame]
Jeff Tinkera53d6552017-01-20 00:31:46 -08001/*
2 * Copyright (C) 2017 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 "DrmHal"
Adam Stonefb679e32018-02-07 10:25:48 -080019#include <iomanip>
20
Jeff Tinkera53d6552017-01-20 00:31:46 -080021#include <utils/Log.h>
22
23#include <binder/IPCThreadState.h>
24#include <binder/IServiceManager.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080025
Jeff Tinkera53d6552017-01-20 00:31:46 -080026#include <android/hardware/drm/1.0/types.h>
Jeff Tinkerabeb36a2017-02-17 09:42:46 -080027#include <android/hidl/manager/1.0/IServiceManager.h>
Jeff Tinker593111f2017-05-25 16:00:21 -070028#include <hidl/ServiceManagement.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080029
Adam Stonef0e618d2018-01-17 19:20:41 -080030#include <media/EventMetric.h>
John W. Bruce33ecc4f2017-04-03 16:49:05 -070031#include <media/PluginMetricsReporting.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080032#include <media/drm/DrmAPI.h>
33#include <media/stagefright/foundation/ADebug.h>
34#include <media/stagefright/foundation/AString.h>
Adam Stone32494f52018-02-26 22:53:27 -080035#include <media/stagefright/foundation/base64.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080036#include <media/stagefright/foundation/hexdump.h>
37#include <media/stagefright/MediaErrors.h>
Jeff Tinker7d2c6e82018-02-16 16:14:59 -080038#include <mediadrm/DrmHal.h>
39#include <mediadrm/DrmSessionClientInterface.h>
40#include <mediadrm/DrmSessionManager.h>
Jeff Tinkera53d6552017-01-20 00:31:46 -080041
Jeff Tinker6d998b62017-12-18 14:37:43 -080042using drm::V1_0::KeyedVector;
Jeff Tinker6d998b62017-12-18 14:37:43 -080043using drm::V1_0::KeyStatusType;
44using drm::V1_0::KeyType;
45using drm::V1_0::KeyValue;
46using drm::V1_1::HdcpLevel;;
47using drm::V1_0::SecureStop;
Jeff Tinker15177d72018-01-25 12:57:55 -080048using drm::V1_1::SecureStopRelease;
49using drm::V1_0::SecureStopId;
Jeff Tinker6d998b62017-12-18 14:37:43 -080050using drm::V1_1::SecurityLevel;
51using drm::V1_0::Status;
Adam Stone28f27c32018-02-05 15:07:48 -080052using ::android::hardware::drm::V1_1::DrmMetricGroup;
Jeff Tinkera53d6552017-01-20 00:31:46 -080053using ::android::hardware::hidl_array;
54using ::android::hardware::hidl_string;
55using ::android::hardware::hidl_vec;
56using ::android::hardware::Return;
57using ::android::hardware::Void;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -080058using ::android::hidl::manager::V1_0::IServiceManager;
Adam Stone637b7852018-01-30 12:09:36 -080059using ::android::os::PersistableBundle;
Jeff Tinkera53d6552017-01-20 00:31:46 -080060using ::android::sp;
61
Adam Stonecea91ce2018-01-22 19:23:28 -080062namespace {
63
64// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
65// in the MediaDrm API.
66constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
Adam Stone32494f52018-02-26 22:53:27 -080067constexpr char kEqualsSign[] = "=";
Adam Stonecea91ce2018-01-22 19:23:28 -080068
Adam Stone32494f52018-02-26 22:53:27 -080069template<typename T>
70std::string toBase64StringNoPad(const T* data, size_t size) {
Adam Stone630092e2018-05-02 13:06:34 -070071 // Note that the base 64 conversion only works with arrays of single-byte
72 // values. If the source is empty or is not an array of single-byte values,
73 // return empty string.
74 if (size == 0 || sizeof(data[0]) != 1) {
Adam Stone32494f52018-02-26 22:53:27 -080075 return "";
76 }
Adam Stone32494f52018-02-26 22:53:27 -080077
78 android::AString outputString;
79 encodeBase64(data, size, &outputString);
80 // Remove trailing equals padding if it exists.
81 while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
82 outputString.erase(outputString.size() - 1, 1);
83 }
84
85 return std::string(outputString.c_str(), outputString.size());
Adam Stonecea91ce2018-01-22 19:23:28 -080086}
87
Adam Stone32494f52018-02-26 22:53:27 -080088} // anonymous namespace
89
Jeff Tinkera53d6552017-01-20 00:31:46 -080090namespace android {
91
Jeff Tinker6d998b62017-12-18 14:37:43 -080092#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
93
Jeff Tinkera53d6552017-01-20 00:31:46 -080094static inline int getCallingPid() {
95 return IPCThreadState::self()->getCallingPid();
96}
97
98static bool checkPermission(const char* permissionString) {
99 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
100 bool ok = checkCallingPermission(String16(permissionString));
101 if (!ok) ALOGE("Request requires %s", permissionString);
102 return ok;
103}
104
105static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
106 Vector<uint8_t> vector;
107 vector.appendArray(vec.data(), vec.size());
108 return *const_cast<const Vector<uint8_t> *>(&vector);
109}
110
111static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
112 hidl_vec<uint8_t> vec;
113 vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
114 return vec;
115}
116
117static String8 toString8(const hidl_string &string) {
118 return String8(string.c_str());
119}
120
121static hidl_string toHidlString(const String8& string) {
122 return hidl_string(string.string());
123}
124
Jeff Tinker6d998b62017-12-18 14:37:43 -0800125static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
126 switch(level) {
127 case SecurityLevel::SW_SECURE_CRYPTO:
128 return DrmPlugin::kSecurityLevelSwSecureCrypto;
129 case SecurityLevel::SW_SECURE_DECODE:
130 return DrmPlugin::kSecurityLevelSwSecureDecode;
131 case SecurityLevel::HW_SECURE_CRYPTO:
132 return DrmPlugin::kSecurityLevelHwSecureCrypto;
133 case SecurityLevel::HW_SECURE_DECODE:
134 return DrmPlugin::kSecurityLevelHwSecureDecode;
135 case SecurityLevel::HW_SECURE_ALL:
136 return DrmPlugin::kSecurityLevelHwSecureAll;
137 default:
138 return DrmPlugin::kSecurityLevelUnknown;
139 }
140}
141
142static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
143 switch(level) {
144 case HdcpLevel::HDCP_NONE:
145 return DrmPlugin::kHdcpNone;
146 case HdcpLevel::HDCP_V1:
147 return DrmPlugin::kHdcpV1;
148 case HdcpLevel::HDCP_V2:
149 return DrmPlugin::kHdcpV2;
150 case HdcpLevel::HDCP_V2_1:
151 return DrmPlugin::kHdcpV2_1;
152 case HdcpLevel::HDCP_V2_2:
153 return DrmPlugin::kHdcpV2_2;
154 case HdcpLevel::HDCP_NO_OUTPUT:
155 return DrmPlugin::kHdcpNoOutput;
156 default:
157 return DrmPlugin::kHdcpLevelUnknown;
158 }
159}
160
Jeff Tinkera53d6552017-01-20 00:31:46 -0800161
162static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
163 keyedVector) {
164 std::vector<KeyValue> stdKeyedVector;
165 for (size_t i = 0; i < keyedVector.size(); i++) {
166 KeyValue keyValue;
167 keyValue.key = toHidlString(keyedVector.keyAt(i));
168 keyValue.value = toHidlString(keyedVector.valueAt(i));
169 stdKeyedVector.push_back(keyValue);
170 }
171 return ::KeyedVector(stdKeyedVector);
172}
173
174static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
175 hKeyedVector) {
176 KeyedVector<String8, String8> keyedVector;
177 for (size_t i = 0; i < hKeyedVector.size(); i++) {
178 keyedVector.add(toString8(hKeyedVector[i].key),
179 toString8(hKeyedVector[i].value));
180 }
181 return keyedVector;
182}
183
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800184static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
Jeff Tinkera53d6552017-01-20 00:31:46 -0800185 hSecureStops) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800186 List<Vector<uint8_t>> secureStops;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800187 for (size_t i = 0; i < hSecureStops.size(); i++) {
188 secureStops.push_back(toVector(hSecureStops[i].opaqueData));
189 }
190 return secureStops;
191}
192
Jeff Tinker15177d72018-01-25 12:57:55 -0800193static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
194 hSecureStopIds) {
195 List<Vector<uint8_t>> secureStopIds;
196 for (size_t i = 0; i < hSecureStopIds.size(); i++) {
197 secureStopIds.push_back(toVector(hSecureStopIds[i]));
198 }
199 return secureStopIds;
200}
201
Jeff Tinkera53d6552017-01-20 00:31:46 -0800202static status_t toStatusT(Status status) {
203 switch (status) {
204 case Status::OK:
205 return OK;
206 break;
207 case Status::ERROR_DRM_NO_LICENSE:
208 return ERROR_DRM_NO_LICENSE;
209 break;
210 case Status::ERROR_DRM_LICENSE_EXPIRED:
211 return ERROR_DRM_LICENSE_EXPIRED;
212 break;
213 case Status::ERROR_DRM_SESSION_NOT_OPENED:
214 return ERROR_DRM_SESSION_NOT_OPENED;
215 break;
216 case Status::ERROR_DRM_CANNOT_HANDLE:
217 return ERROR_DRM_CANNOT_HANDLE;
218 break;
219 case Status::ERROR_DRM_INVALID_STATE:
220 return ERROR_DRM_TAMPER_DETECTED;
221 break;
222 case Status::BAD_VALUE:
223 return BAD_VALUE;
224 break;
225 case Status::ERROR_DRM_NOT_PROVISIONED:
226 return ERROR_DRM_NOT_PROVISIONED;
227 break;
228 case Status::ERROR_DRM_RESOURCE_BUSY:
229 return ERROR_DRM_RESOURCE_BUSY;
230 break;
231 case Status::ERROR_DRM_DEVICE_REVOKED:
232 return ERROR_DRM_DEVICE_REVOKED;
233 break;
234 case Status::ERROR_DRM_UNKNOWN:
235 default:
236 return ERROR_DRM_UNKNOWN;
237 break;
238 }
239}
240
241
242Mutex DrmHal::mLock;
243
244struct DrmSessionClient : public DrmSessionClientInterface {
245 explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
246
247 virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
248 sp<DrmHal> drm = mDrm.promote();
249 if (drm == NULL) {
250 return true;
251 }
252 status_t err = drm->closeSession(sessionId);
253 if (err != OK) {
254 return false;
255 }
256 drm->sendEvent(EventType::SESSION_RECLAIMED,
257 toHidlVec(sessionId), hidl_vec<uint8_t>());
258 return true;
259 }
260
261protected:
262 virtual ~DrmSessionClient() {}
263
264private:
265 wp<DrmHal> mDrm;
266
267 DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
268};
269
270DrmHal::DrmHal()
271 : mDrmSessionClient(new DrmSessionClient(this)),
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800272 mFactories(makeDrmFactories()),
273 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800274}
275
Jeff Tinker61332812017-05-15 16:53:10 -0700276void DrmHal::closeOpenSessions() {
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800277 Mutex::Autolock autoLock(mLock);
278 auto openSessions = mOpenSessions;
279 for (size_t i = 0; i < openSessions.size(); i++) {
280 mLock.unlock();
281 closeSession(openSessions[i]);
282 mLock.lock();
Jeff Tinker61332812017-05-15 16:53:10 -0700283 }
284 mOpenSessions.clear();
285}
286
Jeff Tinkera53d6552017-01-20 00:31:46 -0800287DrmHal::~DrmHal() {
288 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
289}
290
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800291void DrmHal::cleanup() {
292 closeOpenSessions();
293
294 Mutex::Autolock autoLock(mLock);
295 reportPluginMetrics();
296 reportFrameworkMetrics();
297
298 setListener(NULL);
299 mInitCheck = NO_INIT;
300
301 if (mPlugin != NULL) {
302 if (!mPlugin->setListener(NULL).isOk()) {
303 mInitCheck = DEAD_OBJECT;
304 }
305 }
306 mPlugin.clear();
307 mPluginV1_1.clear();
308}
309
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800310Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
311 Vector<sp<IDrmFactory>> factories;
312
Jeff Tinker593111f2017-05-25 16:00:21 -0700313 auto manager = hardware::defaultServiceManager();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800314
315 if (manager != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000316 manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800317 [&factories](const hidl_vec<hidl_string> &registered) {
318 for (const auto &instance : registered) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000319 auto factory = drm::V1_0::IDrmFactory::getService(instance);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800320 if (factory != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000321 ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str());
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800322 factories.push_back(factory);
Jeff Tinkere307dc42018-02-11 19:53:54 +0000323 }
324 }
325 }
326 );
327 manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
328 [&factories](const hidl_vec<hidl_string> &registered) {
329 for (const auto &instance : registered) {
330 auto factory = drm::V1_1::IDrmFactory::getService(instance);
331 if (factory != NULL) {
332 ALOGD("found drm@1.1 IDrmFactory %s", instance.c_str());
333 factories.push_back(factory);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800334 }
335 }
336 }
337 );
Jeff Tinkera53d6552017-01-20 00:31:46 -0800338 }
Jeff Tinkerc82b9c32017-02-14 11:39:51 -0800339
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800340 if (factories.size() == 0) {
341 // must be in passthrough mode, load the default passthrough service
Jeff Tinkere309b222017-04-05 08:01:28 -0700342 auto passthrough = IDrmFactory::getService();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800343 if (passthrough != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000344 ALOGI("makeDrmFactories: using default passthrough drm instance");
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800345 factories.push_back(passthrough);
346 } else {
347 ALOGE("Failed to find any drm factories");
348 }
349 }
350 return factories;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800351}
352
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800353sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
354 const uint8_t uuid[16], const String8& appPackageName) {
Adam Stone32494f52018-02-26 22:53:27 -0800355 mAppPackageName = appPackageName;
Adam Stonefb679e32018-02-07 10:25:48 -0800356 mMetrics.SetAppPackageName(appPackageName);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800357
358 sp<IDrmPlugin> plugin;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800359 Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
Jeff Tinkera53d6552017-01-20 00:31:46 -0800360 [&](Status status, const sp<IDrmPlugin>& hPlugin) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800361 if (status != Status::OK) {
362 ALOGE("Failed to make drm plugin");
363 return;
364 }
365 plugin = hPlugin;
366 }
367 );
Jeff Tinkerf0e89b02017-08-07 15:58:41 -0700368
369 if (!hResult.isOk()) {
370 ALOGE("createPlugin remote call failed");
371 }
372
Jeff Tinkera53d6552017-01-20 00:31:46 -0800373 return plugin;
374}
375
376status_t DrmHal::initCheck() const {
377 return mInitCheck;
378}
379
380status_t DrmHal::setListener(const sp<IDrmClient>& listener)
381{
382 Mutex::Autolock lock(mEventLock);
383 if (mListener != NULL){
384 IInterface::asBinder(mListener)->unlinkToDeath(this);
385 }
386 if (listener != NULL) {
387 IInterface::asBinder(listener)->linkToDeath(this);
388 }
389 mListener = listener;
390 return NO_ERROR;
391}
392
393Return<void> DrmHal::sendEvent(EventType hEventType,
394 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
Adam Stonecea91ce2018-01-22 19:23:28 -0800395 mMetrics.mEventCounter.Increment(hEventType);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800396
397 mEventLock.lock();
398 sp<IDrmClient> listener = mListener;
399 mEventLock.unlock();
400
401 if (listener != NULL) {
402 Parcel obj;
403 writeByteArray(obj, sessionId);
404 writeByteArray(obj, data);
405
406 Mutex::Autolock lock(mNotifyLock);
407 DrmPlugin::EventType eventType;
408 switch(hEventType) {
409 case EventType::PROVISION_REQUIRED:
410 eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
411 break;
412 case EventType::KEY_NEEDED:
413 eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
414 break;
415 case EventType::KEY_EXPIRED:
416 eventType = DrmPlugin::kDrmPluginEventKeyExpired;
417 break;
418 case EventType::VENDOR_DEFINED:
419 eventType = DrmPlugin::kDrmPluginEventVendorDefined;
420 break;
Rahul Friasb86f4b32017-03-27 15:13:30 -0700421 case EventType::SESSION_RECLAIMED:
422 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
423 break;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800424 default:
425 return Void();
426 }
427 listener->notify(eventType, 0, &obj);
428 }
429 return Void();
430}
431
432Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
433 int64_t expiryTimeInMS) {
434
435 mEventLock.lock();
436 sp<IDrmClient> listener = mListener;
437 mEventLock.unlock();
438
439 if (listener != NULL) {
440 Parcel obj;
441 writeByteArray(obj, sessionId);
442 obj.writeInt64(expiryTimeInMS);
443
444 Mutex::Autolock lock(mNotifyLock);
445 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
446 }
447 return Void();
448}
449
450Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
451 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
452
453 mEventLock.lock();
454 sp<IDrmClient> listener = mListener;
455 mEventLock.unlock();
456
457 if (listener != NULL) {
458 Parcel obj;
459 writeByteArray(obj, sessionId);
460
461 size_t nKeys = keyStatusList.size();
462 obj.writeInt32(nKeys);
463 for (size_t i = 0; i < nKeys; ++i) {
464 const KeyStatus &keyStatus = keyStatusList[i];
465 writeByteArray(obj, keyStatus.keyId);
466 uint32_t type;
467 switch(keyStatus.type) {
468 case KeyStatusType::USABLE:
469 type = DrmPlugin::kKeyStatusType_Usable;
470 break;
471 case KeyStatusType::EXPIRED:
472 type = DrmPlugin::kKeyStatusType_Expired;
473 break;
474 case KeyStatusType::OUTPUTNOTALLOWED:
475 type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
476 break;
477 case KeyStatusType::STATUSPENDING:
478 type = DrmPlugin::kKeyStatusType_StatusPending;
479 break;
480 case KeyStatusType::INTERNALERROR:
481 default:
482 type = DrmPlugin::kKeyStatusType_InternalError;
483 break;
484 }
485 obj.writeInt32(type);
Adam Stonecea91ce2018-01-22 19:23:28 -0800486 mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800487 }
488 obj.writeInt32(hasNewUsableKey);
489
490 Mutex::Autolock lock(mNotifyLock);
491 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
Adam Stonecea91ce2018-01-22 19:23:28 -0800492 } else {
493 // There's no listener. But we still want to count the key change
494 // events.
495 size_t nKeys = keyStatusList.size();
496 for (size_t i = 0; i < nKeys; i++) {
497 mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
498 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800499 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800500
Jeff Tinkera53d6552017-01-20 00:31:46 -0800501 return Void();
502}
503
504bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
505 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800506
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800507 for (size_t i = 0; i < mFactories.size(); i++) {
508 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
509 if (mimeType != "") {
510 if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
511 return true;
512 }
513 } else {
514 return true;
515 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800516 }
517 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800518 return false;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800519}
520
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800521status_t DrmHal::createPlugin(const uint8_t uuid[16],
522 const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800523 Mutex::Autolock autoLock(mLock);
524
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800525 for (size_t i = 0; i < mFactories.size(); i++) {
526 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
527 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
Edwin Wong5641aa22018-01-30 17:52:21 -0800528 if (mPlugin != NULL) {
529 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
530 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800531 }
532 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800533
534 if (mPlugin == NULL) {
535 mInitCheck = ERROR_UNSUPPORTED;
536 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700537 if (!mPlugin->setListener(this).isOk()) {
538 mInitCheck = DEAD_OBJECT;
539 } else {
540 mInitCheck = OK;
541 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800542 }
543
544 return mInitCheck;
545}
546
547status_t DrmHal::destroyPlugin() {
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800548 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800549 return OK;
550}
551
Jeff Tinker41d279a2018-02-11 19:52:08 +0000552status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
553 Vector<uint8_t> &sessionId) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800554 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800555 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800556
Jeff Tinker41d279a2018-02-11 19:52:08 +0000557 SecurityLevel hSecurityLevel;
558 bool setSecurityLevel = true;
Tobias Thierer5f5e43f2018-02-11 15:00:57 +0000559
Jeff Tinker41d279a2018-02-11 19:52:08 +0000560 switch(level) {
561 case DrmPlugin::kSecurityLevelSwSecureCrypto:
562 hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
563 break;
564 case DrmPlugin::kSecurityLevelSwSecureDecode:
565 hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
566 break;
567 case DrmPlugin::kSecurityLevelHwSecureCrypto:
568 hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
569 break;
570 case DrmPlugin::kSecurityLevelHwSecureDecode:
571 hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
572 break;
573 case DrmPlugin::kSecurityLevelHwSecureAll:
574 hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
575 break;
576 case DrmPlugin::kSecurityLevelMax:
577 setSecurityLevel = false;
578 break;
579 default:
580 return ERROR_DRM_CANNOT_HANDLE;
581 }
582
583 status_t err = UNKNOWN_ERROR;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800584 bool retry = true;
585 do {
586 hidl_vec<uint8_t> hSessionId;
587
Jeff Tinker41d279a2018-02-11 19:52:08 +0000588 Return<void> hResult;
589 if (mPluginV1_1 == NULL || !setSecurityLevel) {
590 hResult = mPlugin->openSession(
591 [&](Status status,const hidl_vec<uint8_t>& id) {
592 if (status == Status::OK) {
593 sessionId = toVector(id);
594 }
595 err = toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800596 }
Jeff Tinker41d279a2018-02-11 19:52:08 +0000597 );
598 } else {
599 hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
600 [&](Status status, const hidl_vec<uint8_t>& id) {
601 if (status == Status::OK) {
602 sessionId = toVector(id);
603 }
604 err = toStatusT(status);
605 }
606 );
607 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800608
609 if (!hResult.isOk()) {
610 err = DEAD_OBJECT;
611 }
612
613 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
614 mLock.unlock();
615 // reclaimSession may call back to closeSession, since mLock is
616 // shared between Drm instances, we should unlock here to avoid
617 // deadlock.
618 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
619 mLock.lock();
620 } else {
621 retry = false;
622 }
623 } while (retry);
624
625 if (err == OK) {
626 DrmSessionManager::Instance()->addSession(getCallingPid(),
627 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700628 mOpenSessions.push(sessionId);
Adam Stone568b3c42018-01-31 12:57:16 -0800629 mMetrics.SetSessionStart(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800630 }
Adam Stoneaaf87dd2018-01-08 11:55:06 -0800631
Adam Stonef0e618d2018-01-17 19:20:41 -0800632 mMetrics.mOpenSessionCounter.Increment(err);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800633 return err;
634}
635
636status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
637 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800638 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800639
Jeff Tinker319d5f42017-07-26 15:44:33 -0700640 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
641 if (status.isOk()) {
642 if (status == Status::OK) {
643 DrmSessionManager::Instance()->removeSession(sessionId);
644 for (size_t i = 0; i < mOpenSessions.size(); i++) {
645 if (mOpenSessions[i] == sessionId) {
646 mOpenSessions.removeAt(i);
647 break;
648 }
Jeff Tinker61332812017-05-15 16:53:10 -0700649 }
650 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800651 status_t response = toStatusT(status);
Adam Stone568b3c42018-01-31 12:57:16 -0800652 mMetrics.SetSessionEnd(sessionId);
Adam Stonecea91ce2018-01-22 19:23:28 -0800653 mMetrics.mCloseSessionCounter.Increment(response);
654 return response;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800655 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800656 mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
Jeff Tinker319d5f42017-07-26 15:44:33 -0700657 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800658}
659
660status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
661 Vector<uint8_t> const &initData, String8 const &mimeType,
662 DrmPlugin::KeyType keyType, KeyedVector<String8,
663 String8> const &optionalParameters, Vector<uint8_t> &request,
664 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
665 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800666 INIT_CHECK();
Adam Stonefb679e32018-02-07 10:25:48 -0800667 EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800668
669 DrmSessionManager::Instance()->useSession(sessionId);
670
671 KeyType hKeyType;
672 if (keyType == DrmPlugin::kKeyType_Streaming) {
673 hKeyType = KeyType::STREAMING;
674 } else if (keyType == DrmPlugin::kKeyType_Offline) {
675 hKeyType = KeyType::OFFLINE;
676 } else if (keyType == DrmPlugin::kKeyType_Release) {
677 hKeyType = KeyType::RELEASE;
678 } else {
Adam Stonef0e618d2018-01-17 19:20:41 -0800679 keyRequestTimer.SetAttribute(BAD_VALUE);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800680 return BAD_VALUE;
681 }
682
683 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
684
685 status_t err = UNKNOWN_ERROR;
686
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800687 if (mPluginV1_1 != NULL) {
688 Return<void> hResult =
689 mPluginV1_1->getKeyRequest_1_1(
690 toHidlVec(sessionId), toHidlVec(initData),
691 toHidlString(mimeType), hKeyType, hOptionalParameters,
692 [&](Status status, const hidl_vec<uint8_t>& hRequest,
693 drm::V1_1::KeyRequestType hKeyRequestType,
694 const hidl_string& hDefaultUrl) {
695
696 if (status == Status::OK) {
697 request = toVector(hRequest);
698 defaultUrl = toString8(hDefaultUrl);
699
700 switch (hKeyRequestType) {
701 case drm::V1_1::KeyRequestType::INITIAL:
702 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
703 break;
704 case drm::V1_1::KeyRequestType::RENEWAL:
705 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
706 break;
707 case drm::V1_1::KeyRequestType::RELEASE:
708 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
709 break;
710 case drm::V1_1::KeyRequestType::NONE:
711 *keyRequestType = DrmPlugin::kKeyRequestType_None;
712 break;
713 case drm::V1_1::KeyRequestType::UPDATE:
714 *keyRequestType = DrmPlugin::kKeyRequestType_Update;
715 break;
716 default:
717 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
718 break;
719 }
720 err = toStatusT(status);
721 }
722 });
723 return hResult.isOk() ? err : DEAD_OBJECT;
724 }
725
Jeff Tinkera53d6552017-01-20 00:31:46 -0800726 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
727 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
728 [&](Status status, const hidl_vec<uint8_t>& hRequest,
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800729 drm::V1_0::KeyRequestType hKeyRequestType,
730 const hidl_string& hDefaultUrl) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800731
732 if (status == Status::OK) {
733 request = toVector(hRequest);
734 defaultUrl = toString8(hDefaultUrl);
735
736 switch (hKeyRequestType) {
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800737 case drm::V1_0::KeyRequestType::INITIAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800738 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
739 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800740 case drm::V1_0::KeyRequestType::RENEWAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800741 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
742 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800743 case drm::V1_0::KeyRequestType::RELEASE:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800744 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
745 break;
746 default:
747 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
748 break;
749 }
750 err = toStatusT(status);
751 }
752 });
753
Adam Stonef0e618d2018-01-17 19:20:41 -0800754 err = hResult.isOk() ? err : DEAD_OBJECT;
755 keyRequestTimer.SetAttribute(err);
756 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800757}
758
759status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
760 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
761 Mutex::Autolock autoLock(mLock);
Adam Stonefb679e32018-02-07 10:25:48 -0800762 EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800763
Jeff Tinker6d998b62017-12-18 14:37:43 -0800764 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800765
766 DrmSessionManager::Instance()->useSession(sessionId);
767
768 status_t err = UNKNOWN_ERROR;
769
770 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
771 toHidlVec(response),
772 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
773 if (status == Status::OK) {
774 keySetId = toVector(hKeySetId);
775 }
776 err = toStatusT(status);
777 }
778 );
Adam Stonecea91ce2018-01-22 19:23:28 -0800779 err = hResult.isOk() ? err : DEAD_OBJECT;
780 keyResponseTimer.SetAttribute(err);
781 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800782}
783
784status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
785 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800786 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800787
Jeff Tinker58ad4752018-02-16 16:51:59 -0800788 Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
789 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800790}
791
792status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
793 Vector<uint8_t> const &keySetId) {
794 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800795 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800796
797 DrmSessionManager::Instance()->useSession(sessionId);
798
Jeff Tinker58ad4752018-02-16 16:51:59 -0800799 Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId),
800 toHidlVec(keySetId));
801 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800802}
803
804status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
805 KeyedVector<String8, String8> &infoMap) const {
806 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800807 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800808
809 DrmSessionManager::Instance()->useSession(sessionId);
810
811 ::KeyedVector hInfoMap;
812
813 status_t err = UNKNOWN_ERROR;
814
815 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
816 [&](Status status, const hidl_vec<KeyValue>& map) {
817 if (status == Status::OK) {
818 infoMap = toKeyedVector(map);
819 }
820 err = toStatusT(status);
821 }
822 );
823
824 return hResult.isOk() ? err : DEAD_OBJECT;
825}
826
827status_t DrmHal::getProvisionRequest(String8 const &certType,
828 String8 const &certAuthority, Vector<uint8_t> &request,
829 String8 &defaultUrl) {
830 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800831 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800832
833 status_t err = UNKNOWN_ERROR;
834
835 Return<void> hResult = mPlugin->getProvisionRequest(
836 toHidlString(certType), toHidlString(certAuthority),
837 [&](Status status, const hidl_vec<uint8_t>& hRequest,
838 const hidl_string& hDefaultUrl) {
839 if (status == Status::OK) {
840 request = toVector(hRequest);
841 defaultUrl = toString8(hDefaultUrl);
842 }
843 err = toStatusT(status);
844 }
845 );
846
Adam Stonecea91ce2018-01-22 19:23:28 -0800847 err = hResult.isOk() ? err : DEAD_OBJECT;
848 mMetrics.mGetProvisionRequestCounter.Increment(err);
849 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800850}
851
852status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800853 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800854 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800855 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800856
857 status_t err = UNKNOWN_ERROR;
858
859 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
860 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
861 const hidl_vec<uint8_t>& hWrappedKey) {
862 if (status == Status::OK) {
863 certificate = toVector(hCertificate);
864 wrappedKey = toVector(hWrappedKey);
865 }
866 err = toStatusT(status);
867 }
868 );
869
Adam Stonecea91ce2018-01-22 19:23:28 -0800870 err = hResult.isOk() ? err : DEAD_OBJECT;
871 mMetrics.mProvideProvisionResponseCounter.Increment(err);
872 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800873}
874
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800875status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800876 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800877 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800878
879 status_t err = UNKNOWN_ERROR;
880
881 Return<void> hResult = mPlugin->getSecureStops(
882 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
883 if (status == Status::OK) {
884 secureStops = toSecureStops(hSecureStops);
885 }
886 err = toStatusT(status);
887 }
888 );
889
890 return hResult.isOk() ? err : DEAD_OBJECT;
891}
892
893
Jeff Tinker15177d72018-01-25 12:57:55 -0800894status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
895 Mutex::Autolock autoLock(mLock);
896
897 if (mInitCheck != OK) {
898 return mInitCheck;
899 }
900
901 if (mPluginV1_1 == NULL) {
902 return ERROR_DRM_CANNOT_HANDLE;
903 }
904
905 status_t err = UNKNOWN_ERROR;
906
907 Return<void> hResult = mPluginV1_1->getSecureStopIds(
908 [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
909 if (status == Status::OK) {
910 secureStopIds = toSecureStopIds(hSecureStopIds);
911 }
912 err = toStatusT(status);
913 }
914 );
915
916 return hResult.isOk() ? err : DEAD_OBJECT;
917}
918
919
Jeff Tinkera53d6552017-01-20 00:31:46 -0800920status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
921 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800922 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800923
924 status_t err = UNKNOWN_ERROR;
925
926 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
927 [&](Status status, const SecureStop& hSecureStop) {
928 if (status == Status::OK) {
929 secureStop = toVector(hSecureStop.opaqueData);
930 }
931 err = toStatusT(status);
932 }
933 );
934
935 return hResult.isOk() ? err : DEAD_OBJECT;
936}
937
938status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
939 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800940 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800941
Jeff Tinker58ad4752018-02-16 16:51:59 -0800942 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -0800943 if (mPluginV1_1 != NULL) {
944 SecureStopRelease secureStopRelease;
945 secureStopRelease.opaqueData = toHidlVec(ssRelease);
Jeff Tinker58ad4752018-02-16 16:51:59 -0800946 status = mPluginV1_1->releaseSecureStops(secureStopRelease);
947 } else {
948 status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
Jeff Tinker15177d72018-01-25 12:57:55 -0800949 }
Jeff Tinker58ad4752018-02-16 16:51:59 -0800950 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800951}
952
Jeff Tinker15177d72018-01-25 12:57:55 -0800953status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
954 Mutex::Autolock autoLock(mLock);
955
956 if (mInitCheck != OK) {
957 return mInitCheck;
958 }
959
960 if (mPluginV1_1 == NULL) {
961 return ERROR_DRM_CANNOT_HANDLE;
962 }
963
Jeff Tinker58ad4752018-02-16 16:51:59 -0800964 Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
965 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinker15177d72018-01-25 12:57:55 -0800966}
967
968status_t DrmHal::removeAllSecureStops() {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800969 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800970 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800971
Jeff Tinker58ad4752018-02-16 16:51:59 -0800972 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -0800973 if (mPluginV1_1 != NULL) {
Jeff Tinker58ad4752018-02-16 16:51:59 -0800974 status = mPluginV1_1->removeAllSecureStops();
975 } else {
976 status = mPlugin->releaseAllSecureStops();
Jeff Tinker15177d72018-01-25 12:57:55 -0800977 }
Jeff Tinker58ad4752018-02-16 16:51:59 -0800978 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800979}
980
Jeff Tinker6d998b62017-12-18 14:37:43 -0800981status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
982 DrmPlugin::HdcpLevel *max) const {
983 Mutex::Autolock autoLock(mLock);
984 INIT_CHECK();
985
986 if (connected == NULL || max == NULL) {
987 return BAD_VALUE;
988 }
989 status_t err = UNKNOWN_ERROR;
990
991 if (mPluginV1_1 == NULL) {
992 return ERROR_DRM_CANNOT_HANDLE;
993 }
994
995 *connected = DrmPlugin::kHdcpLevelUnknown;
996 *max = DrmPlugin::kHdcpLevelUnknown;
997
998 Return<void> hResult = mPluginV1_1->getHdcpLevels(
999 [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
1000 if (status == Status::OK) {
1001 *connected = toHdcpLevel(hConnected);
1002 *max = toHdcpLevel(hMax);
1003 }
1004 err = toStatusT(status);
1005 }
1006 );
1007
1008 return hResult.isOk() ? err : DEAD_OBJECT;
1009}
1010
1011status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
1012 Mutex::Autolock autoLock(mLock);
1013 INIT_CHECK();
1014
1015 if (open == NULL || max == NULL) {
1016 return BAD_VALUE;
1017 }
1018 status_t err = UNKNOWN_ERROR;
1019
1020 *open = 0;
1021 *max = 0;
1022
1023 if (mPluginV1_1 == NULL) {
1024 return ERROR_DRM_CANNOT_HANDLE;
1025 }
1026
1027 Return<void> hResult = mPluginV1_1->getNumberOfSessions(
1028 [&](Status status, uint32_t hOpen, uint32_t hMax) {
1029 if (status == Status::OK) {
1030 *open = hOpen;
1031 *max = hMax;
1032 }
1033 err = toStatusT(status);
1034 }
1035 );
1036
1037 return hResult.isOk() ? err : DEAD_OBJECT;
1038}
1039
1040status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
1041 DrmPlugin::SecurityLevel *level) const {
1042 Mutex::Autolock autoLock(mLock);
1043 INIT_CHECK();
1044
1045 if (level == NULL) {
1046 return BAD_VALUE;
1047 }
1048 status_t err = UNKNOWN_ERROR;
1049
1050 if (mPluginV1_1 == NULL) {
1051 return ERROR_DRM_CANNOT_HANDLE;
1052 }
1053
1054 *level = DrmPlugin::kSecurityLevelUnknown;
1055
1056 Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
1057 [&](Status status, SecurityLevel hLevel) {
1058 if (status == Status::OK) {
1059 *level = toSecurityLevel(hLevel);
1060 }
1061 err = toStatusT(status);
1062 }
1063 );
1064
1065 return hResult.isOk() ? err : DEAD_OBJECT;
1066}
1067
Jeff Tinkera53d6552017-01-20 00:31:46 -08001068status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
1069 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001070 return getPropertyStringInternal(name, value);
1071}
1072
1073status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
1074 // This function is internal to the class and should only be called while
1075 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001076 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001077
1078 status_t err = UNKNOWN_ERROR;
1079
1080 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
1081 [&](Status status, const hidl_string& hValue) {
1082 if (status == Status::OK) {
1083 value = toString8(hValue);
1084 }
1085 err = toStatusT(status);
1086 }
1087 );
1088
1089 return hResult.isOk() ? err : DEAD_OBJECT;
1090}
1091
1092status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
1093 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001094 return getPropertyByteArrayInternal(name, value);
1095}
1096
1097status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
1098 // This function is internal to the class and should only be called while
1099 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001100 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001101
1102 status_t err = UNKNOWN_ERROR;
1103
1104 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
1105 [&](Status status, const hidl_vec<uint8_t>& hValue) {
1106 if (status == Status::OK) {
1107 value = toVector(hValue);
1108 }
1109 err = toStatusT(status);
1110 }
1111 );
1112
Adam Stonecea91ce2018-01-22 19:23:28 -08001113 err = hResult.isOk() ? err : DEAD_OBJECT;
1114 if (name == kPropertyDeviceUniqueId) {
1115 mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
1116 }
1117 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001118}
1119
1120status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
1121 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001122 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001123
Jeff Tinker58ad4752018-02-16 16:51:59 -08001124 Return<Status> status = mPlugin->setPropertyString(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001125 toHidlString(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001126 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001127}
1128
1129status_t DrmHal::setPropertyByteArray(String8 const &name,
1130 Vector<uint8_t> const &value ) const {
1131 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001132 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001133
Jeff Tinker58ad4752018-02-16 16:51:59 -08001134 Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001135 toHidlVec(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001136 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001137}
1138
Adam Stone28f27c32018-02-05 15:07:48 -08001139status_t DrmHal::getMetrics(PersistableBundle* metrics) {
1140 if (metrics == nullptr) {
1141 return UNEXPECTED_NULL;
1142 }
1143 mMetrics.Export(metrics);
1144
1145 // Append vendor metrics if they are supported.
1146 if (mPluginV1_1 != NULL) {
1147 String8 vendor;
1148 String8 description;
1149 if (getPropertyStringInternal(String8("vendor"), vendor) != OK
1150 || vendor.isEmpty()) {
1151 ALOGE("Get vendor failed or is empty");
1152 vendor = "NONE";
1153 }
1154 if (getPropertyStringInternal(String8("description"), description) != OK
1155 || description.isEmpty()) {
1156 ALOGE("Get description failed or is empty.");
1157 description = "NONE";
1158 }
1159 vendor += ".";
1160 vendor += description;
1161
1162 hidl_vec<DrmMetricGroup> pluginMetrics;
1163 status_t err = UNKNOWN_ERROR;
1164
1165 Return<void> status = mPluginV1_1->getMetrics(
1166 [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
1167 if (status != Status::OK) {
1168 ALOGV("Error getting plugin metrics: %d", status);
1169 } else {
1170 PersistableBundle pluginBundle;
1171 if (MediaDrmMetrics::HidlMetricsToBundle(
1172 pluginMetrics, &pluginBundle) == OK) {
1173 metrics->putPersistableBundle(String16(vendor), pluginBundle);
1174 }
1175 }
1176 err = toStatusT(status);
1177 });
1178 return status.isOk() ? err : DEAD_OBJECT;
Adam Stonef0e618d2018-01-17 19:20:41 -08001179 }
1180
Adam Stoneab394d12017-12-22 12:34:20 -08001181 return OK;
1182}
Jeff Tinkera53d6552017-01-20 00:31:46 -08001183
1184status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
1185 String8 const &algorithm) {
1186 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001187 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001188
1189 DrmSessionManager::Instance()->useSession(sessionId);
1190
Jeff Tinkere6412942018-04-30 17:35:16 -07001191 Return<Status> status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001192 toHidlString(algorithm));
Jeff Tinkere6412942018-04-30 17:35:16 -07001193 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001194}
1195
1196status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
1197 String8 const &algorithm) {
1198 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001199 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001200
1201 DrmSessionManager::Instance()->useSession(sessionId);
1202
Jeff Tinkere6412942018-04-30 17:35:16 -07001203 Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001204 toHidlString(algorithm));
Jeff Tinkere6412942018-04-30 17:35:16 -07001205 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001206}
1207
1208status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001209 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1210 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001211 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001212 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001213
1214 DrmSessionManager::Instance()->useSession(sessionId);
1215
1216 status_t err = UNKNOWN_ERROR;
1217
1218 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
1219 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1220 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1221 if (status == Status::OK) {
1222 output = toVector(hOutput);
1223 }
1224 err = toStatusT(status);
1225 }
1226 );
1227
1228 return hResult.isOk() ? err : DEAD_OBJECT;
1229}
1230
1231status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001232 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1233 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001234 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001235 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001236
1237 DrmSessionManager::Instance()->useSession(sessionId);
1238
1239 status_t err = UNKNOWN_ERROR;
1240
1241 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
1242 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1243 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1244 if (status == Status::OK) {
1245 output = toVector(hOutput);
1246 }
1247 err = toStatusT(status);
1248 }
1249 );
1250
1251 return hResult.isOk() ? err : DEAD_OBJECT;
1252}
1253
1254status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001255 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1256 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001257 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001258 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001259
1260 DrmSessionManager::Instance()->useSession(sessionId);
1261
1262 status_t err = UNKNOWN_ERROR;
1263
1264 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
1265 toHidlVec(keyId), toHidlVec(message),
1266 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1267 if (status == Status::OK) {
1268 signature = toVector(hSignature);
1269 }
1270 err = toStatusT(status);
1271 }
1272 );
1273
1274 return hResult.isOk() ? err : DEAD_OBJECT;
1275}
1276
1277status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001278 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1279 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001280 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001281 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001282
1283 DrmSessionManager::Instance()->useSession(sessionId);
1284
1285 status_t err = UNKNOWN_ERROR;
1286
1287 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
1288 toHidlVec(message), toHidlVec(signature),
1289 [&](Status status, bool hMatch) {
1290 if (status == Status::OK) {
1291 match = hMatch;
1292 } else {
1293 match = false;
1294 }
1295 err = toStatusT(status);
1296 }
1297 );
1298
1299 return hResult.isOk() ? err : DEAD_OBJECT;
1300}
1301
1302status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001303 String8 const &algorithm, Vector<uint8_t> const &message,
1304 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001305 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001306 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001307
1308 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
1309 return -EPERM;
1310 }
1311
1312 DrmSessionManager::Instance()->useSession(sessionId);
1313
1314 status_t err = UNKNOWN_ERROR;
1315
1316 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1317 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1318 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1319 if (status == Status::OK) {
1320 signature = toVector(hSignature);
1321 }
1322 err = toStatusT(status);
1323 }
1324 );
1325
1326 return hResult.isOk() ? err : DEAD_OBJECT;
1327}
1328
1329void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1330{
Jeff Tinker7dfe28f2018-02-15 12:17:40 -08001331 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001332}
1333
1334void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1335{
1336 if (vec.size()) {
1337 obj.writeInt32(vec.size());
1338 obj.write(vec.data(), vec.size());
1339 } else {
1340 obj.writeInt32(0);
1341 }
1342}
1343
Adam Stonefb679e32018-02-07 10:25:48 -08001344void DrmHal::reportFrameworkMetrics() const
1345{
1346 MediaAnalyticsItem item("mediadrm");
1347 item.generateSessionID();
1348 item.setPkgName(mMetrics.GetAppPackageName().c_str());
1349 String8 vendor;
1350 String8 description;
1351 status_t result = getPropertyStringInternal(String8("vendor"), vendor);
1352 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001353 ALOGE("Failed to get vendor from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001354 } else {
1355 item.setCString("vendor", vendor.c_str());
1356 }
1357 result = getPropertyStringInternal(String8("description"), description);
1358 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001359 ALOGE("Failed to get description from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001360 } else {
1361 item.setCString("description", description.c_str());
1362 }
Adam Stoneab394d12017-12-22 12:34:20 -08001363
Adam Stonefb679e32018-02-07 10:25:48 -08001364 std::string serializedMetrics;
1365 result = mMetrics.GetSerializedMetrics(&serializedMetrics);
1366 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001367 ALOGE("Failed to serialize framework metrics: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001368 }
Adam Stone32494f52018-02-26 22:53:27 -08001369 std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
1370 serializedMetrics.size());
1371 if (!b64EncodedMetrics.empty()) {
1372 item.setCString("serialized_metrics", b64EncodedMetrics.c_str());
Adam Stonefb679e32018-02-07 10:25:48 -08001373 }
1374 if (!item.selfrecord()) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001375 ALOGE("Failed to self record framework metrics");
Adam Stonefb679e32018-02-07 10:25:48 -08001376 }
1377}
1378
1379void DrmHal::reportPluginMetrics() const
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001380{
Adam Stone32494f52018-02-26 22:53:27 -08001381 Vector<uint8_t> metricsVector;
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001382 String8 vendor;
1383 String8 description;
1384 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1385 getPropertyStringInternal(String8("description"), description) == OK &&
Adam Stone32494f52018-02-26 22:53:27 -08001386 getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
1387 std::string metricsString = toBase64StringNoPad(metricsVector.array(),
1388 metricsVector.size());
1389 status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
1390 description, mAppPackageName);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001391 if (res != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001392 ALOGE("Metrics were retrieved but could not be reported: %d", res);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001393 }
1394 }
1395}
1396
Jeff Tinkera53d6552017-01-20 00:31:46 -08001397} // namespace android