blob: 4e8ad5293ddbfe04e53f6554b3743b3aae31e016 [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) {
71 if (size == 0) {
72 return "";
73 }
74 CHECK(sizeof(data[0] == 1));
75
76 android::AString outputString;
77 encodeBase64(data, size, &outputString);
78 // Remove trailing equals padding if it exists.
79 while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
80 outputString.erase(outputString.size() - 1, 1);
81 }
82
83 return std::string(outputString.c_str(), outputString.size());
Adam Stonecea91ce2018-01-22 19:23:28 -080084}
85
Adam Stone32494f52018-02-26 22:53:27 -080086} // anonymous namespace
87
Jeff Tinkera53d6552017-01-20 00:31:46 -080088namespace android {
89
Jeff Tinker6d998b62017-12-18 14:37:43 -080090#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
91
Jeff Tinkera53d6552017-01-20 00:31:46 -080092static inline int getCallingPid() {
93 return IPCThreadState::self()->getCallingPid();
94}
95
96static bool checkPermission(const char* permissionString) {
97 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
98 bool ok = checkCallingPermission(String16(permissionString));
99 if (!ok) ALOGE("Request requires %s", permissionString);
100 return ok;
101}
102
103static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
104 Vector<uint8_t> vector;
105 vector.appendArray(vec.data(), vec.size());
106 return *const_cast<const Vector<uint8_t> *>(&vector);
107}
108
109static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
110 hidl_vec<uint8_t> vec;
111 vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
112 return vec;
113}
114
115static String8 toString8(const hidl_string &string) {
116 return String8(string.c_str());
117}
118
119static hidl_string toHidlString(const String8& string) {
120 return hidl_string(string.string());
121}
122
Jeff Tinker6d998b62017-12-18 14:37:43 -0800123static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
124 switch(level) {
125 case SecurityLevel::SW_SECURE_CRYPTO:
126 return DrmPlugin::kSecurityLevelSwSecureCrypto;
127 case SecurityLevel::SW_SECURE_DECODE:
128 return DrmPlugin::kSecurityLevelSwSecureDecode;
129 case SecurityLevel::HW_SECURE_CRYPTO:
130 return DrmPlugin::kSecurityLevelHwSecureCrypto;
131 case SecurityLevel::HW_SECURE_DECODE:
132 return DrmPlugin::kSecurityLevelHwSecureDecode;
133 case SecurityLevel::HW_SECURE_ALL:
134 return DrmPlugin::kSecurityLevelHwSecureAll;
135 default:
136 return DrmPlugin::kSecurityLevelUnknown;
137 }
138}
139
140static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
141 switch(level) {
142 case HdcpLevel::HDCP_NONE:
143 return DrmPlugin::kHdcpNone;
144 case HdcpLevel::HDCP_V1:
145 return DrmPlugin::kHdcpV1;
146 case HdcpLevel::HDCP_V2:
147 return DrmPlugin::kHdcpV2;
148 case HdcpLevel::HDCP_V2_1:
149 return DrmPlugin::kHdcpV2_1;
150 case HdcpLevel::HDCP_V2_2:
151 return DrmPlugin::kHdcpV2_2;
152 case HdcpLevel::HDCP_NO_OUTPUT:
153 return DrmPlugin::kHdcpNoOutput;
154 default:
155 return DrmPlugin::kHdcpLevelUnknown;
156 }
157}
158
Jeff Tinkera53d6552017-01-20 00:31:46 -0800159
160static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
161 keyedVector) {
162 std::vector<KeyValue> stdKeyedVector;
163 for (size_t i = 0; i < keyedVector.size(); i++) {
164 KeyValue keyValue;
165 keyValue.key = toHidlString(keyedVector.keyAt(i));
166 keyValue.value = toHidlString(keyedVector.valueAt(i));
167 stdKeyedVector.push_back(keyValue);
168 }
169 return ::KeyedVector(stdKeyedVector);
170}
171
172static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
173 hKeyedVector) {
174 KeyedVector<String8, String8> keyedVector;
175 for (size_t i = 0; i < hKeyedVector.size(); i++) {
176 keyedVector.add(toString8(hKeyedVector[i].key),
177 toString8(hKeyedVector[i].value));
178 }
179 return keyedVector;
180}
181
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800182static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
Jeff Tinkera53d6552017-01-20 00:31:46 -0800183 hSecureStops) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800184 List<Vector<uint8_t>> secureStops;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800185 for (size_t i = 0; i < hSecureStops.size(); i++) {
186 secureStops.push_back(toVector(hSecureStops[i].opaqueData));
187 }
188 return secureStops;
189}
190
Jeff Tinker15177d72018-01-25 12:57:55 -0800191static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
192 hSecureStopIds) {
193 List<Vector<uint8_t>> secureStopIds;
194 for (size_t i = 0; i < hSecureStopIds.size(); i++) {
195 secureStopIds.push_back(toVector(hSecureStopIds[i]));
196 }
197 return secureStopIds;
198}
199
Jeff Tinkera53d6552017-01-20 00:31:46 -0800200static status_t toStatusT(Status status) {
201 switch (status) {
202 case Status::OK:
203 return OK;
204 break;
205 case Status::ERROR_DRM_NO_LICENSE:
206 return ERROR_DRM_NO_LICENSE;
207 break;
208 case Status::ERROR_DRM_LICENSE_EXPIRED:
209 return ERROR_DRM_LICENSE_EXPIRED;
210 break;
211 case Status::ERROR_DRM_SESSION_NOT_OPENED:
212 return ERROR_DRM_SESSION_NOT_OPENED;
213 break;
214 case Status::ERROR_DRM_CANNOT_HANDLE:
215 return ERROR_DRM_CANNOT_HANDLE;
216 break;
217 case Status::ERROR_DRM_INVALID_STATE:
218 return ERROR_DRM_TAMPER_DETECTED;
219 break;
220 case Status::BAD_VALUE:
221 return BAD_VALUE;
222 break;
223 case Status::ERROR_DRM_NOT_PROVISIONED:
224 return ERROR_DRM_NOT_PROVISIONED;
225 break;
226 case Status::ERROR_DRM_RESOURCE_BUSY:
227 return ERROR_DRM_RESOURCE_BUSY;
228 break;
229 case Status::ERROR_DRM_DEVICE_REVOKED:
230 return ERROR_DRM_DEVICE_REVOKED;
231 break;
232 case Status::ERROR_DRM_UNKNOWN:
233 default:
234 return ERROR_DRM_UNKNOWN;
235 break;
236 }
237}
238
239
240Mutex DrmHal::mLock;
241
242struct DrmSessionClient : public DrmSessionClientInterface {
243 explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
244
245 virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
246 sp<DrmHal> drm = mDrm.promote();
247 if (drm == NULL) {
248 return true;
249 }
250 status_t err = drm->closeSession(sessionId);
251 if (err != OK) {
252 return false;
253 }
254 drm->sendEvent(EventType::SESSION_RECLAIMED,
255 toHidlVec(sessionId), hidl_vec<uint8_t>());
256 return true;
257 }
258
259protected:
260 virtual ~DrmSessionClient() {}
261
262private:
263 wp<DrmHal> mDrm;
264
265 DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
266};
267
268DrmHal::DrmHal()
269 : mDrmSessionClient(new DrmSessionClient(this)),
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800270 mFactories(makeDrmFactories()),
271 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800272}
273
Jeff Tinker61332812017-05-15 16:53:10 -0700274void DrmHal::closeOpenSessions() {
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800275 Mutex::Autolock autoLock(mLock);
276 auto openSessions = mOpenSessions;
277 for (size_t i = 0; i < openSessions.size(); i++) {
278 mLock.unlock();
279 closeSession(openSessions[i]);
280 mLock.lock();
Jeff Tinker61332812017-05-15 16:53:10 -0700281 }
282 mOpenSessions.clear();
283}
284
Jeff Tinkera53d6552017-01-20 00:31:46 -0800285DrmHal::~DrmHal() {
286 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
287}
288
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800289void DrmHal::cleanup() {
290 closeOpenSessions();
291
292 Mutex::Autolock autoLock(mLock);
293 reportPluginMetrics();
294 reportFrameworkMetrics();
295
296 setListener(NULL);
297 mInitCheck = NO_INIT;
298
299 if (mPlugin != NULL) {
300 if (!mPlugin->setListener(NULL).isOk()) {
301 mInitCheck = DEAD_OBJECT;
302 }
303 }
304 mPlugin.clear();
305 mPluginV1_1.clear();
306}
307
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800308Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
309 Vector<sp<IDrmFactory>> factories;
310
Jeff Tinker593111f2017-05-25 16:00:21 -0700311 auto manager = hardware::defaultServiceManager();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800312
313 if (manager != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000314 manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800315 [&factories](const hidl_vec<hidl_string> &registered) {
316 for (const auto &instance : registered) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000317 auto factory = drm::V1_0::IDrmFactory::getService(instance);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800318 if (factory != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000319 ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str());
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800320 factories.push_back(factory);
Jeff Tinkere307dc42018-02-11 19:53:54 +0000321 }
322 }
323 }
324 );
325 manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
326 [&factories](const hidl_vec<hidl_string> &registered) {
327 for (const auto &instance : registered) {
328 auto factory = drm::V1_1::IDrmFactory::getService(instance);
329 if (factory != NULL) {
330 ALOGD("found drm@1.1 IDrmFactory %s", instance.c_str());
331 factories.push_back(factory);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800332 }
333 }
334 }
335 );
Jeff Tinkera53d6552017-01-20 00:31:46 -0800336 }
Jeff Tinkerc82b9c32017-02-14 11:39:51 -0800337
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800338 if (factories.size() == 0) {
339 // must be in passthrough mode, load the default passthrough service
Jeff Tinkere309b222017-04-05 08:01:28 -0700340 auto passthrough = IDrmFactory::getService();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800341 if (passthrough != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000342 ALOGI("makeDrmFactories: using default passthrough drm instance");
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800343 factories.push_back(passthrough);
344 } else {
345 ALOGE("Failed to find any drm factories");
346 }
347 }
348 return factories;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800349}
350
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800351sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
352 const uint8_t uuid[16], const String8& appPackageName) {
Adam Stone32494f52018-02-26 22:53:27 -0800353 mAppPackageName = appPackageName;
Adam Stonefb679e32018-02-07 10:25:48 -0800354 mMetrics.SetAppPackageName(appPackageName);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800355
356 sp<IDrmPlugin> plugin;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800357 Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
Jeff Tinkera53d6552017-01-20 00:31:46 -0800358 [&](Status status, const sp<IDrmPlugin>& hPlugin) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800359 if (status != Status::OK) {
360 ALOGE("Failed to make drm plugin");
361 return;
362 }
363 plugin = hPlugin;
364 }
365 );
Jeff Tinkerf0e89b02017-08-07 15:58:41 -0700366
367 if (!hResult.isOk()) {
368 ALOGE("createPlugin remote call failed");
369 }
370
Jeff Tinkera53d6552017-01-20 00:31:46 -0800371 return plugin;
372}
373
374status_t DrmHal::initCheck() const {
375 return mInitCheck;
376}
377
378status_t DrmHal::setListener(const sp<IDrmClient>& listener)
379{
380 Mutex::Autolock lock(mEventLock);
381 if (mListener != NULL){
382 IInterface::asBinder(mListener)->unlinkToDeath(this);
383 }
384 if (listener != NULL) {
385 IInterface::asBinder(listener)->linkToDeath(this);
386 }
387 mListener = listener;
388 return NO_ERROR;
389}
390
391Return<void> DrmHal::sendEvent(EventType hEventType,
392 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
Adam Stonecea91ce2018-01-22 19:23:28 -0800393 mMetrics.mEventCounter.Increment(hEventType);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800394
395 mEventLock.lock();
396 sp<IDrmClient> listener = mListener;
397 mEventLock.unlock();
398
399 if (listener != NULL) {
400 Parcel obj;
401 writeByteArray(obj, sessionId);
402 writeByteArray(obj, data);
403
404 Mutex::Autolock lock(mNotifyLock);
405 DrmPlugin::EventType eventType;
406 switch(hEventType) {
407 case EventType::PROVISION_REQUIRED:
408 eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
409 break;
410 case EventType::KEY_NEEDED:
411 eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
412 break;
413 case EventType::KEY_EXPIRED:
414 eventType = DrmPlugin::kDrmPluginEventKeyExpired;
415 break;
416 case EventType::VENDOR_DEFINED:
417 eventType = DrmPlugin::kDrmPluginEventVendorDefined;
418 break;
Rahul Friasb86f4b32017-03-27 15:13:30 -0700419 case EventType::SESSION_RECLAIMED:
420 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
421 break;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800422 default:
423 return Void();
424 }
425 listener->notify(eventType, 0, &obj);
426 }
427 return Void();
428}
429
430Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
431 int64_t expiryTimeInMS) {
432
433 mEventLock.lock();
434 sp<IDrmClient> listener = mListener;
435 mEventLock.unlock();
436
437 if (listener != NULL) {
438 Parcel obj;
439 writeByteArray(obj, sessionId);
440 obj.writeInt64(expiryTimeInMS);
441
442 Mutex::Autolock lock(mNotifyLock);
443 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
444 }
445 return Void();
446}
447
448Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
449 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
450
451 mEventLock.lock();
452 sp<IDrmClient> listener = mListener;
453 mEventLock.unlock();
454
455 if (listener != NULL) {
456 Parcel obj;
457 writeByteArray(obj, sessionId);
458
459 size_t nKeys = keyStatusList.size();
460 obj.writeInt32(nKeys);
461 for (size_t i = 0; i < nKeys; ++i) {
462 const KeyStatus &keyStatus = keyStatusList[i];
463 writeByteArray(obj, keyStatus.keyId);
464 uint32_t type;
465 switch(keyStatus.type) {
466 case KeyStatusType::USABLE:
467 type = DrmPlugin::kKeyStatusType_Usable;
468 break;
469 case KeyStatusType::EXPIRED:
470 type = DrmPlugin::kKeyStatusType_Expired;
471 break;
472 case KeyStatusType::OUTPUTNOTALLOWED:
473 type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
474 break;
475 case KeyStatusType::STATUSPENDING:
476 type = DrmPlugin::kKeyStatusType_StatusPending;
477 break;
478 case KeyStatusType::INTERNALERROR:
479 default:
480 type = DrmPlugin::kKeyStatusType_InternalError;
481 break;
482 }
483 obj.writeInt32(type);
Adam Stonecea91ce2018-01-22 19:23:28 -0800484 mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800485 }
486 obj.writeInt32(hasNewUsableKey);
487
488 Mutex::Autolock lock(mNotifyLock);
489 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
Adam Stonecea91ce2018-01-22 19:23:28 -0800490 } else {
491 // There's no listener. But we still want to count the key change
492 // events.
493 size_t nKeys = keyStatusList.size();
494 for (size_t i = 0; i < nKeys; i++) {
495 mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
496 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800497 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800498
Jeff Tinkera53d6552017-01-20 00:31:46 -0800499 return Void();
500}
501
502bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
503 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800504
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800505 for (size_t i = 0; i < mFactories.size(); i++) {
506 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
507 if (mimeType != "") {
508 if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
509 return true;
510 }
511 } else {
512 return true;
513 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800514 }
515 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800516 return false;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800517}
518
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800519status_t DrmHal::createPlugin(const uint8_t uuid[16],
520 const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800521 Mutex::Autolock autoLock(mLock);
522
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800523 for (size_t i = 0; i < mFactories.size(); i++) {
524 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
525 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
Edwin Wong5641aa22018-01-30 17:52:21 -0800526 if (mPlugin != NULL) {
527 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
528 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800529 }
530 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800531
532 if (mPlugin == NULL) {
533 mInitCheck = ERROR_UNSUPPORTED;
534 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700535 if (!mPlugin->setListener(this).isOk()) {
536 mInitCheck = DEAD_OBJECT;
537 } else {
538 mInitCheck = OK;
539 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800540 }
541
542 return mInitCheck;
543}
544
545status_t DrmHal::destroyPlugin() {
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800546 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800547 return OK;
548}
549
Jeff Tinker41d279a2018-02-11 19:52:08 +0000550status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
551 Vector<uint8_t> &sessionId) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800552 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800553 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800554
Jeff Tinker41d279a2018-02-11 19:52:08 +0000555 SecurityLevel hSecurityLevel;
556 bool setSecurityLevel = true;
Tobias Thierer5f5e43f2018-02-11 15:00:57 +0000557
Jeff Tinker41d279a2018-02-11 19:52:08 +0000558 switch(level) {
559 case DrmPlugin::kSecurityLevelSwSecureCrypto:
560 hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
561 break;
562 case DrmPlugin::kSecurityLevelSwSecureDecode:
563 hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
564 break;
565 case DrmPlugin::kSecurityLevelHwSecureCrypto:
566 hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
567 break;
568 case DrmPlugin::kSecurityLevelHwSecureDecode:
569 hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
570 break;
571 case DrmPlugin::kSecurityLevelHwSecureAll:
572 hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
573 break;
574 case DrmPlugin::kSecurityLevelMax:
575 setSecurityLevel = false;
576 break;
577 default:
578 return ERROR_DRM_CANNOT_HANDLE;
579 }
580
581 status_t err = UNKNOWN_ERROR;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800582 bool retry = true;
583 do {
584 hidl_vec<uint8_t> hSessionId;
585
Jeff Tinker41d279a2018-02-11 19:52:08 +0000586 Return<void> hResult;
587 if (mPluginV1_1 == NULL || !setSecurityLevel) {
588 hResult = mPlugin->openSession(
589 [&](Status status,const hidl_vec<uint8_t>& id) {
590 if (status == Status::OK) {
591 sessionId = toVector(id);
592 }
593 err = toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800594 }
Jeff Tinker41d279a2018-02-11 19:52:08 +0000595 );
596 } else {
597 hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
598 [&](Status status, const hidl_vec<uint8_t>& id) {
599 if (status == Status::OK) {
600 sessionId = toVector(id);
601 }
602 err = toStatusT(status);
603 }
604 );
605 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800606
607 if (!hResult.isOk()) {
608 err = DEAD_OBJECT;
609 }
610
611 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
612 mLock.unlock();
613 // reclaimSession may call back to closeSession, since mLock is
614 // shared between Drm instances, we should unlock here to avoid
615 // deadlock.
616 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
617 mLock.lock();
618 } else {
619 retry = false;
620 }
621 } while (retry);
622
623 if (err == OK) {
624 DrmSessionManager::Instance()->addSession(getCallingPid(),
625 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700626 mOpenSessions.push(sessionId);
Adam Stone568b3c42018-01-31 12:57:16 -0800627 mMetrics.SetSessionStart(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800628 }
Adam Stoneaaf87dd2018-01-08 11:55:06 -0800629
Adam Stonef0e618d2018-01-17 19:20:41 -0800630 mMetrics.mOpenSessionCounter.Increment(err);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800631 return err;
632}
633
634status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
635 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800636 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800637
Jeff Tinker319d5f42017-07-26 15:44:33 -0700638 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
639 if (status.isOk()) {
640 if (status == Status::OK) {
641 DrmSessionManager::Instance()->removeSession(sessionId);
642 for (size_t i = 0; i < mOpenSessions.size(); i++) {
643 if (mOpenSessions[i] == sessionId) {
644 mOpenSessions.removeAt(i);
645 break;
646 }
Jeff Tinker61332812017-05-15 16:53:10 -0700647 }
648 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800649 status_t response = toStatusT(status);
Adam Stone568b3c42018-01-31 12:57:16 -0800650 mMetrics.SetSessionEnd(sessionId);
Adam Stonecea91ce2018-01-22 19:23:28 -0800651 mMetrics.mCloseSessionCounter.Increment(response);
652 return response;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800653 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800654 mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
Jeff Tinker319d5f42017-07-26 15:44:33 -0700655 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800656}
657
658status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
659 Vector<uint8_t> const &initData, String8 const &mimeType,
660 DrmPlugin::KeyType keyType, KeyedVector<String8,
661 String8> const &optionalParameters, Vector<uint8_t> &request,
662 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
663 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800664 INIT_CHECK();
Adam Stonefb679e32018-02-07 10:25:48 -0800665 EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800666
667 DrmSessionManager::Instance()->useSession(sessionId);
668
669 KeyType hKeyType;
670 if (keyType == DrmPlugin::kKeyType_Streaming) {
671 hKeyType = KeyType::STREAMING;
672 } else if (keyType == DrmPlugin::kKeyType_Offline) {
673 hKeyType = KeyType::OFFLINE;
674 } else if (keyType == DrmPlugin::kKeyType_Release) {
675 hKeyType = KeyType::RELEASE;
676 } else {
Adam Stonef0e618d2018-01-17 19:20:41 -0800677 keyRequestTimer.SetAttribute(BAD_VALUE);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800678 return BAD_VALUE;
679 }
680
681 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
682
683 status_t err = UNKNOWN_ERROR;
684
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800685 if (mPluginV1_1 != NULL) {
686 Return<void> hResult =
687 mPluginV1_1->getKeyRequest_1_1(
688 toHidlVec(sessionId), toHidlVec(initData),
689 toHidlString(mimeType), hKeyType, hOptionalParameters,
690 [&](Status status, const hidl_vec<uint8_t>& hRequest,
691 drm::V1_1::KeyRequestType hKeyRequestType,
692 const hidl_string& hDefaultUrl) {
693
694 if (status == Status::OK) {
695 request = toVector(hRequest);
696 defaultUrl = toString8(hDefaultUrl);
697
698 switch (hKeyRequestType) {
699 case drm::V1_1::KeyRequestType::INITIAL:
700 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
701 break;
702 case drm::V1_1::KeyRequestType::RENEWAL:
703 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
704 break;
705 case drm::V1_1::KeyRequestType::RELEASE:
706 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
707 break;
708 case drm::V1_1::KeyRequestType::NONE:
709 *keyRequestType = DrmPlugin::kKeyRequestType_None;
710 break;
711 case drm::V1_1::KeyRequestType::UPDATE:
712 *keyRequestType = DrmPlugin::kKeyRequestType_Update;
713 break;
714 default:
715 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
716 break;
717 }
718 err = toStatusT(status);
719 }
720 });
721 return hResult.isOk() ? err : DEAD_OBJECT;
722 }
723
Jeff Tinkera53d6552017-01-20 00:31:46 -0800724 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
725 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
726 [&](Status status, const hidl_vec<uint8_t>& hRequest,
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800727 drm::V1_0::KeyRequestType hKeyRequestType,
728 const hidl_string& hDefaultUrl) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800729
730 if (status == Status::OK) {
731 request = toVector(hRequest);
732 defaultUrl = toString8(hDefaultUrl);
733
734 switch (hKeyRequestType) {
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800735 case drm::V1_0::KeyRequestType::INITIAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800736 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
737 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800738 case drm::V1_0::KeyRequestType::RENEWAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800739 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
740 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800741 case drm::V1_0::KeyRequestType::RELEASE:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800742 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
743 break;
744 default:
745 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
746 break;
747 }
748 err = toStatusT(status);
749 }
750 });
751
Adam Stonef0e618d2018-01-17 19:20:41 -0800752 err = hResult.isOk() ? err : DEAD_OBJECT;
753 keyRequestTimer.SetAttribute(err);
754 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800755}
756
757status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
758 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
759 Mutex::Autolock autoLock(mLock);
Adam Stonefb679e32018-02-07 10:25:48 -0800760 EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800761
Jeff Tinker6d998b62017-12-18 14:37:43 -0800762 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800763
764 DrmSessionManager::Instance()->useSession(sessionId);
765
766 status_t err = UNKNOWN_ERROR;
767
768 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
769 toHidlVec(response),
770 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
771 if (status == Status::OK) {
772 keySetId = toVector(hKeySetId);
773 }
774 err = toStatusT(status);
775 }
776 );
Adam Stonecea91ce2018-01-22 19:23:28 -0800777 err = hResult.isOk() ? err : DEAD_OBJECT;
778 keyResponseTimer.SetAttribute(err);
779 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800780}
781
782status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
783 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800784 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800785
Jeff Tinker58ad4752018-02-16 16:51:59 -0800786 Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
787 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800788}
789
790status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
791 Vector<uint8_t> const &keySetId) {
792 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800793 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800794
795 DrmSessionManager::Instance()->useSession(sessionId);
796
Jeff Tinker58ad4752018-02-16 16:51:59 -0800797 Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId),
798 toHidlVec(keySetId));
799 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800800}
801
802status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
803 KeyedVector<String8, String8> &infoMap) const {
804 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800805 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800806
807 DrmSessionManager::Instance()->useSession(sessionId);
808
809 ::KeyedVector hInfoMap;
810
811 status_t err = UNKNOWN_ERROR;
812
813 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
814 [&](Status status, const hidl_vec<KeyValue>& map) {
815 if (status == Status::OK) {
816 infoMap = toKeyedVector(map);
817 }
818 err = toStatusT(status);
819 }
820 );
821
822 return hResult.isOk() ? err : DEAD_OBJECT;
823}
824
825status_t DrmHal::getProvisionRequest(String8 const &certType,
826 String8 const &certAuthority, Vector<uint8_t> &request,
827 String8 &defaultUrl) {
828 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800829 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800830
831 status_t err = UNKNOWN_ERROR;
832
833 Return<void> hResult = mPlugin->getProvisionRequest(
834 toHidlString(certType), toHidlString(certAuthority),
835 [&](Status status, const hidl_vec<uint8_t>& hRequest,
836 const hidl_string& hDefaultUrl) {
837 if (status == Status::OK) {
838 request = toVector(hRequest);
839 defaultUrl = toString8(hDefaultUrl);
840 }
841 err = toStatusT(status);
842 }
843 );
844
Adam Stonecea91ce2018-01-22 19:23:28 -0800845 err = hResult.isOk() ? err : DEAD_OBJECT;
846 mMetrics.mGetProvisionRequestCounter.Increment(err);
847 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800848}
849
850status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800851 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800852 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800853 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800854
855 status_t err = UNKNOWN_ERROR;
856
857 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
858 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
859 const hidl_vec<uint8_t>& hWrappedKey) {
860 if (status == Status::OK) {
861 certificate = toVector(hCertificate);
862 wrappedKey = toVector(hWrappedKey);
863 }
864 err = toStatusT(status);
865 }
866 );
867
Adam Stonecea91ce2018-01-22 19:23:28 -0800868 err = hResult.isOk() ? err : DEAD_OBJECT;
869 mMetrics.mProvideProvisionResponseCounter.Increment(err);
870 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800871}
872
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800873status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800874 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800875 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800876
877 status_t err = UNKNOWN_ERROR;
878
879 Return<void> hResult = mPlugin->getSecureStops(
880 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
881 if (status == Status::OK) {
882 secureStops = toSecureStops(hSecureStops);
883 }
884 err = toStatusT(status);
885 }
886 );
887
888 return hResult.isOk() ? err : DEAD_OBJECT;
889}
890
891
Jeff Tinker15177d72018-01-25 12:57:55 -0800892status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
893 Mutex::Autolock autoLock(mLock);
894
895 if (mInitCheck != OK) {
896 return mInitCheck;
897 }
898
899 if (mPluginV1_1 == NULL) {
900 return ERROR_DRM_CANNOT_HANDLE;
901 }
902
903 status_t err = UNKNOWN_ERROR;
904
905 Return<void> hResult = mPluginV1_1->getSecureStopIds(
906 [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
907 if (status == Status::OK) {
908 secureStopIds = toSecureStopIds(hSecureStopIds);
909 }
910 err = toStatusT(status);
911 }
912 );
913
914 return hResult.isOk() ? err : DEAD_OBJECT;
915}
916
917
Jeff Tinkera53d6552017-01-20 00:31:46 -0800918status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
919 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800920 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800921
922 status_t err = UNKNOWN_ERROR;
923
924 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
925 [&](Status status, const SecureStop& hSecureStop) {
926 if (status == Status::OK) {
927 secureStop = toVector(hSecureStop.opaqueData);
928 }
929 err = toStatusT(status);
930 }
931 );
932
933 return hResult.isOk() ? err : DEAD_OBJECT;
934}
935
936status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
937 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800938 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800939
Jeff Tinker58ad4752018-02-16 16:51:59 -0800940 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -0800941 if (mPluginV1_1 != NULL) {
942 SecureStopRelease secureStopRelease;
943 secureStopRelease.opaqueData = toHidlVec(ssRelease);
Jeff Tinker58ad4752018-02-16 16:51:59 -0800944 status = mPluginV1_1->releaseSecureStops(secureStopRelease);
945 } else {
946 status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
Jeff Tinker15177d72018-01-25 12:57:55 -0800947 }
Jeff Tinker58ad4752018-02-16 16:51:59 -0800948 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800949}
950
Jeff Tinker15177d72018-01-25 12:57:55 -0800951status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
952 Mutex::Autolock autoLock(mLock);
953
954 if (mInitCheck != OK) {
955 return mInitCheck;
956 }
957
958 if (mPluginV1_1 == NULL) {
959 return ERROR_DRM_CANNOT_HANDLE;
960 }
961
Jeff Tinker58ad4752018-02-16 16:51:59 -0800962 Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
963 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinker15177d72018-01-25 12:57:55 -0800964}
965
966status_t DrmHal::removeAllSecureStops() {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800967 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800968 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800969
Jeff Tinker58ad4752018-02-16 16:51:59 -0800970 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -0800971 if (mPluginV1_1 != NULL) {
Jeff Tinker58ad4752018-02-16 16:51:59 -0800972 status = mPluginV1_1->removeAllSecureStops();
973 } else {
974 status = mPlugin->releaseAllSecureStops();
Jeff Tinker15177d72018-01-25 12:57:55 -0800975 }
Jeff Tinker58ad4752018-02-16 16:51:59 -0800976 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800977}
978
Jeff Tinker6d998b62017-12-18 14:37:43 -0800979status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
980 DrmPlugin::HdcpLevel *max) const {
981 Mutex::Autolock autoLock(mLock);
982 INIT_CHECK();
983
984 if (connected == NULL || max == NULL) {
985 return BAD_VALUE;
986 }
987 status_t err = UNKNOWN_ERROR;
988
989 if (mPluginV1_1 == NULL) {
990 return ERROR_DRM_CANNOT_HANDLE;
991 }
992
993 *connected = DrmPlugin::kHdcpLevelUnknown;
994 *max = DrmPlugin::kHdcpLevelUnknown;
995
996 Return<void> hResult = mPluginV1_1->getHdcpLevels(
997 [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
998 if (status == Status::OK) {
999 *connected = toHdcpLevel(hConnected);
1000 *max = toHdcpLevel(hMax);
1001 }
1002 err = toStatusT(status);
1003 }
1004 );
1005
1006 return hResult.isOk() ? err : DEAD_OBJECT;
1007}
1008
1009status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
1010 Mutex::Autolock autoLock(mLock);
1011 INIT_CHECK();
1012
1013 if (open == NULL || max == NULL) {
1014 return BAD_VALUE;
1015 }
1016 status_t err = UNKNOWN_ERROR;
1017
1018 *open = 0;
1019 *max = 0;
1020
1021 if (mPluginV1_1 == NULL) {
1022 return ERROR_DRM_CANNOT_HANDLE;
1023 }
1024
1025 Return<void> hResult = mPluginV1_1->getNumberOfSessions(
1026 [&](Status status, uint32_t hOpen, uint32_t hMax) {
1027 if (status == Status::OK) {
1028 *open = hOpen;
1029 *max = hMax;
1030 }
1031 err = toStatusT(status);
1032 }
1033 );
1034
1035 return hResult.isOk() ? err : DEAD_OBJECT;
1036}
1037
1038status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
1039 DrmPlugin::SecurityLevel *level) const {
1040 Mutex::Autolock autoLock(mLock);
1041 INIT_CHECK();
1042
1043 if (level == NULL) {
1044 return BAD_VALUE;
1045 }
1046 status_t err = UNKNOWN_ERROR;
1047
1048 if (mPluginV1_1 == NULL) {
1049 return ERROR_DRM_CANNOT_HANDLE;
1050 }
1051
1052 *level = DrmPlugin::kSecurityLevelUnknown;
1053
1054 Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
1055 [&](Status status, SecurityLevel hLevel) {
1056 if (status == Status::OK) {
1057 *level = toSecurityLevel(hLevel);
1058 }
1059 err = toStatusT(status);
1060 }
1061 );
1062
1063 return hResult.isOk() ? err : DEAD_OBJECT;
1064}
1065
Jeff Tinkera53d6552017-01-20 00:31:46 -08001066status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
1067 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001068 return getPropertyStringInternal(name, value);
1069}
1070
1071status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
1072 // This function is internal to the class and should only be called while
1073 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001074 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001075
1076 status_t err = UNKNOWN_ERROR;
1077
1078 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
1079 [&](Status status, const hidl_string& hValue) {
1080 if (status == Status::OK) {
1081 value = toString8(hValue);
1082 }
1083 err = toStatusT(status);
1084 }
1085 );
1086
1087 return hResult.isOk() ? err : DEAD_OBJECT;
1088}
1089
1090status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
1091 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001092 return getPropertyByteArrayInternal(name, value);
1093}
1094
1095status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
1096 // This function is internal to the class and should only be called while
1097 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001098 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001099
1100 status_t err = UNKNOWN_ERROR;
1101
1102 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
1103 [&](Status status, const hidl_vec<uint8_t>& hValue) {
1104 if (status == Status::OK) {
1105 value = toVector(hValue);
1106 }
1107 err = toStatusT(status);
1108 }
1109 );
1110
Adam Stonecea91ce2018-01-22 19:23:28 -08001111 err = hResult.isOk() ? err : DEAD_OBJECT;
1112 if (name == kPropertyDeviceUniqueId) {
1113 mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
1114 }
1115 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001116}
1117
1118status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
1119 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001120 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001121
Jeff Tinker58ad4752018-02-16 16:51:59 -08001122 Return<Status> status = mPlugin->setPropertyString(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001123 toHidlString(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001124 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001125}
1126
1127status_t DrmHal::setPropertyByteArray(String8 const &name,
1128 Vector<uint8_t> const &value ) const {
1129 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001130 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001131
Jeff Tinker58ad4752018-02-16 16:51:59 -08001132 Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001133 toHidlVec(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001134 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001135}
1136
Adam Stone28f27c32018-02-05 15:07:48 -08001137status_t DrmHal::getMetrics(PersistableBundle* metrics) {
1138 if (metrics == nullptr) {
1139 return UNEXPECTED_NULL;
1140 }
1141 mMetrics.Export(metrics);
1142
1143 // Append vendor metrics if they are supported.
1144 if (mPluginV1_1 != NULL) {
1145 String8 vendor;
1146 String8 description;
1147 if (getPropertyStringInternal(String8("vendor"), vendor) != OK
1148 || vendor.isEmpty()) {
1149 ALOGE("Get vendor failed or is empty");
1150 vendor = "NONE";
1151 }
1152 if (getPropertyStringInternal(String8("description"), description) != OK
1153 || description.isEmpty()) {
1154 ALOGE("Get description failed or is empty.");
1155 description = "NONE";
1156 }
1157 vendor += ".";
1158 vendor += description;
1159
1160 hidl_vec<DrmMetricGroup> pluginMetrics;
1161 status_t err = UNKNOWN_ERROR;
1162
1163 Return<void> status = mPluginV1_1->getMetrics(
1164 [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
1165 if (status != Status::OK) {
1166 ALOGV("Error getting plugin metrics: %d", status);
1167 } else {
1168 PersistableBundle pluginBundle;
1169 if (MediaDrmMetrics::HidlMetricsToBundle(
1170 pluginMetrics, &pluginBundle) == OK) {
1171 metrics->putPersistableBundle(String16(vendor), pluginBundle);
1172 }
1173 }
1174 err = toStatusT(status);
1175 });
1176 return status.isOk() ? err : DEAD_OBJECT;
Adam Stonef0e618d2018-01-17 19:20:41 -08001177 }
1178
Adam Stoneab394d12017-12-22 12:34:20 -08001179 return OK;
1180}
Jeff Tinkera53d6552017-01-20 00:31:46 -08001181
1182status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
1183 String8 const &algorithm) {
1184 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001185 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001186
1187 DrmSessionManager::Instance()->useSession(sessionId);
1188
1189 Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
1190 toHidlString(algorithm));
1191 return toStatusT(status);
1192}
1193
1194status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
1195 String8 const &algorithm) {
1196 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001197 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001198
1199 DrmSessionManager::Instance()->useSession(sessionId);
1200
1201 Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
1202 toHidlString(algorithm));
1203 return toStatusT(status);
1204}
1205
1206status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001207 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1208 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001209 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001210 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001211
1212 DrmSessionManager::Instance()->useSession(sessionId);
1213
1214 status_t err = UNKNOWN_ERROR;
1215
1216 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
1217 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1218 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1219 if (status == Status::OK) {
1220 output = toVector(hOutput);
1221 }
1222 err = toStatusT(status);
1223 }
1224 );
1225
1226 return hResult.isOk() ? err : DEAD_OBJECT;
1227}
1228
1229status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001230 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1231 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001232 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001233 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001234
1235 DrmSessionManager::Instance()->useSession(sessionId);
1236
1237 status_t err = UNKNOWN_ERROR;
1238
1239 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
1240 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1241 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1242 if (status == Status::OK) {
1243 output = toVector(hOutput);
1244 }
1245 err = toStatusT(status);
1246 }
1247 );
1248
1249 return hResult.isOk() ? err : DEAD_OBJECT;
1250}
1251
1252status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001253 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1254 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001255 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001256 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001257
1258 DrmSessionManager::Instance()->useSession(sessionId);
1259
1260 status_t err = UNKNOWN_ERROR;
1261
1262 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
1263 toHidlVec(keyId), toHidlVec(message),
1264 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1265 if (status == Status::OK) {
1266 signature = toVector(hSignature);
1267 }
1268 err = toStatusT(status);
1269 }
1270 );
1271
1272 return hResult.isOk() ? err : DEAD_OBJECT;
1273}
1274
1275status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001276 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1277 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001278 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001279 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001280
1281 DrmSessionManager::Instance()->useSession(sessionId);
1282
1283 status_t err = UNKNOWN_ERROR;
1284
1285 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
1286 toHidlVec(message), toHidlVec(signature),
1287 [&](Status status, bool hMatch) {
1288 if (status == Status::OK) {
1289 match = hMatch;
1290 } else {
1291 match = false;
1292 }
1293 err = toStatusT(status);
1294 }
1295 );
1296
1297 return hResult.isOk() ? err : DEAD_OBJECT;
1298}
1299
1300status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001301 String8 const &algorithm, Vector<uint8_t> const &message,
1302 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001303 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001304 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001305
1306 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
1307 return -EPERM;
1308 }
1309
1310 DrmSessionManager::Instance()->useSession(sessionId);
1311
1312 status_t err = UNKNOWN_ERROR;
1313
1314 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1315 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1316 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1317 if (status == Status::OK) {
1318 signature = toVector(hSignature);
1319 }
1320 err = toStatusT(status);
1321 }
1322 );
1323
1324 return hResult.isOk() ? err : DEAD_OBJECT;
1325}
1326
1327void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1328{
Jeff Tinker7dfe28f2018-02-15 12:17:40 -08001329 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001330}
1331
1332void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1333{
1334 if (vec.size()) {
1335 obj.writeInt32(vec.size());
1336 obj.write(vec.data(), vec.size());
1337 } else {
1338 obj.writeInt32(0);
1339 }
1340}
1341
Adam Stonefb679e32018-02-07 10:25:48 -08001342void DrmHal::reportFrameworkMetrics() const
1343{
1344 MediaAnalyticsItem item("mediadrm");
1345 item.generateSessionID();
1346 item.setPkgName(mMetrics.GetAppPackageName().c_str());
1347 String8 vendor;
1348 String8 description;
1349 status_t result = getPropertyStringInternal(String8("vendor"), vendor);
1350 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001351 ALOGE("Failed to get vendor from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001352 } else {
1353 item.setCString("vendor", vendor.c_str());
1354 }
1355 result = getPropertyStringInternal(String8("description"), description);
1356 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001357 ALOGE("Failed to get description from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001358 } else {
1359 item.setCString("description", description.c_str());
1360 }
Adam Stoneab394d12017-12-22 12:34:20 -08001361
Adam Stonefb679e32018-02-07 10:25:48 -08001362 std::string serializedMetrics;
1363 result = mMetrics.GetSerializedMetrics(&serializedMetrics);
1364 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001365 ALOGE("Failed to serialize framework metrics: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001366 }
Adam Stone32494f52018-02-26 22:53:27 -08001367 std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
1368 serializedMetrics.size());
1369 if (!b64EncodedMetrics.empty()) {
1370 item.setCString("serialized_metrics", b64EncodedMetrics.c_str());
Adam Stonefb679e32018-02-07 10:25:48 -08001371 }
1372 if (!item.selfrecord()) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001373 ALOGE("Failed to self record framework metrics");
Adam Stonefb679e32018-02-07 10:25:48 -08001374 }
1375}
1376
1377void DrmHal::reportPluginMetrics() const
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001378{
Adam Stone32494f52018-02-26 22:53:27 -08001379 Vector<uint8_t> metricsVector;
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001380 String8 vendor;
1381 String8 description;
1382 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1383 getPropertyStringInternal(String8("description"), description) == OK &&
Adam Stone32494f52018-02-26 22:53:27 -08001384 getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
1385 std::string metricsString = toBase64StringNoPad(metricsVector.array(),
1386 metricsVector.size());
1387 status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
1388 description, mAppPackageName);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001389 if (res != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001390 ALOGE("Metrics were retrieved but could not be reported: %d", res);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001391 }
1392 }
1393}
1394
Jeff Tinkera53d6552017-01-20 00:31:46 -08001395} // namespace android