blob: 981bd5b03a64dfe6a90fdb429a375054df9e8ab1 [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 Tinkerc8baaba2018-10-23 11:32:36 -070026#include <android/hardware/drm/1.2/types.h>
Peter Kalauskasca5642c2018-11-12 12:34:42 -080027#include <android/hidl/manager/1.2/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;
Jeff Tinker6d998b62017-12-18 14:37:43 -080046using drm::V1_0::SecureStop;
Jeff Tinker15177d72018-01-25 12:57:55 -080047using drm::V1_0::SecureStopId;
Jeff Tinker6d998b62017-12-18 14:37:43 -080048using drm::V1_0::Status;
Jeff Tinkerc8baaba2018-10-23 11:32:36 -070049using drm::V1_1::HdcpLevel;
50using drm::V1_1::SecureStopRelease;
51using drm::V1_1::SecurityLevel;
52using drm::V1_2::KeySetId;
Adam Stone28f27c32018-02-05 15:07:48 -080053using ::android::hardware::drm::V1_1::DrmMetricGroup;
Jeff Tinkera53d6552017-01-20 00:31:46 -080054using ::android::hardware::hidl_array;
55using ::android::hardware::hidl_string;
56using ::android::hardware::hidl_vec;
57using ::android::hardware::Return;
58using ::android::hardware::Void;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -080059using ::android::hidl::manager::V1_0::IServiceManager;
Adam Stone637b7852018-01-30 12:09:36 -080060using ::android::os::PersistableBundle;
Jeff Tinkera53d6552017-01-20 00:31:46 -080061using ::android::sp;
62
Adam Stonecea91ce2018-01-22 19:23:28 -080063namespace {
64
65// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
66// in the MediaDrm API.
67constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
Adam Stone32494f52018-02-26 22:53:27 -080068constexpr char kEqualsSign[] = "=";
Adam Stonecea91ce2018-01-22 19:23:28 -080069
Adam Stone32494f52018-02-26 22:53:27 -080070template<typename T>
71std::string toBase64StringNoPad(const T* data, size_t size) {
Adam Stone630092e2018-05-02 13:06:34 -070072 // Note that the base 64 conversion only works with arrays of single-byte
73 // values. If the source is empty or is not an array of single-byte values,
74 // return empty string.
75 if (size == 0 || sizeof(data[0]) != 1) {
Adam Stone32494f52018-02-26 22:53:27 -080076 return "";
77 }
Adam Stone32494f52018-02-26 22:53:27 -080078
79 android::AString outputString;
80 encodeBase64(data, size, &outputString);
81 // Remove trailing equals padding if it exists.
82 while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
83 outputString.erase(outputString.size() - 1, 1);
84 }
85
86 return std::string(outputString.c_str(), outputString.size());
Adam Stonecea91ce2018-01-22 19:23:28 -080087}
88
Adam Stone32494f52018-02-26 22:53:27 -080089} // anonymous namespace
90
Jeff Tinkera53d6552017-01-20 00:31:46 -080091namespace android {
92
Jeff Tinker6d998b62017-12-18 14:37:43 -080093#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
94
Jeff Tinkera53d6552017-01-20 00:31:46 -080095static inline int getCallingPid() {
96 return IPCThreadState::self()->getCallingPid();
97}
98
99static bool checkPermission(const char* permissionString) {
100 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
101 bool ok = checkCallingPermission(String16(permissionString));
102 if (!ok) ALOGE("Request requires %s", permissionString);
103 return ok;
104}
105
106static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
107 Vector<uint8_t> vector;
108 vector.appendArray(vec.data(), vec.size());
109 return *const_cast<const Vector<uint8_t> *>(&vector);
110}
111
112static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
113 hidl_vec<uint8_t> vec;
114 vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
115 return vec;
116}
117
118static String8 toString8(const hidl_string &string) {
119 return String8(string.c_str());
120}
121
122static hidl_string toHidlString(const String8& string) {
123 return hidl_string(string.string());
124}
125
Jeff Tinker6d998b62017-12-18 14:37:43 -0800126static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
127 switch(level) {
128 case SecurityLevel::SW_SECURE_CRYPTO:
129 return DrmPlugin::kSecurityLevelSwSecureCrypto;
130 case SecurityLevel::SW_SECURE_DECODE:
131 return DrmPlugin::kSecurityLevelSwSecureDecode;
132 case SecurityLevel::HW_SECURE_CRYPTO:
133 return DrmPlugin::kSecurityLevelHwSecureCrypto;
134 case SecurityLevel::HW_SECURE_DECODE:
135 return DrmPlugin::kSecurityLevelHwSecureDecode;
136 case SecurityLevel::HW_SECURE_ALL:
137 return DrmPlugin::kSecurityLevelHwSecureAll;
138 default:
139 return DrmPlugin::kSecurityLevelUnknown;
140 }
141}
142
Jeff Tinkerc8baaba2018-10-23 11:32:36 -0700143static DrmPlugin::OfflineLicenseState toOfflineLicenseState(
144 OfflineLicenseState licenseState) {
145 switch(licenseState) {
146 case OfflineLicenseState::USABLE:
147 return DrmPlugin::kOfflineLicenseStateUsable;
148 case OfflineLicenseState::INACTIVE:
149 return DrmPlugin::kOfflineLicenseStateInactive;
150 default:
151 return DrmPlugin::kOfflineLicenseStateUnknown;
152 }
153}
154
Jeff Tinker6d998b62017-12-18 14:37:43 -0800155static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
156 switch(level) {
157 case HdcpLevel::HDCP_NONE:
158 return DrmPlugin::kHdcpNone;
159 case HdcpLevel::HDCP_V1:
160 return DrmPlugin::kHdcpV1;
161 case HdcpLevel::HDCP_V2:
162 return DrmPlugin::kHdcpV2;
163 case HdcpLevel::HDCP_V2_1:
164 return DrmPlugin::kHdcpV2_1;
165 case HdcpLevel::HDCP_V2_2:
166 return DrmPlugin::kHdcpV2_2;
167 case HdcpLevel::HDCP_NO_OUTPUT:
168 return DrmPlugin::kHdcpNoOutput;
169 default:
170 return DrmPlugin::kHdcpLevelUnknown;
171 }
172}
173
Jeff Tinkera53d6552017-01-20 00:31:46 -0800174
175static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
176 keyedVector) {
177 std::vector<KeyValue> stdKeyedVector;
178 for (size_t i = 0; i < keyedVector.size(); i++) {
179 KeyValue keyValue;
180 keyValue.key = toHidlString(keyedVector.keyAt(i));
181 keyValue.value = toHidlString(keyedVector.valueAt(i));
182 stdKeyedVector.push_back(keyValue);
183 }
184 return ::KeyedVector(stdKeyedVector);
185}
186
187static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
188 hKeyedVector) {
189 KeyedVector<String8, String8> keyedVector;
190 for (size_t i = 0; i < hKeyedVector.size(); i++) {
191 keyedVector.add(toString8(hKeyedVector[i].key),
192 toString8(hKeyedVector[i].value));
193 }
194 return keyedVector;
195}
196
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800197static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
Jeff Tinkera53d6552017-01-20 00:31:46 -0800198 hSecureStops) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800199 List<Vector<uint8_t>> secureStops;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800200 for (size_t i = 0; i < hSecureStops.size(); i++) {
201 secureStops.push_back(toVector(hSecureStops[i].opaqueData));
202 }
203 return secureStops;
204}
205
Jeff Tinker15177d72018-01-25 12:57:55 -0800206static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
207 hSecureStopIds) {
208 List<Vector<uint8_t>> secureStopIds;
209 for (size_t i = 0; i < hSecureStopIds.size(); i++) {
210 secureStopIds.push_back(toVector(hSecureStopIds[i]));
211 }
212 return secureStopIds;
213}
214
Jeff Tinkerc8baaba2018-10-23 11:32:36 -0700215static List<Vector<uint8_t>> toKeySetIds(const hidl_vec<KeySetId>&
216 hKeySetIds) {
217 List<Vector<uint8_t>> keySetIds;
218 for (size_t i = 0; i < hKeySetIds.size(); i++) {
219 keySetIds.push_back(toVector(hKeySetIds[i]));
220 }
221 return keySetIds;
222}
223
Jeff Tinkera53d6552017-01-20 00:31:46 -0800224static status_t toStatusT(Status status) {
225 switch (status) {
226 case Status::OK:
227 return OK;
228 break;
229 case Status::ERROR_DRM_NO_LICENSE:
230 return ERROR_DRM_NO_LICENSE;
231 break;
232 case Status::ERROR_DRM_LICENSE_EXPIRED:
233 return ERROR_DRM_LICENSE_EXPIRED;
234 break;
235 case Status::ERROR_DRM_SESSION_NOT_OPENED:
236 return ERROR_DRM_SESSION_NOT_OPENED;
237 break;
238 case Status::ERROR_DRM_CANNOT_HANDLE:
239 return ERROR_DRM_CANNOT_HANDLE;
240 break;
241 case Status::ERROR_DRM_INVALID_STATE:
242 return ERROR_DRM_TAMPER_DETECTED;
243 break;
244 case Status::BAD_VALUE:
245 return BAD_VALUE;
246 break;
247 case Status::ERROR_DRM_NOT_PROVISIONED:
248 return ERROR_DRM_NOT_PROVISIONED;
249 break;
250 case Status::ERROR_DRM_RESOURCE_BUSY:
251 return ERROR_DRM_RESOURCE_BUSY;
252 break;
253 case Status::ERROR_DRM_DEVICE_REVOKED:
254 return ERROR_DRM_DEVICE_REVOKED;
255 break;
256 case Status::ERROR_DRM_UNKNOWN:
257 default:
258 return ERROR_DRM_UNKNOWN;
259 break;
260 }
261}
262
263
264Mutex DrmHal::mLock;
265
266struct DrmSessionClient : public DrmSessionClientInterface {
267 explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
268
269 virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
270 sp<DrmHal> drm = mDrm.promote();
271 if (drm == NULL) {
272 return true;
273 }
274 status_t err = drm->closeSession(sessionId);
275 if (err != OK) {
276 return false;
277 }
278 drm->sendEvent(EventType::SESSION_RECLAIMED,
279 toHidlVec(sessionId), hidl_vec<uint8_t>());
280 return true;
281 }
282
283protected:
284 virtual ~DrmSessionClient() {}
285
286private:
287 wp<DrmHal> mDrm;
288
289 DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
290};
291
292DrmHal::DrmHal()
293 : mDrmSessionClient(new DrmSessionClient(this)),
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800294 mFactories(makeDrmFactories()),
295 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800296}
297
Jeff Tinker61332812017-05-15 16:53:10 -0700298void DrmHal::closeOpenSessions() {
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800299 Mutex::Autolock autoLock(mLock);
300 auto openSessions = mOpenSessions;
301 for (size_t i = 0; i < openSessions.size(); i++) {
302 mLock.unlock();
303 closeSession(openSessions[i]);
304 mLock.lock();
Jeff Tinker61332812017-05-15 16:53:10 -0700305 }
306 mOpenSessions.clear();
307}
308
Jeff Tinkera53d6552017-01-20 00:31:46 -0800309DrmHal::~DrmHal() {
310 DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
311}
312
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800313void DrmHal::cleanup() {
314 closeOpenSessions();
315
316 Mutex::Autolock autoLock(mLock);
317 reportPluginMetrics();
318 reportFrameworkMetrics();
319
320 setListener(NULL);
321 mInitCheck = NO_INIT;
322
323 if (mPlugin != NULL) {
324 if (!mPlugin->setListener(NULL).isOk()) {
325 mInitCheck = DEAD_OBJECT;
326 }
327 }
328 mPlugin.clear();
329 mPluginV1_1.clear();
Jeff Tinkerc8baaba2018-10-23 11:32:36 -0700330 mPluginV1_2.clear();
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800331}
332
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800333Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
334 Vector<sp<IDrmFactory>> factories;
335
Peter Kalauskasca5642c2018-11-12 12:34:42 -0800336 auto manager = hardware::defaultServiceManager1_2();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800337
338 if (manager != NULL) {
Peter Kalauskasca5642c2018-11-12 12:34:42 -0800339 manager->listManifestByInterface(drm::V1_0::IDrmFactory::descriptor,
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800340 [&factories](const hidl_vec<hidl_string> &registered) {
341 for (const auto &instance : registered) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000342 auto factory = drm::V1_0::IDrmFactory::getService(instance);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800343 if (factory != NULL) {
344 factories.push_back(factory);
Jeff Tinkere307dc42018-02-11 19:53:54 +0000345 }
346 }
347 }
348 );
Peter Kalauskasca5642c2018-11-12 12:34:42 -0800349 manager->listManifestByInterface(drm::V1_1::IDrmFactory::descriptor,
Jeff Tinkere307dc42018-02-11 19:53:54 +0000350 [&factories](const hidl_vec<hidl_string> &registered) {
351 for (const auto &instance : registered) {
352 auto factory = drm::V1_1::IDrmFactory::getService(instance);
353 if (factory != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000354 factories.push_back(factory);
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800355 }
356 }
357 }
358 );
Jeff Tinkerc8baaba2018-10-23 11:32:36 -0700359 manager->listByInterface(drm::V1_2::IDrmFactory::descriptor,
360 [&factories](const hidl_vec<hidl_string> &registered) {
361 for (const auto &instance : registered) {
362 auto factory = drm::V1_2::IDrmFactory::getService(instance);
363 if (factory != NULL) {
364 factories.push_back(factory);
365 }
366 }
367 }
368 );
Jeff Tinkera53d6552017-01-20 00:31:46 -0800369 }
Jeff Tinkerc82b9c32017-02-14 11:39:51 -0800370
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800371 if (factories.size() == 0) {
372 // must be in passthrough mode, load the default passthrough service
Jeff Tinkere309b222017-04-05 08:01:28 -0700373 auto passthrough = IDrmFactory::getService();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800374 if (passthrough != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000375 ALOGI("makeDrmFactories: using default passthrough drm instance");
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800376 factories.push_back(passthrough);
377 } else {
378 ALOGE("Failed to find any drm factories");
379 }
380 }
381 return factories;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800382}
383
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800384sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
385 const uint8_t uuid[16], const String8& appPackageName) {
Adam Stone32494f52018-02-26 22:53:27 -0800386 mAppPackageName = appPackageName;
Adam Stonefb679e32018-02-07 10:25:48 -0800387 mMetrics.SetAppPackageName(appPackageName);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800388
389 sp<IDrmPlugin> plugin;
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800390 Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
Jeff Tinkera53d6552017-01-20 00:31:46 -0800391 [&](Status status, const sp<IDrmPlugin>& hPlugin) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800392 if (status != Status::OK) {
393 ALOGE("Failed to make drm plugin");
394 return;
395 }
396 plugin = hPlugin;
397 }
398 );
Jeff Tinkerf0e89b02017-08-07 15:58:41 -0700399
400 if (!hResult.isOk()) {
401 ALOGE("createPlugin remote call failed");
402 }
403
Jeff Tinkera53d6552017-01-20 00:31:46 -0800404 return plugin;
405}
406
407status_t DrmHal::initCheck() const {
408 return mInitCheck;
409}
410
411status_t DrmHal::setListener(const sp<IDrmClient>& listener)
412{
413 Mutex::Autolock lock(mEventLock);
414 if (mListener != NULL){
415 IInterface::asBinder(mListener)->unlinkToDeath(this);
416 }
417 if (listener != NULL) {
418 IInterface::asBinder(listener)->linkToDeath(this);
419 }
420 mListener = listener;
421 return NO_ERROR;
422}
423
424Return<void> DrmHal::sendEvent(EventType hEventType,
425 const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
Adam Stonecea91ce2018-01-22 19:23:28 -0800426 mMetrics.mEventCounter.Increment(hEventType);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800427
428 mEventLock.lock();
429 sp<IDrmClient> listener = mListener;
430 mEventLock.unlock();
431
432 if (listener != NULL) {
433 Parcel obj;
434 writeByteArray(obj, sessionId);
435 writeByteArray(obj, data);
436
437 Mutex::Autolock lock(mNotifyLock);
438 DrmPlugin::EventType eventType;
439 switch(hEventType) {
440 case EventType::PROVISION_REQUIRED:
441 eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
442 break;
443 case EventType::KEY_NEEDED:
444 eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
445 break;
446 case EventType::KEY_EXPIRED:
447 eventType = DrmPlugin::kDrmPluginEventKeyExpired;
448 break;
449 case EventType::VENDOR_DEFINED:
450 eventType = DrmPlugin::kDrmPluginEventVendorDefined;
451 break;
Rahul Friasb86f4b32017-03-27 15:13:30 -0700452 case EventType::SESSION_RECLAIMED:
453 eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
454 break;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800455 default:
456 return Void();
457 }
458 listener->notify(eventType, 0, &obj);
459 }
460 return Void();
461}
462
463Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
464 int64_t expiryTimeInMS) {
465
466 mEventLock.lock();
467 sp<IDrmClient> listener = mListener;
468 mEventLock.unlock();
469
470 if (listener != NULL) {
471 Parcel obj;
472 writeByteArray(obj, sessionId);
473 obj.writeInt64(expiryTimeInMS);
474
475 Mutex::Autolock lock(mNotifyLock);
476 listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
477 }
478 return Void();
479}
480
481Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
482 const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
483
484 mEventLock.lock();
485 sp<IDrmClient> listener = mListener;
486 mEventLock.unlock();
487
488 if (listener != NULL) {
489 Parcel obj;
490 writeByteArray(obj, sessionId);
491
492 size_t nKeys = keyStatusList.size();
493 obj.writeInt32(nKeys);
494 for (size_t i = 0; i < nKeys; ++i) {
495 const KeyStatus &keyStatus = keyStatusList[i];
496 writeByteArray(obj, keyStatus.keyId);
497 uint32_t type;
498 switch(keyStatus.type) {
499 case KeyStatusType::USABLE:
500 type = DrmPlugin::kKeyStatusType_Usable;
501 break;
502 case KeyStatusType::EXPIRED:
503 type = DrmPlugin::kKeyStatusType_Expired;
504 break;
505 case KeyStatusType::OUTPUTNOTALLOWED:
506 type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
507 break;
508 case KeyStatusType::STATUSPENDING:
509 type = DrmPlugin::kKeyStatusType_StatusPending;
510 break;
511 case KeyStatusType::INTERNALERROR:
512 default:
513 type = DrmPlugin::kKeyStatusType_InternalError;
514 break;
515 }
516 obj.writeInt32(type);
Adam Stonecea91ce2018-01-22 19:23:28 -0800517 mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800518 }
519 obj.writeInt32(hasNewUsableKey);
520
521 Mutex::Autolock lock(mNotifyLock);
522 listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
Adam Stonecea91ce2018-01-22 19:23:28 -0800523 } else {
524 // There's no listener. But we still want to count the key change
525 // events.
526 size_t nKeys = keyStatusList.size();
527 for (size_t i = 0; i < nKeys; i++) {
528 mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
529 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800530 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800531
Jeff Tinkera53d6552017-01-20 00:31:46 -0800532 return Void();
533}
534
535bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
536 Mutex::Autolock autoLock(mLock);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800537
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800538 for (size_t i = 0; i < mFactories.size(); i++) {
539 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
540 if (mimeType != "") {
541 if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
542 return true;
543 }
544 } else {
545 return true;
546 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800547 }
548 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800549 return false;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800550}
551
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800552status_t DrmHal::createPlugin(const uint8_t uuid[16],
553 const String8& appPackageName) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800554 Mutex::Autolock autoLock(mLock);
555
Peter Kalauskas7676a402018-12-27 11:04:16 -0800556 for (size_t i = mFactories.size() - 1; i >= 0; i--) {
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800557 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
Peter Kalauskas7676a402018-12-27 11:04:16 -0800558 auto plugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
559 if (plugin != NULL) {
560 mPlugin = plugin;
Edwin Wong5641aa22018-01-30 17:52:21 -0800561 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
Jeff Tinkerc8baaba2018-10-23 11:32:36 -0700562 mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
Peter Kalauskas7676a402018-12-27 11:04:16 -0800563 break;
Edwin Wong5641aa22018-01-30 17:52:21 -0800564 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800565 }
566 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800567
568 if (mPlugin == NULL) {
569 mInitCheck = ERROR_UNSUPPORTED;
570 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700571 if (!mPlugin->setListener(this).isOk()) {
Peter Kalauskas7676a402018-12-27 11:04:16 -0800572 mPlugin = NULL;
573 mPluginV1_1 = NULL;
574 mPluginV1_2 = NULL;
Jeff Tinker319d5f42017-07-26 15:44:33 -0700575 mInitCheck = DEAD_OBJECT;
576 } else {
577 mInitCheck = OK;
578 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800579 }
580
581 return mInitCheck;
582}
583
584status_t DrmHal::destroyPlugin() {
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800585 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800586 return OK;
587}
588
Jeff Tinker41d279a2018-02-11 19:52:08 +0000589status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
590 Vector<uint8_t> &sessionId) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800591 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800592 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800593
Jeff Tinker41d279a2018-02-11 19:52:08 +0000594 SecurityLevel hSecurityLevel;
595 bool setSecurityLevel = true;
Tobias Thierer5f5e43f2018-02-11 15:00:57 +0000596
Jeff Tinker41d279a2018-02-11 19:52:08 +0000597 switch(level) {
598 case DrmPlugin::kSecurityLevelSwSecureCrypto:
599 hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
600 break;
601 case DrmPlugin::kSecurityLevelSwSecureDecode:
602 hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
603 break;
604 case DrmPlugin::kSecurityLevelHwSecureCrypto:
605 hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
606 break;
607 case DrmPlugin::kSecurityLevelHwSecureDecode:
608 hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
609 break;
610 case DrmPlugin::kSecurityLevelHwSecureAll:
611 hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
612 break;
613 case DrmPlugin::kSecurityLevelMax:
614 setSecurityLevel = false;
615 break;
616 default:
617 return ERROR_DRM_CANNOT_HANDLE;
618 }
619
620 status_t err = UNKNOWN_ERROR;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800621 bool retry = true;
622 do {
623 hidl_vec<uint8_t> hSessionId;
624
Jeff Tinker41d279a2018-02-11 19:52:08 +0000625 Return<void> hResult;
626 if (mPluginV1_1 == NULL || !setSecurityLevel) {
627 hResult = mPlugin->openSession(
628 [&](Status status,const hidl_vec<uint8_t>& id) {
629 if (status == Status::OK) {
630 sessionId = toVector(id);
631 }
632 err = toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800633 }
Jeff Tinker41d279a2018-02-11 19:52:08 +0000634 );
635 } else {
636 hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
637 [&](Status status, const hidl_vec<uint8_t>& id) {
638 if (status == Status::OK) {
639 sessionId = toVector(id);
640 }
641 err = toStatusT(status);
642 }
643 );
644 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800645
646 if (!hResult.isOk()) {
647 err = DEAD_OBJECT;
648 }
649
650 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
651 mLock.unlock();
652 // reclaimSession may call back to closeSession, since mLock is
653 // shared between Drm instances, we should unlock here to avoid
654 // deadlock.
655 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
656 mLock.lock();
657 } else {
658 retry = false;
659 }
660 } while (retry);
661
662 if (err == OK) {
663 DrmSessionManager::Instance()->addSession(getCallingPid(),
664 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700665 mOpenSessions.push(sessionId);
Adam Stone568b3c42018-01-31 12:57:16 -0800666 mMetrics.SetSessionStart(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800667 }
Adam Stoneaaf87dd2018-01-08 11:55:06 -0800668
Adam Stonef0e618d2018-01-17 19:20:41 -0800669 mMetrics.mOpenSessionCounter.Increment(err);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800670 return err;
671}
672
673status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
674 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800675 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800676
Jeff Tinker319d5f42017-07-26 15:44:33 -0700677 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
678 if (status.isOk()) {
679 if (status == Status::OK) {
680 DrmSessionManager::Instance()->removeSession(sessionId);
681 for (size_t i = 0; i < mOpenSessions.size(); i++) {
682 if (mOpenSessions[i] == sessionId) {
683 mOpenSessions.removeAt(i);
684 break;
685 }
Jeff Tinker61332812017-05-15 16:53:10 -0700686 }
687 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800688 status_t response = toStatusT(status);
Adam Stone568b3c42018-01-31 12:57:16 -0800689 mMetrics.SetSessionEnd(sessionId);
Adam Stonecea91ce2018-01-22 19:23:28 -0800690 mMetrics.mCloseSessionCounter.Increment(response);
691 return response;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800692 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800693 mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
Jeff Tinker319d5f42017-07-26 15:44:33 -0700694 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800695}
696
697status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
698 Vector<uint8_t> const &initData, String8 const &mimeType,
699 DrmPlugin::KeyType keyType, KeyedVector<String8,
700 String8> const &optionalParameters, Vector<uint8_t> &request,
701 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
702 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800703 INIT_CHECK();
Adam Stonefb679e32018-02-07 10:25:48 -0800704 EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800705
706 DrmSessionManager::Instance()->useSession(sessionId);
707
708 KeyType hKeyType;
709 if (keyType == DrmPlugin::kKeyType_Streaming) {
710 hKeyType = KeyType::STREAMING;
711 } else if (keyType == DrmPlugin::kKeyType_Offline) {
712 hKeyType = KeyType::OFFLINE;
713 } else if (keyType == DrmPlugin::kKeyType_Release) {
714 hKeyType = KeyType::RELEASE;
715 } else {
Adam Stonef0e618d2018-01-17 19:20:41 -0800716 keyRequestTimer.SetAttribute(BAD_VALUE);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800717 return BAD_VALUE;
718 }
719
720 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
721
722 status_t err = UNKNOWN_ERROR;
723
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800724 if (mPluginV1_1 != NULL) {
725 Return<void> hResult =
726 mPluginV1_1->getKeyRequest_1_1(
727 toHidlVec(sessionId), toHidlVec(initData),
728 toHidlString(mimeType), hKeyType, hOptionalParameters,
729 [&](Status status, const hidl_vec<uint8_t>& hRequest,
730 drm::V1_1::KeyRequestType hKeyRequestType,
731 const hidl_string& hDefaultUrl) {
732
733 if (status == Status::OK) {
734 request = toVector(hRequest);
735 defaultUrl = toString8(hDefaultUrl);
736
737 switch (hKeyRequestType) {
738 case drm::V1_1::KeyRequestType::INITIAL:
739 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
740 break;
741 case drm::V1_1::KeyRequestType::RENEWAL:
742 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
743 break;
744 case drm::V1_1::KeyRequestType::RELEASE:
745 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
746 break;
747 case drm::V1_1::KeyRequestType::NONE:
748 *keyRequestType = DrmPlugin::kKeyRequestType_None;
749 break;
750 case drm::V1_1::KeyRequestType::UPDATE:
751 *keyRequestType = DrmPlugin::kKeyRequestType_Update;
752 break;
753 default:
754 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
755 break;
756 }
757 err = toStatusT(status);
758 }
759 });
760 return hResult.isOk() ? err : DEAD_OBJECT;
761 }
762
Jeff Tinkera53d6552017-01-20 00:31:46 -0800763 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
764 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
765 [&](Status status, const hidl_vec<uint8_t>& hRequest,
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800766 drm::V1_0::KeyRequestType hKeyRequestType,
767 const hidl_string& hDefaultUrl) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800768
769 if (status == Status::OK) {
770 request = toVector(hRequest);
771 defaultUrl = toString8(hDefaultUrl);
772
773 switch (hKeyRequestType) {
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800774 case drm::V1_0::KeyRequestType::INITIAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800775 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
776 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800777 case drm::V1_0::KeyRequestType::RENEWAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800778 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
779 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800780 case drm::V1_0::KeyRequestType::RELEASE:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800781 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
782 break;
783 default:
784 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
785 break;
786 }
787 err = toStatusT(status);
788 }
789 });
790
Adam Stonef0e618d2018-01-17 19:20:41 -0800791 err = hResult.isOk() ? err : DEAD_OBJECT;
792 keyRequestTimer.SetAttribute(err);
793 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800794}
795
796status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
797 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
798 Mutex::Autolock autoLock(mLock);
Adam Stonefb679e32018-02-07 10:25:48 -0800799 EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800800
Jeff Tinker6d998b62017-12-18 14:37:43 -0800801 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800802
803 DrmSessionManager::Instance()->useSession(sessionId);
804
805 status_t err = UNKNOWN_ERROR;
806
807 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
808 toHidlVec(response),
809 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
810 if (status == Status::OK) {
811 keySetId = toVector(hKeySetId);
812 }
813 err = toStatusT(status);
814 }
815 );
Adam Stonecea91ce2018-01-22 19:23:28 -0800816 err = hResult.isOk() ? err : DEAD_OBJECT;
817 keyResponseTimer.SetAttribute(err);
818 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800819}
820
821status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
822 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800823 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800824
Jeff Tinker58ad4752018-02-16 16:51:59 -0800825 Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
826 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800827}
828
829status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
830 Vector<uint8_t> const &keySetId) {
831 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800832 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800833
834 DrmSessionManager::Instance()->useSession(sessionId);
835
Jeff Tinker58ad4752018-02-16 16:51:59 -0800836 Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId),
837 toHidlVec(keySetId));
838 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800839}
840
841status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
842 KeyedVector<String8, String8> &infoMap) const {
843 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800844 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800845
846 DrmSessionManager::Instance()->useSession(sessionId);
847
848 ::KeyedVector hInfoMap;
849
850 status_t err = UNKNOWN_ERROR;
851
852 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
853 [&](Status status, const hidl_vec<KeyValue>& map) {
854 if (status == Status::OK) {
855 infoMap = toKeyedVector(map);
856 }
857 err = toStatusT(status);
858 }
859 );
860
861 return hResult.isOk() ? err : DEAD_OBJECT;
862}
863
864status_t DrmHal::getProvisionRequest(String8 const &certType,
865 String8 const &certAuthority, Vector<uint8_t> &request,
866 String8 &defaultUrl) {
867 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800868 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800869
870 status_t err = UNKNOWN_ERROR;
871
872 Return<void> hResult = mPlugin->getProvisionRequest(
873 toHidlString(certType), toHidlString(certAuthority),
874 [&](Status status, const hidl_vec<uint8_t>& hRequest,
875 const hidl_string& hDefaultUrl) {
876 if (status == Status::OK) {
877 request = toVector(hRequest);
878 defaultUrl = toString8(hDefaultUrl);
879 }
880 err = toStatusT(status);
881 }
882 );
883
Adam Stonecea91ce2018-01-22 19:23:28 -0800884 err = hResult.isOk() ? err : DEAD_OBJECT;
885 mMetrics.mGetProvisionRequestCounter.Increment(err);
886 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800887}
888
889status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800890 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800891 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800892 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800893
894 status_t err = UNKNOWN_ERROR;
895
896 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
897 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
898 const hidl_vec<uint8_t>& hWrappedKey) {
899 if (status == Status::OK) {
900 certificate = toVector(hCertificate);
901 wrappedKey = toVector(hWrappedKey);
902 }
903 err = toStatusT(status);
904 }
905 );
906
Adam Stonecea91ce2018-01-22 19:23:28 -0800907 err = hResult.isOk() ? err : DEAD_OBJECT;
908 mMetrics.mProvideProvisionResponseCounter.Increment(err);
909 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800910}
911
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800912status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800913 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800914 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800915
916 status_t err = UNKNOWN_ERROR;
917
918 Return<void> hResult = mPlugin->getSecureStops(
919 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
920 if (status == Status::OK) {
921 secureStops = toSecureStops(hSecureStops);
922 }
923 err = toStatusT(status);
924 }
925 );
926
927 return hResult.isOk() ? err : DEAD_OBJECT;
928}
929
930
Jeff Tinker15177d72018-01-25 12:57:55 -0800931status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
932 Mutex::Autolock autoLock(mLock);
933
934 if (mInitCheck != OK) {
935 return mInitCheck;
936 }
937
938 if (mPluginV1_1 == NULL) {
939 return ERROR_DRM_CANNOT_HANDLE;
940 }
941
942 status_t err = UNKNOWN_ERROR;
943
944 Return<void> hResult = mPluginV1_1->getSecureStopIds(
945 [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
946 if (status == Status::OK) {
947 secureStopIds = toSecureStopIds(hSecureStopIds);
948 }
949 err = toStatusT(status);
950 }
951 );
952
953 return hResult.isOk() ? err : DEAD_OBJECT;
954}
955
956
Jeff Tinkera53d6552017-01-20 00:31:46 -0800957status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
958 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800959 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800960
961 status_t err = UNKNOWN_ERROR;
962
963 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
964 [&](Status status, const SecureStop& hSecureStop) {
965 if (status == Status::OK) {
966 secureStop = toVector(hSecureStop.opaqueData);
967 }
968 err = toStatusT(status);
969 }
970 );
971
972 return hResult.isOk() ? err : DEAD_OBJECT;
973}
974
975status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
976 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800977 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800978
Jeff Tinker58ad4752018-02-16 16:51:59 -0800979 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -0800980 if (mPluginV1_1 != NULL) {
981 SecureStopRelease secureStopRelease;
982 secureStopRelease.opaqueData = toHidlVec(ssRelease);
Jeff Tinker58ad4752018-02-16 16:51:59 -0800983 status = mPluginV1_1->releaseSecureStops(secureStopRelease);
984 } else {
985 status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
Jeff Tinker15177d72018-01-25 12:57:55 -0800986 }
Jeff Tinker58ad4752018-02-16 16:51:59 -0800987 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800988}
989
Jeff Tinker15177d72018-01-25 12:57:55 -0800990status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
991 Mutex::Autolock autoLock(mLock);
992
993 if (mInitCheck != OK) {
994 return mInitCheck;
995 }
996
997 if (mPluginV1_1 == NULL) {
998 return ERROR_DRM_CANNOT_HANDLE;
999 }
1000
Jeff Tinker58ad4752018-02-16 16:51:59 -08001001 Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
1002 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinker15177d72018-01-25 12:57:55 -08001003}
1004
1005status_t DrmHal::removeAllSecureStops() {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001006 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001007 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001008
Jeff Tinker58ad4752018-02-16 16:51:59 -08001009 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -08001010 if (mPluginV1_1 != NULL) {
Jeff Tinker58ad4752018-02-16 16:51:59 -08001011 status = mPluginV1_1->removeAllSecureStops();
1012 } else {
1013 status = mPlugin->releaseAllSecureStops();
Jeff Tinker15177d72018-01-25 12:57:55 -08001014 }
Jeff Tinker58ad4752018-02-16 16:51:59 -08001015 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001016}
1017
Jeff Tinker6d998b62017-12-18 14:37:43 -08001018status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
1019 DrmPlugin::HdcpLevel *max) const {
1020 Mutex::Autolock autoLock(mLock);
1021 INIT_CHECK();
1022
1023 if (connected == NULL || max == NULL) {
1024 return BAD_VALUE;
1025 }
1026 status_t err = UNKNOWN_ERROR;
1027
1028 if (mPluginV1_1 == NULL) {
1029 return ERROR_DRM_CANNOT_HANDLE;
1030 }
1031
1032 *connected = DrmPlugin::kHdcpLevelUnknown;
1033 *max = DrmPlugin::kHdcpLevelUnknown;
1034
1035 Return<void> hResult = mPluginV1_1->getHdcpLevels(
1036 [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
1037 if (status == Status::OK) {
1038 *connected = toHdcpLevel(hConnected);
1039 *max = toHdcpLevel(hMax);
1040 }
1041 err = toStatusT(status);
1042 }
1043 );
1044
1045 return hResult.isOk() ? err : DEAD_OBJECT;
1046}
1047
1048status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
1049 Mutex::Autolock autoLock(mLock);
1050 INIT_CHECK();
1051
1052 if (open == NULL || max == NULL) {
1053 return BAD_VALUE;
1054 }
1055 status_t err = UNKNOWN_ERROR;
1056
1057 *open = 0;
1058 *max = 0;
1059
1060 if (mPluginV1_1 == NULL) {
1061 return ERROR_DRM_CANNOT_HANDLE;
1062 }
1063
1064 Return<void> hResult = mPluginV1_1->getNumberOfSessions(
1065 [&](Status status, uint32_t hOpen, uint32_t hMax) {
1066 if (status == Status::OK) {
1067 *open = hOpen;
1068 *max = hMax;
1069 }
1070 err = toStatusT(status);
1071 }
1072 );
1073
1074 return hResult.isOk() ? err : DEAD_OBJECT;
1075}
1076
1077status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
1078 DrmPlugin::SecurityLevel *level) const {
1079 Mutex::Autolock autoLock(mLock);
1080 INIT_CHECK();
1081
1082 if (level == NULL) {
1083 return BAD_VALUE;
1084 }
1085 status_t err = UNKNOWN_ERROR;
1086
1087 if (mPluginV1_1 == NULL) {
1088 return ERROR_DRM_CANNOT_HANDLE;
1089 }
1090
1091 *level = DrmPlugin::kSecurityLevelUnknown;
1092
1093 Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
1094 [&](Status status, SecurityLevel hLevel) {
1095 if (status == Status::OK) {
1096 *level = toSecurityLevel(hLevel);
1097 }
1098 err = toStatusT(status);
1099 }
1100 );
1101
1102 return hResult.isOk() ? err : DEAD_OBJECT;
1103}
1104
Jeff Tinkerc8baaba2018-10-23 11:32:36 -07001105status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const {
1106 Mutex::Autolock autoLock(mLock);
1107
1108 if (mInitCheck != OK) {
1109 return mInitCheck;
1110 }
1111
1112 if (mPluginV1_2 == NULL) {
1113 return ERROR_DRM_CANNOT_HANDLE;
1114 }
1115
1116 status_t err = UNKNOWN_ERROR;
1117
1118 Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
1119 [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
1120 if (status == Status::OK) {
1121 keySetIds = toKeySetIds(hKeySetIds);
1122 }
1123 err = toStatusT(status);
1124 }
1125 );
1126
1127 return hResult.isOk() ? err : DEAD_OBJECT;
1128}
1129
1130status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const &keySetId) {
1131 Mutex::Autolock autoLock(mLock);
1132
1133 if (mInitCheck != OK) {
1134 return mInitCheck;
1135 }
1136
1137 if (mPluginV1_2 == NULL) {
1138 return ERROR_DRM_CANNOT_HANDLE;
1139 }
1140
1141 Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
1142 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
1143}
1144
1145status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const &keySetId,
1146 DrmPlugin::OfflineLicenseState *licenseState) const {
1147 Mutex::Autolock autoLock(mLock);
1148
1149 if (mInitCheck != OK) {
1150 return mInitCheck;
1151 }
1152
1153 if (mPluginV1_2 == NULL) {
1154 return ERROR_DRM_CANNOT_HANDLE;
1155 }
1156 *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
1157
1158 status_t err = UNKNOWN_ERROR;
1159
1160 Return<void> hResult = mPluginV1_2->getOfflineLicenseState(toHidlVec(keySetId),
1161 [&](Status status, OfflineLicenseState hLicenseState) {
1162 if (status == Status::OK) {
1163 *licenseState = toOfflineLicenseState(hLicenseState);
1164 }
1165 err = toStatusT(status);
1166 }
1167 );
1168
1169 return hResult.isOk() ? err : DEAD_OBJECT;
1170}
1171
Jeff Tinkera53d6552017-01-20 00:31:46 -08001172status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
1173 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001174 return getPropertyStringInternal(name, value);
1175}
1176
1177status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
1178 // This function is internal to the class and should only be called while
1179 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001180 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001181
1182 status_t err = UNKNOWN_ERROR;
1183
1184 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
1185 [&](Status status, const hidl_string& hValue) {
1186 if (status == Status::OK) {
1187 value = toString8(hValue);
1188 }
1189 err = toStatusT(status);
1190 }
1191 );
1192
1193 return hResult.isOk() ? err : DEAD_OBJECT;
1194}
1195
1196status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
1197 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001198 return getPropertyByteArrayInternal(name, value);
1199}
1200
1201status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
1202 // This function is internal to the class and should only be called while
1203 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001204 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001205
1206 status_t err = UNKNOWN_ERROR;
1207
1208 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
1209 [&](Status status, const hidl_vec<uint8_t>& hValue) {
1210 if (status == Status::OK) {
1211 value = toVector(hValue);
1212 }
1213 err = toStatusT(status);
1214 }
1215 );
1216
Adam Stonecea91ce2018-01-22 19:23:28 -08001217 err = hResult.isOk() ? err : DEAD_OBJECT;
1218 if (name == kPropertyDeviceUniqueId) {
1219 mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
1220 }
1221 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001222}
1223
1224status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
1225 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001226 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001227
Jeff Tinker58ad4752018-02-16 16:51:59 -08001228 Return<Status> status = mPlugin->setPropertyString(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001229 toHidlString(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001230 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001231}
1232
1233status_t DrmHal::setPropertyByteArray(String8 const &name,
1234 Vector<uint8_t> const &value ) const {
1235 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001236 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001237
Jeff Tinker58ad4752018-02-16 16:51:59 -08001238 Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001239 toHidlVec(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001240 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001241}
1242
Adam Stone28f27c32018-02-05 15:07:48 -08001243status_t DrmHal::getMetrics(PersistableBundle* metrics) {
1244 if (metrics == nullptr) {
1245 return UNEXPECTED_NULL;
1246 }
1247 mMetrics.Export(metrics);
1248
1249 // Append vendor metrics if they are supported.
1250 if (mPluginV1_1 != NULL) {
1251 String8 vendor;
1252 String8 description;
1253 if (getPropertyStringInternal(String8("vendor"), vendor) != OK
1254 || vendor.isEmpty()) {
1255 ALOGE("Get vendor failed or is empty");
1256 vendor = "NONE";
1257 }
1258 if (getPropertyStringInternal(String8("description"), description) != OK
1259 || description.isEmpty()) {
1260 ALOGE("Get description failed or is empty.");
1261 description = "NONE";
1262 }
1263 vendor += ".";
1264 vendor += description;
1265
1266 hidl_vec<DrmMetricGroup> pluginMetrics;
1267 status_t err = UNKNOWN_ERROR;
1268
1269 Return<void> status = mPluginV1_1->getMetrics(
1270 [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
1271 if (status != Status::OK) {
1272 ALOGV("Error getting plugin metrics: %d", status);
1273 } else {
1274 PersistableBundle pluginBundle;
1275 if (MediaDrmMetrics::HidlMetricsToBundle(
1276 pluginMetrics, &pluginBundle) == OK) {
1277 metrics->putPersistableBundle(String16(vendor), pluginBundle);
1278 }
1279 }
1280 err = toStatusT(status);
1281 });
1282 return status.isOk() ? err : DEAD_OBJECT;
Adam Stonef0e618d2018-01-17 19:20:41 -08001283 }
1284
Adam Stoneab394d12017-12-22 12:34:20 -08001285 return OK;
1286}
Jeff Tinkera53d6552017-01-20 00:31:46 -08001287
1288status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
1289 String8 const &algorithm) {
1290 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001291 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001292
1293 DrmSessionManager::Instance()->useSession(sessionId);
1294
Jeff Tinkere6412942018-04-30 17:35:16 -07001295 Return<Status> status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001296 toHidlString(algorithm));
Jeff Tinkere6412942018-04-30 17:35:16 -07001297 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001298}
1299
1300status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
1301 String8 const &algorithm) {
1302 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001303 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001304
1305 DrmSessionManager::Instance()->useSession(sessionId);
1306
Jeff Tinkere6412942018-04-30 17:35:16 -07001307 Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001308 toHidlString(algorithm));
Jeff Tinkere6412942018-04-30 17:35:16 -07001309 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001310}
1311
1312status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001313 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1314 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001315 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001316 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001317
1318 DrmSessionManager::Instance()->useSession(sessionId);
1319
1320 status_t err = UNKNOWN_ERROR;
1321
1322 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
1323 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1324 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1325 if (status == Status::OK) {
1326 output = toVector(hOutput);
1327 }
1328 err = toStatusT(status);
1329 }
1330 );
1331
1332 return hResult.isOk() ? err : DEAD_OBJECT;
1333}
1334
1335status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001336 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1337 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001338 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001339 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001340
1341 DrmSessionManager::Instance()->useSession(sessionId);
1342
1343 status_t err = UNKNOWN_ERROR;
1344
1345 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
1346 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1347 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1348 if (status == Status::OK) {
1349 output = toVector(hOutput);
1350 }
1351 err = toStatusT(status);
1352 }
1353 );
1354
1355 return hResult.isOk() ? err : DEAD_OBJECT;
1356}
1357
1358status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001359 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1360 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001361 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001362 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001363
1364 DrmSessionManager::Instance()->useSession(sessionId);
1365
1366 status_t err = UNKNOWN_ERROR;
1367
1368 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
1369 toHidlVec(keyId), toHidlVec(message),
1370 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1371 if (status == Status::OK) {
1372 signature = toVector(hSignature);
1373 }
1374 err = toStatusT(status);
1375 }
1376 );
1377
1378 return hResult.isOk() ? err : DEAD_OBJECT;
1379}
1380
1381status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001382 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1383 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001384 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001385 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001386
1387 DrmSessionManager::Instance()->useSession(sessionId);
1388
1389 status_t err = UNKNOWN_ERROR;
1390
1391 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
1392 toHidlVec(message), toHidlVec(signature),
1393 [&](Status status, bool hMatch) {
1394 if (status == Status::OK) {
1395 match = hMatch;
1396 } else {
1397 match = false;
1398 }
1399 err = toStatusT(status);
1400 }
1401 );
1402
1403 return hResult.isOk() ? err : DEAD_OBJECT;
1404}
1405
1406status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001407 String8 const &algorithm, Vector<uint8_t> const &message,
1408 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001409 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001410 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001411
1412 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
1413 return -EPERM;
1414 }
1415
1416 DrmSessionManager::Instance()->useSession(sessionId);
1417
1418 status_t err = UNKNOWN_ERROR;
1419
1420 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1421 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1422 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1423 if (status == Status::OK) {
1424 signature = toVector(hSignature);
1425 }
1426 err = toStatusT(status);
1427 }
1428 );
1429
1430 return hResult.isOk() ? err : DEAD_OBJECT;
1431}
1432
1433void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1434{
Jeff Tinker7dfe28f2018-02-15 12:17:40 -08001435 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001436}
1437
1438void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1439{
1440 if (vec.size()) {
1441 obj.writeInt32(vec.size());
1442 obj.write(vec.data(), vec.size());
1443 } else {
1444 obj.writeInt32(0);
1445 }
1446}
1447
Adam Stonefb679e32018-02-07 10:25:48 -08001448void DrmHal::reportFrameworkMetrics() const
1449{
1450 MediaAnalyticsItem item("mediadrm");
1451 item.generateSessionID();
1452 item.setPkgName(mMetrics.GetAppPackageName().c_str());
1453 String8 vendor;
1454 String8 description;
1455 status_t result = getPropertyStringInternal(String8("vendor"), vendor);
1456 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001457 ALOGE("Failed to get vendor from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001458 } else {
1459 item.setCString("vendor", vendor.c_str());
1460 }
1461 result = getPropertyStringInternal(String8("description"), description);
1462 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001463 ALOGE("Failed to get description from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001464 } else {
1465 item.setCString("description", description.c_str());
1466 }
Adam Stoneab394d12017-12-22 12:34:20 -08001467
Adam Stonefb679e32018-02-07 10:25:48 -08001468 std::string serializedMetrics;
1469 result = mMetrics.GetSerializedMetrics(&serializedMetrics);
1470 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001471 ALOGE("Failed to serialize framework metrics: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001472 }
Adam Stone32494f52018-02-26 22:53:27 -08001473 std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
1474 serializedMetrics.size());
1475 if (!b64EncodedMetrics.empty()) {
1476 item.setCString("serialized_metrics", b64EncodedMetrics.c_str());
Adam Stonefb679e32018-02-07 10:25:48 -08001477 }
1478 if (!item.selfrecord()) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001479 ALOGE("Failed to self record framework metrics");
Adam Stonefb679e32018-02-07 10:25:48 -08001480 }
1481}
1482
1483void DrmHal::reportPluginMetrics() const
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001484{
Adam Stone32494f52018-02-26 22:53:27 -08001485 Vector<uint8_t> metricsVector;
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001486 String8 vendor;
1487 String8 description;
1488 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1489 getPropertyStringInternal(String8("description"), description) == OK &&
Adam Stone32494f52018-02-26 22:53:27 -08001490 getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
1491 std::string metricsString = toBase64StringNoPad(metricsVector.array(),
1492 metricsVector.size());
1493 status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
1494 description, mAppPackageName);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001495 if (res != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001496 ALOGE("Metrics were retrieved but could not be reported: %d", res);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001497 }
1498 }
1499}
1500
Jeff Tinkera53d6552017-01-20 00:31:46 -08001501} // namespace android