blob: 4a6ccd76459e697068318dacc2cb97b4a9f3a502 [file] [log] [blame]
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +05301/*
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>
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053025#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>
Chong Zhang704d5862017-10-10 13:03:18 -070028#include <binder/MemoryDealer.h>
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +053029#include <hidl/HidlSupport.h>
30#include <hidl/HidlTransportSupport.h>
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053031#include <hidl/Status.h>
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053032#include <utils/Condition.h>
33#include <utils/Mutex.h>
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +053034
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +053035#define CLEAR_KEY_SYSTEM_ID 0xF6D8
36#define INVALID_SYSTEM_ID 0
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053037#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 "} "
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +053050
51using android::Condition;
52using android::hardware::cas::V1_0::ICas;
53using android::hardware::cas::V1_0::ICasListener;
54using android::hardware::cas::V1_0::IDescramblerBase;
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053055using android::hardware::cas::native::V1_0::IDescrambler;
56using android::hardware::cas::native::V1_0::SubSample;
57using android::hardware::cas::native::V1_0::SharedBuffer;
58using android::hardware::cas::native::V1_0::DestinationBuffer;
59using android::hardware::cas::native::V1_0::BufferType;
60using android::hardware::cas::native::V1_0::ScramblingControl;
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +053061using android::hardware::cas::V1_0::IMediaCasService;
62using android::hardware::cas::V1_0::HidlCasPluginDescriptor;
63using android::hardware::Void;
64using android::hardware::hidl_vec;
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053065using android::hardware::hidl_string;
66using android::hardware::hidl_handle;
67using android::hardware::hidl_memory;
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +053068using android::hardware::Return;
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053069using android::hardware::cas::V1_0::Status;
Chong Zhang704d5862017-10-10 13:03:18 -070070using android::IMemory;
71using android::IMemoryHeap;
72using android::MemoryDealer;
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +053073using android::Mutex;
74using android::sp;
75
76namespace {
77
Suresh Sivaraman0645aec2017-09-21 18:44:24 +053078const 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
87const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
88
89const 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
126const 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
163class MediaCasListener : public ICasListener {
164 public:
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
189void 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
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530209class MediaCasHidlTest : public ::testing::VtsHalHidlTargetTestBase {
210 public:
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:
219 static void description(const std::string& description) {
220 RecordProperty("description", description);
221 }
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530222
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,
Chong Zhang704d5862017-10-10 13:03:18 -0700231 sp<IMemory>* hidlInMemory);
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530232};
233
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530234::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) {
235 auto status = mService->isSystemIdSupported(caSystemId);
236 if (!status.isOk() || !status) {
237 return ::testing::AssertionFailure();
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530238 }
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530239 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
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
271::testing::AssertionResult MediaCasHidlTest::descrambleTestInputBuffer(
Chong Zhang704d5862017-10-10 13:03:18 -0700272 const sp<IDescrambler>& descrambler, Status* descrambleStatus, sp<IMemory>* inMemory) {
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530273 hidl_vec<SubSample> hidlSubSamples;
274 hidlSubSamples.setToExternal(const_cast<SubSample*>(kSubSamples),
275 (sizeof(kSubSamples) / sizeof(SubSample)), false /*own*/);
Chong Zhang704d5862017-10-10 13:03:18 -0700276
277 sp<MemoryDealer> dealer = new MemoryDealer(sizeof(kInBinaryBuffer), "vts-cas");
278 if (nullptr == dealer.get()) {
279 ALOGE("couldn't get MemoryDealer!");
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530280 return ::testing::AssertionFailure();
281 }
282
Chong Zhang704d5862017-10-10 13:03:18 -0700283 sp<IMemory> mem = dealer->allocate(sizeof(kInBinaryBuffer));
284 if (nullptr == mem.get()) {
285 ALOGE("couldn't allocate IMemory!");
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530286 return ::testing::AssertionFailure();
287 }
Chong Zhang704d5862017-10-10 13:03:18 -0700288 *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!");
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530296 return ::testing::AssertionFailure();
297 }
298
Chong Zhang704d5862017-10-10 13:03:18 -0700299 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()));
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530307 memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
308
309 SharedBuffer srcBuffer = {
Chong Zhang704d5862017-10-10 13:03:18 -0700310 .heapBase = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize()),
311 .offset = (uint64_t) offset,
312 .size = (uint64_t) size
313 };
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530314
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}
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530334
335TEST_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;
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530351
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530352 ASSERT_TRUE(createCasPlugin(caSystemId));
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530353 }
354}
355
356TEST_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
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530363 auto pluginStatus = mService->createPlugin(INVALID_SYSTEM_ID, casListener);
364 ASSERT_TRUE(pluginStatus.isOk());
365 sp<ICas> mediaCas = pluginStatus;
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530366 EXPECT_EQ(mediaCas, nullptr);
367
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530368 auto descramblerStatus = mService->createDescrambler(INVALID_SYSTEM_ID);
369 ASSERT_TRUE(descramblerStatus.isOk());
370 sp<IDescramblerBase> descramblerBase = descramblerStatus;
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530371 EXPECT_EQ(descramblerBase, nullptr);
372}
373
374TEST_F(MediaCasHidlTest, TestClearKeyPluginInstalled) {
375 description("Test if ClearKey plugin is installed");
376 hidl_vec<HidlCasPluginDescriptor> descriptors;
377 EXPECT_TRUE(mService
378 ->enumeratePlugins([&descriptors](
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530379 hidl_vec<HidlCasPluginDescriptor> const& desc) { descriptors = desc; })
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530380 .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
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530396TEST_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 sp<IDescrambler> descrambler;
472 descrambler = IDescrambler::castFrom(mDescramblerBase);
473 ASSERT_NE(descrambler, nullptr);
474
475 Status descrambleStatus = Status::OK;
Chong Zhang704d5862017-10-10 13:03:18 -0700476 sp<IMemory> dataMemory;
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530477
Chong Zhang704d5862017-10-10 13:03:18 -0700478 ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530479 EXPECT_EQ(Status::OK, descrambleStatus);
480
Chong Zhang704d5862017-10-10 13:03:18 -0700481 ASSERT_NE(nullptr, dataMemory.get());
482 uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->pointer()));
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530483
484 int compareResult =
485 memcmp(static_cast<const void*>(opBuffer), static_cast<const void*>(kOutRefBinaryBuffer),
486 sizeof(kOutRefBinaryBuffer));
487 EXPECT_EQ(0, compareResult);
488}
489
490TEST_F(MediaCasHidlTest, TestClearKeySessionClosedAfterRelease) {
491 description("Test that all sessions are closed after a MediaCas object is released");
492
493 ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
494
495 auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
496 EXPECT_TRUE(returnStatus.isOk());
497 EXPECT_EQ(Status::OK, returnStatus);
498
499 std::vector<uint8_t> sessionId;
500 ASSERT_TRUE(openCasSession(&sessionId));
501 std::vector<uint8_t> streamSessionId;
502 ASSERT_TRUE(openCasSession(&streamSessionId));
503
504 returnStatus = mMediaCas->release();
505 EXPECT_TRUE(returnStatus.isOk());
506 EXPECT_EQ(Status::OK, returnStatus);
507
508 returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
509 EXPECT_TRUE(returnStatus.isOk());
510 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
511
512 returnStatus = mDescramblerBase->setMediaCasSession(streamSessionId);
513 EXPECT_TRUE(returnStatus.isOk());
514 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
515}
516
517TEST_F(MediaCasHidlTest, TestClearKeyErrors) {
518 description("Test that invalid call sequences fail with expected error codes");
519
520 ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
521
522 /*
523 * Test MediaCas error codes
524 */
525 // Provision should fail with an invalid asset string
526 auto returnStatus = mMediaCas->provision(hidl_string("invalid asset string"));
527 EXPECT_TRUE(returnStatus.isOk());
528 EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus);
529
530 // Open a session, then close it so that it should become invalid
531 std::vector<uint8_t> invalidSessionId;
532 ASSERT_TRUE(openCasSession(&invalidSessionId));
533 returnStatus = mMediaCas->closeSession(invalidSessionId);
534 EXPECT_TRUE(returnStatus.isOk());
535 EXPECT_EQ(Status::OK, returnStatus);
536
537 // processEcm should fail with an invalid session id
538 hidl_vec<uint8_t> hidlEcm;
539 hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
540 returnStatus = mMediaCas->processEcm(invalidSessionId, hidlEcm);
541 EXPECT_TRUE(returnStatus.isOk());
542 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
543
544 std::vector<uint8_t> sessionId;
545 ASSERT_TRUE(openCasSession(&sessionId));
546
547 // processEcm should fail without provisioning
548 hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
549 returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
550 EXPECT_TRUE(returnStatus.isOk());
551 EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus);
552
553 returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
554 EXPECT_TRUE(returnStatus.isOk());
555 EXPECT_EQ(Status::OK, returnStatus);
556
557 // processEcm should fail with ecm buffer that's too short
558 hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), 8);
559 returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
560 EXPECT_TRUE(returnStatus.isOk());
561 EXPECT_EQ(Status::BAD_VALUE, returnStatus);
562
563 // processEcm should fail with ecm with bad descriptor count
564 uint8_t badDescriptor[sizeof(kEcmBinaryBuffer)];
565 memcpy(badDescriptor, kEcmBinaryBuffer, sizeof(kEcmBinaryBuffer));
566 badDescriptor[17] = 0x03; // change the descriptor count field to 3 (invalid)
567 hidlEcm.setToExternal(static_cast<uint8_t*>(badDescriptor), sizeof(badDescriptor));
568 returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
569 EXPECT_TRUE(returnStatus.isOk());
570 EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus);
571
572 /*
573 * Test MediaDescrambler error codes
574 */
575 // setMediaCasSession should fail with an invalid session id
576 returnStatus = mDescramblerBase->setMediaCasSession(invalidSessionId);
577 EXPECT_TRUE(returnStatus.isOk());
578 EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus);
579
580 // descramble should fail without a valid session
581 sp<IDescrambler> descrambler;
582 descrambler = IDescrambler::castFrom(mDescramblerBase);
583 ASSERT_NE(descrambler, nullptr);
584
585 Status descrambleStatus = Status::OK;
Chong Zhang704d5862017-10-10 13:03:18 -0700586 sp<IMemory> dataMemory;
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530587
Chong Zhang704d5862017-10-10 13:03:18 -0700588 ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530589 EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED, descrambleStatus);
590
591 // Now set a valid session, should still fail because no valid ecm is processed
592 returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
593 EXPECT_TRUE(returnStatus.isOk());
594 EXPECT_EQ(Status::OK, returnStatus);
595
Chong Zhang704d5862017-10-10 13:03:18 -0700596 ASSERT_TRUE(descrambleTestInputBuffer(descrambler, &descrambleStatus, &dataMemory));
Suresh Sivaraman0645aec2017-09-21 18:44:24 +0530597 EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus);
598}
599
Suresh Sivaramanf1fbb442017-09-15 11:51:15 +0530600} // anonymous namespace
601
602int main(int argc, char** argv) {
603 ::testing::InitGoogleTest(&argc, argv);
604 int status = RUN_ALL_TESTS();
605 LOG(INFO) << "Test result = " << status;
606 return status;
607}