blob: 266b55d1a16f4246db0c49525ad8a7785d0158b0 [file] [log] [blame]
Shraddha Basantwani9837ac12022-09-21 16:30:04 +05301/*
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
48using aidl::android::hardware::common::Ashmem;
49using android::Mutex;
50using namespace aidl::android::hardware::cas;
51using namespace ndk;
52using namespace std;
53using namespace testing;
54
55const 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
64const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
65
66const 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
105const 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
144class MediaCasListener : public BnCasListener {
145 public:
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
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
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
201void 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
220void 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
240void 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
256class MediaCasAidlTest : public testing::TestWithParam<string> {
257 public:
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:
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 openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
290 ScramblingMode mode);
291 AssertionResult descrambleTestInputBuffer(const shared_ptr<IDescrambler>& descrambler,
292 ScopedAStatus& descrambleStatus, uint8_t*& inMemory);
293 AssertionResult descrambleTestOobInput(const shared_ptr<IDescrambler>& descrambler,
294 ScopedAStatus& descrambleStatus,
295 const OobInputTestParams& params);
296};
297
298AssertionResult MediaCasAidlTest::createCasPlugin(int32_t caSystemId) {
299 bool isSystemIdSupported;
300 auto status = mService->isSystemIdSupported(caSystemId, &isSystemIdSupported);
301 bool skipDescrambler = false;
302 if (!status.isOk() || !isSystemIdSupported) {
303 return AssertionFailure();
304 }
305 bool isDescramblerSupported;
306 status = mService->isDescramblerSupported(caSystemId, &isDescramblerSupported);
307 if (!status.isOk() || !isDescramblerSupported) {
308 ALOGI("Skip Descrambler test since it's not required in cas.");
309 mDescrambler = nullptr;
310 skipDescrambler = true;
311 }
312
313 mCasListener = SharedRefBase::make<MediaCasListener>();
314 status = mService->createPlugin(caSystemId, mCasListener, &mMediaCas);
315 if (!status.isOk()) {
316 return AssertionFailure();
317 }
318 if (mMediaCas == nullptr) {
319 return AssertionFailure();
320 }
321
322 if (skipDescrambler) {
323 return AssertionSuccess();
324 }
325
326 status = mService->createDescrambler(caSystemId, &mDescrambler);
327 if (!status.isOk()) {
328 return AssertionFailure();
329 }
330
331 return AssertionResult(mDescrambler != nullptr);
332}
333
334AssertionResult MediaCasAidlTest::openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
335 ScramblingMode mode) {
336 return AssertionResult(mMediaCas->openSession(intent, mode, sessionId).isOk());
337}
338
339AssertionResult MediaCasAidlTest::descrambleTestInputBuffer(
340 const shared_ptr<IDescrambler>& descrambler, ScopedAStatus& descrambleStatus,
341 uint8_t*& sharedMemory) {
342 vector<SubSample> subSample(kSubSamples,
343 kSubSamples + (sizeof(kSubSamples) / sizeof(SubSample)));
344
345 int size = sizeof(kInBinaryBuffer);
346 auto fd = ashmem_create_region("vts-cas", size);
347 if (fd < 0) {
348 ALOGE("ashmem_create_region failed");
349 return AssertionFailure();
350 }
351
352 sharedMemory =
353 static_cast<uint8_t*>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
354 if (sharedMemory == reinterpret_cast<uint8_t*>(MAP_FAILED)) {
355 ALOGE("mmap failed");
356 return AssertionFailure();
357 }
358
359 memcpy(sharedMemory, kInBinaryBuffer, size);
360
361 auto dupFd = dup(fd);
362
363 SharedBuffer srcBuffer = {.heapBase.fd = ScopedFileDescriptor(std::move(fd)),
364 .heapBase.size = size,
365 .offset = 0,
366 .size = size};
367
368 SharedBuffer dupBuffer = {.heapBase.fd = ScopedFileDescriptor(dupFd),
369 .heapBase.size = size,
370 .offset = 0,
371 .size = size};
372
373 DestinationBuffer dstBuffer;
374 dstBuffer.set<DestinationBuffer::nonsecureMemory>(std::move(dupBuffer));
375
376 int32_t outBytes;
377 descrambleStatus = descrambler->descramble(ScramblingControl::EVENKEY /*2*/, subSample,
378 srcBuffer, 0, dstBuffer, 0, &outBytes);
379 if (!descrambleStatus.isOk()) {
380 ALOGI("descramble failed, status=%d, outBytes=%u, error=%s", descrambleStatus.getStatus(),
381 outBytes, descrambleStatus.getDescription().c_str());
382 }
383 return AssertionResult(descrambleStatus.isOk());
384}
385
386AssertionResult MediaCasAidlTest::descrambleTestOobInput(
387 const shared_ptr<IDescrambler>& descrambler, ScopedAStatus& descrambleStatus,
388 const OobInputTestParams& params) {
389 vector<SubSample> subSample(params.subSamples, params.subSamples + params.numSubSamples);
390
391 auto fd = ashmem_create_region("vts-cas", params.imemSizeActual);
392 if (fd < 0) {
393 ALOGE("ashmem_create_region failed");
394 return AssertionFailure();
395 }
396
397 auto dupFd = dup(fd);
398
399 SharedBuffer srcBuffer = {.heapBase.fd = ScopedFileDescriptor(std::move(fd)),
400 .heapBase.size = params.imemSizeActual,
401 .offset = params.imemOffset,
402 .size = params.imemSize};
403
404 SharedBuffer dupBuffer = {.heapBase.fd = ScopedFileDescriptor(dupFd),
405 .heapBase.size = params.imemSizeActual,
406 .offset = params.imemOffset,
407 .size = params.imemSize};
408
409 DestinationBuffer dstBuffer;
410 dstBuffer.set<DestinationBuffer::nonsecureMemory>(std::move(dupBuffer));
411
412 int32_t outBytes;
413 descrambleStatus =
414 descrambler->descramble(ScramblingControl::EVENKEY /*2*/, subSample, srcBuffer,
415 params.srcOffset, dstBuffer, params.dstOffset, &outBytes);
416 if (!descrambleStatus.isOk()) {
417 ALOGI("descramble failed, status=%d, outBytes=%u, error=%s", descrambleStatus.getStatus(),
418 outBytes, descrambleStatus.getDescription().c_str());
419 }
420 return AssertionResult(descrambleStatus.isOk());
421}
422
423TEST_P(MediaCasAidlTest, EnumeratePlugins) {
424 description("Test enumerate plugins");
425
426 vector<AidlCasPluginDescriptor> descriptors;
427 EXPECT_TRUE(mService->enumeratePlugins(&descriptors).isOk());
428
429 if (descriptors.size() == 0) {
430 ALOGW("[ WARN ] enumeratePlugins list empty");
431 return;
432 }
433
434 for (size_t i = 0; i < descriptors.size(); i++) {
435 int32_t caSystemId = descriptors[i].caSystemId;
436
437 ASSERT_TRUE(createCasPlugin(caSystemId));
438 }
439}
440
441TEST_P(MediaCasAidlTest, TestInvalidSystemIdFails) {
442 description("Test failure for invalid system ID");
443
444 bool isSystemIdSupported;
445 auto status = mService->isSystemIdSupported(INVALID_SYSTEM_ID, &isSystemIdSupported);
446
447 EXPECT_TRUE(status.isOk());
448 ASSERT_FALSE(isSystemIdSupported);
449
450 bool isDescramblerSupported;
451 status = mService->isDescramblerSupported(INVALID_SYSTEM_ID, &isDescramblerSupported);
452
453 EXPECT_TRUE(status.isOk());
454 ASSERT_FALSE(isDescramblerSupported);
455
456 shared_ptr<ICas> mediaCas;
457 shared_ptr<MediaCasListener> casListener = SharedRefBase::make<MediaCasListener>();
458 status = mService->createPlugin(INVALID_SYSTEM_ID, casListener, &mediaCas);
459 ASSERT_TRUE(status.isOk());
460 EXPECT_EQ(mediaCas, nullptr);
461
462 shared_ptr<IDescrambler> descrambler;
463 status = mService->createDescrambler(INVALID_SYSTEM_ID, &descrambler);
464 ASSERT_TRUE(status.isOk());
465 EXPECT_EQ(descrambler, nullptr);
466}
467
468TEST_P(MediaCasAidlTest, TestClearKeyPluginInstalled) {
469 description("Test if ClearKey plugin is installed");
470
471 vector<AidlCasPluginDescriptor> descriptors;
472 EXPECT_TRUE(mService->enumeratePlugins(&descriptors).isOk());
473
474 if (descriptors.size() == 0) {
475 ALOGW("[ WARN ] enumeratePlugins list empty");
476 }
477
478 for (size_t i = 0; i < descriptors.size(); i++) {
479 int32_t caSystemId = descriptors[i].caSystemId;
480 if (CLEAR_KEY_SYSTEM_ID == caSystemId) {
481 return;
482 }
483 }
484
485 ADD_FAILURE() << "ClearKey plugin not installed";
486}
487
488TEST_P(MediaCasAidlTest, TestClearKeySessionClosedAfterRelease) {
489 description("Test that all sessions are closed after a MediaCas object is released");
490
491 ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
492
493 EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
494
495 SessionIntent intent = SessionIntent::LIVE;
496 ScramblingMode mode = ScramblingMode::DVB_CSA1;
497
498 vector<uint8_t> sessionId;
499 ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
500
501 vector<uint8_t> streamSessionId;
502 ASSERT_TRUE(openCasSession(&streamSessionId, intent, mode));
503
504 EXPECT_TRUE(mMediaCas->release().isOk());
505
506 if (mDescrambler != nullptr) {
507 auto status = mDescrambler->setMediaCasSession(sessionId);
508 EXPECT_FALSE(status.isOk());
509 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
510
511 status = mDescrambler->setMediaCasSession(streamSessionId);
512 EXPECT_FALSE(status.isOk());
513 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
514 }
515}
516
517TEST_P(MediaCasAidlTest, TestClearKeyErrors) {
518 description("Test that invalid call sequences fail with expected error codes");
519
520 ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
521
522 /*
523 * Test MediaCas error codes
524 */
525 // Provision should fail with an invalid asset string
526 auto returnStatus = mMediaCas->provision("invalid asset string");
527 EXPECT_FALSE(returnStatus.isOk());
528 EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus.getServiceSpecificError());
529
530 SessionIntent intent = SessionIntent::LIVE;
531 ScramblingMode mode = ScramblingMode::DVB_CSA1;
532
533 // Open a session, then close it so that it should become invalid
534 vector<uint8_t> invalidSessionId;
535 ASSERT_TRUE(openCasSession(&invalidSessionId, intent, mode));
536 EXPECT_TRUE(mMediaCas->closeSession(invalidSessionId).isOk());
537
538 // processEcm should fail with an invalid session id
539 vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
540 returnStatus = mMediaCas->processEcm(invalidSessionId, ecm);
541 EXPECT_FALSE(returnStatus.isOk());
542 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus.getServiceSpecificError());
543
544 vector<uint8_t> sessionId;
545 ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
546
547 // processEcm should fail without provisioning
548 returnStatus = mMediaCas->processEcm(sessionId, ecm);
549 EXPECT_FALSE(returnStatus.isOk());
550 EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus.getServiceSpecificError());
551
552 EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
553
554 // processEcm should fail with ecm with bad descriptor count
555 ecm[17] = 0x03; // change the descriptor count field to 3 (invalid)
556 returnStatus = mMediaCas->processEcm(sessionId, ecm);
557 EXPECT_FALSE(returnStatus.isOk());
558 EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus.getServiceSpecificError());
559
560 // processEcm should fail with ecm buffer that's too short
561 ecm.resize(8);
562 returnStatus = mMediaCas->processEcm(sessionId, ecm);
563 EXPECT_FALSE(returnStatus.isOk());
564 EXPECT_EQ(Status::BAD_VALUE, returnStatus.getServiceSpecificError());
565
566 if (mDescrambler != nullptr) {
567 /*
568 * Test MediaDescrambler error codes
569 */
570 // setMediaCasSession should fail with an invalid session id
571 returnStatus = mDescrambler->setMediaCasSession(invalidSessionId);
572 EXPECT_FALSE(returnStatus.isOk());
573 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus.getServiceSpecificError());
574
575 // descramble should fail without a valid session
576 ScopedAStatus descrambleStatus = ScopedAStatus::ok();
577 uint8_t* sharedBuffer = nullptr;
578
579 ASSERT_FALSE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
580 EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED,
581 descrambleStatus.getServiceSpecificError());
582
583 // Now set a valid session, should still fail because no valid ecm is processed
584 EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
585 ASSERT_FALSE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
586 EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus.getServiceSpecificError());
587
588 // Verify that requiresSecureDecoderComponent handles empty mime
589 bool requiresSecureDecoderComponent = true;
590 EXPECT_TRUE(
591 mDescrambler->requiresSecureDecoderComponent("", &requiresSecureDecoderComponent)
592 .isOk());
593 EXPECT_FALSE(requiresSecureDecoderComponent);
594
595 // Verify that requiresSecureDecoderComponent handles invalid mime
596 requiresSecureDecoderComponent = true;
597 EXPECT_TRUE(
598 mDescrambler->requiresSecureDecoderComponent("bad", &requiresSecureDecoderComponent)
599 .isOk());
600 EXPECT_FALSE(requiresSecureDecoderComponent);
601 }
602}
603
604TEST_P(MediaCasAidlTest, TestClearKeyApisWithSession) {
605 description("Test that valid call sequences with SessionEvent send and receive");
606
607 ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
608
609 EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
610
611 vector<uint8_t> pvtData;
612 pvtData.resize(256);
613 EXPECT_TRUE(mMediaCas->setPrivateData(pvtData).isOk());
614
615 SessionIntent intent = SessionIntent::LIVE;
616 ScramblingMode mode = ScramblingMode::DVB_CSA1;
617
618 vector<uint8_t> sessionId;
619 ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
620 EXPECT_TRUE(mMediaCas->setSessionPrivateData(sessionId, pvtData).isOk());
621
622 vector<uint8_t> streamSessionId;
623 ASSERT_TRUE(openCasSession(&streamSessionId, intent, mode));
624 EXPECT_TRUE(mMediaCas->setSessionPrivateData(streamSessionId, pvtData).isOk());
625
626 if (mDescrambler != nullptr) {
627 EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
628 EXPECT_TRUE(mDescrambler->setMediaCasSession(streamSessionId).isOk());
629 }
630
631 vector<uint8_t> nullPtrVector(0);
632 EXPECT_TRUE(mMediaCas->refreshEntitlements(3, nullPtrVector).isOk());
633
634 vector<uint8_t> refreshData{0, 1, 2, 3};
635 EXPECT_TRUE(mMediaCas->refreshEntitlements(10, refreshData).isOk());
636
637 int32_t eventID = 1;
638 int32_t eventArg = 2;
639 mCasListener->testEventEcho(mMediaCas, eventID, eventArg, nullPtrVector);
640 mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, nullPtrVector);
641
642 eventID = 3;
643 eventArg = 4;
644 vector<uint8_t> eventData{'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
645 mCasListener->testEventEcho(mMediaCas, eventID, eventArg, eventData);
646 mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, eventData);
647
648 mCasListener->testStatusUpdate(mMediaCas, &sessionId, intent, mode);
649
650 vector<uint8_t> clearKeyEmmData{'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
651 EXPECT_TRUE(mMediaCas->processEmm(clearKeyEmmData).isOk());
652
653 vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
654 EXPECT_TRUE(mMediaCas->processEcm(sessionId, ecm).isOk());
655 EXPECT_TRUE(mMediaCas->processEcm(streamSessionId, ecm).isOk());
656
657 if (mDescrambler != nullptr) {
658 bool requiresSecureDecoderComponent = true;
659 EXPECT_TRUE(mDescrambler
660 ->requiresSecureDecoderComponent("video/avc",
661 &requiresSecureDecoderComponent)
662 .isOk());
663 EXPECT_FALSE(requiresSecureDecoderComponent);
664
665 ScopedAStatus descrambleStatus = ScopedAStatus::ok();
666 uint8_t* sharedBuffer = nullptr;
667
668 ASSERT_TRUE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
669
670 int compareResult =
671 memcmp(static_cast<const void*>(sharedBuffer),
672 static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
673 EXPECT_EQ(0, compareResult);
674
675 EXPECT_TRUE(mDescrambler->release().isOk());
676 }
677
678 EXPECT_TRUE(mMediaCas->release().isOk());
679}
680
681TEST_P(MediaCasAidlTest, TestClearKeyOobFails) {
682 description("Test that oob descramble request fails with expected error");
683
684 ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
685 EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
686
687 SessionIntent intent = SessionIntent::LIVE;
688 ScramblingMode mode = ScramblingMode::DVB_CSA1;
689
690 vector<uint8_t> sessionId;
691 ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
692
693 if (mDescrambler != nullptr) {
694 EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
695 }
696
697 vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
698 EXPECT_TRUE(mMediaCas->processEcm(sessionId, ecm).isOk());
699
700 if (mDescrambler != nullptr) {
701 ScopedAStatus descrambleStatus = ScopedAStatus::ok();
702
703 // test invalid src buffer offset
704 ASSERT_FALSE(
705 descrambleTestOobInput(mDescrambler, descrambleStatus,
706 {.subSamples = kSubSamples,
707 .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
708 .imemSizeActual = sizeof(kInBinaryBuffer),
709 .imemOffset = 0xcccccc,
710 .imemSize = sizeof(kInBinaryBuffer),
711 .srcOffset = 0,
712 .dstOffset = 0}));
713 EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
714
715 // test invalid src buffer size
716 ASSERT_FALSE(
717 descrambleTestOobInput(mDescrambler, descrambleStatus,
718 {.subSamples = kSubSamples,
719 .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
720 .imemSizeActual = sizeof(kInBinaryBuffer),
721 .imemOffset = 0,
722 .imemSize = 0xcccccc,
723 .srcOffset = 0,
724 .dstOffset = 0}));
725 EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
726
727 // test invalid src buffer size
728 ASSERT_FALSE(
729 descrambleTestOobInput(mDescrambler, descrambleStatus,
730 {.subSamples = kSubSamples,
731 .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
732 .imemSizeActual = sizeof(kInBinaryBuffer),
733 .imemOffset = 1,
734 .imemSize = -1,
735 .srcOffset = 0,
736 .dstOffset = 0}));
737 EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
738
739 // test invalid srcOffset
740 ASSERT_FALSE(
741 descrambleTestOobInput(mDescrambler, descrambleStatus,
742 {.subSamples = kSubSamples,
743 .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
744 .imemSizeActual = sizeof(kInBinaryBuffer),
745 .imemOffset = 0,
746 .imemSize = sizeof(kInBinaryBuffer),
747 .srcOffset = 0xcccccc,
748 .dstOffset = 0}));
749 EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
750
751 // test invalid dstOffset
752 ASSERT_FALSE(
753 descrambleTestOobInput(mDescrambler, descrambleStatus,
754 {.subSamples = kSubSamples,
755 .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
756 .imemSizeActual = sizeof(kInBinaryBuffer),
757 .imemOffset = 0,
758 .imemSize = sizeof(kInBinaryBuffer),
759 .srcOffset = 0,
760 .dstOffset = 0xcccccc}));
761 EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
762
763 // test detection of oob subsample sizes
764 const SubSample invalidSubSamples1[] = {{162, 0}, {0, 184}, {0, 0xdddddd}};
765
766 ASSERT_FALSE(descrambleTestOobInput(
767 mDescrambler, descrambleStatus,
768 {.subSamples = invalidSubSamples1,
769 .numSubSamples = sizeof(invalidSubSamples1) / sizeof(SubSample),
770 .imemSizeActual = sizeof(kInBinaryBuffer),
771 .imemOffset = 0,
772 .imemSize = sizeof(kInBinaryBuffer),
773 .srcOffset = 0,
774 .dstOffset = 0}));
775 EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
776
777 // test detection of overflowing subsample sizes
778 const SubSample invalidSubSamples2[] = {{162, 0}, {0, 184}, {2, -1}};
779
780 ASSERT_FALSE(descrambleTestOobInput(
781 mDescrambler, descrambleStatus,
782 {.subSamples = invalidSubSamples2,
783 .numSubSamples = sizeof(invalidSubSamples2) / sizeof(SubSample),
784 .imemSizeActual = sizeof(kInBinaryBuffer),
785 .imemOffset = 0,
786 .imemSize = sizeof(kInBinaryBuffer),
787 .srcOffset = 0,
788 .dstOffset = 0}));
789 EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
790
791 EXPECT_TRUE(mDescrambler->release().isOk());
792 }
793 EXPECT_TRUE(mMediaCas->release().isOk());
794}
795
796GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MediaCasAidlTest);
797
798INSTANTIATE_TEST_SUITE_P(
799 PerInstance, MediaCasAidlTest,
800 testing::ValuesIn(android::getAidlHalInstanceNames(IMediaCasService::descriptor)),
801 android::PrintInstanceNameToString);
802
803// Start thread pool to receive callbacks from AIDL service.
804int main(int argc, char** argv) {
805 InitGoogleTest(&argc, argv);
806 ABinderProcess_setThreadPoolMaxThreadCount(1);
807 ABinderProcess_startThreadPool();
808 return RUN_ALL_TESTS();
809}