DrmHal.cpp revision 319d5f43d196ca1fc26c5d6169ae0bdd14a81d54
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    return plugin;
261}
262
263status_t DrmHal::initCheck() const {
264    return mInitCheck;
265}
266
267status_t DrmHal::setListener(const sp<IDrmClient>& listener)
268{
269    Mutex::Autolock lock(mEventLock);
270    if (mListener != NULL){
271        IInterface::asBinder(mListener)->unlinkToDeath(this);
272    }
273    if (listener != NULL) {
274        IInterface::asBinder(listener)->linkToDeath(this);
275    }
276    mListener = listener;
277    return NO_ERROR;
278}
279
280Return<void> DrmHal::sendEvent(EventType hEventType,
281        const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
282
283    mEventLock.lock();
284    sp<IDrmClient> listener = mListener;
285    mEventLock.unlock();
286
287    if (listener != NULL) {
288        Parcel obj;
289        writeByteArray(obj, sessionId);
290        writeByteArray(obj, data);
291
292        Mutex::Autolock lock(mNotifyLock);
293        DrmPlugin::EventType eventType;
294        switch(hEventType) {
295        case EventType::PROVISION_REQUIRED:
296            eventType = DrmPlugin::kDrmPluginEventProvisionRequired;
297            break;
298        case EventType::KEY_NEEDED:
299            eventType = DrmPlugin::kDrmPluginEventKeyNeeded;
300            break;
301        case EventType::KEY_EXPIRED:
302            eventType = DrmPlugin::kDrmPluginEventKeyExpired;
303            break;
304        case EventType::VENDOR_DEFINED:
305            eventType = DrmPlugin::kDrmPluginEventVendorDefined;
306            break;
307        case EventType::SESSION_RECLAIMED:
308            eventType = DrmPlugin::kDrmPluginEventSessionReclaimed;
309            break;
310        default:
311            return Void();
312        }
313        listener->notify(eventType, 0, &obj);
314    }
315    return Void();
316}
317
318Return<void> DrmHal::sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
319        int64_t expiryTimeInMS) {
320
321    mEventLock.lock();
322    sp<IDrmClient> listener = mListener;
323    mEventLock.unlock();
324
325    if (listener != NULL) {
326        Parcel obj;
327        writeByteArray(obj, sessionId);
328        obj.writeInt64(expiryTimeInMS);
329
330        Mutex::Autolock lock(mNotifyLock);
331        listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
332    }
333    return Void();
334}
335
336Return<void> DrmHal::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
337        const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
338
339    mEventLock.lock();
340    sp<IDrmClient> listener = mListener;
341    mEventLock.unlock();
342
343    if (listener != NULL) {
344        Parcel obj;
345        writeByteArray(obj, sessionId);
346
347        size_t nKeys = keyStatusList.size();
348        obj.writeInt32(nKeys);
349        for (size_t i = 0; i < nKeys; ++i) {
350            const KeyStatus &keyStatus = keyStatusList[i];
351            writeByteArray(obj, keyStatus.keyId);
352            uint32_t type;
353            switch(keyStatus.type) {
354            case KeyStatusType::USABLE:
355                type = DrmPlugin::kKeyStatusType_Usable;
356                break;
357            case KeyStatusType::EXPIRED:
358                type = DrmPlugin::kKeyStatusType_Expired;
359                break;
360            case KeyStatusType::OUTPUTNOTALLOWED:
361                type = DrmPlugin::kKeyStatusType_OutputNotAllowed;
362                break;
363            case KeyStatusType::STATUSPENDING:
364                type = DrmPlugin::kKeyStatusType_StatusPending;
365                break;
366            case KeyStatusType::INTERNALERROR:
367            default:
368                type = DrmPlugin::kKeyStatusType_InternalError;
369                break;
370            }
371            obj.writeInt32(type);
372        }
373        obj.writeInt32(hasNewUsableKey);
374
375        Mutex::Autolock lock(mNotifyLock);
376        listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
377    }
378    return Void();
379}
380
381bool DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
382    Mutex::Autolock autoLock(mLock);
383
384    for (size_t i = 0; i < mFactories.size(); i++) {
385        if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
386            if (mimeType != "") {
387                if (mFactories[i]->isContentTypeSupported(mimeType.string())) {
388                    return true;
389                }
390            } else {
391                return true;
392            }
393        }
394    }
395    return false;
396}
397
398status_t DrmHal::createPlugin(const uint8_t uuid[16],
399        const String8& appPackageName) {
400    Mutex::Autolock autoLock(mLock);
401
402    for (size_t i = 0; i < mFactories.size(); i++) {
403        if (mFactories[i]->isCryptoSchemeSupported(uuid)) {
404            mPlugin = makeDrmPlugin(mFactories[i], uuid, appPackageName);
405        }
406    }
407
408    if (mPlugin == NULL) {
409        mInitCheck = ERROR_UNSUPPORTED;
410    } else {
411        if (!mPlugin->setListener(this).isOk()) {
412            mInitCheck = DEAD_OBJECT;
413        } else {
414            mInitCheck = OK;
415        }
416    }
417
418    return mInitCheck;
419}
420
421status_t DrmHal::destroyPlugin() {
422    Mutex::Autolock autoLock(mLock);
423    if (mInitCheck != OK) {
424        return mInitCheck;
425    }
426
427    closeOpenSessions();
428    reportMetrics();
429    setListener(NULL);
430    mInitCheck = NO_INIT;
431
432    if (mPlugin != NULL) {
433        if (!mPlugin->setListener(NULL).isOk()) {
434            mInitCheck = DEAD_OBJECT;
435        }
436    }
437    mPlugin.clear();
438    return OK;
439}
440
441status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
442    Mutex::Autolock autoLock(mLock);
443
444    if (mInitCheck != OK) {
445        return mInitCheck;
446    }
447
448    status_t  err = UNKNOWN_ERROR;
449
450    bool retry = true;
451    do {
452        hidl_vec<uint8_t> hSessionId;
453
454        Return<void> hResult = mPlugin->openSession(
455                [&](Status status, const hidl_vec<uint8_t>& id) {
456                    if (status == Status::OK) {
457                        sessionId = toVector(id);
458                    }
459                    err = toStatusT(status);
460                }
461            );
462
463        if (!hResult.isOk()) {
464            err = DEAD_OBJECT;
465        }
466
467        if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
468            mLock.unlock();
469            // reclaimSession may call back to closeSession, since mLock is
470            // shared between Drm instances, we should unlock here to avoid
471            // deadlock.
472            retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
473            mLock.lock();
474        } else {
475            retry = false;
476        }
477    } while (retry);
478
479    if (err == OK) {
480        DrmSessionManager::Instance()->addSession(getCallingPid(),
481                mDrmSessionClient, sessionId);
482        mOpenSessions.push(sessionId);
483    }
484    return err;
485}
486
487status_t DrmHal::closeSession(Vector<uint8_t> const &sessionId) {
488    Mutex::Autolock autoLock(mLock);
489
490    if (mInitCheck != OK) {
491        return mInitCheck;
492    }
493
494    Return<Status> status = mPlugin->closeSession(toHidlVec(sessionId));
495    if (status.isOk()) {
496        if (status == Status::OK) {
497            DrmSessionManager::Instance()->removeSession(sessionId);
498            for (size_t i = 0; i < mOpenSessions.size(); i++) {
499                if (mOpenSessions[i] == sessionId) {
500                    mOpenSessions.removeAt(i);
501                    break;
502                }
503            }
504        }
505        reportMetrics();
506        return toStatusT(status);
507    }
508    return DEAD_OBJECT;
509}
510
511status_t DrmHal::getKeyRequest(Vector<uint8_t> const &sessionId,
512        Vector<uint8_t> const &initData, String8 const &mimeType,
513        DrmPlugin::KeyType keyType, KeyedVector<String8,
514        String8> const &optionalParameters, Vector<uint8_t> &request,
515        String8 &defaultUrl, DrmPlugin::KeyRequestType *keyRequestType) {
516    Mutex::Autolock autoLock(mLock);
517
518    if (mInitCheck != OK) {
519        return mInitCheck;
520    }
521
522    DrmSessionManager::Instance()->useSession(sessionId);
523
524    KeyType hKeyType;
525    if (keyType == DrmPlugin::kKeyType_Streaming) {
526        hKeyType = KeyType::STREAMING;
527    } else if (keyType == DrmPlugin::kKeyType_Offline) {
528        hKeyType = KeyType::OFFLINE;
529    } else if (keyType == DrmPlugin::kKeyType_Release) {
530        hKeyType = KeyType::RELEASE;
531    } else {
532        return BAD_VALUE;
533    }
534
535    ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
536
537    status_t err = UNKNOWN_ERROR;
538
539    Return<void> hResult = mPlugin->getKeyRequest(toHidlVec(sessionId),
540            toHidlVec(initData), toHidlString(mimeType), hKeyType, hOptionalParameters,
541            [&](Status status, const hidl_vec<uint8_t>& hRequest,
542                    KeyRequestType hKeyRequestType, const hidl_string& hDefaultUrl) {
543
544                if (status == Status::OK) {
545                    request = toVector(hRequest);
546                    defaultUrl = toString8(hDefaultUrl);
547
548                    switch (hKeyRequestType) {
549                    case KeyRequestType::INITIAL:
550                        *keyRequestType = DrmPlugin::kKeyRequestType_Initial;
551                        break;
552                    case KeyRequestType::RENEWAL:
553                        *keyRequestType = DrmPlugin::kKeyRequestType_Renewal;
554                        break;
555                    case KeyRequestType::RELEASE:
556                        *keyRequestType = DrmPlugin::kKeyRequestType_Release;
557                        break;
558                    default:
559                        *keyRequestType = DrmPlugin::kKeyRequestType_Unknown;
560                        break;
561                    }
562                    err = toStatusT(status);
563                }
564            });
565
566    return hResult.isOk() ? err : DEAD_OBJECT;
567}
568
569status_t DrmHal::provideKeyResponse(Vector<uint8_t> const &sessionId,
570        Vector<uint8_t> const &response, Vector<uint8_t> &keySetId) {
571    Mutex::Autolock autoLock(mLock);
572
573    if (mInitCheck != OK) {
574        return mInitCheck;
575    }
576
577    DrmSessionManager::Instance()->useSession(sessionId);
578
579    status_t err = UNKNOWN_ERROR;
580
581    Return<void> hResult = mPlugin->provideKeyResponse(toHidlVec(sessionId),
582            toHidlVec(response),
583            [&](Status status, const hidl_vec<uint8_t>& hKeySetId) {
584                if (status == Status::OK) {
585                    keySetId = toVector(hKeySetId);
586                }
587                err = toStatusT(status);
588            }
589        );
590
591    return hResult.isOk() ? err : DEAD_OBJECT;
592}
593
594status_t DrmHal::removeKeys(Vector<uint8_t> const &keySetId) {
595    Mutex::Autolock autoLock(mLock);
596
597    if (mInitCheck != OK) {
598        return mInitCheck;
599    }
600
601    return toStatusT(mPlugin->removeKeys(toHidlVec(keySetId)));
602}
603
604status_t DrmHal::restoreKeys(Vector<uint8_t> const &sessionId,
605        Vector<uint8_t> const &keySetId) {
606    Mutex::Autolock autoLock(mLock);
607
608    if (mInitCheck != OK) {
609        return mInitCheck;
610    }
611
612    DrmSessionManager::Instance()->useSession(sessionId);
613
614    return toStatusT(mPlugin->restoreKeys(toHidlVec(sessionId),
615                    toHidlVec(keySetId)));
616}
617
618status_t DrmHal::queryKeyStatus(Vector<uint8_t> const &sessionId,
619        KeyedVector<String8, String8> &infoMap) const {
620    Mutex::Autolock autoLock(mLock);
621
622    if (mInitCheck != OK) {
623        return mInitCheck;
624    }
625
626    DrmSessionManager::Instance()->useSession(sessionId);
627
628    ::KeyedVector hInfoMap;
629
630    status_t err = UNKNOWN_ERROR;
631
632    Return<void> hResult = mPlugin->queryKeyStatus(toHidlVec(sessionId),
633            [&](Status status, const hidl_vec<KeyValue>& map) {
634                if (status == Status::OK) {
635                    infoMap = toKeyedVector(map);
636                }
637                err = toStatusT(status);
638            }
639        );
640
641    return hResult.isOk() ? err : DEAD_OBJECT;
642}
643
644status_t DrmHal::getProvisionRequest(String8 const &certType,
645        String8 const &certAuthority, Vector<uint8_t> &request,
646        String8 &defaultUrl) {
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->getProvisionRequest(
656            toHidlString(certType), toHidlString(certAuthority),
657            [&](Status status, const hidl_vec<uint8_t>& hRequest,
658                    const hidl_string& hDefaultUrl) {
659                if (status == Status::OK) {
660                    request = toVector(hRequest);
661                    defaultUrl = toString8(hDefaultUrl);
662                }
663                err = toStatusT(status);
664            }
665        );
666
667    return hResult.isOk() ? err : DEAD_OBJECT;
668}
669
670status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const &response,
671        Vector<uint8_t> &certificate, Vector<uint8_t> &wrappedKey) {
672    Mutex::Autolock autoLock(mLock);
673
674    if (mInitCheck != OK) {
675        return mInitCheck;
676    }
677
678    status_t err = UNKNOWN_ERROR;
679
680    Return<void> hResult = mPlugin->provideProvisionResponse(toHidlVec(response),
681            [&](Status status, const hidl_vec<uint8_t>& hCertificate,
682                    const hidl_vec<uint8_t>& hWrappedKey) {
683                if (status == Status::OK) {
684                    certificate = toVector(hCertificate);
685                    wrappedKey = toVector(hWrappedKey);
686                }
687                err = toStatusT(status);
688            }
689        );
690
691    return hResult.isOk() ? err : DEAD_OBJECT;
692}
693
694status_t DrmHal::getSecureStops(List<Vector<uint8_t>> &secureStops) {
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->getSecureStops(
704            [&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
705                if (status == Status::OK) {
706                    secureStops = toSecureStops(hSecureStops);
707                }
708                err = toStatusT(status);
709            }
710    );
711
712    return hResult.isOk() ? err : DEAD_OBJECT;
713}
714
715
716status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
717    Mutex::Autolock autoLock(mLock);
718
719    if (mInitCheck != OK) {
720        return mInitCheck;
721    }
722
723    status_t err = UNKNOWN_ERROR;
724
725    Return<void> hResult = mPlugin->getSecureStop(toHidlVec(ssid),
726            [&](Status status, const SecureStop& hSecureStop) {
727                if (status == Status::OK) {
728                    secureStop = toVector(hSecureStop.opaqueData);
729                }
730                err = toStatusT(status);
731            }
732    );
733
734    return hResult.isOk() ? err : DEAD_OBJECT;
735}
736
737status_t DrmHal::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
738    Mutex::Autolock autoLock(mLock);
739
740    if (mInitCheck != OK) {
741        return mInitCheck;
742    }
743
744    return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
745}
746
747status_t DrmHal::releaseAllSecureStops() {
748    Mutex::Autolock autoLock(mLock);
749
750    if (mInitCheck != OK) {
751        return mInitCheck;
752    }
753
754    return toStatusT(mPlugin->releaseAllSecureStops());
755}
756
757status_t DrmHal::getPropertyString(String8 const &name, String8 &value ) const {
758    Mutex::Autolock autoLock(mLock);
759    return getPropertyStringInternal(name, value);
760}
761
762status_t DrmHal::getPropertyStringInternal(String8 const &name, String8 &value) const {
763    // This function is internal to the class and should only be called while
764    // mLock is already held.
765
766    if (mInitCheck != OK) {
767        return mInitCheck;
768    }
769
770    status_t err = UNKNOWN_ERROR;
771
772    Return<void> hResult = mPlugin->getPropertyString(toHidlString(name),
773            [&](Status status, const hidl_string& hValue) {
774                if (status == Status::OK) {
775                    value = toString8(hValue);
776                }
777                err = toStatusT(status);
778            }
779    );
780
781    return hResult.isOk() ? err : DEAD_OBJECT;
782}
783
784status_t DrmHal::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
785    Mutex::Autolock autoLock(mLock);
786    return getPropertyByteArrayInternal(name, value);
787}
788
789status_t DrmHal::getPropertyByteArrayInternal(String8 const &name, Vector<uint8_t> &value ) const {
790    // This function is internal to the class and should only be called while
791    // mLock is already held.
792
793    if (mInitCheck != OK) {
794        return mInitCheck;
795    }
796
797    status_t err = UNKNOWN_ERROR;
798
799    Return<void> hResult = mPlugin->getPropertyByteArray(toHidlString(name),
800            [&](Status status, const hidl_vec<uint8_t>& hValue) {
801                if (status == Status::OK) {
802                    value = toVector(hValue);
803                }
804                err = toStatusT(status);
805            }
806    );
807
808    return hResult.isOk() ? err : DEAD_OBJECT;
809}
810
811status_t DrmHal::setPropertyString(String8 const &name, String8 const &value ) const {
812    Mutex::Autolock autoLock(mLock);
813
814    if (mInitCheck != OK) {
815        return mInitCheck;
816    }
817
818    Status status =  mPlugin->setPropertyString(toHidlString(name),
819            toHidlString(value));
820    return toStatusT(status);
821}
822
823status_t DrmHal::setPropertyByteArray(String8 const &name,
824                                   Vector<uint8_t> const &value ) const {
825    Mutex::Autolock autoLock(mLock);
826
827    if (mInitCheck != OK) {
828        return mInitCheck;
829    }
830
831    Status status = mPlugin->setPropertyByteArray(toHidlString(name),
832            toHidlVec(value));
833    return toStatusT(status);
834}
835
836
837status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
838                                 String8 const &algorithm) {
839    Mutex::Autolock autoLock(mLock);
840
841    if (mInitCheck != OK) {
842        return mInitCheck;
843    }
844
845    DrmSessionManager::Instance()->useSession(sessionId);
846
847    Status status = mPlugin->setCipherAlgorithm(toHidlVec(sessionId),
848            toHidlString(algorithm));
849    return toStatusT(status);
850}
851
852status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const &sessionId,
853                              String8 const &algorithm) {
854    Mutex::Autolock autoLock(mLock);
855
856    if (mInitCheck != OK) {
857        return mInitCheck;
858    }
859
860    DrmSessionManager::Instance()->useSession(sessionId);
861
862    Status status = mPlugin->setMacAlgorithm(toHidlVec(sessionId),
863            toHidlString(algorithm));
864    return toStatusT(status);
865}
866
867status_t DrmHal::encrypt(Vector<uint8_t> const &sessionId,
868        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
869        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
870    Mutex::Autolock autoLock(mLock);
871
872    if (mInitCheck != OK) {
873        return mInitCheck;
874    }
875
876    DrmSessionManager::Instance()->useSession(sessionId);
877
878    status_t err = UNKNOWN_ERROR;
879
880    Return<void> hResult = mPlugin->encrypt(toHidlVec(sessionId),
881            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
882            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
883                if (status == Status::OK) {
884                    output = toVector(hOutput);
885                }
886                err = toStatusT(status);
887            }
888    );
889
890    return hResult.isOk() ? err : DEAD_OBJECT;
891}
892
893status_t DrmHal::decrypt(Vector<uint8_t> const &sessionId,
894        Vector<uint8_t> const &keyId, Vector<uint8_t> const &input,
895        Vector<uint8_t> const &iv, Vector<uint8_t> &output) {
896    Mutex::Autolock autoLock(mLock);
897
898    if (mInitCheck != OK) {
899        return mInitCheck;
900    }
901
902    DrmSessionManager::Instance()->useSession(sessionId);
903
904    status_t  err = UNKNOWN_ERROR;
905
906    Return<void> hResult = mPlugin->decrypt(toHidlVec(sessionId),
907            toHidlVec(keyId), toHidlVec(input), toHidlVec(iv),
908            [&](Status status, const hidl_vec<uint8_t>& hOutput) {
909                if (status == Status::OK) {
910                    output = toVector(hOutput);
911                }
912                err = toStatusT(status);
913            }
914    );
915
916    return hResult.isOk() ? err : DEAD_OBJECT;
917}
918
919status_t DrmHal::sign(Vector<uint8_t> const &sessionId,
920        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
921        Vector<uint8_t> &signature) {
922    Mutex::Autolock autoLock(mLock);
923
924    if (mInitCheck != OK) {
925        return mInitCheck;
926    }
927
928    DrmSessionManager::Instance()->useSession(sessionId);
929
930    status_t err = UNKNOWN_ERROR;
931
932    Return<void> hResult = mPlugin->sign(toHidlVec(sessionId),
933            toHidlVec(keyId), toHidlVec(message),
934            [&](Status status, const hidl_vec<uint8_t>& hSignature)  {
935                if (status == Status::OK) {
936                    signature = toVector(hSignature);
937                }
938                err = toStatusT(status);
939            }
940    );
941
942    return hResult.isOk() ? err : DEAD_OBJECT;
943}
944
945status_t DrmHal::verify(Vector<uint8_t> const &sessionId,
946        Vector<uint8_t> const &keyId, Vector<uint8_t> const &message,
947        Vector<uint8_t> const &signature, bool &match) {
948    Mutex::Autolock autoLock(mLock);
949
950    if (mInitCheck != OK) {
951        return mInitCheck;
952    }
953
954    DrmSessionManager::Instance()->useSession(sessionId);
955
956    status_t err = UNKNOWN_ERROR;
957
958    Return<void> hResult = mPlugin->verify(toHidlVec(sessionId),toHidlVec(keyId),
959            toHidlVec(message), toHidlVec(signature),
960            [&](Status status, bool hMatch) {
961                if (status == Status::OK) {
962                    match = hMatch;
963                } else {
964                    match = false;
965                }
966                err = toStatusT(status);
967            }
968    );
969
970    return hResult.isOk() ? err : DEAD_OBJECT;
971}
972
973status_t DrmHal::signRSA(Vector<uint8_t> const &sessionId,
974        String8 const &algorithm, Vector<uint8_t> const &message,
975        Vector<uint8_t> const &wrappedKey, Vector<uint8_t> &signature) {
976    Mutex::Autolock autoLock(mLock);
977
978    if (mInitCheck != OK) {
979        return mInitCheck;
980    }
981
982    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
983        return -EPERM;
984    }
985
986    DrmSessionManager::Instance()->useSession(sessionId);
987
988    status_t err = UNKNOWN_ERROR;
989
990    Return<void> hResult = mPlugin->signRSA(toHidlVec(sessionId),
991            toHidlString(algorithm), toHidlVec(message), toHidlVec(wrappedKey),
992            [&](Status status, const hidl_vec<uint8_t>& hSignature) {
993                if (status == Status::OK) {
994                    signature = toVector(hSignature);
995                }
996                err = toStatusT(status);
997            }
998        );
999
1000    return hResult.isOk() ? err : DEAD_OBJECT;
1001}
1002
1003void DrmHal::binderDied(const wp<IBinder> &the_late_who __unused)
1004{
1005    Mutex::Autolock autoLock(mLock);
1006    closeOpenSessions();
1007    setListener(NULL);
1008    mInitCheck = NO_INIT;
1009
1010    if (mPlugin != NULL) {
1011        if (!mPlugin->setListener(NULL).isOk()) {
1012            mInitCheck = DEAD_OBJECT;
1013        }
1014    }
1015    mPlugin.clear();
1016}
1017
1018void DrmHal::writeByteArray(Parcel &obj, hidl_vec<uint8_t> const &vec)
1019{
1020    if (vec.size()) {
1021        obj.writeInt32(vec.size());
1022        obj.write(vec.data(), vec.size());
1023    } else {
1024        obj.writeInt32(0);
1025    }
1026}
1027
1028void DrmHal::reportMetrics() const
1029{
1030    Vector<uint8_t> metrics;
1031    String8 vendor;
1032    String8 description;
1033    if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
1034            getPropertyStringInternal(String8("description"), description) == OK &&
1035            getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
1036        status_t res = android::reportDrmPluginMetrics(
1037                metrics, vendor, description);
1038        if (res != OK) {
1039            ALOGE("Metrics were retrieved but could not be reported: %i", res);
1040        }
1041    }
1042}
1043
1044}  // namespace android
1045