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