Home | History | Annotate | Download | only in mock
      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         void* /*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 status_t MockCasFactory::createPlugin(
     64         int32_t CA_system_id,
     65         void* /*appData*/,
     66         CasPluginCallbackExt /*callback*/,
     67         CasPlugin **plugin) {
     68     if (!isSystemIdSupported(CA_system_id)) {
     69         return BAD_VALUE;
     70     }
     71 
     72     *plugin = new MockCasPlugin();
     73     return OK;
     74 }
     75 
     76 ///////////////////////////////////////////////////////////////////////////////
     77 
     78 bool MockDescramblerFactory::isSystemIdSupported(int32_t CA_system_id) const {
     79     return CA_system_id == sMockId;
     80 }
     81 
     82 status_t MockDescramblerFactory::createPlugin(
     83         int32_t CA_system_id, DescramblerPlugin** plugin) {
     84     if (!isSystemIdSupported(CA_system_id)) {
     85         return BAD_VALUE;
     86     }
     87 
     88     *plugin = new MockDescramblerPlugin();
     89     return OK;
     90 }
     91 
     92 ///////////////////////////////////////////////////////////////////////////////
     93 
     94 static String8 arrayToString(const std::vector<uint8_t> &array) {
     95     String8 result;
     96     for (size_t i = 0; i < array.size(); i++) {
     97         result.appendFormat("%02x ", array[i]);
     98     }
     99     if (result.isEmpty()) {
    100         result.append("(null)");
    101     }
    102     return result;
    103 }
    104 
    105 MockCasPlugin::MockCasPlugin() {
    106     ALOGV("CTOR");
    107 }
    108 
    109 MockCasPlugin::~MockCasPlugin() {
    110     ALOGV("DTOR");
    111     MockSessionLibrary::get()->destroyPlugin(this);
    112 }
    113 
    114 status_t MockCasPlugin::setPrivateData(const CasData& /*data*/) {
    115     ALOGV("setPrivateData");
    116     return OK;
    117 }
    118 
    119 status_t MockCasPlugin::openSession(CasSessionId* sessionId) {
    120     ALOGV("openSession");
    121     return MockSessionLibrary::get()->addSession(this, sessionId);
    122 }
    123 
    124 status_t MockCasPlugin::closeSession(const CasSessionId &sessionId) {
    125     ALOGV("closeSession: sessionId=%s", arrayToString(sessionId).string());
    126     Mutex::Autolock lock(mLock);
    127 
    128     sp<MockCasSession> session =
    129             MockSessionLibrary::get()->findSession(sessionId);
    130     if (session == NULL) {
    131         return BAD_VALUE;
    132     }
    133 
    134     MockSessionLibrary::get()->destroySession(sessionId);
    135     return OK;
    136 }
    137 
    138 status_t MockCasPlugin::setSessionPrivateData(
    139         const CasSessionId &sessionId, const CasData& /*data*/) {
    140     ALOGV("setSessionPrivateData: sessionId=%s",
    141             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     return OK;
    150 }
    151 
    152 status_t MockCasPlugin::processEcm(
    153         const CasSessionId &sessionId, const CasEcm& ecm) {
    154     ALOGV("processEcm: sessionId=%s", arrayToString(sessionId).string());
    155     Mutex::Autolock lock(mLock);
    156 
    157     sp<MockCasSession> session =
    158             MockSessionLibrary::get()->findSession(sessionId);
    159     if (session == NULL) {
    160         return BAD_VALUE;
    161     }
    162     ALOGV("ECM: size=%zu", ecm.size());
    163     ALOGV("ECM: data=%s", arrayToString(ecm).string());
    164 
    165     return OK;
    166 }
    167 
    168 status_t MockCasPlugin::processEmm(const CasEmm& emm) {
    169     ALOGV("processEmm");
    170     Mutex::Autolock lock(mLock);
    171 
    172     ALOGV("EMM: size=%zu", emm.size());
    173     ALOGV("EMM: data=%s", arrayToString(emm).string());
    174 
    175     return OK;
    176 }
    177 
    178 status_t MockCasPlugin::sendEvent(
    179         int32_t event, int /*arg*/, const CasData& /*eventData*/) {
    180     ALOGV("sendEvent: event=%d", event);
    181     Mutex::Autolock lock(mLock);
    182 
    183     return OK;
    184 }
    185 
    186 status_t MockCasPlugin::sendSessionEvent(
    187         const CasSessionId &sessionId, int32_t event,
    188         int /*arg*/, const CasData& /*eventData*/) {
    189     ALOGV("sendSessionEvent: sessionId=%s, event=%d",
    190           arrayToString(sessionId).string(), event);
    191     Mutex::Autolock lock(mLock);
    192 
    193     return OK;
    194 }
    195 
    196 status_t MockCasPlugin::provision(const String8 &str) {
    197     ALOGV("provision: provisionString=%s", str.string());
    198     Mutex::Autolock lock(mLock);
    199 
    200     return OK;
    201 }
    202 
    203 status_t MockCasPlugin::refreshEntitlements(
    204         int32_t /*refreshType*/, const CasData &refreshData) {
    205     ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).string());
    206     Mutex::Autolock lock(mLock);
    207 
    208     return OK;
    209 }
    210 
    211 /////////////////////////////////////////////////////////////////
    212 bool MockDescramblerPlugin::requiresSecureDecoderComponent(
    213         const char *mime) const {
    214     ALOGV("MockDescramblerPlugin::requiresSecureDecoderComponent"
    215             "(mime=%s)", mime);
    216     return false;
    217 }
    218 
    219 status_t MockDescramblerPlugin::setMediaCasSession(
    220         const CasSessionId &sessionId) {
    221     ALOGV("MockDescramblerPlugin::setMediaCasSession");
    222     sp<MockCasSession> session =
    223             MockSessionLibrary::get()->findSession(sessionId);
    224 
    225     if (session == NULL) {
    226         ALOGE("MockDescramblerPlugin: session not found");
    227         return ERROR_DRM_SESSION_NOT_OPENED;
    228     }
    229 
    230     return OK;
    231 }
    232 
    233 ssize_t MockDescramblerPlugin::descramble(
    234         bool secure,
    235         ScramblingControl scramblingControl,
    236         size_t numSubSamples,
    237         const SubSample *subSamples,
    238         const void *srcPtr,
    239         int32_t srcOffset,
    240         void *dstPtr,
    241         int32_t dstOffset,
    242         AString* /*errorDetailMsg*/) {
    243     ALOGV("MockDescramblerPlugin::descramble(secure=%d, sctrl=%d,"
    244           "subSamples=%s, srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d)",
    245           (int)secure, (int)scramblingControl,
    246           subSamplesToString(subSamples, numSubSamples).string(),
    247           srcPtr, dstPtr, srcOffset, dstOffset);
    248 
    249     return 0;
    250 }
    251 
    252 // Conversion utilities
    253 String8 MockDescramblerPlugin::arrayToString(
    254         uint8_t const *array, size_t len) const
    255 {
    256     String8 result("{ ");
    257     for (size_t i = 0; i < len; i++) {
    258         result.appendFormat("0x%02x ", array[i]);
    259     }
    260     result += "}";
    261     return result;
    262 }
    263 
    264 String8 MockDescramblerPlugin::subSamplesToString(
    265         SubSample const *subSamples, size_t numSubSamples) const
    266 {
    267     String8 result;
    268     for (size_t i = 0; i < numSubSamples; i++) {
    269         result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i,
    270                             subSamples[i].mNumBytesOfClearData,
    271                             subSamples[i].mNumBytesOfEncryptedData);
    272     }
    273     return result;
    274 }
    275 
    276 } // namespace android
    277 
    278