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