Merge "Adds non reader/writer based HAL 2.4 tests for AIDL composer3"
diff --git a/audio/core/all-versions/vts/functional/7.0/Generators.cpp b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
index d2ba339..8c92cbd 100644
--- a/audio/core/all-versions/vts/functional/7.0/Generators.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/Generators.cpp
@@ -102,6 +102,9 @@
if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile
auto [flags, isOffload] = generateOutFlags(mixPort);
for (const auto& profile : mixPort.getProfile()) {
+ if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+ !profile.hasChannelMasks())
+ continue;
auto configs = combineAudioConfig(profile.getChannelMasks(),
profile.getSamplingRates(), profile.getFormat());
for (auto& config : configs) {
@@ -231,6 +234,9 @@
std::back_inserter(flags), [](auto flag) { return toString(flag); });
}
for (const auto& profile : mixPort.getProfile()) {
+ if (!profile.hasFormat() || !profile.hasSamplingRates() ||
+ !profile.hasChannelMasks())
+ continue;
auto configs = combineAudioConfig(profile.getChannelMasks(),
profile.getSamplingRates(), profile.getFormat());
for (const auto& config : configs) {
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 7c25c23..b99ed43 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -245,6 +245,7 @@
data: [
"tests/apm_config_no_vx_7_0.xml",
"tests/apm_config_with_vx_7_0.xml",
+ "tests/apm_config_b_204314749_7_0.xml",
],
test_config: "tests/HalAudioV7_0GeneratorTest.xml",
}
diff --git a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
index 2e79455..3dc5b33 100644
--- a/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
+++ b/audio/core/all-versions/vts/functional/tests/HalAudioV7_0GeneratorTest.xml
@@ -24,6 +24,7 @@
<option name="cleanup" value="true" />
<option name="push" value="apm_config_no_vx_7_0.xml->/data/local/tmp/apm_config_no_vx.xml" />
<option name="push" value="apm_config_with_vx_7_0.xml->/data/local/tmp/apm_config_with_vx.xml" />
+ <option name="push" value="apm_config_b_204314749_7_0.xml->/data/local/tmp/apm_config_b_204314749_7_0.xml" />
<option name="push" value="HalAudioV7_0GeneratorTest->/data/local/tmp/HalAudioV7_0GeneratorTest" />
</target_preparer>
diff --git a/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
new file mode 100644
index 0000000..5bdca9a
--- /dev/null
+++ b/audio/core/all-versions/vts/functional/tests/apm_config_b_204314749_7_0.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+ <!-- version section contains a “version” tag in the form “major.minor” e.g. version=”1.0” -->
+
+ <!-- Global configuration Decalaration -->
+ <globalConfiguration speaker_drc_enabled="false"/>
+
+
+ <!-- Modules section:
+ There is one section per audio HW module present on the platform.
+ Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
+ The module names are the same as in current .conf file:
+ “primary”, “A2DP”, “remote_submix”, “USB”
+ Each module will contain the following sections:
+ “devicePorts”: a list of device descriptors for all input and output devices accessible via this
+ module.
+ This contains both permanently attached devices and removable devices.
+ “mixPorts”: listing all output and input streams exposed by the audio HAL
+ “routes”: list of possible connections between input and output devices or between stream and
+ devices.
+ "route": is defined by an attribute:
+ -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
+ -"sink": the sink involved in this route
+ -"sources": all the sources than can be connected to the sink via vis route
+ “attachedDevices”: permanently attached devices.
+ The attachedDevices section is a list of devices names. The names correspond to device names
+ defined in <devicePorts> section.
+ “defaultOutputDevice”: device to be used by default when no policy rule applies
+ -->
+ <modules>
+ <!-- Primary Audio HAL -->
+ <module name="primary" halVersion="3.0">
+ <attachedDevices>
+ <item>Speaker</item>
+ <item>Built-In Mic</item>
+ <item>Built-In Back Mic</item>
+ <item>Echo Reference</item>
+ <item>Tuner</item>
+ </attachedDevices>
+ <defaultOutputDevice>Speaker</defaultOutputDevice>
+ <mixPorts>
+ <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="tunnel pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="direct pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="tunnel direct output" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
+ <mixPort name="primary input" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="tunnel a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_HW_AV_SYNC">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="direct a2dp" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
+ <profile name=""/>
+ </mixPort>
+ <mixPort name="echo reference" role="sink">
+ <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="built-in mic" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="16000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/>
+ </mixPort>
+ <mixPort name="ble_in" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ </mixPorts>
+ <devicePorts>
+ <!-- Output devices declaration, i.e. Sink DEVICE PORT -->
+ <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER">
+ <gains>
+ <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-10000"
+ maxValueMB="0"
+ defaultValueMB="-6000"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="HDMI Out" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink">
+ </devicePort>
+ <devicePort tagName="Tuner" role="source" type="AUDIO_DEVICE_IN_TV_TUNER">
+ <gains>
+ <gain name="gain_1" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-10000"
+ maxValueMB="0"
+ defaultValueMB="-6000"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
+ <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="Wired Headphones" type="AUDIO_DEVICE_OUT_WIRED_HEADPHONE" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_OUT_MONO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="44100"
+ channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </devicePort>
+
+ <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source" address="top">
+ <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK"/>
+ </devicePort>
+ <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ <devicePort tagName="Echo Reference" type="AUDIO_DEVICE_IN_ECHO_REFERENCE" role="source">
+ <profile name="echo_reference" format="AUDIO_FORMAT_PCM_32_BIT"
+ samplingRates="48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
+ </devicePort>
+ <devicePort tagName="BLE-In" type="AUDIO_DEVICE_IN_BLUETOOTH_BLE" role="source">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="16000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </devicePort>
+ </devicePorts>
+ <!-- route declaration, i.e. list all available sources for a given sink -->
+ <routes>
+ <route type="mix" sink="HDMI Out"
+ sources="primary output,tunnel pcm,direct output,Tuner,mmap_no_irq_out,tunnel direct output"/>
+ <route type="mix" sink="Speaker"
+ sources="primary output,tunnel pcm,direct pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT SCO"
+ sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT SCO Headset"
+ sources="primary output,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="Wired Headset"
+ sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="Wired Headphones"
+ sources="primary output,tunnel pcm,BT SCO Headset Mic,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="primary input"
+ sources="Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic,Tuner"/>
+ <route type="mix" sink="BT A2DP Out"
+ sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT A2DP Headphones"
+ sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="BT A2DP Speaker"
+ sources="primary output,tunnel a2dp,direct a2dp,Tuner,mmap_no_irq_out"/>
+ <route type="mix" sink="echo reference"
+ sources="Echo Reference"/>
+ <route type="mix" sink="built-in mic"
+ sources="Built-In Mic"/>
+ <route type="mix" sink="ble_in"
+ sources="BLE-In"/>
+ </routes>
+
+ </module>
+
+ <!-- A2dp Audio HAL -->
+ <!-- <xi:include href="a2dp_audio_policy_configuration.xml"/> -->
+
+ <!-- Usb Audio HAL -->
+ <!-- <xi:include href="usb_audio_policy_configuration.xml"/> -->
+
+ <!-- Remote Submix Audio HAL -->
+ <!-- <xi:include href="r_submix_audio_policy_configuration.xml"/> -->
+
+ <!-- Hearing aid Audio HAL -->
+ <!-- <xi:include href="hearing_aid_audio_policy_configuration.xml"/> -->
+
+ <!-- MSD Audio HAL (optional) -->
+ <!-- <xi:include href="msd_audio_policy_configuration.xml"/> -->
+
+ </modules>
+ <!-- End of Modules section -->
+
+ <!-- Volume section -->
+
+ <!-- <xi:include href="audio_policy_volumes.xml"/> -->
+ <!-- <xi:include href="default_volume_tables.xml"/> -->
+
+ <!-- End of Volume section -->
+
+ <!-- Surround Sound configuration -->
+
+ <surroundSound>
+ <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+ There must be a corresponding Java ENCODING_... constant defined in AudioFormat.java,
+ and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+ need a dedicated Surrond Settings dialog entry, a subformats list has to be used. -->
+ <formats>
+ <format name="AUDIO_FORMAT_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3_JOC" />
+ <format name="AUDIO_FORMAT_DTS" />
+ </formats>
+ </surroundSound>
+
+ <!-- End of Surround Sound configuration -->
+
+</audioPolicyConfiguration>
diff --git a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
index 583ff01..7caa712 100644
--- a/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
+++ b/audio/core/all-versions/vts/functional/tests/generators_tests.cpp
@@ -128,5 +128,11 @@
}
// Target file names are the same for all versions, see 'HalAudioVx_0GeneratorTest.xml' test configs
+// clang-format off
INSTANTIATE_TEST_SUITE_P(Generators, GeneratorsTest,
- ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"));
+ ::testing::Values("apm_config_no_vx.xml", "apm_config_with_vx.xml"
+#if MAJOR_VERSION == 7
+ , "apm_config_b_204314749_7_0.xml"
+#endif
+ ));
+// clang-format on
diff --git a/security/keymint/aidl/OWNERS b/security/OWNERS
similarity index 100%
rename from security/keymint/aidl/OWNERS
rename to security/OWNERS
diff --git a/security/keymint/support/OWNERS b/security/keymint/support/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/keymint/support/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/security/secureclock/aidl/OWNERS b/security/secureclock/aidl/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/secureclock/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/security/sharedsecret/aidl/OWNERS b/security/sharedsecret/aidl/OWNERS
deleted file mode 100644
index a93b171..0000000
--- a/security/sharedsecret/aidl/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-seleneh@google.com
-swillden@google.com
diff --git a/tv/tuner/aidl/default/Filter.cpp b/tv/tuner/aidl/default/Filter.cpp
index c377772..345a984 100644
--- a/tv/tuner/aidl/default/Filter.cpp
+++ b/tv/tuner/aidl/default/Filter.cpp
@@ -34,16 +34,132 @@
#define WAIT_TIMEOUT 3000000000
-Filter::Filter() {}
+FilterCallbackScheduler::FilterCallbackScheduler(const std::shared_ptr<IFilterCallback>& cb)
+ : mCallback(cb), mDataLength(0), mTimeDelayInMs(0), mDataSizeDelayInBytes(0) {
+ start();
+}
+
+FilterCallbackScheduler::~FilterCallbackScheduler() {
+ stop();
+}
+
+void FilterCallbackScheduler::onFilterEvent(DemuxFilterEvent&& event) {
+ std::lock_guard<std::mutex> lock(mLock);
+ mCallbackBuffer.push_back(std::move(event));
+ mDataLength += getDemuxFilterEventDataLength(event);
+
+ if (mDataLength >= mDataSizeDelayInBytes) {
+ // size limit has been reached, send out events
+ mCv.notify_all();
+ }
+}
+
+void FilterCallbackScheduler::onFilterStatus(const DemuxFilterStatus& status) {
+ if (mCallback) {
+ mCallback->onFilterStatus(status);
+ }
+}
+
+void FilterCallbackScheduler::setTimeDelayHint(int timeDelay) {
+ // updating the setTimeDelay does not go into effect until the condition
+ // variable times out or is notified.
+ // One possibility is to notify the condition variable right away when the
+ // time delay changes, but I don't see the benefit over waiting for the next
+ // timeout / push, since -- in any case -- this will not change very often.
+ mTimeDelayInMs = timeDelay;
+}
+
+void FilterCallbackScheduler::setDataSizeDelayHint(int dataSizeDelay) {
+ // similar to updating the time delay hint, when mDataSizeDelayInBytes
+ // changes, this will not go into immediate effect, but will wait until the
+ // next filterEvent.
+ // We could technically check the current data length and notify the
+ // condition variable if we wanted to, but again, this may be overkill.
+ mDataSizeDelayInBytes = dataSizeDelay;
+}
+
+bool FilterCallbackScheduler::hasCallbackRegistered() const {
+ return mCallback != nullptr;
+}
+
+void FilterCallbackScheduler::start() {
+ mIsRunning = true;
+ mCallbackThread = std::thread(&FilterCallbackScheduler::threadLoop, this);
+}
+
+void FilterCallbackScheduler::stop() {
+ mIsRunning = false;
+ if (mCallbackThread.joinable()) {
+ mCallbackThread.join();
+ }
+}
+
+void FilterCallbackScheduler::threadLoop() {
+ while (mIsRunning) {
+ threadLoopOnce();
+ }
+}
+
+void FilterCallbackScheduler::threadLoopOnce() {
+ std::unique_lock<std::mutex> lock(mLock);
+ // mTimeDelayInMs is an atomic value, so it should be copied into a local
+ // variable before use (to make sure both the if statement and wait_for use
+ // the same value).
+ int timeDelayInMs = mTimeDelayInMs;
+ if (timeDelayInMs > 0) {
+ mCv.wait_for(lock, std::chrono::milliseconds(timeDelayInMs));
+ } else {
+ // no reason to timeout, just wait until main thread determines it's
+ // okay to send data.
+ mCv.wait(lock);
+ }
+
+ // condition_variable wait locks mutex on timeout / notify
+ if (!mCallbackBuffer.empty()) {
+ if (mCallback) {
+ mCallback->onFilterEvent(mCallbackBuffer);
+ }
+ mCallbackBuffer.clear();
+ mDataLength = 0;
+ }
+ lock.unlock();
+}
+
+int FilterCallbackScheduler::getDemuxFilterEventDataLength(const DemuxFilterEvent& event) {
+ // there is a risk that dataLength could be a negative value, but it
+ // *should* be safe to assume that it is always positive.
+ switch (event.getTag()) {
+ case DemuxFilterEvent::Tag::section:
+ return event.get<DemuxFilterEvent::Tag::section>().dataLength;
+ case DemuxFilterEvent::Tag::media:
+ return event.get<DemuxFilterEvent::Tag::media>().dataLength;
+ case DemuxFilterEvent::Tag::pes:
+ return event.get<DemuxFilterEvent::Tag::pes>().dataLength;
+ case DemuxFilterEvent::Tag::download:
+ return event.get<DemuxFilterEvent::Tag::download>().dataLength;
+ case DemuxFilterEvent::Tag::ipPayload:
+ return event.get<DemuxFilterEvent::Tag::ipPayload>().dataLength;
+
+ case DemuxFilterEvent::Tag::tsRecord:
+ case DemuxFilterEvent::Tag::mmtpRecord:
+ case DemuxFilterEvent::Tag::temi:
+ case DemuxFilterEvent::Tag::monitorEvent:
+ case DemuxFilterEvent::Tag::startId:
+ // these events do not include a payload and should therefore return
+ // 0.
+ // do not add a default option, so this will not compile when new types
+ // are added.
+ return 0;
+ }
+}
Filter::Filter(DemuxFilterType type, int64_t filterId, uint32_t bufferSize,
- const std::shared_ptr<IFilterCallback>& cb, std::shared_ptr<Demux> demux) {
- mType = type;
- mFilterId = filterId;
- mBufferSize = bufferSize;
- mDemux = demux;
- mCallback = cb;
-
+ const std::shared_ptr<IFilterCallback>& cb, std::shared_ptr<Demux> demux)
+ : mDemux(demux),
+ mCallbackScheduler(cb),
+ mFilterId(filterId),
+ mBufferSize(bufferSize),
+ mType(type) {
switch (mType.mainType) {
case DemuxFilterMainType::TS:
if (mType.subType.get<DemuxFilterSubType::Tag::tsFilterType>() ==
@@ -112,9 +228,29 @@
}
::ndk::ScopedAStatus Filter::setDelayHint(const FilterDelayHint& in_hint) {
+ if (mIsMediaFilter) {
+ // delay hint is not supported for media filters
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::UNAVAILABLE));
+ }
+
ALOGV("%s", __FUNCTION__);
- (void)in_hint;
- // TODO: implement
+ if (in_hint.hintValue < 0) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+
+ switch (in_hint.hintType) {
+ case FilterDelayHintType::TIME_DELAY_IN_MS:
+ mCallbackScheduler.setTimeDelayHint(in_hint.hintValue);
+ break;
+ case FilterDelayHintType::DATA_SIZE_DELAY_IN_BYTES:
+ mCallbackScheduler.setDataSizeDelayHint(in_hint.hintValue);
+ break;
+ default:
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
return ::ndk::ScopedAStatus::ok();
}
@@ -155,40 +291,36 @@
::ndk::ScopedAStatus Filter::start() {
ALOGV("%s", __FUNCTION__);
mFilterThreadRunning = true;
- vector<DemuxFilterEvent> events;
+ std::vector<DemuxFilterEvent> events;
// All the filter event callbacks in start are for testing purpose.
switch (mType.mainType) {
case DemuxFilterMainType::TS:
createMediaEvent(events);
- mCallback->onFilterEvent(events);
createTsRecordEvent(events);
- mCallback->onFilterEvent(events);
createTemiEvent(events);
- mCallback->onFilterEvent(events);
break;
case DemuxFilterMainType::MMTP:
createDownloadEvent(events);
- mCallback->onFilterEvent(events);
createMmtpRecordEvent(events);
- mCallback->onFilterEvent(events);
break;
case DemuxFilterMainType::IP:
createSectionEvent(events);
- mCallback->onFilterEvent(events);
createIpPayloadEvent(events);
- mCallback->onFilterEvent(events);
break;
case DemuxFilterMainType::TLV:
createMonitorEvent(events);
- mCallback->onFilterEvent(events);
break;
case DemuxFilterMainType::ALP:
createMonitorEvent(events);
- mCallback->onFilterEvent(events);
break;
default:
break;
}
+
+ for (auto&& event : events) {
+ mCallbackScheduler.onFilterEvent(std::move(event));
+ }
+
return startFilterLoop();
}
@@ -327,15 +459,14 @@
if (newScramblingStatus ^ mScramblingStatusMonitored) {
mScramblingStatusMonitored = newScramblingStatus;
if (mScramblingStatusMonitored) {
- if (mCallback != nullptr) {
+ if (mCallbackScheduler.hasCallbackRegistered()) {
// Assuming current status is always NOT_SCRAMBLED
- vector<DemuxFilterEvent> events;
- DemuxFilterMonitorEvent monitorEvent;
- events.resize(1);
- monitorEvent.set<DemuxFilterMonitorEvent::Tag::scramblingStatus>(
+ auto monitorEvent = DemuxFilterMonitorEvent::make<
+ DemuxFilterMonitorEvent::Tag::scramblingStatus>(
ScramblingStatus::NOT_SCRAMBLED);
- events[0].set<DemuxFilterEvent::monitorEvent>(monitorEvent);
- mCallback->onFilterEvent(events);
+ auto event =
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::monitorEvent>(monitorEvent);
+ mCallbackScheduler.onFilterEvent(std::move(event));
} else {
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::INVALID_STATE));
@@ -347,14 +478,13 @@
if (newIpCid ^ mIpCidMonitored) {
mIpCidMonitored = newIpCid;
if (mIpCidMonitored) {
- if (mCallback != nullptr) {
+ if (mCallbackScheduler.hasCallbackRegistered()) {
// Return random cid
- vector<DemuxFilterEvent> events;
- DemuxFilterMonitorEvent monitorEvent;
- events.resize(1);
- monitorEvent.set<DemuxFilterMonitorEvent::Tag::cid>(1);
- events[0].set<DemuxFilterEvent::monitorEvent>(monitorEvent);
- mCallback->onFilterEvent(events);
+ auto monitorEvent =
+ DemuxFilterMonitorEvent::make<DemuxFilterMonitorEvent::Tag::cid>(1);
+ auto event =
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::monitorEvent>(monitorEvent);
+ mCallbackScheduler.onFilterEvent(std::move(event));
} else {
return ::ndk::ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(Result::INVALID_STATE));
@@ -410,26 +540,26 @@
}
// After successfully write, send a callback and wait for the read to be done
- if (mCallback != nullptr) {
+ if (mCallbackScheduler.hasCallbackRegistered()) {
if (mConfigured) {
- vector<DemuxFilterEvent> startEvent;
- startEvent.resize(1);
- startEvent[0].set<DemuxFilterEvent::Tag::startId>(mStartId++);
- mCallback->onFilterEvent(startEvent);
+ auto startEvent =
+ DemuxFilterEvent::make<DemuxFilterEvent::Tag::startId>(mStartId++);
+ mCallbackScheduler.onFilterEvent(std::move(startEvent));
mConfigured = false;
}
- mCallback->onFilterEvent(mFilterEvents);
+
+ for (auto&& event : mFilterEvents) {
+ mCallbackScheduler.onFilterEvent(std::move(event));
+ }
} else {
ALOGD("[Filter] filter callback is not configured yet.");
mFilterThreadRunning = false;
return;
}
- mFilterEvents.resize(0);
+ mFilterEvents.clear();
mFilterStatus = DemuxFilterStatus::DATA_READY;
- if (mCallback != nullptr) {
- mCallback->onFilterStatus(mFilterStatus);
- }
+ mCallbackScheduler.onFilterStatus(mFilterStatus);
break;
}
@@ -460,10 +590,10 @@
continue;
}
// After successfully write, send a callback and wait for the read to be done
- if (mCallback != nullptr) {
- mCallback->onFilterEvent(mFilterEvents);
+ for (auto&& event : mFilterEvents) {
+ mCallbackScheduler.onFilterEvent(std::move(event));
}
- mFilterEvents.resize(0);
+ mFilterEvents.clear();
break;
}
// We do not wait for the last read to be done
@@ -499,9 +629,7 @@
DemuxFilterStatus newStatus = checkFilterStatusChange(
availableToWrite, availableToRead, ceil(fmqSize * 0.75), ceil(fmqSize * 0.25));
if (mFilterStatus != newStatus) {
- if (mCallback != nullptr) {
- mCallback->onFilterStatus(newStatus);
- }
+ mCallbackScheduler.onFilterStatus(newStatus);
mFilterStatus = newStatus;
}
}
@@ -657,9 +785,7 @@
ALOGD("[Filter] assembled pes data length %d", pesEvent.dataLength);
}
- int size = mFilterEvents.size();
- mFilterEvents.resize(size + 1);
- mFilterEvents[size].set<DemuxFilterEvent::Tag::pes>(pesEvent);
+ mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::pes>(pesEvent));
mPesOutput.clear();
}
@@ -763,11 +889,7 @@
.firstMbInSlice = 0, // random address
};
- int size;
- size = mFilterEvents.size();
- mFilterEvents.resize(size + 1);
- mFilterEvents[size].set<DemuxFilterEvent::Tag::tsRecord>(recordEvent);
-
+ mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::tsRecord>(recordEvent));
mRecordFilterOutput.clear();
return ::ndk::ScopedAStatus::ok();
}
@@ -789,8 +911,6 @@
if (!writeDataToFilterMQ(data)) {
return false;
}
- int size = mFilterEvents.size();
- mFilterEvents.resize(size + 1);
DemuxFilterSectionEvent secEvent;
secEvent = {
// temp dump meta data
@@ -799,7 +919,7 @@
.sectionNum = 1,
.dataLength = static_cast<int32_t>(data.size()),
};
- mFilterEvents[size].set<DemuxFilterEvent::Tag::section>(secEvent);
+ mFilterEvents.push_back(DemuxFilterEvent::make<DemuxFilterEvent::Tag::section>(secEvent));
return true;
}
@@ -888,19 +1008,16 @@
mDataId2Avfd[dataId] = dup(av_fd);
// Create mediaEvent and send callback
- int size = mFilterEvents.size();
- mFilterEvents.resize(size + 1);
-
- mFilterEvents[size] = DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>();
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().avMemory =
- ::android::dupToAidl(nativeHandle);
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().dataLength =
- static_cast<int64_t>(output.size());
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().avDataId = static_cast<int64_t>(dataId);
+ auto event = DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>();
+ auto& mediaEvent = event.get<DemuxFilterEvent::Tag::media>();
+ mediaEvent.avMemory = ::android::dupToAidl(nativeHandle);
+ mediaEvent.dataLength = static_cast<int64_t>(output.size());
+ mediaEvent.avDataId = static_cast<int64_t>(dataId);
if (mPts) {
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().pts = mPts;
+ mediaEvent.pts = mPts;
mPts = 0;
}
+ mFilterEvents.push_back(std::move(event));
// Clear and log
native_handle_close(nativeHandle);
@@ -931,18 +1048,17 @@
}
// Create mediaEvent and send callback
- int size = mFilterEvents.size();
- mFilterEvents.resize(size + 1);
- mFilterEvents[size] = DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>();
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().avMemory =
- ::android::dupToAidl(nativeHandle);
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().offset = mSharedAvMemOffset;
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().dataLength =
- static_cast<int64_t>(output.size());
+ auto event = DemuxFilterEvent::make<DemuxFilterEvent::Tag::media>();
+ auto& mediaEvent = event.get<DemuxFilterEvent::Tag::media>();
+ mediaEvent.avMemory = ::android::dupToAidl(nativeHandle);
+ mediaEvent.offset = mSharedAvMemOffset;
+ mediaEvent.dataLength = static_cast<int64_t>(output.size());
if (mPts) {
- mFilterEvents[size].get<DemuxFilterEvent::Tag::media>().pts = mPts;
+ mediaEvent.pts = mPts;
mPts = 0;
}
+ mFilterEvents.push_back(std::move(event));
+
mSharedAvMemOffset += output.size();
// Clear and log
diff --git a/tv/tuner/aidl/default/Filter.h b/tv/tuner/aidl/default/Filter.h
index 11bbc11..a5adf4c 100644
--- a/tv/tuner/aidl/default/Filter.h
+++ b/tv/tuner/aidl/default/Filter.h
@@ -18,6 +18,8 @@
#include <aidl/android/hardware/tv/tuner/BnFilter.h>
#include <aidl/android/hardware/tv/tuner/Constant.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterEvent.h>
+#include <aidl/android/hardware/tv/tuner/DemuxFilterStatus.h>
#include <fmq/AidlMessageQueue.h>
#include <inttypes.h>
@@ -25,6 +27,7 @@
#include <math.h>
#include <sys/stat.h>
#include <atomic>
+#include <condition_variable>
#include <set>
#include <thread>
@@ -52,10 +55,49 @@
class Demux;
class Dvr;
-class Filter : public BnFilter {
+class FilterCallbackScheduler final {
public:
- Filter();
+ FilterCallbackScheduler(const std::shared_ptr<IFilterCallback>& cb);
+ ~FilterCallbackScheduler();
+ void onFilterEvent(DemuxFilterEvent&& event);
+ void onFilterStatus(const DemuxFilterStatus& status);
+
+ void setTimeDelayHint(int timeDelay);
+ void setDataSizeDelayHint(int dataSizeDelay);
+
+ bool hasCallbackRegistered() const;
+
+ private:
+ void start();
+ void stop();
+
+ void threadLoop();
+ void threadLoopOnce();
+
+ static int getDemuxFilterEventDataLength(const DemuxFilterEvent& event);
+
+ private:
+ std::shared_ptr<IFilterCallback> mCallback;
+ std::thread mCallbackThread;
+ std::atomic<bool> mIsRunning;
+
+ // mLock protects mCallbackBuffer, mCv, and mDataLength
+ std::mutex mLock;
+ std::vector<DemuxFilterEvent> mCallbackBuffer;
+ std::condition_variable mCv;
+ int mDataLength;
+
+ // both of these need to be atomic (not just mTimeDelayInMs) as this class
+ // needs to be threadsafe.
+ std::atomic<int> mTimeDelayInMs;
+ std::atomic<int> mDataSizeDelayInBytes;
+};
+
+class Filter : public BnFilter {
+ friend class FilterCallbackScheduler;
+
+ public:
Filter(DemuxFilterType type, int64_t filterId, uint32_t bufferSize,
const std::shared_ptr<IFilterCallback>& cb, std::shared_ptr<Demux> demux);
@@ -104,10 +146,8 @@
std::shared_ptr<Demux> mDemux;
// Dvr reference once the filter is attached to any
std::shared_ptr<Dvr> mDvr = nullptr;
- /**
- * Filter callbacks used on filter events or FMQ status
- */
- std::shared_ptr<IFilterCallback> mCallback = nullptr;
+
+ FilterCallbackScheduler mCallbackScheduler;
int64_t mFilterId;
int32_t mCid = static_cast<int32_t>(Constant::INVALID_IP_FILTER_CONTEXT_ID);
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.h b/tv/tuner/aidl/vts/functional/FilterTests.h
index 91a0a4a..c965d95 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.h
+++ b/tv/tuner/aidl/vts/functional/FilterTests.h
@@ -74,7 +74,6 @@
void setFilterId(int32_t filterId) { mFilterId = filterId; }
void setFilterInterface(std::shared_ptr<IFilter> filter) { mFilter = filter; }
- void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
void setSharedHandle(native_handle_t* sharedHandle) { mAvSharedHandle = sharedHandle; }
void setMemSize(uint64_t size) { mAvSharedMemSize = size; }
@@ -89,7 +88,6 @@
private:
int32_t mFilterId;
std::shared_ptr<IFilter> mFilter;
- FilterEventType mFilterEventType;
native_handle_t* mAvSharedHandle = nullptr;
uint64_t mAvSharedMemSize = -1;