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 27 android::CasFactory* createCasFactory() { 28 return new android::MockCasFactory(); 29 } 30 31 android::DescramblerFactory* createDescramblerFactory() { 32 return new android::MockDescramblerFactory(); 33 } 34 35 namespace android { 36 37 static const int32_t sMockId = 0xFFFF; 38 39 bool MockCasFactory::isSystemIdSupported(int32_t CA_system_id) const { 40 return CA_system_id == sMockId; 41 } 42 43 status_t MockCasFactory::queryPlugins( 44 std::vector<CasPluginDescriptor> *descriptors) const { 45 descriptors->clear(); 46 descriptors->push_back({sMockId, String8("MockCAS")}); 47 return OK; 48 } 49 50 status_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 65 bool MockDescramblerFactory::isSystemIdSupported(int32_t CA_system_id) const { 66 return CA_system_id == sMockId; 67 } 68 69 status_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 81 static 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 92 MockCasPlugin::MockCasPlugin() { 93 ALOGV("CTOR"); 94 } 95 96 MockCasPlugin::~MockCasPlugin() { 97 ALOGV("DTOR"); 98 MockSessionLibrary::get()->destroyPlugin(this); 99 } 100 101 status_t MockCasPlugin::setPrivateData(const CasData &data) { 102 ALOGV("setPrivateData"); 103 return OK; 104 } 105 106 status_t MockCasPlugin::openSession(CasSessionId* sessionId) { 107 ALOGV("openSession"); 108 return MockSessionLibrary::get()->addSession(this, sessionId); 109 } 110 111 status_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 125 status_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 139 status_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 155 status_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 165 status_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 173 status_t MockCasPlugin::provision(const String8 &str) { 174 ALOGV("provision: provisionString=%s", str.string()); 175 Mutex::Autolock lock(mLock); 176 177 return OK; 178 } 179 180 status_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 ///////////////////////////////////////////////////////////////// 189 bool MockDescramblerPlugin::requiresSecureDecoderComponent( 190 const char *mime) const { 191 ALOGV("MockDescramblerPlugin::requiresSecureDecoderComponent" 192 "(mime=%s)", mime); 193 return false; 194 } 195 196 status_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 210 ssize_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 230 String8 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 241 String8 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