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