blob: f184f8132dc001c1efd1d1901458bc789413e4d1 [file] [log] [blame]
Yu-Han Yang1e1a6762020-09-30 17:01:53 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080017#define LOG_TAG "GnssHalTest"
18
Yu-Han Yang1e1a6762020-09-30 17:01:53 -070019#include "gnss_hal_test.h"
20#include <hidl/ServiceManagement.h>
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080021#include "Utils.h"
Yu-Han Yang1e1a6762020-09-30 17:01:53 -070022
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080023using android::hardware::gnss::GnssConstellationType;
24using android::hardware::gnss::GnssLocation;
25using android::hardware::gnss::IGnss;
26using android::hardware::gnss::IGnssCallback;
27using android::hardware::gnss::common::Utils;
28using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
Yu-Han Yang1e1a6762020-09-30 17:01:53 -070029
30void GnssHalTest::SetUp() {
31 // Get AIDL handle
32 aidl_gnss_hal_ = android::waitForDeclaredService<IGnssAidl>(String16(GetParam().c_str()));
33 ASSERT_NE(aidl_gnss_hal_, nullptr);
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080034 ALOGD("AIDL Interface Version = %d", aidl_gnss_hal_->getInterfaceVersion());
Yu-Han Yang1e1a6762020-09-30 17:01:53 -070035
Yu-Han Yang4165ed12022-02-09 14:47:50 -080036 if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080037 const auto& hidlInstanceNames = android::hardware::getAllHalInstanceNames(
38 android::hardware::gnss::V2_1::IGnss::descriptor);
39 gnss_hal_ = IGnss_V2_1::getService(hidlInstanceNames[0]);
40 ASSERT_NE(gnss_hal_, nullptr);
41 }
Yu-Han Yang1e1a6762020-09-30 17:01:53 -070042
43 SetUpGnssCallback();
44}
45
46void GnssHalTest::SetUpGnssCallback() {
47 aidl_gnss_cb_ = new GnssCallbackAidl();
48 ASSERT_NE(aidl_gnss_cb_, nullptr);
49
50 auto status = aidl_gnss_hal_->setCallback(aidl_gnss_cb_);
51 if (!status.isOk()) {
52 ALOGE("Failed to setCallback");
53 }
Yu-Han Yang1e1a6762020-09-30 17:01:53 -070054 ASSERT_TRUE(status.isOk());
55
56 /*
57 * Capabilities callback should trigger.
58 */
59 EXPECT_TRUE(aidl_gnss_cb_->capabilities_cbq_.retrieve(aidl_gnss_cb_->last_capabilities_,
60 TIMEOUT_SEC));
Yu-Han Yang1e1a6762020-09-30 17:01:53 -070061 EXPECT_EQ(aidl_gnss_cb_->capabilities_cbq_.calledCount(), 1);
62
Yu-Han Yang4165ed12022-02-09 14:47:50 -080063 if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080064 // Invoke the super method.
65 GnssHalTestTemplate<IGnss_V2_1>::SetUpGnssCallback();
Yu-Han Yang4165ed12022-02-09 14:47:50 -080066 } else {
67 /*
68 * SystemInfo callback should trigger
69 */
70 EXPECT_TRUE(aidl_gnss_cb_->info_cbq_.retrieve(aidl_gnss_cb_->last_info_, TIMEOUT_SEC));
71 EXPECT_EQ(aidl_gnss_cb_->info_cbq_.calledCount(), 1);
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080072 }
73}
74
75void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) {
76 Utils::checkLocation(location, check_speed, /* check_more_accuracies= */ true);
77}
78
79void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
Yu-Han Yang4165ed12022-02-09 14:47:50 -080080 if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080081 // Invoke the super method.
82 return GnssHalTestTemplate<IGnss_V2_1>::SetPositionMode(min_interval_msec, low_power_mode);
83 }
84
85 const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider)
86 const int kPreferredTimeMsec = 0; // Ideally immediate
87
Yu-Han Yang75934f72022-01-24 15:35:25 -080088 IGnss::PositionModeOptions options;
89 options.mode = IGnss::GnssPositionMode::MS_BASED;
90 options.recurrence = IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC;
91 options.minIntervalMs = min_interval_msec;
92 options.preferredAccuracyMeters = kPreferredAccuracy;
93 options.preferredTimeMs = kPreferredTimeMsec;
94 options.lowPowerMode = low_power_mode;
95 auto status = aidl_gnss_hal_->setPositionMode(options);
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -080096
97 ASSERT_TRUE(status.isOk());
98}
99
100bool GnssHalTest::StartAndCheckFirstLocation(const int min_interval_msec,
101 const bool low_power_mode) {
Yu-Han Yang4165ed12022-02-09 14:47:50 -0800102 if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800103 // Invoke the super method.
104 return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckFirstLocation(min_interval_msec,
105 low_power_mode);
106 }
107
108 SetPositionMode(min_interval_msec, low_power_mode);
Yu-Han Yang69f0f8b2022-01-21 13:03:32 -0800109 auto status = aidl_gnss_hal_->start();
110 EXPECT_TRUE(status.isOk());
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800111
Yu-Han Yang69f0f8b2022-01-21 13:03:32 -0800112 status = aidl_gnss_hal_->startSvStatus();
113 EXPECT_TRUE(status.isOk());
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800114
115 /*
116 * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
117 * so allow time to demodulate ephemeris over the air.
118 */
119 const int kFirstGnssLocationTimeoutSeconds = 75;
120
121 EXPECT_TRUE(aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_,
122 kFirstGnssLocationTimeoutSeconds));
123 int locationCalledCount = aidl_gnss_cb_->location_cbq_.calledCount();
124 EXPECT_EQ(locationCalledCount, 1);
125
126 if (locationCalledCount > 0) {
127 // don't require speed on first fix
128 CheckLocation(aidl_gnss_cb_->last_location_, false);
129 return true;
130 }
131 return false;
132}
133
134void GnssHalTest::StopAndClearLocations() {
135 ALOGD("StopAndClearLocations");
Yu-Han Yang4165ed12022-02-09 14:47:50 -0800136 if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800137 // Invoke the super method.
138 return GnssHalTestTemplate<IGnss_V2_1>::StopAndClearLocations();
139 }
Yu-Han Yang69f0f8b2022-01-21 13:03:32 -0800140 auto status = aidl_gnss_hal_->stopSvStatus();
141 EXPECT_TRUE(status.isOk());
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800142
Yu-Han Yang69f0f8b2022-01-21 13:03:32 -0800143 status = aidl_gnss_hal_->stop();
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800144 EXPECT_TRUE(status.isOk());
145
146 /*
147 * Clear notify/waiting counter, allowing up till the timeout after
148 * the last reply for final startup messages to arrive (esp. system
149 * info.)
150 */
151 while (aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_, TIMEOUT_SEC)) {
152 }
153 aidl_gnss_cb_->location_cbq_.reset();
154}
155
156void GnssHalTest::StartAndCheckLocations(int count) {
Yu-Han Yang4165ed12022-02-09 14:47:50 -0800157 if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800158 // Invoke the super method.
159 return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckLocations(count);
160 }
161 const int kMinIntervalMsec = 500;
162 const int kLocationTimeoutSubsequentSec = 2;
163 const bool kLowPowerMode = false;
164
165 EXPECT_TRUE(StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode));
166
167 for (int i = 1; i < count; i++) {
168 EXPECT_TRUE(aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_,
169 kLocationTimeoutSubsequentSec));
170 int locationCalledCount = aidl_gnss_cb_->location_cbq_.calledCount();
171 EXPECT_EQ(locationCalledCount, i + 1);
172 // Don't cause confusion by checking details if no location yet
173 if (locationCalledCount > 0) {
174 // Should be more than 1 location by now, but if not, still don't check first fix speed
175 CheckLocation(aidl_gnss_cb_->last_location_, locationCalledCount > 1);
176 }
177 }
178}
179
180std::list<std::vector<IGnssCallback::GnssSvInfo>> GnssHalTest::convertToAidl(
181 const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>>& sv_info_list) {
182 std::list<std::vector<IGnssCallback::GnssSvInfo>> aidl_sv_info_list;
183 for (const auto& sv_info_vec : sv_info_list) {
184 std::vector<IGnssCallback::GnssSvInfo> aidl_sv_info_vec;
185 for (const auto& sv_info : sv_info_vec) {
186 IGnssCallback::GnssSvInfo aidl_sv_info;
187 aidl_sv_info.svid = sv_info.v2_0.v1_0.svid;
188 aidl_sv_info.constellation =
189 static_cast<GnssConstellationType>(sv_info.v2_0.constellation);
190 aidl_sv_info.cN0Dbhz = sv_info.v2_0.v1_0.cN0Dbhz;
191 aidl_sv_info.basebandCN0DbHz = sv_info.basebandCN0DbHz;
192 aidl_sv_info.elevationDegrees = sv_info.v2_0.v1_0.elevationDegrees;
193 aidl_sv_info.azimuthDegrees = sv_info.v2_0.v1_0.azimuthDegrees;
194 aidl_sv_info.carrierFrequencyHz = (int64_t)sv_info.v2_0.v1_0.carrierFrequencyHz;
195 aidl_sv_info.svFlag = (int)sv_info.v2_0.v1_0.svFlag;
196 aidl_sv_info_vec.push_back(aidl_sv_info);
197 }
198 aidl_sv_info_list.push_back(aidl_sv_info_vec);
199 }
200 return aidl_sv_info_list;
201}
202
203/*
204 * FindStrongFrequentNonGpsSource:
205 *
206 * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
207 *
208 * returns the strongest source,
209 * or a source with constellation == UNKNOWN if none are found sufficient times
210 */
211BlocklistedSource GnssHalTest::FindStrongFrequentNonGpsSource(
212 const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
213 const int min_observations) {
214 return FindStrongFrequentNonGpsSource(convertToAidl(sv_info_list), min_observations);
215}
216
217BlocklistedSource GnssHalTest::FindStrongFrequentNonGpsSource(
218 const std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_list,
219 const int min_observations) {
220 std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
221
222 for (const auto& sv_info_vec : sv_info_list) {
223 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
224 const auto& gnss_sv = sv_info_vec[iSv];
225 if ((gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
226 (gnss_sv.constellation != GnssConstellationType::GPS)) {
227 ComparableBlocklistedSource source;
228 source.id.svid = gnss_sv.svid;
229 source.id.constellation = gnss_sv.constellation;
230
231 const auto& itSignal = mapSignals.find(source);
232 if (itSignal == mapSignals.end()) {
233 SignalCounts counts;
234 counts.observations = 1;
235 counts.max_cn0_dbhz = gnss_sv.cN0Dbhz;
236 mapSignals.insert(
237 std::pair<ComparableBlocklistedSource, SignalCounts>(source, counts));
238 } else {
239 itSignal->second.observations++;
240 if (itSignal->second.max_cn0_dbhz < gnss_sv.cN0Dbhz) {
241 itSignal->second.max_cn0_dbhz = gnss_sv.cN0Dbhz;
242 }
243 }
244 }
245 }
246 }
247
248 float max_cn0_dbhz_with_sufficient_count = 0.;
249 int total_observation_count = 0;
250 int blocklisted_source_count_observation = 0;
251
252 ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation
253 for (auto const& pairSignal : mapSignals) {
254 total_observation_count += pairSignal.second.observations;
255 if ((pairSignal.second.observations >= min_observations) &&
256 (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
257 source_to_blocklist = pairSignal.first;
258 blocklisted_source_count_observation = pairSignal.second.observations;
259 max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
260 }
261 }
262 ALOGD("Among %d observations, chose svid %d, constellation %d, "
263 "with %d observations at %.1f max CNo",
264 total_observation_count, source_to_blocklist.id.svid,
265 (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation,
266 max_cn0_dbhz_with_sufficient_count);
267
268 return source_to_blocklist.id;
269}
270
271GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation(
272 const int locations_to_await, const int gnss_sv_info_list_timeout) {
Yu-Han Yang4165ed12022-02-09 14:47:50 -0800273 if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
Yu-Han Yang1afbd5f2021-11-24 16:39:13 -0800274 return static_cast<GnssConstellationType>(
275 GnssHalTestTemplate<IGnss_V2_1>::startLocationAndGetNonGpsConstellation(
276 locations_to_await, gnss_sv_info_list_timeout));
277 }
278 aidl_gnss_cb_->location_cbq_.reset();
279 StartAndCheckLocations(locations_to_await);
280 const int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount();
281
282 // Tolerate 1 less sv status to handle edge cases in reporting.
283 int sv_info_list_cbq_size = aidl_gnss_cb_->sv_info_list_cbq_.size();
284 EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await);
285 ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
286 sv_info_list_cbq_size, locations_to_await, location_called_count);
287
288 // Find first non-GPS constellation to blocklist
289 GnssConstellationType constellation_to_blocklist = GnssConstellationType::UNKNOWN;
290 for (int i = 0; i < sv_info_list_cbq_size; ++i) {
291 std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
292 aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout);
293 for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
294 auto& gnss_sv = sv_info_vec[iSv];
295 if ((gnss_sv.svFlag & (uint32_t)IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
296 (gnss_sv.constellation != GnssConstellationType::UNKNOWN) &&
297 (gnss_sv.constellation != GnssConstellationType::GPS)) {
298 // found a non-GPS constellation
299 constellation_to_blocklist = gnss_sv.constellation;
300 break;
301 }
302 }
303 if (constellation_to_blocklist != GnssConstellationType::UNKNOWN) {
304 break;
305 }
306 }
307
308 if (constellation_to_blocklist == GnssConstellationType::UNKNOWN) {
309 ALOGI("No non-GPS constellations found, constellation blocklist test less effective.");
310 // Proceed functionally to blocklist something.
311 constellation_to_blocklist = GnssConstellationType::GLONASS;
312 }
313
314 return constellation_to_blocklist;
Yu-Han Yang1e1a6762020-09-30 17:01:53 -0700315}