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
uint32ToVector(uint32_t value)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
DrmPlugin(SessionLibrary * sessionLibrary)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
initProperties()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.
installSecureStop(const hidl_vec<uint8_t> & sessionId)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
openSession(openSession_cb _hidl_cb)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
openSession_1_1(SecurityLevel securityLevel,openSession_1_1_cb _hidl_cb)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
closeSession(const hidl_vec<uint8_t> & sessionId)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
getKeyRequestCommon(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & initData,const hidl_string & mimeType,KeyType keyType,const hidl_vec<KeyValue> & optionalParameters,std::vector<uint8_t> * request,KeyRequestType * keyRequestType,std::string * defaultUrl)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
getKeyRequest(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & initData,const hidl_string & mimeType,KeyType keyType,const hidl_vec<KeyValue> & optionalParameters,getKeyRequest_cb _hidl_cb)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
getKeyRequest_1_1(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & initData,const hidl_string & mimeType,KeyType keyType,const hidl_vec<KeyValue> & optionalParameters,getKeyRequest_1_1_cb _hidl_cb)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
setPlayPolicy()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
provideKeyResponse(const hidl_vec<uint8_t> & scope,const hidl_vec<uint8_t> & response,provideKeyResponse_cb _hidl_cb)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
getPropertyString(const hidl_string & propertyName,getPropertyString_cb _hidl_cb)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
getPropertyByteArray(const hidl_string & propertyName,getPropertyByteArray_cb _hidl_cb)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
setPropertyString(const hidl_string & name,const hidl_string & value)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
setPropertyByteArray(const hidl_string & name,const hidl_vec<uint8_t> & value)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
queryKeyStatus(const hidl_vec<uint8_t> & sessionId,queryKeyStatus_cb _hidl_cb)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
getNumberOfSessions(getNumberOfSessions_cb _hidl_cb)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
getSecurityLevel(const hidl_vec<uint8_t> & sessionId,getSecurityLevel_cb _hidl_cb)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
setSecurityLevel(const hidl_vec<uint8_t> & sessionId,SecurityLevel level)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
getMetrics(getMetrics_cb _hidl_cb)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
getSecureStops(getSecureStops_cb _hidl_cb)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
getSecureStop(const hidl_vec<uint8_t> & secureStopId,getSecureStop_cb _hidl_cb)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
releaseSecureStop(const hidl_vec<uint8_t> & secureStopId)503 Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) {
504 return removeSecureStop(secureStopId);
505 }
506
releaseAllSecureStops()507 Return<Status> DrmPlugin::releaseAllSecureStops() {
508 return removeAllSecureStops();
509 }
510
getSecureStopIds(getSecureStopIds_cb _hidl_cb)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
releaseSecureStops(const SecureStopRelease & ssRelease)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
removeSecureStop(const hidl_vec<uint8_t> & secureStopId)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
removeAllSecureStops()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