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 51using android::Condition; 52using android::hardware::cas::V1_0::ICas; 53using android::hardware::cas::V1_0::ICasListener; 54using android::hardware::cas::V1_0::IDescramblerBase; 55using 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; 61using android::hardware::cas::V1_0::IMediaCasService; 62using android::hardware::cas::V1_0::HidlCasPluginDescriptor; 63using android::hardware::Void; 64using android::hardware::hidl_vec; 65using android::hardware::hidl_string; 66using android::hardware::hidl_handle; 67using android::hardware::hidl_memory; 68using android::hardware::Return; 69using android::hardware::cas::V1_0::Status; 70using android::IMemory; 71using android::IMemoryHeap; 72using android::MemoryDealer; 73using android::Mutex; 74using android::sp; 75 76namespace { 77 78const 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 209class 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 } 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 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 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( 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 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; 351 352 ASSERT_TRUE(createCasPlugin(caSystemId)); 353 } 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 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 374TEST_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 396TEST_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 500TEST_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 527TEST_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 618int 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