From 56d64faff7e56bc355cce2793f51771981252644 Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Wed, 19 Jun 2019 16:23:02 -0700 Subject: [PATCH 01/35] Fix log tag for sensors VTS tests Define log tag at build level to ensure all libraries have a tag defined. Bug: 135638664 Test: run VtsHalSensorsV2_0TargetTest Change-Id: I593055b59238e9fa8dead00a3dafa84c00e90ec4 --- sensors/1.0/vts/functional/Android.bp | 1 + sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp | 2 -- sensors/2.0/vts/functional/Android.bp | 1 + sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp | 2 -- sensors/common/vts/utils/Android.bp | 1 + sensors/common/vts/utils/GrallocWrapper.cpp | 2 -- 6 files changed, 3 insertions(+), 6 deletions(-) diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp index d4c5f321de..444797d4d0 100644 --- a/sensors/1.0/vts/functional/Android.bp +++ b/sensors/1.0/vts/functional/Android.bp @@ -16,6 +16,7 @@ cc_test { name: "VtsHalSensorsV1_0TargetTest", + cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""], defaults: ["VtsHalTargetTestDefaults"], srcs: [ "SensorsHidlEnvironmentV1_0.cpp", diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp index 47308e13b9..5453ef6d0c 100644 --- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp +++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "sensors_hidl_hal_test" - #include "SensorsHidlEnvironmentV1_0.h" #include "sensors-vts-utils/SensorsHidlTestBase.h" diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp index 8e8413c6a2..98f0eacae9 100644 --- a/sensors/2.0/vts/functional/Android.bp +++ b/sensors/2.0/vts/functional/Android.bp @@ -16,6 +16,7 @@ cc_test { name: "VtsHalSensorsV2_0TargetTest", + cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""], defaults: ["VtsHalTargetTestDefaults"], srcs: [ "SensorsHidlEnvironmentV2_0.cpp", diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 39053fe75f..582ab79b69 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "sensors_hidl_hal_test" - #include "SensorsHidlEnvironmentV2_0.h" #include "sensors-vts-utils/SensorsHidlTestBase.h" #include "sensors-vts-utils/SensorsTestSharedMemory.h" diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp index 95df4259e7..8da554aa40 100644 --- a/sensors/common/vts/utils/Android.bp +++ b/sensors/common/vts/utils/Android.bp @@ -16,6 +16,7 @@ cc_library_static { name: "VtsHalSensorsTargetTestUtils", + cflags: ["-DLOG_TAG=\"sensors_hidl_hal_test\""], srcs: [ "GrallocWrapper.cpp", "SensorsHidlEnvironmentBase.cpp", diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp index 7bed16d6c4..153c208b73 100644 --- a/sensors/common/vts/utils/GrallocWrapper.cpp +++ b/sensors/common/vts/utils/GrallocWrapper.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "GrallocWrapper" - #include "GrallocWrapper.h" #include From ccbcaaee457c63582142c84d0e779793d71905b1 Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Wed, 19 Jun 2019 16:24:15 -0700 Subject: [PATCH 02/35] Fix NPD in GrallocWrapper Avoid dereferencing null if mapper service is not available. Bug: 135638664 Test: run VtsHalSensorsV2_0TargetTest Change-Id: I3cf2a9f152d8f1737cb5a94356e252d54156c716 --- sensors/common/vts/utils/GrallocWrapper.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp index 153c208b73..222ef9611a 100644 --- a/sensors/common/vts/utils/GrallocWrapper.cpp +++ b/sensors/common/vts/utils/GrallocWrapper.cpp @@ -33,8 +33,7 @@ void GrallocWrapper::init() { mMapper = mapper2::IMapper::getService(); if (mMapper == nullptr) { ALOGE("Failed to get mapper service"); - } - if (mMapper->isRemote()) { + } else if (mMapper->isRemote()) { ALOGE("Mapper is not in passthrough mode"); } } From bd109b9374360477e4e9a43b926710a394e7702d Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Wed, 19 Jun 2019 16:57:14 -0700 Subject: [PATCH 03/35] Avoid NPD when re-initializing HAL fails If the sensors HAL crashes or errors out during a test where we manually re-run the environment setup function (e.g. CleanupConnectionsOnInitialize), the pointer to the interface will become null. Avoid dereferencing it by checking for nullness in the per-test setup function and after each manual setup call. Also add a death recipient to help identify instances where the HAL crashes during a test. Bug: 135638664 Test: run VTS on device where HAL crashes during above mentioned test Change-Id: Iff7aa159c6b859272cfd18e7efb3ca431ea214fc --- .../functional/SensorsHidlEnvironmentV2_0.cpp | 8 +++++ .../functional/SensorsHidlEnvironmentV2_0.h | 12 +++++++ .../VtsHalSensorsV2_0TargetTest.cpp | 32 +++++++++++++++---- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp index 0525bdc63b..03fcc174ef 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp +++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp @@ -38,6 +38,13 @@ constexpr typename std::underlying_type::type asBaseType(EnumType valu constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT; +void SensorsHalDeathRecipient::serviceDied( + uint64_t /* cookie */, + const ::android::wp<::android::hidl::base::V1_0::IBase>& /* service */) { + ALOGE("Sensors HAL died (likely crashed) during test"); + FAIL() << "Sensors HAL died during test"; +} + struct SensorsCallback : ISensorsCallback { Return onDynamicSensorsConnected(const hidl_vec& /* sensorInfos */) { return Return(); @@ -56,6 +63,7 @@ bool SensorsHidlEnvironmentV2_0::resetHal() { if (mSensors == nullptr) { break; } + mSensors->linkToDeath(mDeathRecipient, 0 /* cookie */); // Initialize FMQs mEventQueue = std::make_unique(MAX_RECEIVE_BUFFER_EVENT_COUNT, diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h index 5e54530917..b0dbd90b05 100644 --- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h +++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h @@ -32,6 +32,13 @@ using ::android::sp; using ::android::hardware::MessageQueue; class SensorsHidlTest; + +class SensorsHalDeathRecipient : public ::android::hardware::hidl_death_recipient { + virtual void serviceDied( + uint64_t cookie, + const ::android::wp<::android::hidl::base::V1_0::IBase>& service) override; +}; + class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { public: using Event = ::android::hardware::sensors::V1_0::Event; @@ -83,6 +90,11 @@ class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase { */ sp mSensors; + /** + * Monitors the HAL for crashes, triggering test failure if seen + */ + sp mDeathRecipient = new SensorsHalDeathRecipient(); + /** * Type used to simplify the creation of the Event FMQ */ diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 582ab79b69..c6d7cada26 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -115,7 +115,13 @@ class EventCallback : public IEventCallback { // The main test class for SENSORS HIDL HAL. class SensorsHidlTest : public SensorsHidlTestBase { - protected: + public: + virtual void SetUp() override { + // Ensure that we have a valid environment before performing tests + ASSERT_NE(getSensors(), nullptr); + } + + protected: SensorInfo defaultSensorByType(SensorType type) override; std::vector getSensorsList(); // implementation wrapper @@ -612,6 +618,9 @@ TEST_F(SensorsHidlTest, CallInitializeTwice) { std::unique_ptr newEnv = std::make_unique(); newEnv->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if setting up the new environment failed + } activateAllSensors(true); // Verify that the old environment does not receive any events @@ -624,8 +633,11 @@ TEST_F(SensorsHidlTest, CallInitializeTwice) { newEnv->HidlTearDown(); // Restore the test environment for future tests - SensorsHidlEnvironmentV2_0::Instance()->HidlTearDown(); - SensorsHidlEnvironmentV2_0::Instance()->HidlSetUp(); + getEnvironment()->HidlTearDown(); + getEnvironment()->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } // Ensure that the original environment is receiving events activateAllSensors(true); @@ -644,8 +656,11 @@ TEST_F(SensorsHidlTest, CleanupConnectionsOnInitialize) { // Clear the active sensor handles so they are not disabled during TearDown auto handles = mSensorHandles; mSensorHandles.clear(); - getEnvironment()->TearDown(); - getEnvironment()->SetUp(); + getEnvironment()->HidlTearDown(); + getEnvironment()->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } // Verify no events are received until sensors are re-activated ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0); @@ -1023,8 +1038,11 @@ TEST_F(SensorsHidlTest, CleanupDirectConnectionOnInitialize) { // Clear the active direct connections so they are not stopped during TearDown auto handles = mDirectChannelHandles; mDirectChannelHandles.clear(); - getEnvironment()->TearDown(); - getEnvironment()->SetUp(); + getEnvironment()->HidlTearDown(); + getEnvironment()->HidlSetUp(); + if (HasFatalFailure()) { + return; // Exit early if resetting the environment failed + } // Attempt to configure the direct channel and expect it to fail configDirectReport( From 09f25f62bb1d2417fbbf7e062d5cfb265272c8db Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Tue, 4 Jun 2019 17:01:25 -0700 Subject: [PATCH 04/35] Added HIDL based software implementation of gatekeeper This patch adds a HIDL based software implementation of gatekeeper based on libgatekeeper. Also adds OWNER files to the vts test and default implementation directories. Test: Manually tested in emulator. Changing passwords and login worked. VtsHalGatekeeperV1_0TargetTest gatekeeper-software-device-unit-tests Change-Id: I632aeb6677640c133ec1b79e72568840adbc0550 Merged-In: I632aeb6677640c133ec1b79e72568840adbc0550 --- gatekeeper/1.0/default/OWNERS | 2 + gatekeeper/1.0/software/Android.bp | 28 +++ gatekeeper/1.0/software/OWNERS | 2 + gatekeeper/1.0/software/SoftGateKeeper.h | 171 +++++++++++++++++ .../1.0/software/SoftGateKeeperDevice.cpp | 114 +++++++++++ .../1.0/software/SoftGateKeeperDevice.h | 80 ++++++++ ...ardware.gatekeeper@1.0-service.software.rc | 4 + ...rdware.gatekeeper@1.0-service.software.xml | 11 ++ gatekeeper/1.0/software/service.cpp | 39 ++++ gatekeeper/1.0/software/tests/Android.bp | 34 ++++ .../1.0/software/tests/gatekeeper_test.cpp | 178 ++++++++++++++++++ gatekeeper/1.0/vts/OWNERS | 3 + 12 files changed, 666 insertions(+) create mode 100644 gatekeeper/1.0/default/OWNERS create mode 100644 gatekeeper/1.0/software/Android.bp create mode 100644 gatekeeper/1.0/software/OWNERS create mode 100644 gatekeeper/1.0/software/SoftGateKeeper.h create mode 100644 gatekeeper/1.0/software/SoftGateKeeperDevice.cpp create mode 100644 gatekeeper/1.0/software/SoftGateKeeperDevice.h create mode 100644 gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc create mode 100644 gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml create mode 100644 gatekeeper/1.0/software/service.cpp create mode 100644 gatekeeper/1.0/software/tests/Android.bp create mode 100644 gatekeeper/1.0/software/tests/gatekeeper_test.cpp create mode 100644 gatekeeper/1.0/vts/OWNERS diff --git a/gatekeeper/1.0/default/OWNERS b/gatekeeper/1.0/default/OWNERS new file mode 100644 index 0000000000..335660da3b --- /dev/null +++ b/gatekeeper/1.0/default/OWNERS @@ -0,0 +1,2 @@ +jdanis@google.com +swillden@google.com diff --git a/gatekeeper/1.0/software/Android.bp b/gatekeeper/1.0/software/Android.bp new file mode 100644 index 0000000000..148c98938f --- /dev/null +++ b/gatekeeper/1.0/software/Android.bp @@ -0,0 +1,28 @@ +cc_binary { + name: "android.hardware.gatekeeper@1.0-service.software", + defaults: ["hidl_defaults"], + relative_install_path: "hw", + vendor: true, + init_rc: ["android.hardware.gatekeeper@1.0-service.software.rc"], + + srcs: [ + "service.cpp", + "SoftGateKeeperDevice.cpp", + ], + + shared_libs: [ + "android.hardware.gatekeeper@1.0", + "libbase", + "libhardware", + "libhidlbase", + "libhidltransport", + "libutils", + "liblog", + "libcrypto", + "libgatekeeper", + ], + + static_libs: ["libscrypt_static"], + + vintf_fragments: ["android.hardware.gatekeeper@1.0-service.software.xml"], +} diff --git a/gatekeeper/1.0/software/OWNERS b/gatekeeper/1.0/software/OWNERS new file mode 100644 index 0000000000..335660da3b --- /dev/null +++ b/gatekeeper/1.0/software/OWNERS @@ -0,0 +1,2 @@ +jdanis@google.com +swillden@google.com diff --git a/gatekeeper/1.0/software/SoftGateKeeper.h b/gatekeeper/1.0/software/SoftGateKeeper.h new file mode 100644 index 0000000000..3276d1ebbd --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeper.h @@ -0,0 +1,171 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef SOFT_GATEKEEPER_H_ +#define SOFT_GATEKEEPER_H_ + +extern "C" { +#include +#include + +#include +} + +#include +#include + +#include +#include +#include + +namespace gatekeeper { + +struct fast_hash_t { + uint64_t salt; + uint8_t digest[SHA256_DIGEST_LENGTH]; +}; + +class SoftGateKeeper : public GateKeeper { + public: + static const uint32_t SIGNATURE_LENGTH_BYTES = 32; + + // scrypt params + static const uint64_t N = 16384; + static const uint32_t r = 8; + static const uint32_t p = 1; + + static const int MAX_UINT_32_CHARS = 11; + + SoftGateKeeper() { + key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]); + memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES); + } + + virtual ~SoftGateKeeper() {} + + virtual bool GetAuthTokenKey(const uint8_t** auth_token_key, uint32_t* length) const { + if (auth_token_key == NULL || length == NULL) return false; + *auth_token_key = key_.get(); + *length = SIGNATURE_LENGTH_BYTES; + return true; + } + + virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) { + if (password_key == NULL || length == NULL) return; + *password_key = key_.get(); + *length = SIGNATURE_LENGTH_BYTES; + } + + virtual void ComputePasswordSignature(uint8_t* signature, uint32_t signature_length, + const uint8_t*, uint32_t, const uint8_t* password, + uint32_t password_length, salt_t salt) const { + if (signature == NULL) return; + crypto_scrypt(password, password_length, reinterpret_cast(&salt), sizeof(salt), N, + r, p, signature, signature_length); + } + + virtual void GetRandom(void* random, uint32_t requested_length) const { + if (random == NULL) return; + RAND_pseudo_bytes((uint8_t*)random, requested_length); + } + + virtual void ComputeSignature(uint8_t* signature, uint32_t signature_length, const uint8_t*, + uint32_t, const uint8_t*, const uint32_t) const { + if (signature == NULL) return; + memset(signature, 0, signature_length); + } + + virtual uint64_t GetMillisecondsSinceBoot() const { + struct timespec time; + int res = clock_gettime(CLOCK_BOOTTIME, &time); + if (res < 0) return 0; + return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000); + } + + virtual bool IsHardwareBacked() const { return false; } + + virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t* record, + bool /* secure */) { + failure_record_t* stored = &failure_map_[uid]; + if (user_id != stored->secure_user_id) { + stored->secure_user_id = user_id; + stored->last_checked_timestamp = 0; + stored->failure_counter = 0; + } + memcpy(record, stored, sizeof(*record)); + return true; + } + + virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) { + failure_record_t* stored = &failure_map_[uid]; + stored->secure_user_id = user_id; + stored->last_checked_timestamp = 0; + stored->failure_counter = 0; + return true; + } + + virtual bool WriteFailureRecord(uint32_t uid, failure_record_t* record, bool /* secure */) { + failure_map_[uid] = *record; + return true; + } + + fast_hash_t ComputeFastHash(const SizedBuffer& password, uint64_t salt) { + fast_hash_t fast_hash; + size_t digest_size = password.size() + sizeof(salt); + std::unique_ptr digest(new uint8_t[digest_size]); + memcpy(digest.get(), &salt, sizeof(salt)); + memcpy(digest.get() + sizeof(salt), password.Data(), password.size()); + + SHA256(digest.get(), digest_size, (uint8_t*)&fast_hash.digest); + + fast_hash.salt = salt; + return fast_hash; + } + + bool VerifyFast(const fast_hash_t& fast_hash, const SizedBuffer& password) { + fast_hash_t computed = ComputeFastHash(password, fast_hash.salt); + return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0; + } + + bool DoVerify(const password_handle_t* expected_handle, const SizedBuffer& password) { + uint64_t user_id = android::base::get_unaligned(&expected_handle->user_id); + FastHashMap::const_iterator it = fast_hash_map_.find(user_id); + if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) { + return true; + } else { + if (GateKeeper::DoVerify(expected_handle, password)) { + uint64_t salt; + GetRandom(&salt, sizeof(salt)); + fast_hash_map_[user_id] = ComputeFastHash(password, salt); + return true; + } + } + + return false; + } + + private: + typedef std::unordered_map FailureRecordMap; + typedef std::unordered_map FastHashMap; + + std::unique_ptr key_; + FailureRecordMap failure_map_; + FastHashMap fast_hash_map_; +}; +} // namespace gatekeeper + +#endif // SOFT_GATEKEEPER_H_ diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp new file mode 100644 index 0000000000..d7a0b46ee6 --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SoftGateKeeperDevice.h" +#include "SoftGateKeeper.h" + +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode; +using ::gatekeeper::EnrollRequest; +using ::gatekeeper::EnrollResponse; +using ::gatekeeper::ERROR_INVALID; +using ::gatekeeper::ERROR_MEMORY_ALLOCATION_FAILED; +using ::gatekeeper::ERROR_NONE; +using ::gatekeeper::ERROR_RETRY; +using ::gatekeeper::SizedBuffer; +using ::gatekeeper::VerifyRequest; +using ::gatekeeper::VerifyResponse; + +#include + +namespace android { + +inline SizedBuffer hidl_vec2sized_buffer(const hidl_vec& vec) { + if (vec.size() == 0 || vec.size() > std::numeric_limits::max()) return {}; + auto dummy = new uint8_t[vec.size()]; + std::copy(vec.begin(), vec.end(), dummy); + return {dummy, static_cast(vec.size())}; +} + +Return SoftGateKeeperDevice::enroll(uint32_t uid, + const hidl_vec& currentPasswordHandle, + const hidl_vec& currentPassword, + const hidl_vec& desiredPassword, + enroll_cb _hidl_cb) { + if (desiredPassword.size() == 0) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + return {}; + } + + EnrollRequest request(uid, hidl_vec2sized_buffer(currentPasswordHandle), + hidl_vec2sized_buffer(desiredPassword), + hidl_vec2sized_buffer(currentPassword)); + EnrollResponse response; + impl_->Enroll(request, &response); + + if (response.error == ERROR_RETRY) { + _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}}); + } else if (response.error != ERROR_NONE) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + } else { + hidl_vec new_handle(response.enrolled_password_handle.Data(), + response.enrolled_password_handle.Data() + + response.enrolled_password_handle.size()); + _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, new_handle}); + } + return {}; +} + +Return SoftGateKeeperDevice::verify( + uint32_t uid, uint64_t challenge, + const ::android::hardware::hidl_vec& enrolledPasswordHandle, + const ::android::hardware::hidl_vec& providedPassword, verify_cb _hidl_cb) { + if (enrolledPasswordHandle.size() == 0) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + return {}; + } + + VerifyRequest request(uid, challenge, hidl_vec2sized_buffer(enrolledPasswordHandle), + hidl_vec2sized_buffer(providedPassword)); + VerifyResponse response; + + impl_->Verify(request, &response); + + if (response.error == ERROR_RETRY) { + _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}}); + } else if (response.error != ERROR_NONE) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + } else { + hidl_vec auth_token( + response.auth_token.Data(), + response.auth_token.Data() + response.auth_token.size()); + + _hidl_cb({response.request_reenroll ? GatekeeperStatusCode::STATUS_REENROLL + : GatekeeperStatusCode::STATUS_OK, + response.retry_timeout, auth_token}); + } + return {}; +} + +Return SoftGateKeeperDevice::deleteUser(uint32_t /*uid*/, deleteUser_cb _hidl_cb) { + _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}}); + return {}; +} + +Return SoftGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb _hidl_cb) { + _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}}); + return {}; +} + +} // namespace android diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.h b/gatekeeper/1.0/software/SoftGateKeeperDevice.h new file mode 100644 index 0000000000..17b474e4aa --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.h @@ -0,0 +1,80 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SOFT_GATEKEEPER_DEVICE_H_ +#define SOFT_GATEKEEPER_DEVICE_H_ + +#include +#include + +#include +#include "SoftGateKeeper.h" + +namespace android { + +/** + * Software based GateKeeper implementation + */ +class SoftGateKeeperDevice : public ::android::hardware::gatekeeper::V1_0::IGatekeeper { + public: + SoftGateKeeperDevice() { impl_.reset(new ::gatekeeper::SoftGateKeeper()); } + + // Wrappers to translate the gatekeeper HAL API to the Kegyuard Messages API. + + /** + * Enrolls password_payload, which should be derived from a user selected pin or password, + * with the authentication factor private key used only for enrolling authentication + * factor data. + * + * Returns: 0 on success or an error code less than 0 on error. + * On error, enrolled_password_handle will not be allocated. + */ + ::android::hardware::Return enroll( + uint32_t uid, const ::android::hardware::hidl_vec& currentPasswordHandle, + const ::android::hardware::hidl_vec& currentPassword, + const ::android::hardware::hidl_vec& desiredPassword, + enroll_cb _hidl_cb) override; + + /** + * Verifies provided_password matches enrolled_password_handle. + * + * Implementations of this module may retain the result of this call + * to attest to the recency of authentication. + * + * On success, writes the address of a verification token to auth_token, + * usable to attest password verification to other trusted services. Clients + * may pass NULL for this value. + * + * Returns: 0 on success or an error code less than 0 on error + * On error, verification token will not be allocated + */ + ::android::hardware::Return verify( + uint32_t uid, uint64_t challenge, + const ::android::hardware::hidl_vec& enrolledPasswordHandle, + const ::android::hardware::hidl_vec& providedPassword, + verify_cb _hidl_cb) override; + + ::android::hardware::Return deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) override; + + ::android::hardware::Return deleteAllUsers(deleteAllUsers_cb _hidl_cb) override; + + private: + std::unique_ptr<::gatekeeper::SoftGateKeeper> impl_; +}; + +} // namespace android + +#endif // SOFT_GATEKEEPER_DEVICE_H_ diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc new file mode 100644 index 0000000000..60cb96c915 --- /dev/null +++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc @@ -0,0 +1,4 @@ +service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service.software + class hal + user system + group system diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml new file mode 100644 index 0000000000..19714a83b7 --- /dev/null +++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml @@ -0,0 +1,11 @@ + + + android.hardware.gatekeeper + hwbinder + 1.0 + + IGatekeeper + default + + + diff --git a/gatekeeper/1.0/software/service.cpp b/gatekeeper/1.0/software/service.cpp new file mode 100644 index 0000000000..a48a964c08 --- /dev/null +++ b/gatekeeper/1.0/software/service.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 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. + */ +#define LOG_TAG "android.hardware.gatekeeper@1.0-service" + +#include +#include + +#include + +#include "SoftGateKeeperDevice.h" + +// Generated HIDL files +using android::SoftGateKeeperDevice; +using android::hardware::gatekeeper::V1_0::IGatekeeper; + +int main() { + ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */); + android::sp gatekeeper(new SoftGateKeeperDevice()); + auto status = gatekeeper->registerAsService(); + if (status != android::OK) { + LOG(FATAL) << "Could not register service for Gatekeeper 1.0 (software) (" << status << ")"; + } + + android::hardware::joinRpcThreadpool(); + return -1; // Should never get here. +} diff --git a/gatekeeper/1.0/software/tests/Android.bp b/gatekeeper/1.0/software/tests/Android.bp new file mode 100644 index 0000000000..3f0300dc18 --- /dev/null +++ b/gatekeeper/1.0/software/tests/Android.bp @@ -0,0 +1,34 @@ +// +// Copyright (C) 2015 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +cc_test { + name: "gatekeeper-software-device-unit-tests", + + cflags: [ + "-g", + "-Wall", + "-Werror", + "-Wno-missing-field-initializers", + ], + shared_libs: [ + "libgatekeeper", + "libcrypto", + "libbase", + ], + static_libs: ["libscrypt_static"], + + srcs: ["gatekeeper_test.cpp"], +} diff --git a/gatekeeper/1.0/software/tests/gatekeeper_test.cpp b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp new file mode 100644 index 0000000000..bf4a8bc5fa --- /dev/null +++ b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp @@ -0,0 +1,178 @@ +/* + * Copyright 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include + +#include "../SoftGateKeeper.h" + +using ::gatekeeper::EnrollRequest; +using ::gatekeeper::EnrollResponse; +using ::gatekeeper::secure_id_t; +using ::gatekeeper::SizedBuffer; +using ::gatekeeper::SoftGateKeeper; +using ::gatekeeper::VerifyRequest; +using ::gatekeeper::VerifyResponse; +using ::testing::Test; + +static SizedBuffer makePasswordBuffer(int init = 0) { + constexpr const uint32_t pw_buffer_size = 16; + auto pw_buffer = new uint8_t[pw_buffer_size]; + memset(pw_buffer, init, pw_buffer_size); + + return {pw_buffer, pw_buffer_size}; +} + +static SizedBuffer makeAndInitializeSizedBuffer(const uint8_t* data, uint32_t size) { + auto buffer = new uint8_t[size]; + memcpy(buffer, data, size); + return {buffer, size}; +} + +static SizedBuffer copySizedBuffer(const SizedBuffer& rhs) { + return makeAndInitializeSizedBuffer(rhs.Data(), rhs.size()); +} + +static void do_enroll(SoftGateKeeper& gatekeeper, EnrollResponse* response) { + EnrollRequest request(0, {}, makePasswordBuffer(), {}); + + gatekeeper.Enroll(request, response); +} + +TEST(GateKeeperTest, EnrollSuccess) { + SoftGateKeeper gatekeeper; + EnrollResponse response; + do_enroll(gatekeeper, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); +} + +TEST(GateKeeperTest, EnrollBogusData) { + SoftGateKeeper gatekeeper; + EnrollResponse response; + + EnrollRequest request(0, {}, {}, {}); + + gatekeeper.Enroll(request, &response); + + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); +} + +TEST(GateKeeperTest, VerifySuccess) { + SoftGateKeeper gatekeeper; + EnrollResponse enroll_response; + + do_enroll(gatekeeper, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + VerifyRequest request(0, 1, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer()); + VerifyResponse response; + + gatekeeper.Verify(request, &response); + + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + + auto auth_token = response.auth_token.Data(); + + ASSERT_NE(nullptr, auth_token); + ASSERT_EQ((uint32_t)HW_AUTH_PASSWORD, ntohl(auth_token->authenticator_type)); + ASSERT_EQ((uint64_t)1, auth_token->challenge); + ASSERT_NE(~((uint32_t)0), auth_token->timestamp); + ASSERT_NE((uint64_t)0, auth_token->user_id); + ASSERT_NE((uint64_t)0, auth_token->authenticator_id); +} + +TEST(GateKeeperTest, TrustedReEnroll) { + SoftGateKeeper gatekeeper; + EnrollResponse enroll_response; + + // do_enroll enrolls an all 0 password + do_enroll(gatekeeper, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify first password + VerifyRequest request(0, 0, copySizedBuffer(enroll_response.enrolled_password_handle), + makePasswordBuffer()); + VerifyResponse response; + gatekeeper.Verify(request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + auto auth_token = response.auth_token.Data(); + ASSERT_NE(nullptr, auth_token); + + secure_id_t secure_id = auth_token->user_id; + + // enroll new password + EnrollRequest enroll_request(0, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer(1) /* new password */, + makePasswordBuffer() /* old password */); + gatekeeper.Enroll(enroll_request, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify new password + VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer(1)); + gatekeeper.Verify(new_request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + ASSERT_NE(nullptr, response.auth_token.Data()); + ASSERT_EQ(secure_id, response.auth_token.Data()->user_id); +} + +TEST(GateKeeperTest, UntrustedReEnroll) { + SoftGateKeeper gatekeeper; + SizedBuffer provided_password; + EnrollResponse enroll_response; + + // do_enroll enrolls an all 0 password + provided_password = makePasswordBuffer(); + do_enroll(gatekeeper, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify first password + VerifyRequest request(0, 0, std::move(enroll_response.enrolled_password_handle), + std::move(provided_password)); + VerifyResponse response; + gatekeeper.Verify(request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + auto auth_token = response.auth_token.Data(); + ASSERT_NE(nullptr, auth_token); + + secure_id_t secure_id = auth_token->user_id; + + EnrollRequest enroll_request(0, {}, makePasswordBuffer(1), {}); + gatekeeper.Enroll(enroll_request, &enroll_response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); + + // verify new password + VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle), + makePasswordBuffer(1)); + gatekeeper.Verify(new_request, &response); + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); + ASSERT_NE(nullptr, response.auth_token.Data()); + ASSERT_NE(secure_id, response.auth_token.Data()->user_id); +} + +TEST(GateKeeperTest, VerifyBogusData) { + SoftGateKeeper gatekeeper; + VerifyResponse response; + + VerifyRequest request(0, 0, {}, {}); + + gatekeeper.Verify(request, &response); + + ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); +} diff --git a/gatekeeper/1.0/vts/OWNERS b/gatekeeper/1.0/vts/OWNERS new file mode 100644 index 0000000000..738c71025a --- /dev/null +++ b/gatekeeper/1.0/vts/OWNERS @@ -0,0 +1,3 @@ +jdanis@google.com +swillden@google.com +guangzhu@google.com From f42602678f0df52ab7ee6a727979ea958f66d48e Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Fri, 7 Jun 2019 18:32:54 -0700 Subject: [PATCH 05/35] Add GNSS satellite blacklist VTS 2.0 test - Use IGnssCallback@2.0::gnssSvStatusCb_2_0() method to receive SV info. - Run the test only if SATELLITE_BLACKLIST capability is supported. - IRNSS is excluded from blacklisting as IGnssConfiguration@2.0 is not updated to support the blacklisting new constellation type. - Modify the corresponding VTS 1.1 test to run only if the GNSS HAL version is 1.1. Bug: 128028791 Test: atest VtsHalGnssV2_0Target Change-Id: Idd44a5a1c9d54d7434da945ecbd1ee90007f5054 --- gnss/1.1/vts/functional/gnss_hal_test.cpp | 28 ++ gnss/1.1/vts/functional/gnss_hal_test.h | 6 + .../vts/functional/gnss_hal_test_cases.cpp | 10 + .../functional/VtsHalGnssV2_0TargetTest.cpp | 1 - gnss/2.0/vts/functional/gnss_hal_test.cpp | 4 +- gnss/2.0/vts/functional/gnss_hal_test.h | 24 +- .../vts/functional/gnss_hal_test_cases.cpp | 363 +++++++++++++++++- 7 files changed, 427 insertions(+), 9 deletions(-) diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp index 381ac1d3af..f3b376e6bd 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp @@ -16,10 +16,16 @@ #define LOG_TAG "GnssHalTest" +#include +#include + #include #include #include "Utils.h" +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; + using ::android::hardware::gnss::common::Utils; // Implementations for the main test class for GNSS HAL @@ -149,6 +155,28 @@ void GnssHalTest::StartAndCheckLocations(int count) { } } +bool GnssHalTest::IsGnssHalVersion_1_1() const { + using ::android::hidl::manager::V1_2::IServiceManager; + sp manager = ::android::hardware::defaultServiceManager1_2(); + + bool hasGnssHalVersion_1_1 = false; + manager->listManifestByInterface( + "android.hardware.gnss@1.1::IGnss", + [&hasGnssHalVersion_1_1](const hidl_vec& registered) { + ASSERT_EQ(1, registered.size()); + hasGnssHalVersion_1_1 = true; + }); + + bool hasGnssHalVersion_2_0 = false; + manager->listManifestByInterface( + "android.hardware.gnss@2.0::IGnss", + [&hasGnssHalVersion_2_0](const hidl_vec& registered) { + hasGnssHalVersion_2_0 = registered.size() != 0; + }); + + return hasGnssHalVersion_1_1 && !hasGnssHalVersion_2_0; +} + void GnssHalTest::notify() { std::unique_lock lock(mtx_); notify_count_++; diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h index 64478b5b1c..84a9f846fc 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.h +++ b/gnss/1.1/vts/functional/gnss_hal_test.h @@ -145,6 +145,12 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ void SetPositionMode(const int min_interval_msec, const bool low_power_mode); + /* + * IsGnssHalVersion_1_1: + * returns true if the GNSS HAL version is exactly 1.1. + */ + bool IsGnssHalVersion_1_1() const; + sp gnss_hal_; // GNSS HAL to call into sp gnss_cb_; // Primary callback interface diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index 2d901f3301..4288d0df9c 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -202,6 +202,11 @@ IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource( * formerly strongest satellite */ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { + if (!IsGnssHalVersion_1_1()) { + ALOGI("Test BlacklistIndividualSatellites skipped. GNSS HAL version is greater than 1.1."); + return; + } + const int kLocationsToAwait = 3; const int kRetriesToUnBlacklist = 10; @@ -323,6 +328,11 @@ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { * 4a & b) Clean up by turning off location, and send in empty blacklist. */ TEST_F(GnssHalTest, BlacklistConstellation) { + if (!IsGnssHalVersion_1_1()) { + ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 1.1."); + return; + } + const int kLocationsToAwait = 3; StartAndCheckLocations(kLocationsToAwait); diff --git a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp index a8e40ba250..ae36c50689 100644 --- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp +++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp @@ -23,7 +23,6 @@ int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); GnssHidlEnvironment::Instance()->init(&argc, argv); - // TODO (b/122463165): Expand coverage to include 1.1 and 1.0 VTS tests. int status = RUN_ALL_TESTS(); ALOGI("Test result = %d", status); return status; diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index a9f858cc9d..14ae43ce26 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -152,7 +152,7 @@ GnssHalTest::GnssCallback::GnssCallback() name_cbq_("name"), capabilities_cbq_("capabilities"), location_cbq_("location"), - sv_info_cbq_("sv_info") {} + sv_info_list_cbq_("sv_info") {} Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( const IGnssCallback_1_0::GnssSystemInfo& info) { @@ -204,7 +204,7 @@ Return GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0:: Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_0( const hidl_vec& svInfoList) { ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size()); - sv_info_cbq_.store(svInfoList); + sv_info_list_cbq_.store(svInfoList); return Void(); } diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 05e37d33f7..90a7866082 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -23,6 +23,7 @@ #include #include +#include #include using android::hardware::hidl_vec; @@ -85,6 +86,14 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ bool retrieve(T& event, int timeout_seconds); + /* + * Removes parameter count number of callack events at the front of the queue, stores + * them in event_list parameter and returns the number of events retrieved. Waits up to + * timeout_seconds to retrieve each event. If timeout occurs, it returns the number of + * items retrieved which will be less than count. + */ + int retrieve(list& event_list, int count, int timeout_seconds); + /* Returns the number of events pending to be retrieved from the callback event queue. */ int size() const; @@ -117,7 +126,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { CallbackQueue name_cbq_; CallbackQueue capabilities_cbq_; CallbackQueue location_cbq_; - CallbackQueue> sv_info_cbq_; + CallbackQueue> sv_info_list_cbq_; GnssCallback(); virtual ~GnssCallback() = default; @@ -264,6 +273,19 @@ bool GnssHalTest::CallbackQueue::retrieve(T& event, int timeout_seconds) { return true; } +template +int GnssHalTest::CallbackQueue::retrieve(list& event_list, int count, int timeout_seconds) { + for (int i = 0; i < count; ++i) { + T event; + if (!retrieve(event, timeout_seconds)) { + return i; + } + event_list.push_back(event); + } + + return count; +} + template int GnssHalTest::CallbackQueue::size() const { std::unique_lock lock(mtx_); 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 155afd614b..6e0887fd9e 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -23,7 +23,10 @@ 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; using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement; using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; @@ -33,15 +36,12 @@ using IAGnssRil_1_0 = android::hardware::gnss::V1_0::IAGnssRil; using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; -using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; -using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; using android::hardware::gnss::common::Utils; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections; using android::hardware::gnss::V1_0::IGnssNi; using android::hardware::gnss::V2_0::ElapsedRealtimeFlags; -using android::hardware::gnss::V2_0::GnssConstellationType; using android::hardware::gnss::V2_0::IGnssCallback; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; @@ -209,9 +209,9 @@ TEST_F(GnssHalTest, TestGnssMeasurementFields) { // Verify ConstellationType is valid. ASSERT_TRUE(static_cast(measurement.constellation) >= - static_cast(GnssConstellationType::UNKNOWN) && + static_cast(GnssConstellationType_2_0::UNKNOWN) && static_cast(measurement.constellation) <= - static_cast(GnssConstellationType::IRNSS)); + static_cast(GnssConstellationType_2_0::IRNSS)); // Verify State is valid. ASSERT_TRUE( @@ -414,3 +414,356 @@ TEST_F(GnssHalTest, TestGnssBatchingExtension) { auto gnssBatching_2_0 = gnss_hal_->getExtensionGnssBatching_2_0(); ASSERT_TRUE(gnssBatching_2_0.isOk()); } + +/* + * 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 + * + * returns the strongest source, + * or a source with constellation == UNKNOWN if none are found sufficient times + */ +IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource( + const list>& sv_info_lists, + const int min_observations) { + struct ComparableBlacklistedSource { + IGnssConfiguration_1_1::BlacklistedSource id; + + ComparableBlacklistedSource() { + id.constellation = GnssConstellationType_1_0::UNKNOWN; + id.svid = 0; + } + + bool operator<(const ComparableBlacklistedSource& compare) const { + return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) && + (id.constellation < compare.id.constellation))); + } + }; + + struct SignalCounts { + int observations; + float max_cn0_dbhz; + }; + + std::map mapSignals; + + for (const auto& sv_info_list : sv_info_lists) { + 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::IRNSS) && + (sv_info.constellation != GnssConstellationType_2_0::GPS)) { + ComparableBlacklistedSource source; + source.id.svid = sv_info.v1_0.svid; + source.id.constellation = MapConstellationType(sv_info.constellation); + + const auto& itSignal = mapSignals.find(source); + if (itSignal == mapSignals.end()) { + SignalCounts counts; + counts.observations = 1; + counts.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz; + mapSignals.insert( + std::pair(source, counts)); + } else { + itSignal->second.observations++; + if (itSignal->second.max_cn0_dbhz < sv_info.v1_0.cN0Dbhz) { + itSignal->second.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz; + } + } + } + } + } + + float max_cn0_dbhz_with_sufficient_count = 0.; + int total_observation_count = 0; + int blacklisted_source_count_observation = 0; + + ComparableBlacklistedSource source_to_blacklist; // initializes to zero = UNKNOWN constellation + for (auto const& pairSignal : mapSignals) { + total_observation_count += pairSignal.second.observations; + if ((pairSignal.second.observations >= min_observations) && + (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) { + source_to_blacklist = pairSignal.first; + blacklisted_source_count_observation = pairSignal.second.observations; + max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz; + } + } + ALOGD("Among %d observations, chose svid %d, constellation %d, " + "with %d observations at %.1f max CNo", + total_observation_count, source_to_blacklist.id.svid, + (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation, + max_cn0_dbhz_with_sufficient_count); + + return source_to_blacklist.id; +} + +/* + * BlacklistIndividualSatellites: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for common satellites (strongest and one other.) + * 2a & b) Turns off location, and blacklists common satellites. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use those satellites. + * 4a & b) Turns off location, and send in empty blacklist. + * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does re-use at least the previously strongest satellite + * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the + * formerly strongest satellite + */ +TEST_F(GnssHalTest, BlacklistIndividualSatellites) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + return; + } + + const int kLocationsToAwait = 3; + const int kRetriesToUnBlacklist = 10; + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + 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); + + /* + * Identify strongest SV seen at least kLocationsToAwait -1 times + * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal + * observability (one epoch RF null) + */ + + const int kGnssSvStatusTimeout = 2; + list> sv_info_lists; + int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, sv_info_list_cbq_size, + kGnssSvStatusTimeout); + ASSERT_EQ(count, sv_info_list_cbq_size); + + IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist = + FindStrongFrequentNonGpsSource(sv_info_lists, kLocationsToAwait - 1); + + if (source_to_blacklist.constellation == GnssConstellationType_1_0::UNKNOWN) { + // Cannot find a non-GPS satellite. Let the test pass. + return; + } + + // Stop locations, blacklist the common SV + StopAndClearLocations(); + + auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1(); + ASSERT_TRUE(gnss_configuration_hal_return.isOk()); + sp gnss_configuration_hal = gnss_configuration_hal_return; + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(1); + sources[0] = source_to_blacklist; + + auto result = gnss_configuration_hal->setBlacklist(sources); + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + // retry and ensure satellite not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + 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); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec 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); + 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)); + } + } + + // clear blacklist and restart - this time updating the blacklist while location is still on + sources.resize(0); + + result = gnss_configuration_hal->setBlacklist(sources); + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + bool strongest_sv_is_reobserved = false; + // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies + int unblacklist_loops_remaining = kRetriesToUnBlacklist; + while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) { + StopAndClearLocations(); + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit loop if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Clear blacklist, observed %d GnssSvStatus, while awaiting %d Locations" + ", tries remaining %d", + sv_info_list_cbq_size, kLocationsToAwait, unblacklist_loops_remaining); + + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec 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); + 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)) { + strongest_sv_is_reobserved = true; + break; + } + } + if (strongest_sv_is_reobserved) break; + } + } + EXPECT_TRUE(strongest_sv_is_reobserved); + StopAndClearLocations(); +} + +/* + * BlacklistConstellation: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for any non-GPS constellations. + * 2a & b) Turns off location, and blacklist first non-GPS constellations. + * 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_F(GnssHalTest, BlacklistConstellation) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + return; + } + + 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 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 + + auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1(); + ASSERT_TRUE(gnss_configuration_hal_return.isOk()); + sp gnss_configuration_hal = gnss_configuration_hal_return; + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(1); + sources[0] = source_to_blacklist; + + auto result = gnss_configuration_hal->setBlacklist(sources); + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + // 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. + 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); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec 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); + 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); +} \ No newline at end of file From 07a53471c45c53c00ca0fbe1d83b23a3f2c2ba76 Mon Sep 17 00:00:00 2001 From: sqian Date: Mon, 1 Jul 2019 13:20:45 -0700 Subject: [PATCH 06/35] Hang up EmergencyDial after Trigger in VTS The whole test case run emergencyDial.RadioHidlTest_v1_4 first and then come after startNetworkScan.RadioHidlTest_v1_4 test case immediately (within ~3 secs) the NWscan failure is device in emergency call in progress/connected while doing emergencyDial.RadioHidlTest_v1_4 test Although emergencyDial.RadioHidlTest_v1_4 only care about command/response is successful or not and don't care call is established or not, modem do care about call condition is in idle/progress/connected state before it can do NWscan When there's dedicated channel established, modem can not perform AP request NWscan in parallel as we are single HW modem restriction. Test: run vts Bug: 135595082 Change-Id: Iecba54b93b96d33b57bc59e00f082ff133d2e57b --- .../1.4/vts/functional/radio_hidl_hal_api.cpp | 18 ++++++++++++++++++ .../1.4/vts/functional/radio_hidl_hal_test.cpp | 17 +++++++++++++++++ .../vts/functional/radio_hidl_hal_utils_v1_4.h | 9 +++++++++ radio/1.4/vts/functional/radio_response.cpp | 7 +++++-- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp index 696c746d65..26f2c90f54 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp @@ -41,6 +41,12 @@ TEST_F(RadioHidlTest_v1_4, emergencyDial) { ALOGI("emergencyDial, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str()); EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error); + + // Give some time for modem to establish the emergency call channel. + sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME); + + // Disconnect all the potential established calls to prevent them affecting other tests. + clearPotentialEstablishedCalls(); } /* @@ -67,6 +73,12 @@ TEST_F(RadioHidlTest_v1_4, emergencyDial_withServices) { ALOGI("emergencyDial_withServices, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str()); EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error); + + // Give some time for modem to establish the emergency call channel. + sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME); + + // Disconnect all the potential established calls to prevent them affecting other tests. + clearPotentialEstablishedCalls(); } /* @@ -93,6 +105,12 @@ TEST_F(RadioHidlTest_v1_4, emergencyDial_withEmergencyRouting) { ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str()); EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error); + + // Give some time for modem to establish the emergency call channel. + sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME); + + // Disconnect all the potential established calls to prevent them affecting other tests. + clearPotentialEstablishedCalls(); } /* diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp index d2d21ce1f6..63e5f6ed53 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp @@ -87,6 +87,23 @@ std::cv_status RadioHidlTest_v1_4::wait() { return status; } +void RadioHidlTest_v1_4::clearPotentialEstablishedCalls() { + // Get the current call Id to hangup the established emergency call. + serial = GetRandomSerialNumber(); + radio_v1_4->getCurrentCalls(serial); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + + // Hang up to disconnect the established call channels. + for (const ::android::hardware::radio::V1_2::Call& call : radioRsp_v1_4->currentCalls) { + serial = GetRandomSerialNumber(); + radio_v1_4->hangup(serial, call.base.index); + ALOGI("Hang up to disconnect the established call channel: %d", call.base.index); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + // Give some time for modem to disconnect the established call channel. + sleep(MODEM_EMERGENCY_CALL_DISCONNECT_TIME); + } +} + void RadioHidlTest_v1_4::updateSimCardStatus() { serial = GetRandomSerialNumber(); radio_v1_4->getIccCardStatus(serial); diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h index f662472d22..b07f9c36e6 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h +++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h @@ -44,6 +44,9 @@ using ::android::hardware::Return; using ::android::hardware::Void; #define TIMEOUT_PERIOD 75 +#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3 +#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3 + #define RADIO_SERVICE_NAME "slot1" class RadioHidlTest_v1_4; @@ -59,6 +62,9 @@ class RadioResponse_v1_4 : public ::android::hardware::radio::V1_4::IRadioRespon RadioResponseInfo rspInfo; + // Call + hidl_vec<::android::hardware::radio::V1_2::Call> currentCalls; + // Modem bool isModemEnabled; bool enableModemResponseToggle; @@ -725,6 +731,9 @@ class RadioHidlTest_v1_4 : public ::testing::VtsHalHidlTargetTestBase { /* Serial number for radio request */ int serial; + /* Clear Potential Established Calls */ + void clearPotentialEstablishedCalls(); + /* Update Sim Card Status */ void updateSimCardStatus(); diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp index eac0c6800f..a849926cf0 100644 --- a/radio/1.4/vts/functional/radio_response.cpp +++ b/radio/1.4/vts/functional/radio_response.cpp @@ -77,7 +77,9 @@ Return RadioResponse_v1_4::getIMSIForAppResponse( return Void(); } -Return RadioResponse_v1_4::hangupConnectionResponse(const RadioResponseInfo& /*info*/) { +Return RadioResponse_v1_4::hangupConnectionResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent_v1_4.notify(info.serial); return Void(); } @@ -729,9 +731,10 @@ Return RadioResponse_v1_4::getIccCardStatusResponse_1_2( Return RadioResponse_v1_4::getCurrentCallsResponse_1_2( const RadioResponseInfo& info, - const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& /*calls*/) { + const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls) { rspInfo = info; parent_v1_4.notify(info.serial); + currentCalls = calls; return Void(); } From 5cef297cb2ed70bcf70abf911dc4bd14c343cbc6 Mon Sep 17 00:00:00 2001 From: Willy Hu Date: Fri, 28 Jun 2019 18:36:03 +0800 Subject: [PATCH 07/35] VTS: Change stopNetworkScan from 1_1 to 1_2 Change stopNetworkScan from 1_1 to 1_2 when testing VtsHalRadioV1_2Target. Symptom: When vts process slot2 "startnetworkscan", it will call "stopnetworkscan()" when startnetworkscan success. But from current design it will set stopnetworkscan to slot1(wrong slot, expect is slot2) as bwlow log. CTS fail log: hardware/interfaces/radio/1.2/vts/functional/radio_hidl_hal_test.cpp:111 //Device request NwScan on 2nd Sim 06-28 11:30:22.770 radio 873 1213 F RILQ : RIL[1][Log.cpp: 48] [DispatcherModul(873,1213)] d: [DispatcherModule]: Handling msg = RIL_REQUEST_START_NETWORK_SCAN //But Device want to abort on Primary Sim 06-28 11:30:22.776 radio 923 1205 F RILQ : RIL[0][Log.cpp: 48] [DispatcherModul(923,1205)] d: [NasModule]: Handling msg = RIL_REQUEST_STOP_NETWORK_SCAN[Context: IRadio(1681692777)] Bug: 135982495 Test: Build pass. Local test VTS pass. Change-Id: Ic53c24ab2a670e806b4ac7f192e6eb81252ade84 --- .../vts/functional/radio_hidl_hal_test.cpp | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp index bff7481bed..6b84810686 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ -#include #include void RadioHidlTest_v1_2::SetUp() { @@ -88,25 +87,7 @@ void RadioHidlTest_v1_2::updateSimCardStatus() { } void RadioHidlTest_v1_2::stopNetworkScan() { - sp<::android::hardware::radio::V1_1::IRadio> radio_v1_1; - - radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService< - ::android::hardware::radio::V1_1::IRadio>( - RadioHidlEnvironment::Instance() - ->getServiceName<::android::hardware::radio::V1_1::IRadio>( - hidl_string(RADIO_SERVICE_NAME))); - if (radio_v1_1 == NULL) { - sleep(60); - radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService< - ::android::hardware::radio::V1_1::IRadio>( - RadioHidlEnvironment::Instance() - ->getServiceName<::android::hardware::radio::V1_1::IRadio>( - hidl_string(RADIO_SERVICE_NAME))); - } - ASSERT_NE(nullptr, radio_v1_1.get()); - serial = GetRandomSerialNumber(); - - radio_v1_1->stopNetworkScan(serial); + radio_v1_2->stopNetworkScan(serial); EXPECT_EQ(std::cv_status::no_timeout, wait()); } From 67306b3aa6433069ca8f933be8813156c116dac0 Mon Sep 17 00:00:00 2001 From: nxp72763 Date: Thu, 16 May 2019 17:40:10 +0530 Subject: [PATCH 08/35] Align NFCEE ID range with NCI 1.0 in VtsNfcv1.2 test As per spec,NFCEE_ID value dynamically assigned by NFCC has the following range - In NCI_2.0, 0x80 <= NFCEE ID <= 0xFE. - In NCI_1.0, 0x01 <= NFCEE ID <= 0xFE. Bug: 137053584 Test: VtsHalNfcV1_2TargetTest with NCI1.0 & NCI2.0 supported device. Change-Id: I09adaca8b36900a92d737b176e09234251aae2bc --- nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp index ee4a88792a..54d3127a75 100644 --- a/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp +++ b/nfc/1.2/vts/functional/VtsHalNfcV1_2TargetTest.cpp @@ -38,7 +38,7 @@ using ::android::hardware::nfc::V1_2::INfc; using ::android::hardware::nfc::V1_2::NfcConfig; // Range of valid off host route ids -constexpr unsigned int MIN_OFFHOST_ROUTE_ID = 0x80; +constexpr unsigned int MIN_OFFHOST_ROUTE_ID = 0x01; constexpr unsigned int MAX_OFFHOST_ROUTE_ID = 0xFE; constexpr char kCallbackNameSendEvent[] = "sendEvent"; From fb1616eb9424564ed274a389ebc52600ef8cb41d Mon Sep 17 00:00:00 2001 From: Willy Hu Date: Fri, 28 Jun 2019 18:36:03 +0800 Subject: [PATCH 09/35] VTS: Change stopNetworkScan from 1_1 to 1_2 Change stopNetworkScan from 1_1 to 1_2 when testing VtsHalRadioV1_2Target. Symptom: When vts process slot2 "startnetworkscan", it will call "stopnetworkscan()" when startnetworkscan success. But from current design it will set stopnetworkscan to slot1(wrong slot, expect is slot2) as bwlow log. CTS fail log: hardware/interfaces/radio/1.2/vts/functional/radio_hidl_hal_test.cpp:111 //Device request NwScan on 2nd Sim 06-28 11:30:22.770 radio 873 1213 F RILQ : RIL[1][Log.cpp: 48] [DispatcherModul(873,1213)] d: [DispatcherModule]: Handling msg = RIL_REQUEST_START_NETWORK_SCAN //But Device want to abort on Primary Sim 06-28 11:30:22.776 radio 923 1205 F RILQ : RIL[0][Log.cpp: 48] [DispatcherModul(923,1205)] d: [NasModule]: Handling msg = RIL_REQUEST_STOP_NETWORK_SCAN[Context: IRadio(1681692777)] Bug: 135982495 Test: Build pass. Local test VTS pass. Change-Id: Ic53c24ab2a670e806b4ac7f192e6eb81252ade84 (cherry picked from commit 5cef297cb2ed70bcf70abf911dc4bd14c343cbc6) --- .../vts/functional/radio_hidl_hal_test.cpp | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp index bff7481bed..6b84810686 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ -#include #include void RadioHidlTest_v1_2::SetUp() { @@ -88,25 +87,7 @@ void RadioHidlTest_v1_2::updateSimCardStatus() { } void RadioHidlTest_v1_2::stopNetworkScan() { - sp<::android::hardware::radio::V1_1::IRadio> radio_v1_1; - - radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService< - ::android::hardware::radio::V1_1::IRadio>( - RadioHidlEnvironment::Instance() - ->getServiceName<::android::hardware::radio::V1_1::IRadio>( - hidl_string(RADIO_SERVICE_NAME))); - if (radio_v1_1 == NULL) { - sleep(60); - radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService< - ::android::hardware::radio::V1_1::IRadio>( - RadioHidlEnvironment::Instance() - ->getServiceName<::android::hardware::radio::V1_1::IRadio>( - hidl_string(RADIO_SERVICE_NAME))); - } - ASSERT_NE(nullptr, radio_v1_1.get()); - serial = GetRandomSerialNumber(); - - radio_v1_1->stopNetworkScan(serial); + radio_v1_2->stopNetworkScan(serial); EXPECT_EQ(std::cv_status::no_timeout, wait()); } From bc5f18aae1118c5197774c751019e73ad80c38ff Mon Sep 17 00:00:00 2001 From: Youming Ye Date: Thu, 11 Jul 2019 14:05:13 -0700 Subject: [PATCH 10/35] Disable startNetworkScan tests with parameters. Network scan tests with parameters are disabled because of vendors failed to fully implement startNetworkScan in HAL 1.4, and GSM rat scan with parameters will get REQUEST_NOT_SUPPORTED error from modem. Test: VTS Bug: 137298570 Change-Id: I99df8495c5f654cb1420b7da36d7f5128ce14dbc --- radio/1.4/vts/functional/radio_hidl_hal_api.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp index 696c746d65..a05f0a712f 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp @@ -151,6 +151,11 @@ TEST_F(RadioHidlTest_v1_4, setPreferredNetworkTypeBitmap) { /* * Test IRadio.startNetworkScan() for the response returned. + * + * REQUEST_NOT_SUPPORTED is temporarily returned because of vendors failed to fully implement + * startNetworkScan in HAL @1.4 (see b/137298570 and b/135595082). Starting from @1.5, however, + * REQUEST_NOT_SUPPORTED will be disallowed for all tests. Modems have "GSM" rat scan need to + * support scanning requests combined with some parameters. */ TEST_F(RadioHidlTest_v1_4, startNetworkScan) { serial = GetRandomSerialNumber(); From f829d259567391ad82e9ab96b91b4463ac854193 Mon Sep 17 00:00:00 2001 From: Youming Ye Date: Thu, 11 Jul 2019 14:05:13 -0700 Subject: [PATCH 11/35] Add REQUEST_NOT_SUPPORTED to startNetworkScan Test: VTS Bug: 137298570 Change-Id: I99df8495c5f654cb1420b7da36d7f5128ce14dbc --- .../1.4/vts/functional/radio_hidl_hal_api.cpp | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp index 0fcd32d615..f81af9b261 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp @@ -196,10 +196,17 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan) { if (cardStatus.base.base.cardState == CardState::ABSENT) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do not support the - // required manual GSM search functionality. This is tracked in b/112206766. - ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, - {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED})); + // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do + // not support the required manual GSM search functionality. This is + // tracked in b/112206766. REQUEST_NOT_SUPPORTED is temporarily added back + // because of vendors failed to implement startNetworkScan in HAL 1.4 (see + // b/137298570 and b/135595082). Starting from 1.5, however, + // REQUEST_NOT_SUPPORTED will be disallowed. Modems have "GSM" rat scan + // need to support scanning requests combined with some parameters. + ASSERT_TRUE( + CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED, + RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -225,8 +232,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidArgument) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -261,8 +269,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -296,8 +305,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -331,8 +341,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -366,8 +377,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -401,8 +413,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -436,8 +449,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -473,8 +487,10 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, - {RadioError::NONE, RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE( + CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::INVALID_ARGUMENTS, + RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -512,8 +528,10 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, - {RadioError::NONE, RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE( + CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::INVALID_ARGUMENTS, + RadioError::REQUEST_NOT_SUPPORTED})); } } From 65945cfb150ee6f046daa472b4ce71729ee69f1b Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Fri, 12 Jul 2019 17:55:30 -0400 Subject: [PATCH 12/35] Verify mPollThread is joinable before detaching If HidlSetUp() bails before startPollingThread() is called (which can happen if the HAL isn't implemented on the given device), mPollThread will initialize with the default constructor resulting in joinable() returning false which means calling detach() throws an exception. Checking joinable() before detaching allows the test suite to be skipped successfully. Fixes: 136736906 Test: Run vts-tradefed on VtsHalSensorsV1_0Target and verify that it is skipped successfully on a device that doesn't support HAL 1.0 Change-Id: Ie685ae2dc314edb8df2f3cc7112141a2f5e46008 --- sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp index affdf8b6b3..fa0e2e9bf0 100644 --- a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp +++ b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp @@ -29,7 +29,9 @@ void SensorsHidlEnvironmentBase::HidlSetUp() { void SensorsHidlEnvironmentBase::HidlTearDown() { mStopThread = true; - mPollThread.detach(); + if (mPollThread.joinable()) { + mPollThread.detach(); + } } void SensorsHidlEnvironmentBase::catEvents(std::vector* output) { From 03bc98e028d3ebe4ab2d657deb0cb24ed76e3e45 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Mon, 15 Jul 2019 18:52:00 -0700 Subject: [PATCH 13/35] Add GetLocationLowPower VTS 2.0 test - Run test only if LOW_POWER_MODE capability is supported. - Modify the corresponding VTS 1.1 test to run only if the GNSS HAL version is 1.1. Fixes: 127434062 Test: atest VtsHalGnssV2_0Target Change-Id: Icbd18d80468e9e5a542f2eace5bfbe45af08ca47 --- .../vts/functional/gnss_hal_test_cases.cpp | 5 ++ .../vts/functional/gnss_hal_test_cases.cpp | 67 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index 4288d0df9c..3a30ceadc6 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -59,6 +59,11 @@ TEST_F(GnssHalTest, TestGnssMeasurementCallback) { * each received location. */ TEST_F(GnssHalTest, GetLocationLowPower) { + if (!IsGnssHalVersion_1_1()) { + ALOGI("Test GetLocationLowPower skipped. GNSS HAL version is greater than 1.1."); + return; + } + const int kMinIntervalMsec = 5000; const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2; const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2; 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 6e0887fd9e..39736cc250 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -415,6 +415,70 @@ TEST_F(GnssHalTest, TestGnssBatchingExtension) { ASSERT_TRUE(gnssBatching_2_0.isOk()); } +/* + * GetLocationLowPower: + * Turns on location, waits for at least 5 locations allowing max of LOCATION_TIMEOUT_SUBSEQUENT_SEC + * between one location and the next. Also ensure that MIN_INTERVAL_MSEC is respected by waiting + * NO_LOCATION_PERIOD_SEC and verfiy that no location is received. Also perform validity checks on + * each received location. + */ +TEST_F(GnssHalTest, GetLocationLowPower) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::LOW_POWER_MODE)) { + ALOGI("Test GetLocationLowPower skipped. LOW_POWER_MODE capability not supported."); + return; + } + + const int kMinIntervalMsec = 5000; + const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2; + const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2; + const int kLocationsToCheck = 5; + const bool kLowPowerMode = true; + + // Warmup period - VTS doesn't have AGPS access via GnssLocationProvider + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToCheck); + StopAndClearLocations(); + gnss_cb_->location_cbq_.reset(); + + // Start of Low Power Mode test + SetPositionMode(kMinIntervalMsec, kLowPowerMode); + + // Don't expect true - as without AGPS access + if (!StartAndCheckFirstLocation()) { + ALOGW("GetLocationLowPower test - no first low power location received."); + } + + for (int i = 1; i < kLocationsToCheck; i++) { + // Verify that kMinIntervalMsec is respected by waiting kNoLocationPeriodSec and + // ensure that no location is received yet + + gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, kNoLocationPeriodSec); + const int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); + + // Tolerate (ignore) one extra location right after the first one + // to handle startup edge case scheduling limitations in some implementations + if ((i == 1) && (locationCalledCount == 2)) { + CheckLocation(gnss_cb_->last_location_, true); + continue; // restart the quiet wait period after this too-fast location + } + EXPECT_LE(locationCalledCount, i); + if (locationCalledCount != i) { + ALOGW("GetLocationLowPower test - not enough locations received. %d vs. %d expected ", + locationCalledCount, i); + } + + if (!gnss_cb_->location_cbq_.retrieve( + gnss_cb_->last_location_, + kLocationTimeoutSubsequentSec - kNoLocationPeriodSec)) { + ALOGW("GetLocationLowPower test - timeout awaiting location %d", i); + } else { + CheckLocation(gnss_cb_->last_location_, true); + } + } + + StopAndClearLocations(); +} + /* * MapConstellationType: * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent @@ -537,6 +601,8 @@ IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource( */ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability" + " not supported."); return; } @@ -680,6 +746,7 @@ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { */ TEST_F(GnssHalTest, BlacklistConstellation) { if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported."); return; } From 0d7f7882e77fdbd9e78c49d47136521357465556 Mon Sep 17 00:00:00 2001 From: "jie.yuan" Date: Wed, 3 Jul 2019 11:01:06 +0800 Subject: [PATCH 14/35] VTS : fix vts fail [1/1] Problem: VtsHalGraphicsComposerV2_1Target#GraphicsComposerHidlCommandTest.PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES fail the testcase setcolormode SRGB without check if current device support SRGB Solution: change setColorMode from SRGB to NATIVE Verify: verify in on franklin Bug:135375302 Test: build, boot, VtsHalGraphicsComposerV2_1TargetTest Change-Id: I5eebe5f530e3b62037d669992cf2eca0849f10be Merged-In: I5eebe5f530e3b62037d669992cf2eca0849f10be --- .../2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 30b96949dc..fa5ace65b1 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -790,7 +790,7 @@ TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) { TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) { mWriter->selectDisplay(mPrimaryDisplay); mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON); - mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB); + mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE); auto handle = allocate(); ASSERT_NE(nullptr, handle); From 70e5b556ef5c799113caf34edde9ca16838b8d6c Mon Sep 17 00:00:00 2001 From: "jie.yuan" Date: Wed, 3 Jul 2019 11:01:06 +0800 Subject: [PATCH 15/35] VTS : fix vts fail [1/1] Problem: VtsHalGraphicsComposerV2_1Target#GraphicsComposerHidlCommandTest.PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES fail the testcase setcolormode SRGB without check if current device support SRGB Solution: change setColorMode from SRGB to NATIVE Verify: verify in on franklin Bug: 135375302 Test: build, boot, VtsHalGraphicsComposerV2_1TargetTest Change-Id: I646c263d96b03f9d30e6563a45cff37835001609 Merged-In: I5eebe5f530e3b62037d669992cf2eca0849f10be --- .../2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 30b96949dc..fa5ace65b1 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp @@ -790,7 +790,7 @@ TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) { TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) { mWriter->selectDisplay(mPrimaryDisplay); mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON); - mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB); + mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE); auto handle = allocate(); ASSERT_NE(nullptr, handle); From 2f3553e1ed5f2e492e9725028108bf0b8e2a536f Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 16 Jul 2019 09:16:58 -0700 Subject: [PATCH 16/35] DO NOT MERGE: Fixing SRGB for devices that do not support SRGB color mode Bug: 135375302 Test: build, boot, VtsHalGraphicsComposerV2_2TargetTest Change-Id: Ie8f53effe3e6e29a4523ebfa450c79fdf96ed585 Merged-In: Ie8f53effe3e6e29a4523ebfa450c79fdf96ed585 --- ...VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 86 ++++++++++++------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index 0648b3456a..02c4c9cec9 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -182,6 +182,14 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase mReader = std::make_unique(); mGralloc = std::make_shared(); + std::vector colorModes = mComposerClient->getColorModes(mPrimaryDisplay); + if (std::find(colorModes.begin(), colorModes.end(), ColorMode::SRGB) == colorModes.end()) { + mHasReadbackBuffer = false; + return; + } + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); mComposerClient->getRaw()->getReadbackBufferAttributes( mPrimaryDisplay, [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) { @@ -471,12 +479,12 @@ class TestBufferLayer : public TestLayer { TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); @@ -515,12 +523,13 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); @@ -562,13 +571,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) { TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); @@ -611,12 +620,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) { TEST_F(GraphicsComposerReadbackTest, ClientComposition) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); fillColorsArea(expectedColors, mDisplayWidth, @@ -690,11 +700,13 @@ TEST_F(GraphicsComposerReadbackTest, ClientComposition) { TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); ASSERT_NO_FATAL_FAILURE( mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)); @@ -776,12 +788,13 @@ TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelformat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - IComposerClient::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4}; std::vector expectedColors(mDisplayWidth * mDisplayHeight); @@ -842,14 +855,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) { TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); - auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); layer->setColor(RED); layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); @@ -886,12 +898,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) { TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); fillColorsArea(expectedColors, mDisplayWidth, @@ -931,14 +944,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) { TEST_F(GraphicsComposerReadbackTest, SetLayerZOrder) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); - IComposerClient::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2}; IComposerClient::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight}; auto redLayer = std::make_shared(mComposerClient, mPrimaryDisplay); @@ -1081,12 +1093,13 @@ class GraphicsComposerBlendModeReadbackTest : public GraphicsComposerReadbackTes TEST_P(GraphicsComposerBlendModeReadbackTest, None) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); setBackgroundColor(BLACK); @@ -1118,12 +1131,13 @@ TEST_P(GraphicsComposerBlendModeReadbackTest, None) { // alpha of .2, expected 10.2 TEST_P(GraphicsComposerBlendModeReadbackTest, DISABLED_Coverage) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); setBackgroundColor(BLACK); @@ -1153,12 +1167,13 @@ TEST_P(GraphicsComposerBlendModeReadbackTest, DISABLED_Coverage) { TEST_P(GraphicsComposerBlendModeReadbackTest, Premultiplied) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); setBackgroundColor(BLACK); @@ -1193,10 +1208,6 @@ class GraphicsComposerTransformReadbackTest : public GraphicsComposerReadbackTes void SetUp() override { GraphicsComposerReadbackTest::SetUp(); - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); - auto backgroundLayer = std::make_shared(mComposerClient, mPrimaryDisplay); backgroundLayer->setColor({0, 0, 0, 0}); backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); @@ -1230,6 +1241,9 @@ class GraphicsComposerTransformReadbackTest : public GraphicsComposerReadbackTes TEST_F(GraphicsComposerTransformReadbackTest, FLIP_H) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } @@ -1262,6 +1276,9 @@ TEST_F(GraphicsComposerTransformReadbackTest, FLIP_H) { TEST_F(GraphicsComposerTransformReadbackTest, FLIP_V) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } @@ -1295,6 +1312,9 @@ TEST_F(GraphicsComposerTransformReadbackTest, FLIP_V) { TEST_F(GraphicsComposerTransformReadbackTest, ROT_180) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } From 37d1599e0b1d450b700fd855b2aa45f2fb97b74b Mon Sep 17 00:00:00 2001 From: Valerie Hau Date: Tue, 16 Jul 2019 09:16:58 -0700 Subject: [PATCH 17/35] DO NOT MERGE: Fixing SRGB for devices that do not support SRGB color mode Bug: 135375302 Test: build, boot, VtsHalGraphicsComposerV2_2TargetTest Change-Id: Ie8f53effe3e6e29a4523ebfa450c79fdf96ed585 --- ...VtsHalGraphicsComposerV2_2ReadbackTest.cpp | 86 ++++++++++++------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp index 0648b3456a..02c4c9cec9 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp @@ -182,6 +182,14 @@ class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase mReader = std::make_unique(); mGralloc = std::make_shared(); + std::vector colorModes = mComposerClient->getColorModes(mPrimaryDisplay); + if (std::find(colorModes.begin(), colorModes.end(), ColorMode::SRGB) == colorModes.end()) { + mHasReadbackBuffer = false; + return; + } + mWriter->selectDisplay(mPrimaryDisplay); + ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, + RenderIntent::COLORIMETRIC)); mComposerClient->getRaw()->getReadbackBufferAttributes( mPrimaryDisplay, [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) { @@ -471,12 +479,12 @@ class TestBufferLayer : public TestLayer { TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); @@ -515,12 +523,13 @@ TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) { TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth, mDisplayHeight, mPixelFormat, mDataspace); ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer()); @@ -562,13 +571,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) { TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight}); @@ -611,12 +620,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) { TEST_F(GraphicsComposerReadbackTest, ClientComposition) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); fillColorsArea(expectedColors, mDisplayWidth, @@ -690,11 +700,13 @@ TEST_F(GraphicsComposerReadbackTest, ClientComposition) { TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); ASSERT_NO_FATAL_FAILURE( mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount)); @@ -776,12 +788,13 @@ TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) { TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelformat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - IComposerClient::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4}; std::vector expectedColors(mDisplayWidth * mDisplayHeight); @@ -842,14 +855,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) { TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); - auto layer = std::make_shared(mComposerClient, mPrimaryDisplay); layer->setColor(RED); layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); @@ -886,12 +898,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) { TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED); fillColorsArea(expectedColors, mDisplayWidth, @@ -931,14 +944,13 @@ TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) { TEST_F(GraphicsComposerReadbackTest, SetLayerZOrder) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); - IComposerClient::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2}; IComposerClient::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight}; auto redLayer = std::make_shared(mComposerClient, mPrimaryDisplay); @@ -1081,12 +1093,13 @@ class GraphicsComposerBlendModeReadbackTest : public GraphicsComposerReadbackTes TEST_P(GraphicsComposerBlendModeReadbackTest, None) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); setBackgroundColor(BLACK); @@ -1118,12 +1131,13 @@ TEST_P(GraphicsComposerBlendModeReadbackTest, None) { // alpha of .2, expected 10.2 TEST_P(GraphicsComposerBlendModeReadbackTest, DISABLED_Coverage) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); setBackgroundColor(BLACK); @@ -1153,12 +1167,13 @@ TEST_P(GraphicsComposerBlendModeReadbackTest, DISABLED_Coverage) { TEST_P(GraphicsComposerBlendModeReadbackTest, Premultiplied) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } - mWriter->selectDisplay(mPrimaryDisplay); - std::vector expectedColors(mDisplayWidth * mDisplayHeight); setBackgroundColor(BLACK); @@ -1193,10 +1208,6 @@ class GraphicsComposerTransformReadbackTest : public GraphicsComposerReadbackTes void SetUp() override { GraphicsComposerReadbackTest::SetUp(); - mWriter->selectDisplay(mPrimaryDisplay); - ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, - RenderIntent::COLORIMETRIC)); - auto backgroundLayer = std::make_shared(mComposerClient, mPrimaryDisplay); backgroundLayer->setColor({0, 0, 0, 0}); backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight}); @@ -1230,6 +1241,9 @@ class GraphicsComposerTransformReadbackTest : public GraphicsComposerReadbackTes TEST_F(GraphicsComposerTransformReadbackTest, FLIP_H) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } @@ -1262,6 +1276,9 @@ TEST_F(GraphicsComposerTransformReadbackTest, FLIP_H) { TEST_F(GraphicsComposerTransformReadbackTest, FLIP_V) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } @@ -1295,6 +1312,9 @@ TEST_F(GraphicsComposerTransformReadbackTest, FLIP_V) { TEST_F(GraphicsComposerTransformReadbackTest, ROT_180) { if (!mHasReadbackBuffer) { + std::cout << "Readback not supported or unsuppported pixelFormat/dataspace or SRGB not a " + "valid color mode" + << std::endl; GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace"; return; } From 0a50473369f4d03b254f34b763c13989ba1b9909 Mon Sep 17 00:00:00 2001 From: zhangweiwei Date: Mon, 24 Jun 2019 17:50:23 +0800 Subject: [PATCH 18/35] Adapt change clearkey to Lazy hal Exempt-From-Owner-Approval Bug:135896867 Test: vts-tradefed run commandAndExit vts-staging-default -m VtsHalDrmV1_1Target Change-Id: Iadba7a7afdccfe8a6299e3c0e1e03f63a58c5ca8 --- drm/1.1/vts/functional/drm_hal_clearkey_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp index 7dedd7f0b9..6be30d34df 100644 --- a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp +++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -129,9 +129,9 @@ public: ALOGD("DrmHalClearkeyTest: Running test %s.%s", test_info->test_case_name(), test_info->name()); - auto manager = android::hardware::defaultServiceManager(); + auto manager = android::hardware::defaultServiceManager1_2(); ASSERT_NE(nullptr, manager.get()); - manager->listByInterface(IDrmFactory::descriptor, + manager->listManifestByInterface(IDrmFactory::descriptor, [&](const hidl_vec ®istered) { for (const auto &instance : registered) { sp drmFactory = @@ -144,7 +144,7 @@ public: } ); - manager->listByInterface(ICryptoFactory::descriptor, + manager->listManifestByInterface(ICryptoFactory::descriptor, [&](const hidl_vec ®istered) { for (const auto &instance : registered) { sp cryptoFactory = From 9a8538b4eed2eed8acd21fa3d056d93e44704af5 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Wed, 10 Jul 2019 08:33:47 -0700 Subject: [PATCH 19/35] hostapd(vts): Add a property for SAP interface Changes to the VTS test to support OEM's who use a separate dedicated SAP interface. Note: This is a VTS test change only. The default implementation does not still support a dedicated SAP interface (OEM's can obviously customize the default implementation for their devices). Bug: 136645414 Test: None (verified by partner OEM) Change-Id: I42b87bf90cfa90c7c218309164ab2b77f3685f9e --- wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp index 26a58b2c61..7aaad02ac2 100644 --- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp @@ -56,6 +56,8 @@ class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { protected: std::string getPrimaryWlanIfaceName() { std::array buffer; + auto res = property_get("wifi.sap.interface", buffer.data(), nullptr); + if (res > 0) return buffer.data(); property_get("wifi.interface", buffer.data(), "wlan0"); return buffer.data(); } From 6abdaac7141ec48a714c08776327c2f5e47d4668 Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Thu, 18 Jul 2019 18:40:53 -0700 Subject: [PATCH 20/35] VTS 1.1 TestGnssMeasurementCallback test must allow 1.1 or 1.0 versions Fixes: 137839372 Test: atest VtsHalGnssV1_1Target Change-Id: Ie3b1fa8b4738c03bff7924396b5eb5c6774841f1 --- gnss/1.1/vts/functional/gnss_hal_test_cases.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index 3a30ceadc6..ee236ba5d1 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -24,6 +24,9 @@ using android::hardware::hidl_vec; +using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement; +using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; + using android::hardware::gnss::V1_0::GnssConstellationType; using android::hardware::gnss::V1_0::GnssLocation; using android::hardware::gnss::V1_0::IGnssDebug; @@ -43,11 +46,15 @@ TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {} * Gets the GnssMeasurementExtension and verify that it returns an actual extension. */ TEST_F(GnssHalTest, TestGnssMeasurementCallback) { - auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_1_1(); - ASSERT_TRUE(gnssMeasurement.isOk()); + auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1(); + ASSERT_TRUE(gnssMeasurement_1_1.isOk()); + auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement(); + ASSERT_TRUE(gnssMeasurement_1_0.isOk()); if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) { - sp iGnssMeas = gnssMeasurement; - EXPECT_NE(iGnssMeas, nullptr); + sp iGnssMeas_1_1 = gnssMeasurement_1_1; + sp iGnssMeas_1_0 = gnssMeasurement_1_0; + // At least one interface must be non-null. + ASSERT_TRUE(iGnssMeas_1_1 != nullptr || iGnssMeas_1_0 != nullptr); } } From e16ca9abcab8fde3cd612e68bb2c7dc94f94b09c Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Thu, 18 Jul 2019 18:40:53 -0700 Subject: [PATCH 21/35] VTS 1.1 TestGnssMeasurementCallback test must allow 1.1 or 1.0 versions Fixes: 137839372 Test: atest VtsHalGnssV1_1Target Change-Id: Ie3b1fa8b4738c03bff7924396b5eb5c6774841f1 (cherry picked from commit 6abdaac7141ec48a714c08776327c2f5e47d4668) --- gnss/1.1/vts/functional/gnss_hal_test_cases.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index 2d901f3301..4016a5ab70 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -24,6 +24,9 @@ using android::hardware::hidl_vec; +using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement; +using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; + using android::hardware::gnss::V1_0::GnssConstellationType; using android::hardware::gnss::V1_0::GnssLocation; using android::hardware::gnss::V1_0::IGnssDebug; @@ -43,11 +46,15 @@ TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {} * Gets the GnssMeasurementExtension and verify that it returns an actual extension. */ TEST_F(GnssHalTest, TestGnssMeasurementCallback) { - auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_1_1(); - ASSERT_TRUE(gnssMeasurement.isOk()); + auto gnssMeasurement_1_1 = gnss_hal_->getExtensionGnssMeasurement_1_1(); + ASSERT_TRUE(gnssMeasurement_1_1.isOk()); + auto gnssMeasurement_1_0 = gnss_hal_->getExtensionGnssMeasurement(); + ASSERT_TRUE(gnssMeasurement_1_0.isOk()); if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) { - sp iGnssMeas = gnssMeasurement; - EXPECT_NE(iGnssMeas, nullptr); + sp iGnssMeas_1_1 = gnssMeasurement_1_1; + sp iGnssMeas_1_0 = gnssMeasurement_1_0; + // At least one interface must be non-null. + ASSERT_TRUE(iGnssMeas_1_1 != nullptr || iGnssMeas_1_0 != nullptr); } } From fc85e8fa50ccae2cd0e538260ccb9e62c109b181 Mon Sep 17 00:00:00 2001 From: Youming Ye Date: Wed, 17 Jul 2019 18:31:28 -0700 Subject: [PATCH 22/35] Add non-dds check for startNetworkScan Providing non-dds exemption for HAL 1.2 network scan due to some devices only perform network scan on preferred data sim. Since logical modem id(0/1) and physical sim slot id(0/1) are intuitively aligned. Set first sim as dds sim, and skip the network scan on the second one (non-dds). Test: Vts Bug: 135243177 Change-Id: I58b89473714dc6d3ce6567ba1809baad6cd6d799 --- radio/1.2/vts/functional/Android.bp | 3 + .../vts/functional/radio_config_response.cpp | 59 +++++++++++++++++ .../1.2/vts/functional/radio_hidl_hal_api.cpp | 9 +++ .../vts/functional/radio_hidl_hal_test.cpp | 66 +++++++++++++++++++ .../functional/radio_hidl_hal_utils_v1_2.h | 58 +++++++++++++++- 5 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 radio/1.2/vts/functional/radio_config_response.cpp diff --git a/radio/1.2/vts/functional/Android.bp b/radio/1.2/vts/functional/Android.bp index 6782f143d0..c5838a8edb 100644 --- a/radio/1.2/vts/functional/Android.bp +++ b/radio/1.2/vts/functional/Android.bp @@ -20,6 +20,7 @@ cc_test { srcs: [ "radio_hidl_hal_api.cpp", "radio_hidl_hal_test.cpp", + "radio_config_response.cpp", "radio_response.cpp", "radio_indication.cpp", "VtsHalRadioV1_2TargetTest.cpp", @@ -29,6 +30,8 @@ cc_test { "android.hardware.radio@1.2", "android.hardware.radio@1.1", "android.hardware.radio@1.0", + "android.hardware.radio.config@1.0", + "android.hardware.radio.config@1.1", ], header_libs: ["radio.util.header@1.0"], test_suites: ["general-tests"], diff --git a/radio/1.2/vts/functional/radio_config_response.cpp b/radio/1.2/vts/functional/radio_config_response.cpp new file mode 100644 index 0000000000..71b74979af --- /dev/null +++ b/radio/1.2/vts/functional/radio_config_response.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +RadioConfigResponse::RadioConfigResponse(RadioHidlTest_v1_2& parent) : parent_v1_2(parent) {} + +Return RadioConfigResponse::getSimSlotsStatusResponse( + const RadioResponseInfo& info, + const ::android::hardware::hidl_vec& slotStatus) { + rspInfo = info; + simSlotStatus = slotStatus; + parent_v1_2.notify(info.serial); + return Void(); +} + +Return RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) { + return Void(); +} + +Return RadioConfigResponse::getPhoneCapabilityResponse( + const RadioResponseInfo& info, const PhoneCapability& phoneCapability) { + rspInfo = info; + phoneCap = phoneCapability; + parent_v1_2.notify(info.serial); + return Void(); +} + +Return RadioConfigResponse::setPreferredDataModemResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent_v1_2.notify(info.serial); + return Void(); +} + +Return RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& info, + const ModemsConfig& /* mConfig */) { + rspInfo = info; + parent_v1_2.notify(info.serial); + return Void(); +} + +Return RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& info) { + rspInfo = info; + parent_v1_2.notify(info.serial); + return Void(); +} diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp index f11f0d8e9e..5184ef962c 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp @@ -34,6 +34,15 @@ const RadioAccessSpecifier GERAN_SPECIFIER_850 = {.radioAccessNetwork = RadioAcc TEST_F(RadioHidlTest_v1_2, startNetworkScan) { serial = GetRandomSerialNumber(); + if (radioConfig != NULL && DDS_LOGICAL_SLOT_INDEX != logicalSlotId) { + // Some DSDS devices have a limitation that network scans can only be performed on the + // logical modem that currently used for packet data. For now, skip the test on the + // non-data SIM. This exemption is removed in HAL version 1.4. See b/135243177 for + // additional information. + ALOGI("Skip network scan on non-dds SIM, slot id = %d", logicalSlotId); + return; + } + ::android::hardware::radio::V1_2::NetworkScanRequest request = { .type = ScanType::ONE_SHOT, .interval = 60, diff --git a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp index bff7481bed..835d9b8d16 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp +++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp @@ -37,6 +37,7 @@ void RadioHidlTest_v1_2::SetUp() { ASSERT_NE(nullptr, radioRsp_v1_2.get()); count_ = 0; + logicalSlotId = -1; radioInd_v1_2 = new (std::nothrow) RadioIndication_v1_2(*this); ASSERT_NE(nullptr, radioInd_v1_2.get()); @@ -50,6 +51,71 @@ void RadioHidlTest_v1_2::SetUp() { /* Enforce Vts Testing with Sim Status Present only. */ EXPECT_EQ(CardState::PRESENT, cardStatus.base.cardState); + + radioConfig = ::testing::VtsHalHidlTargetTestBase::getService< + ::android::hardware::radio::config::V1_1::IRadioConfig>(); + + /* Enforce Vts tesing with RadioConfig for network scan excemption. */ + // Some devices can only perform network scan on logical modem that currently used for packet + // data. This exemption is removed in HAL version 1.4. See b/135243177 for additional info. + if (radioConfig != NULL) { + // RadioConfig 1.1 available, some devices fall in excepmtion category. + ASSERT_NE(nullptr, radioConfig.get()); + + radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this); + ASSERT_NE(nullptr, radioConfigRsp.get()); + + /* Set radio config response functions */ + radioConfig->setResponseFunctions(radioConfigRsp, nullptr); + + /* set preferred data modem */ + setPreferredDataModem(); + + /* get current logical sim id */ + getLogicalSimId(); + } +} + +void RadioHidlTest_v1_2::getLogicalSimId() { + serial = GetRandomSerialNumber(); + radioConfig->getSimSlotsStatus(serial); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); + EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); + + ASSERT_TRUE(CheckAnyOfErrors(radioConfigRsp->rspInfo.error, + {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED})); + + if (radioConfigRsp->rspInfo.error != RadioError ::NONE) { + ALOGI("Failed to get sim slot status, rspInfo.error = %s\n", + toString(radioConfigRsp->rspInfo.error).c_str()); + return; + } + + if (cardStatus.physicalSlotId < 0 || + cardStatus.physicalSlotId >= radioConfigRsp->simSlotStatus.size()) { + ALOGI("Physical slot id: %d is out of range", cardStatus.physicalSlotId); + return; + } + + logicalSlotId = radioConfigRsp->simSlotStatus[cardStatus.physicalSlotId].logicalSlotId; +} + +/* + * Set preferred data modem + */ +void RadioHidlTest_v1_2::setPreferredDataModem() { + serial = GetRandomSerialNumber(); + // Even for single sim device, the setPreferredDataModem should still success. Enforce dds on + // first logical modem. + radioConfig->setPreferredDataModem(serial, DDS_LOGICAL_SLOT_INDEX); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type); + EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial); + + ASSERT_TRUE(CheckAnyOfErrors( + radioConfigRsp->rspInfo.error, + {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR})); } /* diff --git a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h index 3f780e555a..2db1cac724 100644 --- a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h +++ b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h @@ -22,6 +22,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -32,13 +36,17 @@ using namespace ::android::hardware::radio::V1_2; using namespace ::android::hardware::radio::V1_1; using namespace ::android::hardware::radio::V1_0; +using namespace ::android::hardware::radio::config::V1_1; +using ::android::sp; using ::android::hardware::hidl_bitfield; using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; -using ::android::sp; +using ::android::hardware::radio::config::V1_0::SimSlotStatus; +using ::android::hardware::radio::V1_0::RadioResponseInfo; +using ::android::hardware::radio::V1_0::RadioResponseType; #define TIMEOUT_PERIOD 75 #define RADIO_SERVICE_NAME "slot1" @@ -46,6 +54,36 @@ using ::android::sp; class RadioHidlTest_v1_2; extern ::android::hardware::radio::V1_2::CardStatus cardStatus; +/* Callback class for radio config response */ +class RadioConfigResponse : public IRadioConfigResponse { + protected: + RadioHidlTest_v1_2& parent_v1_2; + + public: + RadioResponseInfo rspInfo; + PhoneCapability phoneCap; + hidl_vec simSlotStatus; + + RadioConfigResponse(RadioHidlTest_v1_2& parent_v1_2); + virtual ~RadioConfigResponse() = default; + + Return getSimSlotsStatusResponse( + const RadioResponseInfo& info, + const ::android::hardware::hidl_vec& slotStatus); + + Return setSimSlotsMappingResponse(const RadioResponseInfo& info); + + Return getPhoneCapabilityResponse(const RadioResponseInfo& info, + const PhoneCapability& phoneCapability); + + Return setPreferredDataModemResponse(const RadioResponseInfo& info); + + Return getModemsConfigResponse(const RadioResponseInfo& info, + const ModemsConfig& mConfig); + + Return setModemsConfigResponse(const RadioResponseInfo& info); +}; + /* Callback class for radio response v1_2*/ class RadioResponse_v1_2 : public ::android::hardware::radio::V1_2::IRadioResponse { protected: @@ -616,15 +654,27 @@ class RadioHidlTest_v1_2 : public ::testing::VtsHalHidlTargetTestBase { std::condition_variable cv_; int count_; + /* Preferred data sim id */ + const int DDS_LOGICAL_SLOT_INDEX = 0; + /* Serial number for radio request */ int serial; + /* Current logical slot id */ + int logicalSlotId; + /* Update Sim Card Status */ void updateSimCardStatus(); /* Stop Network Scan Command */ void stopNetworkScan(); + /* Set preferred data modem */ + void setPreferredDataModem(); + + /* get current logical sim id */ + void getLogicalSimId(); + public: virtual void SetUp() override; @@ -642,4 +692,10 @@ class RadioHidlTest_v1_2 : public ::testing::VtsHalHidlTargetTestBase { /* radio indication handle */ sp radioInd_v1_2; + + /* radio config response handle */ + sp radioConfigRsp; + + /* radio config service handle */ + sp radioConfig; }; \ No newline at end of file From 1a20113e688d0b276bbc0e53db6feef8f64f933d Mon Sep 17 00:00:00 2001 From: Nate Jiang Date: Wed, 29 May 2019 13:49:36 -0700 Subject: [PATCH 23/35] Setting callbacktype type to invalid value before invoking HIDL call Avoid race condition between event callback and wait context. Make callbacktype to invalid before call function to change it. Test: excute VtsHalWifiNanV1_0TargetTest VtsHalWifiNanV1_2TargetTest Bug: 133484330 Merged-In: I9211c3e172727f56d0cceaf91b98f8d5b3c7fc7e Change-Id: I0a7e27411cb8fbd877f8228e9d53b62cac424b17 --- wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp | 3 ++- wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp index 85bcccd230..64b4fb6d1a 100644 --- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -91,12 +91,12 @@ class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { }; /* Test code calls this function to wait for data/event callback */ + /* Must set callbackType = INVALID before call this function */ inline std::cv_status wait(CallbackType waitForCallbackType) { std::unique_lock lock(mtx_); EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a non-void-returning method - callbackType = INVALID; std::cv_status status = std::cv_status::no_timeout; auto now = std::chrono::system_clock::now(); while (count_ == 0) { @@ -469,6 +469,7 @@ TEST(WifiNanIfaceHidlTestNoFixture, FailOnIfaceInvalid) { */ TEST_F(WifiNanIfaceHidlTest, getCapabilitiesRequest) { uint16_t inputCmdId = 10; + callbackType = INVALID; ASSERT_EQ(WifiStatusCode::SUCCESS, HIDL_INVOKE(iwifiNanIface, getCapabilitiesRequest, inputCmdId).code); // wait for a callback diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp index cc36faeafc..4dbc82bd99 100644 --- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp +++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp @@ -100,13 +100,13 @@ class WifiNanIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase { }; /* Test code calls this function to wait for data/event callback */ + /* Must set callbackType = INVALID before call this function */ inline std::cv_status wait(CallbackType waitForCallbackType) { std::unique_lock lock(mtx_); EXPECT_NE(INVALID, waitForCallbackType); // can't ASSERT in a // non-void-returning method - callbackType = INVALID; std::cv_status status = std::cv_status::no_timeout; auto now = std::chrono::system_clock::now(); while (count_ == 0) { @@ -475,6 +475,7 @@ TEST(WifiNanIfaceHidlTestNoFixture, Create) { */ TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2InvalidArgs) { uint16_t inputCmdId = 10; + callbackType = INVALID; NanEnableRequest nanEnableRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; ASSERT_EQ(WifiStatusCode::SUCCESS, @@ -509,6 +510,7 @@ TEST_F(WifiNanIfaceHidlTest, enableRequest_1_2ShimInvalidArgs) { */ TEST_F(WifiNanIfaceHidlTest, configRequest_1_2InvalidArgs) { uint16_t inputCmdId = 10; + callbackType = INVALID; NanConfigRequest nanConfigRequest = {}; NanConfigRequestSupplemental nanConfigRequestSupp = {}; ASSERT_EQ(WifiStatusCode::SUCCESS, From d005bbeb53ab7b170335acd038115499d25a5d3c Mon Sep 17 00:00:00 2001 From: Youming Ye Date: Mon, 22 Jul 2019 18:34:52 -0700 Subject: [PATCH 24/35] Add REQUEST_NOT_SUPPORTED to startNetworkScan Test: VTS Bug: 137298570 Change-Id: I0afacd413d467c3e25585d6d5431278fd61a1562 --- .../1.4/vts/functional/radio_hidl_hal_api.cpp | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp index 0fcd32d615..f81af9b261 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp @@ -196,10 +196,17 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan) { if (cardStatus.base.base.cardState == CardState::ABSENT) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do not support the - // required manual GSM search functionality. This is tracked in b/112206766. - ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, - {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED})); + // OPERATION_NOT_ALLOWED should not be allowed; however, some vendors do + // not support the required manual GSM search functionality. This is + // tracked in b/112206766. REQUEST_NOT_SUPPORTED is temporarily added back + // because of vendors failed to implement startNetworkScan in HAL 1.4 (see + // b/137298570 and b/135595082). Starting from 1.5, however, + // REQUEST_NOT_SUPPORTED will be disallowed. Modems have "GSM" rat scan + // need to support scanning requests combined with some parameters. + ASSERT_TRUE( + CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED, + RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -225,8 +232,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidArgument) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -261,8 +269,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -296,8 +305,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -331,8 +341,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -366,8 +377,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -401,8 +413,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -436,8 +449,9 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE( - CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE(CheckAnyOfErrors( + radioRsp_v1_4->rspInfo.error, + {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -473,8 +487,10 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, - {RadioError::NONE, RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE( + CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::INVALID_ARGUMENTS, + RadioError::REQUEST_NOT_SUPPORTED})); } } @@ -512,8 +528,10 @@ TEST_F(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) { ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT})); } else if (cardStatus.base.base.cardState == CardState::PRESENT) { - ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, - {RadioError::NONE, RadioError::INVALID_ARGUMENTS})); + ASSERT_TRUE( + CheckAnyOfErrors(radioRsp_v1_4->rspInfo.error, + {RadioError::NONE, RadioError::INVALID_ARGUMENTS, + RadioError::REQUEST_NOT_SUPPORTED})); } } From 5f68117e87f4761948ce287d239c38b7c33081c0 Mon Sep 17 00:00:00 2001 From: sqian Date: Fri, 26 Jul 2019 11:47:28 -0700 Subject: [PATCH 25/35] Verify there are no more current calls After disconnect calls, we want to verify there are no more current calls by calling IRadio.getCurrenctCalls Test: run vts Bug: 138413412 Change-Id: Iacca49abff11fbdfb4ae6dd060a5f150e9e4a74d --- radio/1.4/vts/functional/radio_hidl_hal_test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp index 63e5f6ed53..f27749b3e3 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp @@ -102,6 +102,12 @@ void RadioHidlTest_v1_4::clearPotentialEstablishedCalls() { // Give some time for modem to disconnect the established call channel. sleep(MODEM_EMERGENCY_CALL_DISCONNECT_TIME); } + + // Verify there are no more current calls. + serial = GetRandomSerialNumber(); + radio_v1_4->getCurrentCalls(serial); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + EXPECT_EQ(0, radioRsp_v1_4->currentCalls.size()); } void RadioHidlTest_v1_4::updateSimCardStatus() { From 4335de4cac65acd3f8cffc88c91982d0cea999d1 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Mon, 29 Jul 2019 11:15:25 -0700 Subject: [PATCH 26/35] hostapd(vts): Use the correct syntax for vendor prop Change the prop to add "ro.vendor." prefix for the new vendor prop. Bug: 136645414 Change-Id: I5edfdc98991068eac279975397b6a29313bf31da --- wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp index 7aaad02ac2..ffd4d97a56 100644 --- a/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.1/vts/functional/hostapd_hidl_test.cpp @@ -56,7 +56,8 @@ class HostapdHidlTest : public ::testing::VtsHalHidlTargetTestBase { protected: std::string getPrimaryWlanIfaceName() { std::array buffer; - auto res = property_get("wifi.sap.interface", buffer.data(), nullptr); + auto res = property_get("ro.vendor.wifi.sap.interface", + buffer.data(), nullptr); if (res > 0) return buffer.data(); property_get("wifi.interface", buffer.data(), "wlan0"); return buffer.data(); From 4a80e231ed6d5c60d4421b11b5f82690a6f737b7 Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Fri, 26 Jul 2019 15:19:00 -0400 Subject: [PATCH 27/35] Fix wait_for timestamps in Sensors VTS Previously, NoStaleEvents was treating any timestamps it dealt with as if they were in microseconds, but sensors.minDelay is in microseconds and Event timestamps are in nanoseconds. This uses std::chrono helpers to ensure the correct time is used when deciding how long to sleep during the test so that if waitForEvents never passes, the test doesn't time out. Bug: 136736906 Test: Run VTS and verify VtsHalSensorsV2_0Target doesn't finish as an incomplete module. Change-Id: Ibba59dbf9312f97d7275e5aa8cd36547ab09e328 --- .../VtsHalSensorsV2_0TargetTest.cpp | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 91b4fa5594..6ff393d4b9 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -38,6 +38,10 @@ using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset; using ::android::hardware::sensors::V1_0::SensorStatus; using ::android::hardware::sensors::V1_0::SharedMemType; using ::android::hardware::sensors::V1_0::Vec3; +using std::chrono::duration_cast; +using std::chrono::microseconds; +using std::chrono::milliseconds; +using std::chrono::nanoseconds; constexpr size_t kEventSize = static_cast(SensorsEventFormatOffset::TOTAL_LENGTH); @@ -67,9 +71,9 @@ class EventCallback : public IEventCallback { } void waitForFlushEvents(const std::vector& sensorsToWaitFor, - int32_t numCallsToFlush, int64_t timeoutMs) { + int32_t numCallsToFlush, milliseconds timeout) { std::unique_lock lock(mFlushMutex); - mFlushCV.wait_for(lock, std::chrono::milliseconds(timeoutMs), + mFlushCV.wait_for(lock, timeout, [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); }); } @@ -78,10 +82,9 @@ class EventCallback : public IEventCallback { return mEventMap[sensorHandle]; } - void waitForEvents(const std::vector& sensorsToWaitFor, int32_t timeoutMs) { + void waitForEvents(const std::vector& sensorsToWaitFor, milliseconds timeout) { std::unique_lock lock(mEventMutex); - mEventCV.wait_for(lock, std::chrono::milliseconds(timeoutMs), - [&] { return eventsReceived(sensorsToWaitFor); }); + mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); }); } protected: @@ -372,7 +375,7 @@ TEST_F(SensorsHidlTest, InjectSensorEventData) { } // Wait for events to be written back to the Event FMQ - callback.waitForEvents(sensors, 1000 /* timeoutMs */); + callback.waitForEvents(sensors, milliseconds(1000) /* timeout */); for (const auto& s : sensors) { auto events = callback.getEvents(s.sensorHandle); @@ -699,7 +702,7 @@ void SensorsHidlTest::runFlushTest(const std::vector& sensors, bool } // Wait up to one second for the flush events - callback.waitForFlushEvents(sensors, flushCalls, 1000 /* timeoutMs */); + callback.waitForFlushEvents(sensors, flushCalls, milliseconds(1000) /* timeout */); // Deactivate all sensors after waiting for flush events so pending flush events are not // abandoned by the HAL. @@ -820,17 +823,18 @@ TEST_F(SensorsHidlTest, Activate) { } TEST_F(SensorsHidlTest, NoStaleEvents) { - constexpr int64_t kFiveHundredMilliseconds = 500 * 1000; - constexpr int64_t kOneSecond = 1000 * 1000; + constexpr milliseconds kFiveHundredMs(500); + constexpr milliseconds kOneSecond(1000); // Register the callback to receive sensor events EventCallback callback; getEnvironment()->registerCallback(&callback); const std::vector sensors = getSensorsList(); - int32_t maxMinDelay = 0; + milliseconds maxMinDelay(0); for (const SensorInfo& sensor : getSensorsList()) { - maxMinDelay = std::max(maxMinDelay, sensor.minDelay); + milliseconds minDelay = duration_cast(microseconds(sensor.minDelay)); + maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count())); } // Activate the sensors so that they start generating events @@ -839,7 +843,7 @@ TEST_F(SensorsHidlTest, NoStaleEvents) { // According to the CDD, the first sample must be generated within 400ms + 2 * sample_time // and the maximum reporting latency is 100ms + 2 * sample_time. Wait a sufficient amount // of time to guarantee that a sample has arrived. - callback.waitForEvents(sensors, kFiveHundredMilliseconds + (5 * maxMinDelay)); + callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); activateAllSensors(false); // Save the last received event for each sensor @@ -851,21 +855,21 @@ TEST_F(SensorsHidlTest, NoStaleEvents) { } // Allow some time to pass, reset the callback, then reactivate the sensors - usleep(kOneSecond + (5 * maxMinDelay)); + usleep(duration_cast(kOneSecond + (5 * maxMinDelay)).count()); callback.reset(); activateAllSensors(true); - callback.waitForEvents(sensors, kFiveHundredMilliseconds + (5 * maxMinDelay)); + callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay)); activateAllSensors(false); for (const SensorInfo& sensor : sensors) { // Ensure that the first event received is not stale by ensuring that its timestamp is // sufficiently different from the previous event const Event newEvent = callback.getEvents(sensor.sensorHandle).front(); - int64_t delta = newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]; - ASSERT_GE(delta, kFiveHundredMilliseconds + (3 * sensor.minDelay)); + milliseconds delta = duration_cast( + nanoseconds(newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle])); + milliseconds sensorMinDelay = duration_cast(microseconds(sensor.minDelay)); + ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay)); } - - getEnvironment()->unregisterCallback(); } void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, From b492526cac77d89a485eb50f811eb6468e2cb639 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 16 Jul 2019 14:43:36 -0700 Subject: [PATCH 28/35] Fix cas build. Bug : 137128492 Test: Manual Change-Id: I37eec1138d9a6eff92c7df30b4c1b7ba7a45e3ae (cherry picked from commit b2ee26784bfa8f1d1520bd0909e3f93f826e0b7d) --- cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc | 1 + 1 file changed, 1 insertion(+) diff --git a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc index 9227b6f7e4..73c505d351 100644 --- a/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc +++ b/cas/1.1/default/android.hardware.cas@1.1-service-lazy.rc @@ -1,4 +1,5 @@ service vendor.cas-hal-1-1 /vendor/bin/hw/android.hardware.cas@1.1-service-lazy + interface android.hardware.cas@1.0::IMediaCasService default interface android.hardware.cas@1.1::IMediaCasService default oneshot disabled From df6e2b70aef693e17a7d25034c7723009b31220b Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Thu, 1 Aug 2019 19:18:06 -0700 Subject: [PATCH 29/35] Add support for new gralloc HAL versions As VTS connects to the IMapper and IAllocator HALs directly, it needs to handle the case where the device only supports the newer HAL versions, which includes IMapper 2.1 & 3.0 and IAllocator 3.0. Since sensors VTS uses the same functionality from the different HAL versions, condense the code into a common interface with HAL version-specific template instantiation. Also remove the unused code that came along with copying from the gralloc VTS reference source. Bug: 138758242 Test: run gralloc-related sensors VTS on Pixel 2+ Change-Id: I1646d8f92546623594af8541bc8ac02955370694 --- sensors/1.0/vts/functional/Android.bp | 3 + sensors/2.0/vts/functional/Android.bp | 3 + sensors/common/vts/utils/Android.bp | 3 + sensors/common/vts/utils/GrallocWrapper.cpp | 372 ++++++++++-------- .../vts/utils/SensorsTestSharedMemory.cpp | 29 +- .../sensors-vts-utils/GrallocWrapper.h | 65 ++- 6 files changed, 250 insertions(+), 225 deletions(-) diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp index 444797d4d0..7bb992bf23 100644 --- a/sensors/1.0/vts/functional/Android.bp +++ b/sensors/1.0/vts/functional/Android.bp @@ -24,7 +24,10 @@ cc_test { ], static_libs: [ "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@3.0", "android.hardware.sensors@1.0", "VtsHalSensorsTargetTestUtils", ], diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp index 98f0eacae9..4765fa2797 100644 --- a/sensors/2.0/vts/functional/Android.bp +++ b/sensors/2.0/vts/functional/Android.bp @@ -24,7 +24,10 @@ cc_test { ], static_libs: [ "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@3.0", "android.hardware.sensors@1.0", "android.hardware.sensors@2.0", "libfmq", diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp index 8da554aa40..02dc608858 100644 --- a/sensors/common/vts/utils/Android.bp +++ b/sensors/common/vts/utils/Android.bp @@ -31,7 +31,10 @@ cc_library_static { ], static_libs: [ "android.hardware.graphics.allocator@2.0", + "android.hardware.graphics.allocator@3.0", "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@2.1", + "android.hardware.graphics.mapper@3.0", "android.hardware.sensors@1.0", "VtsHalHidlTargetTestBase", ], diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp index 222ef9611a..1cad9135b7 100644 --- a/sensors/common/vts/utils/GrallocWrapper.cpp +++ b/sensors/common/vts/utils/GrallocWrapper.cpp @@ -16,206 +16,262 @@ #include "GrallocWrapper.h" +#include +#include +#include +#include +#include + #include +#include +#include + +using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator; +using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator; +using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper; +using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper; +using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper; + +using Error2 = ::android::hardware::graphics::mapper::V2_0::Error; +using Error3 = ::android::hardware::graphics::mapper::V3_0::Error; + +using ::android::hardware::graphics::common::V1_0::BufferUsage; +using ::android::hardware::graphics::common::V1_0::PixelFormat; + +// This is a typedef to the same underlying type across v2.0 and v3.0 +using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor; + +using ::android::hardware::hidl_handle; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; + namespace android { -GrallocWrapper::GrallocWrapper() { - init(); +// Since we use the same APIs across allocator/mapper HALs but they have major +// version differences (meaning they are not related through inheritance), we +// create a common interface abstraction for the IAllocator + IMapper combination +// (major versions need to match in the current HALs, e.g. IAllocator 3.0 needs to +// be paired with IMapper 3.0, so these are tied together) +class IGrallocHalWrapper { + public: + virtual ~IGrallocHalWrapper() = default; + + // IAllocator + virtual std::string dumpDebugInfo() = 0; + virtual native_handle_t* allocate(uint32_t size) = 0; + virtual void freeBuffer(native_handle_t* bufferHandle) = 0; + + // IMapper + virtual void* lock(native_handle_t* bufferHandle) = 0; + virtual void unlock(native_handle_t* bufferHandle) = 0; +}; + +namespace { + +bool failed(Error2 error) { + return (error != Error2::NONE); +} +bool failed(Error3 error) { + return (error != Error3::NONE); } -void GrallocWrapper::init() { - mAllocator = allocator2::IAllocator::getService(); - if (mAllocator == nullptr) { - ALOGE("Failed to get allocator service"); - } - - mMapper = mapper2::IMapper::getService(); - if (mMapper == nullptr) { - ALOGE("Failed to get mapper service"); - } else if (mMapper->isRemote()) { - ALOGE("Mapper is not in passthrough mode"); - } -} - -GrallocWrapper::~GrallocWrapper() { - for (auto bufferHandle : mClonedBuffers) { - auto buffer = const_cast(bufferHandle); - native_handle_close(buffer); - native_handle_delete(buffer); - } - mClonedBuffers.clear(); - - for (auto bufferHandle : mImportedBuffers) { - auto buffer = const_cast(bufferHandle); - if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) { - ALOGE("Failed to free buffer %p", buffer); +// Since all the type and function names are the same for the things we use across the major HAL +// versions, we use template magic to avoid repeating ourselves. +template +class GrallocHalWrapper : public IGrallocHalWrapper { + public: + GrallocHalWrapper(const sp& allocator, const sp& mapper) + : mAllocator(allocator), mMapper(mapper) { + if (mapper->isRemote()) { + ALOGE("Mapper is in passthrough mode"); } } - mImportedBuffers.clear(); -} -sp GrallocWrapper::getAllocator() const { - return mAllocator; -} + virtual std::string dumpDebugInfo() override; + virtual native_handle_t* allocate(uint32_t size) override; + virtual void freeBuffer(native_handle_t* bufferHandle) override; -std::string GrallocWrapper::dumpDebugInfo() { + virtual void* lock(native_handle_t* bufferHandle) override; + virtual void unlock(native_handle_t* bufferHandle) override; + + private: + static constexpr uint64_t kBufferUsage = + static_cast(BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::CPU_READ_OFTEN); + sp mAllocator; + sp mMapper; + + BufferDescriptor getDescriptor(uint32_t size); + native_handle_t* importBuffer(const hidl_handle& rawHandle); +}; + +template +std::string GrallocHalWrapper::dumpDebugInfo() { std::string debugInfo; - mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); - + mAllocator->dumpDebugInfo([&](const hidl_string& tmpDebugInfo) { debugInfo = tmpDebugInfo; }); return debugInfo; } -const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) { - const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle()); +template +native_handle_t* GrallocHalWrapper::allocate(uint32_t size) { + constexpr uint32_t kBufferCount = 1; + BufferDescriptor descriptor = getDescriptor(size); + native_handle_t* bufferHandle = nullptr; - if (bufferHandle) { - mClonedBuffers.insert(bufferHandle); - } + auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec& buffers) { + if (failed(error)) { + ALOGE("Failed to allocate buffer: %" PRId32, static_cast(error)); + } else if (buffers.size() != kBufferCount) { + ALOGE("Invalid buffer array size (got %zu, expected %" PRIu32 ")", buffers.size(), + kBufferCount); + } else { + bufferHandle = importBuffer(buffers[0]); + } + }; + + mAllocator->allocate(descriptor, kBufferCount, callback); return bufferHandle; } -std::vector GrallocWrapper::allocate( - const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) { - std::vector bufferHandles; - bufferHandles.reserve(count); - mAllocator->allocate(descriptor, count, - [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) { - if (mapper2::Error::NONE != tmpError) { - ALOGE("Failed to allocate buffers"); - } - if (count != tmpBuffers.size()) { - ALOGE("Invalid buffer array"); - } - - for (uint32_t i = 0; i < count; i++) { - if (import) { - bufferHandles.push_back(importBuffer(tmpBuffers[i])); - } else { - bufferHandles.push_back(cloneBuffer(tmpBuffers[i])); - } - } - - if (outStride) { - *outStride = tmpStride; - } - }); - - return bufferHandles; +template +void GrallocHalWrapper::freeBuffer(native_handle_t* bufferHandle) { + auto error = mMapper->freeBuffer(bufferHandle); + if (!error.isOk() || failed(error)) { + ALOGE("Failed to free buffer %p", bufferHandle); + } } -const native_handle_t* GrallocWrapper::allocate( - const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import, - uint32_t* outStride) { - mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo); - auto buffers = allocate(descriptor, 1, import, outStride); - return buffers[0]; -} +template +BufferDescriptor GrallocHalWrapper::getDescriptor(uint32_t size) { + typename MapperT::BufferDescriptorInfo descriptorInfo = { + .width = size, + .height = 1, + .layerCount = 1, + .usage = kBufferUsage, + .format = static_cast(PixelFormat::BLOB), + }; -sp GrallocWrapper::getMapper() const { - return mMapper; -} - -mapper2::BufferDescriptor GrallocWrapper::createDescriptor( - const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) { - mapper2::BufferDescriptor descriptor; - mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) { - if (tmpError != mapper2::Error::NONE) { - ALOGE("Failed to create descriptor"); + BufferDescriptor descriptor; + auto callback = [&](auto error, const BufferDescriptor& tmpDescriptor) { + if (failed(error)) { + ALOGE("Failed to create descriptor: %" PRId32, static_cast(error)); + } else { + descriptor = tmpDescriptor; } - descriptor = tmpDescriptor; - }); + }; + mMapper->createDescriptor(descriptorInfo, callback); return descriptor; } -const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) { - const native_handle_t* bufferHandle = nullptr; - mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) { - if (tmpError != mapper2::Error::NONE) { - ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle()); - } - bufferHandle = static_cast(tmpBuffer); - }); +template +native_handle_t* GrallocHalWrapper::importBuffer( + const hidl_handle& rawHandle) { + native_handle_t* bufferHandle = nullptr; - if (bufferHandle) { - mImportedBuffers.insert(bufferHandle); - } + mMapper->importBuffer(rawHandle, [&](auto error, void* tmpBuffer) { + if (failed(error)) { + ALOGE("Failed to import buffer %p: %" PRId32, rawHandle.getNativeHandle(), + static_cast(error)); + } else { + bufferHandle = static_cast(tmpBuffer); + } + }); return bufferHandle; } -void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) { - auto buffer = const_cast(bufferHandle); - - if (mImportedBuffers.erase(bufferHandle)) { - mapper2::Error error = mMapper->freeBuffer(buffer); - if (error != mapper2::Error::NONE) { - ALOGE("Failed to free %p", buffer); - } - } else { - mClonedBuffers.erase(bufferHandle); - native_handle_close(buffer); - native_handle_delete(buffer); - } -} - -void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, - const mapper2::IMapper::Rect& accessRegion, int acquireFence) { - auto buffer = const_cast(bufferHandle); - - NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0); - hardware::hidl_handle acquireFenceHandle; - if (acquireFence >= 0) { - auto h = native_handle_init(acquireFenceStorage, 1, 0); - h->data[0] = acquireFence; - acquireFenceHandle = h; - } +template +void* GrallocHalWrapper::lock(native_handle_t* bufferHandle) { + // Per the HAL, all-zeros Rect means the entire buffer + typename MapperT::Rect accessRegion = {}; + hidl_handle acquireFenceHandle; // No fence needed, already safe to lock void* data = nullptr; - mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle, - [&](const auto& tmpError, const auto& tmpData) { - if (tmpError != mapper2::Error::NONE) { - ALOGE("Failed to lock buffer %p", buffer); + mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle, + [&](auto error, void* tmpData, ...) { // V3_0 passes extra args we don't use + if (failed(error)) { + ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle, + static_cast(error)); + } else { + data = tmpData; } - data = tmpData; }); - if (acquireFence >= 0) { - close(acquireFence); - } - return data; } -int GrallocWrapper::unlock(const native_handle_t* bufferHandle) { - auto buffer = const_cast(bufferHandle); - - int releaseFence = -1; - mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) { - if (tmpError != mapper2::Error::NONE) { - ALOGE("Failed to unlock buffer %p", buffer); - } - - auto fenceHandle = tmpReleaseFence.getNativeHandle(); - if (fenceHandle) { - if (fenceHandle->numInts != 0) { - ALOGE("Invalid fence handle %p", fenceHandle); - } - if (fenceHandle->numFds == 1) { - releaseFence = dup(fenceHandle->data[0]); - if (releaseFence < 0) { - ALOGE("Failed to dup fence fd"); - } - } else { - if (fenceHandle->numFds != 0) { - ALOGE("Invalid fence handle %p", fenceHandle); - } - } +template +void GrallocHalWrapper::unlock(native_handle_t* bufferHandle) { + mMapper->unlock(bufferHandle, [&](auto error, const hidl_handle& /*releaseFence*/) { + if (failed(error)) { + ALOGE("Failed to unlock buffer %p: %" PRId32, bufferHandle, + static_cast(error)); } }); +} - return releaseFence; +} // anonymous namespace + +GrallocWrapper::GrallocWrapper() { + sp allocator3 = IAllocator3::getService(); + sp mapper3 = IMapper3::getService(); + + if (allocator3 != nullptr && mapper3 != nullptr) { + mGrallocHal = std::unique_ptr( + new GrallocHalWrapper(allocator3, mapper3)); + } else { + ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x", + (allocator3 != nullptr), (mapper3 != nullptr)); + + sp allocator2 = IAllocator2::getService(); + sp mapper2 = IMapper2_1::getService(); + if (mapper2 == nullptr) { + mapper2 = IMapper2::getService(); + } + + if (allocator2 != nullptr && mapper2 != nullptr) { + mGrallocHal = std::unique_ptr( + new GrallocHalWrapper(allocator2, mapper2)); + } else { + ALOGE("Couldn't open 2.x/3.0 graphics HALs (2.x allocator %d mapper %d)", + (allocator2 != nullptr), (mapper2 != nullptr)); + } + } +} + +GrallocWrapper::~GrallocWrapper() { + for (auto bufferHandle : mAllocatedBuffers) { + mGrallocHal->unlock(bufferHandle); + mGrallocHal->freeBuffer(bufferHandle); + } + mAllocatedBuffers.clear(); +} + +std::string GrallocWrapper::dumpDebugInfo() { + return mGrallocHal->dumpDebugInfo(); +} + +std::pair GrallocWrapper::allocate(uint32_t size) { + native_handle_t* bufferHandle = mGrallocHal->allocate(size); + void* buffer = nullptr; + if (bufferHandle) { + buffer = mGrallocHal->lock(bufferHandle); + if (buffer) { + mAllocatedBuffers.insert(bufferHandle); + } else { + mGrallocHal->freeBuffer(bufferHandle); + bufferHandle = nullptr; + } + } + return std::make_pair<>(bufferHandle, buffer); +} + +void GrallocWrapper::freeBuffer(native_handle_t* bufferHandle) { + if (mAllocatedBuffers.erase(bufferHandle)) { + mGrallocHal->unlock(bufferHandle); + mGrallocHal->freeBuffer(bufferHandle); + } } } // namespace android diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp index 819e2974f7..3b068bd5c5 100644 --- a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp +++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp @@ -119,32 +119,13 @@ SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size } case SharedMemType::GRALLOC: { mGrallocWrapper = std::make_unique<::android::GrallocWrapper>(); - if (mGrallocWrapper->getAllocator() == nullptr || - mGrallocWrapper->getMapper() == nullptr) { + if (!mGrallocWrapper->isInitialized()) { break; } - using android::hardware::graphics::common::V1_0::BufferUsage; - using android::hardware::graphics::common::V1_0::PixelFormat; - mapper2::IMapper::BufferDescriptorInfo buf_desc_info = { - .width = static_cast(size), - .height = 1, - .layerCount = 1, - .usage = static_cast(BufferUsage::SENSOR_DIRECT_DATA | - BufferUsage::CPU_READ_OFTEN), - .format = PixelFormat::BLOB}; - handle = const_cast(mGrallocWrapper->allocate(buf_desc_info)); - if (handle != nullptr) { - mapper2::IMapper::Rect region{0, 0, static_cast(buf_desc_info.width), - static_cast(buf_desc_info.height)}; - buffer = static_cast( - mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1)); - if (buffer != nullptr) { - break; - } - mGrallocWrapper->freeBuffer(handle); - handle = nullptr; - } + std::pair buf = mGrallocWrapper->allocate(size); + handle = buf.first; + buffer = static_cast(buf.second); break; } default: @@ -175,9 +156,7 @@ SensorsTestSharedMemory::~SensorsTestSharedMemory() { } case SharedMemType::GRALLOC: { if (mSize != 0) { - mGrallocWrapper->unlock(mNativeHandle); mGrallocWrapper->freeBuffer(mNativeHandle); - mNativeHandle = nullptr; mSize = 0; } diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h index 3bd73c36e0..41e6334893 100644 --- a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h +++ b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h @@ -14,66 +14,47 @@ * limitations under the License. */ -#ifndef GRALLO_WRAPPER_H_ -#define GRALLO_WRAPPER_H_ +#pragma once +#include + +#include +#include #include - -#include -#include - -namespace allocator2 = ::android::hardware::graphics::allocator::V2_0; -namespace mapper2 = ::android::hardware::graphics::mapper::V2_0; +#include namespace android { -// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/ +class IGrallocHalWrapper; + +// Reference: hardware/interfaces/graphics/mapper/2.0/vts/functional/ class GrallocWrapper { public: GrallocWrapper(); ~GrallocWrapper(); - sp getAllocator() const; - sp getMapper() const; + // After constructing this object, this function must be called to check the result. If it + // returns false, other methods are not safe to call. + bool isInitialized() const { return (mGrallocHal != nullptr); }; std::string dumpDebugInfo(); - // When import is false, this simply calls IAllocator::allocate. When import - // is true, the returned buffers are also imported into the mapper. - // - // Either case, the returned buffers must be freed with freeBuffer. - std::vector allocate(const mapper2::BufferDescriptor& descriptor, - uint32_t count, bool import = true, - uint32_t* outStride = nullptr); - const native_handle_t* allocate(const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, - bool import = true, uint32_t* outStride = nullptr); + // Allocates a gralloc buffer suitable for direct channel sensors usage with the given size. + // The buffer should be freed using freeBuffer when it's not needed anymore; otherwise it'll + // be freed when this object is destroyed. + // Returns a handle to the buffer, and a CPU-accessible pointer for reading. On failure, both + // will be set to nullptr. + std::pair allocate(uint32_t size); - mapper2::BufferDescriptor createDescriptor( - const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo); + // Releases a gralloc buffer previously returned by allocate() + void freeBuffer(native_handle_t* bufferHandle); - const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle); - void freeBuffer(const native_handle_t* bufferHandle); - - // We use fd instead of hardware::hidl_handle in these functions to pass fences - // in and out of the mapper. The ownership of the fd is always transferred - // with each of these functions. - void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, - const mapper2::IMapper::Rect& accessRegion, int acquireFence); - - int unlock(const native_handle_t* bufferHandle); - - private: - void init(); - const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle); - - sp mAllocator; - sp mMapper; + private: + std::unique_ptr mGrallocHal; // Keep track of all cloned and imported handles. When a test fails with // ASSERT_*, the destructor will free the handles for the test. - std::unordered_set mClonedBuffers; - std::unordered_set mImportedBuffers; + std::unordered_set mAllocatedBuffers; }; } // namespace android -#endif // GRALLO_WRAPPER_H_ From d8b212ec3e70b47e8b352a9d4abb7840403b4f2b Mon Sep 17 00:00:00 2001 From: Andrew Lehmer Date: Fri, 2 Aug 2019 14:01:57 -0700 Subject: [PATCH 30/35] Fix assumptions in SensorsHidlTest.NoStaleEvents This test was making a couple of false assumptions which were causing it to fail. The fixes are related to the following assertions: 1. One-shot sensors do not report an initial event. 2. Special sensors may not report an initial event. 2. Some on-change sensors may not report an initial event. The test now only checks for a stale event if the sensor reports an initial event consistently. Bug: 138758242 Test: ran on C2 DVT; only fails due to an improperly configured sensor Change-Id: I83f0cb2f6e878244f3d94ae77f64bb8ed2f78e0b --- .../VtsHalSensorsV2_0TargetTest.cpp | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 6ff393d4b9..460886fbcc 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -176,6 +176,7 @@ class SensorsHidlTest : public SensorsHidlTestBase { // Helper functions void activateAllSensors(bool enable); std::vector getNonOneShotSensors(); + std::vector getNonOneShotAndNonSpecialSensors(); std::vector getOneShotSensors(); std::vector getInjectEventSensors(); int32_t getInvalidSensorHandle(); @@ -257,6 +258,18 @@ std::vector SensorsHidlTest::getNonOneShotSensors() { return sensors; } +std::vector SensorsHidlTest::getNonOneShotAndNonSpecialSensors() { + std::vector sensors; + for (const SensorInfo& info : getSensorsList()) { + SensorFlagBits reportMode = extractReportMode(info.flags); + if (reportMode != SensorFlagBits::ONE_SHOT_MODE && + reportMode != SensorFlagBits::SPECIAL_REPORTING_MODE) { + sensors.push_back(info); + } + } + return sensors; +} + std::vector SensorsHidlTest::getOneShotSensors() { std::vector sensors; for (const SensorInfo& info : getSensorsList()) { @@ -830,9 +843,10 @@ TEST_F(SensorsHidlTest, NoStaleEvents) { EventCallback callback; getEnvironment()->registerCallback(&callback); - const std::vector sensors = getSensorsList(); + // This test is not valid for one-shot or special-report-mode sensors + const std::vector sensors = getNonOneShotAndNonSpecialSensors(); milliseconds maxMinDelay(0); - for (const SensorInfo& sensor : getSensorsList()) { + for (const SensorInfo& sensor : sensors) { milliseconds minDelay = duration_cast(microseconds(sensor.minDelay)); maxMinDelay = milliseconds(std::max(maxMinDelay.count(), minDelay.count())); } @@ -849,9 +863,14 @@ TEST_F(SensorsHidlTest, NoStaleEvents) { // Save the last received event for each sensor std::map lastEventTimestampMap; for (const SensorInfo& sensor : sensors) { - ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1); - lastEventTimestampMap[sensor.sensorHandle] = - callback.getEvents(sensor.sensorHandle).back().timestamp; + // Some on-change sensors may not report an event without stimulus + if (extractReportMode(sensor.flags) != SensorFlagBits::ON_CHANGE_MODE) { + ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1); + } + if (callback.getEvents(sensor.sensorHandle).size() >= 1) { + lastEventTimestampMap[sensor.sensorHandle] = + callback.getEvents(sensor.sensorHandle).back().timestamp; + } } // Allow some time to pass, reset the callback, then reactivate the sensors @@ -862,6 +881,14 @@ TEST_F(SensorsHidlTest, NoStaleEvents) { activateAllSensors(false); for (const SensorInfo& sensor : sensors) { + // Skip sensors that did not previously report an event + if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) { + continue; + } + // Skip on-change sensors that do not consistently report an initial event + if (callback.getEvents(sensor.sensorHandle).size() < 1) { + continue; + } // Ensure that the first event received is not stale by ensuring that its timestamp is // sufficiently different from the previous event const Event newEvent = callback.getEvents(sensor.sensorHandle).front(); From 66d8297210a6deb2e0a8608470780d52c5e09620 Mon Sep 17 00:00:00 2001 From: Vishal Agarwal Date: Fri, 2 Aug 2019 13:27:31 -0700 Subject: [PATCH 31/35] VTS Sensor HAL 2.0: Fix Batch for One Shot sensors One Shot sensors have minDelay set to -1. Force the minDelay to be 0 in the VTS test to avoid errors from invalid parameter Bug: 138758242 Test: Run Batch test manually VtsHalSensorsV2_0TargetTest --gtest_filter=SensorsHidlTest.Batch Change-Id: Ib2287f6f11502c10d346f5e7216c5f31d585edf9 --- sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 6ff393d4b9..72bdc8ddb4 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -777,7 +777,12 @@ TEST_F(SensorsHidlTest, Batch) { activateAllSensors(false /* enable */); for (const SensorInfo& sensor : getSensorsList()) { // Call batch on inactive sensor - ASSERT_EQ(batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */), + // One shot sensors have minDelay set to -1 which is an invalid + // parameter. Use 0 instead to avoid errors. + int64_t samplingPeriodNs = extractReportMode(sensor.flags) == SensorFlagBits::ONE_SHOT_MODE + ? 0 + : sensor.minDelay; + ASSERT_EQ(batch(sensor.sensorHandle, samplingPeriodNs, 0 /* maxReportLatencyNs */), Result::OK); // Activate the sensor From 4bdd8fc7749db53f477533d01c1234e60afa70a8 Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Fri, 2 Aug 2019 13:11:39 -0400 Subject: [PATCH 32/35] Change expected return type in direct report VTS If a sensor doesn't support a particular memory type for direct reporting, then registerChannel will return an invalid channel handle. When this handle is used in configureDirectReport, it will return BAD_VALUE and when used in unregisterDirectReport, it will return OK. Currently, the VTS tests assert it will return INVALID_OPERATION, but that will only happen if the entire HAL doesn't support direct reporting instead of a single sensor not supporting a certain memory type. Bug: 138758242 Test: Run VTS and verify DirectChannel* tests now pass Change-Id: Ifba4262b68ec0c4ca6921dad40a03e0a52088d28 --- .../VtsHalSensorsV2_0TargetTest.cpp | 80 +++++++++++++------ 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 6ff393d4b9..73789fe161 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -181,14 +181,15 @@ class SensorsHidlTest : public SensorsHidlTestBase { int32_t getInvalidSensorHandle(); bool getDirectChannelSensor(SensorInfo* sensor, SharedMemType* memType, RateLevel* rate); void verifyDirectChannel(SharedMemType memType); - void verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType, - std::shared_ptr mem, - int32_t* directChannelHandle); + void verifyRegisterDirectChannel(std::shared_ptr mem, + int32_t* directChannelHandle, bool supportsSharedMemType, + bool supportsAnyDirectChannel); void verifyConfigure(const SensorInfo& sensor, SharedMemType memType, - int32_t directChannelHandle); - void verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType, - int32_t directChannelHandle); + int32_t directChannelHandle, bool directChannelSupported); + void verifyUnregisterDirectChannel(int32_t directChannelHandle, bool directChannelSupported); void checkRateLevel(const SensorInfo& sensor, int32_t directChannelHandle, RateLevel rateLevel); + void queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType, + bool* supportsAnyDirectChannel); }; Return SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) { @@ -885,14 +886,34 @@ void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directCha }); } -void SensorsHidlTest::verifyRegisterDirectChannel(const SensorInfo& sensor, SharedMemType memType, - std::shared_ptr mem, - int32_t* directChannelHandle) { +void SensorsHidlTest::queryDirectChannelSupport(SharedMemType memType, bool* supportsSharedMemType, + bool* supportsAnyDirectChannel) { + *supportsSharedMemType = false; + *supportsAnyDirectChannel = false; + for (const SensorInfo& curSensor : getSensorsList()) { + if (isDirectChannelTypeSupported(curSensor, memType)) { + *supportsSharedMemType = true; + } + if (isDirectChannelTypeSupported(curSensor, SharedMemType::ASHMEM) || + isDirectChannelTypeSupported(curSensor, SharedMemType::GRALLOC)) { + *supportsAnyDirectChannel = true; + } + + if (*supportsSharedMemType && *supportsAnyDirectChannel) { + break; + } + } +} + +void SensorsHidlTest::verifyRegisterDirectChannel(std::shared_ptr mem, + int32_t* directChannelHandle, + bool supportsSharedMemType, + bool supportsAnyDirectChannel) { char* buffer = mem->getBuffer(); memset(buffer, 0xff, mem->getSize()); registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) { - if (isDirectChannelTypeSupported(sensor, memType)) { + if (supportsSharedMemType) { ASSERT_EQ(result, Result::OK); ASSERT_GT(channelHandle, 0); @@ -901,7 +922,9 @@ void SensorsHidlTest::verifyRegisterDirectChannel(const SensorInfo& sensor, Shar ASSERT_EQ(buffer[i], 0x00); } } else { - ASSERT_EQ(result, Result::INVALID_OPERATION); + Result expectedResult = + supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION; + ASSERT_EQ(result, expectedResult); ASSERT_EQ(channelHandle, -1); } *directChannelHandle = channelHandle; @@ -909,7 +932,7 @@ void SensorsHidlTest::verifyRegisterDirectChannel(const SensorInfo& sensor, Shar } void SensorsHidlTest::verifyConfigure(const SensorInfo& sensor, SharedMemType memType, - int32_t directChannelHandle) { + int32_t directChannelHandle, bool supportsAnyDirectChannel) { if (isDirectChannelTypeSupported(sensor, memType)) { // Verify that each rate level is properly supported checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL); @@ -925,22 +948,22 @@ void SensorsHidlTest::verifyConfigure(const SensorInfo& sensor, SharedMemType me -1 /* sensorHandle */, directChannelHandle, RateLevel::STOP, [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); }); } else { - // Direct channel is not supported for this SharedMemType + // directChannelHandle will be -1 here, HAL should either reject it as a bad value if there + // is some level of direct channel report, otherwise return INVALID_OPERATION if direct + // channel is not supported at all + Result expectedResult = + supportsAnyDirectChannel ? Result::BAD_VALUE : Result::INVALID_OPERATION; configDirectReport(sensor.sensorHandle, directChannelHandle, RateLevel::NORMAL, - [](Result result, int32_t /* reportToken */) { - ASSERT_EQ(result, Result::INVALID_OPERATION); + [expectedResult](Result result, int32_t /* reportToken */) { + ASSERT_EQ(result, expectedResult); }); } } -void SensorsHidlTest::verifyUnregisterDirectChannel(const SensorInfo& sensor, SharedMemType memType, - int32_t directChannelHandle) { - Result result = unregisterDirectChannel(directChannelHandle); - if (isDirectChannelTypeSupported(sensor, memType)) { - ASSERT_EQ(result, Result::OK); - } else { - ASSERT_EQ(result, Result::INVALID_OPERATION); - } +void SensorsHidlTest::verifyUnregisterDirectChannel(int32_t directChannelHandle, + bool supportsAnyDirectChannel) { + Result expectedResult = supportsAnyDirectChannel ? Result::OK : Result::INVALID_OPERATION; + ASSERT_EQ(unregisterDirectChannel(directChannelHandle), expectedResult); } void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) { @@ -951,11 +974,16 @@ void SensorsHidlTest::verifyDirectChannel(SharedMemType memType) { SensorsTestSharedMemory::create(memType, kMemSize)); ASSERT_NE(mem, nullptr); + bool supportsSharedMemType; + bool supportsAnyDirectChannel; + queryDirectChannelSupport(memType, &supportsSharedMemType, &supportsAnyDirectChannel); + for (const SensorInfo& sensor : getSensorsList()) { int32_t directChannelHandle = 0; - verifyRegisterDirectChannel(sensor, memType, mem, &directChannelHandle); - verifyConfigure(sensor, memType, directChannelHandle); - verifyUnregisterDirectChannel(sensor, memType, directChannelHandle); + verifyRegisterDirectChannel(mem, &directChannelHandle, supportsSharedMemType, + supportsAnyDirectChannel); + verifyConfigure(sensor, memType, directChannelHandle, supportsAnyDirectChannel); + verifyUnregisterDirectChannel(directChannelHandle, supportsAnyDirectChannel); } } From 63d4f579762b8b1bba1d0e29c9959aaa838d4529 Mon Sep 17 00:00:00 2001 From: Brian Duddie Date: Fri, 2 Aug 2019 15:06:20 -0700 Subject: [PATCH 33/35] Fix handling of reportToken when stopping VTS should ignore the reportToken returned by configDirectReport when it passes in RateLevel::STOP. Bug: 138758242 Test: run direct channel tests on device using 2.0 HAL Change-Id: I07e789157e051ceab488a61e856f17d50f435072 --- sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp index 73789fe161..da1268d8d2 100644 --- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp +++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp @@ -879,7 +879,9 @@ void SensorsHidlTest::checkRateLevel(const SensorInfo& sensor, int32_t directCha [&](Result result, int32_t reportToken) { if (isDirectReportRateSupported(sensor, rateLevel)) { ASSERT_EQ(result, Result::OK); - ASSERT_GT(reportToken, 0); + if (rateLevel != RateLevel::STOP) { + ASSERT_GT(reportToken, 0); + } } else { ASSERT_EQ(result, Result::BAD_VALUE); } From ad9f6b17a37668fc80e525051ca9cc57d56d681a Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Fri, 7 Jun 2019 18:32:54 -0700 Subject: [PATCH 34/35] Add GNSS satellite blacklist VTS 2.0 test - Use IGnssCallback@2.0::gnssSvStatusCb_2_0() method to receive SV info. - Run the test only if SATELLITE_BLACKLIST capability is supported. - IRNSS is excluded from blacklisting as IGnssConfiguration@2.0 is not updated to support the blacklisting new constellation type. - Modify the corresponding VTS 1.1 test to run only if the GNSS HAL version is 1.1. Bug: 128028791 Test: atest VtsHalGnssV2_0Target Change-Id: Idd44a5a1c9d54d7434da945ecbd1ee90007f5054 Merged-In: Idd44a5a1c9d54d7434da945ecbd1ee90007f5054 (cherry picked from commit f42602678f0df52ab7ee6a727979ea958f66d48e) --- gnss/1.1/vts/functional/gnss_hal_test.cpp | 28 ++ gnss/1.1/vts/functional/gnss_hal_test.h | 6 + .../vts/functional/gnss_hal_test_cases.cpp | 10 + .../functional/VtsHalGnssV2_0TargetTest.cpp | 1 - gnss/2.0/vts/functional/gnss_hal_test.cpp | 4 +- gnss/2.0/vts/functional/gnss_hal_test.h | 24 +- .../vts/functional/gnss_hal_test_cases.cpp | 363 +++++++++++++++++- 7 files changed, 427 insertions(+), 9 deletions(-) diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp index 381ac1d3af..f3b376e6bd 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test.cpp @@ -16,10 +16,16 @@ #define LOG_TAG "GnssHalTest" +#include +#include + #include #include #include "Utils.h" +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; + using ::android::hardware::gnss::common::Utils; // Implementations for the main test class for GNSS HAL @@ -149,6 +155,28 @@ void GnssHalTest::StartAndCheckLocations(int count) { } } +bool GnssHalTest::IsGnssHalVersion_1_1() const { + using ::android::hidl::manager::V1_2::IServiceManager; + sp manager = ::android::hardware::defaultServiceManager1_2(); + + bool hasGnssHalVersion_1_1 = false; + manager->listManifestByInterface( + "android.hardware.gnss@1.1::IGnss", + [&hasGnssHalVersion_1_1](const hidl_vec& registered) { + ASSERT_EQ(1, registered.size()); + hasGnssHalVersion_1_1 = true; + }); + + bool hasGnssHalVersion_2_0 = false; + manager->listManifestByInterface( + "android.hardware.gnss@2.0::IGnss", + [&hasGnssHalVersion_2_0](const hidl_vec& registered) { + hasGnssHalVersion_2_0 = registered.size() != 0; + }); + + return hasGnssHalVersion_1_1 && !hasGnssHalVersion_2_0; +} + void GnssHalTest::notify() { std::unique_lock lock(mtx_); notify_count_++; diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h index 64478b5b1c..84a9f846fc 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test.h +++ b/gnss/1.1/vts/functional/gnss_hal_test.h @@ -145,6 +145,12 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ void SetPositionMode(const int min_interval_msec, const bool low_power_mode); + /* + * IsGnssHalVersion_1_1: + * returns true if the GNSS HAL version is exactly 1.1. + */ + bool IsGnssHalVersion_1_1() const; + sp gnss_hal_; // GNSS HAL to call into sp gnss_cb_; // Primary callback interface diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index 4016a5ab70..6106a678ff 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -209,6 +209,11 @@ IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource( * formerly strongest satellite */ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { + if (!IsGnssHalVersion_1_1()) { + ALOGI("Test BlacklistIndividualSatellites skipped. GNSS HAL version is greater than 1.1."); + return; + } + const int kLocationsToAwait = 3; const int kRetriesToUnBlacklist = 10; @@ -330,6 +335,11 @@ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { * 4a & b) Clean up by turning off location, and send in empty blacklist. */ TEST_F(GnssHalTest, BlacklistConstellation) { + if (!IsGnssHalVersion_1_1()) { + ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 1.1."); + return; + } + const int kLocationsToAwait = 3; StartAndCheckLocations(kLocationsToAwait); diff --git a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp index a8e40ba250..ae36c50689 100644 --- a/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp +++ b/gnss/2.0/vts/functional/VtsHalGnssV2_0TargetTest.cpp @@ -23,7 +23,6 @@ int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(GnssHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); GnssHidlEnvironment::Instance()->init(&argc, argv); - // TODO (b/122463165): Expand coverage to include 1.1 and 1.0 VTS tests. int status = RUN_ALL_TESTS(); ALOGI("Test result = %d", status); return status; diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp index a9f858cc9d..14ae43ce26 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp @@ -152,7 +152,7 @@ GnssHalTest::GnssCallback::GnssCallback() name_cbq_("name"), capabilities_cbq_("capabilities"), location_cbq_("location"), - sv_info_cbq_("sv_info") {} + sv_info_list_cbq_("sv_info") {} Return GnssHalTest::GnssCallback::gnssSetSystemInfoCb( const IGnssCallback_1_0::GnssSystemInfo& info) { @@ -204,7 +204,7 @@ Return GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0:: Return GnssHalTest::GnssCallback::gnssSvStatusCb_2_0( const hidl_vec& svInfoList) { ALOGI("gnssSvStatusCb_2_0. Size = %d", (int)svInfoList.size()); - sv_info_cbq_.store(svInfoList); + sv_info_list_cbq_.store(svInfoList); return Void(); } diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h index 05e37d33f7..90a7866082 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test.h +++ b/gnss/2.0/vts/functional/gnss_hal_test.h @@ -23,6 +23,7 @@ #include #include +#include #include using android::hardware::hidl_vec; @@ -85,6 +86,14 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { */ bool retrieve(T& event, int timeout_seconds); + /* + * Removes parameter count number of callack events at the front of the queue, stores + * them in event_list parameter and returns the number of events retrieved. Waits up to + * timeout_seconds to retrieve each event. If timeout occurs, it returns the number of + * items retrieved which will be less than count. + */ + int retrieve(list& event_list, int count, int timeout_seconds); + /* Returns the number of events pending to be retrieved from the callback event queue. */ int size() const; @@ -117,7 +126,7 @@ class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase { CallbackQueue name_cbq_; CallbackQueue capabilities_cbq_; CallbackQueue location_cbq_; - CallbackQueue> sv_info_cbq_; + CallbackQueue> sv_info_list_cbq_; GnssCallback(); virtual ~GnssCallback() = default; @@ -264,6 +273,19 @@ bool GnssHalTest::CallbackQueue::retrieve(T& event, int timeout_seconds) { return true; } +template +int GnssHalTest::CallbackQueue::retrieve(list& event_list, int count, int timeout_seconds) { + for (int i = 0; i < count; ++i) { + T event; + if (!retrieve(event, timeout_seconds)) { + return i; + } + event_list.push_back(event); + } + + return count; +} + template int GnssHalTest::CallbackQueue::size() const { std::unique_lock lock(mtx_); 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 155afd614b..6e0887fd9e 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -23,7 +23,10 @@ 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; using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement; using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement; @@ -33,15 +36,12 @@ using IAGnssRil_1_0 = android::hardware::gnss::V1_0::IAGnssRil; using IAGnss_2_0 = android::hardware::gnss::V2_0::IAGnss; using IAGnss_1_0 = android::hardware::gnss::V1_0::IAGnss; using IAGnssCallback_2_0 = android::hardware::gnss::V2_0::IAGnssCallback; -using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching; -using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching; using android::hardware::gnss::common::Utils; using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections; using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections; using android::hardware::gnss::V1_0::IGnssNi; using android::hardware::gnss::V2_0::ElapsedRealtimeFlags; -using android::hardware::gnss::V2_0::GnssConstellationType; using android::hardware::gnss::V2_0::IGnssCallback; using android::hardware::gnss::visibility_control::V1_0::IGnssVisibilityControl; @@ -209,9 +209,9 @@ TEST_F(GnssHalTest, TestGnssMeasurementFields) { // Verify ConstellationType is valid. ASSERT_TRUE(static_cast(measurement.constellation) >= - static_cast(GnssConstellationType::UNKNOWN) && + static_cast(GnssConstellationType_2_0::UNKNOWN) && static_cast(measurement.constellation) <= - static_cast(GnssConstellationType::IRNSS)); + static_cast(GnssConstellationType_2_0::IRNSS)); // Verify State is valid. ASSERT_TRUE( @@ -414,3 +414,356 @@ TEST_F(GnssHalTest, TestGnssBatchingExtension) { auto gnssBatching_2_0 = gnss_hal_->getExtensionGnssBatching_2_0(); ASSERT_TRUE(gnssBatching_2_0.isOk()); } + +/* + * 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 + * + * returns the strongest source, + * or a source with constellation == UNKNOWN if none are found sufficient times + */ +IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource( + const list>& sv_info_lists, + const int min_observations) { + struct ComparableBlacklistedSource { + IGnssConfiguration_1_1::BlacklistedSource id; + + ComparableBlacklistedSource() { + id.constellation = GnssConstellationType_1_0::UNKNOWN; + id.svid = 0; + } + + bool operator<(const ComparableBlacklistedSource& compare) const { + return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) && + (id.constellation < compare.id.constellation))); + } + }; + + struct SignalCounts { + int observations; + float max_cn0_dbhz; + }; + + std::map mapSignals; + + for (const auto& sv_info_list : sv_info_lists) { + 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::IRNSS) && + (sv_info.constellation != GnssConstellationType_2_0::GPS)) { + ComparableBlacklistedSource source; + source.id.svid = sv_info.v1_0.svid; + source.id.constellation = MapConstellationType(sv_info.constellation); + + const auto& itSignal = mapSignals.find(source); + if (itSignal == mapSignals.end()) { + SignalCounts counts; + counts.observations = 1; + counts.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz; + mapSignals.insert( + std::pair(source, counts)); + } else { + itSignal->second.observations++; + if (itSignal->second.max_cn0_dbhz < sv_info.v1_0.cN0Dbhz) { + itSignal->second.max_cn0_dbhz = sv_info.v1_0.cN0Dbhz; + } + } + } + } + } + + float max_cn0_dbhz_with_sufficient_count = 0.; + int total_observation_count = 0; + int blacklisted_source_count_observation = 0; + + ComparableBlacklistedSource source_to_blacklist; // initializes to zero = UNKNOWN constellation + for (auto const& pairSignal : mapSignals) { + total_observation_count += pairSignal.second.observations; + if ((pairSignal.second.observations >= min_observations) && + (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) { + source_to_blacklist = pairSignal.first; + blacklisted_source_count_observation = pairSignal.second.observations; + max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz; + } + } + ALOGD("Among %d observations, chose svid %d, constellation %d, " + "with %d observations at %.1f max CNo", + total_observation_count, source_to_blacklist.id.svid, + (int)source_to_blacklist.id.constellation, blacklisted_source_count_observation, + max_cn0_dbhz_with_sufficient_count); + + return source_to_blacklist.id; +} + +/* + * BlacklistIndividualSatellites: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for common satellites (strongest and one other.) + * 2a & b) Turns off location, and blacklists common satellites. + * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does not use those satellites. + * 4a & b) Turns off location, and send in empty blacklist. + * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus does re-use at least the previously strongest satellite + * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the + * formerly strongest satellite + */ +TEST_F(GnssHalTest, BlacklistIndividualSatellites) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + return; + } + + const int kLocationsToAwait = 3; + const int kRetriesToUnBlacklist = 10; + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + 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); + + /* + * Identify strongest SV seen at least kLocationsToAwait -1 times + * Why -1? To avoid test flakiness in case of (plausible) slight flakiness in strongest signal + * observability (one epoch RF null) + */ + + const int kGnssSvStatusTimeout = 2; + list> sv_info_lists; + int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_lists, sv_info_list_cbq_size, + kGnssSvStatusTimeout); + ASSERT_EQ(count, sv_info_list_cbq_size); + + IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist = + FindStrongFrequentNonGpsSource(sv_info_lists, kLocationsToAwait - 1); + + if (source_to_blacklist.constellation == GnssConstellationType_1_0::UNKNOWN) { + // Cannot find a non-GPS satellite. Let the test pass. + return; + } + + // Stop locations, blacklist the common SV + StopAndClearLocations(); + + auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1(); + ASSERT_TRUE(gnss_configuration_hal_return.isOk()); + sp gnss_configuration_hal = gnss_configuration_hal_return; + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(1); + sources[0] = source_to_blacklist; + + auto result = gnss_configuration_hal->setBlacklist(sources); + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + // retry and ensure satellite not used + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + 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); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec 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); + 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)); + } + } + + // clear blacklist and restart - this time updating the blacklist while location is still on + sources.resize(0); + + result = gnss_configuration_hal->setBlacklist(sources); + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + bool strongest_sv_is_reobserved = false; + // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies + int unblacklist_loops_remaining = kRetriesToUnBlacklist; + while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) { + StopAndClearLocations(); + gnss_cb_->sv_info_list_cbq_.reset(); + + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToAwait); + + // early exit loop if test is being run with insufficient signal + location_called_count = gnss_cb_->location_cbq_.calledCount(); + if (location_called_count == 0) { + ALOGE("0 Gnss locations received - ensure sufficient signal and retry"); + } + ASSERT_TRUE(location_called_count > 0); + + // Tolerate 1 less sv status to handle edge cases in reporting. + sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size(); + EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait); + ALOGD("Clear blacklist, observed %d GnssSvStatus, while awaiting %d Locations" + ", tries remaining %d", + sv_info_list_cbq_size, kLocationsToAwait, unblacklist_loops_remaining); + + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec 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); + 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)) { + strongest_sv_is_reobserved = true; + break; + } + } + if (strongest_sv_is_reobserved) break; + } + } + EXPECT_TRUE(strongest_sv_is_reobserved); + StopAndClearLocations(); +} + +/* + * BlacklistConstellation: + * + * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding + * GnssStatus for any non-GPS constellations. + * 2a & b) Turns off location, and blacklist first non-GPS constellations. + * 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_F(GnssHalTest, BlacklistConstellation) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + return; + } + + 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 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 + + auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1(); + ASSERT_TRUE(gnss_configuration_hal_return.isOk()); + sp gnss_configuration_hal = gnss_configuration_hal_return; + ASSERT_NE(gnss_configuration_hal, nullptr); + + hidl_vec sources; + sources.resize(1); + sources[0] = source_to_blacklist; + + auto result = gnss_configuration_hal->setBlacklist(sources); + ASSERT_TRUE(result.isOk()); + EXPECT_TRUE(result); + + // 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. + 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); + for (int i = 0; i < sv_info_list_cbq_size; ++i) { + hidl_vec 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); + 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); +} \ No newline at end of file From 02376b9e1117cda33b7c383c98dca260f9f9365f Mon Sep 17 00:00:00 2001 From: Anil Admal Date: Mon, 15 Jul 2019 18:52:00 -0700 Subject: [PATCH 35/35] Add GetLocationLowPower VTS 2.0 test - Run test only if LOW_POWER_MODE capability is supported. - Modify the corresponding VTS 1.1 test to run only if the GNSS HAL version is 1.1. Fixes: 127434062 Test: atest VtsHalGnssV2_0Target Change-Id: Icbd18d80468e9e5a542f2eace5bfbe45af08ca47 Merged-In: Icbd18d80468e9e5a542f2eace5bfbe45af08ca47 (cherry picked from commit 03bc98e028d3ebe4ab2d657deb0cb24ed76e3e45) --- .../vts/functional/gnss_hal_test_cases.cpp | 5 ++ .../vts/functional/gnss_hal_test_cases.cpp | 69 ++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index 6106a678ff..ee236ba5d1 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp @@ -66,6 +66,11 @@ TEST_F(GnssHalTest, TestGnssMeasurementCallback) { * each received location. */ TEST_F(GnssHalTest, GetLocationLowPower) { + if (!IsGnssHalVersion_1_1()) { + ALOGI("Test GetLocationLowPower skipped. GNSS HAL version is greater than 1.1."); + return; + } + const int kMinIntervalMsec = 5000; const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2; const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2; 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 6e0887fd9e..e2fe3f96a7 100644 --- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp @@ -415,6 +415,70 @@ TEST_F(GnssHalTest, TestGnssBatchingExtension) { ASSERT_TRUE(gnssBatching_2_0.isOk()); } +/* + * GetLocationLowPower: + * Turns on location, waits for at least 5 locations allowing max of LOCATION_TIMEOUT_SUBSEQUENT_SEC + * between one location and the next. Also ensure that MIN_INTERVAL_MSEC is respected by waiting + * NO_LOCATION_PERIOD_SEC and verfiy that no location is received. Also perform validity checks on + * each received location. + */ +TEST_F(GnssHalTest, GetLocationLowPower) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::LOW_POWER_MODE)) { + ALOGI("Test GetLocationLowPower skipped. LOW_POWER_MODE capability not supported."); + return; + } + + const int kMinIntervalMsec = 5000; + const int kLocationTimeoutSubsequentSec = (kMinIntervalMsec / 1000) * 2; + const int kNoLocationPeriodSec = (kMinIntervalMsec / 1000) / 2; + const int kLocationsToCheck = 5; + const bool kLowPowerMode = true; + + // Warmup period - VTS doesn't have AGPS access via GnssLocationProvider + gnss_cb_->location_cbq_.reset(); + StartAndCheckLocations(kLocationsToCheck); + StopAndClearLocations(); + gnss_cb_->location_cbq_.reset(); + + // Start of Low Power Mode test + SetPositionMode(kMinIntervalMsec, kLowPowerMode); + + // Don't expect true - as without AGPS access + if (!StartAndCheckFirstLocation()) { + ALOGW("GetLocationLowPower test - no first low power location received."); + } + + for (int i = 1; i < kLocationsToCheck; i++) { + // Verify that kMinIntervalMsec is respected by waiting kNoLocationPeriodSec and + // ensure that no location is received yet + + gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, kNoLocationPeriodSec); + const int locationCalledCount = gnss_cb_->location_cbq_.calledCount(); + + // Tolerate (ignore) one extra location right after the first one + // to handle startup edge case scheduling limitations in some implementations + if ((i == 1) && (locationCalledCount == 2)) { + CheckLocation(gnss_cb_->last_location_, true); + continue; // restart the quiet wait period after this too-fast location + } + EXPECT_LE(locationCalledCount, i); + if (locationCalledCount != i) { + ALOGW("GetLocationLowPower test - not enough locations received. %d vs. %d expected ", + locationCalledCount, i); + } + + if (!gnss_cb_->location_cbq_.retrieve( + gnss_cb_->last_location_, + kLocationTimeoutSubsequentSec - kNoLocationPeriodSec)) { + ALOGW("GetLocationLowPower test - timeout awaiting location %d", i); + } else { + CheckLocation(gnss_cb_->last_location_, true); + } + } + + StopAndClearLocations(); +} + /* * MapConstellationType: * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent @@ -537,6 +601,8 @@ IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource( */ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability" + " not supported."); return; } @@ -680,6 +746,7 @@ TEST_F(GnssHalTest, BlacklistIndividualSatellites) { */ TEST_F(GnssHalTest, BlacklistConstellation) { if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) { + ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported."); return; } @@ -766,4 +833,4 @@ TEST_F(GnssHalTest, BlacklistConstellation) { result = gnss_configuration_hal->setBlacklist(sources); ASSERT_TRUE(result.isOk()); EXPECT_TRUE(result); -} \ No newline at end of file +}