DrmHal.cpp revision 28f27c3bee88b0f47b1086feeaa904bcdec37af6
1/*
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"
19#include <iomanip>
20
21#include <utils/Log.h>
22
23#include <binder/IPCThreadState.h>
24#include <binder/IServiceManager.h>
25
26#include <android/hardware/drm/1.0/types.h>
27#include <android/hidl/manager/1.0/IServiceManager.h>
28#include <hidl/ServiceManagement.h>
29
30#include <media/DrmHal.h>
31#include <media/DrmSessionClientInterface.h>
32#include <media/DrmSessionManager.h>
33#include <media/EventMetric.h>
34#include <media/PluginMetricsReporting.h>
35#include <media/drm/DrmAPI.h>
36#include <media/stagefright/foundation/ADebug.h>
37#include <media/stagefright/foundation/AString.h>
38#include <media/stagefright/foundation/hexdump.h>
39#include <media/stagefright/MediaErrors.h>
40
41using drm::V1_0::KeyedVector;
42using drm::V1_0::KeyStatusType;
43using drm::V1_0::KeyType;
44using drm::V1_0::KeyValue;
45using drm::V1_1::HdcpLevel;;
46using drm::V1_0::SecureStop;
47using drm::V1_1::SecureStopRelease;
48using drm::V1_0::SecureStopId;
49using drm::V1_1::SecurityLevel;
50using drm::V1_0::Status;
51using ::android::hardware::drm::V1_1::DrmMetricGroup;
52using ::android::hardware::hidl_array;
53using ::android::hardware::hidl_string;
54using ::android::hardware::hidl_vec;
55using ::android::hardware::Return;
56using ::android::hardware::Void;
57using ::android::hidl::manager::V1_0::IServiceManager;
58using ::android::os::PersistableBundle;
59using ::android::sp;
60
61namespace {
62
63// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
64// in the MediaDrm API.
65constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
66
67}
68
69namespace android {
70
71#define INIT_CHECK() {if (mInitCheck != OK) return mInitCheck;}
72
73static inline int getCallingPid() {
74    return IPCThreadState::self()->getCallingPid();
75}
76
77static bool checkPermission(const char* permissionString) {
78    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
79    bool ok = checkCallingPermission(String16(permissionString));
80    if (!ok) ALOGE("Request requires %s", permissionString);
81    return ok;
82}
83
84static const Vector<uint8_t> toVector(const hidl_vec<uint8_t> &vec) {
85    Vector<uint8_t> vector;
86    vector.appendArray(vec.data(), vec.size());
87    return *const_cast<const Vector<uint8_t> *>(&vector);
88}
89
90static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) {
91    hidl_vec<uint8_t> vec;
92    vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size());
93    return vec;
94}
95
96static String8 toString8(const hidl_string &string) {
97    return String8(string.c_str());
98}
99
100static hidl_string toHidlString(const String8& string) {
101    return hidl_string(string.string());
102}
103
104std::string ToHexString(const std::string& str) {
105  std::ostringstream out;
106  out << std::hex << std::setfill('0');
107  for (size_t i = 0; i < str.size(); i++) {
108    out << std::setw(2) << (int)(str[i]);
109  }
110  return out.str();
111}
112
113static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
114    switch(level) {
115    case SecurityLevel::SW_SECURE_CRYPTO:
116        return DrmPlugin::kSecurityLevelSwSecureCrypto;
117    case SecurityLevel::SW_SECURE_DECODE:
118        return DrmPlugin::kSecurityLevelSwSecureDecode;
119    case SecurityLevel::HW_SECURE_CRYPTO:
120        return DrmPlugin::kSecurityLevelHwSecureCrypto;
121    case SecurityLevel::HW_SECURE_DECODE:
122        return DrmPlugin::kSecurityLevelHwSecureDecode;
123    case SecurityLevel::HW_SECURE_ALL:
124        return DrmPlugin::kSecurityLevelHwSecureAll;
125    default:
126        return DrmPlugin::kSecurityLevelUnknown;
127    }
128}
129
130static DrmPlugin::HdcpLevel toHdcpLevel(HdcpLevel level) {
131    switch(level) {
132    case HdcpLevel::HDCP_NONE:
133        return DrmPlugin::kHdcpNone;
134    case HdcpLevel::HDCP_V1:
135        return DrmPlugin::kHdcpV1;
136    case HdcpLevel::HDCP_V2:
137        return DrmPlugin::kHdcpV2;
138    case HdcpLevel::HDCP_V2_1:
139        return DrmPlugin::kHdcpV2_1;
140    case HdcpLevel::HDCP_V2_2:
141        return DrmPlugin::kHdcpV2_2;
142    case HdcpLevel::HDCP_NO_OUTPUT:
143        return DrmPlugin::kHdcpNoOutput;
144    default:
145        return DrmPlugin::kHdcpLevelUnknown;
146    }
147}
148
149
150static ::KeyedVector toHidlKeyedVector(const KeyedVector<String8, String8>&
151        keyedVector) {
152    std::vector<KeyValue> stdKeyedVector;
153    for (size_t i = 0; i < keyedVector.size(); i++) {
154        KeyValue keyValue;
155        keyValue.key = toHidlString(keyedVector.keyAt(i));
156        keyValue.value = toHidlString(keyedVector.valueAt(i));
157        stdKeyedVector.push_back(keyValue);
158    }
159    return ::KeyedVector(stdKeyedVector);
160}
161
162static KeyedVector<String8, String8> toKeyedVector(const ::KeyedVector&
163        hKeyedVector) {
164    KeyedVector<String8, String8> keyedVector;
165    for (size_t i = 0; i < hKeyedVector.size(); i++) {
166        keyedVector.add(toString8(hKeyedVector[i].key),
167                toString8(hKeyedVector[i].value));
168    }
169    return keyedVector;
170}
171
172static List<Vector<uint8_t>> toSecureStops(const hidl_vec<SecureStop>&
173        hSecureStops) {
174    List<Vector<uint8_t>> secureStops;
175    for (size_t i = 0; i < hSecureStops.size(); i++) {
176        secureStops.push_back(toVector(hSecureStops[i].opaqueData));
177    }
178    return secureStops;
179}
180
181static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
182        hSecureStopIds) {
183    List<Vector<uint8_t>> secureStopIds;
184    for (size_t i = 0; i < hSecureStopIds.size(); i++) {
185        secureStopIds.push_back(toVector(hSecureStopIds[i]));
186    }
187    return secureStopIds;
188}
189
190static status_t toStatusT(Status status) {
191    switch (status) {
192    case Status::OK:
193        return OK;
194        break;
195    case Status::ERROR_DRM_NO_LICENSE:
196        return ERROR_DRM_NO_LICENSE;
197        break;
198    case Status::ERROR_DRM_LICENSE_EXPIRED:
199        return ERROR_DRM_LICENSE_EXPIRED;
200        break;
201    case Status::ERROR_DRM_SESSION_NOT_OPENED:
202        return ERROR_DRM_SESSION_NOT_OPENED;
203        break;
204    case Status::ERROR_DRM_CANNOT_HANDLE:
205        return ERROR_DRM_CANNOT_HANDLE;
206        break;
207    case Status::ERROR_DRM_INVALID_STATE:
208        return ERROR_DRM_TAMPER_DETECTED;
209        break;
210    case Status::BAD_VALUE:
211        return BAD_VALUE;
212        break;
213    case Status::ERROR_DRM_NOT_PROVISIONED:
214        return ERROR_DRM_NOT_PROVISIONED;
215        break;
216    case Status::ERROR_DRM_RESOURCE_BUSY:
217        return ERROR_DRM_RESOURCE_BUSY;
218        break;
219    case Status::ERROR_DRM_DEVICE_REVOKED:
220        return ERROR_DRM_DEVICE_REVOKED;
221        break;
222    case Status::ERROR_DRM_UNKNOWN:
223    default:
224        return ERROR_DRM_UNKNOWN;
225        break;
226    }
227}
228
229
230Mutex DrmHal::mLock;
231
232struct DrmSessionClient : public DrmSessionClientInterface {
233    explicit DrmSessionClient(DrmHal* drm) : mDrm(drm) {}
234
235    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
236        sp<DrmHal> drm = mDrm.promote();
237        if (drm == NULL) {
238            return true;
239        }
240        status_t err = drm->closeSession(sessionId);
241        if (err != OK) {
242            return false;
243        }
244        drm->sendEvent(EventType::SESSION_RECLAIMED,
245                toHidlVec(sessionId), hidl_vec<uint8_t>());
246        return true;
247    }
248
249protected:
250    virtual ~DrmSessionClient() {}
251
252private:
253    wp<DrmHal> mDrm;
254
255    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
256};
257
258DrmHal::DrmHal()
259   : mDrmSessionClient(new DrmSessionClient(this)),
260     mFactories(makeDrmFactories()),
261     mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
262}
263
264void DrmHal::closeOpenSessions() {
265    if (mPlugin != NULL) {
266        for (size_t i = 0; i < mOpenSessions.size(); i++) {
267            mPlugin->closeSession(toHidlVec(mOpenSessions[i]));
268            DrmSessionManager::Instance()->removeSession(mOpenSessions[i]);
269        }
270    }
271    mOpenSessions.clear();
272}
273
274DrmHal::~DrmHal() {
275    closeOpenSessions();
276    DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
277}
278
279Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
280    Vector<sp<IDrmFactory>> factories;
281
282    auto manager = hardware::defaultServiceManager();
283
284    if (manager != NULL) {
285        manager->listByInterface(drm::V1_0::IDrmFactory::descriptor,
286                [&factories](const hidl_vec<hidl_string> &registered) {
287                    for (const auto &instance : registered) {
288                        auto factory = drm::V1_0::IDrmFactory::getService(instance);
289                        if (factory != NULL) {
290                            ALOGD("found drm@1.0 IDrmFactory %s", instance.c_str());
291                            factories.push_back(factory);
292                        }
293                    }
294                }
295            );
296        manager->listByInterface(drm::V1_1::IDrmFactory::descriptor,
297                [&factories](const hidl_vec<hidl_string> &registered) {
298                    for (const auto &instance : registered) {
299                        auto factory = drm::V1_1::IDrmFactory::getService(instance);
300                        if (factory != NULL) {
301                            ALOGD("found drm@1.1 IDrmFactory %s", instance.c_str());
302                            factories.push_back(factory);
303                        }
304                    }
305                }
306            );
307    }
308
309    if (factories.size() == 0) {
310        // must be in passthrough mode, load the default passthrough service
311        auto passthrough = IDrmFactory::getService();
312        if (passthrough != NULL) {
313            ALOGI("makeDrmFactories: using default passthrough drm instance");
314            factories.push_back(passthrough);
315        } else {
316            ALOGE("Failed to find any drm factories");
317        }
318    }
319    return factories;
320}
321
322sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
323        const uint8_t uuid[16], const String8& appPackageName) {
324    mMetrics.SetAppPackageName(appPackageName);
325
326    sp<IDrmPlugin> plugin;
327    Return<void> hResult = factory->createPlugin(uuid, appPackageName.string(),
328            [&](Status status, const sp<IDrmPlugin>& hPlugin) {
329                if (status != Status::OK) {
330                    ALOGE("Failed to make drm plugin");
331                    return;
332                }
333                plugin = hPlugin;
334            }
335        );
336
337    if (!hResult.isOk()) {
338        ALOGE("createPlugin remote call failed");
339    }
340
341    return plugin;
342}
343
344status_t DrmHal::initCheck() const {
345    return mInitCheck;
346}
347
348status_t DrmHal::setListener(const sp<IDrmClient>& listener)
349{
350    Mutex::Autolock lock(mEventLock);
351    if (mListener != NULL){
352        IInterface::asBinder(mListener)->unlinkToDeath(this);
353    }
354    if (listener != NULL) {
355        IInterface::asBinder(listener)->linkToDeath(this);
356    }
357    mListener = listener;
358    return NO_ERROR;
359}
360
361Return<void> DrmHal::sendEvent(EventType hEventType,
362        const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
363    mMetrics.mEventCounter.Increment(hEventType);
364
365    mEventLock.lock();
366    sp<IDrmClient> listener = mListener;
367    mEventLock.unlock();
368
369    if (listener != NULL) {
370        Parcel obj;
371        writeByteArray(obj, sessionId);
372        writeByteArray(obj, data);
373
374        Mutex::Autolock lock(mNotifyLock);
375        DrmPlugin::EventType eventType;
376        switch(hEventType) {
377        case EventType::PROVISION_REQUIRED:
378            eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
379            break;
380        case EventType::KEY_NEEDED:
381            eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
382            break;
383        case EventType::KEY_EXPIRED:
384            eventType = DrmPlugin::kDrmPluginEventKeyExpired;
385            break;
386        case EventType::VENDOR_DEFINED:
387            eventType = DrmPlugin::kDrmPluginEventVendorDefined;
388            break;
389        case EventType::SESSION_RECLAIMED:
390            eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
391            break;
392        default:
393            return Void();
394        }
395        listener->notify(eventType, 0, &obj);
396    }
397    return Void();
398}
399
400Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
401        int64_t expiryTimeInMS) {
402
403    mEventLock.lock();
404    sp<IDrmClient> listener = mListener;
405    mEventLock.unlock();
406
407    if (listener != NULL) {
408        Parcel obj;
409        writeByteArray(obj, sessionId);
410        obj.writeInt64(expiryTimeInMS);
411
412        Mutex::Autolock lock(mNotifyLock);
413        listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
414    }
415    return Void();
416}
417
418Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
419        const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
420
421    mEventLock.lock();
422    sp<IDrmClient> listener = mListener;
423    mEventLock.unlock();
424
425    if (listener != NULL) {
426        Parcel obj;
427        writeByteArray(obj, sessionId);
428
429        size_t nKeys = keyStatusList.size();
430        obj.writeInt32(nKeys);
431        for (size_t i = 0; i < nKeys; ++i) {
432            const KeyStatus &keyStatus = keyStatusList[i];
433            writeByteArray(obj, keyStatus.keyId);
434            uint32_t type;
435            switch(keyStatus.type) {
436            case KeyStatusType::USABLE:
437                type = DrmPlugin::kKeyStatusType_Usable;
438                break;
439            case KeyStatusType::EXPIRED:
440                type = DrmPlugin::kKeyStatusType_Expired;
441                break;
442            case KeyStatusType::OUTPUTNOTALLOWED:
443                type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
444                break;
445            case KeyStatusType::STATUSPENDING:
446                type = DrmPlugin::kKeyStatusType_StatusPending;
447                break;
448            case KeyStatusType::INTERNALERROR:
449            default:
450                type = DrmPlugin::kKeyStatusType_InternalError;
451                break;
452            }
453            obj.writeInt32(type);
454            mMetrics.mKeyStatusChangeCounter.Increment(keyStatus.type);
455        }
456        obj.writeInt32(hasNewUsableKey);
457
458        Mutex::Autolock lock(mNotifyLock);
459        listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
460    } else {
461        // There's no listener. But we still want to count the key change
462        // events.
463        size_t nKeys = keyStatusList.size();
464        for (size_t i = 0; i < nKeys; i++) {
465            mMetrics.mKeyStatusChangeCounter.Increment(keyStatusList[i].type);
466        }
467    }
468
469    return Void();
470}
471
472bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
473    Mutex::Autolock autoLock(mLock);
474
475    for (size_t i = 0; i < mFactories.size(); i++) {
476        if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
477            if (mimeType != "") {
478                if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
479                    return true;
480                }
481            } else {
482                return true;
483            }
484        }
485    }
486    return false;
487}
488
489status_t DrmHal::createPlugin(const uint8_t uuid[16],
490        const String8& appPackageName) {
491    Mutex::Autolock autoLock(mLock);
492
493    for (size_t i = 0; i < mFactories.size(); i++) {
494        if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
495            mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
496            if (mPlugin != NULL) {
497                mPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mPlugin);
498            }
499        }
500    }
501
502    if (mPlugin == NULL) {
503        mInitCheck = ERROR_UNSUPPORTED;
504    } else {
505        if (!mPlugin->setListener(this).isOk()) {
506            mInitCheck = DEAD_OBJECT;
507        } else {
508            mInitCheck = OK;
509        }
510    }
511
512    return mInitCheck;
513}
514
515status_t DrmHal::destroyPlugin() {
516    Mutex::Autolock autoLock(mLock);
517    INIT_CHECK();
518
519    closeOpenSessions();
520    reportPluginMetrics();
521    reportFrameworkMetrics();
522    setListener(NULL);
523    mInitCheck = NO_INIT;
524
525    if (mPlugin != NULL) {
526        if (!mPlugin->setListener(NULL).isOk()) {
527            mInitCheck = DEAD_OBJECT;
528        }
529    }
530    mPlugin.clear();
531    mPluginV1_1.clear();
532    return OK;
533}
534
535status_t DrmHal::openSession(DrmPlugin::SecurityLevel level,
536        Vector<uint8_t> &sessionId) {
537    Mutex::Autolock autoLock(mLock);
538    INIT_CHECK();
539
540    SecurityLevel hSecurityLevel;
541    bool setSecurityLevel = true;
542
543    switch(level) {
544    case DrmPlugin::kSecurityLevelSwSecureCrypto:
545        hSecurityLevel = SecurityLevel::SW_SECURE_CRYPTO;
546        break;
547    case DrmPlugin::kSecurityLevelSwSecureDecode:
548        hSecurityLevel = SecurityLevel::SW_SECURE_DECODE;
549        break;
550    case DrmPlugin::kSecurityLevelHwSecureCrypto:
551        hSecurityLevel = SecurityLevel::HW_SECURE_CRYPTO;
552        break;
553    case DrmPlugin::kSecurityLevelHwSecureDecode:
554        hSecurityLevel = SecurityLevel::HW_SECURE_DECODE;
555        break;
556    case DrmPlugin::kSecurityLevelHwSecureAll:
557        hSecurityLevel = SecurityLevel::HW_SECURE_ALL;
558        break;
559    case DrmPlugin::kSecurityLevelMax:
560        setSecurityLevel = false;
561        break;
562    default:
563        return ERROR_DRM_CANNOT_HANDLE;
564    }
565
566    status_t  err = UNKNOWN_ERROR;
567    bool retry = true;
568    do {
569        hidl_vec<uint8_t> hSessionId;
570
571        Return<void> hResult;
572        if (mPluginV1_1 == NULL || !setSecurityLevel) {
573            hResult = mPlugin->openSession(
574                    [&](Status status,const hidl_vec<uint8_t>& id) {
575                        if (status == Status::OK) {
576                            sessionId = toVector(id);
577                        }
578                        err = toStatusT(status);
579                    }
580                );
581        } else {
582            hResult = mPluginV1_1->openSession_1_1(hSecurityLevel,
583                    [&](Status status, const hidl_vec<uint8_t>& id) {
584                        if (status == Status::OK) {
585                            sessionId = toVector(id);
586                        }
587                        err = toStatusT(status);
588                    }
589                );
590        }
591
592        if (!hResult.isOk()) {
593            err = DEAD_OBJECT;
594        }
595
596        if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
597            mLock.unlock();
598            // reclaimSession may call back to closeSession, since mLock is
599            // shared between Drm instances, we should unlock here to avoid
600            // deadlock.
601            retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
602            mLock.lock();
603        } else {
604            retry = false;
605        }
606    } while (retry);
607
608    if (err == OK) {
609        DrmSessionManager::Instance()->addSession(getCallingPid(),
610                mDrmSessionClient, sessionId);
611        mOpenSessions.push(sessionId);
612        mMetrics.SetSessionStart(sessionId);
613    }
614
615    mMetrics.mOpenSessionCounter.Increment(err);
616    return err;
617}
618
619status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
620    Mutex::Autolock autoLock(mLock);
621    INIT_CHECK();
622
623    Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
624    if (status.isOk()) {
625        if (status == Status::OK) {
626            DrmSessionManager::Instance()->removeSession(sessionId);
627            for (size_t i = 0; i < mOpenSessions.size(); i++) {
628                if (mOpenSessions[i] == sessionId) {
629                    mOpenSessions.removeAt(i);
630                    break;
631                }
632            }
633        }
634        status_t response = toStatusT(status);
635        mMetrics.SetSessionEnd(sessionId);
636        mMetrics.mCloseSessionCounter.Increment(response);
637        reportPluginMetrics();
638        return response;
639    }
640    mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
641    return DEAD_OBJECT;
642}
643
644status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
645        Vector<uint8_t> const &initData, String8 const &mimeType,
646        DrmPlugin::KeyType keyType, KeyedVector<String8,
647        String8> const &optionalParameters, Vector<uint8_t> &request,
648        String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
649    Mutex::Autolock autoLock(mLock);
650    INIT_CHECK();
651    EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
652
653    DrmSessionManager::Instance()->useSession(sessionId);
654
655    KeyType hKeyType;
656    if (keyType == DrmPlugin::kKeyType_Streaming) {
657        hKeyType = KeyType::STREAMING;
658    } else if (keyType == DrmPlugin::kKeyType_Offline) {
659        hKeyType = KeyType::OFFLINE;
660    } else if (keyType == DrmPlugin::kKeyType_Release) {
661        hKeyType = KeyType::RELEASE;
662    } else {
663        keyRequestTimer.SetAttribute(BAD_VALUE);
664        return BAD_VALUE;
665    }
666
667    ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
668
669    status_t err = UNKNOWN_ERROR;
670
671    if (mPluginV1_1 != NULL) {
672        Return<void> hResult =
673            mPluginV1_1->getKeyRequest_1_1(
674                toHidlVec(sessionId), toHidlVec(initData),
675                toHidlString(mimeType), hKeyType, hOptionalParameters,
676                [&](Status status, const hidl_vec<uint8_t>& hRequest,
677                    drm::V1_1::KeyRequestType hKeyRequestType,
678                    const hidl_string& hDefaultUrl) {
679
680            if (status == Status::OK) {
681                request = toVector(hRequest);
682                defaultUrl = toString8(hDefaultUrl);
683
684                switch (hKeyRequestType) {
685                    case drm::V1_1::KeyRequestType::INITIAL:
686                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
687                        break;
688                    case drm::V1_1::KeyRequestType::RENEWAL:
689                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
690                        break;
691                    case drm::V1_1::KeyRequestType::RELEASE:
692                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
693                        break;
694                    case drm::V1_1::KeyRequestType::NONE:
695                        *keyRequestType = DrmPlugin::kKeyRequestType_None;
696                        break;
697                    case drm::V1_1::KeyRequestType::UPDATE:
698                        *keyRequestType = DrmPlugin::kKeyRequestType_Update;
699                        break;
700                    default:
701                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
702                        break;
703                }
704                err = toStatusT(status);
705            }
706        });
707        return hResult.isOk() ? err : DEAD_OBJECT;
708    }
709
710    Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
711            toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
712            [&](Status status, const hidl_vec<uint8_t>& hRequest,
713                    drm::V1_0::KeyRequestType hKeyRequestType,
714                    const hidl_string& hDefaultUrl) {
715
716                if (status == Status::OK) {
717                    request = toVector(hRequest);
718                    defaultUrl = toString8(hDefaultUrl);
719
720                    switch (hKeyRequestType) {
721                    case drm::V1_0::KeyRequestType::INITIAL:
722                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
723                        break;
724                    case drm::V1_0::KeyRequestType::RENEWAL:
725                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
726                        break;
727                    case drm::V1_0::KeyRequestType::RELEASE:
728                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
729                        break;
730                    default:
731                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
732                        break;
733                    }
734                    err = toStatusT(status);
735                }
736            });
737
738    err = hResult.isOk() ? err : DEAD_OBJECT;
739    keyRequestTimer.SetAttribute(err);
740    return err;
741}
742
743status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
744        Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
745    Mutex::Autolock autoLock(mLock);
746    EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
747
748    INIT_CHECK();
749
750    DrmSessionManager::Instance()->useSession(sessionId);
751
752    status_t err = UNKNOWN_ERROR;
753
754    Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
755            toHidlVec(response),
756            [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
757                if (status == Status::OK) {
758                    keySetId = toVector(hKeySetId);
759                }
760                err = toStatusT(status);
761            }
762        );
763    err = hResult.isOk() ? err : DEAD_OBJECT;
764    keyResponseTimer.SetAttribute(err);
765    return err;
766}
767
768status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
769    Mutex::Autolock autoLock(mLock);
770    INIT_CHECK();
771
772    return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
773}
774
775status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
776        Vector<uint8_t> const &keySetId) {
777    Mutex::Autolock autoLock(mLock);
778    INIT_CHECK();
779
780    DrmSessionManager::Instance()->useSession(sessionId);
781
782    return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
783                    toHidlVec(keySetId)));
784}
785
786status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
787        KeyedVector<String8, String8> &infoMap) const {
788    Mutex::Autolock autoLock(mLock);
789    INIT_CHECK();
790
791    DrmSessionManager::Instance()->useSession(sessionId);
792
793    ::KeyedVector hInfoMap;
794
795    status_t err = UNKNOWN_ERROR;
796
797    Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
798            [&](Status status, const hidl_vec<KeyValue>& map) {
799                if (status == Status::OK) {
800                    infoMap = toKeyedVector(map);
801                }
802                err = toStatusT(status);
803            }
804        );
805
806    return hResult.isOk() ? err : DEAD_OBJECT;
807}
808
809status_t DrmHal::getProvisionRequest(String8 const &certType,
810        String8 const &certAuthority, Vector<uint8_t> &request,
811        String8 &defaultUrl) {
812    Mutex::Autolock autoLock(mLock);
813    INIT_CHECK();
814
815    status_t err = UNKNOWN_ERROR;
816
817    Return<void> hResult = mPlugin->getProvisionRequest(
818            toHidlString(certType), toHidlString(certAuthority),
819            [&](Status status, const hidl_vec<uint8_t>& hRequest,
820                    const hidl_string& hDefaultUrl) {
821                if (status == Status::OK) {
822                    request = toVector(hRequest);
823                    defaultUrl = toString8(hDefaultUrl);
824                }
825                err = toStatusT(status);
826            }
827        );
828
829    err = hResult.isOk() ? err : DEAD_OBJECT;
830    mMetrics.mGetProvisionRequestCounter.Increment(err);
831    return err;
832}
833
834status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
835        Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
836    Mutex::Autolock autoLock(mLock);
837    INIT_CHECK();
838
839    status_t err = UNKNOWN_ERROR;
840
841    Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
842            [&](Status status, const hidl_vec<uint8_t>& hCertificate,
843                    const hidl_vec<uint8_t>& hWrappedKey) {
844                if (status == Status::OK) {
845                    certificate = toVector(hCertificate);
846                    wrappedKey = toVector(hWrappedKey);
847                }
848                err = toStatusT(status);
849            }
850        );
851
852    err = hResult.isOk() ? err : DEAD_OBJECT;
853    mMetrics.mProvideProvisionResponseCounter.Increment(err);
854    return err;
855}
856
857status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
858    Mutex::Autolock autoLock(mLock);
859    INIT_CHECK();
860
861    status_t err = UNKNOWN_ERROR;
862
863    Return<void> hResult = mPlugin->getSecureStops(
864            [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
865                if (status == Status::OK) {
866                    secureStops = toSecureStops(hSecureStops);
867                }
868                err = toStatusT(status);
869            }
870    );
871
872    return hResult.isOk() ? err : DEAD_OBJECT;
873}
874
875
876status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
877    Mutex::Autolock autoLock(mLock);
878
879    if (mInitCheck != OK) {
880        return mInitCheck;
881    }
882
883    if (mPluginV1_1 == NULL) {
884        return ERROR_DRM_CANNOT_HANDLE;
885    }
886
887    status_t err = UNKNOWN_ERROR;
888
889    Return<void> hResult = mPluginV1_1->getSecureStopIds(
890            [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
891                if (status == Status::OK) {
892                    secureStopIds = toSecureStopIds(hSecureStopIds);
893                }
894                err = toStatusT(status);
895            }
896    );
897
898    return hResult.isOk() ? err : DEAD_OBJECT;
899}
900
901
902status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
903    Mutex::Autolock autoLock(mLock);
904    INIT_CHECK();
905
906    status_t err = UNKNOWN_ERROR;
907
908    Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
909            [&](Status status, const SecureStop& hSecureStop) {
910                if (status == Status::OK) {
911                    secureStop = toVector(hSecureStop.opaqueData);
912                }
913                err = toStatusT(status);
914            }
915    );
916
917    return hResult.isOk() ? err : DEAD_OBJECT;
918}
919
920status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
921    Mutex::Autolock autoLock(mLock);
922    INIT_CHECK();
923
924    if (mPluginV1_1 != NULL) {
925        SecureStopRelease secureStopRelease;
926        secureStopRelease.opaqueData = toHidlVec(ssRelease);
927        return toStatusT(mPluginV1_1->releaseSecureStops(secureStopRelease));
928    }
929
930    return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
931}
932
933status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
934    Mutex::Autolock autoLock(mLock);
935
936    if (mInitCheck != OK) {
937        return mInitCheck;
938    }
939
940    if (mPluginV1_1 == NULL) {
941        return ERROR_DRM_CANNOT_HANDLE;
942    }
943
944    return toStatusT(mPluginV1_1->removeSecureStop(toHidlVec(ssid)));
945}
946
947status_t DrmHal::removeAllSecureStops() {
948    Mutex::Autolock autoLock(mLock);
949    INIT_CHECK();
950
951    if (mPluginV1_1 != NULL) {
952        return toStatusT(mPluginV1_1->removeAllSecureStops());
953    }
954    return toStatusT(mPlugin->releaseAllSecureStops());
955}
956
957status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel *connected,
958            DrmPlugin::HdcpLevel *max) const {
959    Mutex::Autolock autoLock(mLock);
960    INIT_CHECK();
961
962    if (connected == NULL || max == NULL) {
963        return BAD_VALUE;
964    }
965    status_t err = UNKNOWN_ERROR;
966
967    if (mPluginV1_1 == NULL) {
968        return ERROR_DRM_CANNOT_HANDLE;
969    }
970
971    *connected = DrmPlugin::kHdcpLevelUnknown;
972    *max = DrmPlugin::kHdcpLevelUnknown;
973
974    Return<void> hResult = mPluginV1_1->getHdcpLevels(
975            [&](Status status, const HdcpLevel& hConnected, const HdcpLevel& hMax) {
976                if (status == Status::OK) {
977                    *connected = toHdcpLevel(hConnected);
978                    *max = toHdcpLevel(hMax);
979                }
980                err = toStatusT(status);
981            }
982    );
983
984    return hResult.isOk() ? err : DEAD_OBJECT;
985}
986
987status_t DrmHal::getNumberOfSessions(uint32_t *open, uint32_t *max) const {
988    Mutex::Autolock autoLock(mLock);
989    INIT_CHECK();
990
991    if (open == NULL || max == NULL) {
992        return BAD_VALUE;
993    }
994    status_t err = UNKNOWN_ERROR;
995
996    *open = 0;
997    *max = 0;
998
999    if (mPluginV1_1 == NULL) {
1000        return ERROR_DRM_CANNOT_HANDLE;
1001    }
1002
1003    Return<void> hResult = mPluginV1_1->getNumberOfSessions(
1004            [&](Status status, uint32_t hOpen, uint32_t hMax) {
1005                if (status == Status::OK) {
1006                    *open = hOpen;
1007                    *max = hMax;
1008                }
1009                err = toStatusT(status);
1010            }
1011    );
1012
1013    return hResult.isOk() ? err : DEAD_OBJECT;
1014}
1015
1016status_t DrmHal::getSecurityLevel(Vector<uint8_t> const &sessionId,
1017        DrmPlugin::SecurityLevel *level) const {
1018    Mutex::Autolock autoLock(mLock);
1019    INIT_CHECK();
1020
1021    if (level == NULL) {
1022        return BAD_VALUE;
1023    }
1024    status_t err = UNKNOWN_ERROR;
1025
1026    if (mPluginV1_1 == NULL) {
1027        return ERROR_DRM_CANNOT_HANDLE;
1028    }
1029
1030    *level = DrmPlugin::kSecurityLevelUnknown;
1031
1032    Return<void> hResult = mPluginV1_1->getSecurityLevel(toHidlVec(sessionId),
1033            [&](Status status, SecurityLevel hLevel) {
1034                if (status == Status::OK) {
1035                    *level = toSecurityLevel(hLevel);
1036                }
1037                err = toStatusT(status);
1038            }
1039    );
1040
1041    return hResult.isOk() ? err : DEAD_OBJECT;
1042}
1043
1044status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
1045    Mutex::Autolock autoLock(mLock);
1046    return getPropertyStringInternal(name, value);
1047}
1048
1049status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
1050    // This function is internal to the class and should only be called while
1051    // mLock is already held.
1052    INIT_CHECK();
1053
1054    status_t err = UNKNOWN_ERROR;
1055
1056    Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
1057            [&](Status status, const hidl_string& hValue) {
1058                if (status == Status::OK) {
1059                    value = toString8(hValue);
1060                }
1061                err = toStatusT(status);
1062            }
1063    );
1064
1065    return hResult.isOk() ? err : DEAD_OBJECT;
1066}
1067
1068status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
1069    Mutex::Autolock autoLock(mLock);
1070    return getPropertyByteArrayInternal(name, value);
1071}
1072
1073status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
1074    // This function is internal to the class and should only be called while
1075    // mLock is already held.
1076    INIT_CHECK();
1077
1078    status_t err = UNKNOWN_ERROR;
1079
1080    Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
1081            [&](Status status, const hidl_vec<uint8_t>& hValue) {
1082                if (status == Status::OK) {
1083                    value = toVector(hValue);
1084                }
1085                err = toStatusT(status);
1086            }
1087    );
1088
1089    err = hResult.isOk() ? err : DEAD_OBJECT;
1090    if (name == kPropertyDeviceUniqueId) {
1091        mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
1092    }
1093    return err;
1094}
1095
1096status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
1097    Mutex::Autolock autoLock(mLock);
1098    INIT_CHECK();
1099
1100    Status status = mPlugin->setPropertyString(toHidlString(name),
1101            toHidlString(value));
1102    return toStatusT(status);
1103}
1104
1105status_t DrmHal::setPropertyByteArray(String8 const &name,
1106                                   Vector<uint8_t> const &value ) const {
1107    Mutex::Autolock autoLock(mLock);
1108    INIT_CHECK();
1109
1110    Status status = mPlugin->setPropertyByteArray(toHidlString(name),
1111            toHidlVec(value));
1112    return toStatusT(status);
1113}
1114
1115status_t DrmHal::getMetrics(PersistableBundle* metrics) {
1116    if (metrics == nullptr) {
1117        return UNEXPECTED_NULL;
1118    }
1119    mMetrics.Export(metrics);
1120
1121    // Append vendor metrics if they are supported.
1122    if (mPluginV1_1 != NULL) {
1123        String8 vendor;
1124        String8 description;
1125        if (getPropertyStringInternal(String8("vendor"), vendor) != OK
1126            || vendor.isEmpty()) {
1127          ALOGE("Get vendor failed or is empty");
1128          vendor = "NONE";
1129        }
1130        if (getPropertyStringInternal(String8("description"), description) != OK
1131            || description.isEmpty()) {
1132          ALOGE("Get description failed or is empty.");
1133          description = "NONE";
1134        }
1135        vendor += ".";
1136        vendor += description;
1137
1138        hidl_vec<DrmMetricGroup> pluginMetrics;
1139        status_t err = UNKNOWN_ERROR;
1140
1141        Return<void> status = mPluginV1_1->getMetrics(
1142                [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
1143                    if (status != Status::OK) {
1144                      ALOGV("Error getting plugin metrics: %d", status);
1145                    } else {
1146                        PersistableBundle pluginBundle;
1147                        if (MediaDrmMetrics::HidlMetricsToBundle(
1148                                pluginMetrics, &pluginBundle) == OK) {
1149                            metrics->putPersistableBundle(String16(vendor), pluginBundle);
1150                        }
1151                    }
1152                    err = toStatusT(status);
1153                });
1154        return status.isOk() ? err : DEAD_OBJECT;
1155    }
1156
1157    return OK;
1158}
1159
1160status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
1161                                 String8 const &algorithm) {
1162    Mutex::Autolock autoLock(mLock);
1163    INIT_CHECK();
1164
1165    DrmSessionManager::Instance()->useSession(sessionId);
1166
1167    Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
1168            toHidlString(algorithm));
1169    return toStatusT(status);
1170}
1171
1172status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
1173                              String8 const &algorithm) {
1174    Mutex::Autolock autoLock(mLock);
1175    INIT_CHECK();
1176
1177    DrmSessionManager::Instance()->useSession(sessionId);
1178
1179    Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
1180            toHidlString(algorithm));
1181    return toStatusT(status);
1182}
1183
1184status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
1185        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1186        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
1187    Mutex::Autolock autoLock(mLock);
1188    INIT_CHECK();
1189
1190    DrmSessionManager::Instance()->useSession(sessionId);
1191
1192    status_t err = UNKNOWN_ERROR;
1193
1194    Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
1195            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1196            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1197                if (status == Status::OK) {
1198                    output = toVector(hOutput);
1199                }
1200                err = toStatusT(status);
1201            }
1202    );
1203
1204    return hResult.isOk() ? err : DEAD_OBJECT;
1205}
1206
1207status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
1208        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
1209        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
1210    Mutex::Autolock autoLock(mLock);
1211    INIT_CHECK();
1212
1213    DrmSessionManager::Instance()->useSession(sessionId);
1214
1215    status_t  err = UNKNOWN_ERROR;
1216
1217    Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
1218            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
1219            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
1220                if (status == Status::OK) {
1221                    output = toVector(hOutput);
1222                }
1223                err = toStatusT(status);
1224            }
1225    );
1226
1227    return hResult.isOk() ? err : DEAD_OBJECT;
1228}
1229
1230status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
1231        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1232        Vector<uint8_t> &signature) {
1233    Mutex::Autolock autoLock(mLock);
1234    INIT_CHECK();
1235
1236    DrmSessionManager::Instance()->useSession(sessionId);
1237
1238    status_t err = UNKNOWN_ERROR;
1239
1240    Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
1241            toHidlVec(keyId), toHidlVec(message),
1242            [&](Status status, const hidl_vec<uint8_t>& hSignature)  {
1243                if (status == Status::OK) {
1244                    signature = toVector(hSignature);
1245                }
1246                err = toStatusT(status);
1247            }
1248    );
1249
1250    return hResult.isOk() ? err : DEAD_OBJECT;
1251}
1252
1253status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
1254        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
1255        Vector<uint8_t> const &signature, bool &match) {
1256    Mutex::Autolock autoLock(mLock);
1257    INIT_CHECK();
1258
1259    DrmSessionManager::Instance()->useSession(sessionId);
1260
1261    status_t err = UNKNOWN_ERROR;
1262
1263    Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
1264            toHidlVec(message), toHidlVec(signature),
1265            [&](Status status, bool hMatch) {
1266                if (status == Status::OK) {
1267                    match = hMatch;
1268                } else {
1269                    match = false;
1270                }
1271                err = toStatusT(status);
1272            }
1273    );
1274
1275    return hResult.isOk() ? err : DEAD_OBJECT;
1276}
1277
1278status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
1279        String8 const &algorithm, Vector<uint8_t> const &message,
1280        Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
1281    Mutex::Autolock autoLock(mLock);
1282    INIT_CHECK();
1283
1284    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
1285        return -EPERM;
1286    }
1287
1288    DrmSessionManager::Instance()->useSession(sessionId);
1289
1290    status_t err = UNKNOWN_ERROR;
1291
1292    Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
1293            toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
1294            [&](Status status, const hidl_vec<uint8_t>& hSignature) {
1295                if (status == Status::OK) {
1296                    signature = toVector(hSignature);
1297                }
1298                err = toStatusT(status);
1299            }
1300        );
1301
1302    return hResult.isOk() ? err : DEAD_OBJECT;
1303}
1304
1305void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1306{
1307    Mutex::Autolock autoLock(mLock);
1308    closeOpenSessions();
1309    setListener(NULL);
1310    mInitCheck = NO_INIT;
1311
1312    if (mPlugin != NULL) {
1313        if (!mPlugin->setListener(NULL).isOk()) {
1314            mInitCheck = DEAD_OBJECT;
1315        }
1316    }
1317    mPlugin.clear();
1318}
1319
1320void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1321{
1322    if (vec.size()) {
1323        obj.writeInt32(vec.size());
1324        obj.write(vec.data(), vec.size());
1325    } else {
1326        obj.writeInt32(0);
1327    }
1328}
1329
1330void DrmHal::reportFrameworkMetrics() const
1331{
1332    MediaAnalyticsItem item("mediadrm");
1333    item.generateSessionID();
1334    item.setPkgName(mMetrics.GetAppPackageName().c_str());
1335    String8 vendor;
1336    String8 description;
1337    status_t result = getPropertyStringInternal(String8("vendor"), vendor);
1338    if (result != OK) {
1339        ALOGE("Failed to get vendor from drm plugin. %d", result);
1340    } else {
1341        item.setCString("vendor", vendor.c_str());
1342    }
1343    result = getPropertyStringInternal(String8("description"), description);
1344    if (result != OK) {
1345        ALOGE("Failed to get description from drm plugin. %d", result);
1346    } else {
1347        item.setCString("description", description.c_str());
1348    }
1349
1350    std::string serializedMetrics;
1351    result = mMetrics.GetSerializedMetrics(&serializedMetrics);
1352    if (result != OK) {
1353        ALOGE("Failed to serialize Framework metrics: %d", result);
1354    }
1355    serializedMetrics = ToHexString(serializedMetrics);
1356    if (!serializedMetrics.empty()) {
1357        item.setCString("serialized_metrics", serializedMetrics.c_str());
1358    }
1359    if (!item.selfrecord()) {
1360        ALOGE("Failed to self record framework metrics.");
1361    }
1362}
1363
1364void DrmHal::reportPluginMetrics() const
1365{
1366    Vector<uint8_t> metrics;
1367    String8 vendor;
1368    String8 description;
1369    if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1370            getPropertyStringInternal(String8("description"), description) == OK &&
1371            getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
1372        status_t res = android::reportDrmPluginMetrics(
1373                metrics, vendor, description);
1374        if (res != OK) {
1375            ALOGE("Metrics were retrieved but could not be reported: %i", res);
1376        }
1377    }
1378}
1379
1380}  // namespace android
1381