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