Home | History | Annotate | Download | only in libmediadrm
      1 /*
      2  * Copyright (C) 2013 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 "Drm"
     19 #include <utils/Log.h>
     20 
     21 #include <dirent.h>
     22 #include <dlfcn.h>
     23 
     24 #include <media/DrmSessionClientInterface.h>
     25 #include <media/DrmSessionManager.h>
     26 #include <media/Drm.h>
     27 #include <media/drm/DrmAPI.h>
     28 #include <media/stagefright/foundation/ADebug.h>
     29 #include <media/stagefright/foundation/AString.h>
     30 #include <media/stagefright/foundation/hexdump.h>
     31 #include <media/stagefright/MediaErrors.h>
     32 #include <binder/IServiceManager.h>
     33 #include <binder/IPCThreadState.h>
     34 
     35 namespace android {
     36 
     37 static inline int getCallingPid() {
     38     return IPCThreadState::self()->getCallingPid();
     39 }
     40 
     41 static bool checkPermission(const char* permissionString) {
     42     if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
     43     bool ok = checkCallingPermission(String16(permissionString));
     44     if (!ok) ALOGE("Request requires %s", permissionString);
     45     return ok;
     46 }
     47 
     48 KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;
     49 KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;
     50 Mutex Drm::mMapLock;
     51 Mutex Drm::mLock;
     52 
     53 static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) {
     54     if (lhs.size() < rhs.size()) {
     55         return true;
     56     } else if (lhs.size() > rhs.size()) {
     57         return false;
     58     }
     59 
     60     return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
     61 }
     62 
     63 struct DrmSessionClient : public DrmSessionClientInterface {
     64     DrmSessionClient(Drm* drm) : mDrm(drm) {}
     65 
     66     virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
     67         sp<Drm> drm = mDrm.promote();
     68         if (drm == NULL) {
     69             return true;
     70         }
     71         status_t err = drm->closeSession(sessionId);
     72         if (err != OK) {
     73             return false;
     74         }
     75         drm->sendEvent(DrmPlugin::kDrmPluginEventSessionReclaimed, 0, &sessionId, NULL);
     76         return true;
     77     }
     78 
     79 protected:
     80     virtual ~DrmSessionClient() {}
     81 
     82 private:
     83     wp<Drm> mDrm;
     84 
     85     DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
     86 };
     87 
     88 Drm::Drm()
     89     : mInitCheck(NO_INIT),
     90       mDrmSessionClient(new DrmSessionClient(this)),
     91       mListener(NULL),
     92       mFactory(NULL),
     93       mPlugin(NULL) {
     94 }
     95 
     96 Drm::~Drm() {
     97     DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
     98     delete mPlugin;
     99     mPlugin = NULL;
    100     closeFactory();
    101 }
    102 
    103 void Drm::closeFactory() {
    104     delete mFactory;
    105     mFactory = NULL;
    106     mLibrary.clear();
    107 }
    108 
    109 status_t Drm::initCheck() const {
    110     return mInitCheck;
    111 }
    112 
    113 status_t Drm::setListener(const sp<IDrmClient>& listener)
    114 {
    115     Mutex::Autolock lock(mEventLock);
    116     if (mListener != NULL){
    117         IInterface::asBinder(mListener)->unlinkToDeath(this);
    118     }
    119     if (listener != NULL) {
    120         IInterface::asBinder(listener)->linkToDeath(this);
    121     }
    122     mListener = listener;
    123     return NO_ERROR;
    124 }
    125 
    126 void Drm::sendEvent(DrmPlugin::EventType eventType, int extra,
    127                     Vector<uint8_t> const *sessionId,
    128                     Vector<uint8_t> const *data)
    129 {
    130     mEventLock.lock();
    131     sp<IDrmClient> listener = mListener;
    132     mEventLock.unlock();
    133 
    134     if (listener != NULL) {
    135         Parcel obj;
    136         writeByteArray(obj, sessionId);
    137         writeByteArray(obj, data);
    138 
    139         Mutex::Autolock lock(mNotifyLock);
    140         listener->notify(eventType, extra, &obj);
    141     }
    142 }
    143 
    144 void Drm::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
    145                                int64_t expiryTimeInMS)
    146 {
    147     mEventLock.lock();
    148     sp<IDrmClient> listener = mListener;
    149     mEventLock.unlock();
    150 
    151     if (listener != NULL) {
    152         Parcel obj;
    153         writeByteArray(obj, sessionId);
    154         obj.writeInt64(expiryTimeInMS);
    155 
    156         Mutex::Autolock lock(mNotifyLock);
    157         listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
    158     }
    159 }
    160 
    161 void Drm::sendKeysChange(Vector<uint8_t> const *sessionId,
    162                          Vector<DrmPlugin::KeyStatus> const *keyStatusList,
    163                          bool hasNewUsableKey)
    164 {
    165     mEventLock.lock();
    166     sp<IDrmClient> listener = mListener;
    167     mEventLock.unlock();
    168 
    169     if (listener != NULL) {
    170         Parcel obj;
    171         writeByteArray(obj, sessionId);
    172 
    173         size_t nkeys = keyStatusList->size();
    174         obj.writeInt32(keyStatusList->size());
    175         for (size_t i = 0; i < nkeys; ++i) {
    176             const DrmPlugin::KeyStatus *keyStatus = &keyStatusList->itemAt(i);
    177             writeByteArray(obj, &keyStatus->mKeyId);
    178             obj.writeInt32(keyStatus->mType);
    179         }
    180         obj.writeInt32(hasNewUsableKey);
    181 
    182         Mutex::Autolock lock(mNotifyLock);
    183         listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
    184     }
    185 }
    186 
    187 /*
    188  * Search the plugins directory for a plugin that supports the scheme
    189  * specified by uuid
    190  *
    191  * If found:
    192  *    mLibrary holds a strong pointer to the dlopen'd library
    193  *    mFactory is set to the library's factory method
    194  *    mInitCheck is set to OK
    195  *
    196  * If not found:
    197  *    mLibrary is cleared and mFactory are set to NULL
    198  *    mInitCheck is set to an error (!OK)
    199  */
    200 void Drm::findFactoryForScheme(const uint8_t uuid[16]) {
    201 
    202     closeFactory();
    203 
    204     // lock static maps
    205     Mutex::Autolock autoLock(mMapLock);
    206 
    207     // first check cache
    208     Vector<uint8_t> uuidVector;
    209     uuidVector.appendArray(uuid, sizeof(uuid[0]) * 16);
    210     ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector);
    211     if (index >= 0) {
    212         if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) {
    213             mInitCheck = OK;
    214             return;
    215         } else {
    216             ALOGE("Failed to load from cached library path!");
    217             mInitCheck = ERROR_UNSUPPORTED;
    218             return;
    219         }
    220     }
    221 
    222     // no luck, have to search
    223     String8 dirPath("/vendor/lib/mediadrm");
    224     DIR* pDir = opendir(dirPath.string());
    225 
    226     if (pDir == NULL) {
    227         mInitCheck = ERROR_UNSUPPORTED;
    228         ALOGE("Failed to open plugin directory %s", dirPath.string());
    229         return;
    230     }
    231 
    232 
    233     struct dirent* pEntry;
    234     while ((pEntry = readdir(pDir))) {
    235 
    236         String8 pluginPath = dirPath + "/" + pEntry->d_name;
    237 
    238         if (pluginPath.getPathExtension() == ".so") {
    239 
    240             if (loadLibraryForScheme(pluginPath, uuid)) {
    241                 mUUIDToLibraryPathMap.add(uuidVector, pluginPath);
    242                 mInitCheck = OK;
    243                 closedir(pDir);
    244                 return;
    245             }
    246         }
    247     }
    248 
    249     closedir(pDir);
    250 
    251     ALOGE("Failed to find drm plugin");
    252     mInitCheck = ERROR_UNSUPPORTED;
    253 }
    254 
    255 bool Drm::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) {
    256 
    257     // get strong pointer to open shared library
    258     ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
    259     if (index >= 0) {
    260         mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
    261     } else {
    262         index = mLibraryPathToOpenLibraryMap.add(path, NULL);
    263     }
    264 
    265     if (!mLibrary.get()) {
    266         mLibrary = new SharedLibrary(path);
    267         if (!*mLibrary) {
    268             return false;
    269         }
    270 
    271         mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
    272     }
    273 
    274     typedef DrmFactory *(*CreateDrmFactoryFunc)();
    275 
    276     CreateDrmFactoryFunc createDrmFactory =
    277         (CreateDrmFactoryFunc)mLibrary->lookup("createDrmFactory");
    278 
    279     if (createDrmFactory == NULL ||
    280         (mFactory = createDrmFactory()) == NULL ||
    281         !mFactory->isCryptoSchemeSupported(uuid)) {
    282         closeFactory();
    283         return false;
    284     }
    285     return true;
    286 }
    287 
    288 bool Drm::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
    289 
    290     Mutex::Autolock autoLock(mLock);
    291 
    292     if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
    293         findFactoryForScheme(uuid);
    294         if (mInitCheck != OK) {
    295             return false;
    296         }
    297     }
    298 
    299     if (mimeType != "") {
    300         return mFactory->isContentTypeSupported(mimeType);
    301     }
    302 
    303     return true;
    304 }
    305 
    306 status_t Drm::createPlugin(const uint8_t uuid[16]) {
    307     Mutex::Autolock autoLock(mLock);
    308 
    309     if (mPlugin != NULL) {
    310         return -EINVAL;
    311     }
    312 
    313     if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
    314         findFactoryForScheme(uuid);
    315     }
    316 
    317     if (mInitCheck != OK) {
    318         return mInitCheck;
    319     }
    320 
    321     status_t result = mFactory->createDrmPlugin(uuid, &mPlugin);
    322     mPlugin->setListener(this);
    323     return result;
    324 }
    325 
    326 status_t Drm::destroyPlugin() {
    327     Mutex::Autolock autoLock(mLock);
    328 
    329     if (mInitCheck != OK) {
    330         return mInitCheck;
    331     }
    332 
    333     if (mPlugin == NULL) {
    334         return -EINVAL;
    335     }
    336 
    337     delete mPlugin;
    338     mPlugin = NULL;
    339 
    340     return OK;
    341 }
    342 
    343 status_t Drm::openSession(Vector<uint8_t> &sessionId) {
    344     Mutex::Autolock autoLock(mLock);
    345 
    346     if (mInitCheck != OK) {
    347         return mInitCheck;
    348     }
    349 
    350     if (mPlugin == NULL) {
    351         return -EINVAL;
    352     }
    353 
    354     status_t err = mPlugin->openSession(sessionId);
    355     if (err == ERROR_DRM_RESOURCE_BUSY) {
    356         bool retry = false;
    357         mLock.unlock();
    358         // reclaimSession may call back to closeSession, since mLock is shared between Drm
    359         // instances, we should unlock here to avoid deadlock.
    360         retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
    361         mLock.lock();
    362         if (mInitCheck != OK) {
    363             return mInitCheck;
    364         }
    365 
    366         if (mPlugin == NULL) {
    367             return -EINVAL;
    368         }
    369         if (retry) {
    370             err = mPlugin->openSession(sessionId);
    371         }
    372     }
    373     if (err == OK) {
    374         DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId);
    375     }
    376     return err;
    377 }
    378 
    379 status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
    380     Mutex::Autolock autoLock(mLock);
    381 
    382     if (mInitCheck != OK) {
    383         return mInitCheck;
    384     }
    385 
    386     if (mPlugin == NULL) {
    387         return -EINVAL;
    388     }
    389 
    390     status_t err = mPlugin->closeSession(sessionId);
    391     if (err == OK) {
    392         DrmSessionManager::Instance()->removeSession(sessionId);
    393     }
    394     return err;
    395 }
    396 
    397 status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
    398                             Vector<uint8_t> const &initData,
    399                             String8 const &mimeType, DrmPlugin::KeyType keyType,
    400                             KeyedVector<String8, String8> const &optionalParameters,
    401                             Vector<uint8_t> &request, String8 &defaultUrl,
    402                             DrmPlugin::KeyRequestType *keyRequestType) {
    403     Mutex::Autolock autoLock(mLock);
    404 
    405     if (mInitCheck != OK) {
    406         return mInitCheck;
    407     }
    408 
    409     if (mPlugin == NULL) {
    410         return -EINVAL;
    411     }
    412 
    413     DrmSessionManager::Instance()->useSession(sessionId);
    414 
    415     return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType,
    416                                   optionalParameters, request, defaultUrl,
    417                                   keyRequestType);
    418 }
    419 
    420 status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId,
    421                                  Vector<uint8_t> const &response,
    422                                  Vector<uint8_t> &keySetId) {
    423     Mutex::Autolock autoLock(mLock);
    424 
    425     if (mInitCheck != OK) {
    426         return mInitCheck;
    427     }
    428 
    429     if (mPlugin == NULL) {
    430         return -EINVAL;
    431     }
    432 
    433     DrmSessionManager::Instance()->useSession(sessionId);
    434 
    435     return mPlugin->provideKeyResponse(sessionId, response, keySetId);
    436 }
    437 
    438 status_t Drm::removeKeys(Vector<uint8_t> const &keySetId) {
    439     Mutex::Autolock autoLock(mLock);
    440 
    441     if (mInitCheck != OK) {
    442         return mInitCheck;
    443     }
    444 
    445     if (mPlugin == NULL) {
    446         return -EINVAL;
    447     }
    448 
    449     return mPlugin->removeKeys(keySetId);
    450 }
    451 
    452 status_t Drm::restoreKeys(Vector<uint8_t> const &sessionId,
    453                           Vector<uint8_t> const &keySetId) {
    454     Mutex::Autolock autoLock(mLock);
    455 
    456     if (mInitCheck != OK) {
    457         return mInitCheck;
    458     }
    459 
    460     if (mPlugin == NULL) {
    461         return -EINVAL;
    462     }
    463 
    464     DrmSessionManager::Instance()->useSession(sessionId);
    465 
    466     return mPlugin->restoreKeys(sessionId, keySetId);
    467 }
    468 
    469 status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId,
    470                              KeyedVector<String8, String8> &infoMap) const {
    471     Mutex::Autolock autoLock(mLock);
    472 
    473     if (mInitCheck != OK) {
    474         return mInitCheck;
    475     }
    476 
    477     if (mPlugin == NULL) {
    478         return -EINVAL;
    479     }
    480 
    481     DrmSessionManager::Instance()->useSession(sessionId);
    482 
    483     return mPlugin->queryKeyStatus(sessionId, infoMap);
    484 }
    485 
    486 status_t Drm::getProvisionRequest(String8 const &certType, String8 const &certAuthority,
    487                                   Vector<uint8_t> &request, String8 &defaultUrl) {
    488     Mutex::Autolock autoLock(mLock);
    489 
    490     if (mInitCheck != OK) {
    491         return mInitCheck;
    492     }
    493 
    494     if (mPlugin == NULL) {
    495         return -EINVAL;
    496     }
    497 
    498     return mPlugin->getProvisionRequest(certType, certAuthority,
    499                                         request, defaultUrl);
    500 }
    501 
    502 status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response,
    503                                        Vector<uint8_t> &certificate,
    504                                        Vector<uint8_t> &wrappedKey) {
    505     Mutex::Autolock autoLock(mLock);
    506 
    507     if (mInitCheck != OK) {
    508         return mInitCheck;
    509     }
    510 
    511     if (mPlugin == NULL) {
    512         return -EINVAL;
    513     }
    514 
    515     return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);
    516 }
    517 
    518 status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) {
    519     Mutex::Autolock autoLock(mLock);
    520 
    521     if (mInitCheck != OK) {
    522         return mInitCheck;
    523     }
    524 
    525     if (mPlugin == NULL) {
    526         return -EINVAL;
    527     }
    528 
    529     return mPlugin->getSecureStops(secureStops);
    530 }
    531 
    532 status_t Drm::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
    533     Mutex::Autolock autoLock(mLock);
    534 
    535     if (mInitCheck != OK) {
    536         return mInitCheck;
    537     }
    538 
    539     if (mPlugin == NULL) {
    540         return -EINVAL;
    541     }
    542 
    543     return mPlugin->getSecureStop(ssid, secureStop);
    544 }
    545 
    546 status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
    547     Mutex::Autolock autoLock(mLock);
    548 
    549     if (mInitCheck != OK) {
    550         return mInitCheck;
    551     }
    552 
    553     if (mPlugin == NULL) {
    554         return -EINVAL;
    555     }
    556 
    557     return mPlugin->releaseSecureStops(ssRelease);
    558 }
    559 
    560 status_t Drm::releaseAllSecureStops() {
    561     Mutex::Autolock autoLock(mLock);
    562 
    563     if (mInitCheck != OK) {
    564         return mInitCheck;
    565     }
    566 
    567     if (mPlugin == NULL) {
    568         return -EINVAL;
    569     }
    570 
    571     return mPlugin->releaseAllSecureStops();
    572 }
    573 
    574 status_t Drm::getPropertyString(String8 const &name, String8 &value ) const {
    575     Mutex::Autolock autoLock(mLock);
    576 
    577     if (mInitCheck != OK) {
    578         return mInitCheck;
    579     }
    580 
    581     if (mPlugin == NULL) {
    582         return -EINVAL;
    583     }
    584 
    585     return mPlugin->getPropertyString(name, value);
    586 }
    587 
    588 status_t Drm::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
    589     Mutex::Autolock autoLock(mLock);
    590 
    591     if (mInitCheck != OK) {
    592         return mInitCheck;
    593     }
    594 
    595     if (mPlugin == NULL) {
    596         return -EINVAL;
    597     }
    598 
    599     return mPlugin->getPropertyByteArray(name, value);
    600 }
    601 
    602 status_t Drm::setPropertyString(String8 const &name, String8 const &value ) const {
    603     Mutex::Autolock autoLock(mLock);
    604 
    605     if (mInitCheck != OK) {
    606         return mInitCheck;
    607     }
    608 
    609     if (mPlugin == NULL) {
    610         return -EINVAL;
    611     }
    612 
    613     return mPlugin->setPropertyString(name, value);
    614 }
    615 
    616 status_t Drm::setPropertyByteArray(String8 const &name,
    617                                    Vector<uint8_t> const &value ) const {
    618     Mutex::Autolock autoLock(mLock);
    619 
    620     if (mInitCheck != OK) {
    621         return mInitCheck;
    622     }
    623 
    624     if (mPlugin == NULL) {
    625         return -EINVAL;
    626     }
    627 
    628     return mPlugin->setPropertyByteArray(name, value);
    629 }
    630 
    631 
    632 status_t Drm::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
    633                                  String8 const &algorithm) {
    634     Mutex::Autolock autoLock(mLock);
    635 
    636     if (mInitCheck != OK) {
    637         return mInitCheck;
    638     }
    639 
    640     if (mPlugin == NULL) {
    641         return -EINVAL;
    642     }
    643 
    644     DrmSessionManager::Instance()->useSession(sessionId);
    645 
    646     return mPlugin->setCipherAlgorithm(sessionId, algorithm);
    647 }
    648 
    649 status_t Drm::setMacAlgorithm(Vector<uint8_t> const &sessionId,
    650                               String8 const &algorithm) {
    651     Mutex::Autolock autoLock(mLock);
    652 
    653     if (mInitCheck != OK) {
    654         return mInitCheck;
    655     }
    656 
    657     if (mPlugin == NULL) {
    658         return -EINVAL;
    659     }
    660 
    661     DrmSessionManager::Instance()->useSession(sessionId);
    662 
    663     return mPlugin->setMacAlgorithm(sessionId, algorithm);
    664 }
    665 
    666 status_t Drm::encrypt(Vector<uint8_t> const &sessionId,
    667                       Vector<uint8_t> const &keyId,
    668                       Vector<uint8_t> const &input,
    669                       Vector<uint8_t> const &iv,
    670                       Vector<uint8_t> &output) {
    671     Mutex::Autolock autoLock(mLock);
    672 
    673     if (mInitCheck != OK) {
    674         return mInitCheck;
    675     }
    676 
    677     if (mPlugin == NULL) {
    678         return -EINVAL;
    679     }
    680 
    681     DrmSessionManager::Instance()->useSession(sessionId);
    682 
    683     return mPlugin->encrypt(sessionId, keyId, input, iv, output);
    684 }
    685 
    686 status_t Drm::decrypt(Vector<uint8_t> const &sessionId,
    687                       Vector<uint8_t> const &keyId,
    688                       Vector<uint8_t> const &input,
    689                       Vector<uint8_t> const &iv,
    690                       Vector<uint8_t> &output) {
    691     Mutex::Autolock autoLock(mLock);
    692 
    693     if (mInitCheck != OK) {
    694         return mInitCheck;
    695     }
    696 
    697     if (mPlugin == NULL) {
    698         return -EINVAL;
    699     }
    700 
    701     DrmSessionManager::Instance()->useSession(sessionId);
    702 
    703     return mPlugin->decrypt(sessionId, keyId, input, iv, output);
    704 }
    705 
    706 status_t Drm::sign(Vector<uint8_t> const &sessionId,
    707                    Vector<uint8_t> const &keyId,
    708                    Vector<uint8_t> const &message,
    709                    Vector<uint8_t> &signature) {
    710     Mutex::Autolock autoLock(mLock);
    711 
    712     if (mInitCheck != OK) {
    713         return mInitCheck;
    714     }
    715 
    716     if (mPlugin == NULL) {
    717         return -EINVAL;
    718     }
    719 
    720     DrmSessionManager::Instance()->useSession(sessionId);
    721 
    722     return mPlugin->sign(sessionId, keyId, message, signature);
    723 }
    724 
    725 status_t Drm::verify(Vector<uint8_t> const &sessionId,
    726                      Vector<uint8_t> const &keyId,
    727                      Vector<uint8_t> const &message,
    728                      Vector<uint8_t> const &signature,
    729                      bool &match) {
    730     Mutex::Autolock autoLock(mLock);
    731 
    732     if (mInitCheck != OK) {
    733         return mInitCheck;
    734     }
    735 
    736     if (mPlugin == NULL) {
    737         return -EINVAL;
    738     }
    739 
    740     DrmSessionManager::Instance()->useSession(sessionId);
    741 
    742     return mPlugin->verify(sessionId, keyId, message, signature, match);
    743 }
    744 
    745 status_t Drm::signRSA(Vector<uint8_t> const &sessionId,
    746                       String8 const &algorithm,
    747                       Vector<uint8_t> const &message,
    748                       Vector<uint8_t> const &wrappedKey,
    749                       Vector<uint8_t> &signature) {
    750     Mutex::Autolock autoLock(mLock);
    751 
    752     if (mInitCheck != OK) {
    753         return mInitCheck;
    754     }
    755 
    756     if (mPlugin == NULL) {
    757         return -EINVAL;
    758     }
    759 
    760     if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
    761         return -EPERM;
    762     }
    763 
    764     DrmSessionManager::Instance()->useSession(sessionId);
    765 
    766     return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
    767 }
    768 
    769 void Drm::binderDied(const wp<IBinder> &the_late_who __unused)
    770 {
    771     mEventLock.lock();
    772     mListener.clear();
    773     mEventLock.unlock();
    774 
    775     Mutex::Autolock autoLock(mLock);
    776     delete mPlugin;
    777     mPlugin = NULL;
    778     closeFactory();
    779 }
    780 
    781 void Drm::writeByteArray(Parcel &obj, Vector<uint8_t> const *array)
    782 {
    783     if (array && array->size()) {
    784         obj.writeInt32(array->size());
    785         obj.write(array->array(), array->size());
    786     } else {
    787         obj.writeInt32(0);
    788     }
    789 }
    790 
    791 }  // namespace android
    792