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