Merge "[LSC] Add LOCAL_LICENSE_KINDS to hardware/interfaces"
diff --git a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index e389ef3..9a1557a 100644
--- a/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/aidl_api/android.hardware.bluetooth.audio/current/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -38,5 +38,6 @@
void startStream();
void stopStream();
void suspendStream();
- void updateMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+ void updateSourceMetadata(in android.hardware.audio.common.SourceMetadata sourceMetadata);
+ void updateSinkMetadata(in android.hardware.audio.common.SinkMetadata sinkMetadata);
}
diff --git a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
index 50e3197..827f57d 100644
--- a/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
+++ b/bluetooth/audio/aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.aidl
@@ -16,6 +16,7 @@
package android.hardware.bluetooth.audio;
+import android.hardware.audio.common.SinkMetadata;
import android.hardware.audio.common.SourceMetadata;
import android.hardware.bluetooth.audio.PresentationPosition;
@@ -69,5 +70,12 @@
* @param sourceMetadata Description of the audio that is played by the
* clients.
*/
- void updateMetadata(in SourceMetadata sourceMetadata);
+ void updateSourceMetadata(in SourceMetadata sourceMetadata);
+
+ /**
+ * Called when the metadata of the stream's sink has been changed.
+ *
+ * @param sinkMetadata as passed from Audio Framework
+ */
+ void updateSinkMetadata(in SinkMetadata sinkMetadata);
}
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
index 95f7408..4d7be21 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_1.h
@@ -35,7 +35,7 @@
std::shared_ptr<BluetoothAudioSession_2_1> session_ptr =
BluetoothAudioSessionInstance_2_1::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
- return session_ptr->IsSessionReady();
+ return session_ptr->GetAudioSession()->IsSessionReady();
}
return false;
}
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index c250ef1..646e225 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
@@ -60,16 +60,6 @@
}
}
-bool BluetoothAudioSession_2_1::IsSessionReady() {
- if (session_type_2_1_ !=
- SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
- return audio_session->IsSessionReady();
- }
-
- std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- return audio_session->stack_iface_ != nullptr;
-}
-
std::shared_ptr<BluetoothAudioSession>
BluetoothAudioSession_2_1::GetAudioSession() {
return audio_session;
@@ -80,7 +70,7 @@
const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
BluetoothAudioSession_2_1::GetAudioConfig() {
std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
- if (IsSessionReady()) {
+ if (audio_session->IsSessionReady()) {
// If session is unknown it means it should be 2.0 type
if (session_type_2_1_ != SessionType_2_1::UNKNOWN)
return audio_config_2_1_;
@@ -122,9 +112,6 @@
SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
bool is_offload_a2dp_session =
(session_type_2_1_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH);
- bool is_offload_le_audio_session =
- (session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
- session_type_2_1_ == SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
auto audio_config_discriminator = audio_config.getDiscriminator();
bool is_software_audio_config =
(is_software_session &&
@@ -136,13 +123,7 @@
audio_config_discriminator ==
::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
hidl_discriminator::codecConfig);
- bool is_le_audio_offload_audio_config =
- (is_offload_le_audio_session &&
- audio_config_discriminator ==
- ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
- hidl_discriminator::leAudioCodecConfig);
- if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
- !is_le_audio_offload_audio_config) {
+ if (!is_software_audio_config && !is_a2dp_offload_audio_config) {
return false;
}
audio_config_2_1_ = audio_config;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
index db82c73..5a35153 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
@@ -50,10 +50,6 @@
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type);
- // The function helps to check if this session is ready or not
- // @return: true if the Bluetooth stack has started the specified session
- bool IsSessionReady();
-
std::shared_ptr<BluetoothAudioSession> GetAudioSession();
// The report function is used to report that the Bluetooth stack has started
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 9dc6fae..6919b9b 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -298,16 +298,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
- <name>android.hardware.health</name>
- <version>2.1</version>
- <interface>
- <name>IHealth</name>
- <instance>default</instance>
- </interface>
- </hal>
- <!-- TODO(b/177269435): require health AIDL HAL and deprecate HIDL HAL -->
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="false">
<name>android.hardware.health</name>
<version>1</version>
<interface>
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
index bdf97ca..b586e7f 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
@@ -294,6 +294,11 @@
getLayerCommand(display, layer).genericMetadata.emplace(std::move(metadata));
}
+ void setLayerWhitePointNits(int64_t display, int64_t layer, float whitePointNits) {
+ getLayerCommand(display, layer)
+ .whitePointNits.emplace(command::WhitePointNits{.nits = whitePointNits});
+ }
+
const std::vector<command::CommandPayload>& getPendingCommands() {
if (mLayerCommand.has_value()) {
mCommands.emplace_back(std::move(*mLayerCommand));
@@ -305,6 +310,7 @@
}
return mCommands;
}
+
std::vector<command::CommandResultPayload> getPendingCommandResults() {
return std::move(mCommandsResults);
}
@@ -489,18 +495,21 @@
}
// Get the client target properties requested by hardware composer.
- void takeClientTargetProperty(int64_t display, ClientTargetProperty* outClientTargetProperty) {
+ void takeClientTargetProperty(int64_t display, ClientTargetProperty* outClientTargetProperty,
+ float* outWhitePointNits) {
auto found = mReturnData.find(display);
// If not found, return the default values.
if (found == mReturnData.end()) {
outClientTargetProperty->pixelFormat = common::PixelFormat::RGBA_8888;
outClientTargetProperty->dataspace = Dataspace::UNKNOWN;
+ *outWhitePointNits = -1.f;
return;
}
ReturnData& data = found->second;
*outClientTargetProperty = data.clientTargetProperty;
+ *outWhitePointNits = data.clientTargetWhitePointNits;
}
private:
@@ -578,6 +587,7 @@
data.clientTargetProperty.pixelFormat =
clientTargetProperty.clientTargetProperty.pixelFormat;
data.clientTargetProperty.dataspace = clientTargetProperty.clientTargetProperty.dataspace;
+ data.clientTargetWhitePointNits = clientTargetProperty.whitePointNits;
}
struct ReturnData {
@@ -598,6 +608,7 @@
ClientTargetProperty clientTargetProperty{common::PixelFormat::RGBA_8888,
Dataspace::UNKNOWN};
+ float clientTargetWhitePointNits = -1.f;
};
std::vector<command::Error> mErrors;
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.cpp b/tv/tuner/aidl/vts/functional/FilterTests.cpp
index a5acdc1..53afef7 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FilterTests.cpp
@@ -17,6 +17,7 @@
#include "FilterTests.h"
#include <inttypes.h>
+#include <algorithm>
#include <aidl/android/hardware/tv/tuner/DemuxFilterMonitorEventType.h>
#include <aidlcommonsupport/NativeHandle.h>
@@ -31,23 +32,24 @@
mPidFilterOutputCount++;
mMsgCondition.signal();
- // HACK: we need to cast the const away as DemuxFilterEvent contains a ScopedFileDescriptor
- // that cannot be copied.
- for (auto&& e : const_cast<std::vector<DemuxFilterEvent>&>(events)) {
- auto it = mFilterEventPromises.find(e.getTag());
- if (it != mFilterEventPromises.cend()) {
- it->second.set_value(std::move(e));
- mFilterEventPromises.erase(it);
+ for (auto it = mFilterCallbackVerifiers.begin(); it != mFilterCallbackVerifiers.end();) {
+ auto& [verifier, promise] = *it;
+ if (verifier(events)) {
+ promise.set_value();
+ it = mFilterCallbackVerifiers.erase(it);
+ } else {
+ ++it;
}
- }
+ };
return ::ndk::ScopedAStatus::ok();
}
-std::future<DemuxFilterEvent> FilterCallback::getNextFilterEventWithTag(DemuxFilterEvent::Tag tag) {
- // Note: this currently only supports one future per DemuxFilterEvent::Tag.
- mFilterEventPromises[tag] = std::promise<DemuxFilterEvent>();
- return mFilterEventPromises[tag].get_future();
+std::future<void> FilterCallback::verifyFilterCallback(FilterCallbackVerifier&& verifier) {
+ std::promise<void> promise;
+ auto future = promise.get_future();
+ mFilterCallbackVerifiers.emplace_back(std::move(verifier), std::move(promise));
+ return future;
}
void FilterCallback::testFilterDataOutput() {
diff --git a/tv/tuner/aidl/vts/functional/FilterTests.h b/tv/tuner/aidl/vts/functional/FilterTests.h
index 6258bac..f579441 100644
--- a/tv/tuner/aidl/vts/functional/FilterTests.h
+++ b/tv/tuner/aidl/vts/functional/FilterTests.h
@@ -60,9 +60,18 @@
class FilterCallback : public BnFilterCallback {
public:
+ /**
+ * A FilterCallbackVerifier is used to test and verify filter callbacks.
+ * The function should return true when a callback has been handled by this
+ * filter verifier. This will cause the associated future to be unblocked.
+ * If the function returns false, we continue to wait for future callbacks
+ * (the future remains blocked).
+ */
+ using FilterCallbackVerifier = std::function<bool(const std::vector<DemuxFilterEvent>&)>;
+
virtual ::ndk::ScopedAStatus onFilterEvent(const vector<DemuxFilterEvent>& events) override;
- std::future<DemuxFilterEvent> getNextFilterEventWithTag(DemuxFilterEvent::Tag tag);
+ std::future<void> verifyFilterCallback(FilterCallbackVerifier&& verifier);
virtual ::ndk::ScopedAStatus onFilterStatus(const DemuxFilterStatus /*status*/) override {
return ::ndk::ScopedAStatus::ok();
@@ -85,7 +94,7 @@
int32_t mFilterId;
std::shared_ptr<IFilter> mFilter;
- std::unordered_map<DemuxFilterEvent::Tag, std::promise<DemuxFilterEvent>> mFilterEventPromises;
+ std::vector<std::pair<FilterCallbackVerifier, std::promise<void>>> mFilterCallbackVerifiers;
native_handle_t* mAvSharedHandle = nullptr;
uint64_t mAvSharedMemSize = -1;
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 88890e4..89e42df 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -640,10 +640,51 @@
testTimeFilter(timeFilterMap[timeFilter.timeFilterId]);
}
-// TODO: move boilerplate into text fixture
-TEST_P(TunerFilterAidlTest, FilterTimeDelayHintTest) {
- description("Test filter delay hint.");
+static bool isMediaFilter(const FilterConfig& filterConfig) {
+ switch (filterConfig.type.mainType) {
+ case DemuxFilterMainType::TS: {
+ // TS Audio and Video filters are media filters
+ auto tsFilterType =
+ filterConfig.type.subType.get<DemuxFilterSubType::Tag::tsFilterType>();
+ return (tsFilterType == DemuxTsFilterType::AUDIO ||
+ tsFilterType == DemuxTsFilterType::VIDEO);
+ }
+ case DemuxFilterMainType::MMTP: {
+ // MMTP Audio and Video filters are media filters
+ auto mmtpFilterType =
+ filterConfig.type.subType.get<DemuxFilterSubType::Tag::mmtpFilterType>();
+ return (mmtpFilterType == DemuxMmtpFilterType::AUDIO ||
+ mmtpFilterType == DemuxMmtpFilterType::VIDEO);
+ }
+ default:
+ return false;
+ }
+}
+static int getDemuxFilterEventDataLength(const DemuxFilterEvent& event) {
+ 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:
+ return 0;
+ }
+}
+
+// TODO: move boilerplate into text fixture
+void TunerFilterAidlTest::testDelayHint(const FilterConfig& filterConf) {
int32_t feId;
int32_t demuxId;
std::shared_ptr<IDemux> demux;
@@ -657,40 +698,87 @@
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
- const auto& filterConf = filterMap[live.ipFilterId];
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(filterId));
- ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
- ASSERT_TRUE(mFilterTests.configIpFilterCid(filterConf.ipCid, filterId));
+ bool mediaFilter = isMediaFilter(filterConf);
auto filter = mFilterTests.getFilterById(filterId);
- auto delayValue = std::chrono::milliseconds(5000);
- FilterDelayHint delayHint;
- delayHint.hintType = FilterDelayHintType::TIME_DELAY_IN_MS;
- delayHint.hintValue = delayValue.count();
+ auto timeDelayInMs = std::chrono::milliseconds(filterConf.timeDelayInMs);
+ if (timeDelayInMs.count() > 0) {
+ FilterDelayHint delayHint;
+ delayHint.hintType = FilterDelayHintType::TIME_DELAY_IN_MS;
+ delayHint.hintValue = timeDelayInMs.count();
- auto status = filter->setDelayHint(delayHint);
- ASSERT_TRUE(status.isOk());
+ // setDelayHint should fail for media filters.
+ ASSERT_EQ(filter->setDelayHint(delayHint).isOk(), !mediaFilter);
+ }
- auto startTime = std::chrono::steady_clock::now();
- ASSERT_TRUE(mFilterTests.startFilter(filterId));
+ int dataDelayInBytes = filterConf.dataDelayInBytes;
+ if (dataDelayInBytes > 0) {
+ FilterDelayHint delayHint;
+ delayHint.hintType = FilterDelayHintType::DATA_SIZE_DELAY_IN_BYTES;
+ delayHint.hintValue = dataDelayInBytes;
- auto cb = mFilterTests.getFilterCallbacks().at(filterId);
- auto future = cb->getNextFilterEventWithTag(DemuxFilterEvent::Tag::ipPayload);
+ // setDelayHint should fail for media filters.
+ ASSERT_EQ(filter->setDelayHint(delayHint).isOk(), !mediaFilter);
+ }
- // block and wait for callback to be received.
- ASSERT_EQ(future.wait_for(std::chrono::seconds(10)), std::future_status::ready);
- auto duration = std::chrono::steady_clock::now() - startTime;
- ASSERT_GE(duration, delayValue);
+ // start and stop filter in order to circumvent callback scheduler race
+ // conditions after adjusting filter delays.
+ mFilterTests.startFilter(filterId);
+ mFilterTests.stopFilter(filterId);
- // cleanup
- ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ if (!mediaFilter) {
+ auto cb = mFilterTests.getFilterCallbacks().at(filterId);
+ int callbackSize = 0;
+ auto future = cb->verifyFilterCallback(
+ [&callbackSize](const std::vector<DemuxFilterEvent>& events) {
+ for (const auto& event : events) {
+ callbackSize += getDemuxFilterEventDataLength(event);
+ }
+ return true;
+ });
+
+ // The configure stage can also produce events, so we should set the delay
+ // hint beforehand.
+ ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
+
+ auto startTime = std::chrono::steady_clock::now();
+ ASSERT_TRUE(mFilterTests.startFilter(filterId));
+
+ // block and wait for callback to be received.
+ auto timeout = std::chrono::seconds(30);
+ ASSERT_EQ(future.wait_for(timeout), std::future_status::ready);
+ auto duration = std::chrono::steady_clock::now() - startTime;
+
+ bool delayHintTest = duration >= timeDelayInMs;
+ bool dataSizeTest = callbackSize >= dataDelayInBytes;
+
+ if (timeDelayInMs.count() > 0 && dataDelayInBytes > 0) {
+ ASSERT_TRUE(delayHintTest || dataSizeTest);
+ } else {
+ // if only one of time delay / data delay is configured, one of them
+ // holds true by default, so we want both assertions to be true.
+ ASSERT_TRUE(delayHintTest && dataSizeTest);
+ }
+
+ ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+ }
+
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
+TEST_P(TunerFilterAidlTest, FilterDelayHintTest) {
+ description("Test filter time delay hint.");
+
+ for (const auto& obj : filterMap) {
+ testDelayHint(obj.second);
+ }
+}
+
TEST_P(TunerPlaybackAidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
description("Feed ts data from playback and configure Ts section filter to get output");
if (!playback.support || playback.sectionFilterId.compare(emptyHardwareId) == 0) {
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
index 13c5a80..7f80d90 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
@@ -140,6 +140,7 @@
void reconfigSingleFilterInDemuxTest(FilterConfig filterConf, FilterConfig filterReconf,
FrontendConfig frontendConf);
void testTimeFilter(TimeFilterConfig filterConf);
+ void testDelayHint(const FilterConfig& filterConf);
DemuxFilterType getLinkageFilterType(int bit) {
DemuxFilterType type;
diff --git a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
index 7ccf31a..b6cc5f8 100644
--- a/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
+++ b/tv/tuner/config/TunerTestingConfigAidlReaderV1_0.h
@@ -96,6 +96,8 @@
AvStreamType streamType;
int32_t ipCid;
int32_t monitorEventTypes;
+ int timeDelayInMs = 0;
+ int dataDelayInBytes = 0;
bool operator<(const FilterConfig& /*c*/) const { return false; }
};
@@ -336,6 +338,12 @@
if (filterConfig.hasMonitorEventTypes()) {
filterMap[id].monitorEventTypes = (int32_t)filterConfig.getMonitorEventTypes();
}
+ if (filterConfig.hasTimeDelayInMs()) {
+ filterMap[id].timeDelayInMs = filterConfig.getTimeDelayInMs();
+ }
+ if (filterConfig.hasDataDelayInBytes()) {
+ filterMap[id].dataDelayInBytes = filterConfig.getDataDelayInBytes();
+ }
if (filterConfig.hasAvFilterSettings_optional()) {
auto av = filterConfig.getFirstAvFilterSettings_optional();
if (av->hasAudioStreamType_optional()) {
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
index 6c637a4..db1d076 100644
--- a/tv/tuner/config/api/current.txt
+++ b/tv/tuner/config/api/current.txt
@@ -256,6 +256,7 @@
ctor public Filter();
method @Nullable public android.media.tuner.testing.configuration.V1_0.AvFilterSettings getAvFilterSettings_optional();
method @Nullable public java.math.BigInteger getBufferSize();
+ method @Nullable public java.math.BigInteger getDataDelayInBytes();
method @Nullable public String getId();
method @Nullable public android.media.tuner.testing.configuration.V1_0.IpFilterConfig getIpFilterConfig_optional();
method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum getMainType();
@@ -264,9 +265,11 @@
method @Nullable public android.media.tuner.testing.configuration.V1_0.RecordFilterSettings getRecordFilterSettings_optional();
method @Nullable public android.media.tuner.testing.configuration.V1_0.SectionFilterSettings getSectionFilterSettings_optional();
method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum getSubType();
+ method @Nullable public java.math.BigInteger getTimeDelayInMs();
method @Nullable public boolean getUseFMQ();
method public void setAvFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.AvFilterSettings);
method public void setBufferSize(@Nullable java.math.BigInteger);
+ method public void setDataDelayInBytes(@Nullable java.math.BigInteger);
method public void setId(@Nullable String);
method public void setIpFilterConfig_optional(@Nullable android.media.tuner.testing.configuration.V1_0.IpFilterConfig);
method public void setMainType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum);
@@ -275,6 +278,7 @@
method public void setRecordFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.RecordFilterSettings);
method public void setSectionFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.SectionFilterSettings);
method public void setSubType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum);
+ method public void setTimeDelayInMs(@Nullable java.math.BigInteger);
method public void setUseFMQ(@Nullable boolean);
}
diff --git a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
index 8a6229e..da77200 100644
--- a/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
+++ b/tv/tuner/config/sample_tuner_vts_config_aidl_V1.xml
@@ -101,7 +101,7 @@
bufferSize="16777216" pid="257" useFMQ="false">
<recordFilterSettings tsIndexMask="1" scIndexType="NONE"/>
</filter>
- <filter id="FILTER_IP_IP_0" mainType="IP" subType="IP" bufferSize="16777216" useFMQ="false">
+ <filter id="FILTER_IP_IP_0" mainType="IP" subType="IP" bufferSize="16777216" useFMQ="false" timeDelayInMs="5000">
<ipFilterConfig ipCid="1">
<srcIpAddress isIpV4="true" ip="192 168 1 1"/>
<destIpAddress isIpV4="true" ip="192 168 1 1"/>
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
index fc2827f..54cedfc 100644
--- a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -243,6 +243,10 @@
"bufferSize": the buffer size of the filter in hex.
"pid": the pid that would be used to configure the filter.
"useFMQ": if the filter uses FMQ.
+ "timeDelayInMs": the filter's time delay hint. 0 by default. Must not be
+ longer than 30 seconds.
+ "dataDelayInBytes": the filter's data delay hint. 0 by default. Configured data
+ size must be received within 30 seconds.
Each filter element also contains at most one type-related "filterSettings".
- The settings type should match the filter "subType" attribute.
@@ -274,6 +278,8 @@
<xs:attribute name="pid" type="xs:nonNegativeInteger" use="optional"/>
<xs:attribute name="useFMQ" type="xs:boolean" use="required"/>
<xs:attribute name="monitorEventTypes" type="monitoEvents" use="optional"/>
+ <xs:attribute name="timeDelayInMs" type="xs:nonNegativeInteger" use="optional"/>
+ <xs:attribute name="dataDelayInBytes" type="xs:nonNegativeInteger" use="optional"/>
</xs:complexType>
<!-- DVR SESSION -->