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