Merge "Log NNAPI VTS test case to logcat" into rvc-dev
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
index f712ea2..2c2f23c 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
@@ -158,6 +158,20 @@
return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), requestId);
}
+ if (value.value.int32Values.size() > 1) {
+ auto messageType = static_cast<SwitchUserMessageType>(value.value.int32Values[1]);
+ switch (messageType) {
+ case SwitchUserMessageType::LEGACY_ANDROID_SWITCH:
+ ALOGI("request is LEGACY_ANDROID_SWITCH; ignoring it");
+ return {};
+ case SwitchUserMessageType::ANDROID_POST_SWITCH:
+ ALOGI("request is ANDROID_POST_SWITCH; ignoring it");
+ return {};
+ default:
+ break;
+ }
+ }
+
// Returns default response
auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
updatedValue->prop = SWITCH_USER;
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 341aae7..acdea8a 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2546,9 +2546,8 @@
* NOTE: if the HAL doesn't support user management, then it should not define this property,
* which in turn would disable the other user-related properties (for example, the Android
* system would never issue them and user-related requests from the HAL layer would be ignored
- * by the Android System). But if it supports user management, then it must support all
- * user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, REMOVE_USER,
- * and USER_IDENTIFICATION_ASSOCIATION).
+ * by the Android System). But if it supports user management, then it must support all core
+ * user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, and REMOVE_USER).
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ_WRITE
@@ -2818,6 +2817,10 @@
* Property used to associate (or query the association) the current user with vehicle-specific
* identification mechanisms (such as key FOB).
*
+ * This is an optional user management property - the OEM could still support user management
+ * without defining it. In fact, this property could be used without supporting the core
+ * user-related functions described on INITIAL_USER_INFO.
+ *
* To query the association, the Android system gets the property, passing a VehiclePropValue
* containing the types of associations are being queried, as defined by
* UserIdentificationGetRequest. The HAL must return right away, returning a VehiclePropValue
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index 7ac44a4..78f93af 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -28,6 +28,7 @@
#include <chrono>
#include <cstdint>
#include <random>
+#include <thread>
using android::sp;
using android::hardware::hidl_vec;
@@ -144,7 +145,10 @@
ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
}
- void TearDown() override {}
+ void TearDown() override {
+ // Hack to allow the asynchronous operations to finish on time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(250));
+ }
sp<IBiometricsFace> mService;
sp<FaceCallback> mCallback;
diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
index dec3bd8..607502e 100644
--- a/camera/device/3.2/ICameraDeviceCallback.hal
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -95,7 +95,8 @@
* statuses must be STATUS_ERROR, and the result metadata must be an
* empty buffer. In addition, notify() must be called with a ERROR_REQUEST
* message. In this case, individual ERROR_RESULT/ERROR_BUFFER messages
- * must not be sent.
+ * must not be sent. Note that valid partial results are still allowed
+ * as long as the final result metadata fails to be generated.
*
* Performance requirements:
*
diff --git a/camera/provider/2.4/vts/functional/AndroidTest.xml b/camera/provider/2.4/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..05e1639
--- /dev/null
+++ b/camera/provider/2.4/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Runs VtsHalCameraProviderV2_4TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalCameraProviderV2_4TargetTest->/data/local/tmp/VtsHalCameraProviderV2_4TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalCameraProviderV2_4TargetTest" />
+ <option name="native-test-timeout" value="180000"/>
+ </test>
+</configuration>
diff --git a/camera/provider/2.6/ICameraProvider.hal b/camera/provider/2.6/ICameraProvider.hal
index ed1d31d..b8873a6 100644
--- a/camera/provider/2.6/ICameraProvider.hal
+++ b/camera/provider/2.6/ICameraProvider.hal
@@ -76,12 +76,16 @@
* configuration settings exposed through camera metadata), should the sum
* of resource costs for the combination be <= 100.
*
- * The lists of camera id combinations returned by this method may contain
- * hidden physical camera ids. If a combination does contain hidden physical
- * camera ids, the camera framework must be able to open any logical cameras
- * that contain these hidden physical camera ids in their
- * ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS list, in addition to the other
- * camera ids advertised in the combination, for concurrent operation.
+ * For guaranteed concurrent camera operation, the camera framework must call
+ * ICameraDevice.open() on all devices (intended for concurrent operation), before configuring
+ * any streams on them. This gives the camera HAL process an opportunity to potentially
+ * distribute hardware resources better before stream configuration.
+ *
+ * Due to potential hardware constraints around internal switching of physical camera devices,
+ * a device's complete ZOOM_RATIO_RANGE(if supported), may not apply during concurrent
+ * operation. If ZOOM_RATIO is supported, camera HALs must ensure ZOOM_RATIO_RANGE of
+ * [1.0, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM] is supported by that device, during
+ * concurrent operation.
*
* @return status Status code for the operation
* @return cameraIds a list of camera id combinations that support
diff --git a/current.txt b/current.txt
index e2d1408..2608b54 100644
--- a/current.txt
+++ b/current.txt
@@ -588,6 +588,7 @@
578f640c653726d58f99c84a7e1bb63862e21ef7cbb4f7d95c3cc62de00dca35 android.hardware.automotive.evs@1.0::IEvsDisplay
f5bc6aa840db933cb9fd36668b06d3e2021cf5384bb70e459f22e2f2f921fba5 android.hardware.automotive.evs@1.0::IEvsEnumerator
d3a344b7bd4c0d2658ae7209f55a979b8f53f361fd00f4fca29d5baa56d11fd2 android.hardware.automotive.evs@1.0::types
+d123013165a19b6353cdc46a57b2ff4a17179619d36dbd595dfcf15dcd099af6 android.hardware.camera.device@3.2::ICameraDeviceCallback # b/155353799
2410dd02d67786a732d36e80b0f8ccf55086604ef37f9838e2013ff2c571e404 android.hardware.camera.device@3.5::types
cd06a7911b9acd4a653bbf7133888878fbcb3f84be177c7a3f1becaae3d8618f android.hardware.camera.metadata@3.2::types
5cf81b1001296fbb3c5b3d275a859244f61cec5fa858d7be9cca46c5b7dfa733 android.hardware.camera.metadata@3.2::types # b/150331548
@@ -676,7 +677,7 @@
a718c8a3acaa938de5a57923e8c4625ed7ca051e05a1d930ba6998557d7b57c8 android.hardware.camera.device@3.6::ICameraOfflineSession
a35d5151b48505f06a775b38c0e2e265f80a845d92802324c643565807f81c53 android.hardware.camera.device@3.6::types
02bdf82dba7dce273a554b4474468a8fb1fb4f61ab65da95eb16e080df63fff6 android.hardware.camera.metadata@3.5::types
-21086e1c7a2acc0ebe0ff8561b11f3c2009be687a92d79b608a5f00b16c5f598 android.hardware.camera.provider@2.6::ICameraProvider
+7d6b362681f4a4fd0be95535d8913d8de9a26f0765c1bdda4bd837dea8c25db6 android.hardware.camera.provider@2.6::ICameraProvider
8f8d9463508ff9cae88eb35c429fd0e2dbca0ca8f5de7fdf836cc0c4370becb6 android.hardware.camera.provider@2.6::ICameraProviderCallback
1edf7aef68ef3bd577a1175b1462fb82e3e39f01c6915dda61fba121028df283 android.hardware.camera.provider@2.6::types
c1aa508d00b66ed5feefea398fd5edf28fa651ac89773adad7dfda4e0a73a952 android.hardware.cas@1.2::ICas
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index 0d540b7..94bfb89 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -25,6 +25,7 @@
static_libs: [
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
+ "android.hardware.gnss@2.0",
"android.hardware.gnss@common-vts-lib",
],
shared_libs: [
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index 59e18f3..1cb44c5 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -247,3 +247,46 @@
capabilities_cbq_.store(capabilities);
return Void();
}
+
+GnssConstellationType_1_0 GnssHalTest::startLocationAndGetNonGpsConstellation() {
+ const int kLocationsToAwait = 3;
+
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToAwait);
+ const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+ // Tolerate 1 less sv status to handle edge cases in reporting.
+ int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+ ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+ sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+
+ // Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
+ // as blacklisting of this constellation is not supported in gnss@2.0.
+ const int kGnssSvStatusTimeout = 2;
+ GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
+ for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+ hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+ for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+ if ((sv_info.v1_0.svFlag & IGnssCallback_2_0::GnssSvFlags::USED_IN_FIX) &&
+ (sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
+ (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
+ (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
+ // found a non-GPS V1_0 constellation
+ constellation_to_blacklist = Utils::mapConstellationType(sv_info.constellation);
+ break;
+ }
+ }
+ if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
+ break;
+ }
+ }
+
+ if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
+ ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
+ // Proceed functionally to blacklist something.
+ constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
+ }
+ return constellation_to_blacklist;
+}
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index a02a9ff..7fbd735 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -31,6 +31,9 @@
using android::hardware::gnss::V1_0::GnssLocationFlags;
using android::hardware::gnss::V2_0::IGnss;
+using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
+using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
+
using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
@@ -194,6 +197,16 @@
*/
void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
+ /*
+ * startLocationAndGetNonGpsConstellation:
+ * 1. Start location
+ * 2. Find and return first non-GPS constellation
+ *
+ * Note that location is not stopped in this method. The client should call
+ * StopAndClearLocations() after the call.
+ */
+ GnssConstellationType_1_0 startLocationAndGetNonGpsConstellation();
+
sp<IGnss> gnss_hal_; // GNSS HAL to call into
sp<GnssCallback> gnss_cb_; // Primary callback interface
};
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 094c7c1..51dcf0d 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -24,8 +24,6 @@
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
-using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
-using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
@@ -492,31 +490,6 @@
}
/*
- * MapConstellationType:
- * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
- * GnssConstellationType_1_0 type constellation. For constellations that do not have
- * an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
- */
-GnssConstellationType_1_0 MapConstellationType(GnssConstellationType_2_0 constellation) {
- switch (constellation) {
- case GnssConstellationType_2_0::GPS:
- return GnssConstellationType_1_0::GPS;
- case GnssConstellationType_2_0::SBAS:
- return GnssConstellationType_1_0::SBAS;
- case GnssConstellationType_2_0::GLONASS:
- return GnssConstellationType_1_0::GLONASS;
- case GnssConstellationType_2_0::QZSS:
- return GnssConstellationType_1_0::QZSS;
- case GnssConstellationType_2_0::BEIDOU:
- return GnssConstellationType_1_0::BEIDOU;
- case GnssConstellationType_2_0::GALILEO:
- return GnssConstellationType_1_0::GALILEO;
- default:
- return GnssConstellationType_1_0::UNKNOWN;
- }
-}
-
-/*
* FindStrongFrequentNonGpsSource:
*
* Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
@@ -555,7 +528,7 @@
(sv_info.constellation != GnssConstellationType_2_0::GPS)) {
ComparableBlacklistedSource source;
source.id.svid = sv_info.v1_0.svid;
- source.id.constellation = MapConstellationType(sv_info.constellation);
+ source.id.constellation = Utils::mapConstellationType(sv_info.constellation);
const auto& itSignal = mapSignals.find(source);
if (itSignal == mapSignals.end()) {
@@ -694,7 +667,7 @@
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
- auto constellation = MapConstellationType(sv_info.constellation);
+ auto constellation = Utils::mapConstellationType(sv_info.constellation);
EXPECT_FALSE((sv_info.v1_0.svid == source_to_blacklist.svid) &&
(constellation == source_to_blacklist.constellation) &&
(sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
@@ -736,7 +709,7 @@
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
- auto constellation = MapConstellationType(sv_info.constellation);
+ auto constellation = Utils::mapConstellationType(sv_info.constellation);
if ((sv_info.v1_0.svid == source_to_blacklist.svid) &&
(constellation == source_to_blacklist.constellation) &&
(sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
@@ -752,7 +725,7 @@
}
/*
- * BlacklistConstellation:
+ * BlacklistConstellationWithLocationOff:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus for any non-GPS constellations.
@@ -761,12 +734,11 @@
* GnssStatus does not use any constellation but GPS.
* 4a & b) Clean up by turning off location, and send in empty blacklist.
*/
-TEST_P(GnssHalTest, BlacklistConstellation) {
+TEST_P(GnssHalTest, BlacklistConstellationWithLocationOff) {
if (!IsGnssHalVersion_2_0()) {
ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
return;
}
-
if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
return;
@@ -774,43 +746,12 @@
const int kLocationsToAwait = 3;
- gnss_cb_->location_cbq_.reset();
- StartAndCheckLocations(kLocationsToAwait);
- const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+ // Find first non-GPS constellation to blacklist
+ GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
- // Tolerate 1 less sv status to handle edge cases in reporting.
- int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
- EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
- ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
- sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+ // Turns off location
+ StopAndClearLocations();
- // Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
- // as blacklisting of this constellation is not supported in gnss@2.0.
- const int kGnssSvStatusTimeout = 2;
- GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
- for (int i = 0; i < sv_info_list_cbq_size; ++i) {
- hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
- gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
- for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
- if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
- (sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
- (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
- (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
- // found a non-GPS V1_0 constellation
- constellation_to_blacklist = MapConstellationType(sv_info.constellation);
- break;
- }
- }
- if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
- break;
- }
- }
-
- if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
- ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
- // Proceed functionally to blacklist something.
- constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
- }
IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
source_to_blacklist.constellation = constellation_to_blacklist;
source_to_blacklist.svid = 0; // documented wildcard for all satellites in this constellation
@@ -824,6 +765,7 @@
sources.resize(1);
sources[0] = source_to_blacklist;
+ // setBlacklist when location is off.
auto result = gnss_configuration_hal->setBlacklist(sources);
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
@@ -835,15 +777,93 @@
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
- sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
+ const int kGnssSvStatusTimeout = 2;
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
- auto constellation = MapConstellationType(sv_info.constellation);
+ auto constellation = Utils::mapConstellationType(sv_info.constellation);
+ EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
+ (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ }
+ }
+
+ // clean up
+ StopAndClearLocations();
+ sources.resize(0);
+ result = gnss_configuration_hal->setBlacklist(sources);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+}
+
+/*
+ * BlacklistConstellationWithLocationOn:
+ *
+ * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus for any non-GPS constellations.
+ * 2a & b) Blacklist first non-GPS constellations, and turns off location.
+ * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does not use any constellation but GPS.
+ * 4a & b) Clean up by turning off location, and send in empty blacklist.
+ */
+TEST_P(GnssHalTest, BlacklistConstellationWithLocationOn) {
+ if (!IsGnssHalVersion_2_0()) {
+ ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
+ return;
+ }
+
+ if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
+ ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
+ return;
+ }
+
+ const int kLocationsToAwait = 3;
+
+ // Find first non-GPS constellation to blacklist
+ GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
+
+ IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
+ source_to_blacklist.constellation = constellation_to_blacklist;
+ source_to_blacklist.svid = 0; // documented wildcard for all satellites in this constellation
+
+ auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
+ ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+ sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
+ ASSERT_NE(gnss_configuration_hal, nullptr);
+
+ hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
+ sources.resize(1);
+ sources[0] = source_to_blacklist;
+
+ // setBlacklist when location is on.
+ auto result = gnss_configuration_hal->setBlacklist(sources);
+ ASSERT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+
+ // Turns off location
+ StopAndClearLocations();
+
+ // retry and ensure constellation not used
+ gnss_cb_->sv_info_list_cbq_.reset();
+
+ gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(kLocationsToAwait);
+
+ // Tolerate 1 less sv status to handle edge cases in reporting.
+ int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+ ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
+ kLocationsToAwait);
+ const int kGnssSvStatusTimeout = 2;
+ for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+ hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+ for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+ auto constellation = Utils::mapConstellationType(sv_info.constellation);
EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
(sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp
index fd9613b..4c6d443 100644
--- a/gnss/common/utils/vts/Android.bp
+++ b/gnss/common/utils/vts/Android.bp
@@ -29,6 +29,7 @@
export_include_dirs: ["include"],
shared_libs: [
"android.hardware.gnss@1.0",
+ "android.hardware.gnss@2.0",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.measurement_corrections@1.1",
],
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 4b5a50f..9bf68e6 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -169,6 +169,31 @@
return mockCorrections_1_1;
}
+/*
+ * MapConstellationType:
+ * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
+ * GnssConstellationType_1_0 type constellation. For constellations that do not have
+ * an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
+ */
+GnssConstellationType_1_0 Utils::mapConstellationType(GnssConstellationType_2_0 constellation) {
+ switch (constellation) {
+ case GnssConstellationType_2_0::GPS:
+ return GnssConstellationType_1_0::GPS;
+ case GnssConstellationType_2_0::SBAS:
+ return GnssConstellationType_1_0::SBAS;
+ case GnssConstellationType_2_0::GLONASS:
+ return GnssConstellationType_1_0::GLONASS;
+ case GnssConstellationType_2_0::QZSS:
+ return GnssConstellationType_1_0::QZSS;
+ case GnssConstellationType_2_0::BEIDOU:
+ return GnssConstellationType_1_0::BEIDOU;
+ case GnssConstellationType_2_0::GALILEO:
+ return GnssConstellationType_1_0::GALILEO;
+ default:
+ return GnssConstellationType_1_0::UNKNOWN;
+ }
+}
+
} // namespace common
} // namespace gnss
} // namespace hardware
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index c3cdd18..9c838b2 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -18,9 +18,12 @@
#define android_hardware_gnss_common_vts_Utils_H_
#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
+using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation;
using namespace android::hardware::gnss::measurement_corrections::V1_0;
@@ -44,6 +47,8 @@
bool check_more_accuracies);
static const MeasurementCorrections_1_0 getMockMeasurementCorrections();
static const MeasurementCorrections_1_1 getMockMeasurementCorrections_1_1();
+
+ static GnssConstellationType_1_0 mapConstellationType(GnssConstellationType_2_0 constellation);
};
} // namespace common
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
index ccb0690..b329cb2 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
@@ -100,10 +100,11 @@
long totalSizeInBytes;
/**
- * Horizontal and vertical subsampling. Must be a positive power of 2.
+ * Horizontal and vertical subsampling. Must be a positive power of 2. A value of 1
+ * indicates no subsampling.
*
* These fields indicate the number of horizontally or vertically adjacent pixels that use
- * the same pixel data. A value of 1 indicates no subsampling.
+ * the same pixel data.
*/
long horizontalSubsampling;
long verticalSubsampling;
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 529fb18..6df7f8d 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -605,6 +605,9 @@
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
+/**
+ * Test multiple operations associated with different color formats
+ */
TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YCRCB_420_SP;
@@ -751,6 +754,90 @@
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
+TEST_P(GraphicsMapperHidlTest, Lock_RAW10) {
+ auto info = mDummyDescriptorInfo;
+ info.format = PixelFormat::RAW10;
+
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(
+ info, true, Tolerance::kToleranceUnSupported, &stride));
+ if (bufferHandle == nullptr) {
+ GTEST_SUCCEED() << "RAW10 format is unsupported";
+ return;
+ }
+
+ const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+ static_cast<int32_t>(info.height)};
+ unique_fd fence;
+
+ ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.get()));
+
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+ std::vector<PlaneLayout> planeLayouts;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+ ASSERT_EQ(1, planeLayouts.size());
+ auto planeLayout = planeLayouts[0];
+
+ EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
+ EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+ EXPECT_EQ(1, planeLayout.verticalSubsampling);
+
+ ASSERT_EQ(1, planeLayout.components.size());
+ auto planeLayoutComponent = planeLayout.components[0];
+
+ EXPECT_EQ(PlaneLayoutComponentType::RAW,
+ static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
+ EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+ EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
+
+ ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
+TEST_P(GraphicsMapperHidlTest, Lock_RAW12) {
+ auto info = mDummyDescriptorInfo;
+ info.format = PixelFormat::RAW12;
+
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(
+ info, true, Tolerance::kToleranceUnSupported, &stride));
+ if (bufferHandle == nullptr) {
+ GTEST_SUCCEED() << "RAW12 format is unsupported";
+ return;
+ }
+
+ const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+ static_cast<int32_t>(info.height)};
+ unique_fd fence;
+
+ ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.get()));
+
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+ std::vector<PlaneLayout> planeLayouts;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+ ASSERT_EQ(1, planeLayouts.size());
+ auto planeLayout = planeLayouts[0];
+
+ EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
+ EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+ EXPECT_EQ(1, planeLayout.verticalSubsampling);
+
+ ASSERT_EQ(1, planeLayout.components.size());
+ auto planeLayoutComponent = planeLayout.components[0];
+
+ EXPECT_EQ(PlaneLayoutComponentType::RAW,
+ static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
+ EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+ EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
+
+ ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
/**
* Test IMapper::unlock with bad access region
*/
@@ -1707,6 +1794,84 @@
}
/**
+ * Test get::metadata with cloned native_handle
+ */
+TEST_P(GraphicsMapperHidlTest, GetMetadataClonedHandle) {
+ const native_handle_t* bufferHandle = nullptr;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+ const auto dataspace = Dataspace::SRGB_LINEAR;
+ {
+ hidl_vec<uint8_t> metadata;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata));
+
+ Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, metadata);
+ if (err == Error::UNSUPPORTED) {
+ GTEST_SUCCEED() << "setting this metadata is unsupported";
+ return;
+ }
+ ASSERT_EQ(Error::NONE, err);
+ }
+
+ const native_handle_t* importedHandle;
+ {
+ auto clonedHandle = native_handle_clone(bufferHandle);
+ ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle));
+ native_handle_close(clonedHandle);
+ native_handle_delete(clonedHandle);
+ }
+
+ Dataspace realSpace = Dataspace::UNKNOWN;
+ {
+ hidl_vec<uint8_t> metadata;
+ ASSERT_EQ(Error::NONE,
+ mGralloc->get(importedHandle, gralloc4::MetadataType_Dataspace, &metadata));
+ ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace));
+ }
+
+ EXPECT_EQ(dataspace, realSpace);
+}
+
+/**
+ * Test set::metadata with cloned native_handle
+ */
+TEST_P(GraphicsMapperHidlTest, SetMetadataClonedHandle) {
+ const native_handle_t* bufferHandle = nullptr;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+ const native_handle_t* importedHandle;
+ {
+ auto clonedHandle = native_handle_clone(bufferHandle);
+ ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle));
+ native_handle_close(clonedHandle);
+ native_handle_delete(clonedHandle);
+ }
+
+ const auto dataspace = Dataspace::SRGB_LINEAR;
+ {
+ hidl_vec<uint8_t> metadata;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata));
+
+ Error err = mGralloc->set(importedHandle, gralloc4::MetadataType_Dataspace, metadata);
+ if (err == Error::UNSUPPORTED) {
+ GTEST_SUCCEED() << "setting this metadata is unsupported";
+ return;
+ }
+ ASSERT_EQ(Error::NONE, err);
+ }
+
+ Dataspace realSpace = Dataspace::UNKNOWN;
+ {
+ hidl_vec<uint8_t> metadata;
+ ASSERT_EQ(Error::NONE,
+ mGralloc->get(bufferHandle, gralloc4::MetadataType_Dataspace, &metadata));
+ ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace));
+ }
+
+ EXPECT_EQ(dataspace, realSpace);
+}
+
+/**
* Test IMapper::set(metadata) for constant metadata
*/
TEST_P(GraphicsMapperHidlTest, SetConstantMetadata) {
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 58473dc..cd6f9b0 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -17,13 +17,13 @@
"android.hardware.keymaster@4.0",
"libbinder",
"libcrypto",
- "libkeymaster_portable",
- "libsoft_attestation_cert",
- "libpuresoftkeymasterdevice",
"android.hardware.keymaster-ndk_platform",
],
static_libs: [
"libcppbor",
+ "libkeymaster_portable",
+ "libsoft_attestation_cert",
+ "libpuresoftkeymasterdevice",
"android.hardware.identity-support-lib",
"android.hardware.identity-cpp",
"android.hardware.keymaster-cpp",
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 6cbe4da..aa2de2a 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -438,10 +438,10 @@
EXPECT_TRUE(device_locked);
}
- // Check that the expected result from VBMeta matches the build type. Only a user build
- // should have AVB reporting the device is locked.
- EXPECT_NE(property_get("ro.build.type", property_value, ""), 0);
- if (!strcmp(property_value, "user")) {
+ // Check that the device is locked if not debuggable, e.g., user build
+ // images in CTS. For VTS, debuggable images are used to allow adb root
+ // and the device is unlocked.
+ if (!property_get_bool("ro.debuggable", false)) {
EXPECT_TRUE(device_locked);
} else {
EXPECT_FALSE(device_locked);
diff --git a/neuralnetworks/1.0/vts/functional/AndroidTest.xml b/neuralnetworks/1.0/vts/functional/AndroidTest.xml
index 54e6e91..13671f9 100644
--- a/neuralnetworks/1.0/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.0/vts/functional/AndroidTest.xml
@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
- <!-- b/155577050, temporarily disable the failing tests.
- Must be deleted after corresponding driver issues are fixed.
- -->
- <option name="native-test-flag" value="--gtest_filter=-*Validation*:*CycleTest*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_0TargetTest" />
</test>
diff --git a/neuralnetworks/1.1/vts/functional/AndroidTest.xml b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
index a6f812f..cfde60c 100644
--- a/neuralnetworks/1.1/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
- <!-- b/155577050, temporarily disable the failing tests.
- Must be deleted after corresponding driver issues are fixed.
- -->
- <option name="native-test-flag" value="--gtest_filter=-*Validation*:*CycleTest*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_1TargetTest" />
</test>
diff --git a/neuralnetworks/1.2/vts/functional/AndroidTest.xml b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
index adbdf40..3f91618 100644
--- a/neuralnetworks/1.2/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
- <!-- b/155577050, b/155674368, b/153876253, temporarily disable the test.
- Must be deleted after corresponding driver issues are fixed.
- -->
- <option name="native-test-flag" value="--gtest_filter=-*Validation*:*squeeze*_all*_inputs*:*strided_slice*_all*_inputs*:*transpose*_all*_inputs*:*l2_normalization_axis_corner_case*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_2TargetTest" />
</test>
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 449b8f3..16b313a 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -315,7 +315,8 @@
void saveModelToCache(const Model& model, const hidl_vec<hidl_handle>& modelCache,
const hidl_vec<hidl_handle>& dataCache,
- sp<IPreparedModel>* preparedModel = nullptr) {
+ sp<IPreparedModel>* preparedModel = nullptr,
+ bool allowGeneralFailure = false) {
if (preparedModel != nullptr) *preparedModel = nullptr;
// Launch prepare model.
@@ -329,7 +330,10 @@
// Retrieve prepared model.
preparedModelCallback->wait();
- ASSERT_EQ(preparedModelCallback->getStatus(), ErrorStatus::NONE);
+ const auto prepareCallbackStatus = preparedModelCallback->getStatus();
+ if (!allowGeneralFailure || prepareCallbackStatus != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(prepareCallbackStatus, ErrorStatus::NONE);
+ }
if (preparedModel != nullptr) {
*preparedModel = IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
.withDefault(nullptr);
@@ -1022,7 +1026,8 @@
// Number of operations in the large test model.
constexpr uint32_t kLargeModelSize = 100;
-constexpr uint32_t kNumIterationsTOCTOU = 100;
+constexpr uint32_t kNumSuccessfulIterationsTOCTOU = 100;
+constexpr uint32_t kMaxNumFailedIterationsTOCTOU = 100;
TEST_P(CompilationCachingTest, SaveToCache_TOCTOU) {
if (!mIsCachingSupported) return;
@@ -1050,18 +1055,30 @@
// Use a different token for modelAdd.
mToken[0]++;
- // This test is probabilistic, so we run it multiple times.
- for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
+ // This test is probabilistic, so we run it multiple times. We allow the compilation to fail
+ // because it is not related to the security aspect of the TOCTOU test. However, we need to have
+ // enough successful iterations to ensure the test coverage.
+ uint32_t numSuccessfulIterations = 0, numFailedIterations = 0;
+ while (numSuccessfulIterations < kNumSuccessfulIterationsTOCTOU) {
// Save the modelAdd compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ sp<IPreparedModel> preparedModel = nullptr;
// Spawn a thread to copy the cache content concurrently while saving to cache.
std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache));
- saveModelToCache(modelAdd, modelCache, dataCache);
+ saveModelToCache(modelAdd, modelCache, dataCache, &preparedModel,
+ /*allowGeneralFailure=*/true);
thread.join();
+
+ if (preparedModel == nullptr) {
+ numFailedIterations++;
+ ASSERT_LE(numFailedIterations, kMaxNumFailedIterationsTOCTOU);
+ } else {
+ numSuccessfulIterations++;
+ }
}
// Retrieve preparedModel from cache.
@@ -1112,14 +1129,26 @@
// Use a different token for modelAdd.
mToken[0]++;
- // This test is probabilistic, so we run it multiple times.
- for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
+ // This test is probabilistic, so we run it multiple times. We allow the compilation to fail
+ // because it is not related to the security aspect of the TOCTOU test. However, we need to have
+ // enough successful iterations to ensure the test coverage.
+ uint32_t numSuccessfulIterations = 0, numFailedIterations = 0;
+ while (numSuccessfulIterations < kNumSuccessfulIterationsTOCTOU) {
// Save the modelAdd compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(modelAdd, modelCache, dataCache);
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(modelAdd, modelCache, dataCache, &preparedModel,
+ /*allowGeneralFailure=*/true);
+
+ if (preparedModel == nullptr) {
+ numFailedIterations++;
+ ASSERT_LE(numFailedIterations, kMaxNumFailedIterationsTOCTOU);
+ } else {
+ numSuccessfulIterations++;
+ }
}
// Retrieve preparedModel from cache.
diff --git a/neuralnetworks/1.3/vts/functional/AndroidTest.xml b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
index 30cff2e..e5acd90 100644
--- a/neuralnetworks/1.3/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
- <!-- b/156691406, b/155577050, b/155674368, b/153876253, temporarily disable the test.
- Must be deleted after corresponding driver issues are fixed.
- -->
- <option name="native-test-flag" value="--gtest_filter=-*Validation*:*DynamicOutputShapeTest*:*FencedComputeTest*:*MemoryDomain*:*QuantizationCouplingTest*:*DeadlineTest*:*resize_*_v1_3*:*squeeze*_all*_inputs*:*strided_slice*_all*_inputs*:*transpose*_all*_inputs*:*l2_normalization_axis_corner_case*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_3TargetTest" />
</test>
diff --git a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
index ac18c8f..382fc76 100644
--- a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
@@ -318,7 +318,8 @@
void saveModelToCache(const Model& model, const hidl_vec<hidl_handle>& modelCache,
const hidl_vec<hidl_handle>& dataCache,
- sp<IPreparedModel>* preparedModel = nullptr) {
+ sp<IPreparedModel>* preparedModel = nullptr,
+ bool allowGeneralFailure = false) {
if (preparedModel != nullptr) *preparedModel = nullptr;
// Launch prepare model.
@@ -332,7 +333,10 @@
// Retrieve prepared model.
preparedModelCallback->wait();
- ASSERT_EQ(preparedModelCallback->getStatus(), ErrorStatus::NONE);
+ const auto prepareCallbackStatus = preparedModelCallback->getStatus();
+ if (!allowGeneralFailure || prepareCallbackStatus != ErrorStatus::GENERAL_FAILURE) {
+ ASSERT_EQ(prepareCallbackStatus, ErrorStatus::NONE);
+ }
if (preparedModel != nullptr) {
*preparedModel = IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
.withDefault(nullptr);
@@ -1013,7 +1017,8 @@
// Number of operations in the large test model.
constexpr uint32_t kLargeModelSize = 100;
-constexpr uint32_t kNumIterationsTOCTOU = 100;
+constexpr uint32_t kNumSuccessfulIterationsTOCTOU = 100;
+constexpr uint32_t kMaxNumFailedIterationsTOCTOU = 100;
TEST_P(CompilationCachingTest, SaveToCache_TOCTOU) {
if (!mIsCachingSupported) return;
@@ -1041,18 +1046,30 @@
// Use a different token for modelAdd.
mToken[0]++;
- // This test is probabilistic, so we run it multiple times.
- for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
+ // This test is probabilistic, so we run it multiple times. We allow the compilation to fail
+ // because it is not related to the security aspect of the TOCTOU test. However, we need to have
+ // enough successful iterations to ensure the test coverage.
+ uint32_t numSuccessfulIterations = 0, numFailedIterations = 0;
+ while (numSuccessfulIterations < kNumSuccessfulIterationsTOCTOU) {
// Save the modelAdd compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
+ sp<IPreparedModel> preparedModel = nullptr;
// Spawn a thread to copy the cache content concurrently while saving to cache.
std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache));
- saveModelToCache(modelAdd, modelCache, dataCache);
+ saveModelToCache(modelAdd, modelCache, dataCache, &preparedModel,
+ /*allowGeneralFailure=*/true);
thread.join();
+
+ if (preparedModel == nullptr) {
+ numFailedIterations++;
+ ASSERT_LE(numFailedIterations, kMaxNumFailedIterationsTOCTOU);
+ } else {
+ numSuccessfulIterations++;
+ }
}
// Retrieve preparedModel from cache.
@@ -1103,14 +1120,26 @@
// Use a different token for modelAdd.
mToken[0]++;
- // This test is probabilistic, so we run it multiple times.
- for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
+ // This test is probabilistic, so we run it multiple times. We allow the compilation to fail
+ // because it is not related to the security aspect of the TOCTOU test. However, we need to have
+ // enough successful iterations to ensure the test coverage.
+ uint32_t numSuccessfulIterations = 0, numFailedIterations = 0;
+ while (numSuccessfulIterations < kNumSuccessfulIterationsTOCTOU) {
// Save the modelAdd compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(modelAdd, modelCache, dataCache);
+ sp<IPreparedModel> preparedModel = nullptr;
+ saveModelToCache(modelAdd, modelCache, dataCache, &preparedModel,
+ /*allowGeneralFailure=*/true);
+
+ if (preparedModel == nullptr) {
+ numFailedIterations++;
+ ASSERT_LE(numFailedIterations, kMaxNumFailedIterationsTOCTOU);
+ } else {
+ numSuccessfulIterations++;
+ }
}
// Retrieve preparedModel from cache.
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
index 02dcbab..08121fd 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
@@ -49,7 +49,6 @@
}
EXPECT_EQ(CardState::ABSENT, cardStatus.cardState);
}
-#endif
/* Test setSimCardPower power up */
serial = GetRandomSerialNumber();
@@ -60,6 +59,7 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE}));
+#endif
/**
* If the sim card status for the testing environment is PRESENT,
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index 8cbb2d0..9b6d450 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -1017,8 +1017,10 @@
return Void();
}
-Return<void> RadioResponse_v1_5::sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& /*info*/,
+Return<void> RadioResponse_v1_5::sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
const SendSmsResult& /*sms*/) {
+ rspInfo = info;
+ parent_v1_5.notify(info.serial);
return Void();
}
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index b74f6ec..67eff1b 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -48,8 +48,6 @@
return Result::INVALID_STATE;
}
- mFrontendSourceFile = mFrontend->getSourceFile();
-
mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
return Result::SUCCESS;
@@ -62,8 +60,6 @@
uint32_t filterId;
filterId = ++mLastUsedFilterId;
- mUsedFilterIds.insert(filterId);
-
if (cb == nullptr) {
ALOGW("[Demux] callback can't be null");
_hidl_cb(Result::INVALID_ARGUMENT, new Filter());
@@ -82,8 +78,13 @@
mPcrFilterIds.insert(filterId);
}
bool result = true;
- if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
- result = mDvr->addPlaybackFilter(filter);
+ if (!filter->isRecordFilter()) {
+ // Only save non-record filters for now. Record filters are saved when the
+ // IDvr.attacheFilter is called.
+ mPlaybackFilterIds.insert(filterId);
+ if (mDvrPlayback != nullptr) {
+ result = mDvrPlayback->addPlaybackFilter(filterId, filter);
+ }
}
_hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
@@ -93,9 +94,9 @@
Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
- sp<TimeFilter> timeFilter = new TimeFilter(this);
+ mTimeFilter = new TimeFilter(this);
- _hidl_cb(Result::SUCCESS, timeFilter);
+ _hidl_cb(Result::SUCCESS, mTimeFilter);
return Void();
}
@@ -154,7 +155,13 @@
Return<Result> Demux::close() {
ALOGV("%s", __FUNCTION__);
- mUsedFilterIds.clear();
+ set<uint32_t>::iterator it;
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+ mDvrPlayback->removePlaybackFilter(*it);
+ }
+ mPlaybackFilterIds.clear();
+ mRecordFilterIds.clear();
+ mFilters.clear();
mLastUsedFilterId = -1;
return Result::SUCCESS;
@@ -170,15 +177,38 @@
return Void();
}
- mDvr = new Dvr(type, bufferSize, cb, this);
+ set<uint32_t>::iterator it;
+ switch (type) {
+ case DvrType::PLAYBACK:
+ mDvrPlayback = new Dvr(type, bufferSize, cb, this);
+ if (!mDvrPlayback->createDvrMQ()) {
+ _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+ return Void();
+ }
- if (!mDvr->createDvrMQ()) {
- _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
- return Void();
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+ if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
+ ALOGE("[Demux] Can't get filter info for DVR playback");
+ _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+ return Void();
+ }
+ }
+
+ _hidl_cb(Result::SUCCESS, mDvrPlayback);
+ return Void();
+ case DvrType::RECORD:
+ mDvrRecord = new Dvr(type, bufferSize, cb, this);
+ if (!mDvrRecord->createDvrMQ()) {
+ _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
+ return Void();
+ }
+
+ _hidl_cb(Result::SUCCESS, mDvrRecord);
+ return Void();
+ default:
+ _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
+ return Void();
}
-
- _hidl_cb(Result::SUCCESS, mDvr);
- return Void();
}
Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
@@ -198,8 +228,10 @@
Result Demux::removeFilter(uint32_t filterId) {
ALOGV("%s", __FUNCTION__);
- // resetFilterRecords(filterId);
- mUsedFilterIds.erase(filterId);
+ if (mDvrPlayback != nullptr) {
+ mDvrPlayback->removePlaybackFilter(filterId);
+ }
+ mPlaybackFilterIds.erase(filterId);
mRecordFilterIds.erase(filterId);
mFilters.erase(filterId);
@@ -212,7 +244,7 @@
if (DEBUG_DEMUX) {
ALOGW("[Demux] start ts filter pid: %d", pid);
}
- for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
if (pid == mFilters[*it]->getTpid()) {
mFilters[*it]->updateFilterOutput(data);
}
@@ -233,7 +265,7 @@
set<uint32_t>::iterator it;
// Handle the output data per filter type
- for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
return false;
}
@@ -280,58 +312,27 @@
void Demux::frontendInputThreadLoop() {
std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
mFrontendInputThreadRunning = true;
- mKeepFetchingDataFromFrontend = true;
-
- // open the stream and get its length
- std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
- // TODO take the packet size from the frontend setting
- int packetSize = 188;
- int writePacketAmount = 6;
- char* buffer = new char[packetSize];
- ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
- if (!inputData.is_open()) {
- mFrontendInputThreadRunning = false;
- ALOGW("[Demux] Error %s", strerror(errno));
- }
while (mFrontendInputThreadRunning) {
- // move the stream pointer for packet size * 6 every read until the end
- while (mKeepFetchingDataFromFrontend) {
- for (int i = 0; i < writePacketAmount; i++) {
- inputData.read(buffer, packetSize);
- if (!inputData) {
- mKeepFetchingDataFromFrontend = false;
- mFrontendInputThreadRunning = false;
- break;
- }
- // filter and dispatch filter output
- vector<uint8_t> byteBuffer;
- byteBuffer.resize(packetSize);
- for (int index = 0; index < byteBuffer.size(); index++) {
- byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
- }
- if (mIsRecording) {
- // Feed the data into the Dvr recording input
- sendFrontendInputToRecord(byteBuffer);
- } else {
- // Feed the data into the broadcast demux filter
- startBroadcastTsFilter(byteBuffer);
- }
- }
- if (mIsRecording) {
- // Dispatch the data into the broadcasting filters.
- startRecordFilterDispatcher();
- } else {
- // Dispatch the data into the broadcasting filters.
- startBroadcastFilterDispatcher();
- }
- usleep(100);
+ uint32_t efState = 0;
+ status_t status = mDvrPlayback->getDvrEventFlag()->wait(
+ static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
+ true /* retry on spurious wake */);
+ if (status != OK) {
+ ALOGD("[Demux] wait for data ready on the playback FMQ");
+ continue;
+ }
+ // Our current implementation filter the data and write it into the filter FMQ immediately
+ // after the DATA_READY from the VTS/framework
+ if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
+ !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
+ ALOGE("[Demux] playback data failed to be filtered. Ending thread");
+ break;
}
}
+ mFrontendInputThreadRunning = false;
ALOGW("[Demux] Frontend Input thread end.");
- delete[] buffer;
- inputData.close();
}
void Demux::stopFrontendInput() {
@@ -346,18 +347,19 @@
}
bool Demux::attachRecordFilter(int filterId) {
- if (mFilters[filterId] == nullptr || mDvr == nullptr) {
+ if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
+ !mFilters[filterId]->isRecordFilter()) {
return false;
}
mRecordFilterIds.insert(filterId);
- mFilters[filterId]->attachFilterToRecord(mDvr);
+ mFilters[filterId]->attachFilterToRecord(mDvrRecord);
return true;
}
bool Demux::detachRecordFilter(int filterId) {
- if (mFilters[filterId] == nullptr || mDvr == nullptr) {
+ if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
return false;
}
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 6c46b0d..7f282b2 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -91,13 +91,23 @@
void setIsRecording(bool isRecording);
void startFrontendInputLoop();
+ /**
+ * A dispatcher to read and dispatch input data to all the started filters.
+ * Each filter handler handles the data filtering/output writing/filterEvent updating.
+ * Note that recording filters are not included.
+ */
+ bool startBroadcastFilterDispatcher();
+ void startBroadcastTsFilter(vector<uint8_t> data);
+
+ void sendFrontendInputToRecord(vector<uint8_t> data);
+ bool startRecordFilterDispatcher();
+
private:
// Tuner service
sp<Tuner> mTunerService;
// Frontend source
sp<Frontend> mFrontend;
- string mFrontendSourceFile;
// A struct that passes the arguments to a newly created filter thread
struct ThreadArgs {
@@ -117,16 +127,6 @@
*/
void deleteEventFlag();
bool readDataFromMQ();
- /**
- * A dispatcher to read and dispatch input data to all the started filters.
- * Each filter handler handles the data filtering/output writing/filterEvent updating.
- * Note that recording filters are not included.
- */
- bool startBroadcastFilterDispatcher();
- void startBroadcastTsFilter(vector<uint8_t> data);
-
- void sendFrontendInputToRecord(vector<uint8_t> data);
- bool startRecordFilterDispatcher();
uint32_t mDemuxId;
uint32_t mCiCamId;
@@ -137,25 +137,31 @@
*/
uint32_t mLastUsedFilterId = -1;
/**
- * Record all the used filter Ids.
+ * Record all the used playback filter Ids.
* Any removed filter id should be removed from this set.
*/
- set<uint32_t> mUsedFilterIds;
+ set<uint32_t> mPlaybackFilterIds;
/**
* Record all the attached record filter Ids.
* Any removed filter id should be removed from this set.
*/
set<uint32_t> mRecordFilterIds;
/**
- * A list of created FilterMQ ptrs.
+ * A list of created Filter sp.
* The array number is the filter ID.
*/
std::map<uint32_t, sp<Filter>> mFilters;
/**
+ * Local reference to the opened Timer Filter instance.
+ */
+ sp<TimeFilter> mTimeFilter;
+
+ /**
* Local reference to the opened DVR object.
*/
- sp<Dvr> mDvr;
+ sp<Dvr> mDvrPlayback;
+ sp<Dvr> mDvrRecord;
// Thread handlers
pthread_t mFrontendInputThread;
diff --git a/tv/tuner/1.0/default/Dvr.cpp b/tv/tuner/1.0/default/Dvr.cpp
index adb2635..68e175c 100644
--- a/tv/tuner/1.0/default/Dvr.cpp
+++ b/tv/tuner/1.0/default/Dvr.cpp
@@ -70,8 +70,7 @@
return status;
}
- // check if the attached filter is a record filter
- mFilters[filterId] = filter;
+ // TODO check if the attached filter is a record filter
if (!mDemux->attachRecordFilter(filterId)) {
return Result::INVALID_ARGUMENT;
}
@@ -94,19 +93,8 @@
return status;
}
- std::map<uint32_t, sp<IFilter>>::iterator it;
-
- it = mFilters.find(filterId);
- if (it != mFilters.end()) {
- mFilters.erase(filterId);
- if (!mDemux->detachRecordFilter(filterId)) {
- return Result::INVALID_ARGUMENT;
- }
- }
-
- // If all the filters are detached, record can't be started
- if (mFilters.empty()) {
- mIsRecordFilterAttached = false;
+ if (!mDemux->detachRecordFilter(filterId)) {
+ return Result::INVALID_ARGUMENT;
}
return Result::SUCCESS;
@@ -183,6 +171,10 @@
return true;
}
+EventFlag* Dvr::getDvrEventFlag() {
+ return mDvrEventFlag;
+}
+
void* Dvr::__threadLoopPlayback(void* user) {
Dvr* const self = static_cast<Dvr*>(user);
self->playbackThreadLoop();
@@ -205,8 +197,9 @@
}
// Our current implementation filter the data and write it into the filter FMQ immediately
// after the DATA_READY from the VTS/framework
- if (!readPlaybackFMQ() || !startFilterDispatcher()) {
- ALOGD("[Dvr] playback data failed to be filtered. Ending thread");
+ if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) ||
+ !startFilterDispatcher(false /*isVirtualFrontend*/, false /*isRecording*/)) {
+ ALOGE("[Dvr] playback data failed to be filtered. Ending thread");
break;
}
@@ -245,7 +238,7 @@
return mPlaybackStatus;
}
-bool Dvr::readPlaybackFMQ() {
+bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) {
// Read playback data from the input FMQ
int size = mDvrMQ->availableToRead();
int playbackPacketSize = mDvrSettings.playback().packetSize;
@@ -256,7 +249,15 @@
if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) {
return false;
}
- startTpidFilter(dataOutputBuffer);
+ if (isVirtualFrontend) {
+ if (isRecording) {
+ mDemux->sendFrontendInputToRecord(dataOutputBuffer);
+ } else {
+ mDemux->startBroadcastTsFilter(dataOutputBuffer);
+ }
+ } else {
+ startTpidFilter(dataOutputBuffer);
+ }
}
return true;
@@ -275,7 +276,15 @@
}
}
-bool Dvr::startFilterDispatcher() {
+bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) {
+ if (isVirtualFrontend) {
+ if (isRecording) {
+ return mDemux->startRecordFilterDispatcher();
+ } else {
+ return mDemux->startBroadcastFilterDispatcher();
+ }
+ }
+
std::map<uint32_t, sp<IFilter>>::iterator it;
// Handle the output data per filter type
for (it = mFilters.begin(); it != mFilters.end(); it++) {
@@ -329,27 +338,15 @@
return mRecordStatus;
}
-bool Dvr::addPlaybackFilter(sp<IFilter> filter) {
- uint32_t filterId;
- Result status;
-
- filter->getId([&](Result result, uint32_t id) {
- filterId = id;
- status = result;
- });
-
- if (status != Result::SUCCESS) {
- return false;
- }
-
+bool Dvr::addPlaybackFilter(uint32_t filterId, sp<IFilter> filter) {
mFilters[filterId] = filter;
return true;
}
-DvrType Dvr::getType() {
- return mType;
+bool Dvr::removePlaybackFilter(uint32_t filterId) {
+ mFilters.erase(filterId);
+ return true;
}
-
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Dvr.h b/tv/tuner/1.0/default/Dvr.h
index 08afd5d..a63a256 100644
--- a/tv/tuner/1.0/default/Dvr.h
+++ b/tv/tuner/1.0/default/Dvr.h
@@ -81,8 +81,11 @@
bool createDvrMQ();
void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer);
bool writeRecordFMQ(const std::vector<uint8_t>& data);
- DvrType getType();
- bool addPlaybackFilter(sp<IFilter> filter);
+ bool addPlaybackFilter(uint32_t filterId, sp<IFilter> filter);
+ bool removePlaybackFilter(uint32_t filterId);
+ bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording);
+ bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording);
+ EventFlag* getDvrEventFlag();
private:
// Demux service
@@ -105,9 +108,7 @@
* A dispatcher to read and dispatch input data to all the started filters.
* Each filter handler handles the data filtering/output writing/filterEvent updating.
*/
- bool readPlaybackFMQ();
void startTpidFilter(vector<uint8_t> data);
- bool startFilterDispatcher();
static void* __threadLoopPlayback(void* user);
static void* __threadLoopRecord(void* user);
void playbackThreadLoop();
@@ -123,7 +124,6 @@
// Thread handlers
pthread_t mDvrThread;
- pthread_t mBroadcastInputThread;
// FMQ status local records
PlaybackStatus mPlaybackStatus;
@@ -132,7 +132,6 @@
* If a specific filter's writing loop is still running
*/
bool mDvrThreadRunning;
- bool mBroadcastInputThreadRunning;
bool mKeepFetchingDataFromFrontend;
/**
* Lock to protect writes to the FMQs
@@ -143,7 +142,6 @@
*/
std::mutex mPlaybackStatusLock;
std::mutex mRecordStatusLock;
- std::mutex mBroadcastInputThreadLock;
std::mutex mDvrThreadLock;
const bool DEBUG_DVR = false;
@@ -151,7 +149,6 @@
// Booleans to check if recording is running.
// Recording is ready when both of the following are set to true.
bool mIsRecordStarted = false;
- bool mIsRecordFilterAttached = false;
};
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index 8bca70c..30b19c0 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -47,12 +47,18 @@
if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) {
mIsPcrFilter = true;
}
+ if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) {
+ mIsRecordFilter = true;
+ }
break;
case DemuxFilterMainType::MMTP:
if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
mIsMediaFilter = true;
}
+ if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) {
+ mIsRecordFilter = true;
+ }
break;
case DemuxFilterMainType::IP:
break;
@@ -535,12 +541,6 @@
}
Result Filter::startRecordFilterHandler() {
- /*DemuxFilterTsRecordEvent tsRecordEvent;
- tsRecordEvent.pid.tPid(0);
- tsRecordEvent.indexMask.tsIndexMask(0x01);
- mFilterEvent.events.resize(1);
- mFilterEvent.events[0].tsRecord(tsRecordEvent);
-*/
std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
if (mRecordFilterOutput.empty()) {
return Result::SUCCESS;
@@ -567,7 +567,7 @@
bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) {
// TODO check how many sections has been read
- ALOGD("[Filter] section hander");
+ ALOGD("[Filter] section handler");
std::lock_guard<std::mutex> lock(mFilterEventLock);
if (!writeDataToFilterMQ(data)) {
return false;
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index 09e9604..9386dca 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -91,6 +91,7 @@
void freeAvHandle();
bool isMediaFilter() { return mIsMediaFilter; };
bool isPcrFilter() { return mIsPcrFilter; };
+ bool isRecordFilter() { return mIsRecordFilter; };
private:
// Tuner service
@@ -107,6 +108,7 @@
DemuxFilterType mType;
bool mIsMediaFilter = false;
bool mIsPcrFilter = false;
+ bool mIsRecordFilter = false;
DemuxFilterSettings mFilterSettings;
uint16_t mTpid;
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index 61bbbf8..8bf0ec5 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -66,7 +66,7 @@
mTunerService->frontendStartTune(mId);
mCallback->onEvent(FrontendEventType::LOCKED);
- mIsLocked = false;
+ mIsLocked = true;
return Result::SUCCESS;
}
@@ -268,14 +268,14 @@
return mId;
}
-string Frontend::getSourceFile() {
- return FRONTEND_STREAM_FILE;
-}
-
bool Frontend::supportsSatellite() {
return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
mType == FrontendType::ISDBS3;
}
+
+bool Frontend::isLocked() {
+ return mIsLocked;
+}
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
index c0d1613..a529b74 100644
--- a/tv/tuner/1.0/default/Frontend.h
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -68,6 +68,8 @@
string getSourceFile();
+ bool isLocked();
+
private:
virtual ~Frontend();
bool supportsSatellite();
@@ -77,7 +79,6 @@
FrontendId mId = 0;
bool mIsLocked = false;
- const string FRONTEND_STREAM_FILE = "/vendor/etc/segment000000.ts";
std::ifstream mFrontendData;
};
diff --git a/tv/tuner/1.0/default/TimeFilter.cpp b/tv/tuner/1.0/default/TimeFilter.cpp
index 0b1fd1c..cec824f 100644
--- a/tv/tuner/1.0/default/TimeFilter.cpp
+++ b/tv/tuner/1.0/default/TimeFilter.cpp
@@ -34,24 +34,32 @@
TimeFilter::~TimeFilter() {}
-Return<Result> TimeFilter::setTimeStamp(uint64_t /* timeStamp */) {
+Return<Result> TimeFilter::setTimeStamp(uint64_t timeStamp) {
ALOGV("%s", __FUNCTION__);
+ if (timeStamp == INVALID_TIME_STAMP) {
+ return Result::INVALID_ARGUMENT;
+ }
+ mTimeStamp = timeStamp;
+ mBeginTime = time(NULL);
return Result::SUCCESS;
}
Return<Result> TimeFilter::clearTimeStamp() {
ALOGV("%s", __FUNCTION__);
+ mTimeStamp = INVALID_TIME_STAMP;
return Result::SUCCESS;
}
Return<void> TimeFilter::getTimeStamp(getTimeStamp_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
+ if (mTimeStamp == INVALID_TIME_STAMP) {
+ _hidl_cb(Result::INVALID_STATE, mTimeStamp);
+ }
- uint64_t timeStamp = 0;
-
- _hidl_cb(Result::SUCCESS, timeStamp);
+ uint64_t currentTimeStamp = mTimeStamp + difftime(time(NULL), mBeginTime) * 900000;
+ _hidl_cb(Result::SUCCESS, currentTimeStamp);
return Void();
}
@@ -66,6 +74,7 @@
Return<Result> TimeFilter::close() {
ALOGV("%s", __FUNCTION__);
+ mTimeStamp = INVALID_TIME_STAMP;
return Result::SUCCESS;
}
diff --git a/tv/tuner/1.0/default/TimeFilter.h b/tv/tuner/1.0/default/TimeFilter.h
index 7131df8..cb3f29d 100644
--- a/tv/tuner/1.0/default/TimeFilter.h
+++ b/tv/tuner/1.0/default/TimeFilter.h
@@ -19,6 +19,7 @@
#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
#include "Demux.h"
+#include "time.h"
using namespace std;
@@ -35,6 +36,8 @@
using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+#define INVALID_TIME_STAMP -1
+
class Demux;
class TimeFilter : public ITimeFilter {
@@ -57,6 +60,8 @@
private:
sp<Demux> mDemux;
+ uint64_t mTimeStamp = INVALID_TIME_STAMP;
+ time_t mBeginTime;
};
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index ae8070c..48ce384 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -231,6 +231,9 @@
void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
mFrontendToDemux[frontendId] = demuxId;
+ if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
+ mDemuxes[demuxId]->startFrontendInputLoop();
+ }
}
void Tuner::frontendStopTune(uint32_t frontendId) {
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp
index 7e7f8e6..0dfc032 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp
@@ -49,49 +49,73 @@
EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
android::OK);
- // open the stream and get its length
- std::ifstream inputData(mInputDataFile.c_str(), std::ifstream::binary);
- int writeSize = mPlaybackSettings.packetSize * 6;
- char* buffer = new char[writeSize];
- ALOGW("[vts] playback thread loop start %s!", mInputDataFile.c_str());
- if (!inputData.is_open()) {
+ int fd = open(mInputDataFile.c_str(), O_RDONLY | O_LARGEFILE);
+ int readBytes;
+ uint32_t regionSize = 0;
+ uint8_t* buffer;
+ ALOGW("[vts] playback thread loop start %s", mInputDataFile.c_str());
+ if (fd < 0) {
mPlaybackThreadRunning = false;
ALOGW("[vts] Error %s", strerror(errno));
}
while (mPlaybackThreadRunning) {
- // move the stream pointer for packet size * 6 every read until the end
while (mKeepWritingPlaybackFMQ) {
- inputData.read(buffer, writeSize);
- if (!inputData) {
- int leftSize = inputData.gcount();
- if (leftSize == 0) {
- mPlaybackThreadRunning = false;
- break;
- }
- inputData.clear();
- inputData.read(buffer, leftSize);
- // Write the left over of the input data and quit the thread
- if (leftSize > 0) {
- EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
- playbackMQEventFlag->wake(
- static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
- }
+ int totalWrite = mPlaybackMQ->availableToWrite();
+ if (totalWrite * 4 < mPlaybackMQ->getQuantumCount()) {
+ // Wait for the HAL implementation to read more data then write.
+ continue;
+ }
+ MessageQueue<uint8_t, kSynchronizedReadWrite>::MemTransaction memTx;
+ if (!mPlaybackMQ->beginWrite(totalWrite, &memTx)) {
+ ALOGW("[vts] Fail to write into Playback fmq.");
mPlaybackThreadRunning = false;
break;
}
- // Write input FMQ and notify the Tuner Implementation
- EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
+ auto first = memTx.getFirstRegion();
+ buffer = first.getAddress();
+ regionSize = first.getLength();
+
+ if (regionSize > 0) {
+ readBytes = read(fd, buffer, regionSize);
+ if (readBytes <= 0) {
+ if (readBytes < 0) {
+ ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
+ } else {
+ ALOGW("[vts] playback input EOF.");
+ }
+ mPlaybackThreadRunning = false;
+ break;
+ }
+ }
+ if (regionSize == 0 || (readBytes == regionSize && regionSize < totalWrite)) {
+ auto second = memTx.getSecondRegion();
+ buffer = second.getAddress();
+ regionSize = second.getLength();
+ int ret = read(fd, buffer, regionSize);
+ if (ret <= 0) {
+ if (ret < 0) {
+ ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
+ } else {
+ ALOGW("[vts] playback input EOF.");
+ }
+ mPlaybackThreadRunning = false;
+ break;
+ }
+ readBytes += ret;
+ }
+ if (!mPlaybackMQ->commitWrite(readBytes)) {
+ ALOGW("[vts] Failed to commit write playback fmq.");
+ mPlaybackThreadRunning = false;
+ break;
+ }
playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
- inputData.seekg(writeSize, inputData.cur);
- sleep(1);
}
}
+ mPlaybackThreadRunning = false;
ALOGW("[vts] Playback thread end.");
-
- delete[] buffer;
- inputData.close();
+ close(fd);
}
void DvrCallback::testRecordOutput() {
@@ -186,32 +210,65 @@
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
// Create dvr callback
- mDvrCallback = new DvrCallback();
+ if (type == DvrType::PLAYBACK) {
+ mDvrPlaybackCallback = new DvrCallback();
+ mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback,
+ [&](Result result, const sp<IDvr>& dvr) {
+ mDvrPlayback = dvr;
+ status = result;
+ });
+ if (status == Result::SUCCESS) {
+ mDvrPlaybackCallback->setDvr(mDvrPlayback);
+ }
+ }
- mDemux->openDvr(type, bufferSize, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
- mDvr = dvr;
+ if (type == DvrType::RECORD) {
+ mDvrRecordCallback = new DvrCallback();
+ mDemux->openDvr(type, bufferSize, mDvrRecordCallback,
+ [&](Result result, const sp<IDvr>& dvr) {
+ mDvrRecord = dvr;
+ status = result;
+ });
+ if (status == Result::SUCCESS) {
+ mDvrRecordCallback->setDvr(mDvrRecord);
+ }
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) {
+ Result status = mDvrPlayback->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrRecord(DvrSettings setting) {
+ Result status = mDvrRecord->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::getDvrPlaybackMQDescriptor() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+ mDvrPlayback->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+ mDvrPlaybackMQDescriptor = dvrMQDesc;
status = result;
});
- if (status == Result::SUCCESS) {
- mDvrCallback->setDvr(mDvr);
- }
return AssertionResult(status == Result::SUCCESS);
}
-AssertionResult DvrTests::configDvr(DvrSettings setting) {
- Result status = mDvr->configure(setting);
-
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult DvrTests::getDvrMQDescriptor() {
+AssertionResult DvrTests::getDvrRecordMQDescriptor() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
- mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
- mDvrMQDescriptor = dvrMQDesc;
+ mDvrRecord->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+ mDvrRecordMQDescriptor = dvrMQDesc;
status = result;
});
@@ -221,9 +278,9 @@
AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
- status = mDvr->attachFilter(filter);
+ status = mDvrRecord->attachFilter(filter);
return AssertionResult(status == Result::SUCCESS);
}
@@ -231,35 +288,61 @@
AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
- status = mDvr->detachFilter(filter);
+ status = mDvrRecord->detachFilter(filter);
return AssertionResult(status == Result::SUCCESS);
}
-AssertionResult DvrTests::startDvr() {
+AssertionResult DvrTests::startDvrPlayback() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
- status = mDvr->start();
+ status = mDvrPlayback->start();
return AssertionResult(status == Result::SUCCESS);
}
-AssertionResult DvrTests::stopDvr() {
+AssertionResult DvrTests::stopDvrPlayback() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
- status = mDvr->stop();
+ status = mDvrPlayback->stop();
return AssertionResult(status == Result::SUCCESS);
}
-void DvrTests::closeDvr() {
+void DvrTests::closeDvrPlayback() {
ASSERT_TRUE(mDemux);
- ASSERT_TRUE(mDvr);
- ASSERT_TRUE(mDvr->close() == Result::SUCCESS);
+ ASSERT_TRUE(mDvrPlayback);
+ ASSERT_TRUE(mDvrPlayback->close() == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::startDvrRecord() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+ status = mDvrRecord->start();
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::stopDvrRecord() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+ status = mDvrRecord->stop();
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+void DvrTests::closeDvrRecord() {
+ ASSERT_TRUE(mDemux);
+ ASSERT_TRUE(mDvrRecord);
+ ASSERT_TRUE(mDvrRecord->close() == Result::SUCCESS);
}
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.h b/tv/tuner/1.0/vts/functional/DvrTests.h
index dd00c27..3997839 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.h
+++ b/tv/tuner/1.0/vts/functional/DvrTests.h
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
#include <android/hardware/tv/tuner/1.0/IDvr.h>
#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <android/hardware/tv/tuner/1.0/types.h>
+#include <fcntl.h>
#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
#include <hidl/Status.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
@@ -52,6 +53,8 @@
using android::hardware::tv::tuner::V1_0::RecordStatus;
using android::hardware::tv::tuner::V1_0::Result;
+using namespace std;
+
#define WAIT_TIMEOUT 3000000000
class DvrCallback : public IDvrCallback {
@@ -149,25 +152,31 @@
void setDemux(sp<IDemux> demux) { mDemux = demux; }
void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) {
- mDvrCallback->startPlaybackInputThread(dataInputFile, settings, mDvrMQDescriptor);
+ mDvrPlaybackCallback->startPlaybackInputThread(dataInputFile, settings,
+ mDvrPlaybackMQDescriptor);
};
void startRecordOutputThread(RecordSettings settings) {
- mDvrCallback->startRecordOutputThread(settings, mDvrMQDescriptor);
+ mDvrRecordCallback->startRecordOutputThread(settings, mDvrRecordMQDescriptor);
};
- void stopPlaybackThread() { mDvrCallback->stopPlaybackThread(); }
- void testRecordOutput() { mDvrCallback->testRecordOutput(); }
- void stopRecordThread() { mDvrCallback->stopPlaybackThread(); }
+ void stopPlaybackThread() { mDvrPlaybackCallback->stopPlaybackThread(); }
+ void testRecordOutput() { mDvrRecordCallback->testRecordOutput(); }
+ void stopRecordThread() { mDvrRecordCallback->stopRecordThread(); }
AssertionResult openDvrInDemux(DvrType type, uint32_t bufferSize);
- AssertionResult configDvr(DvrSettings setting);
- AssertionResult getDvrMQDescriptor();
+ AssertionResult configDvrPlayback(DvrSettings setting);
+ AssertionResult configDvrRecord(DvrSettings setting);
+ AssertionResult getDvrPlaybackMQDescriptor();
+ AssertionResult getDvrRecordMQDescriptor();
AssertionResult attachFilterToDvr(sp<IFilter> filter);
AssertionResult detachFilterToDvr(sp<IFilter> filter);
- AssertionResult stopDvr();
- AssertionResult startDvr();
- void closeDvr();
+ AssertionResult stopDvrPlayback();
+ AssertionResult startDvrPlayback();
+ AssertionResult stopDvrRecord();
+ AssertionResult startDvrRecord();
+ void closeDvrPlayback();
+ void closeDvrRecord();
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
@@ -175,11 +184,11 @@
static AssertionResult success() { return ::testing::AssertionSuccess(); }
sp<ITuner> mService;
- sp<IDvr> mDvr;
+ sp<IDvr> mDvrPlayback;
+ sp<IDvr> mDvrRecord;
sp<IDemux> mDemux;
- sp<DvrCallback> mDvrCallback;
- MQDesc mDvrMQDescriptor;
-
- pthread_t mPlaybackshread;
- bool mPlaybackThreadRunning;
+ sp<DvrCallback> mDvrPlaybackCallback;
+ sp<DvrCallback> mDvrRecordCallback;
+ MQDesc mDvrPlaybackMQDescriptor;
+ MQDesc mDvrRecordMQDescriptor;
};
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
index ca8bd19..0ecdf73 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -149,6 +149,44 @@
return AssertionResult(status == Result::SUCCESS);
}
+AssertionResult FilterTests::openTimeFilterInDemux() {
+ if (!mDemux) {
+ ALOGW("[vts] Test with openDemux first.");
+ return failure();
+ }
+
+ // Add time filter to the local demux
+ Result status;
+ mDemux->openTimeFilter([&](Result result, const sp<ITimeFilter>& filter) {
+ mTimeFilter = filter;
+ status = result;
+ });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::setTimeStamp(uint64_t timeStamp) {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ mBeginTimeStamp = timeStamp;
+ return AssertionResult(mTimeFilter->setTimeStamp(timeStamp) == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::getTimeStamp() {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ Result status;
+ mTimeFilter->getTimeStamp([&](Result result, uint64_t /*timeStamp*/) { status = result; });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
AssertionResult FilterTests::getNewlyOpenedFilterId(uint32_t& filterId) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
@@ -229,6 +267,15 @@
return AssertionResult(status == Result::SUCCESS);
}
+AssertionResult FilterTests::clearTimeStamp() {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ return AssertionResult(mTimeFilter->clearTimeStamp() == Result::SUCCESS);
+}
+
AssertionResult FilterTests::closeFilter(uint32_t filterId) {
EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
Result status = mFilters[filterId]->close();
@@ -244,3 +291,12 @@
}
return AssertionResult(status == Result::SUCCESS);
}
+
+AssertionResult FilterTests::closeTimeFilter() {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ return AssertionResult(mTimeFilter->close() == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
index 2aa1b90..a76a6b9 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.h
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -57,6 +57,7 @@
using android::hardware::tv::tuner::V1_0::IDemux;
using android::hardware::tv::tuner::V1_0::IFilter;
using android::hardware::tv::tuner::V1_0::IFilterCallback;
+using android::hardware::tv::tuner::V1_0::ITimeFilter;
using android::hardware::tv::tuner::V1_0::ITuner;
using android::hardware::tv::tuner::V1_0::Result;
@@ -151,14 +152,19 @@
std::map<uint32_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize);
+ AssertionResult openTimeFilterInDemux();
+ AssertionResult setTimeStamp(uint64_t timeStamp);
+ AssertionResult getTimeStamp();
AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
AssertionResult getFilterMQDescriptor(uint32_t filterId);
AssertionResult setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId);
AssertionResult setFilterDataSourceToDemux(uint32_t filterId);
AssertionResult startFilter(uint32_t filterId);
+ AssertionResult clearTimeStamp();
AssertionResult stopFilter(uint32_t filterId);
AssertionResult closeFilter(uint32_t filterId);
+ AssertionResult closeTimeFilter();
FilterEventType getFilterEventType(DemuxFilterType type) {
FilterEventType eventType = FilterEventType::UNDEFINED;
@@ -214,6 +220,7 @@
sp<ITuner> mService;
sp<IFilter> mFilter;
+ sp<ITimeFilter> mTimeFilter;
sp<IDemux> mDemux;
std::map<uint32_t, sp<IFilter>> mFilters;
std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
@@ -223,4 +230,5 @@
vector<uint32_t> mUsedFilterIds;
uint32_t mFilterId = -1;
+ uint64_t mBeginTimeStamp;
};
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index d094510..45951d2 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -360,13 +360,28 @@
ASSERT_TRUE(status == Result::SUCCESS);
}
-AssertionResult FrontendTests::tuneFrontend(FrontendConfig config) {
+AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
EXPECT_TRUE(mFrontendCallback)
<< "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
EXPECT_TRUE(mFrontendInfo.type == config.type)
<< "FrontendConfig does not match the frontend info of the given id.";
+ mIsSoftwareFe = config.isSoftwareFe;
+ bool result = true;
+ if (mIsSoftwareFe && testWithDemux) {
+ DvrConfig dvrConfig;
+ getSoftwareFrontendPlaybackConfig(dvrConfig);
+ result &= mDvrTests.openDvrInDemux(dvrConfig.type, dvrConfig.bufferSize) == success();
+ result &= mDvrTests.configDvrPlayback(dvrConfig.settings) == success();
+ result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
+ mDvrTests.startPlaybackInputThread(dvrConfig.playbackInputFile,
+ dvrConfig.settings.playback());
+ if (!result) {
+ ALOGW("[vts] Software frontend dvr configure failed.");
+ return failure();
+ }
+ }
mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
return AssertionResult(true);
}
@@ -379,10 +394,14 @@
return AssertionResult(mFrontend->setLnb(lnbId) == Result::SUCCESS);
}
-AssertionResult FrontendTests::stopTuneFrontend() {
+AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
Result status;
status = mFrontend->stopTune();
+ if (mIsSoftwareFe && testWithDemux) {
+ mDvrTests.stopPlaybackThread();
+ mDvrTests.closeDvrPlayback();
+ }
return AssertionResult(status == Result::SUCCESS);
}
@@ -415,9 +434,9 @@
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(openFrontendById(feId));
ASSERT_TRUE(setFrontendCallback());
- ASSERT_TRUE(tuneFrontend(frontendConf));
+ ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
- ASSERT_TRUE(stopTuneFrontend());
+ ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
ASSERT_TRUE(closeFrontend());
}
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index b8b9f47..c536325 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -31,6 +31,7 @@
#include <utils/Mutex.h>
#include <map>
+#include "DvrTests.h"
#include "VtsHalTvTunerV1_0TestConfigurations.h"
#define WAIT_TIMEOUT 3000000000
@@ -100,7 +101,10 @@
public:
sp<ITuner> mService;
- void setService(sp<ITuner> tuner) { mService = tuner; }
+ void setService(sp<ITuner> tuner) {
+ mService = tuner;
+ mDvrTests.setService(tuner);
+ }
AssertionResult getFrontendIds();
AssertionResult getFrontendInfo(uint32_t frontendId);
@@ -108,23 +112,43 @@
AssertionResult setFrontendCallback();
AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
AssertionResult stopScanFrontend();
- AssertionResult tuneFrontend(FrontendConfig config);
+ AssertionResult tuneFrontend(FrontendConfig config, bool testWithDemux);
AssertionResult setLnb(uint32_t lnbId);
void verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
vector<FrontendStatus> expectStatuses);
- AssertionResult stopTuneFrontend();
+ AssertionResult stopTuneFrontend(bool testWithDemux);
AssertionResult closeFrontend();
void getFrontendIdByType(FrontendType feType, uint32_t& feId);
void tuneTest(FrontendConfig frontendConf);
void scanTest(FrontendConfig frontend, FrontendScanType type);
+ void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
+ void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
+
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
static AssertionResult success() { return ::testing::AssertionSuccess(); }
+ void getSoftwareFrontendPlaybackConfig(DvrConfig& dvrConfig) {
+ PlaybackSettings playbackSettings{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x07fff,
+ .dataFormat = DataFormat::TS,
+ .packetSize = 188,
+ };
+ dvrConfig.type = DvrType::PLAYBACK;
+ dvrConfig.playbackInputFile = "/data/local/tmp/segment000000.ts";
+ dvrConfig.bufferSize = FMQ_SIZE_4M;
+ dvrConfig.settings.playback(playbackSettings);
+ }
+
sp<IFrontend> mFrontend;
FrontendInfo mFrontendInfo;
sp<FrontendCallback> mFrontendCallback;
hidl_vec<FrontendId> mFeIds;
+
+ DvrTests mDvrTests;
+ bool mIsSoftwareFe = false;
};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index e1284b4..6819659 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -56,6 +56,23 @@
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
+void TunerFilterHidlTest::testTimeFilter(TimeFilterConfig filterConf) {
+ if (!filterConf.supportTimeFilter) {
+ return;
+ }
+ uint32_t demuxId;
+ sp<IDemux> demux;
+
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ mFilterTests.setDemux(demux);
+ ASSERT_TRUE(mFilterTests.openTimeFilterInDemux());
+ ASSERT_TRUE(mFilterTests.setTimeStamp(filterConf.timeStamp));
+ ASSERT_TRUE(mFilterTests.getTimeStamp());
+ ASSERT_TRUE(mFilterTests.clearTimeStamp());
+ ASSERT_TRUE(mFilterTests.closeTimeFilter());
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
void TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
uint32_t feId;
@@ -77,6 +94,7 @@
}
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFrontendTests.setDemux(demux);
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
@@ -84,9 +102,9 @@
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
- ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
- ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
@@ -122,21 +140,21 @@
mFilterTests.setDemux(demux);
mDvrTests.setDemux(demux);
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
- ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
- ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile, dvrConf.settings.playback());
- ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mDvrTests.startDvrPlayback());
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
mDvrTests.stopPlaybackThread();
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
- ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.stopDvrPlayback());
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
- mDvrTests.closeDvr();
+ mDvrTests.closeDvrPlayback();
ASSERT_TRUE(mDemuxTests.closeDemux());
}
@@ -159,9 +177,10 @@
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
mDvrTests.setDemux(demux);
+ mFrontendTests.setDvrTests(mDvrTests);
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
- ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
- ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
@@ -170,17 +189,17 @@
ASSERT_TRUE(filter != nullptr);
mDvrTests.startRecordOutputThread(dvrConf.settings.record());
ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
- ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mDvrTests.startDvrRecord());
ASSERT_TRUE(mFilterTests.startFilter(filterId));
- ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
mDvrTests.testRecordOutput();
mDvrTests.stopRecordThread();
- ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
- ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.stopDvrRecord());
ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
- mDvrTests.closeDvr();
+ mDvrTests.closeDvrRecord();
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
@@ -223,8 +242,8 @@
mFilterTests.setDemux(demux);
mDvrTests.setDemux(demux);
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
- ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
- ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
@@ -232,13 +251,13 @@
filter = mFilterTests.getFilterById(filterId);
ASSERT_TRUE(filter != nullptr);
ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
- ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mDvrTests.startDvrRecord());
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
- ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.stopDvrRecord());
ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
- mDvrTests.closeDvr();
+ mDvrTests.closeDvrRecord();
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
@@ -266,6 +285,7 @@
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
+ mFrontendTests.setDemux(demux);
for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
ASSERT_TRUE(mFilterTests.openFilterInDemux((*config).type, (*config).bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
@@ -289,9 +309,9 @@
ASSERT_TRUE(mFilterTests.startFilter(*id));
}
// tune test
- ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
- ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
for (id = filterIds.begin(); id != filterIds.end(); id++) {
ASSERT_TRUE(mFilterTests.stopFilter(*id));
}
@@ -321,6 +341,17 @@
mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
}
+TEST_P(TunerLnbHidlTest, OpenLnbByName) {
+ description("Open and configure an Lnb with name then send a diseqc msg to it.");
+ ASSERT_TRUE(mLnbTests.openLnbByName(lnbArray[LNB_EXTERNAL].name));
+ ASSERT_TRUE(mLnbTests.setLnbCallback());
+ ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB_EXTERNAL].voltage));
+ ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB_EXTERNAL].tone));
+ ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB_EXTERNAL].position));
+ ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
+ ASSERT_TRUE(mLnbTests.closeLnb());
+}
+
TEST_P(TunerLnbHidlTest, SendDiseqcMessageToLnb) {
description("Open and configure an Lnb with specific settings then send a diseqc msg to it.");
vector<uint32_t> ids;
@@ -424,6 +455,12 @@
ASSERT_TRUE(mDemuxTests.closeDemux());
}
+TEST_P(TunerFilterHidlTest, testTimeFilter) {
+ description("Open a timer filter in Demux and set time stamp.");
+ // TODO use paramterized tests
+ testTimeFilter(timeFilterArray[TIMER0]);
+}
+
TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowVideoFilterTest) {
description("Test Video Filter functionality in Broadcast use case.");
broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBT]);
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index d71222b..6804f3c 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -16,7 +16,6 @@
#include "DemuxTests.h"
#include "DescramblerTests.h"
-#include "DvrTests.h"
#include "FrontendTests.h"
#include "LnbTests.h"
@@ -34,6 +33,7 @@
initFrontendScanConfig();
initLnbConfig();
initFilterConfig();
+ initTimeFilterConfig();
initDvrConfig();
initDescramblerConfig();
}
@@ -127,6 +127,7 @@
}
void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
+ void testTimeFilter(TimeFilterConfig filterConf);
sp<ITuner> mService;
FrontendTests mFrontendTests;
@@ -145,6 +146,7 @@
mDemuxTests.setService(mService);
mFilterTests.setService(mService);
mLnbTests.setService(mService);
+ mDvrTests.setService(mService);
}
protected:
@@ -157,6 +159,7 @@
DemuxTests mDemuxTests;
FilterTests mFilterTests;
LnbTests mLnbTests;
+ DvrTests mDvrTests;
AssertionResult filterDataOutputTest(vector<string> goldenOutputFiles);
@@ -245,6 +248,7 @@
mFrontendTests.setService(mService);
mDemuxTests.setService(mService);
+ mDvrTests.setService(mService);
mDescramblerTests.setService(mService);
mDescramblerTests.setCasService(mCasService);
}
@@ -264,5 +268,6 @@
DemuxTests mDemuxTests;
FilterTests mFilterTests;
DescramblerTests mDescramblerTests;
+ DvrTests mDvrTests;
};
} // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index d0f2b9c..6c68e35 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -86,6 +86,11 @@
} Filter;
typedef enum {
+ TIMER0,
+ TIMER_MAX,
+} TimeFilter;
+
+typedef enum {
SOURCE,
SINK,
LINKAGE_DIR,
@@ -99,6 +104,7 @@
typedef enum {
LNB0,
+ LNB_EXTERNAL,
LNB_MAX,
} Lnb;
@@ -115,6 +121,7 @@
typedef enum {
DVR_RECORD0,
DVR_PLAYBACK0,
+ DVR_SOFTWARE_FE,
DVR_MAX,
} Dvr;
@@ -131,7 +138,13 @@
bool operator<(const FilterConfig& /*c*/) const { return false; }
};
+struct TimeFilterConfig {
+ bool supportTimeFilter;
+ uint64_t timeStamp;
+};
+
struct FrontendConfig {
+ bool isSoftwareFe;
FrontendType type;
FrontendSettings settings;
vector<FrontendStatusType> tuneStatusTypes;
@@ -140,6 +153,7 @@
struct LnbConfig {
bool usingLnb;
+ string name;
LnbVoltage voltage;
LnbTone tone;
LnbPosition position;
@@ -172,6 +186,7 @@
static vector<uint8_t> diseqcMsgArray[DISEQC_MAX];
static ChannelConfig channelArray[FRONTEND_MAX];
static FilterConfig filterArray[FILTER_MAX];
+static TimeFilterConfig timeFilterArray[TIMER_MAX];
static DemuxFilterType filterLinkageTypes[LINKAGE_DIR][FILTER_MAIN_TYPE_BIT_COUNT];
static DvrConfig dvrArray[DVR_MAX];
static DescramblerConfig descramblerArray[DESC_MAX];
@@ -200,7 +215,9 @@
statuses.push_back(status);
frontendArray[DVBT].tuneStatusTypes = types;
frontendArray[DVBT].expectTuneStatuses = statuses;
+ frontendArray[DVBT].isSoftwareFe = true;
frontendArray[DVBS].type = FrontendType::DVBS;
+ frontendArray[DVBS].isSoftwareFe = true;
};
/** Configuration array for the frontend scan test */
@@ -226,6 +243,11 @@
lnbArray[LNB0].voltage = LnbVoltage::VOLTAGE_12V;
lnbArray[LNB0].tone = LnbTone::NONE;
lnbArray[LNB0].position = LnbPosition::UNDEFINED;
+ lnbArray[LNB_EXTERNAL].usingLnb = true;
+ lnbArray[LNB_EXTERNAL].name = "default_lnb_external";
+ lnbArray[LNB_EXTERNAL].voltage = LnbVoltage::VOLTAGE_5V;
+ lnbArray[LNB_EXTERNAL].tone = LnbTone::NONE;
+ lnbArray[LNB_EXTERNAL].position = LnbPosition::UNDEFINED;
};
/** Diseqc messages array for the Lnb test */
@@ -311,6 +333,12 @@
filterLinkageTypes[SINK][4] = filterLinkageTypes[SOURCE][4];
};
+/** Configuration array for the timer filter test */
+inline void initTimeFilterConfig() {
+ timeFilterArray[TIMER0].supportTimeFilter = true;
+ timeFilterArray[TIMER0].timeStamp = 1;
+}
+
/** Configuration array for the dvr test */
inline void initDvrConfig() {
RecordSettings recordSettings{
@@ -331,9 +359,20 @@
.packetSize = 188,
};
dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
- dvrArray[DVR_PLAYBACK0].playbackInputFile = "/vendor/etc/segment000000.ts";
+ dvrArray[DVR_PLAYBACK0].playbackInputFile = "/data/local/tmp/segment000000.ts";
dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
+ PlaybackSettings softwareFePlaybackSettings{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x07fff,
+ .dataFormat = DataFormat::TS,
+ .packetSize = 188,
+ };
+ dvrArray[DVR_SOFTWARE_FE].type = DvrType::PLAYBACK;
+ dvrArray[DVR_SOFTWARE_FE].playbackInputFile = "/data/local/tmp/segment000000.ts";
+ dvrArray[DVR_SOFTWARE_FE].bufferSize = FMQ_SIZE_4M;
+ dvrArray[DVR_SOFTWARE_FE].settings.playback(softwareFePlaybackSettings);
};
/** Configuration array for the descrambler test */