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 "GnssDebug.h"
8 #include "GnssMeasurement.h"
9 #include "Utils.h"
10
11 namespace android {
12 namespace hardware {
13 namespace gnss {
14 namespace V1_1 {
15 namespace implementation {
16
17 using ::android::hardware::gnss::common::Utils;
18 using GnssSvFlags = IGnssCallback::GnssSvFlags;
19
20 const uint32_t MIN_INTERVAL_MILLIS = 100;
21 sp<::android::hardware::gnss::V1_1::IGnssCallback> Gnss::sGnssCallback = nullptr;
22
Gnss()23 Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
24
~Gnss()25 Gnss::~Gnss() {
26 stop();
27 }
28
29 // Methods from ::android::hardware::gnss::V1_0::IGnss follow.
setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback> &)30 Return<bool> Gnss::setCallback(const sp<::android::hardware::gnss::V1_0::IGnssCallback>&) {
31 // Mock handles only new callback (see setCallback1_1) coming from Android P+
32 return false;
33 }
34
start()35 Return<bool> Gnss::start() {
36 if (mIsActive) {
37 ALOGW("Gnss has started. Restarting...");
38 stop();
39 }
40
41 mIsActive = true;
42 mThread = std::thread([this]() {
43 while (mIsActive == true) {
44 auto svStatus = this->getMockSvStatus();
45 this->reportSvStatus(svStatus);
46
47 auto location = Utils::getMockLocationV1_0();
48 this->reportLocation(location);
49
50 std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
51 }
52 });
53
54 return true;
55 }
56
stop()57 Return<bool> Gnss::stop() {
58 mIsActive = false;
59 if (mThread.joinable()) {
60 mThread.join();
61 }
62 return true;
63 }
64
cleanup()65 Return<void> Gnss::cleanup() {
66 // TODO implement
67 return Void();
68 }
69
injectTime(int64_t,int64_t,int32_t)70 Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
71 // TODO implement
72 return bool{};
73 }
74
injectLocation(double,double,float)75 Return<bool> Gnss::injectLocation(double, double, float) {
76 // TODO implement
77 return bool{};
78 }
79
deleteAidingData(::android::hardware::gnss::V1_0::IGnss::GnssAidingData)80 Return<void> Gnss::deleteAidingData(::android::hardware::gnss::V1_0::IGnss::GnssAidingData) {
81 return Void();
82 }
83
setPositionMode(::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence,uint32_t,uint32_t,uint32_t)84 Return<bool> Gnss::setPositionMode(::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,
85 ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence,
86 uint32_t, uint32_t, uint32_t) {
87 // TODO implement
88 return bool{};
89 }
90
getExtensionAGnssRil()91 Return<sp<::android::hardware::gnss::V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
92 // TODO implement
93 return ::android::sp<::android::hardware::gnss::V1_0::IAGnssRil>{};
94 }
95
getExtensionGnssGeofencing()96 Return<sp<::android::hardware::gnss::V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
97 // TODO implement
98 return ::android::sp<::android::hardware::gnss::V1_0::IGnssGeofencing>{};
99 }
100
getExtensionAGnss()101 Return<sp<::android::hardware::gnss::V1_0::IAGnss>> Gnss::getExtensionAGnss() {
102 // TODO implement
103 return ::android::sp<::android::hardware::gnss::V1_0::IAGnss>{};
104 }
105
getExtensionGnssNi()106 Return<sp<::android::hardware::gnss::V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
107 // TODO implement
108 return ::android::sp<::android::hardware::gnss::V1_0::IGnssNi>{};
109 }
110
getExtensionGnssMeasurement()111 Return<sp<::android::hardware::gnss::V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
112 // TODO implement
113 return new GnssMeasurement();
114 }
115
116 Return<sp<::android::hardware::gnss::V1_0::IGnssNavigationMessage>>
getExtensionGnssNavigationMessage()117 Gnss::getExtensionGnssNavigationMessage() {
118 // TODO implement
119 return ::android::sp<::android::hardware::gnss::V1_0::IGnssNavigationMessage>{};
120 }
121
getExtensionXtra()122 Return<sp<::android::hardware::gnss::V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
123 // TODO implement
124 return ::android::sp<::android::hardware::gnss::V1_0::IGnssXtra>{};
125 }
126
127 Return<sp<::android::hardware::gnss::V1_0::IGnssConfiguration>>
getExtensionGnssConfiguration()128 Gnss::getExtensionGnssConfiguration() {
129 // TODO implement
130 return new GnssConfiguration();
131 }
132
getExtensionGnssDebug()133 Return<sp<::android::hardware::gnss::V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
134 return new GnssDebug();
135 }
136
getExtensionGnssBatching()137 Return<sp<::android::hardware::gnss::V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
138 // TODO implement
139 return ::android::sp<::android::hardware::gnss::V1_0::IGnssBatching>{};
140 }
141
142 // Methods from ::android::hardware::gnss::V1_1::IGnss follow.
setCallback_1_1(const sp<::android::hardware::gnss::V1_1::IGnssCallback> & callback)143 Return<bool> Gnss::setCallback_1_1(
144 const sp<::android::hardware::gnss::V1_1::IGnssCallback>& callback) {
145 if (callback == nullptr) {
146 ALOGE("%s: Null callback ignored", __func__);
147 return false;
148 }
149
150 sGnssCallback = callback;
151
152 uint32_t capabilities = 0x0;
153 auto ret = sGnssCallback->gnssSetCapabilitesCb(capabilities);
154 if (!ret.isOk()) {
155 ALOGE("%s: Unable to invoke callback", __func__);
156 }
157
158 IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
159
160 ret = sGnssCallback->gnssSetSystemInfoCb(gnssInfo);
161 if (!ret.isOk()) {
162 ALOGE("%s: Unable to invoke callback", __func__);
163 }
164
165 auto gnssName = "Google Mock GNSS Implementation v1.1";
166 ret = sGnssCallback->gnssNameCb(gnssName);
167 if (!ret.isOk()) {
168 ALOGE("%s: Unable to invoke callback", __func__);
169 }
170
171 return true;
172 }
173
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)174 Return<bool> Gnss::setPositionMode_1_1(
175 ::android::hardware::gnss::V1_0::IGnss::GnssPositionMode,
176 ::android::hardware::gnss::V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
177 uint32_t, uint32_t, bool) {
178 mMinIntervalMs = (minIntervalMs < MIN_INTERVAL_MILLIS) ? MIN_INTERVAL_MILLIS : minIntervalMs;
179 return true;
180 }
181
182 Return<sp<::android::hardware::gnss::V1_1::IGnssConfiguration>>
getExtensionGnssConfiguration_1_1()183 Gnss::getExtensionGnssConfiguration_1_1() {
184 return mGnssConfiguration;
185 }
186
187 Return<sp<::android::hardware::gnss::V1_1::IGnssMeasurement>>
getExtensionGnssMeasurement_1_1()188 Gnss::getExtensionGnssMeasurement_1_1() {
189 // TODO implement
190 return new GnssMeasurement();
191 }
192
injectBestLocation(const GnssLocation &)193 Return<bool> Gnss::injectBestLocation(const GnssLocation&) {
194 return true;
195 }
196
getMockSvStatus() const197 Return<GnssSvStatus> Gnss::getMockSvStatus() const {
198 std::unique_lock<std::recursive_mutex> lock(mGnssConfiguration->getMutex());
199 GnssSvInfo mockGnssSvInfoList[] = {
200 Utils::getMockSvInfoV1_0(3, GnssConstellationType::GPS, 32.5, 59.1, 166.5),
201 Utils::getMockSvInfoV1_0(5, GnssConstellationType::GPS, 27.0, 29.0, 56.5),
202 Utils::getMockSvInfoV1_0(17, GnssConstellationType::GPS, 30.5, 71.0, 77.0),
203 Utils::getMockSvInfoV1_0(26, GnssConstellationType::GPS, 24.1, 28.0, 253.0),
204 Utils::getMockSvInfoV1_0(5, GnssConstellationType::GLONASS, 20.5, 11.5, 116.0),
205 Utils::getMockSvInfoV1_0(17, GnssConstellationType::GLONASS, 21.5, 28.5, 186.0),
206 Utils::getMockSvInfoV1_0(18, GnssConstellationType::GLONASS, 28.3, 38.8, 69.0),
207 Utils::getMockSvInfoV1_0(10, GnssConstellationType::GLONASS, 25.0, 66.0, 247.0)};
208
209 GnssSvStatus svStatus = {.numSvs = sizeof(mockGnssSvInfoList) / sizeof(GnssSvInfo)};
210 for (uint32_t i = 0; i < svStatus.numSvs; i++) {
211 if (mGnssConfiguration->isBlacklisted(mockGnssSvInfoList[i])) {
212 /**
213 * Note well, this is a simple, mock emulation of not using a satellite by changing the
214 * used bit. Simply blanking the used bit, as is done here, is *not* an acceptable
215 * actual device implementation - actual devices *must not* use the satellite in the
216 * position calculation, as specified in IGnssConfiguration.hal.
217 */
218 mockGnssSvInfoList[i].svFlag &=
219 ~static_cast<uint8_t>(IGnssCallback::GnssSvFlags::USED_IN_FIX);
220 }
221 svStatus.gnssSvList[i] = mockGnssSvInfoList[i];
222 }
223
224 return svStatus;
225 }
226
reportLocation(const GnssLocation & location) const227 Return<void> Gnss::reportLocation(const GnssLocation& location) const {
228 std::unique_lock<std::mutex> lock(mMutex);
229 if (sGnssCallback == nullptr) {
230 ALOGE("%s: sGnssCallback is null.", __func__);
231 return Void();
232 }
233 sGnssCallback->gnssLocationCb(location);
234 return Void();
235 }
236
reportSvStatus(const GnssSvStatus & svStatus) const237 Return<void> Gnss::reportSvStatus(const GnssSvStatus& svStatus) const {
238 std::unique_lock<std::mutex> lock(mMutex);
239 if (sGnssCallback == nullptr) {
240 ALOGE("%s: sGnssCallback is null.", __func__);
241 return Void();
242 }
243 sGnssCallback->gnssSvStatusCb(svStatus);
244 return Void();
245 }
246
247 } // namespace implementation
248 } // namespace V1_1
249 } // namespace gnss
250 } // namespace hardware
251 } // namespace android
252