1 /*
2  * Copyright (C) 2016 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 
17 #define LOG_TAG "LocSvc_GnssDebugInterface"
18 
19 #include <log/log.h>
20 #include <log_util.h>
21 #include "Gnss.h"
22 #include "GnssDebug.h"
23 #include "LocationUtil.h"
24 
25 namespace android {
26 namespace hardware {
27 namespace gnss {
28 namespace V1_1 {
29 namespace implementation {
30 
31 using ::android::hardware::hidl_vec;
32 
33 #define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000)
34 #define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS   (20000)
35 #define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC     (500)
36 #define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG       (180)
37 
38 #define GNSS_DEBUG_UNKNOWN_UTC_TIME            (1483228800000LL) // 1/1/2017 00:00 GMT
39 #define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN    (999) // 999 ns
40 #define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX    (1.57783680E17) // 5 years in ns
41 #define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5)  // ppm
42 
GnssDebug(Gnss * gnss)43 GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss)
44 {
45 }
46 
47 /*
48  * This methods requests position, time and satellite ephemeris debug information
49  * from the HAL.
50  *
51  * @return void
52 */
getDebugData(getDebugData_cb _hidl_cb)53 Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)
54 {
55     LOC_LOGD("%s]: ", __func__);
56 
57     DebugData data = { };
58 
59     if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){
60         LOC_LOGE("GnssDebug - Null GNSS interface");
61         _hidl_cb(data);
62         return Void();
63     }
64 
65     // get debug report snapshot via hal interface
66     GnssDebugReport reports = { };
67     mGnss->getGnssInterface()->getDebugReport(reports);
68 
69     // location block
70     if (reports.mLocation.mValid) {
71         data.position.valid = true;
72         data.position.latitudeDegrees = reports.mLocation.mLocation.latitude;
73         data.position.longitudeDegrees = reports.mLocation.mLocation.longitude;
74         data.position.altitudeMeters = reports.mLocation.mLocation.altitude;
75 
76         data.position.speedMetersPerSec =
77             (double)(reports.mLocation.mLocation.speed);
78         data.position.bearingDegrees =
79             (double)(reports.mLocation.mLocation.bearing);
80         data.position.horizontalAccuracyMeters =
81             (double)(reports.mLocation.mLocation.accuracy);
82         data.position.verticalAccuracyMeters =
83             reports.mLocation.verticalAccuracyMeters;
84         data.position.speedAccuracyMetersPerSecond =
85             reports.mLocation.speedAccuracyMetersPerSecond;
86         data.position.bearingAccuracyDegrees =
87             reports.mLocation.bearingAccuracyDegrees;
88 
89         timeval tv_now, tv_report;
90         tv_report.tv_sec  = reports.mLocation.mUtcReported.tv_sec;
91         tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL;
92         gettimeofday(&tv_now, NULL);
93         data.position.ageSeconds =
94             (tv_now.tv_sec - tv_report.tv_sec) +
95             (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000;
96     }
97     else {
98         data.position.valid = false;
99     }
100 
101     if (data.position.horizontalAccuracyMeters <= 0 ||
102         data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) {
103         data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS;
104     }
105     if (data.position.verticalAccuracyMeters <= 0 ||
106         data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) {
107         data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS;
108     }
109     if (data.position.speedAccuracyMetersPerSecond <= 0 ||
110         data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) {
111         data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC;
112     }
113     if (data.position.bearingAccuracyDegrees <= 0 ||
114         data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) {
115         data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG;
116     }
117 
118     // time block
119     if (reports.mTime.mValid) {
120         data.time.timeEstimate = reports.mTime.timeEstimate;
121         data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs;
122         data.time.frequencyUncertaintyNsPerSec =
123             reports.mTime.frequencyUncertaintyNsPerSec;
124     }
125 
126     if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) {
127         data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME;
128     }
129     if (data.time.timeUncertaintyNs <= 0) {
130         data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MIN;
131     } else if (data.time.timeUncertaintyNs > GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX) {
132         data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC_MAX;
133     }
134     if (data.time.frequencyUncertaintyNsPerSec <= 0 ||
135         data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) {
136         data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC;
137     }
138 
139     // satellite data block
140     SatelliteData s = { };
141     std::vector<SatelliteData> s_array = { };
142 
143     for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) {
144         memset(&s, 0, sizeof(s));
145         s.svid = reports.mSatelliteInfo[i].svid;
146         convertGnssConstellationType(
147             reports.mSatelliteInfo[i].constellation, s.constellation);
148         convertGnssEphemerisType(
149             reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType);
150         convertGnssEphemerisSource(
151             reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource);
152         convertGnssEphemerisHealth(
153             reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth);
154 
155         s.ephemerisAgeSeconds =
156             reports.mSatelliteInfo[i].ephemerisAgeSeconds;
157         s.serverPredictionIsAvailable =
158             reports.mSatelliteInfo[i].serverPredictionIsAvailable;
159         s.serverPredictionAgeSeconds =
160             reports.mSatelliteInfo[i].serverPredictionAgeSeconds;
161 
162         s_array.push_back(s);
163     }
164     data.satelliteDataArray = s_array;
165 
166     // callback HIDL with collected debug data
167     _hidl_cb(data);
168     return Void();
169 }
170 
171 }  // namespace implementation
172 }  // namespace V1_1
173 }  // namespace gnss
174 }  // namespace hardware
175 }  // namespace android
176