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