xref: /aosp_15_r20/frameworks/av/media/module/mpeg2ts/CasManager.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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