From 73b18ac9abebbb8a85fa4e787b918c804c4ab98c Mon Sep 17 00:00:00 2001 From: Kensuke Miyagi Date: Mon, 7 Nov 2022 10:49:09 -0800 Subject: [PATCH] Enable support for main type cap aware demux management Adding 3 ITuner.aidl APIs: - int[] getDemuxIds(); - IDemux openDemuxById(in int demuxId); - DemuxInfo getDemuxInfo(in int demuxId); And adding DemuxInfo.aidl. Bug: 239211919 Bug: 239227510 Test: atest VtsHalTvTunerTargetTest Change-Id: Icd34cc974a6f6fa167d90b69b3ff0a119bf50ae8 --- .../android/hardware/tv/tuner/DemuxInfo.aidl | 39 ++++++++ .../android/hardware/tv/tuner/ITuner.aidl | 3 + .../android/hardware/tv/tuner/DemuxInfo.aidl | 31 +++++++ .../android/hardware/tv/tuner/ITuner.aidl | 31 ++++++- tv/tuner/aidl/default/Demux.cpp | 22 ++++- tv/tuner/aidl/default/Demux.h | 11 ++- tv/tuner/aidl/default/Tuner.cpp | 93 +++++++++++++++++-- tv/tuner/aidl/default/Tuner.h | 10 +- tv/tuner/aidl/vts/functional/DemuxTests.cpp | 23 ++++- tv/tuner/aidl/vts/functional/DemuxTests.h | 4 + .../functional/VtsHalTvTunerTargetTest.cpp | 28 ++++++ 11 files changed, 276 insertions(+), 19 deletions(-) create mode 100644 tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl create mode 100644 tv/tuner/aidl/android/hardware/tv/tuner/DemuxInfo.aidl diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl new file mode 100644 index 0000000000..872d9634d1 --- /dev/null +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxInfo.aidl @@ -0,0 +1,39 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.tv.tuner; +/* @hide */ +@VintfStability +parcelable DemuxInfo { + int filterTypes = 0; +} diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl index 5d1d21513e..732f3fd952 100644 --- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl +++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl @@ -48,4 +48,7 @@ interface ITuner { void setMaxNumberOfFrontends(in android.hardware.tv.tuner.FrontendType frontendType, in int maxNumber); int getMaxNumberOfFrontends(in android.hardware.tv.tuner.FrontendType frontendType); boolean isLnaSupported(); + int[] getDemuxIds(); + android.hardware.tv.tuner.IDemux openDemuxById(in int demuxId); + android.hardware.tv.tuner.DemuxInfo getDemuxInfo(in int demuxId); } diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxInfo.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxInfo.aidl new file mode 100644 index 0000000000..2720e2137e --- /dev/null +++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxInfo.aidl @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package android.hardware.tv.tuner; + +import android.hardware.tv.tuner.DemuxFilterMainType; + +/** + * Information for the Demux. + * @hide + */ +@VintfStability +parcelable DemuxInfo { + /** + * Bitwise OR of DemuxFilterMainTypes + */ + int filterTypes = DemuxFilterMainType.UNDEFINED; +} diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl index 4a0b7a23ee..9ead7dddf9 100644 --- a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl +++ b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl @@ -17,6 +17,7 @@ package android.hardware.tv.tuner; import android.hardware.tv.tuner.DemuxCapabilities; +import android.hardware.tv.tuner.DemuxInfo; import android.hardware.tv.tuner.FrontendInfo; import android.hardware.tv.tuner.FrontendType; import android.hardware.tv.tuner.IDemux; @@ -65,7 +66,7 @@ interface ITuner { IDemux openDemux(out int[] demuxId); /** - * Retrieve the Demux's Capabilities. + * Retrieve the system wide Demux's Capabilities * * @return the Demux's Capabilities. */ @@ -158,4 +159,32 @@ interface ITuner { * @return true if supported, otherwise false */ boolean isLnaSupported(); + + /** + * Get Demux IDs + * + * It is used by the client to get all available demuxes' IDs. + * + * @return an array of IDs for the available Demuxes. + */ + int[] getDemuxIds(); + + /** + * Create a new instance of Demux given a demuxId. + * + * It is used by the client to create a demux instance. + * + * @param demuxId the id of the demux to be opened. + * + * @return the newly created demux interface. + */ + IDemux openDemuxById(in int demuxId); + + /** + * Retrieve the DemuxInfo of the specified Demux. + * + * @param demuxId the demux ID to query the DemuxInfo for. + * @return the DemuxInfo of the specified Demux by demuxId. + */ + DemuxInfo getDemuxInfo(in int demuxId); } diff --git a/tv/tuner/aidl/default/Demux.cpp b/tv/tuner/aidl/default/Demux.cpp index 60fd89981b..11e7131220 100644 --- a/tv/tuner/aidl/default/Demux.cpp +++ b/tv/tuner/aidl/default/Demux.cpp @@ -31,8 +31,12 @@ namespace tuner { #define WAIT_TIMEOUT 3000000000 -Demux::Demux(int32_t demuxId, std::shared_ptr tuner) { +Demux::Demux(int32_t demuxId, uint32_t filterTypes) { mDemuxId = demuxId; + mFilterTypes = filterTypes; +} + +void Demux::setTunerService(std::shared_ptr tuner) { mTuner = tuner; } @@ -346,6 +350,22 @@ uint16_t Demux::getFilterTpid(int64_t filterId) { return mFilters[filterId]->getTpid(); } +int32_t Demux::getDemuxId() { + return mDemuxId; +} + +bool Demux::isInUse() { + return mInUse; +} + +void Demux::setInUse(bool inUse) { + mInUse = inUse; +} + +void Demux::getDemuxInfo(DemuxInfo* demuxInfo) { + *demuxInfo = {.filterTypes = mFilterTypes}; +} + void Demux::startFrontendInputLoop() { ALOGD("[Demux] start frontend on demux"); // Stop current Frontend thread loop first, in case the user starts a new diff --git a/tv/tuner/aidl/default/Demux.h b/tv/tuner/aidl/default/Demux.h index 7f0b0a7d62..7d7aee4c89 100644 --- a/tv/tuner/aidl/default/Demux.h +++ b/tv/tuner/aidl/default/Demux.h @@ -53,7 +53,7 @@ class Tuner; class Demux : public BnDemux { public: - Demux(int32_t demuxId, std::shared_ptr tuner); + Demux(int32_t demuxId, uint32_t filterTypes); ~Demux(); ::ndk::ScopedAStatus setFrontendDataSource(int32_t in_frontendId) override; @@ -98,6 +98,12 @@ class Demux : public BnDemux { void sendFrontendInputToRecord(vector data, uint16_t pid, uint64_t pts); bool startRecordFilterDispatcher(); + void getDemuxInfo(DemuxInfo* demuxInfo); + int32_t getDemuxId(); + bool isInUse(); + void setInUse(bool inUse); + void setTunerService(std::shared_ptr tuner); + private: // Tuner service std::shared_ptr mTuner; @@ -183,6 +189,9 @@ class Demux : public BnDemux { vector mPesOutput; const bool DEBUG_DEMUX = false; + + int32_t mFilterTypes; + bool mInUse = false; }; } // namespace tuner diff --git a/tv/tuner/aidl/default/Tuner.cpp b/tv/tuner/aidl/default/Tuner.cpp index 8c715a0e12..0c1ae2da8a 100644 --- a/tv/tuner/aidl/default/Tuner.cpp +++ b/tv/tuner/aidl/default/Tuner.cpp @@ -17,6 +17,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "android.hardware.tv.tuner-service.example-Tuner" +#include #include #include @@ -60,6 +61,16 @@ void Tuner::init() { mMaxUsableFrontends[FrontendType::ISDBS3] = 1; mMaxUsableFrontends[FrontendType::DTMB] = 1; + mDemuxes[0] = + ndk::SharedRefBase::make(0, (static_cast(DemuxFilterMainType::TS) | + static_cast(DemuxFilterMainType::MMTP) | + static_cast(DemuxFilterMainType::TLV))); + mDemuxes[1] = + ndk::SharedRefBase::make(1, (static_cast(DemuxFilterMainType::MMTP) | + static_cast(DemuxFilterMainType::TLV))); + mDemuxes[2] = ndk::SharedRefBase::make(2, static_cast(DemuxFilterMainType::IP)); + mDemuxes[3] = ndk::SharedRefBase::make(3, static_cast(DemuxFilterMainType::TS)); + mLnbs.resize(2); mLnbs[0] = ndk::SharedRefBase::make(0); mLnbs[1] = ndk::SharedRefBase::make(1); @@ -78,6 +89,28 @@ Tuner::~Tuner() {} return ::ndk::ScopedAStatus::ok(); } +::ndk::ScopedAStatus Tuner::getDemuxInfo(int32_t in_demuxId, DemuxInfo* _aidl_return) { + if (mDemuxes.find(in_demuxId) == mDemuxes.end()) { + return ::ndk::ScopedAStatus::fromServiceSpecificError( + static_cast(Result::INVALID_ARGUMENT)); + } else { + mDemuxes[in_demuxId]->getDemuxInfo(_aidl_return); + return ::ndk::ScopedAStatus::ok(); + } +} + +::ndk::ScopedAStatus Tuner::getDemuxIds(std::vector* _aidl_return) { + ALOGV("%s", __FUNCTION__); + + int numOfDemuxes = mDemuxes.size(); + _aidl_return->resize(numOfDemuxes); + int i = 0; + for (auto e = mDemuxes.begin(); e != mDemuxes.end(); e++) { + (*_aidl_return)[i++] = e->first; + } + return ::ndk::ScopedAStatus::ok(); +} + ::ndk::ScopedAStatus Tuner::openFrontendById(int32_t in_frontendId, std::shared_ptr* _aidl_return) { ALOGV("%s", __FUNCTION__); @@ -94,17 +127,49 @@ Tuner::~Tuner() {} return ::ndk::ScopedAStatus::ok(); } +::ndk::ScopedAStatus Tuner::openDemuxById(int32_t in_demuxId, + std::shared_ptr* _aidl_return) { + ALOGV("%s", __FUNCTION__); + + if (mDemuxes.find(in_demuxId) == mDemuxes.end()) { + ALOGW("[ WARN ] Demux with id %d isn't available", in_demuxId); + *_aidl_return = nullptr; + return ::ndk::ScopedAStatus::fromServiceSpecificError( + static_cast(Result::INVALID_ARGUMENT)); + } + + if (mDemuxes[in_demuxId]->isInUse()) { + return ::ndk::ScopedAStatus::fromServiceSpecificError( + static_cast(Result::UNAVAILABLE)); + } else { + mDemuxes[in_demuxId]->setTunerService(this->ref()); + mDemuxes[in_demuxId]->setInUse(true); + + *_aidl_return = mDemuxes[in_demuxId]; + return ::ndk::ScopedAStatus::ok(); + } +} + ::ndk::ScopedAStatus Tuner::openDemux(std::vector* out_demuxId, std::shared_ptr* _aidl_return) { ALOGV("%s", __FUNCTION__); - mLastUsedId += 1; - mDemuxes[mLastUsedId] = ndk::SharedRefBase::make(mLastUsedId, this->ref()); + bool found = false; + int32_t demuxId = 0; + for (auto e = mDemuxes.begin(); e != mDemuxes.end(); e++) { + if (!e->second->isInUse()) { + found = true; + demuxId = e->second->getDemuxId(); + } + } - out_demuxId->push_back(mLastUsedId); - *_aidl_return = mDemuxes[mLastUsedId]; - - return ::ndk::ScopedAStatus::ok(); + if (found) { + out_demuxId->push_back(demuxId); + return openDemuxById(demuxId, _aidl_return); + } else { + return ::ndk::ScopedAStatus::fromServiceSpecificError( + static_cast(Result::UNAVAILABLE)); + } } ::ndk::ScopedAStatus Tuner::getDemuxCaps(DemuxCapabilities* _aidl_return) { @@ -115,6 +180,18 @@ Tuner::~Tuner() {} // Support time filter testing _aidl_return->bTimeFilter = true; + // set filterCaps as the bitwize OR of all the demux' caps + std::vector demuxIds; + getDemuxIds(&demuxIds); + int32_t filterCaps = 0; + + for (int i = 0; i < demuxIds.size(); i++) { + DemuxInfo demuxInfo; + getDemuxInfo(demuxIds[i], &demuxInfo); + filterCaps |= demuxInfo.filterTypes; + } + _aidl_return->filterCaps = filterCaps; + return ::ndk::ScopedAStatus::ok(); } @@ -250,13 +327,13 @@ void Tuner::removeDemux(int32_t demuxId) { break; } } - mDemuxes.erase(demuxId); + mDemuxes[demuxId]->setInUse(false); } void Tuner::removeFrontend(int32_t frontendId) { map::iterator it = mFrontendToDemux.find(frontendId); if (it != mFrontendToDemux.end()) { - mDemuxes.erase(it->second); + mDemuxes[it->second]->setInUse(false); } mFrontendToDemux.erase(frontendId); } diff --git a/tv/tuner/aidl/default/Tuner.h b/tv/tuner/aidl/default/Tuner.h index a77c9304a1..26569336ef 100644 --- a/tv/tuner/aidl/default/Tuner.h +++ b/tv/tuner/aidl/default/Tuner.h @@ -46,7 +46,11 @@ class Tuner : public BnTuner { std::shared_ptr* _aidl_return) override; ::ndk::ScopedAStatus openDemux(std::vector* out_demuxId, std::shared_ptr* _aidl_return) override; + ::ndk::ScopedAStatus openDemuxById(int32_t in_demuxId, + std::shared_ptr* _aidl_return) override; ::ndk::ScopedAStatus getDemuxCaps(DemuxCapabilities* _aidl_return) override; + ::ndk::ScopedAStatus getDemuxInfo(int32_t in_demuxId, DemuxInfo* _aidl_return) override; + ::ndk::ScopedAStatus getDemuxIds(std::vector* _aidl_return) override; ::ndk::ScopedAStatus openDescrambler(std::shared_ptr* _aidl_return) override; ::ndk::ScopedAStatus getFrontendInfo(int32_t in_frontendId, FrontendInfo* _aidl_return) override; @@ -77,12 +81,10 @@ class Tuner : public BnTuner { // Static mFrontends array to maintain local frontends information map> mFrontends; map mFrontendToDemux; - map> mDemuxes; + map> mDemuxes; // use demuxId as the key in + // this sample implementation // To maintain how many Frontends we have int mFrontendSize; - // The last used demux id. Initial value is -1. - // First used id will be 0. - int32_t mLastUsedId = -1; vector> mLnbs; map mMaxUsableFrontends; }; diff --git a/tv/tuner/aidl/vts/functional/DemuxTests.cpp b/tv/tuner/aidl/vts/functional/DemuxTests.cpp index 9de01e1eab..b2fca6f7f1 100644 --- a/tv/tuner/aidl/vts/functional/DemuxTests.cpp +++ b/tv/tuner/aidl/vts/functional/DemuxTests.cpp @@ -16,6 +16,12 @@ #include "DemuxTests.h" +AssertionResult DemuxTests::getDemuxIds(std::vector& demuxIds) { + ndk::ScopedAStatus status; + status = mService->getDemuxIds(&demuxIds); + return AssertionResult(status.isOk()); +} + AssertionResult DemuxTests::openDemux(std::shared_ptr& demux, int32_t& demuxId) { std::vector id; auto status = mService->openDemux(&id, &mDemux); @@ -26,6 +32,14 @@ AssertionResult DemuxTests::openDemux(std::shared_ptr& demux, int32_t& d return AssertionResult(status.isOk()); } +AssertionResult DemuxTests::openDemuxById(int32_t demuxId, std::shared_ptr& demux) { + auto status = mService->openDemuxById(demuxId, &mDemux); + if (status.isOk()) { + demux = mDemux; + } + return AssertionResult(status.isOk()); +} + AssertionResult DemuxTests::setDemuxFrontendDataSource(int32_t frontendId) { EXPECT_TRUE(mDemux) << "Test with openDemux first."; auto status = mDemux->setFrontendDataSource(frontendId); @@ -33,14 +47,15 @@ AssertionResult DemuxTests::setDemuxFrontendDataSource(int32_t frontendId) { } AssertionResult DemuxTests::getDemuxCaps(DemuxCapabilities& demuxCaps) { - if (!mDemux) { - ALOGW("[vts] Test with openDemux first."); - return failure(); - } auto status = mService->getDemuxCaps(&demuxCaps); return AssertionResult(status.isOk()); } +AssertionResult DemuxTests::getDemuxInfo(int32_t demuxId, DemuxInfo& demuxInfo) { + auto status = mService->getDemuxInfo(demuxId, &demuxInfo); + return AssertionResult(status.isOk()); +} + AssertionResult DemuxTests::getAvSyncId(std::shared_ptr filter, int32_t& avSyncHwId) { EXPECT_TRUE(mDemux) << "Demux is not opened yet."; diff --git a/tv/tuner/aidl/vts/functional/DemuxTests.h b/tv/tuner/aidl/vts/functional/DemuxTests.h index 7698de33b3..b58cf70823 100644 --- a/tv/tuner/aidl/vts/functional/DemuxTests.h +++ b/tv/tuner/aidl/vts/functional/DemuxTests.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include #include @@ -32,11 +33,14 @@ class DemuxTests { public: void setService(std::shared_ptr tuner) { mService = tuner; } + AssertionResult getDemuxIds(std::vector& demuxIds); AssertionResult openDemux(std::shared_ptr& demux, int32_t& demuxId); + AssertionResult openDemuxById(int32_t demuxId, std::shared_ptr& demux); AssertionResult setDemuxFrontendDataSource(int32_t frontendId); AssertionResult getAvSyncId(std::shared_ptr filter, int32_t& avSyncHwId); AssertionResult getAvSyncTime(int32_t avSyncId); AssertionResult getDemuxCaps(DemuxCapabilities& demuxCaps); + AssertionResult getDemuxInfo(int32_t demuxId, DemuxInfo& demuxInfo); AssertionResult closeDemux(); protected: diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp index 6aa1e162cf..9db82c893d 100644 --- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp +++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp @@ -695,6 +695,34 @@ TEST_P(TunerDemuxAidlTest, openDemux) { } } +TEST_P(TunerDemuxAidlTest, openDemuxById) { + description("Open (with id) and close a Demux."); + std::vector demuxIds; + ASSERT_TRUE(mDemuxTests.getDemuxIds(demuxIds)); + for (int i = 0; i < demuxIds.size(); i++) { + std::shared_ptr demux; + ASSERT_TRUE(mDemuxTests.openDemuxById(demuxIds[i], demux)); + ASSERT_TRUE(mDemuxTests.closeDemux()); + } +} + +TEST_P(TunerDemuxAidlTest, getDemuxInfo) { + description("Check getDemuxInfo against demux caps"); + std::vector demuxIds; + ASSERT_TRUE(mDemuxTests.getDemuxIds(demuxIds)); + int32_t combinedFilterTypes = 0; + for (int i = 0; i < demuxIds.size(); i++) { + DemuxInfo demuxInfo; + ASSERT_TRUE(mDemuxTests.getDemuxInfo(demuxIds[i], demuxInfo)); + combinedFilterTypes |= demuxInfo.filterTypes; + } + if (demuxIds.size() > 0) { + DemuxCapabilities demuxCaps; + ASSERT_TRUE(mDemuxTests.getDemuxCaps(demuxCaps)); + ASSERT_TRUE(demuxCaps.filterCaps == combinedFilterTypes); + } +} + TEST_P(TunerDemuxAidlTest, getAvSyncTime) { description("Get the A/V sync time from a PCR filter."); if (!live.hasFrontendConnection) {