• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "mediacas_hidl_hal_test"
18 
19 #include <android-base/logging.h>
20 #include <android/hardware/cas/1.0/ICas.h>
21 #include <android/hardware/cas/1.0/ICasListener.h>
22 #include <android/hardware/cas/1.0/IDescramblerBase.h>
23 #include <android/hardware/cas/1.0/IMediaCasService.h>
24 #include <android/hardware/cas/1.0/types.h>
25 #include <android/hardware/cas/native/1.0/IDescrambler.h>
26 #include <android/hardware/cas/native/1.0/types.h>
27 #include <binder/MemoryDealer.h>
28 #include <gtest/gtest.h>
29 #include <hidl/GtestPrinter.h>
30 #include <hidl/HidlSupport.h>
31 #include <hidl/HidlTransportSupport.h>
32 #include <hidl/ServiceManagement.h>
33 #include <hidl/Status.h>
34 #include <hidlmemory/FrameworkUtils.h>
35 #include <utils/Condition.h>
36 #include <utils/Mutex.h>
37 
38 #define CLEAR_KEY_SYSTEM_ID 0xF6D8
39 #define INVALID_SYSTEM_ID 0
40 #define WAIT_TIMEOUT 3000000000
41 
42 #define PROVISION_STR                                      \
43     "{                                                   " \
44     "  \"id\": 21140844,                                 " \
45     "  \"name\": \"Test Title\",                         " \
46     "  \"lowercase_organization_name\": \"Android\",     " \
47     "  \"asset_key\": {                                  " \
48     "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
49     "  },                                                " \
50     "  \"cas_type\": 1,                                  " \
51     "  \"track_types\": [ ]                              " \
52     "}                                                   "
53 
54 using android::Condition;
55 using android::hardware::cas::V1_0::ICas;
56 using android::hardware::cas::V1_0::ICasListener;
57 using android::hardware::cas::V1_0::IDescramblerBase;
58 using android::hardware::cas::V1_0::Status;
59 using android::hardware::cas::native::V1_0::IDescrambler;
60 using android::hardware::cas::native::V1_0::SubSample;
61 using android::hardware::cas::native::V1_0::SharedBuffer;
62 using android::hardware::cas::native::V1_0::DestinationBuffer;
63 using android::hardware::cas::native::V1_0::BufferType;
64 using android::hardware::cas::native::V1_0::ScramblingControl;
65 using android::hardware::cas::V1_0::IMediaCasService;
66 using android::hardware::cas::V1_0::HidlCasPluginDescriptor;
67 using android::hardware::fromHeap;
68 using android::hardware::hidl_vec;
69 using android::hardware::hidl_string;
70 using android::hardware::HidlMemory;
71 using android::hardware::Return;
72 using android::hardware::Void;
73 using android::IMemory;
74 using android::IMemoryHeap;
75 using android::MemoryDealer;
76 using android::Mutex;
77 using android::sp;
78 
79 namespace {
80 
81 const uint8_t kEcmBinaryBuffer[] = {
82     0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00,
83     0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00,
84     0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60, 0x4f,
85     0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
86     0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c,
87     0x62, 0x19, 0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48,
88 };
89 
90 const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
91 
92 const uint8_t kInBinaryBuffer[] = {
93     0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, 0x01,
94     0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, 0xc5, 0x8b,
95     0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, 0x05, 0xff, 0xff,
96     0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee,
97     0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x31, 0x34, 0x32,
98     0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20,
99     0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79,
100     0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d,
101     0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65,
102     0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74,
103     0x6d, 0x6c, 0x6e, 0x45, 0x21, 0x82, 0x38, 0xf0, 0x9d, 0x7d, 0x96, 0xe6, 0x94, 0xae, 0xe2, 0x87,
104     0x8f, 0x04, 0x49, 0xe5, 0xf6, 0x8c, 0x8b, 0x9a, 0x10, 0x18, 0xba, 0x94, 0xe9, 0x22, 0x31, 0x04,
105     0x7e, 0x60, 0x5b, 0xc4, 0x24, 0x00, 0x90, 0x62, 0x0d, 0xdc, 0x85, 0x74, 0x75, 0x78, 0xd0, 0x14,
106     0x08, 0xcb, 0x02, 0x1d, 0x7d, 0x9d, 0x34, 0xe8, 0x81, 0xb9, 0xf7, 0x09, 0x28, 0x79, 0x29, 0x8d,
107     0xe3, 0x14, 0xed, 0x5f, 0xca, 0xaf, 0xf4, 0x1c, 0x49, 0x15, 0xe1, 0x80, 0x29, 0x61, 0x76, 0x80,
108     0x43, 0xf8, 0x58, 0x53, 0x40, 0xd7, 0x31, 0x6d, 0x61, 0x81, 0x41, 0xe9, 0x77, 0x9f, 0x9c, 0xe1,
109     0x6d, 0xf2, 0xee, 0xd9, 0xc8, 0x67, 0xd2, 0x5f, 0x48, 0x73, 0xe3, 0x5c, 0xcd, 0xa7, 0x45, 0x58,
110     0xbb, 0xdd, 0x28, 0x1d, 0x68, 0xfc, 0xb4, 0xc6, 0xf6, 0x92, 0xf6, 0x30, 0x03, 0xaa, 0xe4, 0x32,
111     0xf6, 0x34, 0x51, 0x4b, 0x0f, 0x8c, 0xf9, 0xac, 0x98, 0x22, 0xfb, 0x49, 0xc8, 0xbf, 0xca, 0x8c,
112     0x80, 0x86, 0x5d, 0xd7, 0xa4, 0x52, 0xb1, 0xd9, 0xa6, 0x04, 0x4e, 0xb3, 0x2d, 0x1f, 0xb8, 0x35,
113     0xcc, 0x45, 0x6d, 0x9c, 0x20, 0xa7, 0xa4, 0x34, 0x59, 0x72, 0xe3, 0xae, 0xba, 0x49, 0xde, 0xd1,
114     0xaa, 0xee, 0x3d, 0x77, 0xfc, 0x5d, 0xc6, 0x1f, 0x9d, 0xac, 0xc2, 0x15, 0x66, 0xb8, 0xe1, 0x54,
115     0x4e, 0x74, 0x93, 0xdb, 0x9a, 0x24, 0x15, 0x6e, 0x20, 0xa3, 0x67, 0x3e, 0x5a, 0x24, 0x41, 0x5e,
116     0xb0, 0xe6, 0x35, 0x87, 0x1b, 0xc8, 0x7a, 0xf9, 0x77, 0x65, 0xe0, 0x01, 0xf2, 0x4c, 0xe4, 0x2b,
117     0xa9, 0x64, 0x96, 0x96, 0x0b, 0x46, 0xca, 0xea, 0x79, 0x0e, 0x78, 0xa3, 0x5f, 0x43, 0xfc, 0x47,
118     0x6a, 0x12, 0xfa, 0xc4, 0x33, 0x0e, 0x88, 0x1c, 0x19, 0x3a, 0x00, 0xc3, 0x4e, 0xb5, 0xd8, 0xfa,
119     0x8e, 0xf1, 0xbc, 0x3d, 0xb2, 0x7e, 0x50, 0x8d, 0x67, 0xc3, 0x6b, 0xed, 0xe2, 0xea, 0xa6, 0x1f,
120     0x25, 0x24, 0x7c, 0x94, 0x74, 0x50, 0x49, 0xe3, 0xc6, 0x58, 0x2e, 0xfd, 0x28, 0xb4, 0xc6, 0x73,
121     0xb1, 0x53, 0x74, 0x27, 0x94, 0x5c, 0xdf, 0x69, 0xb7, 0xa1, 0xd7, 0xf5, 0xd3, 0x8a, 0x2c, 0x2d,
122     0xb4, 0x5e, 0x8a, 0x16, 0x14, 0x54, 0x64, 0x6e, 0x00, 0x6b, 0x11, 0x59, 0x8a, 0x63, 0x38, 0x80,
123     0x76, 0xc3, 0xd5, 0x59, 0xf7, 0x3f, 0xd2, 0xfa, 0xa5, 0xca, 0x82, 0xff, 0x4a, 0x62, 0xf0, 0xe3,
124     0x42, 0xf9, 0x3b, 0x38, 0x27, 0x8a, 0x89, 0xaa, 0x50, 0x55, 0x4b, 0x29, 0xf1, 0x46, 0x7c, 0x75,
125     0xef, 0x65, 0xaf, 0x9b, 0x0d, 0x6d, 0xda, 0x25, 0x94, 0x14, 0xc1, 0x1b, 0xf0, 0xc5, 0x4c, 0x24,
126     0x0e, 0x65,
127 };
128 
129 const uint8_t kOutRefBinaryBuffer[] = {
130     0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb, 0x01,
131     0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03, 0xc5, 0x8b,
132     0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06, 0x05, 0xff, 0xff,
133     0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8, 0x20, 0xd9, 0x23, 0xee,
134     0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x31, 0x34, 0x32,
135     0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d, 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20,
136     0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63, 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79,
137     0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30, 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d,
138     0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65,
139     0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74,
140     0x6d, 0x6c, 0x20, 0x2d, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61,
141     0x62, 0x61, 0x63, 0x3d, 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c,
142     0x6f, 0x63, 0x6b, 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73,
143     0x65, 0x3d, 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68,
144     0x65, 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
145     0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e, 0x30,
146     0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20, 0x6d, 0x65,
147     0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61,
148     0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69, 0x73, 0x3d, 0x31, 0x20,
149     0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71, 0x6d, 0x3d, 0x30, 0x20, 0x64,
150     0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31, 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61,
151     0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d, 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d,
152     0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74,
153     0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68,
154     0x65, 0x61, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c,
155     0x69, 0x63, 0x65, 0x64, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e,
156     0x72, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69,
157     0x6e, 0x74, 0x65, 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72,
158     0x61, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73,
159     0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
160     0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74,
161     0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30, 0x20, 0x6b,
162     0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20, 0x73, 0x63, 0x65,
163     0x6e, 0x65,
164 };
165 
166 class MediaCasListener : public ICasListener {
167    public:
onEvent(int32_t event,int32_t arg,const hidl_vec<uint8_t> & data)168     virtual Return<void> onEvent(int32_t event, int32_t arg,
169                                  const hidl_vec<uint8_t>& data) override {
170         android::Mutex::Autolock autoLock(mMsgLock);
171         mEvent = event;
172         mEventArg = arg;
173         mEventData = data;
174 
175         mEventReceived = true;
176         mMsgCondition.signal();
177         return Void();
178     }
179 
180     void testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
181                        hidl_vec<uint8_t>& eventData);
182 
183    private:
184     int32_t mEvent = -1;
185     int32_t mEventArg = -1;
186     bool mEventReceived = false;
187     hidl_vec<uint8_t> mEventData;
188     android::Mutex mMsgLock;
189     android::Condition mMsgCondition;
190 };
191 
testEventEcho(sp<ICas> & mediaCas,int32_t & event,int32_t & eventArg,hidl_vec<uint8_t> & eventData)192 void MediaCasListener::testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
193                                      hidl_vec<uint8_t>& eventData) {
194     mEventReceived = false;
195     auto returnStatus = mediaCas->sendEvent(event, eventArg, eventData);
196     EXPECT_TRUE(returnStatus.isOk());
197     EXPECT_EQ(Status::OK, returnStatus);
198 
199     android::Mutex::Autolock autoLock(mMsgLock);
200     while (!mEventReceived) {
201         if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
202             EXPECT_TRUE(false) << "event not received within timeout";
203             return;
204         }
205     }
206 
207     EXPECT_EQ(mEvent, event);
208     EXPECT_EQ(mEventArg, eventArg);
209     EXPECT_TRUE(mEventData == eventData);
210 }
211 
212 class MediaCasHidlTest : public testing::TestWithParam<std::string> {
213   public:
SetUp()214     virtual void SetUp() override {
215         mService = IMediaCasService::getService(GetParam());
216         ASSERT_NE(mService, nullptr);
217     }
218 
219     sp<IMediaCasService> mService = nullptr;
220 
221   protected:
description(const std::string & description)222     static void description(const std::string& description) {
223         RecordProperty("description", description);
224     }
225 
226     sp<ICas> mMediaCas;
227     sp<IDescramblerBase> mDescramblerBase;
228     sp<MediaCasListener> mCasListener;
229     typedef struct _OobInputTestParams {
230         const SubSample* subSamples;
231         uint32_t numSubSamples;
232         size_t imemSizeActual;
233         uint64_t imemOffset;
234         uint64_t imemSize;
235         uint64_t srcOffset;
236         uint64_t dstOffset;
237     } OobInputTestParams;
238 
239     ::testing::AssertionResult createCasPlugin(int32_t caSystemId);
240     ::testing::AssertionResult openCasSession(std::vector<uint8_t>* sessionId);
241     ::testing::AssertionResult descrambleTestInputBuffer(
242             const sp<IDescrambler>& descrambler,
243             Status* descrambleStatus,
244             sp<IMemory>* hidlInMemory);
245     ::testing::AssertionResult descrambleTestOobInput(
246             const sp<IDescrambler>& descrambler,
247             Status* descrambleStatus,
248             const OobInputTestParams& params);
249 };
250 
createCasPlugin(int32_t caSystemId)251 ::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) {
252     auto status = mService->isSystemIdSupported(caSystemId);
253     if (!status.isOk() || !status) {
254         return ::testing::AssertionFailure();
255     }
256     status = mService->isDescramblerSupported(caSystemId);
257     if (!status.isOk() || !status) {
258         return ::testing::AssertionFailure();
259     }
260 
261     mCasListener = new MediaCasListener();
262     auto pluginStatus = mService->createPlugin(caSystemId, mCasListener);
263     if (!pluginStatus.isOk()) {
264         return ::testing::AssertionFailure();
265     }
266     mMediaCas = pluginStatus;
267     if (mMediaCas == nullptr) {
268         return ::testing::AssertionFailure();
269     }
270 
271     auto descramblerStatus = mService->createDescrambler(caSystemId);
272     if (!descramblerStatus.isOk()) {
273         return ::testing::AssertionFailure();
274     }
275     mDescramblerBase = descramblerStatus;
276     return ::testing::AssertionResult(mDescramblerBase != nullptr);
277 }
278 
openCasSession(std::vector<uint8_t> * sessionId)279 ::testing::AssertionResult MediaCasHidlTest::openCasSession(std::vector<uint8_t>* sessionId) {
280     Status sessionStatus;
281     auto returnVoid = mMediaCas->openSession([&](Status status, const hidl_vec<uint8_t>& id) {
282         sessionStatus = status;
283         *sessionId = id;
284     });
285     return ::testing::AssertionResult(returnVoid.isOk() && (Status::OK == sessionStatus));
286 }
287 
descrambleTestInputBuffer(const sp<IDescrambler> & descrambler,Status * descrambleStatus,sp<IMemory> * inMemory)288 ::testing::AssertionResult MediaCasHidlTest::descrambleTestInputBuffer(
289     const sp<IDescrambler>& descrambler, Status* descrambleStatus, sp<IMemory>* inMemory) {
290     hidl_vec<SubSample> hidlSubSamples;
291     hidlSubSamples.setToExternal(const_cast<SubSample*>(kSubSamples),
292                                  (sizeof(kSubSamples) / sizeof(SubSample)), false /*own*/);
293 
294     sp<MemoryDealer> dealer = new MemoryDealer(sizeof(kInBinaryBuffer), "vts-cas");
295     if (nullptr == dealer.get()) {
296         ALOGE("couldn't get MemoryDealer!");
297         return ::testing::AssertionFailure();
298     }
299 
300     sp<IMemory> mem = dealer->allocate(sizeof(kInBinaryBuffer));
301     if (nullptr == mem.get()) {
302         ALOGE("couldn't allocate IMemory!");
303         return ::testing::AssertionFailure();
304     }
305     *inMemory = mem;
306 
307     // build HidlMemory from memory heap
308     ssize_t offset;
309     size_t size;
310     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
311     if (nullptr == heap.get()) {
312         ALOGE("couldn't get memory heap!");
313         return ::testing::AssertionFailure();
314     }
315 
316     uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->unsecurePointer()));
317     memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
318 
319     // hidlMemory is not to be passed out of scope!
320     sp<HidlMemory> hidlMemory = fromHeap(heap);
321 
322     SharedBuffer srcBuffer = {
323             .heapBase = *hidlMemory,
324             .offset = (uint64_t) offset,
325             .size = (uint64_t) size
326     };
327 
328     DestinationBuffer dstBuffer;
329     dstBuffer.type = BufferType::SHARED_MEMORY;
330     dstBuffer.nonsecureMemory = srcBuffer;
331 
332     uint32_t outBytes;
333     hidl_string detailedError;
334     auto returnVoid = descrambler->descramble(
335         ScramblingControl::EVENKEY /*2*/, hidlSubSamples, srcBuffer, 0, dstBuffer, 0,
336         [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
337             *descrambleStatus = status;
338             outBytes = bytesWritten;
339             detailedError = detailedErr;
340         });
341     if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
342         ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
343               returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
344     }
345     return ::testing::AssertionResult(returnVoid.isOk());
346 }
347 
descrambleTestOobInput(const sp<IDescrambler> & descrambler,Status * descrambleStatus,const OobInputTestParams & params)348 ::testing::AssertionResult MediaCasHidlTest::descrambleTestOobInput(
349         const sp<IDescrambler>& descrambler,
350         Status* descrambleStatus,
351         const OobInputTestParams& params) {
352     hidl_vec<SubSample> hidlSubSamples;
353     hidlSubSamples.setToExternal(
354             const_cast<SubSample*>(params.subSamples), params.numSubSamples, false /*own*/);
355 
356     sp<MemoryDealer> dealer = new MemoryDealer(params.imemSizeActual, "vts-cas");
357     if (nullptr == dealer.get()) {
358         ALOGE("couldn't get MemoryDealer!");
359         return ::testing::AssertionFailure();
360     }
361 
362     sp<IMemory> mem = dealer->allocate(params.imemSizeActual);
363     if (nullptr == mem.get()) {
364         ALOGE("couldn't allocate IMemory!");
365         return ::testing::AssertionFailure();
366     }
367 
368     // build HidlMemory from memory heap
369     ssize_t offset;
370     size_t size;
371     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
372     if (nullptr == heap.get()) {
373         ALOGE("couldn't get memory heap!");
374         return ::testing::AssertionFailure();
375     }
376 
377     // hidlMemory is not to be passed out of scope!
378     sp<HidlMemory> hidlMemory = fromHeap(heap);
379 
380     SharedBuffer srcBuffer = {
381             .heapBase = *hidlMemory,
382             .offset = (uint64_t) offset + params.imemOffset,
383             .size = (uint64_t) params.imemSize,
384     };
385 
386     DestinationBuffer dstBuffer;
387     dstBuffer.type = BufferType::SHARED_MEMORY;
388     dstBuffer.nonsecureMemory = srcBuffer;
389 
390     uint32_t outBytes;
391     hidl_string detailedError;
392     auto returnVoid = descrambler->descramble(
393         ScramblingControl::EVENKEY /*2*/, hidlSubSamples,
394         srcBuffer,
395         params.srcOffset,
396         dstBuffer,
397         params.dstOffset,
398         [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
399             *descrambleStatus = status;
400             outBytes = bytesWritten;
401             detailedError = detailedErr;
402         });
403     if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
404         ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
405               returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
406     }
407     return ::testing::AssertionResult(returnVoid.isOk());
408 }
409 
TEST_P(MediaCasHidlTest,EnumeratePlugins)410 TEST_P(MediaCasHidlTest, EnumeratePlugins) {
411     description("Test enumerate plugins");
412     hidl_vec<HidlCasPluginDescriptor> descriptors;
413     EXPECT_TRUE(mService
414                     ->enumeratePlugins([&descriptors](
415                         hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
416                     .isOk());
417 
418     if (descriptors.size() == 0) {
419         ALOGW("[   WARN   ] enumeratePlugins list empty");
420         return;
421     }
422 
423     sp<MediaCasListener> casListener = new MediaCasListener();
424     for (size_t i = 0; i < descriptors.size(); i++) {
425         int32_t caSystemId = descriptors[i].caSystemId;
426 
427         ASSERT_TRUE(createCasPlugin(caSystemId));
428     }
429 }
430 
TEST_P(MediaCasHidlTest,TestInvalidSystemIdFails)431 TEST_P(MediaCasHidlTest, TestInvalidSystemIdFails) {
432     description("Test failure for invalid system ID");
433     sp<MediaCasListener> casListener = new MediaCasListener();
434 
435     ASSERT_FALSE(mService->isSystemIdSupported(INVALID_SYSTEM_ID));
436     ASSERT_FALSE(mService->isDescramblerSupported(INVALID_SYSTEM_ID));
437 
438     auto pluginStatus = mService->createPlugin(INVALID_SYSTEM_ID, casListener);
439     ASSERT_TRUE(pluginStatus.isOk());
440     sp<ICas> mediaCas = pluginStatus;
441     EXPECT_EQ(mediaCas, nullptr);
442 
443     auto descramblerStatus = mService->createDescrambler(INVALID_SYSTEM_ID);
444     ASSERT_TRUE(descramblerStatus.isOk());
445     sp<IDescramblerBase> descramblerBase = descramblerStatus;
446     EXPECT_EQ(descramblerBase, nullptr);
447 }
448 
TEST_P(MediaCasHidlTest,TestClearKeyPluginInstalled)449 TEST_P(MediaCasHidlTest, TestClearKeyPluginInstalled) {
450     description("Test if ClearKey plugin is installed");
451     hidl_vec<HidlCasPluginDescriptor> descriptors;
452     EXPECT_TRUE(mService
453                     ->enumeratePlugins([&descriptors](
454                         hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
455                     .isOk());
456 
457     if (descriptors.size() == 0) {
458         ALOGW("[   WARN   ] enumeratePlugins list empty");
459     }
460 
461     for (size_t i = 0; i < descriptors.size(); i++) {
462         int32_t caSystemId = descriptors[i].caSystemId;
463         if (CLEAR_KEY_SYSTEM_ID == caSystemId) {
464             return;
465         }
466     }
467 
468     ASSERT_TRUE(false) << "ClearKey plugin not installed";
469 }
470 
TEST_P(MediaCasHidlTest,TestClearKeyApis)471 TEST_P(MediaCasHidlTest, TestClearKeyApis) {
472     description("Test that valid call sequences succeed");
473 
474     ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
475 
476     auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
477     EXPECT_TRUE(returnStatus.isOk());
478     EXPECT_EQ(Status::OK, returnStatus);
479 
480     hidl_vec<uint8_t> hidlPvtData;
481     hidlPvtData.resize(256);
482     returnStatus = mMediaCas->setPrivateData(hidlPvtData);
483     EXPECT_TRUE(returnStatus.isOk());
484     EXPECT_EQ(Status::OK, returnStatus);
485 
486     std::vector<uint8_t> sessionId;
487     ASSERT_TRUE(openCasSession(&sessionId));
488     returnStatus = mMediaCas->setSessionPrivateData(sessionId, hidlPvtData);
489     EXPECT_TRUE(returnStatus.isOk());
490     EXPECT_EQ(Status::OK, returnStatus);
491 
492     std::vector<uint8_t> streamSessionId;
493     ASSERT_TRUE(openCasSession(&streamSessionId));
494     returnStatus = mMediaCas->setSessionPrivateData(streamSessionId, hidlPvtData);
495     EXPECT_TRUE(returnStatus.isOk());
496     EXPECT_EQ(Status::OK, returnStatus);
497 
498     returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
499     EXPECT_TRUE(returnStatus.isOk());
500     EXPECT_EQ(Status::OK, returnStatus);
501 
502     returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
503     EXPECT_TRUE(returnStatus.isOk());
504     EXPECT_EQ(Status::OK, returnStatus);
505 
506     hidl_vec<uint8_t> hidlNullPtr;
507     hidlNullPtr.setToExternal(static_cast<uint8_t*>(nullptr), 0);
508     returnStatus = mMediaCas->refreshEntitlements(3, hidlNullPtr);
509     EXPECT_TRUE(returnStatus.isOk());
510     EXPECT_EQ(Status::OK, returnStatus);
511 
512     uint8_t refreshData[] = {0, 1, 2, 3};
513     hidl_vec<uint8_t> hidlRefreshData;
514     hidlRefreshData.setToExternal(static_cast<uint8_t*>(refreshData), sizeof(refreshData));
515     returnStatus = mMediaCas->refreshEntitlements(10, hidlRefreshData);
516     EXPECT_TRUE(returnStatus.isOk());
517     EXPECT_EQ(Status::OK, returnStatus);
518 
519     int32_t eventID = 1;
520     int32_t eventArg = 2;
521     mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlNullPtr);
522 
523     eventID = 3;
524     eventArg = 4;
525     uint8_t eventData[] = {'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
526     hidl_vec<uint8_t> hidlEventData;
527     hidlEventData.setToExternal(static_cast<uint8_t*>(eventData), sizeof(eventData));
528     mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlEventData);
529 
530     uint8_t clearKeyEmmData[] = {'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
531     hidl_vec<uint8_t> hidlClearKeyEmm;
532     hidlClearKeyEmm.setToExternal(static_cast<uint8_t*>(clearKeyEmmData), sizeof(clearKeyEmmData));
533     returnStatus = mMediaCas->processEmm(hidlClearKeyEmm);
534     EXPECT_TRUE(returnStatus.isOk());
535     EXPECT_EQ(Status::OK, returnStatus);
536 
537     hidl_vec<uint8_t> hidlEcm;
538     hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
539     returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
540     EXPECT_TRUE(returnStatus.isOk());
541     EXPECT_EQ(Status::OK, returnStatus);
542     returnStatus = mMediaCas->processEcm(streamSessionId, hidlEcm);
543     EXPECT_TRUE(returnStatus.isOk());
544     EXPECT_EQ(Status::OK, returnStatus);
545 
546     EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
547 
548     sp<IDescrambler> descrambler;
549     descrambler = IDescrambler::castFrom(mDescramblerBase);
550     ASSERT_NE(descrambler, nullptr);
551 
552     Status descrambleStatus = Status::OK;
553     sp<IMemory> dataMemory;
554 
555     ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
556     EXPECT_EQ(Status::OK, descrambleStatus);
557 
558     ASSERT_NE(nullptr, dataMemory.get());
559     uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
560 
561     int compareResult =
562         memcmp(static_cast<const void*>(opBuffer), static_cast<const void*>(kOutRefBinaryBuffer),
563                sizeof(kOutRefBinaryBuffer));
564     EXPECT_EQ(0, compareResult);
565 
566     returnStatus = mDescramblerBase->release();
567     EXPECT_TRUE(returnStatus.isOk());
568     EXPECT_EQ(Status::OK, returnStatus);
569 
570     returnStatus = mMediaCas->release();
571     EXPECT_TRUE(returnStatus.isOk());
572     EXPECT_EQ(Status::OK, returnStatus);
573 }
574 
TEST_P(MediaCasHidlTest,TestClearKeySessionClosedAfterRelease)575 TEST_P(MediaCasHidlTest, TestClearKeySessionClosedAfterRelease) {
576     description("Test that all sessions are closed after a MediaCas object is released");
577 
578     ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
579 
580     auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
581     EXPECT_TRUE(returnStatus.isOk());
582     EXPECT_EQ(Status::OK, returnStatus);
583 
584     std::vector<uint8_t> sessionId;
585     ASSERT_TRUE(openCasSession(&sessionId));
586     std::vector<uint8_t> streamSessionId;
587     ASSERT_TRUE(openCasSession(&streamSessionId));
588 
589     returnStatus = mMediaCas->release();
590     EXPECT_TRUE(returnStatus.isOk());
591     EXPECT_EQ(Status::OK, returnStatus);
592 
593     returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
594     EXPECT_TRUE(returnStatus.isOk());
595     EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
596 
597     returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
598     EXPECT_TRUE(returnStatus.isOk());
599     EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
600 }
601 
TEST_P(MediaCasHidlTest,TestClearKeyErrors)602 TEST_P(MediaCasHidlTest, TestClearKeyErrors) {
603     description("Test that invalid call sequences fail with expected error codes");
604 
605     ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
606 
607     /*
608      * Test MediaCas error codes
609      */
610     // Provision should fail with an invalid asset string
611     auto returnStatus = mMediaCas->provision(hidl_string("invalid asset string"));
612     EXPECT_TRUE(returnStatus.isOk());
613     EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus);
614 
615     // Open a session, then close it so that it should become invalid
616     std::vector<uint8_t> invalidSessionId;
617     ASSERT_TRUE(openCasSession(&invalidSessionId));
618     returnStatus = mMediaCas->closeSession(invalidSessionId);
619     EXPECT_TRUE(returnStatus.isOk());
620     EXPECT_EQ(Status::OK, returnStatus);
621 
622     // processEcm should fail with an invalid session id
623     hidl_vec<uint8_t> hidlEcm;
624     hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
625     returnStatus = mMediaCas->processEcm(invalidSessionId, hidlEcm);
626     EXPECT_TRUE(returnStatus.isOk());
627     EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
628 
629     std::vector<uint8_t> sessionId;
630     ASSERT_TRUE(openCasSession(&sessionId));
631 
632     // processEcm should fail without provisioning
633     hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
634     returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
635     EXPECT_TRUE(returnStatus.isOk());
636     EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus);
637 
638     returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
639     EXPECT_TRUE(returnStatus.isOk());
640     EXPECT_EQ(Status::OK, returnStatus);
641 
642     // processEcm should fail with ecm buffer that's too short
643     hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), 8);
644     returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
645     EXPECT_TRUE(returnStatus.isOk());
646     EXPECT_EQ(Status::BAD_VALUE, returnStatus);
647 
648     // processEcm should fail with ecm with bad descriptor count
649     uint8_t badDescriptor[sizeof(kEcmBinaryBuffer)];
650     memcpy(badDescriptor, kEcmBinaryBuffer, sizeof(kEcmBinaryBuffer));
651     badDescriptor[17] = 0x03;  // change the descriptor count field to 3 (invalid)
652     hidlEcm.setToExternal(static_cast<uint8_t*>(badDescriptor), sizeof(badDescriptor));
653     returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
654     EXPECT_TRUE(returnStatus.isOk());
655     EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus);
656 
657     /*
658      * Test MediaDescrambler error codes
659      */
660     // setMediaCasSession should fail with an invalid session id
661     returnStatus = mDescramblerBase->setMediaCasSession(invalidSessionId);
662     EXPECT_TRUE(returnStatus.isOk());
663     EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
664 
665     // descramble should fail without a valid session
666     sp<IDescrambler> descrambler;
667     descrambler = IDescrambler::castFrom(mDescramblerBase);
668     ASSERT_NE(descrambler, nullptr);
669 
670     Status descrambleStatus = Status::OK;
671     sp<IMemory> dataMemory;
672 
673     ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
674     EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus);
675 
676     // Now set a valid session, should still fail because no valid ecm is processed
677     returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
678     EXPECT_TRUE(returnStatus.isOk());
679     EXPECT_EQ(Status::OK, returnStatus);
680 
681     ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
682     EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus);
683 
684     // Verify that requiresSecureDecoderComponent handles empty mime
685     EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent(""));
686 
687     // Verify that requiresSecureDecoderComponent handles invalid mime
688     EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad"));
689 }
690 
TEST_P(MediaCasHidlTest,TestClearKeyOobFails)691 TEST_P(MediaCasHidlTest, TestClearKeyOobFails) {
692     description("Test that oob descramble request fails with expected error");
693 
694     ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
695 
696     auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
697     EXPECT_TRUE(returnStatus.isOk());
698     EXPECT_EQ(Status::OK, returnStatus);
699 
700     std::vector<uint8_t> sessionId;
701     ASSERT_TRUE(openCasSession(&sessionId));
702 
703     returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
704     EXPECT_TRUE(returnStatus.isOk());
705     EXPECT_EQ(Status::OK, returnStatus);
706 
707     hidl_vec<uint8_t> hidlEcm;
708     hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
709     returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
710     EXPECT_TRUE(returnStatus.isOk());
711     EXPECT_EQ(Status::OK, returnStatus);
712 
713     sp<IDescrambler> descrambler = IDescrambler::castFrom(mDescramblerBase);
714     ASSERT_NE(nullptr, descrambler.get());
715 
716     Status descrambleStatus = Status::OK;
717 
718     // test invalid src buffer offset
719     ASSERT_TRUE(descrambleTestOobInput(
720             descrambler,
721             &descrambleStatus,
722             {
723                 .subSamples     = kSubSamples,
724                 .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
725                 .imemSizeActual = sizeof(kInBinaryBuffer),
726                 .imemOffset     = 0xcccccc,
727                 .imemSize       = sizeof(kInBinaryBuffer),
728                 .srcOffset      = 0,
729                 .dstOffset      = 0
730             }));
731     EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
732 
733     // test invalid src buffer size
734     ASSERT_TRUE(descrambleTestOobInput(
735             descrambler,
736             &descrambleStatus,
737             {
738                 .subSamples     = kSubSamples,
739                 .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
740                 .imemSizeActual = sizeof(kInBinaryBuffer),
741                 .imemOffset     = 0,
742                 .imemSize       = 0xcccccc,
743                 .srcOffset      = 0,
744                 .dstOffset      = 0
745             }));
746     EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
747 
748     // test invalid src buffer size
749     ASSERT_TRUE(descrambleTestOobInput(
750             descrambler,
751             &descrambleStatus,
752             {
753                 .subSamples     = kSubSamples,
754                 .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
755                 .imemSizeActual = sizeof(kInBinaryBuffer),
756                 .imemOffset     = 1,
757                 .imemSize       = (uint64_t)-1,
758                 .srcOffset      = 0,
759                 .dstOffset      = 0
760             }));
761     EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
762 
763     // test invalid srcOffset
764     ASSERT_TRUE(descrambleTestOobInput(
765             descrambler,
766             &descrambleStatus,
767             {
768                 .subSamples     = kSubSamples,
769                 .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
770                 .imemSizeActual = sizeof(kInBinaryBuffer),
771                 .imemOffset     = 0,
772                 .imemSize       = sizeof(kInBinaryBuffer),
773                 .srcOffset      = 0xcccccc,
774                 .dstOffset      = 0
775             }));
776     EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
777 
778     // test invalid dstOffset
779     ASSERT_TRUE(descrambleTestOobInput(
780             descrambler,
781             &descrambleStatus,
782             {
783                 .subSamples     = kSubSamples,
784                 .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
785                 .imemSizeActual = sizeof(kInBinaryBuffer),
786                 .imemOffset     = 0,
787                 .imemSize       = sizeof(kInBinaryBuffer),
788                 .srcOffset      = 0,
789                 .dstOffset      = 0xcccccc
790             }));
791     EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
792 
793     // test detection of oob subsample sizes
794     const SubSample invalidSubSamples1[] =
795         {{162, 0}, {0, 184}, {0, 0xdddddd}};
796 
797     ASSERT_TRUE(descrambleTestOobInput(
798             descrambler,
799             &descrambleStatus,
800             {
801                 .subSamples     = invalidSubSamples1,
802                 .numSubSamples  = sizeof(invalidSubSamples1)/sizeof(SubSample),
803                 .imemSizeActual = sizeof(kInBinaryBuffer),
804                 .imemOffset     = 0,
805                 .imemSize       = sizeof(kInBinaryBuffer),
806                 .srcOffset      = 0,
807                 .dstOffset      = 0
808             }));
809     EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
810 
811     // test detection of overflowing subsample sizes
812     const SubSample invalidSubSamples2[] =
813         {{162, 0}, {0, 184}, {2, (uint32_t)-1}};
814 
815     ASSERT_TRUE(descrambleTestOobInput(
816             descrambler,
817             &descrambleStatus,
818             {
819                 .subSamples     = invalidSubSamples2,
820                 .numSubSamples  = sizeof(invalidSubSamples2)/sizeof(SubSample),
821                 .imemSizeActual = sizeof(kInBinaryBuffer),
822                 .imemOffset     = 0,
823                 .imemSize       = sizeof(kInBinaryBuffer),
824                 .srcOffset      = 0,
825                 .dstOffset      = 0
826             }));
827     EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
828 
829     returnStatus = mDescramblerBase->release();
830     EXPECT_TRUE(returnStatus.isOk());
831     EXPECT_EQ(Status::OK, returnStatus);
832 
833     returnStatus = mMediaCas->release();
834     EXPECT_TRUE(returnStatus.isOk());
835     EXPECT_EQ(Status::OK, returnStatus);
836 }
837 
838 }  // anonymous namespace
839 
840 INSTANTIATE_TEST_SUITE_P(
841         PerInstance, MediaCasHidlTest,
842         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMediaCasService::descriptor)),
843         android::hardware::PrintInstanceNameToString);