/* * Copyright 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "../../../config/TunerTestingConfigAidlReaderV1_0.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace aidl::android::hardware::tv::tuner; using namespace android::media::tuner::testing::configuration::V1_0; const int32_t FMQ_SIZE_4M = 0x400000; const int32_t FMQ_SIZE_16M = 0x1000000; #define FILTER_MAIN_TYPE_BIT_COUNT 5 #define STATUS_CHECK_INTERVAL_MS 100L // Hardware configs static map frontendMap; static map filterMap; static map dvrMap; static map lnbMap; static map timeFilterMap; static map> diseqcMsgMap; static map descramblerMap; // Hardware and test cases connections static LiveBroadcastHardwareConnections live; static ScanHardwareConnections scan; static DvrPlaybackHardwareConnections playback; static DvrRecordHardwareConnections record; static DescramblingHardwareConnections descrambling; static LnbLiveHardwareConnections lnbLive; static LnbRecordHardwareConnections lnbRecord; static TimeFilterHardwareConnections timeFilter; static LnbDescramblingHardwareConnections lnbDescrambling; /* * This function takes in a 2d vector of device Id's * The n vectors correlate to the ids for n different devices (eg frontends, filters) * The resultant 2d vector is every combination of id's with 1 id from each vector */ inline vector> generateIdCombinations(vector>& ids) { vector> combinations; // The index of each vector in ids that will be used in the next combination // EG {0, 2} means combo {ids[0][0] ids[1][2]} will be next const int size = static_cast(ids.size()); vector indexes_used_in_combination(size, 0); // The vector number from ids whose elements we will cycle through to make combinations. // First, start at the right most vector int cycled_vector = size - 1; while (cycled_vector >= 0) { // Make a combination (one at a time) vector combo; for (size_t i = 0; i < indexes_used_in_combination.size(); ++i) { const int combo_index = indexes_used_in_combination[i]; combo.push_back(ids[i][combo_index]); } combinations.push_back(combo); // Find the right most vector that still has space [elements left] to cycle through and // create a combination while (cycled_vector >= 0 && indexes_used_in_combination[cycled_vector] == ids[cycled_vector].size() - 1) { cycled_vector--; } // Use this check to avoid segmentation faults if (cycled_vector >= 0) { // Once found, we have a vector we can cycle through, so increase to its next element indexes_used_in_combination[cycled_vector]++; // Reset the other vectors to the right to their first element so we can cycle through // them again with the new element from cycled vector for (size_t i = cycled_vector + 1; i < indexes_used_in_combination.size(); ++i) { indexes_used_in_combination[i] = 0; } // all the vectors to the right were reset, so we can cycle through them again // Start at the furthest right vector cycled_vector = size - 1; } } return combinations; } /* * index 0 - playback dvr * index 1 - audio filters * index 2 - optional section filters */ static inline vector generatePlaybackCombinations() { vector combinations; vector sectionFilterIds_optional = sectionFilterIds; sectionFilterIds_optional.push_back(emptyHardwareId); vector> deviceIds{playbackDvrIds, audioFilterIds, sectionFilterIds_optional}; const int dvrIndex = 0; const int audioFilterIndex = 1; const int sectionFilterIndex = 2; auto idCombinations = generateIdCombinations(deviceIds); for (auto& combo : idCombinations) { DvrPlaybackHardwareConnections mPlayback; mPlayback.dvrId = combo[dvrIndex]; mPlayback.audioFilterId = combo[audioFilterIndex]; mPlayback.sectionFilterId = combo[sectionFilterIndex]; const int videoFilterIndex = find(audioFilterIds.begin(), audioFilterIds.end(), mPlayback.audioFilterId) - audioFilterIds.begin(); mPlayback.videoFilterId = videoFilterIds[videoFilterIndex]; combinations.push_back(mPlayback); } return combinations; } static inline vector generatePlaybackConfigs() { vector playback_configs; if (configuredPlayback) { ALOGD("Using DVR playback configuration provided."); playback_configs = {playback}; } else { ALOGD("Dvr playback not provided. Generating possible combinations. Consider adding it to " "the configuration file."); playback_configs = generatePlaybackCombinations(); } return playback_configs; } /* * index 0 - frontends * index 1 - audio filters * index 2 - lnbs */ static inline vector generateLnbLiveCombinations() { vector combinations; vector> deviceIds{frontendIds, audioFilterIds, lnbIds}; const int frontendIndex = 0; const int audioFilterIndex = 1; const int lnbIndex = 2; // TODO: Find a better way to vary diseqcMsgs, if at all auto idCombinations = generateIdCombinations(deviceIds); for (auto& combo : idCombinations) { const string feId = combo[frontendIndex]; auto type = frontendMap[feId].type; if (type == FrontendType::DVBS || type == FrontendType::ISDBS || type == FrontendType::ISDBS3) { LnbLiveHardwareConnections mLnbLive; mLnbLive.frontendId = feId; mLnbLive.audioFilterId = combo[audioFilterIndex]; const int videoFilterIndex = find(audioFilterIds.begin(), audioFilterIds.end(), mLnbLive.audioFilterId) - audioFilterIds.begin(); mLnbLive.videoFilterId = videoFilterIds[videoFilterIndex]; mLnbLive.lnbId = combo[lnbIndex]; mLnbLive.diseqcMsgs = diseqcMsgs; combinations.push_back(mLnbLive); } } return combinations; } static inline vector generateLnbLiveConfigurations() { vector lnbLive_configs; if (configuredLnbLive) { ALOGD("Using LnbLive configuration provided."); lnbLive_configs = {lnbLive}; } else { ALOGD("LnbLive not provided. Generating possible combinations. Consider adding it to the " "configuration file."); lnbLive_configs = generateLnbLiveCombinations(); } return lnbLive_configs; } static inline vector generateScanCombinations() { vector combinations; for (auto& id : frontendIds) { ScanHardwareConnections mScan; mScan.frontendId = id; combinations.push_back(mScan); } return combinations; } static inline vector generateScanConfigurations() { vector scan_configs; if (configuredScan) { ALOGD("Using scan configuration provided."); scan_configs = {scan}; } else { ALOGD("Scan not provided. Generating possible combinations. Consider adding it to " "the configuration file."); scan_configs = generateScanCombinations(); } return scan_configs; } /* * index 0 - frontends * index 1 - record filter * index 2 - Record Dvr * index 3 - Lnb */ static inline vector generateLnbRecordCombinations() { vector combinations; vector> deviceIds{frontendIds, recordFilterIds, recordDvrIds, lnbIds}; const int frontendIndex = 0; const int recordFilterIndex = 1; const int dvrIndex = 2; const int lnbIndex = 3; auto idCombinations = generateIdCombinations(deviceIds); // TODO : Find a better way to vary diseqcMsgs, if at all for (auto& combo : idCombinations) { const string feId = combo[frontendIndex]; auto type = frontendMap[feId].type; if (type == FrontendType::DVBS || type == FrontendType::ISDBS || type == FrontendType::ISDBS3) { LnbRecordHardwareConnections mLnbRecord; mLnbRecord.frontendId = feId; mLnbRecord.recordFilterId = combo[recordFilterIndex]; mLnbRecord.dvrRecordId = combo[dvrIndex]; mLnbRecord.lnbId = combo[lnbIndex]; mLnbRecord.diseqcMsgs = diseqcMsgs; combinations.push_back(mLnbRecord); } } return combinations; } static inline vector generateLnbRecordConfigurations() { vector lnbRecord_configs; if (configuredLnbRecord) { ALOGD("Using LnbRecord configuration provided."); lnbRecord_configs = {lnbRecord}; } else { ALOGD("LnbRecord not provided. Generating possible combinations. Consider adding it to " "the configuration file."); lnbRecord_configs = generateLnbRecordCombinations(); } return lnbRecord_configs; } /* * index 0 - decramblers * index 1 - frontends * index 2 - audio filters * index 3 - Dvr SW Fe Connections * index 4 - DVR Source Connections */ static inline vector generateDescramblingCombinations() { vector combinations; vector mfrontendIds = frontendIds; vector mDvrFeConnectionIds = playbackDvrIds; vector mDvrSourceConnectionIds = playbackDvrIds; // Add the empty hardware id to each vector to include combinations where these 3 fields might // be optional mfrontendIds.push_back(emptyHardwareId); mDvrFeConnectionIds.push_back(emptyHardwareId); mDvrSourceConnectionIds.push_back(emptyHardwareId); const int descramblerIndex = 0; const int frontendIndex = 1; const int audioFilterIndex = 2; const int dvrFeIdIndex = 3; const int dvrSourceIdIndex = 4; vector> deviceIds{descramblerIds, mfrontendIds, audioFilterIds, mDvrFeConnectionIds, mDvrSourceConnectionIds}; auto idCombinations = generateIdCombinations(deviceIds); for (auto& combo : idCombinations) { DescramblingHardwareConnections mDescrambling; const string feId = combo[frontendIndex]; const string dvrSwFeId = combo[dvrFeIdIndex]; const string dvrSourceId = combo[dvrSourceIdIndex]; mDescrambling.hasFrontendConnection = feId.compare(emptyHardwareId) == 0 ? false : true; if (!mDescrambling.hasFrontendConnection) { if (dvrSourceId.compare(emptyHardwareId) == 0) { // If combination does not have a frontend or dvr source connection, do not include // it continue; } } else { if (frontendMap[feId].isSoftwareFe && dvrSwFeId.compare(emptyHardwareId) == 0) { // If combination has a software frontend and no dvr->software frontend connection, // do not include it continue; } } if (dvrSwFeId.compare(dvrSourceId) == 0) { // If dvr->software frontend connection is the same as dvr source input to tuner, do not // include it. continue; } mDescrambling.frontendId = feId; mDescrambling.audioFilterId = combo[audioFilterIndex]; const int videoFilterIndex = find(audioFilterIds.begin(), audioFilterIds.end(), mDescrambling.audioFilterId) - audioFilterIds.begin(); mDescrambling.videoFilterId = videoFilterIds[videoFilterIndex]; mDescrambling.dvrSoftwareFeId = dvrSwFeId; mDescrambling.dvrSourceId = dvrSourceId; mDescrambling.descramblerId = combo[descramblerIndex]; combinations.push_back(mDescrambling); } return combinations; } static inline vector generateDescramblingConfigurations() { vector descrambling_configs; if (configuredDescrambling) { ALOGD("Using Descrambling configuration provided."); descrambling_configs = {descrambling}; } else { ALOGD("Descrambling not provided. Generating possible combinations. Consider adding it to " "the " "configuration file."); descrambling_configs = generateDescramblingCombinations(); } return descrambling_configs; } static inline vector generateTimeFilterCombinations() { vector combinations; for (auto& id : timeFilterIds) { TimeFilterHardwareConnections mTimeFilter; mTimeFilter.timeFilterId = id; combinations.push_back(mTimeFilter); } return combinations; } static inline vector generateTimeFilterConfigurations() { vector timeFilter_configs; if (configuredTimeFilter) { ALOGD("Using TimeFilter configuration provided."); timeFilter_configs = {timeFilter}; } else { ALOGD("TimeFilter not provided. Generating possible combinations. Consider adding it to " "the " "configuration file."); timeFilter_configs = generateTimeFilterCombinations(); } return timeFilter_configs; } /* * index 0 - frontends * index 1 - record dvrs * index 2 - record filters */ static inline vector generateRecordCombinations() { vector combinations; const int frontendIdIndex = 0; const int recordDvrIndex = 1; const int recordFilterIndex = 2; vector> deviceIds{frontendIds, recordDvrIds, recordFilterIds}; auto idCombinations = generateIdCombinations(deviceIds); for (auto& combo : idCombinations) { DvrRecordHardwareConnections mRecord; const string feId = combo[frontendIdIndex]; mRecord.hasFrontendConnection = true; if (frontendMap[feId].isSoftwareFe) { // If we have a software frontend, do not include configuration for testing. continue; } mRecord.frontendId = feId; mRecord.support = true; mRecord.dvrSourceId = emptyHardwareId; mRecord.dvrSoftwareFeId = emptyHardwareId; mRecord.recordFilterId = combo[recordFilterIndex]; mRecord.dvrRecordId = combo[recordDvrIndex]; combinations.push_back(mRecord); } return combinations; } static inline vector generateRecordConfigurations() { vector record_configs; if (configuredRecord) { ALOGD("Using Record configuration provided."); record_configs = {record}; } else { ALOGD("Record not provided. Generating possible combinations. Consider adding it to " "the " "configuration file."); record_configs = generateRecordCombinations(); } return record_configs; } /* * index 0 - frontends * index 1 - audio filters * index 2 - playback dvrs * index 3 - section Filters */ static inline vector generateLiveCombinations() { vector combinations; vector mSectionFilterIds = sectionFilterIds; vector mDvrSwConnectionIds = playbackDvrIds; // Adding the empty hardware id to cover cases where fields are optional mSectionFilterIds.push_back(emptyHardwareId); mDvrSwConnectionIds.push_back(emptyHardwareId); const int frontendIdIndex = 0; const int audioFilterIdIndex = 1; const int dvrSwConnectionIdIndex = 2; const int sectionFilterIdIndex = 3; vector> deviceIds{frontendIds, audioFilterIds, mDvrSwConnectionIds, mSectionFilterIds}; auto idCombinations = generateIdCombinations(deviceIds); for (auto& combo : idCombinations) { LiveBroadcastHardwareConnections mLive; const string feId = combo[frontendIdIndex]; const string dvrSwConnectionId = combo[dvrSwConnectionIdIndex]; mLive.hasFrontendConnection = true; if (frontendMap[feId].isSoftwareFe && dvrSwConnectionId.compare(emptyHardwareId) == 0) { // If the frontend is a software frontend and there is no dvr playback connected, do not // include configuration continue; } mLive.frontendId = feId; mLive.dvrSoftwareFeId = dvrSwConnectionId; mLive.audioFilterId = combo[audioFilterIdIndex]; const int videoFilterIdIndex = find(audioFilterIds.begin(), audioFilterIds.end(), mLive.audioFilterId) - audioFilterIds.begin(); mLive.videoFilterId = videoFilterIds[videoFilterIdIndex]; mLive.sectionFilterId = combo[sectionFilterIdIndex]; if (pcrFilterIds.empty()) { // If pcr Filters have not been provided, set it to empty hardware id mLive.pcrFilterId = emptyHardwareId; } else { // If pcr Filters have been provided, use the first index if there is only 1, or choose // the filter that corresponds to the correct audio and video filter pair const int pcrFilterIdIndex = pcrFilterIds.size() == 1 ? 0 : videoFilterIdIndex; mLive.pcrFilterId = pcrFilterIds[pcrFilterIdIndex]; } combinations.push_back(mLive); } return combinations; } static inline vector generateLiveConfigurations() { vector live_configs; if (configuredLive) { ALOGD("Using Live configuration provided."); live_configs = {live}; } else { ALOGD("Live not provided. Generating possible combinations. Consider adding it to " "the " "configuration file."); live_configs = generateLiveCombinations(); } return live_configs; } static inline vector generateLnbDescramblingCombinations() { vector combinations; vector> deviceIds{frontendIds, audioFilterIds, lnbIds, descramblerIds}; const int frontendIdIndex = 0; const int audioFilterIdIndex = 1; const int lnbIdIndex = 2; const int descramblerIdIndex = 3; auto idCombinations = generateIdCombinations(deviceIds); // TODO : Find a better way to vary diseqcMsgs, if at all for (auto& combo : idCombinations) { const string feId = combo[frontendIdIndex]; auto type = frontendMap[feId].type; if (type == FrontendType::DVBS || type == FrontendType::ISDBS || type == FrontendType::ISDBS3) { LnbDescramblingHardwareConnections mLnbDescrambling; mLnbDescrambling.support = true; mLnbDescrambling.frontendId = feId; mLnbDescrambling.audioFilterId = combo[audioFilterIdIndex]; const int videoFilterIdIndex = find(audioFilterIds.begin(), audioFilterIds.end(), mLnbDescrambling.audioFilterId) - audioFilterIds.begin(); mLnbDescrambling.videoFilterId = videoFilterIds[videoFilterIdIndex]; mLnbDescrambling.lnbId = combo[lnbIdIndex]; mLnbDescrambling.descramblerId = combo[descramblerIdIndex]; mLnbDescrambling.diseqcMsgs = diseqcMsgs; combinations.push_back(mLnbDescrambling); } } return combinations; } static inline vector generateLnbDescramblingConfigurations() { vector lnbDescrambling_configs; if (configuredLnbDescrambling) { ALOGD("Using LnbDescrambling configuration provided"); lnbDescrambling_configs = {lnbDescrambling}; } else { ALOGD("LnbDescrambling not provided. Generating possible combinations. Consider adding it " "to the configuration file."); lnbDescrambling_configs = generateLnbDescramblingCombinations(); } return lnbDescrambling_configs; } /** Config all the frontends that would be used in the tests */ inline void initFrontendConfig() { // The test will use the internal default fe when default fe is connected to any data flow // without overriding in the xml config. string defaultFeId = "FE_DEFAULT"; FrontendDvbtSettings dvbtSettings{ .frequency = 578000000, .transmissionMode = FrontendDvbtTransmissionMode::AUTO, .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ, .isHighPriority = true, }; frontendMap[defaultFeId].type = FrontendType::DVBT; frontendMap[defaultFeId].settings.set(dvbtSettings); vector types; types.push_back(FrontendStatusType::UEC); types.push_back(FrontendStatusType::IS_MISO); vector statuses; FrontendStatus status; status.set(4); statuses.push_back(status); status.set(true); statuses.push_back(status); frontendMap[defaultFeId].tuneStatusTypes = types; frontendMap[defaultFeId].expectTuneStatuses = statuses; frontendMap[defaultFeId].isSoftwareFe = true; frontendMap[defaultFeId].canConnectToCiCam = true; frontendMap[defaultFeId].ciCamId = 0; frontendMap[defaultFeId].supportBlindScan = true; FrontendDvbtSettings dvbt; dvbt.transmissionMode = FrontendDvbtTransmissionMode::MODE_8K_E; frontendMap[defaultFeId].settings.set(dvbt); // Read customized config TunerTestingConfigAidlReader1_0::readFrontendConfig1_0(frontendMap); }; inline void initFilterConfig() { // The test will use the internal default filter when default filter is connected to any // data flow without overriding in the xml config. string defaultAudioFilterId = "FILTER_AUDIO_DEFAULT"; string defaultVideoFilterId = "FILTER_VIDEO_DEFAULT"; filterMap[defaultVideoFilterId].type.mainType = DemuxFilterMainType::TS; filterMap[defaultVideoFilterId].type.subType.set( DemuxTsFilterType::VIDEO); filterMap[defaultVideoFilterId].bufferSize = FMQ_SIZE_16M; filterMap[defaultVideoFilterId].settings = DemuxFilterSettings::make(); filterMap[defaultVideoFilterId].settings.get().tpid = 256; DemuxFilterAvSettings video; video.isPassthrough = false; filterMap[defaultVideoFilterId] .settings.get() .filterSettings.set(video); filterMap[defaultVideoFilterId].monitorEventTypes = static_cast(DemuxFilterMonitorEventType::SCRAMBLING_STATUS) | static_cast(DemuxFilterMonitorEventType::IP_CID_CHANGE); filterMap[defaultVideoFilterId].streamType.set( VideoStreamType::MPEG1); filterMap[defaultAudioFilterId].type.mainType = DemuxFilterMainType::TS; filterMap[defaultAudioFilterId].type.subType.set( DemuxTsFilterType::AUDIO); filterMap[defaultAudioFilterId].bufferSize = FMQ_SIZE_16M; filterMap[defaultAudioFilterId].settings = DemuxFilterSettings::make(); filterMap[defaultAudioFilterId].settings.get().tpid = 256; DemuxFilterAvSettings audio; audio.isPassthrough = false; filterMap[defaultAudioFilterId] .settings.get() .filterSettings.set(audio); filterMap[defaultAudioFilterId].monitorEventTypes = static_cast(DemuxFilterMonitorEventType::SCRAMBLING_STATUS) | static_cast(DemuxFilterMonitorEventType::IP_CID_CHANGE); filterMap[defaultAudioFilterId].streamType.set(AudioStreamType::MP3); // Read customized config TunerTestingConfigAidlReader1_0::readFilterConfig1_0(filterMap); }; /** Config all the dvrs that would be used in the tests */ inline void initDvrConfig() { // Read customized config TunerTestingConfigAidlReader1_0::readDvrConfig1_0(dvrMap); }; inline void initTimeFilterConfig() { // Read customized config TunerTestingConfigAidlReader1_0::readTimeFilterConfig1_0(timeFilterMap); }; inline void initDescramblerConfig() { // Read customized config TunerTestingConfigAidlReader1_0::readDescramblerConfig1_0(descramblerMap); } inline void initLnbConfig() { // Read customized config TunerTestingConfigAidlReader1_0::readLnbConfig1_0(lnbMap); }; inline void initDiseqcMsgsConfig() { // Read customized config TunerTestingConfigAidlReader1_0::readDiseqcMessages(diseqcMsgMap); }; inline void determineScan() { if (!frontendMap.empty()) { scan.hasFrontendConnection = true; ALOGD("Can support scan"); } } inline void determineTimeFilter() { if (!timeFilterMap.empty()) { timeFilter.support = true; ALOGD("Can support time filter"); } } inline void determineDvrPlayback() { if (!playbackDvrIds.empty() && !audioFilterIds.empty() && !videoFilterIds.empty()) { playback.support = true; ALOGD("Can support dvr playback"); } } inline void determineLnbLive() { if (!audioFilterIds.empty() && !videoFilterIds.empty() && !frontendMap.empty() && !lnbMap.empty()) { lnbLive.support = true; ALOGD("Can support lnb live"); } } inline void determineLnbRecord() { if (!frontendMap.empty() && !recordFilterIds.empty() && !recordDvrIds.empty() && !lnbMap.empty()) { lnbRecord.support = true; ALOGD("Can support lnb record"); } } inline void determineLive() { if (videoFilterIds.empty() || audioFilterIds.empty() || frontendMap.empty()) { return; } if (!hasHwFe) { if (hasSwFe) { if (dvrMap.empty()) { ALOGD("Cannot configure Live. Only software frontends and no dvr connections."); return; } // Live is available if there is SW FE and some DVR is attached. } else { // We will arrive here because frontendMap won't be empty since // there will be at least a default frontend declared. But the // default frontend doesn't count as "hasSwFe". ALOGD("Cannot configure Live. No frontend declared at all."); return; } } ALOGD("Can support live"); live.hasFrontendConnection = true; } inline void determineDescrambling() { if (descramblerMap.empty() || audioFilterIds.empty() || videoFilterIds.empty()) { return; } if (frontendMap.empty() && playbackDvrIds.empty()) { ALOGD("Cannot configure descrambling. No frontends or playback dvr's"); return; } if (hasSwFe && !hasHwFe && playbackDvrIds.empty()) { ALOGD("cannot configure descrambling. Only SW frontends and no playback dvr's"); return; } ALOGD("Can support descrambling"); descrambling.support = true; } inline void determineDvrRecord() { if (recordDvrIds.empty() || recordFilterIds.empty()) { return; } if (frontendMap.empty() && playbackDvrIds.empty()) { ALOGD("Cannot support dvr record. No frontends and no playback dvr's"); return; } if (hasSwFe && !hasHwFe && playbackDvrIds.empty()) { ALOGD("Cannot support dvr record. Only SW frontends and no playback dvr's"); return; } ALOGD("Can support dvr record."); record.support = true; } inline void determineLnbDescrambling() { if (frontendIds.empty() || audioFilterIds.empty() || videoFilterIds.empty() || lnbIds.empty() || descramblerIds.empty()) { return; } ALOGD("Can support LnbDescrambling."); lnbDescrambling.support = true; } /** Read the vendor configurations of which hardware to use for each test cases/data flows */ inline void connectHardwaresToTestCases() { TunerTestingConfigAidlReader1_0::connectLiveBroadcast(live); TunerTestingConfigAidlReader1_0::connectScan(scan); TunerTestingConfigAidlReader1_0::connectDvrRecord(record); TunerTestingConfigAidlReader1_0::connectTimeFilter(timeFilter); TunerTestingConfigAidlReader1_0::connectDescrambling(descrambling); TunerTestingConfigAidlReader1_0::connectLnbLive(lnbLive); TunerTestingConfigAidlReader1_0::connectLnbRecord(lnbRecord); TunerTestingConfigAidlReader1_0::connectDvrPlayback(playback); TunerTestingConfigAidlReader1_0::connectLnbDescrambling(lnbDescrambling); }; inline void determineDataFlows() { determineScan(); determineTimeFilter(); determineDvrPlayback(); determineLnbLive(); determineLnbRecord(); determineLive(); determineDescrambling(); determineDvrRecord(); determineLnbDescrambling(); } inline bool validateConnections() { if (record.support && !record.hasFrontendConnection && record.dvrSourceId.compare(emptyHardwareId) == 0) { ALOGW("[vts config] Record must support either a DVR source or a Frontend source."); return false; } bool feIsValid = live.hasFrontendConnection ? frontendMap.find(live.frontendId) != frontendMap.end() : true; feIsValid &= scan.hasFrontendConnection ? frontendMap.find(scan.frontendId) != frontendMap.end() : true; feIsValid &= record.support && record.hasFrontendConnection ? frontendMap.find(record.frontendId) != frontendMap.end() : true; feIsValid &= descrambling.support && descrambling.hasFrontendConnection ? frontendMap.find(descrambling.frontendId) != frontendMap.end() : true; feIsValid &= lnbLive.support ? frontendMap.find(lnbLive.frontendId) != frontendMap.end() : true; feIsValid &= lnbRecord.support ? frontendMap.find(lnbRecord.frontendId) != frontendMap.end() : true; feIsValid &= lnbDescrambling.support ? frontendMap.find(lnbDescrambling.frontendId) != frontendMap.end() : true; if (!feIsValid) { ALOGW("[vts config] dynamic config fe connection is invalid."); return false; } bool dvrIsValid = frontendMap[live.frontendId].isSoftwareFe ? dvrMap.find(live.dvrSoftwareFeId) != dvrMap.end() : true; if (record.support) { if (record.hasFrontendConnection) { if (frontendMap[record.frontendId].isSoftwareFe) { dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end(); } } else { dvrIsValid &= dvrMap.find(record.dvrSourceId) != dvrMap.end(); } dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end(); } if (descrambling.support) { if (descrambling.hasFrontendConnection) { if (frontendMap[descrambling.frontendId].isSoftwareFe) { dvrIsValid &= dvrMap.find(descrambling.dvrSoftwareFeId) != dvrMap.end(); } } else { dvrIsValid &= dvrMap.find(descrambling.dvrSourceId) != dvrMap.end(); } } dvrIsValid &= lnbRecord.support ? dvrMap.find(lnbRecord.dvrRecordId) != dvrMap.end() : true; dvrIsValid &= playback.support ? dvrMap.find(playback.dvrId) != dvrMap.end() : true; if (!dvrIsValid) { ALOGW("[vts config] dynamic config dvr connection is invalid."); return false; } bool filterIsValid = (live.hasFrontendConnection) ? filterMap.find(live.audioFilterId) != filterMap.end() && filterMap.find(live.videoFilterId) != filterMap.end() : true; filterIsValid &= record.support ? filterMap.find(record.recordFilterId) != filterMap.end() : true; filterIsValid &= descrambling.support ? filterMap.find(descrambling.videoFilterId) != filterMap.end() && filterMap.find(descrambling.audioFilterId) != filterMap.end() : true; for (auto& filterId : descrambling.extraFilters) { filterIsValid &= filterMap.find(filterId) != filterMap.end(); } filterIsValid &= lnbLive.support ? filterMap.find(lnbLive.audioFilterId) != filterMap.end() && filterMap.find(lnbLive.videoFilterId) != filterMap.end() : true; filterIsValid &= lnbRecord.support ? filterMap.find(lnbRecord.recordFilterId) != filterMap.end() : true; for (auto& filterId : lnbRecord.extraFilters) { filterIsValid &= filterMap.find(filterId) != filterMap.end(); } for (auto& filterId : lnbLive.extraFilters) { filterIsValid &= filterMap.find(filterId) != filterMap.end(); } filterIsValid &= playback.support ? filterMap.find(playback.audioFilterId) != filterMap.end() && filterMap.find(playback.videoFilterId) != filterMap.end() : true; filterIsValid &= playback.sectionFilterId.compare(emptyHardwareId) == 0 ? true : filterMap.find(playback.sectionFilterId) != filterMap.end(); for (auto& filterId : playback.extraFilters) { filterIsValid &= playback.hasExtraFilters ? filterMap.find(filterId) != filterMap.end() : true; } filterIsValid &= lnbDescrambling.support ? filterMap.find(lnbDescrambling.audioFilterId) != filterMap.end() && filterMap.find(lnbDescrambling.videoFilterId) != filterMap.end() : true; if (!filterIsValid) { ALOGW("[vts config] dynamic config filter connection is invalid."); return false; } if (audioFilterIds.size() != videoFilterIds.size()) { ALOGW("[vts config] the number of audio and video filters should be equal"); return false; } if (!pcrFilterIds.empty() && pcrFilterIds.size() != 1 && pcrFilterIds.size() != audioFilterIds.size()) { ALOGW("[vts config] When more than 1 pcr filter is configured, the number of pcr filters " "must equal the number of audio and video filters."); return false; } bool timeFilterIsValid = timeFilter.support ? timeFilterMap.find(timeFilter.timeFilterId) != timeFilterMap.end() : true; if (!timeFilterIsValid) { ALOGW("[vts config] dynamic config time filter connection is invalid."); } bool descramblerIsValid = descrambling.support ? descramblerMap.find(descrambling.descramblerId) != descramblerMap.end() : true; descramblerIsValid &= lnbDescrambling.support ? descramblerMap.find(lnbDescrambling.descramblerId) != descramblerMap.end() : true; if (!descramblerIsValid) { ALOGW("[vts config] dynamic config descrambler connection is invalid."); return false; } bool lnbIsValid = lnbLive.support ? lnbMap.find(lnbLive.lnbId) != lnbMap.end() : true; lnbIsValid &= lnbRecord.support ? lnbMap.find(lnbRecord.lnbId) != lnbMap.end() : true; lnbIsValid &= lnbDescrambling.support ? lnbMap.find(lnbDescrambling.lnbId) != lnbMap.end() : true; if (!lnbIsValid) { ALOGW("[vts config] dynamic config lnb connection is invalid."); return false; } bool diseqcMsgsIsValid = true; for (auto& msg : lnbRecord.diseqcMsgs) { diseqcMsgsIsValid &= diseqcMsgMap.find(msg) != diseqcMsgMap.end(); } for (auto& msg : lnbLive.diseqcMsgs) { diseqcMsgsIsValid &= diseqcMsgMap.find(msg) != diseqcMsgMap.end(); } for (auto& msg : lnbDescrambling.diseqcMsgs) { diseqcMsgsIsValid &= diseqcMsgMap.find(msg) != diseqcMsgMap.end(); } if (!diseqcMsgsIsValid) { ALOGW("[vts config] dynamic config diseqcMsg is invalid."); return false; } return true; }