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