1 #define LOG_TAG "Gnss"
2 
3 #include <android/hardware/gnss/1.0/types.h>
4 #include <log/log.h>
5 
6 #include "Gnss.h"
7 #include "GnssConstants.h"
8 #include "GnssDebug.h"
9 #include "GnssMeasurement.h"
10 
11 namespace android {
12 namespace hardware {
13 namespace gnss {
14 namespace V1_1 {
15 namespace implementation {
16 
17 using GnssSvFlags = IGnssCallback::GnssSvFlags;
18 
19 const uint32_t MIN_INTERVAL_MILLIS = 100;
20 sp<::android::hardware::gnss::V1_1::IGnssCallback> Gnss::sGnssCallback = nullptr;
21 
Gnss()22 Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
23 
~Gnss()24 Gnss::~Gnss() {
25     stop();
26 }
27 
28 // Methods from ::android::hardware::gnss::V1_0::IGnss follow.
setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback> &)29 Return<bool> Gnss::setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback>&) {
30     // Mock handles only new callback (see setCallback1_1) coming from Android P+
31     return false;
32 }
33 
start()34 Return<bool> Gnss::start() {
35     if (mIsActive) {
36         ALOGW("Gnss has started. Restarting...");
37         stop();
38     }
39 
40     mIsActive = true;
41     mThread = std::thread([this]() {
42         while (mIsActive == true) {
43             auto svStatus = this->getMockSvStatus();
44             this->reportSvStatus(svStatus);
45 
46             auto location = this->getMockLocation();
47             this->reportLocation(location);
48 
49             std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
50         }
51     });
52 
53     return true;
54 }
55 
stop()56 Return<bool> Gnss::stop() {
57     mIsActive = false;
58     if (mThread.joinable()) {
59         mThread.join();
60     }
61     return true;
62 }
63 
cleanup()64 Return<void> Gnss::cleanup() {
65     // TODO implement
66     return Void();
67 }
68 
injectTime(int64_t,int64_t,int32_t)69 Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
70     // TODO implement
71     return bool{};
72 }
73 
injectLocation(double,double,float)74 Return<bool> Gnss::injectLocation(double, double, float) {
75     // TODO implement
76     return bool{};
77 }
78 
deleteAidingData(::android::hardware::gnss::V1_0::IGnss::GnssAidingData)79 Return<void> Gnss::deleteAidingData(::android::hardware::gnss::V1_0::IGnss::GnssAidingData) {
80     return Void();
81 }
82 
setPositionMode(::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence,uint32_t,uint32_t,uint32_t)83 Return<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 
getExtensionAGnssRil()90 Return<sp<::android::hardware::gnss::V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
91     // TODO implement
92     return ::android::sp<::android::hardware::gnss::V1_0::IAGnssRil>{};
93 }
94 
getExtensionGnssGeofencing()95 Return<sp<::android::hardware::gnss::V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
96     // TODO implement
97     return ::android::sp<::android::hardware::gnss::V1_0::IGnssGeofencing>{};
98 }
99 
getExtensionAGnss()100 Return<sp<::android::hardware::gnss::V1_0::IAGnss>> Gnss::getExtensionAGnss() {
101     // TODO implement
102     return ::android::sp<::android::hardware::gnss::V1_0::IAGnss>{};
103 }
104 
getExtensionGnssNi()105 Return<sp<::android::hardware::gnss::V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
106     // TODO implement
107     return ::android::sp<::android::hardware::gnss::V1_0::IGnssNi>{};
108 }
109 
getExtensionGnssMeasurement()110 Return<sp<::android::hardware::gnss::V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
111     // TODO implement
112     return new GnssMeasurement();
113 }
114 
115 Return<sp<::android::hardware::gnss::V1_0::IGnssNavigationMessage>>
getExtensionGnssNavigationMessage()116 Gnss::getExtensionGnssNavigationMessage() {
117     // TODO implement
118     return ::android::sp<::android::hardware::gnss::V1_0::IGnssNavigationMessage>{};
119 }
120 
getExtensionXtra()121 Return<sp<::android::hardware::gnss::V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
122     // TODO implement
123     return ::android::sp<::android::hardware::gnss::V1_0::IGnssXtra>{};
124 }
125 
126 Return<sp<::android::hardware::gnss::V1_0::IGnssConfiguration>>
getExtensionGnssConfiguration()127 Gnss::getExtensionGnssConfiguration() {
128     // TODO implement
129     return new GnssConfiguration();
130 }
131 
getExtensionGnssDebug()132 Return<sp<::android::hardware::gnss::V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
133     return new GnssDebug();
134 }
135 
getExtensionGnssBatching()136 Return<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.
setCallback_1_1(const sp<::android::hardware::gnss::V1_1::IGnssCallback> & callback)142 Return<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;
171 }
172 
setPositionMode_1_1(::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence,uint32_t minIntervalMs,uint32_t,uint32_t,bool)173 Return<bool> Gnss::setPositionMode_1_1(
174     ::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,
175     ::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;
179 }
180 
181 Return<sp<::android::hardware::gnss::V1_1::IGnssConfiguration>>
getExtensionGnssConfiguration_1_1()182 Gnss::getExtensionGnssConfiguration_1_1() {
183     return mGnssConfiguration;
184 }
185 
186 Return<sp<::android::hardware::gnss::V1_1::IGnssMeasurement>>
getExtensionGnssMeasurement_1_1()187 Gnss::getExtensionGnssMeasurement_1_1() {
188     // TODO implement
189     return new GnssMeasurement();
190 }
191 
injectBestLocation(const GnssLocation &)192 Return<bool> Gnss::injectBestLocation(const GnssLocation&) {
193     return true;
194 }
195 
getMockLocation() const196 Return<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};
208     return location;
209 }
210 
getSvInfo(int16_t svid,GnssConstellationType type,float cN0DbHz,float elevationDegrees,float azimuthDegrees) const211 Return<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 
getMockSvStatus() const223 Return<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),
230         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),
233         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 
reportLocation(const GnssLocation & location) const253 Return<void> Gnss::reportLocation(const GnssLocation& location) const {
254     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 }
262 
reportSvStatus(const GnssSvStatus & svStatus) const263 Return<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 
273 }  // namespace implementation
274 }  // namespace V1_1
275 }  // namespace gnss
276 }  // namespace hardware
277 }  // namespace android
278