MockCasPlugin.cpp revision 791a1a206b56be8601a6fffd2614926e67d64790
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(
107        uint16_t program_number, CasSessionId* sessionId) {
108    ALOGV("openSession: program_number=%u", program_number);
109    return MockSessionLibrary::get()->addSession(
110            this, program_number, 0, sessionId);
111}
112
113status_t MockCasPlugin::openSession(
114        uint16_t program_number,
115        uint16_t elementary_PID,
116        CasSessionId *sessionId) {
117    ALOGV("openSession: program_number=%u, elementary_PID=%u",
118            program_number, elementary_PID);
119
120    return MockSessionLibrary::get()->addSession(
121            this, program_number, elementary_PID, sessionId);
122}
123
124status_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
138status_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
152status_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=%d", ecm.size());
163    ALOGV("ECM: data=%s", arrayToString(ecm).string());
164
165    return OK;
166}
167
168status_t MockCasPlugin::processEmm(const CasEmm& emm) {
169    ALOGV("processEmm");
170    Mutex::Autolock lock(mLock);
171
172    ALOGV("EMM: size=%d", emm.size());
173    ALOGV("EMM: data=%s", arrayToString(emm).string());
174
175    return OK;
176}
177
178status_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
186status_t MockCasPlugin::provision(const String8 &str) {
187    ALOGV("provision: provisionString=%s", str.string());
188    Mutex::Autolock lock(mLock);
189
190    return OK;
191}
192
193status_t MockCasPlugin::refreshEntitlements(
194        int32_t refreshType, const CasData &refreshData) {
195    ALOGV("refreshEntitlements: refreshData=%s", arrayToString(refreshData).string());
196    Mutex::Autolock lock(mLock);
197
198    return OK;
199}
200
201/////////////////////////////////////////////////////////////////
202bool MockDescramblerPlugin::requiresSecureDecoderComponent(
203        const char *mime) const {
204    ALOGV("MockDescramblerPlugin::requiresSecureDecoderComponent"
205            "(mime=%s)", mime);
206    return false;
207}
208
209status_t MockDescramblerPlugin::setMediaCasSession(
210        const CasSessionId &sessionId) {
211    ALOGV("MockDescramblerPlugin::setMediaCasSession");
212    sp<MockCasSession> session =
213            MockSessionLibrary::get()->findSession(sessionId);
214
215    if (session == NULL) {
216        ALOGE("MockDescramblerPlugin: session not found");
217        return ERROR_DRM_SESSION_NOT_OPENED;
218    }
219
220    return OK;
221}
222
223ssize_t MockDescramblerPlugin::descramble(
224        bool secure,
225        ScramblingControl scramblingControl,
226        size_t numSubSamples,
227        const SubSample *subSamples,
228        const void *srcPtr,
229        int32_t srcOffset,
230        void *dstPtr,
231        int32_t dstOffset,
232        AString *errorDetailMsg) {
233    ALOGV("MockDescramblerPlugin::descramble(secure=%d, sctrl=%d,"
234          "subSamples=%s, srcPtr=%p, dstPtr=%p, srcOffset=%d, dstOffset=%d)",
235          (int)secure, (int)scramblingControl,
236          subSamplesToString(subSamples, numSubSamples).string(),
237          srcPtr, dstPtr, srcOffset, dstOffset);
238
239    return 0;
240}
241
242// Conversion utilities
243String8 MockDescramblerPlugin::arrayToString(
244        uint8_t const *array, size_t len) const
245{
246    String8 result("{ ");
247    for (size_t i = 0; i < len; i++) {
248        result.appendFormat("0x%02x ", array[i]);
249    }
250    result += "}";
251    return result;
252}
253
254String8 MockDescramblerPlugin::subSamplesToString(
255        SubSample const *subSamples, size_t numSubSamples) const
256{
257    String8 result;
258    for (size_t i = 0; i < numSubSamples; i++) {
259        result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i,
260                            subSamples[i].mNumBytesOfClearData,
261                            subSamples[i].mNumBytesOfEncryptedData);
262    }
263    return result;
264}
265
266} // namespace android
267
268