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_NDEBUG 0 18#define LOG_TAG "MockCasPlugin" 19 20#include <media/stagefright/foundation/hexdump.h> 21#include <media/stagefright/MediaErrors.h> 22#include <utils/Log.h> 23 24#include "MockCasPlugin.h" 25#include "MockSessionLibrary.h" 26 27android::CasFactory* createCasFactory() { 28 return new android::MockCasFactory(); 29} 30 31android::DescramblerFactory* createDescramblerFactory() { 32 return new android::MockDescramblerFactory(); 33} 34 35namespace android { 36 37static const int32_t sMockId = 0xFFFF; 38 39bool MockCasFactory::isSystemIdSupported(int32_t CA_system_id) const { 40 return CA_system_id == sMockId; 41} 42 43status_t MockCasFactory::queryPlugins( 44 std::vector<CasPluginDescriptor> *descriptors) const { 45 descriptors->clear(); 46 descriptors->push_back({sMockId, String8("MockCAS")}); 47 return OK; 48} 49 50status_t MockCasFactory::createPlugin( 51 int32_t CA_system_id, 52 uint64_t appData, 53 CasPluginCallback callback, 54 CasPlugin **plugin) { 55 if (!isSystemIdSupported(CA_system_id)) { 56 return BAD_VALUE; 57 } 58 59 *plugin = new MockCasPlugin(); 60 return OK; 61} 62 63/////////////////////////////////////////////////////////////////////////////// 64 65bool MockDescramblerFactory::isSystemIdSupported(int32_t CA_system_id) const { 66 return CA_system_id == sMockId; 67} 68 69status_t MockDescramblerFactory::createPlugin( 70 int32_t CA_system_id, DescramblerPlugin** plugin) { 71 if (!isSystemIdSupported(CA_system_id)) { 72 return BAD_VALUE; 73 } 74 75 *plugin = new MockDescramblerPlugin(); 76 return OK; 77} 78 79/////////////////////////////////////////////////////////////////////////////// 80 81static String8 arrayToString(const std::vector<uint8_t> &array) { 82 String8 result; 83 for (size_t i = 0; i < array.size(); i++) { 84 result.appendFormat("%02x ", array[i]); 85 } 86 if (result.isEmpty()) { 87 result.append("(null)"); 88 } 89 return result; 90} 91 92MockCasPlugin::MockCasPlugin() { 93 ALOGV("CTOR"); 94} 95 96MockCasPlugin::~MockCasPlugin() { 97 ALOGV("DTOR"); 98 MockSessionLibrary::get()->destroyPlugin(this); 99} 100 101status_t MockCasPlugin::setPrivateData(const CasData &data) { 102 ALOGV("setPrivateData"); 103 return OK; 104} 105 106status_t MockCasPlugin::openSession(CasSessionId* sessionId) { 107 ALOGV("openSession"); 108 return MockSessionLibrary::get()->addSession(this, sessionId); 109} 110 111status_t MockCasPlugin::closeSession(const CasSessionId &sessionId) { 112 ALOGV("closeSession: sessionId=%s", arrayToString(sessionId).string()); 113 Mutex::Autolock lock(mLock); 114 115 sp<MockCasSession> session = 116 MockSessionLibrary::get()->findSession(sessionId); 117 if (session == NULL) { 118 return BAD_VALUE; 119 } 120 121 MockSessionLibrary::get()->destroySession(sessionId); 122 return OK; 123} 124 125status_t MockCasPlugin::setSessionPrivateData( 126 const CasSessionId &sessionId, const CasData &data) { 127 ALOGV("setSessionPrivateData: sessionId=%s", 128 arrayToString(sessionId).string()); 129 Mutex::Autolock lock(mLock); 130 131 sp<MockCasSession> session = 132 MockSessionLibrary::get()->findSession(sessionId); 133 if (session == NULL) { 134 return BAD_VALUE; 135 } 136 return OK; 137} 138 139status_t MockCasPlugin::processEcm( 140 const CasSessionId &sessionId, const CasEcm& ecm) { 141 ALOGV("processEcm: sessionId=%s", arrayToString(sessionId).string()); 142 Mutex::Autolock lock(mLock); 143 144 sp<MockCasSession> session = 145 MockSessionLibrary::get()->findSession(sessionId); 146 if (session == NULL) { 147 return BAD_VALUE; 148 } 149 ALOGV("ECM: size=%d", ecm.size()); 150 ALOGV("ECM: data=%s", arrayToString(ecm).string()); 151 152 return OK; 153} 154 155status_t MockCasPlugin::processEmm(const CasEmm& emm) { 156 ALOGV("processEmm"); 157 Mutex::Autolock lock(mLock); 158 159 ALOGV("EMM: size=%d", emm.size()); 160 ALOGV("EMM: data=%s", arrayToString(emm).string()); 161 162 return OK; 163} 164 165status_t MockCasPlugin::sendEvent( 166 int32_t event, int arg, const CasData &eventData) { 167 ALOGV("sendEvent: event=%d", event); 168 Mutex::Autolock lock(mLock); 169 170 return OK; 171} 172 173status_t MockCasPlugin::provision(const String8 &str) { 174 ALOGV("provision: provisionString=%s", str.string()); 175 Mutex::Autolock lock(mLock); 176 177 return OK; 178} 179 180status_t MockCasPlugin::refreshEntitlements( 181 int32_t refreshType, const CasData &refreshData) { 182 ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).string()); 183 Mutex::Autolock lock(mLock); 184 185 return OK; 186} 187 188///////////////////////////////////////////////////////////////// 189bool MockDescramblerPlugin::requiresSecureDecoderComponent( 190 const char *mime) const { 191 ALOGV("MockDescramblerPlugin::requiresSecureDecoderComponent" 192 "(mime=%s)", mime); 193 return false; 194} 195 196status_t MockDescramblerPlugin::setMediaCasSession( 197 const CasSessionId &sessionId) { 198 ALOGV("MockDescramblerPlugin::setMediaCasSession"); 199 sp<MockCasSession> session = 200 MockSessionLibrary::get()->findSession(sessionId); 201 202 if (session == NULL) { 203 ALOGE("MockDescramblerPlugin: session not found"); 204 return ERROR_DRM_SESSION_NOT_OPENED; 205 } 206 207 return OK; 208} 209 210ssize_t MockDescramblerPlugin::descramble( 211 bool secure, 212 ScramblingControl scramblingControl, 213 size_t numSubSamples, 214 const SubSample *subSamples, 215 const void *srcPtr, 216 int32_t srcOffset, 217 void *dstPtr, 218 int32_t dstOffset, 219 AString *errorDetailMsg) { 220 ALOGV("MockDescramblerPlugin::descramble(secure=%d, sctrl=%d," 221 "subSamples=%s, srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d)", 222 (int)secure, (int)scramblingControl, 223 subSamplesToString(subSamples, numSubSamples).string(), 224 srcPtr, dstPtr, srcOffset, dstOffset); 225 226 return 0; 227} 228 229// Conversion utilities 230String8 MockDescramblerPlugin::arrayToString( 231 uint8_t const *array, size_t len) const 232{ 233 String8 result("{ "); 234 for (size_t i = 0; i < len; i++) { 235 result.appendFormat("0x%02x ", array[i]); 236 } 237 result += "}"; 238 return result; 239} 240 241String8 MockDescramblerPlugin::subSamplesToString( 242 SubSample const *subSamples, size_t numSubSamples) const 243{ 244 String8 result; 245 for (size_t i = 0; i < numSubSamples; i++) { 246 result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i, 247 subSamples[i].mNumBytesOfClearData, 248 subSamples[i].mNumBytesOfEncryptedData); 249 } 250 return result; 251} 252 253} // namespace android 254 255