Home | History | Annotate | Download | only in hidl
      1 /*
      2  * Copyright (C) 2018 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 "hidl_ClearKeyPlugin"
     19 #include <utils/Log.h>
     20 
     21 #include <stdio.h>
     22 #include <inttypes.h>
     23 
     24 #include "DrmPlugin.h"
     25 #include "ClearKeyDrmProperties.h"
     26 #include "Session.h"
     27 #include "TypeConvert.h"
     28 #include "Utils.h"
     29 
     30 namespace {
     31 const std::string kKeySetIdPrefix("ckid");
     32 const int kKeySetIdLength = 16;
     33 const int kSecureStopIdStart = 100;
     34 const std::string kOfflineLicense("\"type\":\"persistent-license\"");
     35 const std::string kStreaming("Streaming");
     36 const std::string kTemporaryLicense("\"type\":\"temporary\"");
     37 const std::string kTrue("True");
     38 
     39 const std::string kQueryKeyLicenseType("LicenseType");
     40     // Value: "Streaming" or "Offline"
     41 const std::string kQueryKeyPlayAllowed("PlayAllowed");
     42     // Value: "True" or "False"
     43 const std::string kQueryKeyRenewAllowed("RenewAllowed");
     44     // Value: "True" or "False"
     45 
     46 const int kSecureStopIdSize = 10;
     47 
     48 std::vector<uint8_t> uint32ToVector(uint32_t value) {
     49     // 10 bytes to display max value 4294967295 + one byte null terminator
     50     char buffer[kSecureStopIdSize];
     51     memset(buffer, 0, kSecureStopIdSize);
     52     snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value);
     53     return std::vector<uint8_t>(buffer, buffer + sizeof(buffer));
     54 }
     55 
     56 }; // unnamed namespace
     57 
     58 namespace android {
     59 namespace hardware {
     60 namespace drm {
     61 namespace V1_2 {
     62 namespace clearkey {
     63 
     64 KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) {
     65   switch (keyRequestType) {
     66     case KeyRequestType_V1_1::NONE:
     67     case KeyRequestType_V1_1::UPDATE:
     68       return KeyRequestType::UNKNOWN;
     69     default:
     70       return static_cast<KeyRequestType>(keyRequestType);
     71   }
     72 }
     73 
     74 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
     75         : mSessionLibrary(sessionLibrary),
     76           mOpenSessionOkCount(0),
     77           mCloseSessionOkCount(0),
     78           mCloseSessionNotOpenedCount(0),
     79           mNextSecureStopId(kSecureStopIdStart),
     80           mMockError(Status_V1_2::OK) {
     81     mPlayPolicy.clear();
     82     initProperties();
     83     mSecureStops.clear();
     84     mReleaseKeysMap.clear();
     85     std::srand(std::time(nullptr));
     86 }
     87 
     88 void DrmPlugin::initProperties() {
     89     mStringProperties.clear();
     90     mStringProperties[kVendorKey] = kVendorValue;
     91     mStringProperties[kVersionKey] = kVersionValue;
     92     mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
     93     mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
     94     mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
     95     mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
     96 
     97     std::vector<uint8_t> valueVector;
     98     valueVector.clear();
     99     valueVector.insert(valueVector.end(),
    100             kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
    101     mByteArrayProperties[kDeviceIdKey] = valueVector;
    102 
    103     valueVector.clear();
    104     valueVector.insert(valueVector.end(),
    105             kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
    106     mByteArrayProperties[kMetricsKey] = valueVector;
    107 }
    108 
    109 // The secure stop in ClearKey implementation is not installed securely.
    110 // This function merely creates a test environment for testing secure stops APIs.
    111 // The content in this secure stop is implementation dependent, the clearkey
    112 // secureStop does not serve as a reference implementation.
    113 void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) {
    114     ClearkeySecureStop clearkeySecureStop;
    115     clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId);
    116     clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end());
    117 
    118     mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>(
    119             clearkeySecureStop.id, clearkeySecureStop));
    120 }
    121 
    122 Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
    123     sp<Session> session = mSessionLibrary->createSession();
    124     processMockError(session);
    125     std::vector<uint8_t> sessionId = session->sessionId();
    126 
    127     Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
    128     _hidl_cb(status, toHidlVec(sessionId));
    129     mOpenSessionOkCount++;
    130     return Void();
    131 }
    132 
    133 Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
    134         openSession_1_1_cb _hidl_cb) {
    135     sp<Session> session = mSessionLibrary->createSession();
    136     processMockError(session);
    137     std::vector<uint8_t> sessionId = session->sessionId();
    138 
    139     Status status = setSecurityLevel(sessionId, securityLevel);
    140     _hidl_cb(status, toHidlVec(sessionId));
    141     mOpenSessionOkCount++;
    142     return Void();
    143 }
    144 
    145 Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
    146     if (sessionId.size() == 0) {
    147         return Status::BAD_VALUE;
    148     }
    149 
    150     sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
    151     if (session.get()) {
    152         if (session->getMockError() != Status_V1_2::OK) {
    153             sendSessionLostState(sessionId);
    154             return Status::ERROR_DRM_INVALID_STATE;
    155         }
    156         mCloseSessionOkCount++;
    157         mSessionLibrary->destroySession(session);
    158         return Status::OK;
    159     }
    160     mCloseSessionNotOpenedCount++;
    161     return Status::ERROR_DRM_SESSION_NOT_OPENED;
    162 }
    163 
    164 Status_V1_2 DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
    165         const hidl_vec<uint8_t>& initData,
    166         const hidl_string& mimeType,
    167         KeyType keyType,
    168         const hidl_vec<KeyValue>& optionalParameters,
    169         std::vector<uint8_t> *request,
    170         KeyRequestType_V1_1 *keyRequestType,
    171         std::string *defaultUrl) {
    172         UNUSED(optionalParameters);
    173 
    174     // GetKeyRequestOfflineKeyTypeNotSupported() in vts 1.0 and 1.1 expects
    175     // KeyType::OFFLINE to return ERROR_DRM_CANNOT_HANDLE in clearkey plugin.
    176     // Those tests pass in an empty initData, we use the empty initData to
    177     // signal such specific use case.
    178     if (keyType == KeyType::OFFLINE && 0 == initData.size()) {
    179         return Status_V1_2::ERROR_DRM_CANNOT_HANDLE;
    180     }
    181 
    182     *defaultUrl = "";
    183     *keyRequestType = KeyRequestType_V1_1::UNKNOWN;
    184     *request = std::vector<uint8_t>();
    185 
    186     if (scope.size() == 0 ||
    187             (keyType != KeyType::STREAMING &&
    188             keyType != KeyType::OFFLINE &&
    189             keyType != KeyType::RELEASE)) {
    190         return Status_V1_2::BAD_VALUE;
    191     }
    192 
    193     const std::vector<uint8_t> scopeId = toVector(scope);
    194     sp<Session> session;
    195     if (keyType == KeyType::STREAMING || keyType == KeyType::OFFLINE) {
    196         std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end());
    197         session = mSessionLibrary->findSession(sessionId);
    198         if (!session.get()) {
    199             return Status_V1_2::ERROR_DRM_SESSION_NOT_OPENED;
    200         } else if (session->getMockError() != Status_V1_2::OK) {
    201             return session->getMockError();
    202         }
    203 
    204         *keyRequestType = KeyRequestType_V1_1::INITIAL;
    205     }
    206 
    207     Status_V1_2 status = static_cast<Status_V1_2>(
    208             session->getKeyRequest(initData, mimeType, keyType, request));
    209 
    210     if (keyType == KeyType::RELEASE) {
    211         std::vector<uint8_t> keySetId(scopeId.begin(), scopeId.end());
    212         std::string requestString(request->begin(), request->end());
    213         if (requestString.find(kOfflineLicense) != std::string::npos) {
    214             std::string emptyResponse;
    215             std::string keySetIdString(keySetId.begin(), keySetId.end());
    216             if (!mFileHandle.StoreLicense(keySetIdString,
    217                     DeviceFiles::kLicenseStateReleasing,
    218                     emptyResponse)) {
    219                 ALOGE("Problem releasing offline license");
    220                 return Status_V1_2::ERROR_DRM_UNKNOWN;
    221             }
    222             if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) {
    223                 sp<Session> session = mSessionLibrary->createSession();
    224                 mReleaseKeysMap[keySetIdString] = session->sessionId();
    225             } else {
    226                 ALOGI("key is in use, ignore release request");
    227             }
    228         } else {
    229             ALOGE("Offline license not found, nothing to release");
    230         }
    231         *keyRequestType = KeyRequestType_V1_1::RELEASE;
    232     }
    233     return status;
    234 }
    235 
    236 Return<void> DrmPlugin::getKeyRequest(
    237         const hidl_vec<uint8_t>& scope,
    238         const hidl_vec<uint8_t>& initData,
    239         const hidl_string& mimeType,
    240         KeyType keyType,
    241         const hidl_vec<KeyValue>& optionalParameters,
    242         getKeyRequest_cb _hidl_cb) {
    243     UNUSED(optionalParameters);
    244 
    245     KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
    246     std::string defaultUrl("");
    247     std::vector<uint8_t> request;
    248     Status_V1_2 status = getKeyRequestCommon(
    249             scope, initData, mimeType, keyType, optionalParameters,
    250             &request, &keyRequestType, &defaultUrl);
    251 
    252     _hidl_cb(toStatus_1_0(status), toHidlVec(request),
    253             toKeyRequestType_V1_0(keyRequestType),
    254             hidl_string(defaultUrl));
    255     return Void();
    256 }
    257 
    258 Return<void> DrmPlugin::getKeyRequest_1_1(
    259         const hidl_vec<uint8_t>& scope,
    260         const hidl_vec<uint8_t>& initData,
    261         const hidl_string& mimeType,
    262         KeyType keyType,
    263         const hidl_vec<KeyValue>& optionalParameters,
    264         getKeyRequest_1_1_cb _hidl_cb) {
    265     UNUSED(optionalParameters);
    266 
    267     KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
    268     std::string defaultUrl("");
    269     std::vector<uint8_t> request;
    270     Status_V1_2 status = getKeyRequestCommon(
    271             scope, initData, mimeType, keyType, optionalParameters,
    272             &request, &keyRequestType, &defaultUrl);
    273 
    274     _hidl_cb(toStatus_1_0(status), toHidlVec(request),
    275             keyRequestType, hidl_string(defaultUrl));
    276     return Void();
    277 }
    278 
    279 Return<void> DrmPlugin::getKeyRequest_1_2(
    280         const hidl_vec<uint8_t>& scope,
    281         const hidl_vec<uint8_t>& initData,
    282         const hidl_string& mimeType,
    283         KeyType keyType,
    284         const hidl_vec<KeyValue>& optionalParameters,
    285         getKeyRequest_1_2_cb _hidl_cb) {
    286     UNUSED(optionalParameters);
    287 
    288     KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
    289     std::string defaultUrl("");
    290     std::vector<uint8_t> request;
    291     Status_V1_2 status = getKeyRequestCommon(
    292             scope, initData, mimeType, keyType, optionalParameters,
    293             &request, &keyRequestType, &defaultUrl);
    294 
    295     _hidl_cb(status, toHidlVec(request), keyRequestType, hidl_string(defaultUrl));
    296     return Void();
    297 }
    298 
    299 void DrmPlugin::setPlayPolicy() {
    300     mPlayPolicy.clear();
    301 
    302     KeyValue policy;
    303     policy.key = kQueryKeyLicenseType;
    304     policy.value = kStreaming;
    305     mPlayPolicy.push_back(policy);
    306 
    307     policy.key = kQueryKeyPlayAllowed;
    308     policy.value = kTrue;
    309     mPlayPolicy.push_back(policy);
    310 
    311     policy.key = kQueryKeyRenewAllowed;
    312     mPlayPolicy.push_back(policy);
    313 }
    314 
    315 bool DrmPlugin::makeKeySetId(std::string* keySetId) {
    316     if (!keySetId) {
    317         ALOGE("keySetId destination not provided");
    318         return false;
    319     }
    320     std::vector<uint8_t> ksid(kKeySetIdPrefix.begin(), kKeySetIdPrefix.end());
    321     ksid.resize(kKeySetIdLength);
    322     std::vector<uint8_t> randomData((kKeySetIdLength - kKeySetIdPrefix.size()) / 2, 0);
    323 
    324     while (keySetId->empty()) {
    325         for (auto itr = randomData.begin(); itr != randomData.end(); ++itr) {
    326             *itr = std::rand() % 0xff;
    327         }
    328         *keySetId = kKeySetIdPrefix + ByteArrayToHexString(
    329                 reinterpret_cast<const uint8_t*>(randomData.data()), randomData.size());
    330         if (mFileHandle.LicenseExists(*keySetId)) {
    331             // collision, regenerate
    332             ALOGV("Retry generating KeySetId");
    333             keySetId->clear();
    334         }
    335     }
    336     return true;
    337 }
    338 
    339 Return<void> DrmPlugin::provideKeyResponse(
    340         const hidl_vec<uint8_t>& scope,
    341         const hidl_vec<uint8_t>& response,
    342         provideKeyResponse_cb _hidl_cb) {
    343     if (scope.size() == 0 || response.size() == 0) {
    344         // Returns empty keySetId
    345         _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
    346         return Void();
    347     }
    348 
    349     std::string responseString(
    350             reinterpret_cast<const char*>(response.data()), response.size());
    351     const std::vector<uint8_t> scopeId = toVector(scope);
    352     std::vector<uint8_t> sessionId;
    353     std::string keySetId;
    354 
    355     Status status = Status::OK;
    356     bool isOfflineLicense = responseString.find(kOfflineLicense) != std::string::npos;
    357     bool isRelease = (memcmp(scopeId.data(), kKeySetIdPrefix.data(), kKeySetIdPrefix.size()) == 0);
    358     if (isRelease) {
    359         keySetId.assign(scopeId.begin(), scopeId.end());
    360 
    361         auto iter = mReleaseKeysMap.find(std::string(keySetId.begin(), keySetId.end()));
    362         if (iter != mReleaseKeysMap.end()) {
    363             sessionId.assign(iter->second.begin(), iter->second.end());
    364         }
    365     } else {
    366         sessionId.assign(scopeId.begin(), scopeId.end());
    367         // non offline license returns empty keySetId
    368         keySetId.clear();
    369     }
    370 
    371     sp<Session> session = mSessionLibrary->findSession(sessionId);
    372     if (!session.get()) {
    373         _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
    374         return Void();
    375     }
    376     setPlayPolicy();
    377 
    378     status = session->provideKeyResponse(response);
    379     if (status == Status::OK) {
    380         if (isOfflineLicense) {
    381             if (isRelease) {
    382                 mFileHandle.DeleteLicense(keySetId);
    383             } else {
    384                 if (!makeKeySetId(&keySetId)) {
    385                     _hidl_cb(Status::ERROR_DRM_UNKNOWN, hidl_vec<uint8_t>());
    386                     return Void();
    387                 }
    388 
    389                 bool ok = mFileHandle.StoreLicense(
    390                         keySetId,
    391                         DeviceFiles::kLicenseStateActive,
    392                         std::string(response.begin(), response.end()));
    393                 if (!ok) {
    394                     ALOGE("Failed to store offline license");
    395                 }
    396             }
    397         }
    398 
    399         // Test calling AMediaDrm listeners.
    400         sendEvent(EventType::VENDOR_DEFINED, sessionId, sessionId);
    401 
    402         sendExpirationUpdate(sessionId, 100);
    403 
    404         std::vector<KeyStatus_V1_2> keysStatus;
    405         KeyStatus_V1_2 keyStatus;
    406 
    407         std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC };
    408         keyStatus.keyId = keyId1;
    409         keyStatus.type = V1_2::KeyStatusType::USABLE;
    410         keysStatus.push_back(keyStatus);
    411 
    412         std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF };
    413         keyStatus.keyId = keyId2;
    414         keyStatus.type = V1_2::KeyStatusType::EXPIRED;
    415         keysStatus.push_back(keyStatus);
    416 
    417         std::vector<uint8_t> keyId3 = { 0x0, 0x1, 0x2 };
    418         keyStatus.keyId = keyId3;
    419         keyStatus.type = V1_2::KeyStatusType::USABLEINFUTURE;
    420         keysStatus.push_back(keyStatus);
    421 
    422         sendKeysChange_1_2(sessionId, keysStatus, true);
    423 
    424         installSecureStop(sessionId);
    425     } else {
    426         ALOGE("provideKeyResponse returns error=%d", status);
    427     }
    428 
    429     std::vector<uint8_t> keySetIdVec(keySetId.begin(), keySetId.end());
    430     _hidl_cb(status, toHidlVec(keySetIdVec));
    431     return Void();
    432 }
    433 
    434 Return<Status> DrmPlugin::restoreKeys(
    435         const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& keySetId) {
    436         if (sessionId.size() == 0 || keySetId.size() == 0) {
    437             return Status::BAD_VALUE;
    438         }
    439 
    440         DeviceFiles::LicenseState licenseState;
    441         std::string offlineLicense;
    442         Status status = Status::OK;
    443         if (!mFileHandle.RetrieveLicense(std::string(keySetId.begin(), keySetId.end()),
    444                 &licenseState, &offlineLicense)) {
    445             ALOGE("Failed to restore offline license");
    446             return Status::ERROR_DRM_NO_LICENSE;
    447         }
    448 
    449         if (DeviceFiles::kLicenseStateUnknown == licenseState ||
    450                 DeviceFiles::kLicenseStateReleasing == licenseState) {
    451             ALOGE("Invalid license state=%d", licenseState);
    452             return Status::ERROR_DRM_NO_LICENSE;
    453         }
    454 
    455         sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
    456         if (!session.get()) {
    457             return Status::ERROR_DRM_SESSION_NOT_OPENED;
    458         }
    459         status = session->provideKeyResponse(std::vector<uint8_t>(offlineLicense.begin(),
    460                 offlineLicense.end()));
    461         if (status != Status::OK) {
    462             ALOGE("Failed to restore keys");
    463         }
    464         return status;
    465 }
    466 
    467 Return<void> DrmPlugin::getPropertyString(
    468         const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
    469     std::string name(propertyName.c_str());
    470     std::string value;
    471 
    472     if (name == kVendorKey) {
    473         value = mStringProperties[kVendorKey];
    474     } else if (name == kVersionKey) {
    475         value = mStringProperties[kVersionKey];
    476     } else if (name == kPluginDescriptionKey) {
    477         value = mStringProperties[kPluginDescriptionKey];
    478     } else if (name == kAlgorithmsKey) {
    479         value = mStringProperties[kAlgorithmsKey];
    480     } else if (name == kListenerTestSupportKey) {
    481         value = mStringProperties[kListenerTestSupportKey];
    482     } else if (name == kDrmErrorTestKey) {
    483         value = mStringProperties[kDrmErrorTestKey];
    484     } else {
    485         ALOGE("App requested unknown string property %s", name.c_str());
    486         _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
    487         return Void();
    488     }
    489     _hidl_cb(Status::OK, value.c_str());
    490     return Void();
    491 }
    492 
    493 Return<void> DrmPlugin::getPropertyByteArray(
    494         const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
    495     std::map<std::string, std::vector<uint8_t> >::iterator itr =
    496             mByteArrayProperties.find(std::string(propertyName.c_str()));
    497     if (itr == mByteArrayProperties.end()) {
    498         ALOGE("App requested unknown property: %s", propertyName.c_str());
    499         _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
    500         return Void();
    501     }
    502     _hidl_cb(Status::OK, itr->second);
    503     return Void();
    504 
    505 }
    506 
    507 Return<Status> DrmPlugin::setPropertyString(
    508     const hidl_string& name, const hidl_string& value) {
    509     std::string immutableKeys;
    510     immutableKeys.append(kAlgorithmsKey + ",");
    511     immutableKeys.append(kPluginDescriptionKey + ",");
    512     immutableKeys.append(kVendorKey + ",");
    513     immutableKeys.append(kVersionKey + ",");
    514 
    515     std::string key = std::string(name.c_str());
    516     if (immutableKeys.find(key) != std::string::npos) {
    517         ALOGD("Cannot set immutable property: %s", key.c_str());
    518         return Status::BAD_VALUE;
    519     }
    520 
    521     std::map<std::string, std::string>::iterator itr =
    522             mStringProperties.find(key);
    523     if (itr == mStringProperties.end()) {
    524         ALOGE("Cannot set undefined property string, key=%s", key.c_str());
    525         return Status::BAD_VALUE;
    526     }
    527 
    528     if (name == kDrmErrorTestKey) {
    529         if (value == kResourceContentionValue) {
    530             mMockError = Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION;
    531         } else if (value == kLostStateValue) {
    532             mMockError = Status_V1_2::ERROR_DRM_SESSION_LOST_STATE;
    533         } else if (value == kFrameTooLargeValue) {
    534             mMockError = Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE;
    535         } else if (value == kInvalidStateValue)  {
    536             mMockError = Status_V1_2::ERROR_DRM_INVALID_STATE;
    537         } else {
    538             mMockError = Status_V1_2::ERROR_DRM_UNKNOWN;
    539         }
    540     }
    541 
    542     mStringProperties[key] = std::string(value.c_str());
    543     return Status::OK;
    544 }
    545 
    546 Return<Status> DrmPlugin::setPropertyByteArray(
    547     const hidl_string& name, const hidl_vec<uint8_t>& value) {
    548    UNUSED(value);
    549    if (name == kDeviceIdKey) {
    550       ALOGD("Cannot set immutable property: %s", name.c_str());
    551       return Status::BAD_VALUE;
    552    } else if (name == kClientIdKey) {
    553        mByteArrayProperties[kClientIdKey] = toVector(value);
    554        return Status::OK;
    555    }
    556 
    557    // Setting of undefined properties is not supported
    558    ALOGE("Failed to set property byte array, key=%s", name.c_str());
    559    return Status::ERROR_DRM_CANNOT_HANDLE;
    560 }
    561 
    562 Return<void> DrmPlugin::queryKeyStatus(
    563         const hidl_vec<uint8_t>& sessionId,
    564         queryKeyStatus_cb _hidl_cb) {
    565 
    566     if (sessionId.size() == 0) {
    567         // Returns empty key status KeyValue pair
    568         _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
    569         return Void();
    570     }
    571 
    572     std::vector<KeyValue> infoMapVec;
    573     infoMapVec.clear();
    574 
    575     KeyValue keyValuePair;
    576     for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
    577         keyValuePair.key = mPlayPolicy[i].key;
    578         keyValuePair.value = mPlayPolicy[i].value;
    579         infoMapVec.push_back(keyValuePair);
    580     }
    581     _hidl_cb(Status::OK, toHidlVec(infoMapVec));
    582     return Void();
    583 }
    584 
    585 Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
    586         uint32_t currentSessions = mSessionLibrary->numOpenSessions();
    587         uint32_t maxSessions = 10;
    588         _hidl_cb(Status::OK, currentSessions, maxSessions);
    589         return Void();
    590 }
    591 
    592 Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
    593             getSecurityLevel_cb _hidl_cb) {
    594     if (sessionId.size() == 0) {
    595         _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
    596         return Void();
    597     }
    598 
    599     std::vector<uint8_t> sid = toVector(sessionId);
    600     sp<Session> session = mSessionLibrary->findSession(sid);
    601     if (!session.get()) {
    602         _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
    603         return Void();
    604     }
    605 
    606     std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
    607             mSecurityLevel.find(sid);
    608     if (itr == mSecurityLevel.end()) {
    609         ALOGE("Session id not found");
    610         _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
    611         return Void();
    612     }
    613 
    614     _hidl_cb(Status::OK, itr->second);
    615     return Void();
    616 }
    617 
    618 Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
    619             SecurityLevel level) {
    620     if (sessionId.size() == 0) {
    621         ALOGE("Invalid empty session id");
    622         return Status::BAD_VALUE;
    623     }
    624 
    625     if (level > SecurityLevel::SW_SECURE_CRYPTO) {
    626         ALOGE("Cannot set security level > max");
    627         return Status::ERROR_DRM_CANNOT_HANDLE;
    628     }
    629 
    630     std::vector<uint8_t> sid = toVector(sessionId);
    631     sp<Session> session = mSessionLibrary->findSession(sid);
    632     if (!session.get()) {
    633         return Status::ERROR_DRM_SESSION_NOT_OPENED;
    634     }
    635 
    636     std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
    637             mSecurityLevel.find(sid);
    638     if (itr != mSecurityLevel.end()) {
    639         mSecurityLevel[sid] = level;
    640     } else {
    641         if (!mSecurityLevel.insert(
    642                 std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
    643             ALOGE("Failed to set security level");
    644             return Status::ERROR_DRM_INVALID_STATE;
    645         }
    646     }
    647     return Status::OK;
    648 }
    649 
    650 Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
    651     // Set the open session count metric.
    652     DrmMetricGroup::Attribute openSessionOkAttribute = {
    653       "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
    654     };
    655     DrmMetricGroup::Value openSessionMetricValue = {
    656       "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
    657     };
    658     DrmMetricGroup::Metric openSessionMetric = {
    659       "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
    660     };
    661 
    662     // Set the close session count metric.
    663     DrmMetricGroup::Attribute closeSessionOkAttribute = {
    664       "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
    665     };
    666     DrmMetricGroup::Value closeSessionMetricValue = {
    667       "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
    668     };
    669     DrmMetricGroup::Metric closeSessionMetric = {
    670       "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
    671     };
    672 
    673     // Set the close session, not opened metric.
    674     DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
    675       "status", DrmMetricGroup::ValueType::INT64_TYPE,
    676       (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
    677     };
    678     DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
    679       "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
    680     };
    681     DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
    682       "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
    683     };
    684 
    685     DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
    686                                 closeSessionNotOpenedMetric } };
    687 
    688     _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
    689     return Void();
    690 }
    691 
    692 Return<void> DrmPlugin::getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) {
    693     std::vector<std::string> licenseNames = mFileHandle.ListLicenses();
    694     std::vector<KeySetId> keySetIds;
    695     if (mMockError != Status_V1_2::OK) {
    696         _hidl_cb(toStatus_1_0(mMockError), keySetIds);
    697         return Void();
    698     }
    699     for (const auto& name : licenseNames) {
    700         std::vector<uint8_t> keySetId(name.begin(), name.end());
    701         keySetIds.push_back(keySetId);
    702     }
    703     _hidl_cb(Status::OK, keySetIds);
    704     return Void();
    705 }
    706 
    707 
    708 Return<Status> DrmPlugin::removeOfflineLicense(const KeySetId& keySetId) {
    709     if (mMockError != Status_V1_2::OK) {
    710         return toStatus_1_0(mMockError);
    711     }
    712     std::string licenseName(keySetId.begin(), keySetId.end());
    713     if (mFileHandle.DeleteLicense(licenseName)) {
    714         return Status::OK;
    715     }
    716     return Status::BAD_VALUE;
    717 }
    718 
    719 Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId,
    720         getOfflineLicenseState_cb _hidl_cb) {
    721     std::string licenseName(keySetId.begin(), keySetId.end());
    722     DeviceFiles::LicenseState state;
    723     std::string license;
    724     OfflineLicenseState hLicenseState;
    725     if (mMockError != Status_V1_2::OK) {
    726         _hidl_cb(toStatus_1_0(mMockError), OfflineLicenseState::UNKNOWN);
    727     } else if (mFileHandle.RetrieveLicense(licenseName, &state, &license)) {
    728         switch (state) {
    729         case DeviceFiles::kLicenseStateActive:
    730             hLicenseState = OfflineLicenseState::USABLE;
    731             break;
    732         case DeviceFiles::kLicenseStateReleasing:
    733             hLicenseState = OfflineLicenseState::INACTIVE;
    734             break;
    735         case DeviceFiles::kLicenseStateUnknown:
    736             hLicenseState = OfflineLicenseState::UNKNOWN;
    737             break;
    738         }
    739         _hidl_cb(Status::OK, hLicenseState);
    740     } else {
    741         _hidl_cb(Status::BAD_VALUE, OfflineLicenseState::UNKNOWN);
    742     }
    743     return Void();
    744 }
    745 
    746 Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
    747     std::vector<SecureStop> stops;
    748     for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
    749         ClearkeySecureStop clearkeyStop = itr->second;
    750         std::vector<uint8_t> stopVec;
    751         stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
    752         stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
    753 
    754         SecureStop stop;
    755         stop.opaqueData = toHidlVec(stopVec);
    756         stops.push_back(stop);
    757     }
    758     _hidl_cb(Status::OK, stops);
    759     return Void();
    760 }
    761 
    762 Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
    763         getSecureStop_cb _hidl_cb) {
    764     SecureStop stop;
    765     auto itr = mSecureStops.find(toVector(secureStopId));
    766     if (itr != mSecureStops.end()) {
    767         ClearkeySecureStop clearkeyStop = itr->second;
    768         std::vector<uint8_t> stopVec;
    769         stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
    770         stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
    771 
    772         stop.opaqueData = toHidlVec(stopVec);
    773         _hidl_cb(Status::OK, stop);
    774     } else {
    775         _hidl_cb(Status::BAD_VALUE, stop);
    776     }
    777 
    778     return Void();
    779 }
    780 
    781 Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) {
    782     return removeSecureStop(secureStopId);
    783 }
    784 
    785 Return<Status> DrmPlugin::releaseAllSecureStops() {
    786     return removeAllSecureStops();
    787 }
    788 
    789 Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
    790     std::vector<SecureStopId> ids;
    791     for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
    792         ids.push_back(itr->first);
    793     }
    794 
    795     _hidl_cb(Status::OK, toHidlVec(ids));
    796     return Void();
    797 }
    798 
    799 Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
    800     if (ssRelease.opaqueData.size() == 0) {
    801         return Status::BAD_VALUE;
    802     }
    803 
    804     Status status = Status::OK;
    805     std::vector<uint8_t> input = toVector(ssRelease.opaqueData);
    806 
    807     // The format of opaqueData is shared between the server
    808     // and the drm service. The clearkey implementation consists of:
    809     //    count - number of secure stops
    810     //    list of fixed length secure stops
    811     size_t countBufferSize = sizeof(uint32_t);
    812     uint32_t count = 0;
    813     sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
    814 
    815     // Avoid divide by 0 below.
    816     if (count == 0) {
    817         return Status::BAD_VALUE;
    818     }
    819 
    820     size_t secureStopSize = (input.size() - countBufferSize) / count;
    821     uint8_t buffer[secureStopSize];
    822     size_t offset = countBufferSize; // skip the count
    823     for (size_t i = 0; i < count; ++i, offset += secureStopSize) {
    824         memcpy(buffer, input.data() + offset, secureStopSize);
    825         std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
    826 
    827         status = removeSecureStop(toHidlVec(id));
    828         if (Status::OK != status) break;
    829     }
    830 
    831     return status;
    832 }
    833 
    834 Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
    835     if (1 != mSecureStops.erase(toVector(secureStopId))) {
    836         return Status::BAD_VALUE;
    837     }
    838     return Status::OK;
    839 }
    840 
    841 Return<Status> DrmPlugin::removeAllSecureStops() {
    842     mSecureStops.clear();
    843     mNextSecureStopId = kSecureStopIdStart;
    844     return Status::OK;
    845 }
    846 
    847 }  // namespace clearkey
    848 }  // namespace V1_2
    849 }  // namespace drm
    850 }  // namespace hardware
    851 }  // namespace android
    852