blob: bbf1cd31dee84a91fb36d4633f9a2bbaeaaef53e [file] [log] [blame]
Yu-Han Yang73f16ad2018-02-24 10:05:32 -08001#define LOG_TAG "Gnss"
2
Yu-Han Yanga2f77322018-03-06 10:12:55 -08003#include <android/hardware/gnss/1.0/types.h>
Yu-Han Yang73f16ad2018-02-24 10:05:32 -08004#include <log/log.h>
Yu-Han Yang584ad322018-03-01 16:10:27 -08005
6#include "Gnss.h"
Yu-Han Yanga2f77322018-03-06 10:12:55 -08007#include "GnssConstants.h"
8#include "GnssDebug.h"
Yu-Han Yang73f16ad2018-02-24 10:05:32 -08009#include "GnssMeasurement.h"
10
11namespace android {
12namespace hardware {
13namespace gnss {
14namespace V1_1 {
15namespace implementation {
16
Yu-Han Yanga2f77322018-03-06 10:12:55 -080017using GnssSvFlags = IGnssCallback::GnssSvFlags;
18
Yu-Han Yang584ad322018-03-01 16:10:27 -080019const uint32_t MIN_INTERVAL_MILLIS = 100;
20sp<::android::hardware::gnss::V1_1::IGnssCallback> Gnss::sGnssCallback = nullptr;
21
Yu-Han Yanga2f77322018-03-06 10:12:55 -080022Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
Yu-Han Yang584ad322018-03-01 16:10:27 -080023
24Gnss::~Gnss() {
25 stop();
26}
27
Yu-Han Yang73f16ad2018-02-24 10:05:32 -080028// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
29Return<bool> Gnss::setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback>&) {
Yu-Han Yang584ad322018-03-01 16:10:27 -080030 // Mock handles only new callback (see setCallback1_1) coming from Android P+
31 return false;
Yu-Han Yang73f16ad2018-02-24 10:05:32 -080032}
33
34Return<bool> Gnss::start() {
Yu-Han Yang584ad322018-03-01 16:10:27 -080035 if (mIsActive) {
36 ALOGW("Gnss has started. Restarting...");
37 stop();
38 }
39
40 mIsActive = true;
41 mThread = std::thread([this]() {
42 while (mIsActive == true) {
Yu-Han Yanga2f77322018-03-06 10:12:55 -080043 auto svStatus = this->getMockSvStatus();
44 this->reportSvStatus(svStatus);
45
46 auto location = this->getMockLocation();
Yu-Han Yang584ad322018-03-01 16:10:27 -080047 this->reportLocation(location);
48
49 std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
50 }
51 });
52
53 return true;
Yu-Han Yang73f16ad2018-02-24 10:05:32 -080054}
55
56Return<bool> Gnss::stop() {
Yu-Han Yang584ad322018-03-01 16:10:27 -080057 mIsActive = false;
58 if (mThread.joinable()) {
59 mThread.join();
60 }
61 return true;
Yu-Han Yang73f16ad2018-02-24 10:05:32 -080062}
63
64Return<void> Gnss::cleanup() {
65 // TODO implement
66 return Void();
67}
68
69Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
70 // TODO implement
71 return bool{};
72}
73
74Return<bool> Gnss::injectLocation(double, double, float) {
75 // TODO implement
76 return bool{};
77}
78
79Return<void> Gnss::deleteAidingData(::android::hardware::gnss::V1_0::IGnss::GnssAidingData) {
Yu-Han Yang73f16ad2018-02-24 10:05:32 -080080 return Void();
81}
82
83Return<bool> Gnss::setPositionMode(::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,
84 ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence,
85 uint32_t, uint32_t, uint32_t) {
86 // TODO implement
87 return bool{};
88}
89
90Return<sp<::android::hardware::gnss::V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
91 // TODO implement
92 return ::android::sp<::android::hardware::gnss::V1_0::IAGnssRil>{};
93}
94
95Return<sp<::android::hardware::gnss::V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
96 // TODO implement
97 return ::android::sp<::android::hardware::gnss::V1_0::IGnssGeofencing>{};
98}
99
100Return<sp<::android::hardware::gnss::V1_0::IAGnss>> Gnss::getExtensionAGnss() {
101 // TODO implement
102 return ::android::sp<::android::hardware::gnss::V1_0::IAGnss>{};
103}
104
105Return<sp<::android::hardware::gnss::V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
106 // TODO implement
107 return ::android::sp<::android::hardware::gnss::V1_0::IGnssNi>{};
108}
109
110Return<sp<::android::hardware::gnss::V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
111 // TODO implement
112 return new GnssMeasurement();
113}
114
115Return<sp<::android::hardware::gnss::V1_0::IGnssNavigationMessage>>
116Gnss::getExtensionGnssNavigationMessage() {
117 // TODO implement
118 return ::android::sp<::android::hardware::gnss::V1_0::IGnssNavigationMessage>{};
119}
120
121Return<sp<::android::hardware::gnss::V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
122 // TODO implement
123 return ::android::sp<::android::hardware::gnss::V1_0::IGnssXtra>{};
124}
125
126Return<sp<::android::hardware::gnss::V1_0::IGnssConfiguration>>
127Gnss::getExtensionGnssConfiguration() {
128 // TODO implement
129 return new GnssConfiguration();
130}
131
132Return<sp<::android::hardware::gnss::V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
Yu-Han Yanga2f77322018-03-06 10:12:55 -0800133 return new GnssDebug();
Yu-Han Yang73f16ad2018-02-24 10:05:32 -0800134}
135
136Return<sp<::android::hardware::gnss::V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
137 // TODO implement
138 return ::android::sp<::android::hardware::gnss::V1_0::IGnssBatching>{};
139}
140
141// Methods from ::android::hardware::gnss::V1_1::IGnss follow.
Yu-Han Yang584ad322018-03-01 16:10:27 -0800142Return<bool> Gnss::setCallback_1_1(
143 const sp<::android::hardware::gnss::V1_1::IGnssCallback>& callback) {
144 if (callback == nullptr) {
145 ALOGE("%s: Null callback ignored", __func__);
146 return false;
147 }
148
149 sGnssCallback = callback;
150
151 uint32_t capabilities = 0x0;
152 auto ret = sGnssCallback->gnssSetCapabilitesCb(capabilities);
153 if (!ret.isOk()) {
154 ALOGE("%s: Unable to invoke callback", __func__);
155 }
156
157 IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
158
159 ret = sGnssCallback->gnssSetSystemInfoCb(gnssInfo);
160 if (!ret.isOk()) {
161 ALOGE("%s: Unable to invoke callback", __func__);
162 }
163
164 auto gnssName = "Google Mock GNSS Implementation v1.1";
165 ret = sGnssCallback->gnssNameCb(gnssName);
166 if (!ret.isOk()) {
167 ALOGE("%s: Unable to invoke callback", __func__);
168 }
169
170 return true;
Yu-Han Yang73f16ad2018-02-24 10:05:32 -0800171}
172
173Return<bool> Gnss::setPositionMode_1_1(
174 ::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,
Yu-Han Yang584ad322018-03-01 16:10:27 -0800175 ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
176 uint32_t, uint32_t, bool) {
177 mMinIntervalMs = (minIntervalMs < MIN_INTERVAL_MILLIS) ? MIN_INTERVAL_MILLIS : minIntervalMs;
178 return true;
Yu-Han Yang73f16ad2018-02-24 10:05:32 -0800179}
180
181Return<sp<::android::hardware::gnss::V1_1::IGnssConfiguration>>
182Gnss::getExtensionGnssConfiguration_1_1() {
Yu-Han Yanga2f77322018-03-06 10:12:55 -0800183 return mGnssConfiguration;
Yu-Han Yang73f16ad2018-02-24 10:05:32 -0800184}
185
186Return<sp<::android::hardware::gnss::V1_1::IGnssMeasurement>>
187Gnss::getExtensionGnssMeasurement_1_1() {
188 // TODO implement
189 return new GnssMeasurement();
190}
191
Yu-Han Yanga2f77322018-03-06 10:12:55 -0800192Return<bool> Gnss::injectBestLocation(const GnssLocation&) {
193 return true;
Yu-Han Yang73f16ad2018-02-24 10:05:32 -0800194}
195
Yu-Han Yanga2f77322018-03-06 10:12:55 -0800196Return<GnssLocation> Gnss::getMockLocation() const {
197 GnssLocation location = {.gnssLocationFlags = 0xFF,
198 .latitudeDegrees = kMockLatitudeDegrees,
199 .longitudeDegrees = kMockLongitudeDegrees,
200 .altitudeMeters = kMockAltitudeMeters,
201 .speedMetersPerSec = kMockSpeedMetersPerSec,
202 .bearingDegrees = kMockBearingDegrees,
203 .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters,
204 .verticalAccuracyMeters = kMockVerticalAccuracyMeters,
205 .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
206 .bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
207 .timestamp = kMockTimestamp};
Yu-Han Yang584ad322018-03-01 16:10:27 -0800208 return location;
209}
210
Yu-Han Yanga2f77322018-03-06 10:12:55 -0800211Return<GnssSvInfo> Gnss::getSvInfo(int16_t svid, GnssConstellationType type, float cN0DbHz,
212 float elevationDegrees, float azimuthDegrees) const {
213 GnssSvInfo svInfo = {.svid = svid,
214 .constellation = type,
215 .cN0Dbhz = cN0DbHz,
216 .elevationDegrees = elevationDegrees,
217 .azimuthDegrees = azimuthDegrees,
218 .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
219 GnssSvFlags::HAS_ALMANAC_DATA};
220 return svInfo;
221}
222
223Return<GnssSvStatus> Gnss::getMockSvStatus() const {
224 std::unique_lock<std::recursive_mutex> lock(mGnssConfiguration->getMutex());
225 GnssSvInfo mockGnssSvInfoList[] = {
226 getSvInfo(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5),
227 getSvInfo(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
228 getSvInfo(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
229 getSvInfo(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
Yu-Han Yangca63cbf2018-05-16 13:31:24 -0700230 getSvInfo(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0),
231 getSvInfo(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0),
232 getSvInfo(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0),
Yu-Han Yanga2f77322018-03-06 10:12:55 -0800233 getSvInfo(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
234
235 GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)};
236 for (uint32_t i = 0; i < svStatus.numSvs; i++) {
237 if (mGnssConfiguration->isBlacklisted(mockGnssSvInfoList[i])) {
238 /**
239 * Note well, this is a simple, mock emulation of not using a satellite by changing the
240 * used bit. Simply blanking the used bit, as is done here, is *not* an acceptable
241 * actual device implementation - actual devices *must not* use the satellite in the
242 * position calculation, as specified in IGnssConfiguration.hal.
243 */
244 mockGnssSvInfoList[i].svFlag &=
245 ~static_cast<uint8_t>(IGnssCallback::GnssSvFlags::USED_IN_FIX);
246 }
247 svStatus.gnssSvList[i] = mockGnssSvInfoList[i];
248 }
249
250 return svStatus;
251}
252
253Return<void> Gnss::reportLocation(const GnssLocation& location) const {
Yu-Han Yang584ad322018-03-01 16:10:27 -0800254 std::unique_lock<std::mutex> lock(mMutex);
255 if (sGnssCallback == nullptr) {
256 ALOGE("%s: sGnssCallback is null.", __func__);
257 return Void();
258 }
259 sGnssCallback->gnssLocationCb(location);
260 return Void();
261}
Yu-Han Yang73f16ad2018-02-24 10:05:32 -0800262
Yu-Han Yanga2f77322018-03-06 10:12:55 -0800263Return<void> Gnss::reportSvStatus(const GnssSvStatus& svStatus) const {
264 std::unique_lock<std::mutex> lock(mMutex);
265 if (sGnssCallback == nullptr) {
266 ALOGE("%s: sGnssCallback is null.", __func__);
267 return Void();
268 }
269 sGnssCallback->gnssSvStatusCb(svStatus);
270 return Void();
271}
272
Yu-Han Yang73f16ad2018-02-24 10:05:32 -0800273} // namespace implementation
274} // namespace V1_1
275} // namespace gnss
276} // namespace hardware
277} // namespace android