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