1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "drm_hal_clearkey_test@1.1"
18 
19 #include <log/log.h>
20 #include <vector>
21 
22 #include "android/hardware/drm/1.1/vts/drm_hal_clearkey_test.h"
23 
24 namespace android {
25 namespace hardware {
26 namespace drm {
27 namespace V1_1 {
28 namespace vts {
29 
30 const uint8_t kClearKeyUUID[16] = {
31     0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
32     0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E
33 };
34 
35 /**
36  * Helper method to open a session and verify that a non-empty
37  * session ID is returned
38  */
openSession()39 SessionId DrmHalClearkeyTest::openSession() {
40     SessionId sessionId;
41 
42     auto res = drmPlugin->openSession(
43             [&sessionId](Status status, const SessionId& id) {
44                 EXPECT_EQ(Status::OK, status);
45                 EXPECT_NE(0u, id.size());
46                 sessionId = id;
47             });
48     EXPECT_OK(res);
49     return sessionId;
50 }
51 
52 /**
53  * Helper method to open as session using V1.1 API
54  */
openSession(SecurityLevel level)55 SessionId DrmHalClearkeyTest::openSession(SecurityLevel level) {
56     SessionId sessionId;
57 
58     auto res = drmPlugin->openSession_1_1(level,
59             [&sessionId](Status status, const SessionId& id) {
60                 EXPECT_EQ(Status::OK, status);
61                 EXPECT_NE(0u, id.size());
62                 sessionId = id;
63             });
64     EXPECT_OK(res);
65     return sessionId;
66 }
67 
68 
69 /**
70  * Helper method to close a session
71  */
closeSession(const SessionId & sessionId)72 void DrmHalClearkeyTest::closeSession(const SessionId& sessionId) {
73     EXPECT_TRUE(drmPlugin->closeSession(sessionId).isOk());
74 }
75 
76 /**
77  * Helper method to load keys for subsequent decrypt tests.
78  * These tests use predetermined key request/response to
79  * avoid requiring a round trip to a license server.
80  */
loadKeys(const SessionId & sessionId,const KeyType & type=KeyType::STREAMING)81 hidl_vec<uint8_t> DrmHalClearkeyTest::loadKeys(
82     const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
83     hidl_vec<uint8_t> initData = {
84         // BMFF box header (4 bytes size + 'pssh')
85         0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
86         // full box header (version = 1 flags = 0)
87         0x01, 0x00, 0x00, 0x00,
88         // system id
89         0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
90         0x1e, 0x52, 0xe2, 0xfb, 0x4b,
91         // number of key ids
92         0x00, 0x00, 0x00, 0x01,
93         // key id
94         0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
95         0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
96         // size of data, must be zero
97         0x00, 0x00, 0x00, 0x00};
98 
99     hidl_vec<uint8_t> expectedKeyRequest = {
100         0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65,
101         0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74,
102         0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a,
103         0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
104 
105     hidl_vec<uint8_t> knownKeyResponse = {
106         0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22,
107         0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59,
108         0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e,
109         0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f,
110         0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65,
111         0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
112 
113     hidl_string mimeType = "video/mp4";
114     KeyedVector optionalParameters;
115     auto res = drmPlugin->getKeyRequest_1_1(
116         sessionId, initData, mimeType, type, optionalParameters,
117         [&](Status status, const hidl_vec<uint8_t>& request,
118             KeyRequestType requestType, const hidl_string&) {
119             EXPECT_EQ(Status::OK, status);
120             EXPECT_EQ(KeyRequestType::INITIAL, requestType);
121             EXPECT_EQ(request, expectedKeyRequest);
122         });
123     EXPECT_OK(res);
124 
125     hidl_vec<uint8_t> keySetId;
126     res = drmPlugin->provideKeyResponse(
127         sessionId, knownKeyResponse,
128         [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
129             EXPECT_EQ(Status::OK, status);
130             EXPECT_EQ(0u, myKeySetId.size());
131             keySetId = myKeySetId;
132         });
133     EXPECT_OK(res);
134     return keySetId;
135 }
136 
137 /**
138  * Test openSession negative case: security level higher than supported
139  */
TEST_P(DrmHalClearkeyTest,OpenSessionBadLevel)140 TEST_P(DrmHalClearkeyTest, OpenSessionBadLevel) {
141     auto res = drmPlugin->openSession_1_1(SecurityLevel::HW_SECURE_ALL,
142             [&](Status status, const SessionId& /* id */) {
143                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
144             });
145     EXPECT_OK(res);
146 }
147 
148 /**
149  * Test getKeyRequest_1_1 via loadKeys
150  */
TEST_P(DrmHalClearkeyTest,GetKeyRequest)151 TEST_P(DrmHalClearkeyTest, GetKeyRequest) {
152     auto sessionId = openSession();
153     loadKeys(sessionId);
154     closeSession(sessionId);
155 }
156 
157 /**
158  * A get key request should fail if no sessionId is provided
159  */
TEST_P(DrmHalClearkeyTest,GetKeyRequestNoSession)160 TEST_P(DrmHalClearkeyTest, GetKeyRequestNoSession) {
161     SessionId invalidSessionId;
162     hidl_vec<uint8_t> initData;
163     hidl_string mimeType = "video/mp4";
164     KeyedVector optionalParameters;
165     auto res = drmPlugin->getKeyRequest_1_1(
166             invalidSessionId, initData, mimeType, KeyType::STREAMING,
167             optionalParameters,
168             [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
169                 const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
170     EXPECT_OK(res);
171 }
172 
173 /**
174  * The clearkey plugin doesn't support offline key requests.
175  * Test that the plugin returns the expected error code in
176  * this case.
177  */
TEST_P(DrmHalClearkeyTest,GetKeyRequestOfflineKeyTypeNotSupported)178 TEST_P(DrmHalClearkeyTest, GetKeyRequestOfflineKeyTypeNotSupported) {
179     auto sessionId = openSession();
180     hidl_vec<uint8_t> initData;
181     hidl_string mimeType = "video/mp4";
182     KeyedVector optionalParameters;
183 
184     auto res = drmPlugin->getKeyRequest_1_1(
185             sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters,
186             [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
187                 const hidl_string&) {
188                 // Clearkey plugin doesn't support offline key type
189                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
190             });
191     EXPECT_OK(res);
192     closeSession(sessionId);
193 }
194 
195 /**
196  * Test that the plugin returns valid connected and max HDCP levels
197  */
TEST_P(DrmHalClearkeyTest,GetHdcpLevels)198 TEST_P(DrmHalClearkeyTest, GetHdcpLevels) {
199     auto res = drmPlugin->getHdcpLevels(
200             [&](Status status, const HdcpLevel &connectedLevel,
201                 const HdcpLevel &maxLevel) {
202                 EXPECT_EQ(Status::OK, status);
203                 EXPECT_GE(connectedLevel, HdcpLevel::HDCP_NONE);
204                 EXPECT_LE(maxLevel, HdcpLevel::HDCP_NO_OUTPUT);
205             });
206     EXPECT_OK(res);
207 }
208 
209 /**
210  * Since getHdcpLevels only queries information there are no
211  * negative cases.
212  */
213 
214 /**
215  * Test that the plugin returns default open and max session counts
216  */
TEST_P(DrmHalClearkeyTest,GetDefaultSessionCounts)217 TEST_P(DrmHalClearkeyTest, GetDefaultSessionCounts) {
218     auto res = drmPlugin->getNumberOfSessions(
219             [&](Status status, uint32_t currentSessions,
220                     uint32_t maxSessions) {
221                 EXPECT_EQ(Status::OK, status);
222                 EXPECT_GE(maxSessions, (uint32_t)8);
223                 EXPECT_GE(currentSessions, (uint32_t)0);
224                 EXPECT_LE(currentSessions, maxSessions);
225             });
226     EXPECT_OK(res);
227 }
228 
229 /**
230  * Test that the plugin returns valid open and max session counts
231  * after a session is opened.
232  */
TEST_P(DrmHalClearkeyTest,GetOpenSessionCounts)233 TEST_P(DrmHalClearkeyTest, GetOpenSessionCounts) {
234     uint32_t initialSessions = 0;
235     auto res = drmPlugin->getNumberOfSessions(
236             [&](Status status, uint32_t currentSessions,
237                     uint32_t maxSessions) {
238                 EXPECT_EQ(Status::OK, status);
239                 EXPECT_GE(maxSessions, (uint32_t)8);
240                 EXPECT_GE(currentSessions, (uint32_t)0);
241                 EXPECT_LE(currentSessions, maxSessions);
242                 initialSessions = currentSessions;
243             });
244     EXPECT_OK(res);
245 
246     SessionId session = openSession();
247     res = drmPlugin->getNumberOfSessions(
248             [&](Status status, uint32_t currentSessions,
249                     uint32_t /*maxSessions*/) {
250                 EXPECT_EQ(Status::OK, status);
251                 EXPECT_EQ(currentSessions, initialSessions + 1);
252             });
253     EXPECT_OK(res);
254 
255     closeSession(session);
256     res = drmPlugin->getNumberOfSessions(
257             [&](Status status, uint32_t currentSessions,
258                     uint32_t /*maxSessions*/) {
259                 EXPECT_EQ(Status::OK, status);
260                 EXPECT_EQ(currentSessions, initialSessions);
261             });
262     EXPECT_OK(res);
263 }
264 
265 /**
266  * Since getNumberOfSessions only queries information there are no
267  * negative cases.
268  */
269 
270 /**
271  * Test that the plugin returns the same security level
272  * by default as when it is requested explicitly
273  */
TEST_P(DrmHalClearkeyTest,GetDefaultSecurityLevel)274 TEST_P(DrmHalClearkeyTest, GetDefaultSecurityLevel) {
275     SessionId session = openSession();
276     SecurityLevel defaultLevel;
277     auto res = drmPlugin->getSecurityLevel(session,
278             [&](Status status, SecurityLevel level) {
279                 EXPECT_EQ(Status::OK, status);
280                 defaultLevel = level;
281             });
282     EXPECT_OK(res);
283     closeSession(session);
284 
285     session = openSession(defaultLevel);
286     res = drmPlugin->getSecurityLevel(session,
287             [&](Status status, SecurityLevel level) {
288                 EXPECT_EQ(Status::OK, status);
289                 EXPECT_EQ(level, defaultLevel);
290             });
291     EXPECT_OK(res);
292     closeSession(session);
293 }
294 
295 /**
296  * Test that the plugin returns the lowest security level
297  * when it is requested
298  */
TEST_P(DrmHalClearkeyTest,GetSecurityLevel)299 TEST_P(DrmHalClearkeyTest, GetSecurityLevel) {
300     SessionId session = openSession(SecurityLevel::SW_SECURE_CRYPTO);
301     auto res = drmPlugin->getSecurityLevel(session,
302             [&](Status status, SecurityLevel level) {
303                 EXPECT_EQ(Status::OK, status);
304                 EXPECT_EQ(level, SecurityLevel::SW_SECURE_CRYPTO);
305             });
306     EXPECT_OK(res);
307     closeSession(session);
308 }
309 
310 /**
311  * Test that the plugin returns the documented error
312  * when requesting the security level for an invalid sessionId
313  */
TEST_P(DrmHalClearkeyTest,GetSecurityLevelInvalidSessionId)314 TEST_P(DrmHalClearkeyTest, GetSecurityLevelInvalidSessionId) {
315     SessionId session;
316     auto res = drmPlugin->getSecurityLevel(session,
317             [&](Status status, SecurityLevel /*level*/) {
318                 EXPECT_EQ(Status::BAD_VALUE, status);
319             });
320     EXPECT_OK(res);
321 }
322 
323 /**
324  * Test metrics are set appropriately for open and close operations.
325  */
TEST_P(DrmHalClearkeyTest,GetMetricsOpenClose)326 TEST_P(DrmHalClearkeyTest, GetMetricsOpenClose) {
327     SessionId sessionId = openSession();
328     // The first close should be successful.
329     closeSession(sessionId);
330     // The second close should fail (not opened).
331     EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, drmPlugin->closeSession(sessionId));
332 
333     auto res = drmPlugin->getMetrics([this](Status status, hidl_vec<DrmMetricGroup> metricGroups) {
334         EXPECT_EQ(Status::OK, status);
335 
336         // Verify the open_session metric.
337         EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "open_session", "status",
338                                                     (int64_t)0, "count", (int64_t)1));
339         // Verify the close_session - success metric.
340         EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
341                                                     (int64_t)0, "count", (int64_t)1));
342         // Verify the close_session - error metric.
343         EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
344                                                     (int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
345                                                     "count", (int64_t)1));
346     });
347     EXPECT_OK(res);
348 }
349 
350 /**
351  * Since getMetrics only queries information there are no
352  * negative cases.
353  */
354 
355 /**
356  * Test that there are no secure stop ids after clearing them
357  */
TEST_P(DrmHalClearkeyTest,GetSecureStopIdsCleared)358 TEST_P(DrmHalClearkeyTest, GetSecureStopIdsCleared) {
359     auto stat = drmPlugin->removeAllSecureStops();
360     EXPECT_OK(stat);
361 
362     bool ok = drmPlugin->getSecureStopIds(
363             [&](Status status, const hidl_vec<SecureStopId>& ids) {
364                 EXPECT_EQ(Status::OK, status);
365                 EXPECT_EQ(0u, ids.size());
366             }).isOk();
367     EXPECT_TRUE(ok);
368 }
369 
370 /**
371  * Test that there are secure stop ids after loading keys once
372  */
TEST_P(DrmHalClearkeyTest,GetSecureStopIdsOnce)373 TEST_P(DrmHalClearkeyTest, GetSecureStopIdsOnce) {
374     auto stat = drmPlugin->removeAllSecureStops();
375     EXPECT_OK(stat);
376 
377     auto sessionId = openSession();
378     loadKeys(sessionId);
379     closeSession(sessionId);
380 
381     auto res = drmPlugin->getSecureStopIds(
382             [&](Status status, const hidl_vec<SecureStopId>& ids) {
383                 EXPECT_EQ(Status::OK, status);
384                 EXPECT_EQ(1u, ids.size());
385             });
386     EXPECT_OK(res);
387 
388     stat = drmPlugin->removeAllSecureStops();
389     EXPECT_OK(stat);
390 
391     res = drmPlugin->getSecureStopIds(
392             [&](Status status, const hidl_vec<SecureStopId>& ids) {
393                 EXPECT_EQ(Status::OK, status);
394                 EXPECT_EQ(0u, ids.size());
395             });
396     EXPECT_OK(res);
397 }
398 
399 /**
400  * Since getSecureStopIds only queries information there are no
401  * negative cases.
402  */
403 
404 /**
405  * Test that the clearkey plugin reports no secure stops when
406  * there are none.
407  */
TEST_P(DrmHalClearkeyTest,GetNoSecureStops)408 TEST_P(DrmHalClearkeyTest, GetNoSecureStops) {
409     auto stat = drmPlugin->removeAllSecureStops();
410     EXPECT_OK(stat);
411 
412     auto res = drmPlugin->getSecureStops(
413             [&](Status status, const hidl_vec<SecureStop>& stops) {
414                 EXPECT_EQ(Status::OK, status);
415                 EXPECT_EQ(0u, stops.size());
416             });
417     EXPECT_OK(res);
418 }
419 
420 /**
421  * Test get/remove of one secure stop
422  */
TEST_P(DrmHalClearkeyTest,GetOneSecureStopAndRemoveIt)423 TEST_P(DrmHalClearkeyTest, GetOneSecureStopAndRemoveIt) {
424     auto stat = drmPlugin->removeAllSecureStops();
425     EXPECT_OK(stat);
426 
427     auto sessionId = openSession();
428     loadKeys(sessionId);
429     closeSession(sessionId);
430 
431     auto res = drmPlugin->getSecureStops(
432             [&](Status status, const hidl_vec<SecureStop>& stops) {
433                 EXPECT_EQ(Status::OK, status);
434                 EXPECT_EQ(1u, stops.size());
435             });
436     EXPECT_OK(res);
437 
438     stat = drmPlugin->removeAllSecureStops();
439     EXPECT_OK(stat);
440 
441     res = drmPlugin->getSecureStops(
442             [&](Status status, const hidl_vec<SecureStop>& stops) {
443                 EXPECT_EQ(Status::OK, status);
444                 EXPECT_EQ(0u, stops.size());
445             });
446     EXPECT_OK(res);
447 }
448 
449 /**
450  * Since getSecureStops only queries information there are no
451  * negative cases.
452  */
453 
454 /**
455  * Test that there are no secure stops after clearing them
456  */
TEST_P(DrmHalClearkeyTest,GetSecureStopsCleared)457 TEST_P(DrmHalClearkeyTest, GetSecureStopsCleared) {
458     auto stat = drmPlugin->removeAllSecureStops();
459     EXPECT_OK(stat);
460 
461     auto res = drmPlugin->getSecureStops(
462             [&](Status status, const hidl_vec<SecureStop>& stops) {
463                 EXPECT_EQ(Status::OK, status);
464                 EXPECT_EQ(0u, stops.size());
465             });
466     EXPECT_OK(res);
467 }
468 
469 /**
470  * Test that there are secure stops after loading keys once
471  */
TEST_P(DrmHalClearkeyTest,GetSecureStopsOnce)472 TEST_P(DrmHalClearkeyTest, GetSecureStopsOnce) {
473     auto stat = drmPlugin->removeAllSecureStops();
474     EXPECT_OK(stat);
475 
476     auto sessionId = openSession();
477     loadKeys(sessionId);
478     closeSession(sessionId);
479 
480     auto res = drmPlugin->getSecureStops(
481             [&](Status status, const hidl_vec<SecureStop>& stops) {
482                 EXPECT_EQ(Status::OK, status);
483                 EXPECT_EQ(1u, stops.size());
484             });
485     EXPECT_OK(res);
486 
487     stat = drmPlugin->removeAllSecureStops();
488     EXPECT_OK(stat);
489 
490     res = drmPlugin->getSecureStops(
491             [&](Status status, const hidl_vec<SecureStop>& stops) {
492                 EXPECT_EQ(Status::OK, status);
493                 EXPECT_EQ(0u, stops.size());
494             });
495     EXPECT_OK(res);
496 }
497 
498 /**
499  * Since getSecureStops only queries information there are no
500  * negative cases.
501  */
502 
503 /**
504  * Test that releasing a secure stop with empty
505  * release message fails with the documented error
506  */
TEST_P(DrmHalClearkeyTest,ReleaseEmptySecureStop)507 TEST_P(DrmHalClearkeyTest, ReleaseEmptySecureStop) {
508     SecureStopRelease emptyRelease = {.opaqueData = hidl_vec<uint8_t>()};
509     Status status = drmPlugin->releaseSecureStops(emptyRelease);
510     EXPECT_EQ(Status::BAD_VALUE, status);
511 }
512 
513 /**
514  * Helper function to create a secure release message for
515  * a secure stop. The clearkey secure stop release format
516  * is just a count followed by the secure stop opaque data.
517  */
makeSecureRelease(const SecureStop & stop)518 SecureStopRelease makeSecureRelease(const SecureStop &stop) {
519     std::vector<uint8_t> stopData = stop.opaqueData;
520     std::vector<uint8_t> buffer;
521     std::string count = "0001";
522 
523     auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
524     buffer.insert(it + count.size(), stopData.begin(), stopData.end());
525     SecureStopRelease release = { .opaqueData = hidl_vec<uint8_t>(buffer) };
526     return release;
527 }
528 
529 /**
530  * Test that releasing one secure stop works
531  */
TEST_P(DrmHalClearkeyTest,ReleaseOneSecureStop)532 TEST_P(DrmHalClearkeyTest, ReleaseOneSecureStop) {
533     auto stat = drmPlugin->removeAllSecureStops();
534     EXPECT_OK(stat);
535 
536     auto sessionId = openSession();
537     loadKeys(sessionId);
538     closeSession(sessionId);
539 
540     SecureStopRelease release;
541     auto res = drmPlugin->getSecureStops(
542             [&](Status status, const hidl_vec<SecureStop>& stops) {
543                 EXPECT_EQ(Status::OK, status);
544                 EXPECT_EQ(1u, stops.size());
545                 release = makeSecureRelease(stops[0]);
546             });
547     EXPECT_OK(res);
548 
549     stat = drmPlugin->releaseSecureStops(release);
550     EXPECT_OK(stat);
551 
552     res = drmPlugin->getSecureStops(
553             [&](Status status, const hidl_vec<SecureStop>& stops) {
554                 EXPECT_EQ(Status::OK, status);
555                 EXPECT_EQ(0u, stops.size());
556             });
557     EXPECT_OK(res);
558 }
559 
560 /**
561  * Test that removing a secure stop with an empty ID returns
562  * documented error
563  */
TEST_P(DrmHalClearkeyTest,RemoveEmptySecureStopId)564 TEST_P(DrmHalClearkeyTest, RemoveEmptySecureStopId) {
565     hidl_vec<uint8_t> emptyId;
566     auto stat = drmPlugin->removeSecureStop(emptyId);
567     EXPECT_OK(stat);
568     EXPECT_EQ(Status::BAD_VALUE, stat);
569 }
570 
571 /**
572  * Test that removing a secure stop after it has already
573  * been removed fails with the documented error code.
574  */
TEST_P(DrmHalClearkeyTest,RemoveRemovedSecureStopId)575 TEST_P(DrmHalClearkeyTest, RemoveRemovedSecureStopId) {
576     auto stat = drmPlugin->removeAllSecureStops();
577     EXPECT_OK(stat);
578 
579     auto sessionId = openSession();
580     loadKeys(sessionId);
581     closeSession(sessionId);
582     SecureStopId ssid;
583 
584     auto res = drmPlugin->getSecureStopIds(
585             [&](Status status, const hidl_vec<SecureStopId>& ids) {
586                 EXPECT_EQ(Status::OK, status);
587                 EXPECT_EQ(1u, ids.size());
588                 ssid = ids[0];
589             });
590     EXPECT_OK(res);
591 
592     stat = drmPlugin->removeAllSecureStops();
593     EXPECT_OK(stat);
594 
595     Status status = drmPlugin->removeSecureStop(ssid);
596     EXPECT_EQ(Status::BAD_VALUE, status);
597 }
598 
599 /**
600  * Test that removing a secure stop by id works
601  */
TEST_P(DrmHalClearkeyTest,RemoveSecureStopById)602 TEST_P(DrmHalClearkeyTest, RemoveSecureStopById) {
603     auto stat = drmPlugin->removeAllSecureStops();
604     EXPECT_OK(stat);
605 
606     auto sessionId = openSession();
607     loadKeys(sessionId);
608     closeSession(sessionId);
609     SecureStopId ssid;
610 
611     auto res = drmPlugin->getSecureStopIds(
612             [&](Status status, const hidl_vec<SecureStopId>& ids) {
613                 EXPECT_EQ(Status::OK, status);
614                 EXPECT_EQ(1u, ids.size());
615                 ssid = ids[0];
616             });
617     EXPECT_OK(res);
618 
619     stat = drmPlugin->removeSecureStop(ssid);
620     EXPECT_OK(stat);
621 
622     res = drmPlugin->getSecureStopIds(
623             [&](Status status, const hidl_vec<SecureStopId>& ids) {
624                 EXPECT_EQ(Status::OK, status);
625                 EXPECT_EQ(0u, ids.size());
626             });
627     EXPECT_OK(res);
628 }
629 
630 }  // namespace vts
631 }  // namespace V1_1
632 }  // namespace drm
633 }  // namespace hardware
634 }  // namespace android
635