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