Add support to blacklist IRNSS in HAL 2.1
Test: atest VtsHalGnssV2_1TargetTest Bug: 135042665 Change-Id: I10a12f5171c640e400af4ee66ce9ab63cf6e94f2
This commit is contained in:
parent
dcd93513e6
commit
845f6d54e4
11 changed files with 679 additions and 3 deletions
|
@ -595,8 +595,9 @@ f18695dd36ee205640b8326a17453858a7b4596653aaa6ef0016b0aef1bd4dac android.hardwar
|
|||
4d85e814f94949dae4dc6cb82bbd7d6bb24ffafda6ddb2eac928d2a4fc2e21ce android.hardware.cas@1.2::types
|
||||
66931c2506fbb5af61f20138cb05e0a09e7bf67d6964c231d27c648933bb33ec android.hardware.drm@1.3::ICryptoFactory
|
||||
994d08ab27d613022c258a9ec48cece7adf2a305e92df5d76ef923e2c6665f64 android.hardware.drm@1.3::IDrmFactory
|
||||
1bd8028b974bf1d65cfa102196a2b008afc5d42fe73fed2cb94fa7533d07f581 android.hardware.gnss@2.1::IGnss
|
||||
3dacec7801968e1e4479724dc0180442d9e915466bff051f80996266b1a51c2c android.hardware.gnss@2.1::IGnss
|
||||
ba62e1e8993bfb9f27fa04816fa0f2241ae2d01edfa3d0c04182e2e5de80045c android.hardware.gnss@2.1::IGnssCallback
|
||||
ccdf3c0fb2c02a6d4dc57afb276c3497ae8172b80b00ebc0bf8a0238dd38b01d android.hardware.gnss@2.1::IGnssConfiguration
|
||||
5a125c49ca83629e22afc8c39e865509343bfa2c38f0baea9a186bbac103492d android.hardware.gnss@2.1::IGnssMeasurement
|
||||
0bfb291708dd4a7c6ec6b9883e2b8592357edde8d7e962ef83918e4a2154ce69 android.hardware.gnss@2.1::IGnssMeasurementCallback
|
||||
ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
|
||||
|
|
|
@ -11,6 +11,7 @@ hidl_interface {
|
|||
"IGnssCallback.hal",
|
||||
"IGnssMeasurement.hal",
|
||||
"IGnssMeasurementCallback.hal",
|
||||
"IGnssConfiguration.hal",
|
||||
],
|
||||
interfaces: [
|
||||
"android.hardware.gnss.measurement_corrections@1.0",
|
||||
|
|
|
@ -20,6 +20,7 @@ import @2.0::IGnss;
|
|||
|
||||
import IGnssCallback;
|
||||
import IGnssMeasurement;
|
||||
import IGnssConfiguration;
|
||||
|
||||
/**
|
||||
* Represents the standard GNSS (Global Navigation Satellite System) interface.
|
||||
|
@ -50,4 +51,15 @@ interface IGnss extends @2.0::IGnss {
|
|||
* @return gnssMeasurementIface Handle to the IGnssMeasurement interface.
|
||||
*/
|
||||
getExtensionGnssMeasurement_2_1() generates (IGnssMeasurement gnssMeasurementIface);
|
||||
|
||||
/**
|
||||
* This method returns the IGnssConfiguration interface.
|
||||
*
|
||||
* At least one of getExtensionGnssConfiguration(), getExtensionGnssConfiguration_1_1(),
|
||||
* getExtensionGnssConfiguration_2_0(), and getExtensionGnssConfiguration_2_1() methods must
|
||||
* return a non-null handle, and the other methods must return nullptr.
|
||||
*
|
||||
* @return gnssConfigurationIface Handle to the IGnssConfiguration interface.
|
||||
*/
|
||||
getExtensionGnssConfiguration_2_1() generates (IGnssConfiguration gnssConfigurationIface);
|
||||
};
|
68
gnss/2.1/IGnssConfiguration.hal
Normal file
68
gnss/2.1/IGnssConfiguration.hal
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package android.hardware.gnss@2.1;
|
||||
|
||||
import @2.0::IGnssConfiguration;
|
||||
import @2.0::GnssConstellationType;
|
||||
|
||||
/**
|
||||
* Extended interface for GNSS Configuration support.
|
||||
*/
|
||||
interface IGnssConfiguration extends @2.0::IGnssConfiguration {
|
||||
/**
|
||||
* Represents a blacklisted source, updating the GnssConstellationType to 2.0, which supports
|
||||
* IRNSS.
|
||||
*/
|
||||
struct BlacklistedSource {
|
||||
/**
|
||||
* Defines the constellation of the given satellite(s).
|
||||
*/
|
||||
GnssConstellationType constellation;
|
||||
|
||||
/**
|
||||
* Satellite (space vehicle) ID number, as defined in GnssSvInfo::svid
|
||||
*
|
||||
* Or 0 to blacklist all svid's for the specified constellation
|
||||
*/
|
||||
int16_t svid;
|
||||
};
|
||||
|
||||
/**
|
||||
* Injects a vector of BlacklistedSource(s) which the HAL must not use to calculate the
|
||||
* GNSS location output.
|
||||
*
|
||||
* The superset of all satellite sources provided, including wildcards, in the latest call
|
||||
* to this method, is the set of satellites sources that must not be used in calculating
|
||||
* location.
|
||||
*
|
||||
* All measurements from the specified satellites, across frequency bands, are blacklisted
|
||||
* together.
|
||||
*
|
||||
* If this method is never called after the IGnssConfiguration.hal connection is made on boot,
|
||||
* or is called with an empty vector, then no satellites are to be blacklisted as a result of
|
||||
* this API.
|
||||
*
|
||||
* This blacklist must be considered as an additional source of which satellites
|
||||
* should not be trusted for location on top of existing sources of similar information
|
||||
* such as satellite broadcast health being unhealthy and measurement outlier removal.
|
||||
*
|
||||
* @param blacklist The BlacklistedSource(s) of satellites the HAL must not use.
|
||||
*
|
||||
* @return success Whether the HAL accepts and abides by the provided blacklist.
|
||||
*/
|
||||
setBlacklist_2_1(vec<BlacklistedSource> blacklist) generates (bool success);
|
||||
};
|
|
@ -23,6 +23,7 @@ cc_binary {
|
|||
srcs: [
|
||||
"Gnss.cpp",
|
||||
"GnssMeasurement.cpp",
|
||||
"GnssConfiguration.cpp",
|
||||
"service.cpp"
|
||||
],
|
||||
shared_libs: [
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace implementation {
|
|||
|
||||
sp<V2_1::IGnssCallback> Gnss::sGnssCallback_2_1 = nullptr;
|
||||
|
||||
Gnss::Gnss() : mMinIntervalMs(1000) {}
|
||||
Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
|
||||
|
||||
Gnss::~Gnss() {
|
||||
stop();
|
||||
|
@ -48,7 +48,7 @@ Return<bool> Gnss::start() {
|
|||
mIsActive = true;
|
||||
mThread = std::thread([this]() {
|
||||
while (mIsActive == true) {
|
||||
auto svStatus = Utils::getMockSvInfoListV2_1();
|
||||
auto svStatus = filterBlacklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1());
|
||||
this->reportSvStatus(svStatus);
|
||||
|
||||
const auto location = Utils::getMockLocationV2_0();
|
||||
|
@ -60,6 +60,16 @@ Return<bool> Gnss::start() {
|
|||
return true;
|
||||
}
|
||||
|
||||
hidl_vec<GnssSvInfo> Gnss::filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList) {
|
||||
for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) {
|
||||
if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) {
|
||||
gnssSvInfoList[i].v2_0.v1_0.svFlag &=
|
||||
~static_cast<uint8_t>(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX);
|
||||
}
|
||||
}
|
||||
return gnssSvInfoList;
|
||||
}
|
||||
|
||||
Return<bool> Gnss::stop() {
|
||||
ALOGD("stop");
|
||||
mIsActive = false;
|
||||
|
@ -270,6 +280,10 @@ Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
|
|||
return new GnssMeasurement();
|
||||
}
|
||||
|
||||
Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
|
||||
return mGnssConfiguration;
|
||||
}
|
||||
|
||||
void Gnss::reportSvStatus(const hidl_vec<GnssSvInfo>& svInfoList) const {
|
||||
std::unique_lock<std::mutex> lock(mMutex);
|
||||
if (sGnssCallback_2_1 == nullptr) {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include "GnssConfiguration.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
|
@ -87,6 +88,7 @@ struct Gnss : public IGnss {
|
|||
// Methods from V2_1::IGnss follow.
|
||||
Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
|
||||
Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
|
||||
Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
|
||||
|
||||
private:
|
||||
void reportLocation(const V2_0::GnssLocation&) const;
|
||||
|
@ -94,9 +96,11 @@ struct Gnss : public IGnss {
|
|||
|
||||
static sp<V2_1::IGnssCallback> sGnssCallback_2_1;
|
||||
std::atomic<long> mMinIntervalMs;
|
||||
sp<GnssConfiguration> mGnssConfiguration;
|
||||
std::atomic<bool> mIsActive;
|
||||
std::thread mThread;
|
||||
mutable std::mutex mMutex;
|
||||
hidl_vec<GnssSvInfo> filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList);
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
|
106
gnss/2.1/default/GnssConfiguration.cpp
Normal file
106
gnss/2.1/default/GnssConfiguration.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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 "GnssConfiguration"
|
||||
|
||||
#include "GnssConfiguration.h"
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace gnss {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
// Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
|
||||
Return<bool> GnssConfiguration::setSuplEs(bool enable) {
|
||||
ALOGD("setSuplEs enable: %d", enable);
|
||||
// Method deprecated in 2.0 and not expected to be called by the framework.
|
||||
return false;
|
||||
}
|
||||
|
||||
Return<bool> GnssConfiguration::setSuplVersion(uint32_t) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Return<bool> GnssConfiguration::setSuplMode(hidl_bitfield<SuplMode>) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Return<bool> GnssConfiguration::setGpsLock(hidl_bitfield<GpsLock> gpsLock) {
|
||||
ALOGD("setGpsLock gpsLock: %hhu", static_cast<GpsLock>(gpsLock));
|
||||
// Method deprecated in 2.0 and not expected to be called by the framework.
|
||||
return false;
|
||||
}
|
||||
|
||||
Return<bool> GnssConfiguration::setLppProfile(hidl_bitfield<LppProfile>) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Return<bool> GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol>) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Return<bool> GnssConfiguration::setEmergencySuplPdn(bool) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
|
||||
Return<bool> GnssConfiguration::setBlacklist(
|
||||
const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>&) {
|
||||
// TODO (b/122463906): Reuse 1.1 implementation.
|
||||
return bool{};
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
|
||||
Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
|
||||
ALOGD("setEsExtensionSec emergencyExtensionSeconds: %d", emergencyExtensionSeconds);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
|
||||
Return<bool> GnssConfiguration::setBlacklist_2_1(
|
||||
const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& sourceList) {
|
||||
std::unique_lock<std::recursive_mutex> lock(mMutex);
|
||||
mBlacklistedConstellationSet.clear();
|
||||
mBlacklistedSourceSet.clear();
|
||||
for (auto source : sourceList) {
|
||||
if (source.svid == 0) {
|
||||
// Wildcard blacklist, i.e., blacklist entire constellation.
|
||||
mBlacklistedConstellationSet.insert(source.constellation);
|
||||
} else {
|
||||
mBlacklistedSourceSet.insert(source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Return<bool> GnssConfiguration::isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const {
|
||||
std::unique_lock<std::recursive_mutex> lock(mMutex);
|
||||
if (mBlacklistedConstellationSet.find(gnssSvInfo.v2_0.constellation) !=
|
||||
mBlacklistedConstellationSet.end()) {
|
||||
return true;
|
||||
}
|
||||
BlacklistedSourceV2_1 source = {.constellation = gnssSvInfo.v2_0.constellation,
|
||||
.svid = gnssSvInfo.v2_0.v1_0.svid};
|
||||
return (mBlacklistedSourceSet.find(source) != mBlacklistedSourceSet.end());
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace gnss
|
||||
} // namespace hardware
|
||||
} // namespace android
|
101
gnss/2.1/default/GnssConfiguration.h
Normal file
101
gnss/2.1/default/GnssConfiguration.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
|
||||
#define ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
|
||||
|
||||
#include <android/hardware/gnss/2.1/IGnssCallback.h>
|
||||
#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
|
||||
#include <hidl/MQDescriptor.h>
|
||||
#include <hidl/Status.h>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace gnss {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::sp;
|
||||
using ::android::hardware::hidl_array;
|
||||
using ::android::hardware::hidl_memory;
|
||||
using ::android::hardware::hidl_string;
|
||||
using ::android::hardware::hidl_vec;
|
||||
using ::android::hardware::Return;
|
||||
using ::android::hardware::Void;
|
||||
|
||||
using BlacklistedSourceV2_1 =
|
||||
::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource;
|
||||
using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType;
|
||||
using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo;
|
||||
|
||||
struct BlacklistedSourceHashV2_1 {
|
||||
inline int operator()(const BlacklistedSourceV2_1& source) const {
|
||||
return int(source.constellation) * 1000 + int(source.svid);
|
||||
}
|
||||
};
|
||||
|
||||
struct BlacklistedSourceEqualV2_1 {
|
||||
inline bool operator()(const BlacklistedSourceV2_1& s1, const BlacklistedSourceV2_1& s2) const {
|
||||
return (s1.constellation == s2.constellation) && (s1.svid == s2.svid);
|
||||
}
|
||||
};
|
||||
|
||||
using BlacklistedSourceSetV2_1 =
|
||||
std::unordered_set<BlacklistedSourceV2_1, BlacklistedSourceHashV2_1,
|
||||
BlacklistedSourceEqualV2_1>;
|
||||
using BlacklistedConstellationSetV2_1 = std::unordered_set<GnssConstellationTypeV2_0>;
|
||||
|
||||
struct GnssConfiguration : public IGnssConfiguration {
|
||||
// Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
|
||||
Return<bool> setSuplEs(bool enabled) override;
|
||||
Return<bool> setSuplVersion(uint32_t version) override;
|
||||
Return<bool> setSuplMode(hidl_bitfield<SuplMode> mode) override;
|
||||
Return<bool> setGpsLock(hidl_bitfield<GpsLock> lock) override;
|
||||
Return<bool> setLppProfile(hidl_bitfield<LppProfile> lppProfile) override;
|
||||
Return<bool> setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol> protocol) override;
|
||||
Return<bool> setEmergencySuplPdn(bool enable) override;
|
||||
|
||||
// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
|
||||
Return<bool> setBlacklist(
|
||||
const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
|
||||
|
||||
std::recursive_mutex& getMutex() const;
|
||||
|
||||
// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
|
||||
Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
|
||||
|
||||
// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
|
||||
Return<bool> setBlacklist_2_1(
|
||||
const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
|
||||
|
||||
Return<bool> isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const;
|
||||
|
||||
private:
|
||||
mutable std::recursive_mutex mMutex;
|
||||
|
||||
BlacklistedSourceSetV2_1 mBlacklistedSourceSet;
|
||||
BlacklistedConstellationSetV2_1 mBlacklistedConstellationSet;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace gnss
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
|
|
@ -30,6 +30,13 @@ using IGnssMeasurement_2_1 = android::hardware::gnss::V2_1::IGnssMeasurement;
|
|||
using IGnssMeasurement_2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
|
||||
using IGnssMeasurement_1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
|
||||
using IGnssMeasurement_1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
|
||||
using IGnssConfiguration_2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
|
||||
using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
|
||||
using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
|
||||
using IGnssConfiguration_1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
|
||||
|
||||
using android::hardware::gnss::V2_0::GnssConstellationType;
|
||||
using android::hardware::gnss::V2_1::IGnssConfiguration;
|
||||
|
||||
/*
|
||||
* SetupTeardownCreateCleanup:
|
||||
|
@ -60,6 +67,27 @@ TEST_P(GnssHalTest, TestGnssMeasurementExtension) {
|
|||
ASSERT_TRUE(numNonNull >= 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* TestGnssConfigurationExtension:
|
||||
* Gets the GnssConfigurationExtension and verifies that it returns an actual extension.
|
||||
*/
|
||||
TEST_P(GnssHalTest, TestGnssConfigurationExtension) {
|
||||
auto gnssConfiguration_2_1 = gnss_hal_->getExtensionGnssConfiguration_2_1();
|
||||
auto gnssConfiguration_2_0 = gnss_hal_->getExtensionGnssConfiguration_2_0();
|
||||
auto gnssConfiguration_1_1 = gnss_hal_->getExtensionGnssConfiguration_1_1();
|
||||
auto gnssConfiguration_1_0 = gnss_hal_->getExtensionGnssConfiguration();
|
||||
ASSERT_TRUE(gnssConfiguration_2_1.isOk() && gnssConfiguration_2_0.isOk() &&
|
||||
gnssConfiguration_1_1.isOk() && gnssConfiguration_1_0.isOk());
|
||||
sp<IGnssConfiguration_2_1> iGnssConfig_2_1 = gnssConfiguration_2_1;
|
||||
sp<IGnssConfiguration_2_0> iGnssConfig_2_0 = gnssConfiguration_2_0;
|
||||
sp<IGnssConfiguration_1_1> iGnssConfig_1_1 = gnssConfiguration_1_1;
|
||||
sp<IGnssConfiguration_1_0> iGnssConfig_1_0 = gnssConfiguration_1_0;
|
||||
// At least one interface is non-null.
|
||||
int numNonNull = (int)(iGnssConfig_2_1 != nullptr) + (int)(iGnssConfig_2_0 != nullptr) +
|
||||
(int)(iGnssConfig_1_1 != nullptr) + (int)(iGnssConfig_1_0 != nullptr);
|
||||
ASSERT_TRUE(numNonNull >= 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* TestGnssMeasurementFields:
|
||||
* Sets a GnssMeasurementCallback, waits for a measurement, and verifies
|
||||
|
@ -126,3 +154,338 @@ TEST_P(GnssHalTest, TestGnssSvInfoFields) {
|
|||
ASSERT_TRUE(nonZeroCn0Found);
|
||||
StopAndClearLocations();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
* TODO(skz): create a template for this to reduce code duplication of v2.1 and v2.0 since both
|
||||
* are using vectors.
|
||||
*/
|
||||
IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource(
|
||||
const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
|
||||
const int min_observations) {
|
||||
struct ComparableBlacklistedSource {
|
||||
IGnssConfiguration::BlacklistedSource id;
|
||||
|
||||
ComparableBlacklistedSource() {
|
||||
id.constellation = GnssConstellationType::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<ComparableBlacklistedSource, SignalCounts> mapSignals;
|
||||
|
||||
for (const auto& sv_info_vec : sv_info_list) {
|
||||
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
|
||||
const auto& gnss_sv = sv_info_vec[iSv];
|
||||
if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
|
||||
(gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
|
||||
ComparableBlacklistedSource source;
|
||||
source.id.svid = gnss_sv.v2_0.v1_0.svid;
|
||||
source.id.constellation = gnss_sv.v2_0.constellation;
|
||||
|
||||
const auto& itSignal = mapSignals.find(source);
|
||||
if (itSignal == mapSignals.end()) {
|
||||
SignalCounts counts;
|
||||
counts.observations = 1;
|
||||
counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
|
||||
mapSignals.insert(
|
||||
std::pair<ComparableBlacklistedSource, SignalCounts>(source, counts));
|
||||
} else {
|
||||
itSignal->second.observations++;
|
||||
if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) {
|
||||
itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.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_P(GnssHalTest, BlacklistIndividualSatellites) {
|
||||
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 GnssSvInfo, 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 kGnssSvInfoListTimeout = 2;
|
||||
std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
|
||||
int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
|
||||
kGnssSvInfoListTimeout);
|
||||
|
||||
ASSERT_EQ(count, sv_info_list_cbq_size);
|
||||
|
||||
IGnssConfiguration::BlacklistedSource source_to_blacklist =
|
||||
FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
|
||||
|
||||
if (source_to_blacklist.constellation == GnssConstellationType::UNKNOWN) {
|
||||
// Cannot find a non-GPS satellite. Let the test pass.
|
||||
ALOGD("Cannot find a non-GPS satellite. Letting the test pass.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop locations, blacklist the common SV
|
||||
StopAndClearLocations();
|
||||
|
||||
auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_2_1();
|
||||
ASSERT_TRUE(gnss_configuration_hal_return.isOk());
|
||||
sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
|
||||
ASSERT_NE(gnss_configuration_hal, nullptr);
|
||||
|
||||
hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
|
||||
sources.resize(1);
|
||||
sources[0] = source_to_blacklist;
|
||||
|
||||
auto result = gnss_configuration_hal->setBlacklist_2_1(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 GnssSvInfo, 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<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
|
||||
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
|
||||
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
|
||||
const auto& gnss_sv = sv_info_vec[iSv];
|
||||
EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blacklist.svid) &&
|
||||
(gnss_sv.v2_0.constellation == source_to_blacklist.constellation) &&
|
||||
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::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_2_1(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 GnssSvInfo, 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<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
|
||||
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
|
||||
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
|
||||
const auto& gnss_sv = sv_info_vec[iSv];
|
||||
if ((gnss_sv.v2_0.v1_0.svid == source_to_blacklist.svid) &&
|
||||
(gnss_sv.v2_0.constellation == source_to_blacklist.constellation) &&
|
||||
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::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_P(GnssHalTest, BlacklistConstellation) {
|
||||
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 GnssSvInfo, while awaiting %d Locations (%d received)",
|
||||
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
|
||||
|
||||
// Find first non-GPS constellation to blacklist
|
||||
const int kGnssSvInfoListTimeout = 2;
|
||||
GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
|
||||
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
|
||||
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
|
||||
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
|
||||
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
|
||||
const auto& gnss_sv = sv_info_vec[iSv];
|
||||
if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
|
||||
(gnss_sv.v2_0.constellation != GnssConstellationType::UNKNOWN) &&
|
||||
(gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
|
||||
// found a non-GPS constellation
|
||||
constellation_to_blacklist = gnss_sv.v2_0.constellation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Turns off location
|
||||
StopAndClearLocations();
|
||||
|
||||
if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
|
||||
ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
|
||||
// Proceed functionally to blacklist something.
|
||||
constellation_to_blacklist = GnssConstellationType::GLONASS;
|
||||
}
|
||||
IGnssConfiguration::BlacklistedSource source_to_blacklist_1;
|
||||
source_to_blacklist_1.constellation = constellation_to_blacklist;
|
||||
source_to_blacklist_1.svid = 0; // documented wildcard for all satellites in this constellation
|
||||
|
||||
// IRNSS was added in 2.0. Always attempt to blacklist IRNSS to verify that the new enum is
|
||||
// supported.
|
||||
IGnssConfiguration::BlacklistedSource source_to_blacklist_2;
|
||||
source_to_blacklist_2.constellation = GnssConstellationType::IRNSS;
|
||||
source_to_blacklist_2.svid = 0; // documented wildcard for all satellites in this constellation
|
||||
|
||||
auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_2_1();
|
||||
ASSERT_TRUE(gnss_configuration_hal_return.isOk());
|
||||
sp<IGnssConfiguration> gnss_configuration_hal = gnss_configuration_hal_return;
|
||||
ASSERT_NE(gnss_configuration_hal, nullptr);
|
||||
|
||||
hidl_vec<IGnssConfiguration::BlacklistedSource> sources;
|
||||
sources.resize(2);
|
||||
sources[0] = source_to_blacklist_1;
|
||||
sources[1] = source_to_blacklist_2;
|
||||
|
||||
auto result = gnss_configuration_hal->setBlacklist_2_1(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 GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
|
||||
kLocationsToAwait);
|
||||
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
|
||||
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
|
||||
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
|
||||
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
|
||||
const auto& gnss_sv = sv_info_vec[iSv];
|
||||
EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_1.constellation) &&
|
||||
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
|
||||
EXPECT_FALSE((gnss_sv.v2_0.constellation == source_to_blacklist_2.constellation) &&
|
||||
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
StopAndClearLocations();
|
||||
sources.resize(0);
|
||||
result = gnss_configuration_hal->setBlacklist_2_1(sources);
|
||||
ASSERT_TRUE(result.isOk());
|
||||
EXPECT_TRUE(result);
|
||||
}
|
|
@ -175,6 +175,11 @@ hidl_vec<GnssSvInfoV2_1> Utils::getMockSvInfoListV2_1() {
|
|||
25.0, 66.0, 247.0),
|
||||
V2_0::GnssConstellationType::GLONASS),
|
||||
20.0),
|
||||
getMockSvInfoV2_1(
|
||||
getMockSvInfoV2_0(getMockSvInfoV1_0(3, V1_0::GnssConstellationType::UNKNOWN,
|
||||
22.0, 35.0, 112.0),
|
||||
V2_0::GnssConstellationType::IRNSS),
|
||||
19.7),
|
||||
};
|
||||
return gnssSvInfoList;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue