blob: 14ff49356e04c75239b8a3cd0de45db7480d8c05 [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>
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;
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
Jeff Tinker593111f2017-05-25 16:00:21 -0700336 auto manager = hardware::defaultServiceManager();
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800337
338 if (manager != NULL) {
Jeff Tinkere307dc42018-02-11 19:53:54 +0000339 manager->listByInterface(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 );
349 manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
350 [&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
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800556 for (size_t i = 0; i < mFactories.size(); i++) {
557 if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
558 mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
Edwin Wong5641aa22018-01-30 17:52:21 -0800559 if (mPlugin != NULL) {
560 mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
Jeff Tinkerc8baaba2018-10-23 11:32:36 -0700561 mPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mPlugin);
Edwin Wong5641aa22018-01-30 17:52:21 -0800562 }
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800563 }
564 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800565
566 if (mPlugin == NULL) {
567 mInitCheck = ERROR_UNSUPPORTED;
568 } else {
Jeff Tinker319d5f42017-07-26 15:44:33 -0700569 if (!mPlugin->setListener(this).isOk()) {
570 mInitCheck = DEAD_OBJECT;
571 } else {
572 mInitCheck = OK;
573 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800574 }
575
576 return mInitCheck;
577}
578
579status_t DrmHal::destroyPlugin() {
Jeff Tinker7dfe28f2018-02-15 12:17:40 -0800580 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800581 return OK;
582}
583
Jeff Tinker41d279a2018-02-11 19:52:08 +0000584status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
585 Vector<uint8_t> &sessionId) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800586 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800587 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800588
Jeff Tinker41d279a2018-02-11 19:52:08 +0000589 SecurityLevel hSecurityLevel;
590 bool setSecurityLevel = true;
Tobias Thierer5f5e43f2018-02-11 15:00:57 +0000591
Jeff Tinker41d279a2018-02-11 19:52:08 +0000592 switch(level) {
593 case DrmPlugin::kSecurityLevelSwSecureCrypto:
594 hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
595 break;
596 case DrmPlugin::kSecurityLevelSwSecureDecode:
597 hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
598 break;
599 case DrmPlugin::kSecurityLevelHwSecureCrypto:
600 hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
601 break;
602 case DrmPlugin::kSecurityLevelHwSecureDecode:
603 hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
604 break;
605 case DrmPlugin::kSecurityLevelHwSecureAll:
606 hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
607 break;
608 case DrmPlugin::kSecurityLevelMax:
609 setSecurityLevel = false;
610 break;
611 default:
612 return ERROR_DRM_CANNOT_HANDLE;
613 }
614
615 status_t err = UNKNOWN_ERROR;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800616 bool retry = true;
617 do {
618 hidl_vec<uint8_t> hSessionId;
619
Jeff Tinker41d279a2018-02-11 19:52:08 +0000620 Return<void> hResult;
621 if (mPluginV1_1 == NULL || !setSecurityLevel) {
622 hResult = mPlugin->openSession(
623 [&](Status status,const hidl_vec<uint8_t>& id) {
624 if (status == Status::OK) {
625 sessionId = toVector(id);
626 }
627 err = toStatusT(status);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800628 }
Jeff Tinker41d279a2018-02-11 19:52:08 +0000629 );
630 } else {
631 hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
632 [&](Status status, const hidl_vec<uint8_t>& id) {
633 if (status == Status::OK) {
634 sessionId = toVector(id);
635 }
636 err = toStatusT(status);
637 }
638 );
639 }
Jeff Tinkera53d6552017-01-20 00:31:46 -0800640
641 if (!hResult.isOk()) {
642 err = DEAD_OBJECT;
643 }
644
645 if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
646 mLock.unlock();
647 // reclaimSession may call back to closeSession, since mLock is
648 // shared between Drm instances, we should unlock here to avoid
649 // deadlock.
650 retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
651 mLock.lock();
652 } else {
653 retry = false;
654 }
655 } while (retry);
656
657 if (err == OK) {
658 DrmSessionManager::Instance()->addSession(getCallingPid(),
659 mDrmSessionClient, sessionId);
Jeff Tinker61332812017-05-15 16:53:10 -0700660 mOpenSessions.push(sessionId);
Adam Stone568b3c42018-01-31 12:57:16 -0800661 mMetrics.SetSessionStart(sessionId);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800662 }
Adam Stoneaaf87dd2018-01-08 11:55:06 -0800663
Adam Stonef0e618d2018-01-17 19:20:41 -0800664 mMetrics.mOpenSessionCounter.Increment(err);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800665 return err;
666}
667
668status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
669 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800670 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800671
Jeff Tinker319d5f42017-07-26 15:44:33 -0700672 Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
673 if (status.isOk()) {
674 if (status == Status::OK) {
675 DrmSessionManager::Instance()->removeSession(sessionId);
676 for (size_t i = 0; i < mOpenSessions.size(); i++) {
677 if (mOpenSessions[i] == sessionId) {
678 mOpenSessions.removeAt(i);
679 break;
680 }
Jeff Tinker61332812017-05-15 16:53:10 -0700681 }
682 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800683 status_t response = toStatusT(status);
Adam Stone568b3c42018-01-31 12:57:16 -0800684 mMetrics.SetSessionEnd(sessionId);
Adam Stonecea91ce2018-01-22 19:23:28 -0800685 mMetrics.mCloseSessionCounter.Increment(response);
686 return response;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800687 }
Adam Stonecea91ce2018-01-22 19:23:28 -0800688 mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
Jeff Tinker319d5f42017-07-26 15:44:33 -0700689 return DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800690}
691
692status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
693 Vector<uint8_t> const &initData, String8 const &mimeType,
694 DrmPlugin::KeyType keyType, KeyedVector<String8,
695 String8> const &optionalParameters, Vector<uint8_t> &request,
696 String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
697 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800698 INIT_CHECK();
Adam Stonefb679e32018-02-07 10:25:48 -0800699 EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800700
701 DrmSessionManager::Instance()->useSession(sessionId);
702
703 KeyType hKeyType;
704 if (keyType == DrmPlugin::kKeyType_Streaming) {
705 hKeyType = KeyType::STREAMING;
706 } else if (keyType == DrmPlugin::kKeyType_Offline) {
707 hKeyType = KeyType::OFFLINE;
708 } else if (keyType == DrmPlugin::kKeyType_Release) {
709 hKeyType = KeyType::RELEASE;
710 } else {
Adam Stonef0e618d2018-01-17 19:20:41 -0800711 keyRequestTimer.SetAttribute(BAD_VALUE);
Jeff Tinkera53d6552017-01-20 00:31:46 -0800712 return BAD_VALUE;
713 }
714
715 ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
716
717 status_t err = UNKNOWN_ERROR;
718
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800719 if (mPluginV1_1 != NULL) {
720 Return<void> hResult =
721 mPluginV1_1->getKeyRequest_1_1(
722 toHidlVec(sessionId), toHidlVec(initData),
723 toHidlString(mimeType), hKeyType, hOptionalParameters,
724 [&](Status status, const hidl_vec<uint8_t>& hRequest,
725 drm::V1_1::KeyRequestType hKeyRequestType,
726 const hidl_string& hDefaultUrl) {
727
728 if (status == Status::OK) {
729 request = toVector(hRequest);
730 defaultUrl = toString8(hDefaultUrl);
731
732 switch (hKeyRequestType) {
733 case drm::V1_1::KeyRequestType::INITIAL:
734 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
735 break;
736 case drm::V1_1::KeyRequestType::RENEWAL:
737 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
738 break;
739 case drm::V1_1::KeyRequestType::RELEASE:
740 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
741 break;
742 case drm::V1_1::KeyRequestType::NONE:
743 *keyRequestType = DrmPlugin::kKeyRequestType_None;
744 break;
745 case drm::V1_1::KeyRequestType::UPDATE:
746 *keyRequestType = DrmPlugin::kKeyRequestType_Update;
747 break;
748 default:
749 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
750 break;
751 }
752 err = toStatusT(status);
753 }
754 });
755 return hResult.isOk() ? err : DEAD_OBJECT;
756 }
757
Jeff Tinkera53d6552017-01-20 00:31:46 -0800758 Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
759 toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
760 [&](Status status, const hidl_vec<uint8_t>& hRequest,
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800761 drm::V1_0::KeyRequestType hKeyRequestType,
762 const hidl_string& hDefaultUrl) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800763
764 if (status == Status::OK) {
765 request = toVector(hRequest);
766 defaultUrl = toString8(hDefaultUrl);
767
768 switch (hKeyRequestType) {
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800769 case drm::V1_0::KeyRequestType::INITIAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800770 *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
771 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800772 case drm::V1_0::KeyRequestType::RENEWAL:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800773 *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
774 break;
Rahul Frias59bc3fa2018-01-22 23:48:52 -0800775 case drm::V1_0::KeyRequestType::RELEASE:
Jeff Tinkera53d6552017-01-20 00:31:46 -0800776 *keyRequestType = DrmPlugin::kKeyRequestType_Release;
777 break;
778 default:
779 *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
780 break;
781 }
782 err = toStatusT(status);
783 }
784 });
785
Adam Stonef0e618d2018-01-17 19:20:41 -0800786 err = hResult.isOk() ? err : DEAD_OBJECT;
787 keyRequestTimer.SetAttribute(err);
788 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800789}
790
791status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
792 Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
793 Mutex::Autolock autoLock(mLock);
Adam Stonefb679e32018-02-07 10:25:48 -0800794 EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
Adam Stonecea91ce2018-01-22 19:23:28 -0800795
Jeff Tinker6d998b62017-12-18 14:37:43 -0800796 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800797
798 DrmSessionManager::Instance()->useSession(sessionId);
799
800 status_t err = UNKNOWN_ERROR;
801
802 Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
803 toHidlVec(response),
804 [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
805 if (status == Status::OK) {
806 keySetId = toVector(hKeySetId);
807 }
808 err = toStatusT(status);
809 }
810 );
Adam Stonecea91ce2018-01-22 19:23:28 -0800811 err = hResult.isOk() ? err : DEAD_OBJECT;
812 keyResponseTimer.SetAttribute(err);
813 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800814}
815
816status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
817 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800818 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800819
Jeff Tinker58ad4752018-02-16 16:51:59 -0800820 Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
821 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800822}
823
824status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
825 Vector<uint8_t> const &keySetId) {
826 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800827 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800828
829 DrmSessionManager::Instance()->useSession(sessionId);
830
Jeff Tinker58ad4752018-02-16 16:51:59 -0800831 Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId),
832 toHidlVec(keySetId));
833 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800834}
835
836status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
837 KeyedVector<String8, String8> &infoMap) const {
838 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800839 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800840
841 DrmSessionManager::Instance()->useSession(sessionId);
842
843 ::KeyedVector hInfoMap;
844
845 status_t err = UNKNOWN_ERROR;
846
847 Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
848 [&](Status status, const hidl_vec<KeyValue>& map) {
849 if (status == Status::OK) {
850 infoMap = toKeyedVector(map);
851 }
852 err = toStatusT(status);
853 }
854 );
855
856 return hResult.isOk() ? err : DEAD_OBJECT;
857}
858
859status_t DrmHal::getProvisionRequest(String8 const &certType,
860 String8 const &certAuthority, Vector<uint8_t> &request,
861 String8 &defaultUrl) {
862 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800863 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800864
865 status_t err = UNKNOWN_ERROR;
866
867 Return<void> hResult = mPlugin->getProvisionRequest(
868 toHidlString(certType), toHidlString(certAuthority),
869 [&](Status status, const hidl_vec<uint8_t>& hRequest,
870 const hidl_string& hDefaultUrl) {
871 if (status == Status::OK) {
872 request = toVector(hRequest);
873 defaultUrl = toString8(hDefaultUrl);
874 }
875 err = toStatusT(status);
876 }
877 );
878
Adam Stonecea91ce2018-01-22 19:23:28 -0800879 err = hResult.isOk() ? err : DEAD_OBJECT;
880 mMetrics.mGetProvisionRequestCounter.Increment(err);
881 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800882}
883
884status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
Edwin Wong68b3d9f2017-01-06 19:07:54 -0800885 Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800886 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800887 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800888
889 status_t err = UNKNOWN_ERROR;
890
891 Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
892 [&](Status status, const hidl_vec<uint8_t>& hCertificate,
893 const hidl_vec<uint8_t>& hWrappedKey) {
894 if (status == Status::OK) {
895 certificate = toVector(hCertificate);
896 wrappedKey = toVector(hWrappedKey);
897 }
898 err = toStatusT(status);
899 }
900 );
901
Adam Stonecea91ce2018-01-22 19:23:28 -0800902 err = hResult.isOk() ? err : DEAD_OBJECT;
903 mMetrics.mProvideProvisionResponseCounter.Increment(err);
904 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800905}
906
Jeff Tinkerabeb36a2017-02-17 09:42:46 -0800907status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
Jeff Tinkera53d6552017-01-20 00:31:46 -0800908 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800909 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800910
911 status_t err = UNKNOWN_ERROR;
912
913 Return<void> hResult = mPlugin->getSecureStops(
914 [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
915 if (status == Status::OK) {
916 secureStops = toSecureStops(hSecureStops);
917 }
918 err = toStatusT(status);
919 }
920 );
921
922 return hResult.isOk() ? err : DEAD_OBJECT;
923}
924
925
Jeff Tinker15177d72018-01-25 12:57:55 -0800926status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
927 Mutex::Autolock autoLock(mLock);
928
929 if (mInitCheck != OK) {
930 return mInitCheck;
931 }
932
933 if (mPluginV1_1 == NULL) {
934 return ERROR_DRM_CANNOT_HANDLE;
935 }
936
937 status_t err = UNKNOWN_ERROR;
938
939 Return<void> hResult = mPluginV1_1->getSecureStopIds(
940 [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
941 if (status == Status::OK) {
942 secureStopIds = toSecureStopIds(hSecureStopIds);
943 }
944 err = toStatusT(status);
945 }
946 );
947
948 return hResult.isOk() ? err : DEAD_OBJECT;
949}
950
951
Jeff Tinkera53d6552017-01-20 00:31:46 -0800952status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
953 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800954 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800955
956 status_t err = UNKNOWN_ERROR;
957
958 Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
959 [&](Status status, const SecureStop& hSecureStop) {
960 if (status == Status::OK) {
961 secureStop = toVector(hSecureStop.opaqueData);
962 }
963 err = toStatusT(status);
964 }
965 );
966
967 return hResult.isOk() ? err : DEAD_OBJECT;
968}
969
970status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
971 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -0800972 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -0800973
Jeff Tinker58ad4752018-02-16 16:51:59 -0800974 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -0800975 if (mPluginV1_1 != NULL) {
976 SecureStopRelease secureStopRelease;
977 secureStopRelease.opaqueData = toHidlVec(ssRelease);
Jeff Tinker58ad4752018-02-16 16:51:59 -0800978 status = mPluginV1_1->releaseSecureStops(secureStopRelease);
979 } else {
980 status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
Jeff Tinker15177d72018-01-25 12:57:55 -0800981 }
Jeff Tinker58ad4752018-02-16 16:51:59 -0800982 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -0800983}
984
Jeff Tinker15177d72018-01-25 12:57:55 -0800985status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
986 Mutex::Autolock autoLock(mLock);
987
988 if (mInitCheck != OK) {
989 return mInitCheck;
990 }
991
992 if (mPluginV1_1 == NULL) {
993 return ERROR_DRM_CANNOT_HANDLE;
994 }
995
Jeff Tinker58ad4752018-02-16 16:51:59 -0800996 Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
997 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinker15177d72018-01-25 12:57:55 -0800998}
999
1000status_t DrmHal::removeAllSecureStops() {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001001 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001002 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001003
Jeff Tinker58ad4752018-02-16 16:51:59 -08001004 Return<Status> status(Status::ERROR_DRM_UNKNOWN);
Jeff Tinker15177d72018-01-25 12:57:55 -08001005 if (mPluginV1_1 != NULL) {
Jeff Tinker58ad4752018-02-16 16:51:59 -08001006 status = mPluginV1_1->removeAllSecureStops();
1007 } else {
1008 status = mPlugin->releaseAllSecureStops();
Jeff Tinker15177d72018-01-25 12:57:55 -08001009 }
Jeff Tinker58ad4752018-02-16 16:51:59 -08001010 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001011}
1012
Jeff Tinker6d998b62017-12-18 14:37:43 -08001013status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
1014 DrmPlugin::HdcpLevel *max) const {
1015 Mutex::Autolock autoLock(mLock);
1016 INIT_CHECK();
1017
1018 if (connected == NULL || max == NULL) {
1019 return BAD_VALUE;
1020 }
1021 status_t err = UNKNOWN_ERROR;
1022
1023 if (mPluginV1_1 == NULL) {
1024 return ERROR_DRM_CANNOT_HANDLE;
1025 }
1026
1027 *connected = DrmPlugin::kHdcpLevelUnknown;
1028 *max = DrmPlugin::kHdcpLevelUnknown;
1029
1030 Return<void> hResult = mPluginV1_1->getHdcpLevels(
1031 [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
1032 if (status == Status::OK) {
1033 *connected = toHdcpLevel(hConnected);
1034 *max = toHdcpLevel(hMax);
1035 }
1036 err = toStatusT(status);
1037 }
1038 );
1039
1040 return hResult.isOk() ? err : DEAD_OBJECT;
1041}
1042
1043status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
1044 Mutex::Autolock autoLock(mLock);
1045 INIT_CHECK();
1046
1047 if (open == NULL || max == NULL) {
1048 return BAD_VALUE;
1049 }
1050 status_t err = UNKNOWN_ERROR;
1051
1052 *open = 0;
1053 *max = 0;
1054
1055 if (mPluginV1_1 == NULL) {
1056 return ERROR_DRM_CANNOT_HANDLE;
1057 }
1058
1059 Return<void> hResult = mPluginV1_1->getNumberOfSessions(
1060 [&](Status status, uint32_t hOpen, uint32_t hMax) {
1061 if (status == Status::OK) {
1062 *open = hOpen;
1063 *max = hMax;
1064 }
1065 err = toStatusT(status);
1066 }
1067 );
1068
1069 return hResult.isOk() ? err : DEAD_OBJECT;
1070}
1071
1072status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
1073 DrmPlugin::SecurityLevel *level) const {
1074 Mutex::Autolock autoLock(mLock);
1075 INIT_CHECK();
1076
1077 if (level == NULL) {
1078 return BAD_VALUE;
1079 }
1080 status_t err = UNKNOWN_ERROR;
1081
1082 if (mPluginV1_1 == NULL) {
1083 return ERROR_DRM_CANNOT_HANDLE;
1084 }
1085
1086 *level = DrmPlugin::kSecurityLevelUnknown;
1087
1088 Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
1089 [&](Status status, SecurityLevel hLevel) {
1090 if (status == Status::OK) {
1091 *level = toSecurityLevel(hLevel);
1092 }
1093 err = toStatusT(status);
1094 }
1095 );
1096
1097 return hResult.isOk() ? err : DEAD_OBJECT;
1098}
1099
Jeff Tinkerc8baaba2018-10-23 11:32:36 -07001100status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const {
1101 Mutex::Autolock autoLock(mLock);
1102
1103 if (mInitCheck != OK) {
1104 return mInitCheck;
1105 }
1106
1107 if (mPluginV1_2 == NULL) {
1108 return ERROR_DRM_CANNOT_HANDLE;
1109 }
1110
1111 status_t err = UNKNOWN_ERROR;
1112
1113 Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
1114 [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
1115 if (status == Status::OK) {
1116 keySetIds = toKeySetIds(hKeySetIds);
1117 }
1118 err = toStatusT(status);
1119 }
1120 );
1121
1122 return hResult.isOk() ? err : DEAD_OBJECT;
1123}
1124
1125status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const &keySetId) {
1126 Mutex::Autolock autoLock(mLock);
1127
1128 if (mInitCheck != OK) {
1129 return mInitCheck;
1130 }
1131
1132 if (mPluginV1_2 == NULL) {
1133 return ERROR_DRM_CANNOT_HANDLE;
1134 }
1135
1136 Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
1137 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
1138}
1139
1140status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const &keySetId,
1141 DrmPlugin::OfflineLicenseState *licenseState) const {
1142 Mutex::Autolock autoLock(mLock);
1143
1144 if (mInitCheck != OK) {
1145 return mInitCheck;
1146 }
1147
1148 if (mPluginV1_2 == NULL) {
1149 return ERROR_DRM_CANNOT_HANDLE;
1150 }
1151 *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
1152
1153 status_t err = UNKNOWN_ERROR;
1154
1155 Return<void> hResult = mPluginV1_2->getOfflineLicenseState(toHidlVec(keySetId),
1156 [&](Status status, OfflineLicenseState hLicenseState) {
1157 if (status == Status::OK) {
1158 *licenseState = toOfflineLicenseState(hLicenseState);
1159 }
1160 err = toStatusT(status);
1161 }
1162 );
1163
1164 return hResult.isOk() ? err : DEAD_OBJECT;
1165}
1166
Jeff Tinkera53d6552017-01-20 00:31:46 -08001167status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
1168 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001169 return getPropertyStringInternal(name, value);
1170}
1171
1172status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
1173 // This function is internal to the class and should only be called while
1174 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001175 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001176
1177 status_t err = UNKNOWN_ERROR;
1178
1179 Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
1180 [&](Status status, const hidl_string& hValue) {
1181 if (status == Status::OK) {
1182 value = toString8(hValue);
1183 }
1184 err = toStatusT(status);
1185 }
1186 );
1187
1188 return hResult.isOk() ? err : DEAD_OBJECT;
1189}
1190
1191status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
1192 Mutex::Autolock autoLock(mLock);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001193 return getPropertyByteArrayInternal(name, value);
1194}
1195
1196status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
1197 // This function is internal to the class and should only be called while
1198 // mLock is already held.
Jeff Tinker6d998b62017-12-18 14:37:43 -08001199 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001200
1201 status_t err = UNKNOWN_ERROR;
1202
1203 Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
1204 [&](Status status, const hidl_vec<uint8_t>& hValue) {
1205 if (status == Status::OK) {
1206 value = toVector(hValue);
1207 }
1208 err = toStatusT(status);
1209 }
1210 );
1211
Adam Stonecea91ce2018-01-22 19:23:28 -08001212 err = hResult.isOk() ? err : DEAD_OBJECT;
1213 if (name == kPropertyDeviceUniqueId) {
1214 mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
1215 }
1216 return err;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001217}
1218
1219status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
1220 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001221 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001222
Jeff Tinker58ad4752018-02-16 16:51:59 -08001223 Return<Status> status = mPlugin->setPropertyString(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001224 toHidlString(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001225 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001226}
1227
1228status_t DrmHal::setPropertyByteArray(String8 const &name,
1229 Vector<uint8_t> const &value ) const {
1230 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001231 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001232
Jeff Tinker58ad4752018-02-16 16:51:59 -08001233 Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001234 toHidlVec(value));
Jeff Tinker58ad4752018-02-16 16:51:59 -08001235 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001236}
1237
Adam Stone28f27c32018-02-05 15:07:48 -08001238status_t DrmHal::getMetrics(PersistableBundle* metrics) {
1239 if (metrics == nullptr) {
1240 return UNEXPECTED_NULL;
1241 }
1242 mMetrics.Export(metrics);
1243
1244 // Append vendor metrics if they are supported.
1245 if (mPluginV1_1 != NULL) {
1246 String8 vendor;
1247 String8 description;
1248 if (getPropertyStringInternal(String8("vendor"), vendor) != OK
1249 || vendor.isEmpty()) {
1250 ALOGE("Get vendor failed or is empty");
1251 vendor = "NONE";
1252 }
1253 if (getPropertyStringInternal(String8("description"), description) != OK
1254 || description.isEmpty()) {
1255 ALOGE("Get description failed or is empty.");
1256 description = "NONE";
1257 }
1258 vendor += ".";
1259 vendor += description;
1260
1261 hidl_vec<DrmMetricGroup> pluginMetrics;
1262 status_t err = UNKNOWN_ERROR;
1263
1264 Return<void> status = mPluginV1_1->getMetrics(
1265 [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
1266 if (status != Status::OK) {
1267 ALOGV("Error getting plugin metrics: %d", status);
1268 } else {
1269 PersistableBundle pluginBundle;
1270 if (MediaDrmMetrics::HidlMetricsToBundle(
1271 pluginMetrics, &pluginBundle) == OK) {
1272 metrics->putPersistableBundle(String16(vendor), pluginBundle);
1273 }
1274 }
1275 err = toStatusT(status);
1276 });
1277 return status.isOk() ? err : DEAD_OBJECT;
Adam Stonef0e618d2018-01-17 19:20:41 -08001278 }
1279
Adam Stoneab394d12017-12-22 12:34:20 -08001280 return OK;
1281}
Jeff Tinkera53d6552017-01-20 00:31:46 -08001282
1283status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
1284 String8 const &algorithm) {
1285 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001286 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001287
1288 DrmSessionManager::Instance()->useSession(sessionId);
1289
Jeff Tinkere6412942018-04-30 17:35:16 -07001290 Return<Status> status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001291 toHidlString(algorithm));
Jeff Tinkere6412942018-04-30 17:35:16 -07001292 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001293}
1294
1295status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
1296 String8 const &algorithm) {
1297 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001298 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001299
1300 DrmSessionManager::Instance()->useSession(sessionId);
1301
Jeff Tinkere6412942018-04-30 17:35:16 -07001302 Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
Jeff Tinkera53d6552017-01-20 00:31:46 -08001303 toHidlString(algorithm));
Jeff Tinkere6412942018-04-30 17:35:16 -07001304 return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
Jeff Tinkera53d6552017-01-20 00:31:46 -08001305}
1306
1307status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001308 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1309 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001310 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001311 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001312
1313 DrmSessionManager::Instance()->useSession(sessionId);
1314
1315 status_t err = UNKNOWN_ERROR;
1316
1317 Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
1318 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1319 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1320 if (status == Status::OK) {
1321 output = toVector(hOutput);
1322 }
1323 err = toStatusT(status);
1324 }
1325 );
1326
1327 return hResult.isOk() ? err : DEAD_OBJECT;
1328}
1329
1330status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001331 Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1332 Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001333 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001334 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001335
1336 DrmSessionManager::Instance()->useSession(sessionId);
1337
1338 status_t err = UNKNOWN_ERROR;
1339
1340 Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
1341 toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1342 [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1343 if (status == Status::OK) {
1344 output = toVector(hOutput);
1345 }
1346 err = toStatusT(status);
1347 }
1348 );
1349
1350 return hResult.isOk() ? err : DEAD_OBJECT;
1351}
1352
1353status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001354 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1355 Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001356 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001357 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001358
1359 DrmSessionManager::Instance()->useSession(sessionId);
1360
1361 status_t err = UNKNOWN_ERROR;
1362
1363 Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
1364 toHidlVec(keyId), toHidlVec(message),
1365 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1366 if (status == Status::OK) {
1367 signature = toVector(hSignature);
1368 }
1369 err = toStatusT(status);
1370 }
1371 );
1372
1373 return hResult.isOk() ? err : DEAD_OBJECT;
1374}
1375
1376status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001377 Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1378 Vector<uint8_t> const &signature, bool &match) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001379 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001380 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001381
1382 DrmSessionManager::Instance()->useSession(sessionId);
1383
1384 status_t err = UNKNOWN_ERROR;
1385
1386 Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
1387 toHidlVec(message), toHidlVec(signature),
1388 [&](Status status, bool hMatch) {
1389 if (status == Status::OK) {
1390 match = hMatch;
1391 } else {
1392 match = false;
1393 }
1394 err = toStatusT(status);
1395 }
1396 );
1397
1398 return hResult.isOk() ? err : DEAD_OBJECT;
1399}
1400
1401status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
Edwin Wong68b3d9f2017-01-06 19:07:54 -08001402 String8 const &algorithm, Vector<uint8_t> const &message,
1403 Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
Jeff Tinkera53d6552017-01-20 00:31:46 -08001404 Mutex::Autolock autoLock(mLock);
Jeff Tinker6d998b62017-12-18 14:37:43 -08001405 INIT_CHECK();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001406
1407 if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
1408 return -EPERM;
1409 }
1410
1411 DrmSessionManager::Instance()->useSession(sessionId);
1412
1413 status_t err = UNKNOWN_ERROR;
1414
1415 Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1416 toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1417 [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1418 if (status == Status::OK) {
1419 signature = toVector(hSignature);
1420 }
1421 err = toStatusT(status);
1422 }
1423 );
1424
1425 return hResult.isOk() ? err : DEAD_OBJECT;
1426}
1427
1428void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1429{
Jeff Tinker7dfe28f2018-02-15 12:17:40 -08001430 cleanup();
Jeff Tinkera53d6552017-01-20 00:31:46 -08001431}
1432
1433void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1434{
1435 if (vec.size()) {
1436 obj.writeInt32(vec.size());
1437 obj.write(vec.data(), vec.size());
1438 } else {
1439 obj.writeInt32(0);
1440 }
1441}
1442
Adam Stonefb679e32018-02-07 10:25:48 -08001443void DrmHal::reportFrameworkMetrics() const
1444{
1445 MediaAnalyticsItem item("mediadrm");
1446 item.generateSessionID();
1447 item.setPkgName(mMetrics.GetAppPackageName().c_str());
1448 String8 vendor;
1449 String8 description;
1450 status_t result = getPropertyStringInternal(String8("vendor"), vendor);
1451 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001452 ALOGE("Failed to get vendor from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001453 } else {
1454 item.setCString("vendor", vendor.c_str());
1455 }
1456 result = getPropertyStringInternal(String8("description"), description);
1457 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001458 ALOGE("Failed to get description from drm plugin: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001459 } else {
1460 item.setCString("description", description.c_str());
1461 }
Adam Stoneab394d12017-12-22 12:34:20 -08001462
Adam Stonefb679e32018-02-07 10:25:48 -08001463 std::string serializedMetrics;
1464 result = mMetrics.GetSerializedMetrics(&serializedMetrics);
1465 if (result != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001466 ALOGE("Failed to serialize framework metrics: %d", result);
Adam Stonefb679e32018-02-07 10:25:48 -08001467 }
Adam Stone32494f52018-02-26 22:53:27 -08001468 std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
1469 serializedMetrics.size());
1470 if (!b64EncodedMetrics.empty()) {
1471 item.setCString("serialized_metrics", b64EncodedMetrics.c_str());
Adam Stonefb679e32018-02-07 10:25:48 -08001472 }
1473 if (!item.selfrecord()) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001474 ALOGE("Failed to self record framework metrics");
Adam Stonefb679e32018-02-07 10:25:48 -08001475 }
1476}
1477
1478void DrmHal::reportPluginMetrics() const
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001479{
Adam Stone32494f52018-02-26 22:53:27 -08001480 Vector<uint8_t> metricsVector;
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001481 String8 vendor;
1482 String8 description;
1483 if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1484 getPropertyStringInternal(String8("description"), description) == OK &&
Adam Stone32494f52018-02-26 22:53:27 -08001485 getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
1486 std::string metricsString = toBase64StringNoPad(metricsVector.array(),
1487 metricsVector.size());
1488 status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
1489 description, mAppPackageName);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001490 if (res != OK) {
Jeff Tinker987ac702018-02-15 17:02:22 -08001491 ALOGE("Metrics were retrieved but could not be reported: %d", res);
John W. Bruce33ecc4f2017-04-03 16:49:05 -07001492 }
1493 }
1494}
1495
Jeff Tinkera53d6552017-01-20 00:31:46 -08001496} // namespace android