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