1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "mediacas_hidl_hal_test"
18
19 #include <VtsHalHidlTargetTestBase.h>
20 #include <VtsHalHidlTargetTestEnvBase.h>
21 #include <android-base/logging.h>
22 #include <android/hardware/cas/1.0/IDescramblerBase.h>
23 #include <android/hardware/cas/1.0/types.h>
24 #include <android/hardware/cas/1.2/ICas.h>
25 #include <android/hardware/cas/1.2/ICasListener.h>
26 #include <android/hardware/cas/1.2/IMediaCasService.h>
27 #include <android/hardware/cas/1.2/types.h>
28 #include <android/hardware/cas/native/1.0/IDescrambler.h>
29 #include <android/hardware/cas/native/1.0/types.h>
30 #include <binder/MemoryDealer.h>
31 #include <hidl/HidlSupport.h>
32 #include <hidl/HidlTransportSupport.h>
33 #include <hidl/Status.h>
34 #include <hidlmemory/FrameworkUtils.h>
35 #include <utils/Condition.h>
36 #include <utils/Mutex.h>
37
38 #define CLEAR_KEY_SYSTEM_ID 0xF6D8
39 #define INVALID_SYSTEM_ID 0
40 #define WAIT_TIMEOUT 3000000000
41
42 #define PROVISION_STR \
43 "{ " \
44 " \"id\": 21140844, " \
45 " \"name\": \"Test Title\", " \
46 " \"lowercase_organization_name\": \"Android\", " \
47 " \"asset_key\": { " \
48 " \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\" " \
49 " }, " \
50 " \"cas_type\": 1, " \
51 " \"track_types\": [ ] " \
52 "} "
53
54 using android::Condition;
55 using android::IMemory;
56 using android::IMemoryHeap;
57 using android::MemoryDealer;
58 using android::Mutex;
59 using android::sp;
60 using android::hardware::fromHeap;
61 using android::hardware::hidl_string;
62 using android::hardware::hidl_vec;
63 using android::hardware::HidlMemory;
64 using android::hardware::Return;
65 using android::hardware::Void;
66 using android::hardware::cas::native::V1_0::BufferType;
67 using android::hardware::cas::native::V1_0::DestinationBuffer;
68 using android::hardware::cas::native::V1_0::IDescrambler;
69 using android::hardware::cas::native::V1_0::ScramblingControl;
70 using android::hardware::cas::native::V1_0::SharedBuffer;
71 using android::hardware::cas::native::V1_0::SubSample;
72 using android::hardware::cas::V1_0::HidlCasPluginDescriptor;
73 using android::hardware::cas::V1_0::IDescramblerBase;
74 using android::hardware::cas::V1_0::Status;
75 using android::hardware::cas::V1_2::ICas;
76 using android::hardware::cas::V1_2::ICasListener;
77 using android::hardware::cas::V1_2::IMediaCasService;
78 using android::hardware::cas::V1_2::ScramblingMode;
79 using android::hardware::cas::V1_2::SessionIntent;
80 using android::hardware::cas::V1_2::StatusEvent;
81
82 namespace {
83
84 const uint8_t kEcmBinaryBuffer[] = {
85 0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00,
86 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00,
87 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60, 0x4f,
88 0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
89 0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c,
90 0x62, 0x19, 0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48,
91 };
92
93 const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
94
95 const uint8_t kInBinaryBuffer[] = {
96 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
97 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
98 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
99 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
100 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
101 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
102 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
103 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
104 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
105 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
106 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x6e, 0x45, 0x21,
107 0x82, 0x38, 0xf0, 0x9d, 0x7d, 0x96, 0xe6, 0x94, 0xae, 0xe2, 0x87, 0x8f, 0x04, 0x49, 0xe5,
108 0xf6, 0x8c, 0x8b, 0x9a, 0x10, 0x18, 0xba, 0x94, 0xe9, 0x22, 0x31, 0x04, 0x7e, 0x60, 0x5b,
109 0xc4, 0x24, 0x00, 0x90, 0x62, 0x0d, 0xdc, 0x85, 0x74, 0x75, 0x78, 0xd0, 0x14, 0x08, 0xcb,
110 0x02, 0x1d, 0x7d, 0x9d, 0x34, 0xe8, 0x81, 0xb9, 0xf7, 0x09, 0x28, 0x79, 0x29, 0x8d, 0xe3,
111 0x14, 0xed, 0x5f, 0xca, 0xaf, 0xf4, 0x1c, 0x49, 0x15, 0xe1, 0x80, 0x29, 0x61, 0x76, 0x80,
112 0x43, 0xf8, 0x58, 0x53, 0x40, 0xd7, 0x31, 0x6d, 0x61, 0x81, 0x41, 0xe9, 0x77, 0x9f, 0x9c,
113 0xe1, 0x6d, 0xf2, 0xee, 0xd9, 0xc8, 0x67, 0xd2, 0x5f, 0x48, 0x73, 0xe3, 0x5c, 0xcd, 0xa7,
114 0x45, 0x58, 0xbb, 0xdd, 0x28, 0x1d, 0x68, 0xfc, 0xb4, 0xc6, 0xf6, 0x92, 0xf6, 0x30, 0x03,
115 0xaa, 0xe4, 0x32, 0xf6, 0x34, 0x51, 0x4b, 0x0f, 0x8c, 0xf9, 0xac, 0x98, 0x22, 0xfb, 0x49,
116 0xc8, 0xbf, 0xca, 0x8c, 0x80, 0x86, 0x5d, 0xd7, 0xa4, 0x52, 0xb1, 0xd9, 0xa6, 0x04, 0x4e,
117 0xb3, 0x2d, 0x1f, 0xb8, 0x35, 0xcc, 0x45, 0x6d, 0x9c, 0x20, 0xa7, 0xa4, 0x34, 0x59, 0x72,
118 0xe3, 0xae, 0xba, 0x49, 0xde, 0xd1, 0xaa, 0xee, 0x3d, 0x77, 0xfc, 0x5d, 0xc6, 0x1f, 0x9d,
119 0xac, 0xc2, 0x15, 0x66, 0xb8, 0xe1, 0x54, 0x4e, 0x74, 0x93, 0xdb, 0x9a, 0x24, 0x15, 0x6e,
120 0x20, 0xa3, 0x67, 0x3e, 0x5a, 0x24, 0x41, 0x5e, 0xb0, 0xe6, 0x35, 0x87, 0x1b, 0xc8, 0x7a,
121 0xf9, 0x77, 0x65, 0xe0, 0x01, 0xf2, 0x4c, 0xe4, 0x2b, 0xa9, 0x64, 0x96, 0x96, 0x0b, 0x46,
122 0xca, 0xea, 0x79, 0x0e, 0x78, 0xa3, 0x5f, 0x43, 0xfc, 0x47, 0x6a, 0x12, 0xfa, 0xc4, 0x33,
123 0x0e, 0x88, 0x1c, 0x19, 0x3a, 0x00, 0xc3, 0x4e, 0xb5, 0xd8, 0xfa, 0x8e, 0xf1, 0xbc, 0x3d,
124 0xb2, 0x7e, 0x50, 0x8d, 0x67, 0xc3, 0x6b, 0xed, 0xe2, 0xea, 0xa6, 0x1f, 0x25, 0x24, 0x7c,
125 0x94, 0x74, 0x50, 0x49, 0xe3, 0xc6, 0x58, 0x2e, 0xfd, 0x28, 0xb4, 0xc6, 0x73, 0xb1, 0x53,
126 0x74, 0x27, 0x94, 0x5c, 0xdf, 0x69, 0xb7, 0xa1, 0xd7, 0xf5, 0xd3, 0x8a, 0x2c, 0x2d, 0xb4,
127 0x5e, 0x8a, 0x16, 0x14, 0x54, 0x64, 0x6e, 0x00, 0x6b, 0x11, 0x59, 0x8a, 0x63, 0x38, 0x80,
128 0x76, 0xc3, 0xd5, 0x59, 0xf7, 0x3f, 0xd2, 0xfa, 0xa5, 0xca, 0x82, 0xff, 0x4a, 0x62, 0xf0,
129 0xe3, 0x42, 0xf9, 0x3b, 0x38, 0x27, 0x8a, 0x89, 0xaa, 0x50, 0x55, 0x4b, 0x29, 0xf1, 0x46,
130 0x7c, 0x75, 0xef, 0x65, 0xaf, 0x9b, 0x0d, 0x6d, 0xda, 0x25, 0x94, 0x14, 0xc1, 0x1b, 0xf0,
131 0xc5, 0x4c, 0x24, 0x0e, 0x65,
132 };
133
134 const uint8_t kOutRefBinaryBuffer[] = {
135 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
136 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
137 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
138 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
139 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
140 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
141 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
142 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
143 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
144 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
145 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
146 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
147 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
148 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
149 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
150 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
151 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
152 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
153 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
154 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
155 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
156 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
157 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
158 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
159 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
160 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
161 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
162 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
163 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
164 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
165 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
166 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
167 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
168 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
169 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
170 0x73, 0x63, 0x65, 0x6e, 0x65,
171 };
172
173 class MediaCasListener : public ICasListener {
174 public:
onEvent(int32_t event,int32_t arg,const hidl_vec<uint8_t> & data)175 virtual Return<void> onEvent(int32_t event, int32_t arg,
176 const hidl_vec<uint8_t>& data) override {
177 android::Mutex::Autolock autoLock(mMsgLock);
178 mEvent = event;
179 mEventArg = arg;
180 mEventData = data;
181
182 mEventReceived = true;
183 mMsgCondition.signal();
184 return Void();
185 }
186
onSessionEvent(const hidl_vec<uint8_t> & sessionId,int32_t event,int32_t arg,const hidl_vec<uint8_t> & data)187 virtual Return<void> onSessionEvent(const hidl_vec<uint8_t>& sessionId, int32_t event,
188 int32_t arg, const hidl_vec<uint8_t>& data) override {
189 android::Mutex::Autolock autoLock(mMsgLock);
190 mSessionId = sessionId;
191 mEvent = event;
192 mEventArg = arg;
193 mEventData = data;
194
195 mEventReceived = true;
196 mMsgCondition.signal();
197 return Void();
198 }
199
onStatusUpdate(StatusEvent event,int32_t arg)200 virtual Return<void> onStatusUpdate(StatusEvent event, int32_t arg) override {
201 android::Mutex::Autolock autoLock(mMsgLock);
202 mStatusEvent = event;
203 mEventArg = arg;
204
205 mEventReceived = true;
206 mMsgCondition.signal();
207 return Void();
208 }
209
210 void testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
211 hidl_vec<uint8_t>& eventData);
212
213 void testSessionEventEcho(sp<ICas>& mediaCas, const hidl_vec<uint8_t>& sessionId,
214 int32_t& event, int32_t& eventArg, hidl_vec<uint8_t>& eventData);
215
216 void testStatusUpdate(sp<ICas>& mediaCas, std::vector<uint8_t>* sessionId, SessionIntent intent,
217 ScramblingMode mode);
218
219 private:
220 int32_t mEvent = -1;
221 int32_t mEventArg = -1;
222 StatusEvent mStatusEvent;
223 bool mEventReceived = false;
224 hidl_vec<uint8_t> mEventData;
225 hidl_vec<uint8_t> mSessionId;
226 android::Mutex mMsgLock;
227 android::Condition mMsgCondition;
228 };
229
testEventEcho(sp<ICas> & mediaCas,int32_t & event,int32_t & eventArg,hidl_vec<uint8_t> & eventData)230 void MediaCasListener::testEventEcho(sp<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
231 hidl_vec<uint8_t>& eventData) {
232 mEventReceived = false;
233 auto returnStatus = mediaCas->sendEvent(event, eventArg, eventData);
234 EXPECT_TRUE(returnStatus.isOk());
235 EXPECT_EQ(Status::OK, returnStatus);
236
237 android::Mutex::Autolock autoLock(mMsgLock);
238 while (!mEventReceived) {
239 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
240 EXPECT_TRUE(false) << "event not received within timeout";
241 return;
242 }
243 }
244
245 EXPECT_EQ(mEvent, event);
246 EXPECT_EQ(mEventArg, eventArg);
247 EXPECT_TRUE(mEventData == eventData);
248 }
249
testSessionEventEcho(sp<ICas> & mediaCas,const hidl_vec<uint8_t> & sessionId,int32_t & event,int32_t & eventArg,hidl_vec<uint8_t> & eventData)250 void MediaCasListener::testSessionEventEcho(sp<ICas>& mediaCas, const hidl_vec<uint8_t>& sessionId,
251 int32_t& event, int32_t& eventArg,
252 hidl_vec<uint8_t>& eventData) {
253 mEventReceived = false;
254 auto returnStatus = mediaCas->sendSessionEvent(sessionId, event, eventArg, eventData);
255 EXPECT_TRUE(returnStatus.isOk());
256 EXPECT_EQ(Status::OK, returnStatus);
257
258 android::Mutex::Autolock autoLock(mMsgLock);
259 while (!mEventReceived) {
260 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
261 EXPECT_TRUE(false) << "event not received within timeout";
262 return;
263 }
264 }
265
266 EXPECT_TRUE(mSessionId == sessionId);
267 EXPECT_EQ(mEvent, event);
268 EXPECT_EQ(mEventArg, eventArg);
269 EXPECT_TRUE(mEventData == eventData);
270 }
271
testStatusUpdate(sp<ICas> & mediaCas,std::vector<uint8_t> * sessionId,SessionIntent intent,ScramblingMode mode)272 void MediaCasListener::testStatusUpdate(sp<ICas>& mediaCas, std::vector<uint8_t>* sessionId,
273 SessionIntent intent, ScramblingMode mode) {
274 mEventReceived = false;
275 android::hardware::cas::V1_2::Status sessionStatus;
276 auto returnVoid = mediaCas->openSession_1_2(
277 intent, mode,
278 [&](android::hardware::cas::V1_2::Status status, const hidl_vec<uint8_t>& id) {
279 sessionStatus = status;
280 *sessionId = id;
281 });
282 EXPECT_TRUE(returnVoid.isOk());
283 EXPECT_EQ(android::hardware::cas::V1_2::Status::OK, sessionStatus);
284
285 android::Mutex::Autolock autoLock(mMsgLock);
286 while (!mEventReceived) {
287 if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
288 EXPECT_TRUE(false) << "event not received within timeout";
289 return;
290 }
291 }
292 EXPECT_EQ(mStatusEvent, static_cast<StatusEvent>(intent));
293 EXPECT_EQ(mEventArg, static_cast<int32_t>(mode));
294 }
295
296 // Test environment for Cas HIDL HAL.
297 class CasHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
298 public:
299 // get the test environment singleton
Instance()300 static CasHidlEnvironment* Instance() {
301 static CasHidlEnvironment* instance = new CasHidlEnvironment;
302 return instance;
303 }
304
registerTestServices()305 virtual void registerTestServices() override { registerTestService<IMediaCasService>(); }
306 };
307
308 class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase {
309 public:
SetUp()310 virtual void SetUp() override {
311 mService = ::testing::VtsHalHidlTargetTestBase::getService<IMediaCasService>(
312 CasHidlEnvironment::Instance()->getServiceName<IMediaCasService>());
313 ASSERT_NE(mService, nullptr);
314 }
315
316 sp<IMediaCasService> mService;
317
318 protected:
description(const std::string & description)319 static void description(const std::string& description) {
320 RecordProperty("description", description);
321 }
322
323 sp<ICas> mMediaCas;
324 sp<IDescramblerBase> mDescramblerBase;
325 sp<MediaCasListener> mCasListener;
326 typedef struct _OobInputTestParams {
327 const SubSample* subSamples;
328 uint32_t numSubSamples;
329 size_t imemSizeActual;
330 uint64_t imemOffset;
331 uint64_t imemSize;
332 uint64_t srcOffset;
333 uint64_t dstOffset;
334 } OobInputTestParams;
335
336 ::testing::AssertionResult createCasPlugin(int32_t caSystemId);
337 ::testing::AssertionResult openCasSession(std::vector<uint8_t>* sessionId);
338 ::testing::AssertionResult openCasSession_1_2(std::vector<uint8_t>* sessionId,
339 SessionIntent intent, ScramblingMode mode);
340 ::testing::AssertionResult descrambleTestInputBuffer(const sp<IDescrambler>& descrambler,
341 Status* descrambleStatus,
342 sp<IMemory>* hidlInMemory);
343 ::testing::AssertionResult descrambleTestOobInput(const sp<IDescrambler>& descrambler,
344 Status* descrambleStatus,
345 const OobInputTestParams& params);
346 };
347
createCasPlugin(int32_t caSystemId)348 ::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) {
349 auto status = mService->isSystemIdSupported(caSystemId);
350 if (!status.isOk() || !status) {
351 return ::testing::AssertionFailure();
352 }
353 status = mService->isDescramblerSupported(caSystemId);
354 if (!status.isOk() || !status) {
355 return ::testing::AssertionFailure();
356 }
357
358 mCasListener = new MediaCasListener();
359 auto pluginStatus = mService->createPluginExt(caSystemId, mCasListener);
360 if (!pluginStatus.isOk()) {
361 return ::testing::AssertionFailure();
362 }
363 mMediaCas = ICas::castFrom(pluginStatus);
364 if (mMediaCas == nullptr) {
365 return ::testing::AssertionFailure();
366 }
367
368 auto descramblerStatus = mService->createDescrambler(caSystemId);
369 if (!descramblerStatus.isOk()) {
370 return ::testing::AssertionFailure();
371 }
372 mDescramblerBase = descramblerStatus;
373 return ::testing::AssertionResult(mDescramblerBase != nullptr);
374 }
375
openCasSession(std::vector<uint8_t> * sessionId)376 ::testing::AssertionResult MediaCasHidlTest::openCasSession(std::vector<uint8_t>* sessionId) {
377 Status sessionStatus;
378 auto returnVoid = mMediaCas->openSession([&](Status status, const hidl_vec<uint8_t>& id) {
379 sessionStatus = status;
380 *sessionId = id;
381 });
382 return ::testing::AssertionResult(returnVoid.isOk() && (Status::OK == sessionStatus));
383 }
384
descrambleTestInputBuffer(const sp<IDescrambler> & descrambler,Status * descrambleStatus,sp<IMemory> * inMemory)385 ::testing::AssertionResult MediaCasHidlTest::descrambleTestInputBuffer(
386 const sp<IDescrambler>& descrambler, Status* descrambleStatus, sp<IMemory>* inMemory) {
387 hidl_vec<SubSample> hidlSubSamples;
388 hidlSubSamples.setToExternal(const_cast<SubSample*>(kSubSamples),
389 (sizeof(kSubSamples) / sizeof(SubSample)), false /*own*/);
390
391 sp<MemoryDealer> dealer = new MemoryDealer(sizeof(kInBinaryBuffer), "vts-cas");
392 if (nullptr == dealer.get()) {
393 ALOGE("couldn't get MemoryDealer!");
394 return ::testing::AssertionFailure();
395 }
396
397 sp<IMemory> mem = dealer->allocate(sizeof(kInBinaryBuffer));
398 if (nullptr == mem.get()) {
399 ALOGE("couldn't allocate IMemory!");
400 return ::testing::AssertionFailure();
401 }
402 *inMemory = mem;
403
404 // build HidlMemory from memory heap
405 ssize_t offset;
406 size_t size;
407 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
408 if (nullptr == heap.get()) {
409 ALOGE("couldn't get memory heap!");
410 return ::testing::AssertionFailure();
411 }
412
413 uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->unsecurePointer()));
414 memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
415
416 // hidlMemory is not to be passed out of scope!
417 sp<HidlMemory> hidlMemory = fromHeap(heap);
418
419 SharedBuffer srcBuffer = {
420 .heapBase = *hidlMemory, .offset = (uint64_t)offset, .size = (uint64_t)size};
421
422 DestinationBuffer dstBuffer;
423 dstBuffer.type = BufferType::SHARED_MEMORY;
424 dstBuffer.nonsecureMemory = srcBuffer;
425
426 uint32_t outBytes;
427 hidl_string detailedError;
428 auto returnVoid = descrambler->descramble(
429 ScramblingControl::EVENKEY /*2*/, hidlSubSamples, srcBuffer, 0, dstBuffer, 0,
430 [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
431 *descrambleStatus = status;
432 outBytes = bytesWritten;
433 detailedError = detailedErr;
434 });
435 if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
436 ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
437 returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
438 }
439 return ::testing::AssertionResult(returnVoid.isOk());
440 }
441
descrambleTestOobInput(const sp<IDescrambler> & descrambler,Status * descrambleStatus,const OobInputTestParams & params)442 ::testing::AssertionResult MediaCasHidlTest::descrambleTestOobInput(
443 const sp<IDescrambler>& descrambler, Status* descrambleStatus,
444 const OobInputTestParams& params) {
445 hidl_vec<SubSample> hidlSubSamples;
446 hidlSubSamples.setToExternal(const_cast<SubSample*>(params.subSamples), params.numSubSamples,
447 false /*own*/);
448
449 sp<MemoryDealer> dealer = new MemoryDealer(params.imemSizeActual, "vts-cas");
450 if (nullptr == dealer.get()) {
451 ALOGE("couldn't get MemoryDealer!");
452 return ::testing::AssertionFailure();
453 }
454
455 sp<IMemory> mem = dealer->allocate(params.imemSizeActual);
456 if (nullptr == mem.get()) {
457 ALOGE("couldn't allocate IMemory!");
458 return ::testing::AssertionFailure();
459 }
460
461 // build HidlMemory from memory heap
462 ssize_t offset;
463 size_t size;
464 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
465 if (nullptr == heap.get()) {
466 ALOGE("couldn't get memory heap!");
467 return ::testing::AssertionFailure();
468 }
469
470 // hidlMemory is not to be passed out of scope!
471 sp<HidlMemory> hidlMemory = fromHeap(heap);
472
473 SharedBuffer srcBuffer = {
474 .heapBase = *hidlMemory,
475 .offset = (uint64_t)offset + params.imemOffset,
476 .size = (uint64_t)params.imemSize,
477 };
478
479 DestinationBuffer dstBuffer;
480 dstBuffer.type = BufferType::SHARED_MEMORY;
481 dstBuffer.nonsecureMemory = srcBuffer;
482
483 uint32_t outBytes;
484 hidl_string detailedError;
485 auto returnVoid = descrambler->descramble(
486 ScramblingControl::EVENKEY /*2*/, hidlSubSamples, srcBuffer, params.srcOffset,
487 dstBuffer, params.dstOffset,
488 [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
489 *descrambleStatus = status;
490 outBytes = bytesWritten;
491 detailedError = detailedErr;
492 });
493 if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
494 ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
495 returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
496 }
497 return ::testing::AssertionResult(returnVoid.isOk());
498 }
499
TEST_F(MediaCasHidlTest,TestClearKeyApisWithSession)500 TEST_F(MediaCasHidlTest, TestClearKeyApisWithSession) {
501 description("Test that valid call sequences with SessionEvent send and receive");
502
503 ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
504
505 auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
506 EXPECT_TRUE(returnStatus.isOk());
507 EXPECT_EQ(Status::OK, returnStatus);
508
509 hidl_vec<uint8_t> hidlPvtData;
510 hidlPvtData.resize(256);
511 returnStatus = mMediaCas->setPrivateData(hidlPvtData);
512 EXPECT_TRUE(returnStatus.isOk());
513 EXPECT_EQ(Status::OK, returnStatus);
514
515 std::vector<uint8_t> sessionId;
516 ASSERT_TRUE(openCasSession(&sessionId));
517 returnStatus = mMediaCas->setSessionPrivateData(sessionId, hidlPvtData);
518 EXPECT_TRUE(returnStatus.isOk());
519 EXPECT_EQ(Status::OK, returnStatus);
520
521 std::vector<uint8_t> streamSessionId;
522 ASSERT_TRUE(openCasSession(&streamSessionId));
523 returnStatus = mMediaCas->setSessionPrivateData(streamSessionId, hidlPvtData);
524 EXPECT_TRUE(returnStatus.isOk());
525 EXPECT_EQ(Status::OK, returnStatus);
526
527 returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
528 EXPECT_TRUE(returnStatus.isOk());
529 EXPECT_EQ(Status::OK, returnStatus);
530
531 returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
532 EXPECT_TRUE(returnStatus.isOk());
533 EXPECT_EQ(Status::OK, returnStatus);
534
535 hidl_vec<uint8_t> hidlNullPtr;
536 hidlNullPtr.setToExternal(static_cast<uint8_t*>(nullptr), 0);
537 returnStatus = mMediaCas->refreshEntitlements(3, hidlNullPtr);
538 EXPECT_TRUE(returnStatus.isOk());
539 EXPECT_EQ(Status::OK, returnStatus);
540
541 uint8_t refreshData[] = {0, 1, 2, 3};
542 hidl_vec<uint8_t> hidlRefreshData;
543 hidlRefreshData.setToExternal(static_cast<uint8_t*>(refreshData), sizeof(refreshData));
544 returnStatus = mMediaCas->refreshEntitlements(10, hidlRefreshData);
545 EXPECT_TRUE(returnStatus.isOk());
546 EXPECT_EQ(Status::OK, returnStatus);
547
548 int32_t eventID = 1;
549 int32_t eventArg = 2;
550 mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlNullPtr);
551 mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, hidlNullPtr);
552
553 eventID = 3;
554 eventArg = 4;
555 uint8_t eventData[] = {'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
556 hidl_vec<uint8_t> hidlEventData;
557 hidlEventData.setToExternal(static_cast<uint8_t*>(eventData), sizeof(eventData));
558 mCasListener->testEventEcho(mMediaCas, eventID, eventArg, hidlEventData);
559 mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, hidlEventData);
560
561 SessionIntent intent = SessionIntent::LIVE;
562 ScramblingMode mode = ScramblingMode::DVB_CSA1;
563 mCasListener->testStatusUpdate(mMediaCas, &sessionId, intent, mode);
564
565 uint8_t clearKeyEmmData[] = {'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
566 hidl_vec<uint8_t> hidlClearKeyEmm;
567 hidlClearKeyEmm.setToExternal(static_cast<uint8_t*>(clearKeyEmmData), sizeof(clearKeyEmmData));
568 returnStatus = mMediaCas->processEmm(hidlClearKeyEmm);
569 EXPECT_TRUE(returnStatus.isOk());
570 EXPECT_EQ(Status::OK, returnStatus);
571
572 hidl_vec<uint8_t> hidlEcm;
573 hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
574 returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
575 EXPECT_TRUE(returnStatus.isOk());
576 EXPECT_EQ(Status::OK, returnStatus);
577 returnStatus = mMediaCas->processEcm(streamSessionId, hidlEcm);
578 EXPECT_TRUE(returnStatus.isOk());
579 EXPECT_EQ(Status::OK, returnStatus);
580
581 EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("video/avc"));
582
583 sp<IDescrambler> descrambler;
584 descrambler = IDescrambler::castFrom(mDescramblerBase);
585 ASSERT_NE(descrambler, nullptr);
586
587 Status descrambleStatus = Status::OK;
588 sp<IMemory> dataMemory;
589
590 ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
591 EXPECT_EQ(Status::OK, descrambleStatus);
592
593 ASSERT_NE(nullptr, dataMemory.get());
594 uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
595
596 int compareResult =
597 memcmp(static_cast<const void*>(opBuffer),
598 static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
599 EXPECT_EQ(0, compareResult);
600
601 returnStatus = mDescramblerBase->release();
602 EXPECT_TRUE(returnStatus.isOk());
603 EXPECT_EQ(Status::OK, returnStatus);
604
605 returnStatus = mMediaCas->release();
606 EXPECT_TRUE(returnStatus.isOk());
607 EXPECT_EQ(Status::OK, returnStatus);
608 }
609
610 } // anonymous namespace
611
main(int argc,char ** argv)612 int main(int argc, char** argv) {
613 ::testing::AddGlobalTestEnvironment(CasHidlEnvironment::Instance());
614 ::testing::InitGoogleTest(&argc, argv);
615 CasHidlEnvironment::Instance()->init(&argc, argv);
616 int status = RUN_ALL_TESTS();
617 LOG(INFO) << "Test result = " << status;
618 return status;
619 }
620