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