13b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang/* 23b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * Copyright (C) 2017 The Android Open Source Project 33b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * 43b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 53b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * you may not use this file except in compliance with the License. 63b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * You may obtain a copy of the License at 73b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * 83b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * http://www.apache.org/licenses/LICENSE-2.0 93b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * 103b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * Unless required by applicable law or agreed to in writing, software 113b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 123b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * See the License for the specific language governing permissions and 143b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang * limitations under the License. 153b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang */ 163b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 173b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang//#define LOG_NDEBUG 0 183b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#define LOG_TAG "CasManager" 193b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include "CasManager.h" 203b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 213b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include <android/media/ICas.h> 223b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include <android/media/IDescrambler.h> 233b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include <android/media/IMediaCasService.h> 243b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include <binder/IServiceManager.h> 253b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include <media/stagefright/foundation/ABitReader.h> 263b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang#include <utils/Log.h> 273b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 283b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangnamespace android { 293b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangusing binder::Status; 303b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 313b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangstruct ATSParser::CasManager::ProgramCasManager : public RefBase { 323b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ProgramCasManager(unsigned programNumber, const CADescriptor &descriptor); 333b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ProgramCasManager(unsigned programNumber); 343b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 353b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang bool addStream(unsigned elementaryPID, const CADescriptor &descriptor); 363b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 373b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status_t setMediaCas(const sp<ICas> &cas, PidToSessionMap &sessionMap); 383b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 393b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang bool getCasSession(unsigned elementaryPID, 403b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<IDescrambler> *descrambler, std::vector<uint8_t> *sessionId) const; 413b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 423b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang void closeAllSessions(const sp<ICas>& cas); 433b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 443b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangprivate: 453b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang struct CasSession { 463b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang CasSession() {} 473b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang CasSession(const CADescriptor &descriptor) : 483b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mCADescriptor(descriptor) {} 493b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 503b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang CADescriptor mCADescriptor; 513b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang std::vector<uint8_t> mSessionId; 523b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<IDescrambler> mDescrambler; 533b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang }; 543b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status_t initSession( 55a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang const sp<ICas>& cas, 56a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang PidToSessionMap &sessionMap, 57a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang CasSession *session); 583b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang void closeSession(const sp<ICas>& cas, const CasSession &casSession); 593b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 603b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned mProgramNumber; 613b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang bool mHasProgramCas; 623b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang CasSession mProgramCas; 633b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang KeyedVector<unsigned, CasSession> mStreamPidToCasMap; 643b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang}; 653b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 663b2847fa5506dc265d2e46f067bfbb66ae209f74Chong ZhangATSParser::CasManager::ProgramCasManager::ProgramCasManager( 673b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned programNumber, const CADescriptor &descriptor) : 683b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mProgramNumber(programNumber), 693b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mHasProgramCas(true), 703b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mProgramCas(descriptor) {} 713b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 723b2847fa5506dc265d2e46f067bfbb66ae209f74Chong ZhangATSParser::CasManager::ProgramCasManager::ProgramCasManager( 733b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned programNumber) : 743b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mProgramNumber(programNumber), 753b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mHasProgramCas(false) {} 763b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 773b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangbool ATSParser::CasManager::ProgramCasManager::addStream( 783b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned elementaryPID, const CADescriptor &descriptor) { 793b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ssize_t index = mStreamPidToCasMap.indexOfKey(elementaryPID); 803b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (index >= 0) { 813b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 823b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 833b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGV("addStream: program=%d, elementaryPID=%d, CA_system_ID=0x%x", 843b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mProgramNumber, elementaryPID, descriptor.mSystemID); 853b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mStreamPidToCasMap.add(elementaryPID, CasSession(descriptor)); 863b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return true; 873b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 883b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 893b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangstatus_t ATSParser::CasManager::ProgramCasManager::setMediaCas( 903b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang const sp<ICas> &cas, PidToSessionMap &sessionMap) { 913b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (mHasProgramCas) { 92a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang return initSession(cas, sessionMap, &mProgramCas); 933b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 94a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang // TODO: share session among streams that has identical CA_descriptors. 95a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang // For now, we open one session for each stream that has CA_descriptor. 963b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang for (size_t index = 0; index < mStreamPidToCasMap.size(); index++) { 97a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang status_t err = initSession( 98a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang cas, sessionMap, &mStreamPidToCasMap.editValueAt(index)); 99a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang if (err != OK) { 1003b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return err; 1013b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1023b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1033b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return OK; 1043b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 1053b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1063b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangbool ATSParser::CasManager::ProgramCasManager::getCasSession( 1073b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned elementaryPID, sp<IDescrambler> *descrambler, 1083b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang std::vector<uint8_t> *sessionId) const { 1093b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (mHasProgramCas) { 1103b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang *descrambler = mProgramCas.mDescrambler; 1113b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang *sessionId = mProgramCas.mSessionId; 1123b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return true; 1133b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1143b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ssize_t index = mStreamPidToCasMap.indexOfKey(elementaryPID); 1153b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (index < 0) { 1163b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 1173b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1183b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1193b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang *descrambler = mStreamPidToCasMap[index].mDescrambler; 1203b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang *sessionId = mStreamPidToCasMap[index].mSessionId; 1213b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return true; 1223b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 1233b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1243b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangstatus_t ATSParser::CasManager::ProgramCasManager::initSession( 125a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang const sp<ICas>& cas, 126a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang PidToSessionMap &sessionMap, 127a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang CasSession *session) { 1283b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<IServiceManager> sm = defaultServiceManager(); 1293b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<IBinder> casServiceBinder = sm->getService(String16("media.cas")); 1303b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<IMediaCasService> casService = 1313b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang interface_cast<IMediaCasService>(casServiceBinder); 1323b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1333b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (casService == NULL) { 1343b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Cannot obtain IMediaCasService"); 1353b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return NO_INIT; 1363b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1373b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1383b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<IDescrambler> descrambler; 1393b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang std::vector<uint8_t> sessionId; 1403b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang const CADescriptor &descriptor = session->mCADescriptor; 1413b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 142a78c1cc9773532b1f9d066ed8fa0d9414c1bb8bbChong Zhang Status status = cas->openSession(&sessionId); 1433b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!status.isOk()) { 1443b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Failed to open session: exception=%d, error=%d", 1453b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status.exceptionCode(), status.serviceSpecificErrorCode()); 1463b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang goto l_fail; 1473b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1483b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1493b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang cas->setSessionPrivateData(sessionId, descriptor.mPrivateData); 1503b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!status.isOk()) { 1513b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Failed to set private data: exception=%d, error=%d", 1523b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status.exceptionCode(), status.serviceSpecificErrorCode()); 1533b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang goto l_fail; 1543b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1553b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1563b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status = casService->createDescrambler(descriptor.mSystemID, &descrambler); 1573b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!status.isOk() || descrambler == NULL) { 1583b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Failed to create descrambler: : exception=%d, error=%d", 1593b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status.exceptionCode(), status.serviceSpecificErrorCode()); 1603b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang goto l_fail; 1613b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1623b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1633b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status = descrambler->setMediaCasSession(sessionId); 1643b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!status.isOk()) { 1653b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Failed to init descrambler: : exception=%d, error=%d", 1663b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status.exceptionCode(), status.serviceSpecificErrorCode()); 1673b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang goto l_fail; 1683b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1693b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1703b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang session->mSessionId = sessionId; 1713b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang session->mDescrambler = descrambler; 1723b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sessionMap.add(descriptor.mPID, sessionId); 1733b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1743b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return OK; 1753b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1763b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangl_fail: 1773b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!sessionId.empty()) { 1783b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang cas->closeSession(sessionId); 1793b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1803b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (descrambler != NULL) { 1813b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang descrambler->release(); 1823b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1833b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return NO_INIT; 1843b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 1853b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1863b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangvoid ATSParser::CasManager::ProgramCasManager::closeSession( 1873b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang const sp<ICas>& cas, const CasSession &casSession) { 1883b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (casSession.mDescrambler != NULL) { 1893b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang casSession.mDescrambler->release(); 1903b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1913b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!casSession.mSessionId.empty()) { 1923b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang cas->closeSession(casSession.mSessionId); 1933b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 1943b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 1953b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 1963b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangvoid ATSParser::CasManager::ProgramCasManager::closeAllSessions( 1973b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang const sp<ICas>& cas) { 1983b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (mHasProgramCas) { 1993b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang closeSession(cas, mProgramCas); 2003b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2013b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang for (size_t index = 0; index < mStreamPidToCasMap.size(); index++) { 2023b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang closeSession(cas, mStreamPidToCasMap.editValueAt(index)); 2033b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2043b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 2053b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2063b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang//////////////////////////////////////////////////////////////////////////////// 2073b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2083b2847fa5506dc265d2e46f067bfbb66ae209f74Chong ZhangATSParser::CasManager::CasManager() : mSystemId(-1) {} 2093b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2103b2847fa5506dc265d2e46f067bfbb66ae209f74Chong ZhangATSParser::CasManager::~CasManager() { 2113b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // Explictly close the sessions opened by us, since the CAS object is owned 2123b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // by the app and may not go away after the parser is destroyed, and the app 2133b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // may not have information about the sessions. 2143b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (mICas != NULL) { 2153b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang for (size_t index = 0; index < mProgramCasMap.size(); index++) { 2163b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mProgramCasMap.editValueAt(index)->closeAllSessions(mICas); 2173b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2183b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2193b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 2203b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2213b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangbool ATSParser::CasManager::setSystemId(int32_t CA_system_ID) { 2223b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (mSystemId == -1) { 2233b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // Verify the CA_system_ID is within range on the first program 2243b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (CA_system_ID < 0 || CA_system_ID > 0xffff) { 2253b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Invalid CA_system_id: %d", CA_system_ID); 2263b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 2273b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2283b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mSystemId = CA_system_ID; 2293b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } else if (mSystemId != CA_system_ID) { 2303b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang // All sessions need to be under the same CA system 2313b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Multiple CA systems not allowed: %d vs %d", 2323b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mSystemId, CA_system_ID); 2333b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 2343b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2353b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return true; 2363b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 2373b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2383b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangstatus_t ATSParser::CasManager::setMediaCas(const sp<ICas> &cas) { 2393b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (cas == NULL) { 2403b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("setMediaCas: received NULL object"); 2413b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return BAD_VALUE; 2423b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2433b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (mICas != NULL) { 2443b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGW("setMediaCas: already set"); 2453b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return ALREADY_EXISTS; 2463b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2473b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang for (size_t index = 0; index < mProgramCasMap.size(); index++) { 2483b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status_t err; 2493b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if ((err = mProgramCasMap.editValueAt( 2503b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang index)->setMediaCas(cas, mCAPidToSessionIdMap)) != OK) { 2513b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return err; 2523b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2533b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2543b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mICas = cas; 2553b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return OK; 2563b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 2573b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2583b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangbool ATSParser::CasManager::addProgram( 2593b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned programNumber, const CADescriptor &descriptor) { 2603b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!setSystemId(descriptor.mSystemID)) { 2613b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 2623b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2633b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2643b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ssize_t index = mProgramCasMap.indexOfKey(programNumber); 2653b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (index < 0) { 2663b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGV("addProgram: programNumber=%d, CA_system_ID=0x%x", 2673b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang programNumber, descriptor.mSystemID); 2683b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mProgramCasMap.add(programNumber, 2693b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang new ProgramCasManager(programNumber, descriptor)); 2703b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mCAPidSet.insert(descriptor.mPID); 2713b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2723b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return true; 2733b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 2743b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2753b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangbool ATSParser::CasManager::addStream( 2763b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned programNumber, unsigned elementaryPID, 2773b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang const CADescriptor &descriptor) { 2783b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!setSystemId(descriptor.mSystemID)) { 2793b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 2803b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2813b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 2823b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ssize_t index = mProgramCasMap.indexOfKey(programNumber); 2833b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang sp<ProgramCasManager> programCasManager; 2843b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (index < 0) { 2853b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGV("addProgram (no CADescriptor): programNumber=%d", programNumber); 2863b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang programCasManager = new ProgramCasManager(programNumber); 2873b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mProgramCasMap.add(programNumber, programCasManager); 2883b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } else { 2893b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang programCasManager = mProgramCasMap.editValueAt(index); 2903b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2913b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (programCasManager->addStream(elementaryPID, descriptor)) { 2923b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang mCAPidSet.insert(descriptor.mPID); 2933b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 2943b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return true; 2953b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 2963b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 297bc7aae4ff7e72e5bf0fa888f946835840a4357bbChong Zhangbool ATSParser::CasManager::getCasInfo( 2983b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang unsigned programNumber, unsigned elementaryPID, 299bc7aae4ff7e72e5bf0fa888f946835840a4357bbChong Zhang int32_t *systemId, sp<IDescrambler> *descrambler, 300bc7aae4ff7e72e5bf0fa888f946835840a4357bbChong Zhang std::vector<uint8_t> *sessionId) const { 3013b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ssize_t index = mProgramCasMap.indexOfKey(programNumber); 3023b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (index < 0) { 3033b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 3043b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 305bc7aae4ff7e72e5bf0fa888f946835840a4357bbChong Zhang *systemId = mSystemId; 3063b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return mProgramCasMap[index]->getCasSession( 3073b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang elementaryPID, descrambler, sessionId); 3083b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 3093b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 3103b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangbool ATSParser::CasManager::isCAPid(unsigned pid) { 3113b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return mCAPidSet.find(pid) != mCAPidSet.end(); 3123b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 3133b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 3143b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhangbool ATSParser::CasManager::parsePID(ABitReader *br, unsigned pid) { 3153b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ssize_t index = mCAPidToSessionIdMap.indexOfKey(pid); 3163b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (index < 0) { 3173b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return false; 3183b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 3193b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang MediaCas::ParcelableCasData ecm(br->data(), br->numBitsLeft() / 8); 3203b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang Status status = mICas->processEcm(mCAPidToSessionIdMap[index], ecm); 3213b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang if (!status.isOk()) { 3223b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang ALOGE("Failed to process ECM: exception=%d, error=%d", 3233b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang status.exceptionCode(), status.serviceSpecificErrorCode()); 3243b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang } 3253b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang return true; // handled 3263b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} 3273b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang 3283b2847fa5506dc265d2e46f067bfbb66ae209f74Chong Zhang} // namespace android 329