DrmHal.cpp revision 38875a41d62003ee9ad1f537106a86289fb0c437
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        return NULL;
205    }
206
207    ALOGD("makeDrmFactory: service is %s",
208            factory->isRemote() ? "Remote" : "Not Remote");
209
210    return factory;
211}
212
213sp<IDrmPlugin> DrmHal::makeDrmPlugin(const uint8_t uuid[16],
214        const String8& appPackageName) {
215    if (mFactory == NULL){
216        return NULL;
217    }
218
219    sp<IDrmPlugin> plugin;
220    Return<void> hResult = mFactory->createPlugin(uuid, appPackageName.string(),
221            [&](Status status, const sp<IDrmPlugin>& hPlugin) {
222      if (status != Status::OK) {
223        ALOGD("Failed to make drm plugin");
224        return;
225      }
226      plugin = hPlugin;
227    }
228    );
229    return plugin;
230}
231
232status_t DrmHal::initCheck() const {
233    return mInitCheck;
234}
235
236status_t DrmHal::setListener(const sp<IDrmClient>& listener)
237{
238    Mutex::Autolock lock(mEventLock);
239    if (mListener != NULL){
240        IInterface::asBinder(mListener)->unlinkToDeath(this);
241    }
242    if (listener != NULL) {
243        IInterface::asBinder(listener)->linkToDeath(this);
244    }
245    mListener = listener;
246    return NO_ERROR;
247}
248
249Return<void> DrmHal::sendEvent(EventType hEventType,
250        const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
251
252    mEventLock.lock();
253    sp<IDrmClient> listener = mListener;
254    mEventLock.unlock();
255
256    if (listener != NULL) {
257        Parcel obj;
258        writeByteArray(obj, sessionId);
259        writeByteArray(obj, data);
260
261        Mutex::Autolock lock(mNotifyLock);
262        DrmPlugin::EventType eventType;
263        switch(hEventType) {
264        case EventType::PROVISION_REQUIRED:
265            eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
266            break;
267        case EventType::KEY_NEEDED:
268            eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
269            break;
270        case EventType::KEY_EXPIRED:
271            eventType = DrmPlugin::kDrmPluginEventKeyExpired;
272            break;
273        case EventType::VENDOR_DEFINED:
274            eventType = DrmPlugin::kDrmPluginEventVendorDefined;
275            break;
276        default:
277            return Void();
278        }
279        listener->notify(eventType, 0, &obj);
280    }
281    return Void();
282}
283
284Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
285        int64_t expiryTimeInMS) {
286
287    mEventLock.lock();
288    sp<IDrmClient> listener = mListener;
289    mEventLock.unlock();
290
291    if (listener != NULL) {
292        Parcel obj;
293        writeByteArray(obj, sessionId);
294        obj.writeInt64(expiryTimeInMS);
295
296        Mutex::Autolock lock(mNotifyLock);
297        listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
298    }
299    return Void();
300}
301
302Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
303        const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
304
305    mEventLock.lock();
306    sp<IDrmClient> listener = mListener;
307    mEventLock.unlock();
308
309    if (listener != NULL) {
310        Parcel obj;
311        writeByteArray(obj, sessionId);
312
313        size_t nKeys = keyStatusList.size();
314        obj.writeInt32(nKeys);
315        for (size_t i = 0; i < nKeys; ++i) {
316            const KeyStatus &keyStatus = keyStatusList[i];
317            writeByteArray(obj, keyStatus.keyId);
318            uint32_t type;
319            switch(keyStatus.type) {
320            case KeyStatusType::USABLE:
321                type = DrmPlugin::kKeyStatusType_Usable;
322                break;
323            case KeyStatusType::EXPIRED:
324                type = DrmPlugin::kKeyStatusType_Expired;
325                break;
326            case KeyStatusType::OUTPUTNOTALLOWED:
327                type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
328                break;
329            case KeyStatusType::STATUSPENDING:
330                type = DrmPlugin::kKeyStatusType_StatusPending;
331                break;
332            case KeyStatusType::INTERNALERROR:
333            default:
334                type = DrmPlugin::kKeyStatusType_InternalError;
335                break;
336            }
337            obj.writeInt32(type);
338        }
339        obj.writeInt32(hasNewUsableKey);
340
341        Mutex::Autolock lock(mNotifyLock);
342        listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
343    }
344    return Void();
345}
346
347bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
348    Mutex::Autolock autoLock(mLock);
349    bool result = false;
350
351    if (mFactory != NULL && mFactory->isCryptoSchemeSupported(uuid)) {
352        result = true;
353        if (mimeType != "") {
354            result = mFactory->isContentTypeSupported(mimeType.string());
355        }
356    }
357    return result;
358}
359
360status_t DrmHal::createPlugin(const uint8_t uuid[16],
361        const String8& appPackageName) {
362    Mutex::Autolock autoLock(mLock);
363
364    mPlugin = makeDrmPlugin(uuid, appPackageName);
365
366    if (mPlugin == NULL) {
367        mInitCheck = ERROR_UNSUPPORTED;
368    } else {
369        mInitCheck = OK;
370        mPlugin->setListener(this);
371    }
372
373    return mInitCheck;
374}
375
376status_t DrmHal::destroyPlugin() {
377    Mutex::Autolock autoLock(mLock);
378
379    if (mInitCheck != OK) {
380        return mInitCheck;
381    }
382
383    setListener(NULL);
384    mPlugin.clear();
385
386    return OK;
387}
388
389status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
390    Mutex::Autolock autoLock(mLock);
391
392    if (mInitCheck != OK) {
393        return mInitCheck;
394    }
395
396    status_t  err = UNKNOWN_ERROR;
397
398    bool retry = true;
399    do {
400        hidl_vec<uint8_t> hSessionId;
401
402        Return<void> hResult = mPlugin->openSession(
403                [&](Status status, const hidl_vec<uint8_t>& id) {
404                    if (status == Status::OK) {
405                        sessionId = toVector(id);
406                    }
407                    err = toStatusT(status);
408                }
409            );
410
411        if (!hResult.isOk()) {
412            err = DEAD_OBJECT;
413        }
414
415        if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
416            mLock.unlock();
417            // reclaimSession may call back to closeSession, since mLock is
418            // shared between Drm instances, we should unlock here to avoid
419            // deadlock.
420            retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
421            mLock.lock();
422        } else {
423            retry = false;
424        }
425    } while (retry);
426
427    if (err == OK) {
428        DrmSessionManager::Instance()->addSession(getCallingPid(),
429                mDrmSessionClient, sessionId);
430    }
431    return err;
432}
433
434status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
435    Mutex::Autolock autoLock(mLock);
436
437    if (mInitCheck != OK) {
438        return mInitCheck;
439    }
440
441    Status status = mPlugin->closeSession(toHidlVec(sessionId));
442    if (status == Status::OK) {
443        DrmSessionManager::Instance()->removeSession(sessionId);
444    }
445    return toStatusT(status);
446}
447
448status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
449        Vector<uint8_t> const &initData, String8 const &mimeType,
450        DrmPlugin::KeyType keyType, KeyedVector<String8,
451        String8> const &optionalParameters, Vector<uint8_t> &request,
452        String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
453    Mutex::Autolock autoLock(mLock);
454
455    if (mInitCheck != OK) {
456        return mInitCheck;
457    }
458
459    DrmSessionManager::Instance()->useSession(sessionId);
460
461    KeyType hKeyType;
462    if (keyType == DrmPlugin::kKeyType_Streaming) {
463        hKeyType = KeyType::STREAMING;
464    } else if (keyType == DrmPlugin::kKeyType_Offline) {
465        hKeyType = KeyType::OFFLINE;
466    } else if (keyType == DrmPlugin::kKeyType_Release) {
467        hKeyType = KeyType::RELEASE;
468    } else {
469        return BAD_VALUE;
470    }
471
472    ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
473
474    status_t err = UNKNOWN_ERROR;
475
476    Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
477            toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
478            [&](Status status, const hidl_vec<uint8_t>& hRequest,
479                    KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
480
481                if (status == Status::OK) {
482                    request = toVector(hRequest);
483                    defaultUrl = toString8(hDefaultUrl);
484
485                    switch (hKeyRequestType) {
486                    case KeyRequestType::INITIAL:
487                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
488                        break;
489                    case KeyRequestType::RENEWAL:
490                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
491                        break;
492                    case KeyRequestType::RELEASE:
493                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
494                        break;
495                    default:
496                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
497                        break;
498                    }
499                    err = toStatusT(status);
500                }
501            });
502
503    return hResult.isOk() ? err : DEAD_OBJECT;
504}
505
506status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
507        Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
508    Mutex::Autolock autoLock(mLock);
509
510    if (mInitCheck != OK) {
511        return mInitCheck;
512    }
513
514    DrmSessionManager::Instance()->useSession(sessionId);
515
516    status_t err = UNKNOWN_ERROR;
517
518    Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
519            toHidlVec(response),
520            [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
521                if (status == Status::OK) {
522                    keySetId = toVector(hKeySetId);
523                }
524                err = toStatusT(status);
525            }
526        );
527
528    return hResult.isOk() ? err : DEAD_OBJECT;
529}
530
531status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
532    Mutex::Autolock autoLock(mLock);
533
534    if (mInitCheck != OK) {
535        return mInitCheck;
536    }
537
538    return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
539}
540
541status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
542        Vector<uint8_t> const &keySetId) {
543    Mutex::Autolock autoLock(mLock);
544
545    if (mInitCheck != OK) {
546        return mInitCheck;
547    }
548
549    DrmSessionManager::Instance()->useSession(sessionId);
550
551    return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
552                    toHidlVec(keySetId)));
553}
554
555status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
556        KeyedVector<String8, String8> &infoMap) const {
557    Mutex::Autolock autoLock(mLock);
558
559    if (mInitCheck != OK) {
560        return mInitCheck;
561    }
562
563    DrmSessionManager::Instance()->useSession(sessionId);
564
565    ::KeyedVector hInfoMap;
566
567    status_t err = UNKNOWN_ERROR;
568
569    Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
570            [&](Status status, const hidl_vec<KeyValue>& map) {
571                if (status == Status::OK) {
572                    infoMap = toKeyedVector(map);
573                }
574                err = toStatusT(status);
575            }
576        );
577
578    return hResult.isOk() ? err : DEAD_OBJECT;
579}
580
581status_t DrmHal::getProvisionRequest(String8 const &certType,
582        String8 const &certAuthority, Vector<uint8_t> &request,
583        String8 &defaultUrl) {
584    Mutex::Autolock autoLock(mLock);
585
586    if (mInitCheck != OK) {
587        return mInitCheck;
588    }
589
590    status_t err = UNKNOWN_ERROR;
591
592    Return<void> hResult = mPlugin->getProvisionRequest(
593            toHidlString(certType), toHidlString(certAuthority),
594            [&](Status status, const hidl_vec<uint8_t>& hRequest,
595                    const hidl_string& hDefaultUrl) {
596                if (status == Status::OK) {
597                    request = toVector(hRequest);
598                    defaultUrl = toString8(hDefaultUrl);
599                }
600                err = toStatusT(status);
601            }
602        );
603
604    return hResult.isOk() ? err : DEAD_OBJECT;
605}
606
607status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
608        Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
609    Mutex::Autolock autoLock(mLock);
610
611    if (mInitCheck != OK) {
612        return mInitCheck;
613    }
614
615    status_t err = UNKNOWN_ERROR;
616
617    Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
618            [&](Status status, const hidl_vec<uint8_t>& hCertificate,
619                    const hidl_vec<uint8_t>& hWrappedKey) {
620                if (status == Status::OK) {
621                    certificate = toVector(hCertificate);
622                    wrappedKey = toVector(hWrappedKey);
623                }
624                err = toStatusT(status);
625            }
626        );
627
628    return hResult.isOk() ? err : DEAD_OBJECT;
629}
630
631status_t DrmHal::getSecureStops(List<Vector<uint8_t> > &secureStops) {
632    Mutex::Autolock autoLock(mLock);
633
634    if (mInitCheck != OK) {
635        return mInitCheck;
636    }
637
638    status_t err = UNKNOWN_ERROR;
639
640    Return<void> hResult = mPlugin->getSecureStops(
641            [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
642                if (status == Status::OK) {
643                    secureStops = toSecureStops(hSecureStops);
644                }
645                err = toStatusT(status);
646            }
647    );
648
649    return hResult.isOk() ? err : DEAD_OBJECT;
650}
651
652
653status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
654    Mutex::Autolock autoLock(mLock);
655
656    if (mInitCheck != OK) {
657        return mInitCheck;
658    }
659
660    status_t err = UNKNOWN_ERROR;
661
662    Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
663            [&](Status status, const SecureStop& hSecureStop) {
664                if (status == Status::OK) {
665                    secureStop = toVector(hSecureStop.opaqueData);
666                }
667                err = toStatusT(status);
668            }
669    );
670
671    return hResult.isOk() ? err : DEAD_OBJECT;
672}
673
674status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
675    Mutex::Autolock autoLock(mLock);
676
677    if (mInitCheck != OK) {
678        return mInitCheck;
679    }
680
681    return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
682}
683
684status_t DrmHal::releaseAllSecureStops() {
685    Mutex::Autolock autoLock(mLock);
686
687    if (mInitCheck != OK) {
688        return mInitCheck;
689    }
690
691    return toStatusT(mPlugin->releaseAllSecureStops());
692}
693
694status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
695    Mutex::Autolock autoLock(mLock);
696
697    if (mInitCheck != OK) {
698        return mInitCheck;
699    }
700
701    status_t err = UNKNOWN_ERROR;
702
703    Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
704            [&](Status status, const hidl_string& hValue) {
705                if (status == Status::OK) {
706                    value = toString8(hValue);
707                }
708                err = toStatusT(status);
709            }
710    );
711
712    return hResult.isOk() ? err : DEAD_OBJECT;
713}
714
715status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
716    Mutex::Autolock autoLock(mLock);
717
718    if (mInitCheck != OK) {
719        return mInitCheck;
720    }
721
722    status_t err = UNKNOWN_ERROR;
723
724    Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
725            [&](Status status, const hidl_vec<uint8_t>& hValue) {
726                if (status == Status::OK) {
727                    value = toVector(hValue);
728                }
729                err = toStatusT(status);
730            }
731    );
732
733    return hResult.isOk() ? err : DEAD_OBJECT;
734}
735
736status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
737    Mutex::Autolock autoLock(mLock);
738
739    if (mInitCheck != OK) {
740        return mInitCheck;
741    }
742
743    Status status =  mPlugin->setPropertyString(toHidlString(name),
744            toHidlString(value));
745    return toStatusT(status);
746}
747
748status_t DrmHal::setPropertyByteArray(String8 const &name,
749                                   Vector<uint8_t> const &value ) const {
750    Mutex::Autolock autoLock(mLock);
751
752    if (mInitCheck != OK) {
753        return mInitCheck;
754    }
755
756    Status status = mPlugin->setPropertyByteArray(toHidlString(name),
757            toHidlVec(value));
758    return toStatusT(status);
759}
760
761
762status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
763                                 String8 const &algorithm) {
764    Mutex::Autolock autoLock(mLock);
765
766    if (mInitCheck != OK) {
767        return mInitCheck;
768    }
769
770    DrmSessionManager::Instance()->useSession(sessionId);
771
772    Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
773            toHidlString(algorithm));
774    return toStatusT(status);
775}
776
777status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
778                              String8 const &algorithm) {
779    Mutex::Autolock autoLock(mLock);
780
781    if (mInitCheck != OK) {
782        return mInitCheck;
783    }
784
785    DrmSessionManager::Instance()->useSession(sessionId);
786
787    Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
788            toHidlString(algorithm));
789    return toStatusT(status);
790}
791
792status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
793        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
794        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
795    Mutex::Autolock autoLock(mLock);
796
797    if (mInitCheck != OK) {
798        return mInitCheck;
799    }
800
801    DrmSessionManager::Instance()->useSession(sessionId);
802
803    status_t err = UNKNOWN_ERROR;
804
805    Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
806            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
807            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
808                if (status == Status::OK) {
809                    output = toVector(hOutput);
810                }
811                err = toStatusT(status);
812            }
813    );
814
815    return hResult.isOk() ? err : DEAD_OBJECT;
816}
817
818status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
819        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
820        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
821    Mutex::Autolock autoLock(mLock);
822
823    if (mInitCheck != OK) {
824        return mInitCheck;
825    }
826
827    DrmSessionManager::Instance()->useSession(sessionId);
828
829    status_t  err = UNKNOWN_ERROR;
830
831    Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
832            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
833            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
834                if (status == Status::OK) {
835                    output = toVector(hOutput);
836                }
837                err = toStatusT(status);
838            }
839    );
840
841    return hResult.isOk() ? err : DEAD_OBJECT;
842}
843
844status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
845        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
846        Vector<uint8_t> &signature) {
847    Mutex::Autolock autoLock(mLock);
848
849    if (mInitCheck != OK) {
850        return mInitCheck;
851    }
852
853    DrmSessionManager::Instance()->useSession(sessionId);
854
855    status_t err = UNKNOWN_ERROR;
856
857    Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
858            toHidlVec(keyId), toHidlVec(message),
859            [&](Status status, const hidl_vec<uint8_t>& hSignature)  {
860                if (status == Status::OK) {
861                    signature = toVector(hSignature);
862                }
863                err = toStatusT(status);
864            }
865    );
866
867    return hResult.isOk() ? err : DEAD_OBJECT;
868}
869
870status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
871        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
872        Vector<uint8_t> const &signature, 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, Vector<uint8_t> const &message,
900        Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
901    Mutex::Autolock autoLock(mLock);
902
903    if (mInitCheck != OK) {
904        return mInitCheck;
905    }
906
907    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
908        return -EPERM;
909    }
910
911    DrmSessionManager::Instance()->useSession(sessionId);
912
913    status_t err = UNKNOWN_ERROR;
914
915    Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
916            toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
917            [&](Status status, const hidl_vec<uint8_t>& hSignature) {
918                if (status == Status::OK) {
919                    signature = toVector(hSignature);
920                }
921                err = toStatusT(status);
922            }
923        );
924
925    return hResult.isOk() ? err : DEAD_OBJECT;
926}
927
928void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
929{
930    mEventLock.lock();
931    mListener.clear();
932    mEventLock.unlock();
933
934    Mutex::Autolock autoLock(mLock);
935    mPlugin.clear();
936}
937
938void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
939{
940    if (vec.size()) {
941        obj.writeInt32(vec.size());
942        obj.write(vec.data(), vec.size());
943    } else {
944        obj.writeInt32(0);
945    }
946}
947
948}  // namespace android
949