1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "CasManager"
19*ec779b8eSAndroid Build Coastguard Worker #include "CasManager.h"
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include <android/hardware/cas/1.0/ICas.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <android/hardware/cas/1.0/IMediaCasService.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <android/hardware/cas/native/1.0/IDescrambler.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <hidl/HidlSupport.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABitReader.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
27*ec779b8eSAndroid Build Coastguard Worker
28*ec779b8eSAndroid Build Coastguard Worker namespace android {
29*ec779b8eSAndroid Build Coastguard Worker
30*ec779b8eSAndroid Build Coastguard Worker using hardware::hidl_vec;
31*ec779b8eSAndroid Build Coastguard Worker using hardware::Return;
32*ec779b8eSAndroid Build Coastguard Worker using namespace hardware::cas::V1_0;
33*ec779b8eSAndroid Build Coastguard Worker using namespace hardware::cas::native::V1_0;
34*ec779b8eSAndroid Build Coastguard Worker
35*ec779b8eSAndroid Build Coastguard Worker struct ATSParser::CasManager::ProgramCasManager : public RefBase {
36*ec779b8eSAndroid Build Coastguard Worker ProgramCasManager(unsigned programNumber, const CADescriptor &descriptor);
37*ec779b8eSAndroid Build Coastguard Worker ProgramCasManager(unsigned programNumber);
38*ec779b8eSAndroid Build Coastguard Worker
39*ec779b8eSAndroid Build Coastguard Worker bool addStream(unsigned elementaryPID, const CADescriptor &descriptor);
40*ec779b8eSAndroid Build Coastguard Worker
41*ec779b8eSAndroid Build Coastguard Worker status_t setMediaCas(const sp<ICas> &cas, PidToSessionMap &sessionMap);
42*ec779b8eSAndroid Build Coastguard Worker
43*ec779b8eSAndroid Build Coastguard Worker bool getCasSession(unsigned elementaryPID,
44*ec779b8eSAndroid Build Coastguard Worker sp<IDescrambler> *descrambler, std::vector<uint8_t> *sessionId) const;
45*ec779b8eSAndroid Build Coastguard Worker
46*ec779b8eSAndroid Build Coastguard Worker void closeAllSessions(const sp<ICas>& cas);
47*ec779b8eSAndroid Build Coastguard Worker
48*ec779b8eSAndroid Build Coastguard Worker private:
49*ec779b8eSAndroid Build Coastguard Worker struct CasSession {
CasSessionandroid::ATSParser::CasManager::ProgramCasManager::CasSession50*ec779b8eSAndroid Build Coastguard Worker CasSession() {}
CasSessionandroid::ATSParser::CasManager::ProgramCasManager::CasSession51*ec779b8eSAndroid Build Coastguard Worker CasSession(const CADescriptor &descriptor) :
52*ec779b8eSAndroid Build Coastguard Worker mCADescriptor(descriptor) {}
53*ec779b8eSAndroid Build Coastguard Worker
54*ec779b8eSAndroid Build Coastguard Worker CADescriptor mCADescriptor;
55*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t> mSessionId;
56*ec779b8eSAndroid Build Coastguard Worker sp<IDescrambler> mDescrambler;
57*ec779b8eSAndroid Build Coastguard Worker };
58*ec779b8eSAndroid Build Coastguard Worker status_t initSession(
59*ec779b8eSAndroid Build Coastguard Worker const sp<ICas>& cas,
60*ec779b8eSAndroid Build Coastguard Worker PidToSessionMap &sessionMap,
61*ec779b8eSAndroid Build Coastguard Worker CasSession *session);
62*ec779b8eSAndroid Build Coastguard Worker void closeSession(const sp<ICas>& cas, const CasSession &casSession);
63*ec779b8eSAndroid Build Coastguard Worker
64*ec779b8eSAndroid Build Coastguard Worker unsigned mProgramNumber;
65*ec779b8eSAndroid Build Coastguard Worker bool mHasProgramCas;
66*ec779b8eSAndroid Build Coastguard Worker CasSession mProgramCas;
67*ec779b8eSAndroid Build Coastguard Worker KeyedVector<unsigned, CasSession> mStreamPidToCasMap;
68*ec779b8eSAndroid Build Coastguard Worker };
69*ec779b8eSAndroid Build Coastguard Worker
ProgramCasManager(unsigned programNumber,const CADescriptor & descriptor)70*ec779b8eSAndroid Build Coastguard Worker ATSParser::CasManager::ProgramCasManager::ProgramCasManager(
71*ec779b8eSAndroid Build Coastguard Worker unsigned programNumber, const CADescriptor &descriptor) :
72*ec779b8eSAndroid Build Coastguard Worker mProgramNumber(programNumber),
73*ec779b8eSAndroid Build Coastguard Worker mHasProgramCas(true),
74*ec779b8eSAndroid Build Coastguard Worker mProgramCas(descriptor) {}
75*ec779b8eSAndroid Build Coastguard Worker
ProgramCasManager(unsigned programNumber)76*ec779b8eSAndroid Build Coastguard Worker ATSParser::CasManager::ProgramCasManager::ProgramCasManager(
77*ec779b8eSAndroid Build Coastguard Worker unsigned programNumber) :
78*ec779b8eSAndroid Build Coastguard Worker mProgramNumber(programNumber),
79*ec779b8eSAndroid Build Coastguard Worker mHasProgramCas(false) {}
80*ec779b8eSAndroid Build Coastguard Worker
addStream(unsigned elementaryPID,const CADescriptor & descriptor)81*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::ProgramCasManager::addStream(
82*ec779b8eSAndroid Build Coastguard Worker unsigned elementaryPID, const CADescriptor &descriptor) {
83*ec779b8eSAndroid Build Coastguard Worker ssize_t index = mStreamPidToCasMap.indexOfKey(elementaryPID);
84*ec779b8eSAndroid Build Coastguard Worker if (index >= 0) {
85*ec779b8eSAndroid Build Coastguard Worker return false;
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker ALOGV("addStream: program=%d, elementaryPID=%d, CA_system_ID=0x%x",
88*ec779b8eSAndroid Build Coastguard Worker mProgramNumber, elementaryPID, descriptor.mSystemID);
89*ec779b8eSAndroid Build Coastguard Worker mStreamPidToCasMap.add(elementaryPID, CasSession(descriptor));
90*ec779b8eSAndroid Build Coastguard Worker return true;
91*ec779b8eSAndroid Build Coastguard Worker }
92*ec779b8eSAndroid Build Coastguard Worker
setMediaCas(const sp<ICas> & cas,PidToSessionMap & sessionMap)93*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::CasManager::ProgramCasManager::setMediaCas(
94*ec779b8eSAndroid Build Coastguard Worker const sp<ICas> &cas, PidToSessionMap &sessionMap) {
95*ec779b8eSAndroid Build Coastguard Worker if (mHasProgramCas) {
96*ec779b8eSAndroid Build Coastguard Worker return initSession(cas, sessionMap, &mProgramCas);
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker // TODO: share session among streams that has identical CA_descriptors.
99*ec779b8eSAndroid Build Coastguard Worker // For now, we open one session for each stream that has CA_descriptor.
100*ec779b8eSAndroid Build Coastguard Worker for (size_t index = 0; index < mStreamPidToCasMap.size(); index++) {
101*ec779b8eSAndroid Build Coastguard Worker status_t err = initSession(
102*ec779b8eSAndroid Build Coastguard Worker cas, sessionMap, &mStreamPidToCasMap.editValueAt(index));
103*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
104*ec779b8eSAndroid Build Coastguard Worker return err;
105*ec779b8eSAndroid Build Coastguard Worker }
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker return OK;
108*ec779b8eSAndroid Build Coastguard Worker }
109*ec779b8eSAndroid Build Coastguard Worker
getCasSession(unsigned elementaryPID,sp<IDescrambler> * descrambler,std::vector<uint8_t> * sessionId) const110*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::ProgramCasManager::getCasSession(
111*ec779b8eSAndroid Build Coastguard Worker unsigned elementaryPID, sp<IDescrambler> *descrambler,
112*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t> *sessionId) const {
113*ec779b8eSAndroid Build Coastguard Worker if (mHasProgramCas) {
114*ec779b8eSAndroid Build Coastguard Worker *descrambler = mProgramCas.mDescrambler;
115*ec779b8eSAndroid Build Coastguard Worker *sessionId = mProgramCas.mSessionId;
116*ec779b8eSAndroid Build Coastguard Worker return true;
117*ec779b8eSAndroid Build Coastguard Worker }
118*ec779b8eSAndroid Build Coastguard Worker ssize_t index = mStreamPidToCasMap.indexOfKey(elementaryPID);
119*ec779b8eSAndroid Build Coastguard Worker if (index < 0) {
120*ec779b8eSAndroid Build Coastguard Worker return false;
121*ec779b8eSAndroid Build Coastguard Worker }
122*ec779b8eSAndroid Build Coastguard Worker
123*ec779b8eSAndroid Build Coastguard Worker *descrambler = mStreamPidToCasMap[index].mDescrambler;
124*ec779b8eSAndroid Build Coastguard Worker *sessionId = mStreamPidToCasMap[index].mSessionId;
125*ec779b8eSAndroid Build Coastguard Worker return true;
126*ec779b8eSAndroid Build Coastguard Worker }
127*ec779b8eSAndroid Build Coastguard Worker
initSession(const sp<ICas> & cas,PidToSessionMap & sessionMap,CasSession * session)128*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::CasManager::ProgramCasManager::initSession(
129*ec779b8eSAndroid Build Coastguard Worker const sp<ICas>& cas,
130*ec779b8eSAndroid Build Coastguard Worker PidToSessionMap &sessionMap,
131*ec779b8eSAndroid Build Coastguard Worker CasSession *session) {
132*ec779b8eSAndroid Build Coastguard Worker sp<IMediaCasService> casService = IMediaCasService::getService("default");
133*ec779b8eSAndroid Build Coastguard Worker if (casService == NULL) {
134*ec779b8eSAndroid Build Coastguard Worker ALOGE("Cannot obtain IMediaCasService");
135*ec779b8eSAndroid Build Coastguard Worker return NO_INIT;
136*ec779b8eSAndroid Build Coastguard Worker }
137*ec779b8eSAndroid Build Coastguard Worker
138*ec779b8eSAndroid Build Coastguard Worker Status status;
139*ec779b8eSAndroid Build Coastguard Worker sp<IDescrambler> descrambler;
140*ec779b8eSAndroid Build Coastguard Worker sp<IDescramblerBase> descramblerBase;
141*ec779b8eSAndroid Build Coastguard Worker Return<Status> returnStatus(Status::OK);
142*ec779b8eSAndroid Build Coastguard Worker Return<sp<IDescramblerBase> > returnDescrambler(NULL);
143*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t> sessionId;
144*ec779b8eSAndroid Build Coastguard Worker const CADescriptor &descriptor = session->mCADescriptor;
145*ec779b8eSAndroid Build Coastguard Worker
146*ec779b8eSAndroid Build Coastguard Worker auto returnVoid = cas->openSession(
147*ec779b8eSAndroid Build Coastguard Worker [&status, &sessionId] (Status _status, const hidl_vec<uint8_t>& _sessionId) {
148*ec779b8eSAndroid Build Coastguard Worker status = _status;
149*ec779b8eSAndroid Build Coastguard Worker sessionId = _sessionId;
150*ec779b8eSAndroid Build Coastguard Worker });
151*ec779b8eSAndroid Build Coastguard Worker if (!returnVoid.isOk() || status != Status::OK) {
152*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to open session: trans=%s, status=%d",
153*ec779b8eSAndroid Build Coastguard Worker returnVoid.description().c_str(), status);
154*ec779b8eSAndroid Build Coastguard Worker goto l_fail;
155*ec779b8eSAndroid Build Coastguard Worker }
156*ec779b8eSAndroid Build Coastguard Worker
157*ec779b8eSAndroid Build Coastguard Worker returnStatus = cas->setSessionPrivateData(sessionId, descriptor.mPrivateData);
158*ec779b8eSAndroid Build Coastguard Worker if (!returnStatus.isOk() || returnStatus != Status::OK) {
159*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to set private data: trans=%s, status=%d",
160*ec779b8eSAndroid Build Coastguard Worker returnStatus.description().c_str(), (Status)returnStatus);
161*ec779b8eSAndroid Build Coastguard Worker goto l_fail;
162*ec779b8eSAndroid Build Coastguard Worker }
163*ec779b8eSAndroid Build Coastguard Worker
164*ec779b8eSAndroid Build Coastguard Worker returnDescrambler = casService->createDescrambler(descriptor.mSystemID);
165*ec779b8eSAndroid Build Coastguard Worker if (!returnDescrambler.isOk()) {
166*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create descrambler: trans=%s",
167*ec779b8eSAndroid Build Coastguard Worker returnDescrambler.description().c_str());
168*ec779b8eSAndroid Build Coastguard Worker goto l_fail;
169*ec779b8eSAndroid Build Coastguard Worker }
170*ec779b8eSAndroid Build Coastguard Worker descramblerBase = (sp<IDescramblerBase>) returnDescrambler;
171*ec779b8eSAndroid Build Coastguard Worker if (descramblerBase == NULL) {
172*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create descrambler: null ptr");
173*ec779b8eSAndroid Build Coastguard Worker goto l_fail;
174*ec779b8eSAndroid Build Coastguard Worker }
175*ec779b8eSAndroid Build Coastguard Worker
176*ec779b8eSAndroid Build Coastguard Worker returnStatus = descramblerBase->setMediaCasSession(sessionId);
177*ec779b8eSAndroid Build Coastguard Worker if (!returnStatus.isOk() || (Status) returnStatus != Status::OK) {
178*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to init descrambler: : trans=%s, status=%d",
179*ec779b8eSAndroid Build Coastguard Worker returnStatus.description().c_str(), (Status) returnStatus);
180*ec779b8eSAndroid Build Coastguard Worker goto l_fail;
181*ec779b8eSAndroid Build Coastguard Worker }
182*ec779b8eSAndroid Build Coastguard Worker
183*ec779b8eSAndroid Build Coastguard Worker descrambler = IDescrambler::castFrom(descramblerBase);
184*ec779b8eSAndroid Build Coastguard Worker if (descrambler == NULL) {
185*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to cast from IDescramblerBase to IDescrambler");
186*ec779b8eSAndroid Build Coastguard Worker goto l_fail;
187*ec779b8eSAndroid Build Coastguard Worker }
188*ec779b8eSAndroid Build Coastguard Worker
189*ec779b8eSAndroid Build Coastguard Worker session->mSessionId = sessionId;
190*ec779b8eSAndroid Build Coastguard Worker session->mDescrambler = descrambler;
191*ec779b8eSAndroid Build Coastguard Worker sessionMap.add(descriptor.mPID, sessionId);
192*ec779b8eSAndroid Build Coastguard Worker
193*ec779b8eSAndroid Build Coastguard Worker return OK;
194*ec779b8eSAndroid Build Coastguard Worker
195*ec779b8eSAndroid Build Coastguard Worker l_fail:
196*ec779b8eSAndroid Build Coastguard Worker if (!sessionId.empty()) {
197*ec779b8eSAndroid Build Coastguard Worker cas->closeSession(sessionId);
198*ec779b8eSAndroid Build Coastguard Worker }
199*ec779b8eSAndroid Build Coastguard Worker if (descramblerBase != NULL) {
200*ec779b8eSAndroid Build Coastguard Worker descramblerBase->release();
201*ec779b8eSAndroid Build Coastguard Worker }
202*ec779b8eSAndroid Build Coastguard Worker return NO_INIT;
203*ec779b8eSAndroid Build Coastguard Worker }
204*ec779b8eSAndroid Build Coastguard Worker
closeSession(const sp<ICas> & cas,const CasSession & casSession)205*ec779b8eSAndroid Build Coastguard Worker void ATSParser::CasManager::ProgramCasManager::closeSession(
206*ec779b8eSAndroid Build Coastguard Worker const sp<ICas>& cas, const CasSession &casSession) {
207*ec779b8eSAndroid Build Coastguard Worker if (casSession.mDescrambler != NULL) {
208*ec779b8eSAndroid Build Coastguard Worker casSession.mDescrambler->release();
209*ec779b8eSAndroid Build Coastguard Worker }
210*ec779b8eSAndroid Build Coastguard Worker if (!casSession.mSessionId.empty()) {
211*ec779b8eSAndroid Build Coastguard Worker cas->closeSession(casSession.mSessionId);
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker }
214*ec779b8eSAndroid Build Coastguard Worker
closeAllSessions(const sp<ICas> & cas)215*ec779b8eSAndroid Build Coastguard Worker void ATSParser::CasManager::ProgramCasManager::closeAllSessions(
216*ec779b8eSAndroid Build Coastguard Worker const sp<ICas>& cas) {
217*ec779b8eSAndroid Build Coastguard Worker if (mHasProgramCas) {
218*ec779b8eSAndroid Build Coastguard Worker closeSession(cas, mProgramCas);
219*ec779b8eSAndroid Build Coastguard Worker }
220*ec779b8eSAndroid Build Coastguard Worker for (size_t index = 0; index < mStreamPidToCasMap.size(); index++) {
221*ec779b8eSAndroid Build Coastguard Worker closeSession(cas, mStreamPidToCasMap.editValueAt(index));
222*ec779b8eSAndroid Build Coastguard Worker }
223*ec779b8eSAndroid Build Coastguard Worker }
224*ec779b8eSAndroid Build Coastguard Worker
225*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
226*ec779b8eSAndroid Build Coastguard Worker
CasManager()227*ec779b8eSAndroid Build Coastguard Worker ATSParser::CasManager::CasManager() : mSystemId(-1) {}
228*ec779b8eSAndroid Build Coastguard Worker
~CasManager()229*ec779b8eSAndroid Build Coastguard Worker ATSParser::CasManager::~CasManager() {
230*ec779b8eSAndroid Build Coastguard Worker // Explictly close the sessions opened by us, since the CAS object is owned
231*ec779b8eSAndroid Build Coastguard Worker // by the app and may not go away after the parser is destroyed, and the app
232*ec779b8eSAndroid Build Coastguard Worker // may not have information about the sessions.
233*ec779b8eSAndroid Build Coastguard Worker if (mICas != NULL) {
234*ec779b8eSAndroid Build Coastguard Worker for (size_t index = 0; index < mProgramCasMap.size(); index++) {
235*ec779b8eSAndroid Build Coastguard Worker mProgramCasMap.editValueAt(index)->closeAllSessions(mICas);
236*ec779b8eSAndroid Build Coastguard Worker }
237*ec779b8eSAndroid Build Coastguard Worker }
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker
setSystemId(int32_t CA_system_ID)240*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::setSystemId(int32_t CA_system_ID) {
241*ec779b8eSAndroid Build Coastguard Worker if (mSystemId == -1) {
242*ec779b8eSAndroid Build Coastguard Worker // Verify the CA_system_ID is within range on the first program
243*ec779b8eSAndroid Build Coastguard Worker if (CA_system_ID < 0 || CA_system_ID > 0xffff) {
244*ec779b8eSAndroid Build Coastguard Worker ALOGE("Invalid CA_system_id: %d", CA_system_ID);
245*ec779b8eSAndroid Build Coastguard Worker return false;
246*ec779b8eSAndroid Build Coastguard Worker }
247*ec779b8eSAndroid Build Coastguard Worker mSystemId = CA_system_ID;
248*ec779b8eSAndroid Build Coastguard Worker } else if (mSystemId != CA_system_ID) {
249*ec779b8eSAndroid Build Coastguard Worker // All sessions need to be under the same CA system
250*ec779b8eSAndroid Build Coastguard Worker ALOGE("Multiple CA systems not allowed: %d vs %d",
251*ec779b8eSAndroid Build Coastguard Worker mSystemId, CA_system_ID);
252*ec779b8eSAndroid Build Coastguard Worker return false;
253*ec779b8eSAndroid Build Coastguard Worker }
254*ec779b8eSAndroid Build Coastguard Worker return true;
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker
setMediaCas(const sp<ICas> & cas)257*ec779b8eSAndroid Build Coastguard Worker status_t ATSParser::CasManager::setMediaCas(const sp<ICas> &cas) {
258*ec779b8eSAndroid Build Coastguard Worker if (cas == NULL) {
259*ec779b8eSAndroid Build Coastguard Worker ALOGE("setMediaCas: received NULL object");
260*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
261*ec779b8eSAndroid Build Coastguard Worker }
262*ec779b8eSAndroid Build Coastguard Worker if (mICas != NULL) {
263*ec779b8eSAndroid Build Coastguard Worker ALOGW("setMediaCas: already set");
264*ec779b8eSAndroid Build Coastguard Worker return ALREADY_EXISTS;
265*ec779b8eSAndroid Build Coastguard Worker }
266*ec779b8eSAndroid Build Coastguard Worker for (size_t index = 0; index < mProgramCasMap.size(); index++) {
267*ec779b8eSAndroid Build Coastguard Worker status_t err;
268*ec779b8eSAndroid Build Coastguard Worker if ((err = mProgramCasMap.editValueAt(
269*ec779b8eSAndroid Build Coastguard Worker index)->setMediaCas(cas, mCAPidToSessionIdMap)) != OK) {
270*ec779b8eSAndroid Build Coastguard Worker return err;
271*ec779b8eSAndroid Build Coastguard Worker }
272*ec779b8eSAndroid Build Coastguard Worker }
273*ec779b8eSAndroid Build Coastguard Worker mICas = cas;
274*ec779b8eSAndroid Build Coastguard Worker return OK;
275*ec779b8eSAndroid Build Coastguard Worker }
276*ec779b8eSAndroid Build Coastguard Worker
addProgram(unsigned programNumber,const CADescriptor & descriptor)277*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::addProgram(
278*ec779b8eSAndroid Build Coastguard Worker unsigned programNumber, const CADescriptor &descriptor) {
279*ec779b8eSAndroid Build Coastguard Worker if (!setSystemId(descriptor.mSystemID)) {
280*ec779b8eSAndroid Build Coastguard Worker return false;
281*ec779b8eSAndroid Build Coastguard Worker }
282*ec779b8eSAndroid Build Coastguard Worker
283*ec779b8eSAndroid Build Coastguard Worker ssize_t index = mProgramCasMap.indexOfKey(programNumber);
284*ec779b8eSAndroid Build Coastguard Worker if (index < 0) {
285*ec779b8eSAndroid Build Coastguard Worker ALOGV("addProgram: programNumber=%d, CA_system_ID=0x%x",
286*ec779b8eSAndroid Build Coastguard Worker programNumber, descriptor.mSystemID);
287*ec779b8eSAndroid Build Coastguard Worker mProgramCasMap.add(programNumber,
288*ec779b8eSAndroid Build Coastguard Worker new ProgramCasManager(programNumber, descriptor));
289*ec779b8eSAndroid Build Coastguard Worker mCAPidSet.insert(descriptor.mPID);
290*ec779b8eSAndroid Build Coastguard Worker }
291*ec779b8eSAndroid Build Coastguard Worker return true;
292*ec779b8eSAndroid Build Coastguard Worker }
293*ec779b8eSAndroid Build Coastguard Worker
addStream(unsigned programNumber,unsigned elementaryPID,const CADescriptor & descriptor)294*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::addStream(
295*ec779b8eSAndroid Build Coastguard Worker unsigned programNumber, unsigned elementaryPID,
296*ec779b8eSAndroid Build Coastguard Worker const CADescriptor &descriptor) {
297*ec779b8eSAndroid Build Coastguard Worker if (!setSystemId(descriptor.mSystemID)) {
298*ec779b8eSAndroid Build Coastguard Worker return false;
299*ec779b8eSAndroid Build Coastguard Worker }
300*ec779b8eSAndroid Build Coastguard Worker
301*ec779b8eSAndroid Build Coastguard Worker ssize_t index = mProgramCasMap.indexOfKey(programNumber);
302*ec779b8eSAndroid Build Coastguard Worker sp<ProgramCasManager> programCasManager;
303*ec779b8eSAndroid Build Coastguard Worker if (index < 0) {
304*ec779b8eSAndroid Build Coastguard Worker ALOGV("addProgram (no CADescriptor): programNumber=%d", programNumber);
305*ec779b8eSAndroid Build Coastguard Worker programCasManager = new ProgramCasManager(programNumber);
306*ec779b8eSAndroid Build Coastguard Worker mProgramCasMap.add(programNumber, programCasManager);
307*ec779b8eSAndroid Build Coastguard Worker } else {
308*ec779b8eSAndroid Build Coastguard Worker programCasManager = mProgramCasMap.editValueAt(index);
309*ec779b8eSAndroid Build Coastguard Worker }
310*ec779b8eSAndroid Build Coastguard Worker if (programCasManager->addStream(elementaryPID, descriptor)) {
311*ec779b8eSAndroid Build Coastguard Worker mCAPidSet.insert(descriptor.mPID);
312*ec779b8eSAndroid Build Coastguard Worker }
313*ec779b8eSAndroid Build Coastguard Worker return true;
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker
getCasInfo(unsigned programNumber,unsigned elementaryPID,int32_t * systemId,sp<IDescrambler> * descrambler,std::vector<uint8_t> * sessionId) const316*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::getCasInfo(
317*ec779b8eSAndroid Build Coastguard Worker unsigned programNumber, unsigned elementaryPID,
318*ec779b8eSAndroid Build Coastguard Worker int32_t *systemId, sp<IDescrambler> *descrambler,
319*ec779b8eSAndroid Build Coastguard Worker std::vector<uint8_t> *sessionId) const {
320*ec779b8eSAndroid Build Coastguard Worker ssize_t index = mProgramCasMap.indexOfKey(programNumber);
321*ec779b8eSAndroid Build Coastguard Worker if (index < 0) {
322*ec779b8eSAndroid Build Coastguard Worker return false;
323*ec779b8eSAndroid Build Coastguard Worker }
324*ec779b8eSAndroid Build Coastguard Worker *systemId = mSystemId;
325*ec779b8eSAndroid Build Coastguard Worker return mProgramCasMap[index]->getCasSession(
326*ec779b8eSAndroid Build Coastguard Worker elementaryPID, descrambler, sessionId);
327*ec779b8eSAndroid Build Coastguard Worker }
328*ec779b8eSAndroid Build Coastguard Worker
isCAPid(unsigned pid)329*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::isCAPid(unsigned pid) {
330*ec779b8eSAndroid Build Coastguard Worker return mCAPidSet.find(pid) != mCAPidSet.end();
331*ec779b8eSAndroid Build Coastguard Worker }
332*ec779b8eSAndroid Build Coastguard Worker
parsePID(ABitReader * br,unsigned pid)333*ec779b8eSAndroid Build Coastguard Worker bool ATSParser::CasManager::parsePID(ABitReader *br, unsigned pid) {
334*ec779b8eSAndroid Build Coastguard Worker ssize_t index = mCAPidToSessionIdMap.indexOfKey(pid);
335*ec779b8eSAndroid Build Coastguard Worker if (index < 0) {
336*ec779b8eSAndroid Build Coastguard Worker return false;
337*ec779b8eSAndroid Build Coastguard Worker }
338*ec779b8eSAndroid Build Coastguard Worker hidl_vec<uint8_t> ecm;
339*ec779b8eSAndroid Build Coastguard Worker ecm.setToExternal((uint8_t*)br->data(), br->numBitsLeft() / 8);
340*ec779b8eSAndroid Build Coastguard Worker auto returnStatus = mICas->processEcm(mCAPidToSessionIdMap[index], ecm);
341*ec779b8eSAndroid Build Coastguard Worker if (!returnStatus.isOk() || (Status) returnStatus != Status::OK) {
342*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to process ECM: trans=%s, status=%d",
343*ec779b8eSAndroid Build Coastguard Worker returnStatus.description().c_str(), (Status) returnStatus);
344*ec779b8eSAndroid Build Coastguard Worker }
345*ec779b8eSAndroid Build Coastguard Worker return true; // handled
346*ec779b8eSAndroid Build Coastguard Worker }
347*ec779b8eSAndroid Build Coastguard Worker
348*ec779b8eSAndroid Build Coastguard Worker } // namespace android
349