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