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 
     29 namespace {
     30 const int kSecureStopIdStart = 100;
     31 const std::string kStreaming("Streaming");
     32 const std::string kOffline("Offline");
     33 const std::string kTrue("True");
     34 
     35 const std::string kQueryKeyLicenseType("LicenseType");
     36     // Value: "Streaming" or "Offline"
     37 const std::string kQueryKeyPlayAllowed("PlayAllowed");
     38     // Value: "True" or "False"
     39 const std::string kQueryKeyRenewAllowed("RenewAllowed");
     40     // Value: "True" or "False"
     41 
     42 const int kSecureStopIdSize = 10;
     43 
     44 std::vector<uint8_t> uint32ToVector(uint32_t value) {
     45     // 10 bytes to display max value 4294967295 + one byte null terminator
     46     char buffer[kSecureStopIdSize];
     47     memset(buffer, 0, kSecureStopIdSize);
     48     snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value);
     49     return std::vector<uint8_t>(buffer, buffer + sizeof(buffer));
     50 }
     51 
     52 }; // unnamed namespace
     53 
     54 namespace android {
     55 namespace hardware {
     56 namespace drm {
     57 namespace V1_1 {
     58 namespace clearkey {
     59 
     60 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
     61         : mSessionLibrary(sessionLibrary),
     62           mOpenSessionOkCount(0),
     63           mCloseSessionOkCount(0),
     64           mCloseSessionNotOpenedCount(0),
     65           mNextSecureStopId(kSecureStopIdStart) {
     66     mPlayPolicy.clear();
     67     initProperties();
     68     mSecureStops.clear();
     69 }
     70 
     71 void DrmPlugin::initProperties() {
     72     mStringProperties.clear();
     73     mStringProperties[kVendorKey] = kVendorValue;
     74     mStringProperties[kVersionKey] = kVersionValue;
     75     mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
     76     mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
     77     mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
     78 
     79     std::vector<uint8_t> valueVector;
     80     valueVector.clear();
     81     valueVector.insert(valueVector.end(),
     82             kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
     83     mByteArrayProperties[kDeviceIdKey] = valueVector;
     84 
     85     valueVector.clear();
     86     valueVector.insert(valueVector.end(),
     87             kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
     88     mByteArrayProperties[kMetricsKey] = valueVector;
     89 }
     90 
     91 // The secure stop in ClearKey implementation is not installed securely.
     92 // This function merely creates a test environment for testing secure stops APIs.
     93 // The content in this secure stop is implementation dependent, the clearkey
     94 // secureStop does not serve as a reference implementation.
     95 void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) {
     96     ClearkeySecureStop clearkeySecureStop;
     97     clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId);
     98     clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end());
     99 
    100     mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>(
    101             clearkeySecureStop.id, clearkeySecureStop));
    102 }
    103 
    104 Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
    105     sp<Session> session = mSessionLibrary->createSession();
    106     std::vector<uint8_t> sessionId = session->sessionId();
    107 
    108     Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
    109     _hidl_cb(status, toHidlVec(sessionId));
    110     mOpenSessionOkCount++;
    111     return Void();
    112 }
    113 
    114 Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
    115         openSession_1_1_cb _hidl_cb) {
    116     sp<Session> session = mSessionLibrary->createSession();
    117     std::vector<uint8_t> sessionId = session->sessionId();
    118 
    119     Status status = setSecurityLevel(sessionId, securityLevel);
    120     _hidl_cb(status, toHidlVec(sessionId));
    121     mOpenSessionOkCount++;
    122     return Void();
    123 }
    124 
    125 Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
    126     if (sessionId.size() == 0) {
    127         return Status::BAD_VALUE;
    128     }
    129 
    130     sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
    131     if (session.get()) {
    132         mCloseSessionOkCount++;
    133         mSessionLibrary->destroySession(session);
    134         return Status::OK;
    135     }
    136     mCloseSessionNotOpenedCount++;
    137     return Status::ERROR_DRM_SESSION_NOT_OPENED;
    138 }
    139 
    140 Status DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
    141         const hidl_vec<uint8_t>& initData,
    142         const hidl_string& mimeType,
    143         KeyType keyType,
    144         const hidl_vec<KeyValue>& optionalParameters,
    145         std::vector<uint8_t> *request,
    146         KeyRequestType *keyRequestType,
    147         std::string *defaultUrl) {
    148         UNUSED(optionalParameters);
    149 
    150     *defaultUrl = "";
    151     *keyRequestType = KeyRequestType::UNKNOWN;
    152     *request = std::vector<uint8_t>();
    153 
    154     if (scope.size() == 0) {
    155         return Status::BAD_VALUE;
    156     }
    157 
    158     if (keyType != KeyType::STREAMING) {
    159         return Status::ERROR_DRM_CANNOT_HANDLE;
    160     }
    161 
    162     sp<Session> session = mSessionLibrary->findSession(toVector(scope));
    163     if (!session.get()) {
    164         return Status::ERROR_DRM_SESSION_NOT_OPENED;
    165     }
    166 
    167     Status status = session->getKeyRequest(initData, mimeType, request);
    168     *keyRequestType = KeyRequestType::INITIAL;
    169     return status;
    170 }
    171 
    172 Return<void> DrmPlugin::getKeyRequest(
    173         const hidl_vec<uint8_t>& scope,
    174         const hidl_vec<uint8_t>& initData,
    175         const hidl_string& mimeType,
    176         KeyType keyType,
    177         const hidl_vec<KeyValue>& optionalParameters,
    178         getKeyRequest_cb _hidl_cb) {
    179     UNUSED(optionalParameters);
    180 
    181     KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
    182     std::string defaultUrl("");
    183     std::vector<uint8_t> request;
    184     Status status = getKeyRequestCommon(
    185             scope, initData, mimeType, keyType, optionalParameters,
    186             &request, &keyRequestType, &defaultUrl);
    187 
    188     _hidl_cb(status, toHidlVec(request),
    189             static_cast<drm::V1_0::KeyRequestType>(keyRequestType),
    190             hidl_string(defaultUrl));
    191     return Void();
    192 }
    193 
    194 Return<void> DrmPlugin::getKeyRequest_1_1(
    195         const hidl_vec<uint8_t>& scope,
    196         const hidl_vec<uint8_t>& initData,
    197         const hidl_string& mimeType,
    198         KeyType keyType,
    199         const hidl_vec<KeyValue>& optionalParameters,
    200         getKeyRequest_1_1_cb _hidl_cb) {
    201     UNUSED(optionalParameters);
    202 
    203     KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
    204     std::string defaultUrl("");
    205     std::vector<uint8_t> request;
    206     Status status = getKeyRequestCommon(
    207             scope, initData, mimeType, keyType, optionalParameters,
    208             &request, &keyRequestType, &defaultUrl);
    209 
    210     _hidl_cb(status, toHidlVec(request), keyRequestType, hidl_string(defaultUrl));
    211     return Void();
    212 }
    213 
    214 void DrmPlugin::setPlayPolicy() {
    215     mPlayPolicy.clear();
    216 
    217     KeyValue policy;
    218     policy.key = kQueryKeyLicenseType;
    219     policy.value = kStreaming;
    220     mPlayPolicy.push_back(policy);
    221 
    222     policy.key = kQueryKeyPlayAllowed;
    223     policy.value = kTrue;
    224     mPlayPolicy.push_back(policy);
    225 
    226     policy.key = kQueryKeyRenewAllowed;
    227     mPlayPolicy.push_back(policy);
    228 }
    229 
    230 Return<void> DrmPlugin::provideKeyResponse(
    231         const hidl_vec<uint8_t>& scope,
    232         const hidl_vec<uint8_t>& response,
    233         provideKeyResponse_cb _hidl_cb) {
    234     if (scope.size() == 0 || response.size() == 0) {
    235         // Returns empty keySetId
    236         _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
    237         return Void();
    238     }
    239 
    240     sp<Session> session = mSessionLibrary->findSession(toVector(scope));
    241     if (!session.get()) {
    242         _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
    243         return Void();
    244     }
    245 
    246     setPlayPolicy();
    247     std::vector<uint8_t> keySetId;
    248     Status status = session->provideKeyResponse(response);
    249     if (status == Status::OK) {
    250         // This is for testing AMediaDrm_setOnEventListener only.
    251         sendEvent(EventType::VENDOR_DEFINED, 0, scope);
    252         keySetId.clear();
    253     }
    254 
    255     installSecureStop(scope);
    256 
    257     // Returns status and empty keySetId
    258     _hidl_cb(status, toHidlVec(keySetId));
    259     return Void();
    260 }
    261 
    262 Return<void> DrmPlugin::getPropertyString(
    263         const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
    264     std::string name(propertyName.c_str());
    265     std::string value;
    266 
    267     if (name == kVendorKey) {
    268         value = mStringProperties[kVendorKey];
    269     } else if (name == kVersionKey) {
    270         value = mStringProperties[kVersionKey];
    271     } else if (name == kPluginDescriptionKey) {
    272         value = mStringProperties[kPluginDescriptionKey];
    273     } else if (name == kAlgorithmsKey) {
    274         value = mStringProperties[kAlgorithmsKey];
    275     } else if (name == kListenerTestSupportKey) {
    276         value = mStringProperties[kListenerTestSupportKey];
    277     } else {
    278         ALOGE("App requested unknown string property %s", name.c_str());
    279         _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
    280         return Void();
    281     }
    282     _hidl_cb(Status::OK, value.c_str());
    283     return Void();
    284 }
    285 
    286 Return<void> DrmPlugin::getPropertyByteArray(
    287         const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
    288     std::map<std::string, std::vector<uint8_t> >::iterator itr =
    289             mByteArrayProperties.find(std::string(propertyName.c_str()));
    290     if (itr == mByteArrayProperties.end()) {
    291         ALOGE("App requested unknown property: %s", propertyName.c_str());
    292         _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
    293         return Void();
    294     }
    295     _hidl_cb(Status::OK, itr->second);
    296     return Void();
    297 
    298 }
    299 
    300 Return<Status> DrmPlugin::setPropertyString(
    301     const hidl_string& name, const hidl_string& value) {
    302     std::string immutableKeys;
    303     immutableKeys.append(kAlgorithmsKey + ",");
    304     immutableKeys.append(kPluginDescriptionKey + ",");
    305     immutableKeys.append(kVendorKey + ",");
    306     immutableKeys.append(kVersionKey + ",");
    307 
    308     std::string key = std::string(name.c_str());
    309     if (immutableKeys.find(key) != std::string::npos) {
    310         ALOGD("Cannot set immutable property: %s", key.c_str());
    311         return Status::BAD_VALUE;
    312     }
    313 
    314     std::map<std::string, std::string>::iterator itr =
    315             mStringProperties.find(key);
    316     if (itr == mStringProperties.end()) {
    317         ALOGE("Cannot set undefined property string, key=%s", key.c_str());
    318         return Status::BAD_VALUE;
    319     }
    320 
    321     mStringProperties[key] = std::string(value.c_str());
    322     return Status::OK;
    323 }
    324 
    325 Return<Status> DrmPlugin::setPropertyByteArray(
    326     const hidl_string& name, const hidl_vec<uint8_t>& value) {
    327    UNUSED(value);
    328    if (name == kDeviceIdKey) {
    329       ALOGD("Cannot set immutable property: %s", name.c_str());
    330       return Status::BAD_VALUE;
    331    }
    332 
    333    // Setting of undefined properties is not supported
    334    ALOGE("Failed to set property byte array, key=%s", name.c_str());
    335    return Status::ERROR_DRM_CANNOT_HANDLE;
    336 }
    337 
    338 Return<void> DrmPlugin::queryKeyStatus(
    339         const hidl_vec<uint8_t>& sessionId,
    340         queryKeyStatus_cb _hidl_cb) {
    341 
    342     if (sessionId.size() == 0) {
    343         // Returns empty key status KeyValue pair
    344         _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
    345         return Void();
    346     }
    347 
    348     std::vector<KeyValue> infoMapVec;
    349     infoMapVec.clear();
    350 
    351     KeyValue keyValuePair;
    352     for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
    353         keyValuePair.key = mPlayPolicy[i].key;
    354         keyValuePair.value = mPlayPolicy[i].value;
    355         infoMapVec.push_back(keyValuePair);
    356     }
    357     _hidl_cb(Status::OK, toHidlVec(infoMapVec));
    358     return Void();
    359 }
    360 
    361 Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
    362         uint32_t currentSessions = mSessionLibrary->numOpenSessions();
    363         uint32_t maxSessions = 10;
    364         _hidl_cb(Status::OK, currentSessions, maxSessions);
    365         return Void();
    366 }
    367 
    368 Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
    369             getSecurityLevel_cb _hidl_cb) {
    370     if (sessionId.size() == 0) {
    371         _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
    372         return Void();
    373     }
    374 
    375     std::vector<uint8_t> sid = toVector(sessionId);
    376     sp<Session> session = mSessionLibrary->findSession(sid);
    377     if (!session.get()) {
    378         _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
    379         return Void();
    380     }
    381 
    382     std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
    383             mSecurityLevel.find(sid);
    384     if (itr == mSecurityLevel.end()) {
    385         ALOGE("Session id not found");
    386         _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
    387         return Void();
    388     }
    389 
    390     _hidl_cb(Status::OK, itr->second);
    391     return Void();
    392 }
    393 
    394 Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
    395             SecurityLevel level) {
    396     if (sessionId.size() == 0) {
    397         ALOGE("Invalid empty session id");
    398         return Status::BAD_VALUE;
    399     }
    400 
    401     if (level > SecurityLevel::SW_SECURE_CRYPTO) {
    402         ALOGE("Cannot set security level > max");
    403         return Status::ERROR_DRM_CANNOT_HANDLE;
    404     }
    405 
    406     std::vector<uint8_t> sid = toVector(sessionId);
    407     sp<Session> session = mSessionLibrary->findSession(sid);
    408     if (!session.get()) {
    409         return Status::ERROR_DRM_SESSION_NOT_OPENED;
    410     }
    411 
    412     std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
    413             mSecurityLevel.find(sid);
    414     if (itr != mSecurityLevel.end()) {
    415         mSecurityLevel[sid] = level;
    416     } else {
    417         if (!mSecurityLevel.insert(
    418                 std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
    419             ALOGE("Failed to set security level");
    420             return Status::ERROR_DRM_INVALID_STATE;
    421         }
    422     }
    423     return Status::OK;
    424 }
    425 
    426 Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
    427     // Set the open session count metric.
    428     DrmMetricGroup::Attribute openSessionOkAttribute = {
    429       "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
    430     };
    431     DrmMetricGroup::Value openSessionMetricValue = {
    432       "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
    433     };
    434     DrmMetricGroup::Metric openSessionMetric = {
    435       "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
    436     };
    437 
    438     // Set the close session count metric.
    439     DrmMetricGroup::Attribute closeSessionOkAttribute = {
    440       "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
    441     };
    442     DrmMetricGroup::Value closeSessionMetricValue = {
    443       "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
    444     };
    445     DrmMetricGroup::Metric closeSessionMetric = {
    446       "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
    447     };
    448 
    449     // Set the close session, not opened metric.
    450     DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
    451       "status", DrmMetricGroup::ValueType::INT64_TYPE,
    452       (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
    453     };
    454     DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
    455       "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
    456     };
    457     DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
    458       "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
    459     };
    460 
    461     DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
    462                                 closeSessionNotOpenedMetric } };
    463 
    464     _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
    465     return Void();
    466 }
    467 
    468 Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
    469     std::vector<SecureStop> stops;
    470     for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
    471         ClearkeySecureStop clearkeyStop = itr->second;
    472         std::vector<uint8_t> stopVec;
    473         stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
    474         stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
    475 
    476         SecureStop stop;
    477         stop.opaqueData = toHidlVec(stopVec);
    478         stops.push_back(stop);
    479     }
    480     _hidl_cb(Status::OK, stops);
    481     return Void();
    482 }
    483 
    484 Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
    485         getSecureStop_cb _hidl_cb) {
    486     SecureStop stop;
    487     auto itr = mSecureStops.find(toVector(secureStopId));
    488     if (itr != mSecureStops.end()) {
    489         ClearkeySecureStop clearkeyStop = itr->second;
    490         std::vector<uint8_t> stopVec;
    491         stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
    492         stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
    493 
    494         stop.opaqueData = toHidlVec(stopVec);
    495         _hidl_cb(Status::OK, stop);
    496     } else {
    497         _hidl_cb(Status::BAD_VALUE, stop);
    498     }
    499 
    500     return Void();
    501 }
    502 
    503 Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) {
    504     return removeSecureStop(secureStopId);
    505 }
    506 
    507 Return<Status> DrmPlugin::releaseAllSecureStops() {
    508     return removeAllSecureStops();
    509 }
    510 
    511 Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
    512     std::vector<SecureStopId> ids;
    513     for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
    514         ids.push_back(itr->first);
    515     }
    516 
    517     _hidl_cb(Status::OK, toHidlVec(ids));
    518     return Void();
    519 }
    520 
    521 Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
    522     if (ssRelease.opaqueData.size() == 0) {
    523         return Status::BAD_VALUE;
    524     }
    525 
    526     Status status = Status::OK;
    527     std::vector<uint8_t> input = toVector(ssRelease.opaqueData);
    528 
    529     // The format of opaqueData is shared between the server
    530     // and the drm service. The clearkey implementation consists of:
    531     //    count - number of secure stops
    532     //    list of fixed length secure stops
    533     size_t countBufferSize = sizeof(uint32_t);
    534     uint32_t count = 0;
    535     sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
    536 
    537     // Avoid divide by 0 below.
    538     if (count == 0) {
    539         return Status::BAD_VALUE;
    540     }
    541 
    542     size_t secureStopSize = (input.size() - countBufferSize) / count;
    543     uint8_t buffer[secureStopSize];
    544     size_t offset = countBufferSize; // skip the count
    545     for (size_t i = 0; i < count; ++i, offset += secureStopSize) {
    546         memcpy(buffer, input.data() + offset, secureStopSize);
    547         std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
    548 
    549         status = removeSecureStop(toHidlVec(id));
    550         if (Status::OK != status) break;
    551     }
    552 
    553     return status;
    554 }
    555 
    556 Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
    557     if (1 != mSecureStops.erase(toVector(secureStopId))) {
    558         return Status::BAD_VALUE;
    559     }
    560     return Status::OK;
    561 }
    562 
    563 Return<Status> DrmPlugin::removeAllSecureStops() {
    564     mSecureStops.clear();
    565     mNextSecureStopId = kSecureStopIdStart;
    566     return Status::OK;
    567 }
    568 
    569 }  // namespace clearkey
    570 }  // namespace V1_1
    571 }  // namespace drm
    572 }  // namespace hardware
    573 }  // namespace android
    574