blob: c97323c60e70a45ac2f82ef7738e60a48e3b2e87 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 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
Lifu Tang30f95a72016-01-07 23:20:38 -080017#define LOG_TAG "GnssLocationProvider"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Mike Lockwoodb8d90332010-10-18 17:59:48 -040019#define LOG_NDEBUG 0
Danke Xie22d1f9f2009-08-18 18:28:45 -040020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021#include "JNIHelp.h"
22#include "jni.h"
Mike Lockwoodb7ff4572010-04-05 15:24:34 -040023#include "hardware/hardware.h"
Lifu Tanga8b7bb52016-01-26 01:22:10 -080024#include "hardware/gps_internal.h"
Mike Lockwood8f5a8002010-04-07 09:05:26 -040025#include "hardware_legacy/power.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include "utils/Log.h"
27#include "utils/misc.h"
Mike Lockwoodf602d362010-06-20 14:28:16 -070028#include "android_runtime/AndroidRuntime.h"
Ruben Brunk87eac992013-09-09 17:44:59 -070029#include "android_runtime/Log.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
destradaa931a37f2014-08-12 16:36:59 -070031#include <arpa/inet.h>
Lifu Tang38bce792016-02-24 17:17:38 -080032#include <limits>
destradaa96a14702014-06-05 11:36:30 -070033#include <linux/in.h>
34#include <linux/in6.h>
Lifu Tang38bce792016-02-24 17:17:38 -080035#include <pthread.h>
36#include <string.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
Mike Lockwoodf602d362010-06-20 14:28:16 -070038static jobject mCallbacksObj = NULL;
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040static jmethodID method_reportLocation;
41static jmethodID method_reportStatus;
42static jmethodID method_reportSvStatus;
Mike Lockwoode3635c92009-05-11 08:38:02 -040043static jmethodID method_reportAGpsStatus;
Mike Lockwoodb16e7802009-08-06 09:26:02 -040044static jmethodID method_reportNmea;
Mike Lockwood04598b62010-04-14 17:17:24 -040045static jmethodID method_setEngineCapabilities;
Lifu Tang9363b942016-02-16 18:07:00 -080046static jmethodID method_setGnssYearOfHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047static jmethodID method_xtraDownloadRequest;
Danke Xie22d1f9f2009-08-18 18:28:45 -040048static jmethodID method_reportNiNotification;
Miguel Torroja1e84da82010-07-27 07:02:24 +020049static jmethodID method_requestRefLocation;
50static jmethodID method_requestSetID;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -040051static jmethodID method_requestUtcTime;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070052static jmethodID method_reportGeofenceTransition;
53static jmethodID method_reportGeofenceStatus;
54static jmethodID method_reportGeofenceAddStatus;
55static jmethodID method_reportGeofenceRemoveStatus;
56static jmethodID method_reportGeofencePauseStatus;
57static jmethodID method_reportGeofenceResumeStatus;
destradaaea8a8a62014-06-23 18:19:03 -070058static jmethodID method_reportMeasurementData;
destradaa4b3e3932014-07-21 18:01:47 -070059static jmethodID method_reportNavigationMessages;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060
61static const GpsInterface* sGpsInterface = NULL;
62static const GpsXtraInterface* sGpsXtraInterface = NULL;
Mike Lockwoode3635c92009-05-11 08:38:02 -040063static const AGpsInterface* sAGpsInterface = NULL;
Danke Xie22d1f9f2009-08-18 18:28:45 -040064static const GpsNiInterface* sGpsNiInterface = NULL;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -060065static const GpsDebugInterface* sGpsDebugInterface = NULL;
Miguel Torroja1e84da82010-07-27 07:02:24 +020066static const AGpsRilInterface* sAGpsRilInterface = NULL;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070067static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
destradaaea8a8a62014-06-23 18:19:03 -070068static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
destradaa4b3e3932014-07-21 18:01:47 -070069static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
Tsuwei Chen52617bb2014-08-25 11:49:11 -070070static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
Lifu Tang120480f2016-02-07 18:08:19 -080072#define GPS_MAX_SATELLITE_COUNT 32
73#define GNSS_MAX_SATELLITE_COUNT 64
Lifu Tang30f95a72016-01-07 23:20:38 -080074
Lifu Tang120480f2016-02-07 18:08:19 -080075#define SVID_SHIFT_WIDTH 7
76#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
Lifu Tang30f95a72016-01-07 23:20:38 -080077
Mike Lockwoodf602d362010-06-20 14:28:16 -070078// temporary storage for GPS callbacks
Lifu Tang120480f2016-02-07 18:08:19 -080079static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
Lifu Tang30f95a72016-01-07 23:20:38 -080080static size_t sGnssSvListSize;
Mike Lockwoodf602d362010-06-20 14:28:16 -070081static const char* sNmeaString;
82static int sNmeaStringLength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083
Mike Lockwood8f5a8002010-04-07 09:05:26 -040084#define WAKE_LOCK_NAME "GPS"
85
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086namespace android {
87
Mike Lockwoodf602d362010-06-20 14:28:16 -070088static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
89 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +000090 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwoodf602d362010-06-20 14:28:16 -070091 LOGE_EX(env);
92 env->ExceptionClear();
93 }
94}
95
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096static void location_callback(GpsLocation* location)
97{
Mike Lockwoodf602d362010-06-20 14:28:16 -070098 JNIEnv* env = AndroidRuntime::getJNIEnv();
99 env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
100 (jdouble)location->latitude, (jdouble)location->longitude,
101 (jdouble)location->altitude,
102 (jfloat)location->speed, (jfloat)location->bearing,
103 (jfloat)location->accuracy, (jlong)location->timestamp);
104 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105}
106
107static void status_callback(GpsStatus* status)
108{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700109 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf602d362010-06-20 14:28:16 -0700110 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
111 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112}
113
114static void sv_status_callback(GpsSvStatus* sv_status)
115{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700116 JNIEnv* env = AndroidRuntime::getJNIEnv();
Lifu Tang30f95a72016-01-07 23:20:38 -0800117 size_t status_size = sv_status->size;
Lifu Tang120480f2016-02-07 18:08:19 -0800118 // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
119 // if it doesn't provide a valid size.
Lifu Tang30f95a72016-01-07 23:20:38 -0800120 if (status_size == 0) {
Lifu Tang120480f2016-02-07 18:08:19 -0800121 ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
Lifu Tang30f95a72016-01-07 23:20:38 -0800122 }
Lifu Tang120480f2016-02-07 18:08:19 -0800123 sGnssSvListSize = sv_status->num_svs;
124 // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
125 if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
Lifu Tanga2b74fd2016-02-11 12:57:59 -0800126 ALOGW("Too many satellites %zd. Clamps to %d.",
Lifu Tang120480f2016-02-07 18:08:19 -0800127 sGnssSvListSize,
128 GPS_MAX_SATELLITE_COUNT);
129 sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
130 }
131 uint32_t ephemeris_mask = sv_status->ephemeris_mask;
132 uint32_t almanac_mask = sv_status->almanac_mask;
133 uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
134 for (size_t i = 0; i < sGnssSvListSize; i++) {
135 GnssSvInfo& info = sGnssSvList[i];
136 info.svid = sv_status->sv_list[i].prn;
Lifu Tang120480f2016-02-07 18:08:19 -0800137 if (info.svid >=1 && info.svid <= 32) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800138 info.constellation = GNSS_CONSTELLATION_GPS;
Lifu Tang120480f2016-02-07 18:08:19 -0800139 } else {
Lifu Tang9363b942016-02-16 18:07:00 -0800140 ALOGD("Unknown constellation type with Svid = %d.", info.svid);
Lifu Tang120480f2016-02-07 18:08:19 -0800141 info.constellation = GNSS_CONSTELLATION_UNKNOWN;
142 }
143 info.snr = sv_status->sv_list[i].snr;
144 info.elevation = sv_status->sv_list[i].elevation;
145 info.azimuth = sv_status->sv_list[i].azimuth;
146 info.flags = GNSS_SV_FLAGS_NONE;
147 if (info.svid > 0 && info.svid <= 32) {
148 int32_t this_svid_mask = (1 << (info.svid - 1));
149 if ((ephemeris_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800150 info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
Lifu Tang120480f2016-02-07 18:08:19 -0800151 }
152 if ((almanac_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800153 info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
Lifu Tang120480f2016-02-07 18:08:19 -0800154 }
155 if ((used_in_fix_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800156 info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
157 }
158 }
Lifu Tang120480f2016-02-07 18:08:19 -0800159 }
160 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
161 checkAndClearExceptionFromCallback(env, __FUNCTION__);
162}
163
164static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
165 JNIEnv* env = AndroidRuntime::getJNIEnv();
166 size_t status_size = sv_status->size;
167 // Check the size, and reject the object that has invalid size.
168 if (status_size != sizeof(GnssSvStatus)) {
169 ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
Lifu Tang30f95a72016-01-07 23:20:38 -0800170 return;
171 }
Lifu Tang120480f2016-02-07 18:08:19 -0800172 sGnssSvListSize = sv_status->num_svs;
173 // Clamp the list size
174 if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
Lifu Tanga2b74fd2016-02-11 12:57:59 -0800175 ALOGD("Too many satellites %zd. Clamps to %d.",
Lifu Tang120480f2016-02-07 18:08:19 -0800176 sGnssSvListSize,
177 GNSS_MAX_SATELLITE_COUNT);
178 sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
179 }
180 // Copy GNSS SV info into sGnssSvList, if any.
181 if (sGnssSvListSize > 0) {
182 memcpy(sGnssSvList,
183 sv_status->gnss_sv_list,
184 sizeof(GnssSvInfo) * sGnssSvListSize);
185 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700186 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
187 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188}
189
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400190static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
191{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700192 JNIEnv* env = AndroidRuntime::getJNIEnv();
193 // The Java code will call back to read these values
194 // We do this to avoid creating unnecessary String objects
195 sNmeaString = nmea;
196 sNmeaStringLength = length;
197 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
198 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400199}
200
Lifu Tang9363b942016-02-16 18:07:00 -0800201static void set_system_info_callback(const GnssSystemInfo* info) {
Lifu Tang82f893d2016-01-21 18:15:33 -0800202 ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
203 JNIEnv* env = AndroidRuntime::getJNIEnv();
Lifu Tang9363b942016-02-16 18:07:00 -0800204 env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
Lifu Tang82f893d2016-01-21 18:15:33 -0800205 info->year_of_hw);
206 checkAndClearExceptionFromCallback(env, __FUNCTION__);
207}
208
Mike Lockwood04598b62010-04-14 17:17:24 -0400209static void set_capabilities_callback(uint32_t capabilities)
210{
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700211 ALOGD("set_capabilities_callback: %du\n", capabilities);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700212 JNIEnv* env = AndroidRuntime::getJNIEnv();
213 env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
214 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood04598b62010-04-14 17:17:24 -0400215}
216
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400217static void acquire_wakelock_callback()
218{
219 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
220}
221
222static void release_wakelock_callback()
223{
224 release_wake_lock(WAKE_LOCK_NAME);
225}
226
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400227static void request_utc_time_callback()
228{
229 JNIEnv* env = AndroidRuntime::getJNIEnv();
230 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
231 checkAndClearExceptionFromCallback(env, __FUNCTION__);
232}
233
Mike Lockwoodf602d362010-06-20 14:28:16 -0700234static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
Mike Lockwood58bda982009-04-14 16:25:07 -0400235{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700236 return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
Mike Lockwood58bda982009-04-14 16:25:07 -0400237}
238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239GpsCallbacks sGpsCallbacks = {
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400240 sizeof(GpsCallbacks),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 location_callback,
242 status_callback,
243 sv_status_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400244 nmea_callback,
Mike Lockwood04598b62010-04-14 17:17:24 -0400245 set_capabilities_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400246 acquire_wakelock_callback,
247 release_wakelock_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700248 create_thread_callback,
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400249 request_utc_time_callback,
Lifu Tang82f893d2016-01-21 18:15:33 -0800250 set_system_info_callback,
Lifu Tang120480f2016-02-07 18:08:19 -0800251 gnss_sv_status_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252};
253
Mike Lockwoodf602d362010-06-20 14:28:16 -0700254static void xtra_download_request_callback()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700256 JNIEnv* env = AndroidRuntime::getJNIEnv();
257 env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
258 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Danke Xie22d1f9f2009-08-18 18:28:45 -0400259}
260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261GpsXtraCallbacks sGpsXtraCallbacks = {
Mike Lockwoodf602d362010-06-20 14:28:16 -0700262 xtra_download_request_callback,
263 create_thread_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264};
265
destradaa96a14702014-06-05 11:36:30 -0700266static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
267{
268 if (INADDR_NONE == ip) {
269 return NULL;
270 }
271
272 JNIEnv* env = AndroidRuntime::getJNIEnv();
273 jbyteArray byteArray = env->NewByteArray(4);
274 if (byteArray == NULL) {
275 ALOGE("Unable to allocate byte array for IPv4 address");
276 return NULL;
277 }
278
279 jbyte ipv4[4];
280 if (net_order) {
destradaa931a37f2014-08-12 16:36:59 -0700281 ALOGV("Converting IPv4 address(net_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700282 memcpy(ipv4, &ip, sizeof(ipv4));
283 } else {
destradaa931a37f2014-08-12 16:36:59 -0700284 ALOGV("Converting IPv4 address(host_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700285 //endianess transparent conversion from int to char[]
286 ipv4[0] = (jbyte) (ip & 0xFF);
287 ipv4[1] = (jbyte)((ip>>8) & 0xFF);
288 ipv4[2] = (jbyte)((ip>>16) & 0xFF);
289 ipv4[3] = (jbyte) (ip>>24);
290 }
291
292 env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
293 return byteArray;
294}
295
Mike Lockwoodf602d362010-06-20 14:28:16 -0700296static void agps_status_callback(AGpsStatus* agps_status)
297{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700298 JNIEnv* env = AndroidRuntime::getJNIEnv();
destradaa96a14702014-06-05 11:36:30 -0700299 jbyteArray byteArray = NULL;
300 bool isSupported = false;
Stephen Li8efd74d2011-03-01 20:56:00 -0800301
destradaa96a14702014-06-05 11:36:30 -0700302 size_t status_size = agps_status->size;
Lifu Tanga8b7bb52016-01-26 01:22:10 -0800303 if (status_size == sizeof(AGpsStatus)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100304 ALOGV("AGpsStatus is V3: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700305 switch (agps_status->addr.ss_family)
306 {
307 case AF_INET:
308 {
309 struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
destradaace48c1c2015-05-29 13:47:39 -0700310 uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
311 byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
312 if (ipAddr == INADDR_NONE || byteArray != NULL) {
destradaa96a14702014-06-05 11:36:30 -0700313 isSupported = true;
314 }
destradaa931a37f2014-08-12 16:36:59 -0700315 IF_ALOGD() {
316 // log the IP for reference in case there is a bogus value pushed by HAL
317 char str[INET_ADDRSTRLEN];
318 inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
319 ALOGD("AGPS IP is v4: %s", str);
320 }
destradaa96a14702014-06-05 11:36:30 -0700321 }
322 break;
323 case AF_INET6:
324 {
325 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
326 byteArray = env->NewByteArray(16);
327 if (byteArray != NULL) {
328 env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
329 isSupported = true;
330 } else {
331 ALOGE("Unable to allocate byte array for IPv6 address.");
332 }
destradaa931a37f2014-08-12 16:36:59 -0700333 IF_ALOGD() {
334 // log the IP for reference in case there is a bogus value pushed by HAL
335 char str[INET6_ADDRSTRLEN];
336 inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
337 ALOGD("AGPS IP is v6: %s", str);
338 }
destradaa96a14702014-06-05 11:36:30 -0700339 }
340 break;
341 default:
342 ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
343 break;
344 }
345 } else if (status_size >= sizeof(AGpsStatus_v2)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100346 ALOGV("AGpsStatus is V2+: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700347 // for back-compatibility reasons we check in v2 that the data structure size is greater or
348 // equal to the declared size in gps.h
349 uint32_t ipaddr = agps_status->ipaddr;
destradaa931a37f2014-08-12 16:36:59 -0700350 ALOGV("AGPS IP is v4: %x", ipaddr);
destradaa96a14702014-06-05 11:36:30 -0700351 byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
352 if (ipaddr == INADDR_NONE || byteArray != NULL) {
353 isSupported = true;
354 }
355 } else if (status_size >= sizeof(AGpsStatus_v1)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100356 ALOGV("AGpsStatus is V1+: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700357 // because we have to check for >= with regards to v2, we also need to relax the check here
358 // and only make sure that the size is at least what we expect
359 isSupported = true;
360 } else {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100361 ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
destradaa96a14702014-06-05 11:36:30 -0700362 }
363
364 if (isSupported) {
destradaa931a37f2014-08-12 16:36:59 -0700365 jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
366 ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
destradaa96a14702014-06-05 11:36:30 -0700367 env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
368 agps_status->status, byteArray);
369
370 checkAndClearExceptionFromCallback(env, __FUNCTION__);
371 } else {
372 ALOGD("Skipping calling method_reportAGpsStatus.");
373 }
374
375 if (byteArray) {
376 env->DeleteLocalRef(byteArray);
377 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700378}
379
Mike Lockwoode3635c92009-05-11 08:38:02 -0400380AGpsCallbacks sAGpsCallbacks = {
381 agps_status_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700382 create_thread_callback,
Mike Lockwood58bda982009-04-14 16:25:07 -0400383};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
Mike Lockwoodf602d362010-06-20 14:28:16 -0700385static void gps_ni_notify_callback(GpsNiNotification *notification)
386{
Steve Block5baa3a62011-12-20 16:23:08 +0000387 ALOGD("gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700388 JNIEnv* env = AndroidRuntime::getJNIEnv();
389 jstring requestor_id = env->NewStringUTF(notification->requestor_id);
390 jstring text = env->NewStringUTF(notification->text);
391 jstring extras = env->NewStringUTF(notification->extras);
392
393 if (requestor_id && text && extras) {
394 env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
395 notification->notification_id, notification->ni_type,
396 notification->notify_flags, notification->timeout,
397 notification->default_response, requestor_id, text,
398 notification->requestor_id_encoding,
399 notification->text_encoding, extras);
400 } else {
Steve Block3762c312012-01-06 19:20:56 +0000401 ALOGE("out of memory in gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700402 }
403
404 if (requestor_id)
405 env->DeleteLocalRef(requestor_id);
406 if (text)
407 env->DeleteLocalRef(text);
408 if (extras)
409 env->DeleteLocalRef(extras);
410 checkAndClearExceptionFromCallback(env, __FUNCTION__);
411}
412
Danke Xie22d1f9f2009-08-18 18:28:45 -0400413GpsNiCallbacks sGpsNiCallbacks = {
414 gps_ni_notify_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700415 create_thread_callback,
Danke Xie22d1f9f2009-08-18 18:28:45 -0400416};
417
Miguel Torroja1e84da82010-07-27 07:02:24 +0200418static void agps_request_set_id(uint32_t flags)
419{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200420 JNIEnv* env = AndroidRuntime::getJNIEnv();
421 env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
422 checkAndClearExceptionFromCallback(env, __FUNCTION__);
423}
424
425static void agps_request_ref_location(uint32_t flags)
426{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200427 JNIEnv* env = AndroidRuntime::getJNIEnv();
428 env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
429 checkAndClearExceptionFromCallback(env, __FUNCTION__);
430}
431
432AGpsRilCallbacks sAGpsRilCallbacks = {
433 agps_request_set_id,
434 agps_request_ref_location,
435 create_thread_callback,
436};
437
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700438static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location,
439 int32_t transition, GpsUtcTime timestamp)
440{
441 JNIEnv* env = AndroidRuntime::getJNIEnv();
442
443 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
444 location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
445 (jdouble)location->altitude,
446 (jfloat)location->speed, (jfloat)location->bearing,
447 (jfloat)location->accuracy, (jlong)location->timestamp,
448 transition, timestamp);
449 checkAndClearExceptionFromCallback(env, __FUNCTION__);
450};
451
452static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
453{
454 JNIEnv* env = AndroidRuntime::getJNIEnv();
455 jint flags = 0;
456 jdouble latitude = 0;
457 jdouble longitude = 0;
458 jdouble altitude = 0;
459 jfloat speed = 0;
460 jfloat bearing = 0;
461 jfloat accuracy = 0;
462 jlong timestamp = 0;
463 if (location != NULL) {
464 flags = location->flags;
465 latitude = location->latitude;
466 longitude = location->longitude;
467 altitude = location->altitude;
468 speed = location->speed;
469 bearing = location->bearing;
470 accuracy = location->accuracy;
471 timestamp = location->timestamp;
472 }
473
474 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
475 flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
476 checkAndClearExceptionFromCallback(env, __FUNCTION__);
477};
478
479static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
480{
481 JNIEnv* env = AndroidRuntime::getJNIEnv();
482 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
483 ALOGE("Error in geofence_add_callback: %d\n", status);
484 }
485 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
486 checkAndClearExceptionFromCallback(env, __FUNCTION__);
487};
488
489static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
490{
491 JNIEnv* env = AndroidRuntime::getJNIEnv();
492 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
493 ALOGE("Error in geofence_remove_callback: %d\n", status);
494 }
495 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
496 checkAndClearExceptionFromCallback(env, __FUNCTION__);
497};
498
499static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
500{
501 JNIEnv* env = AndroidRuntime::getJNIEnv();
502 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
503 ALOGE("Error in geofence_resume_callback: %d\n", status);
504 }
505 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
506 checkAndClearExceptionFromCallback(env, __FUNCTION__);
507};
508
509static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
510{
511 JNIEnv* env = AndroidRuntime::getJNIEnv();
512 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
513 ALOGE("Error in geofence_pause_callback: %d\n", status);
514 }
515 env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
516 checkAndClearExceptionFromCallback(env, __FUNCTION__);
517};
518
519GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
520 gps_geofence_transition_callback,
521 gps_geofence_status_callback,
522 gps_geofence_add_callback,
523 gps_geofence_remove_callback,
524 gps_geofence_pause_callback,
525 gps_geofence_resume_callback,
526 create_thread_callback,
527};
528
Lifu Tang30f95a72016-01-07 23:20:38 -0800529static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400530 int err;
531 hw_module_t* module;
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400532
Mike Lockwoodbea31182010-10-05 14:29:53 -0400533 method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
534 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
535 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
destradaa96a14702014-06-05 11:36:30 -0700536 method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400537 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
538 method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
Lifu Tang9363b942016-02-16 18:07:00 -0800539 method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400540 method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800541 method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
542 "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400543 method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
544 method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400545 method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700546 method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
547 "(IIDDDFFFJIJ)V");
548 method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
549 "(IIDDDFFFJ)V");
550 method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
551 "(II)V");
552 method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
553 "(II)V");
554 method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
555 "(II)V");
556 method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
557 "(II)V");
destradaaea8a8a62014-06-23 18:19:03 -0700558 method_reportMeasurementData = env->GetMethodID(
559 clazz,
560 "reportMeasurementData",
Lifu Tang818aa2c2016-02-01 01:52:00 -0800561 "(Landroid/location/GnssMeasurementsEvent;)V");
destradaa4b3e3932014-07-21 18:01:47 -0700562 method_reportNavigationMessages = env->GetMethodID(
563 clazz,
564 "reportNavigationMessage",
Lifu Tang818aa2c2016-02-01 01:52:00 -0800565 "(Landroid/location/GnssNavigationMessageEvent;)V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800566
567 err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
568 if (err == 0) {
569 hw_device_t* device;
570 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
571 if (err == 0) {
572 gps_device_t* gps_device = (gps_device_t *)device;
573 sGpsInterface = gps_device->get_gps_interface(gps_device);
574 }
575 }
576 if (sGpsInterface) {
577 sGpsXtraInterface =
578 (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
579 sAGpsInterface =
580 (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
581 sGpsNiInterface =
582 (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
583 sGpsDebugInterface =
584 (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
585 sAGpsRilInterface =
586 (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700587 sGpsGeofencingInterface =
588 (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
destradaaea8a8a62014-06-23 18:19:03 -0700589 sGpsMeasurementInterface =
590 (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
destradaa4b3e3932014-07-21 18:01:47 -0700591 sGpsNavigationMessageInterface =
592 (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
593 GPS_NAVIGATION_MESSAGE_INTERFACE);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700594 sGnssConfigurationInterface =
595 (const GnssConfigurationInterface*)sGpsInterface->get_extension(
596 GNSS_CONFIGURATION_INTERFACE);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800597 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400598}
599
Lifu Tang30f95a72016-01-07 23:20:38 -0800600static jboolean android_location_GnssLocationProvider_is_supported(
destradaaef752b62015-04-17 13:10:47 -0700601 JNIEnv* /* env */, jclass /* clazz */)
602{
603 return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE;
604}
605
Lifu Tang30f95a72016-01-07 23:20:38 -0800606static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
destradaaef752b62015-04-17 13:10:47 -0700607 JNIEnv* /* env */, jclass /* clazz */)
608{
609 return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
610}
611
612static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
613 JNIEnv* /* env */, jclass /* jclazz */)
614{
615 return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616}
617
Lifu Tang30f95a72016-01-07 23:20:38 -0800618static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800620 // this must be set before calling into the HAL library
621 if (!mCallbacksObj)
622 mCallbacksObj = env->NewGlobalRef(obj);
623
624 // fail if the main interface fails to initialize
625 if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000626 return JNI_FALSE;
Mike Lockwood58bda982009-04-14 16:25:07 -0400627
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700628 // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800629 // but continue to allow the rest of the GPS interface to work.
630 if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
631 sGpsXtraInterface = NULL;
632 if (sAGpsInterface)
633 sAGpsInterface->init(&sAGpsCallbacks);
634 if (sGpsNiInterface)
635 sGpsNiInterface->init(&sGpsNiCallbacks);
636 if (sAGpsRilInterface)
637 sAGpsRilInterface->init(&sAGpsRilCallbacks);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700638 if (sGpsGeofencingInterface)
639 sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600640
Narayan Kamath87d6cd42014-01-08 12:26:28 +0000641 return JNI_TRUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800642}
643
Lifu Tang30f95a72016-01-07 23:20:38 -0800644static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800646 if (sGpsInterface)
647 sGpsInterface->cleanup();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648}
649
Lifu Tang30f95a72016-01-07 23:20:38 -0800650static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700651 jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
652 jint preferred_time)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000654 if (sGpsInterface) {
655 if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
656 preferred_time) == 0) {
657 return JNI_TRUE;
658 } else {
659 return JNI_FALSE;
660 }
661 }
Mike Lockwood42702372010-10-10 16:04:18 -0400662 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000663 return JNI_FALSE;
Mike Lockwood04598b62010-04-14 17:17:24 -0400664}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665
Lifu Tang30f95a72016-01-07 23:20:38 -0800666static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
Mike Lockwood04598b62010-04-14 17:17:24 -0400667{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000668 if (sGpsInterface) {
669 if (sGpsInterface->start() == 0) {
670 return JNI_TRUE;
671 } else {
672 return JNI_FALSE;
673 }
674 }
Mike Lockwood42702372010-10-10 16:04:18 -0400675 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000676 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677}
678
Lifu Tang30f95a72016-01-07 23:20:38 -0800679static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000681 if (sGpsInterface) {
682 if (sGpsInterface->stop() == 0) {
683 return JNI_TRUE;
684 } else {
685 return JNI_FALSE;
686 }
687 }
Mike Lockwood42702372010-10-10 16:04:18 -0400688 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000689 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690}
691
Lifu Tang30f95a72016-01-07 23:20:38 -0800692static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700693 jobject /* obj */,
694 jint flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800696 if (sGpsInterface)
697 sGpsInterface->delete_aiding_data(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698}
699
Lifu Tang30f95a72016-01-07 23:20:38 -0800700static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
Lifu Tang120480f2016-02-07 18:08:19 -0800701 jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
702 jfloatArray azumArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700704 // this should only be called from within a call to reportSvStatus
Lifu Tang120480f2016-02-07 18:08:19 -0800705 jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
707 jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
708 jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709
Lifu Tang30f95a72016-01-07 23:20:38 -0800710 // GNSS SV info.
711 for (size_t i = 0; i < sGnssSvListSize; ++i) {
712 const GnssSvInfo& info = sGnssSvList[i];
Lifu Tang120480f2016-02-07 18:08:19 -0800713 svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
714 (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
715 info.flags;
Lifu Tang30f95a72016-01-07 23:20:38 -0800716 snrs[i] = info.snr;
717 elev[i] = info.elevation;
718 azim[i] = info.azimuth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720
Lifu Tang120480f2016-02-07 18:08:19 -0800721 env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 env->ReleaseFloatArrayElements(snrArray, snrs, 0);
723 env->ReleaseFloatArrayElements(elevArray, elev, 0);
724 env->ReleaseFloatArrayElements(azumArray, azim, 0);
Lifu Tang30f95a72016-01-07 23:20:38 -0800725 return (jint) sGnssSvListSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726}
727
Lifu Tang30f95a72016-01-07 23:20:38 -0800728static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700729 JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200730{
731 AGpsRefLocation location;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800732
733 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000734 ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200735 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400736 }
737
Miguel Torroja1e84da82010-07-27 07:02:24 +0200738 switch(type) {
739 case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
740 case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
741 location.type = type;
742 location.u.cellID.mcc = mcc;
743 location.u.cellID.mnc = mnc;
744 location.u.cellID.lac = lac;
745 location.u.cellID.cid = cid;
746 break;
747 default:
Steve Block3762c312012-01-06 19:20:56 +0000748 ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200749 return;
750 break;
751 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800752 sAGpsRilInterface->set_ref_location(&location, sizeof(location));
Miguel Torroja1e84da82010-07-27 07:02:24 +0200753}
754
Lifu Tang30f95a72016-01-07 23:20:38 -0800755static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700756 jobject /* obj */, jbyteArray ni_msg, jint size)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200757{
758 size_t sz;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800759
760 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000761 ALOGE("no AGPS RIL interface in send_ni_message");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200762 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400763 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200764 if (size < 0)
765 return;
766 sz = (size_t)size;
767 jbyte* b = env->GetByteArrayElements(ni_msg, 0);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800768 sAGpsRilInterface->ni_message((uint8_t *)b,sz);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200769 env->ReleaseByteArrayElements(ni_msg,b,0);
770}
771
Lifu Tang30f95a72016-01-07 23:20:38 -0800772static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700773 jint type, jstring setid_string)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200774{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800775 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000776 ALOGE("no AGPS RIL interface in agps_set_id");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200777 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400778 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200779
780 const char *setid = env->GetStringUTFChars(setid_string, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800781 sAGpsRilInterface->set_set_id(type, setid);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200782 env->ReleaseStringUTFChars(setid_string, setid);
783}
784
Lifu Tang30f95a72016-01-07 23:20:38 -0800785static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700786 jbyteArray nmeaArray, jint buffer_size)
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400787{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700788 // this should only be called from within a call to reportNmea
789 jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
790 int length = sNmeaStringLength;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400791 if (length > buffer_size)
792 length = buffer_size;
Mike Lockwoodf602d362010-06-20 14:28:16 -0700793 memcpy(nmea, sNmeaString, length);
794 env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000795 return (jint) length;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400796}
797
Lifu Tang30f95a72016-01-07 23:20:38 -0800798static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700799 jlong time, jlong timeReference, jint uncertainty)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800801 if (sGpsInterface)
802 sGpsInterface->inject_time(time, timeReference, uncertainty);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803}
804
Lifu Tang30f95a72016-01-07 23:20:38 -0800805static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700806 jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400807{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800808 if (sGpsInterface)
809 sGpsInterface->inject_location(latitude, longitude, accuracy);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400810}
811
Lifu Tang30f95a72016-01-07 23:20:38 -0800812static jboolean android_location_GnssLocationProvider_supports_xtra(
destradaaef752b62015-04-17 13:10:47 -0700813 JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814{
destradaaef752b62015-04-17 13:10:47 -0700815 return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816}
817
Lifu Tang30f95a72016-01-07 23:20:38 -0800818static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 jbyteArray data, jint length)
820{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800821 if (!sGpsXtraInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000822 ALOGE("no XTRA interface in inject_xtra_data");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800823 return;
824 }
825
Mike Lockwoodf602d362010-06-20 14:28:16 -0700826 jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700828 env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829}
830
Lifu Tang30f95a72016-01-07 23:20:38 -0800831static void android_location_GnssLocationProvider_agps_data_conn_open(
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700832 JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
The Android Open Source Project10592532009-03-18 17:39:46 -0700833{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800834 if (!sAGpsInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000835 ALOGE("no AGPS interface in agps_data_conn_open");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400836 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700837 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400838 if (apn == NULL) {
839 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
840 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700841 }
destradaa96a14702014-06-05 11:36:30 -0700842
Mike Lockwoodbea31182010-10-05 14:29:53 -0400843 const char *apnStr = env->GetStringUTFChars(apn, NULL);
destradaa96a14702014-06-05 11:36:30 -0700844
845 size_t interface_size = sAGpsInterface->size;
Lifu Tanga8b7bb52016-01-26 01:22:10 -0800846 if (interface_size == sizeof(AGpsInterface)) {
destradaa96a14702014-06-05 11:36:30 -0700847 sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
848 } else if (interface_size == sizeof(AGpsInterface_v1)) {
849 sAGpsInterface->data_conn_open(apnStr);
850 } else {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100851 ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
destradaa96a14702014-06-05 11:36:30 -0700852 }
853
Mike Lockwoodbea31182010-10-05 14:29:53 -0400854 env->ReleaseStringUTFChars(apn, apnStr);
The Android Open Source Project10592532009-03-18 17:39:46 -0700855}
856
Lifu Tang30f95a72016-01-07 23:20:38 -0800857static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700858 jobject /* obj */)
Mike Lockwood58bda982009-04-14 16:25:07 -0400859{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800860 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100861 ALOGE("no AGPS interface in agps_data_conn_closed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400862 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400863 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800864 sAGpsInterface->data_conn_closed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400865}
866
Lifu Tang30f95a72016-01-07 23:20:38 -0800867static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700868 jobject /* obj */)
Mike Lockwood58bda982009-04-14 16:25:07 -0400869{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800870 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100871 ALOGE("no AGPS interface in agps_data_conn_failed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400872 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400873 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800874 sAGpsInterface->data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400875}
876
Lifu Tang30f95a72016-01-07 23:20:38 -0800877static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
Mike Lockwooda9e54612009-06-19 14:54:42 -0400878 jint type, jstring hostname, jint port)
Mike Lockwood58bda982009-04-14 16:25:07 -0400879{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800880 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100881 ALOGE("no AGPS interface in set_agps_server");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400882 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400883 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400884 const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800885 sAGpsInterface->set_server(type, c_hostname, port);
Mike Lockwoodbea31182010-10-05 14:29:53 -0400886 env->ReleaseStringUTFChars(hostname, c_hostname);
Mike Lockwood58bda982009-04-14 16:25:07 -0400887}
888
Lifu Tang30f95a72016-01-07 23:20:38 -0800889static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700890 jobject /* obj */, jint notifId, jint response)
Danke Xie22d1f9f2009-08-18 18:28:45 -0400891{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800892 if (!sGpsNiInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000893 ALOGE("no NI interface in send_ni_response");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400894 return;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600895 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400896
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800897 sGpsNiInterface->respond(notifId, response);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600898}
899
Lifu Tang30f95a72016-01-07 23:20:38 -0800900static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700901 jobject /* obj */) {
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600902 jstring result = NULL;
903 if (sGpsDebugInterface) {
904 const size_t maxLength = 2047;
905 char buffer[maxLength+1];
906 size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
907 if (length > maxLength) length = maxLength;
908 buffer[length] = 0;
909 result = env->NewStringUTF(buffer);
910 }
911 return result;
Danke Xie22d1f9f2009-08-18 18:28:45 -0400912}
913
Lifu Tang30f95a72016-01-07 23:20:38 -0800914static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000915 jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
Mike Lockwood50130bb2010-10-11 06:22:50 -0400916{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800917
918 if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
Mike Lockwood50130bb2010-10-11 06:22:50 -0400919 if (extraInfo) {
920 const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800921 sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400922 env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
923 } else {
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800924 sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400925 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700926
927 // update_network_availability callback was not included in original AGpsRilInterface
928 if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
929 && sAGpsRilInterface->update_network_availability) {
930 const char *c_apn = env->GetStringUTFChars(apn, NULL);
931 sAGpsRilInterface->update_network_availability(available, c_apn);
932 env->ReleaseStringUTFChars(apn, c_apn);
933 }
Mike Lockwood50130bb2010-10-11 06:22:50 -0400934 }
935}
936
Lifu Tang30f95a72016-01-07 23:20:38 -0800937static jboolean android_location_GnssLocationProvider_is_geofence_supported(
destradaaef752b62015-04-17 13:10:47 -0700938 JNIEnv* /* env */, jobject /* obj */)
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700939{
destradaaef752b62015-04-17 13:10:47 -0700940 return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700941}
942
Lifu Tang30f95a72016-01-07 23:20:38 -0800943static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700944 jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700945 jint last_transition, jint monitor_transition, jint notification_responsiveness,
946 jint unknown_timer) {
947 if (sGpsGeofencingInterface != NULL) {
948 sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
949 radius, last_transition, monitor_transition, notification_responsiveness,
950 unknown_timer);
951 return JNI_TRUE;
952 } else {
953 ALOGE("Geofence interface not available");
954 }
955 return JNI_FALSE;
956}
957
Lifu Tang30f95a72016-01-07 23:20:38 -0800958static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700959 jobject /* obj */, jint geofence_id) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700960 if (sGpsGeofencingInterface != NULL) {
961 sGpsGeofencingInterface->remove_geofence_area(geofence_id);
962 return JNI_TRUE;
963 } else {
964 ALOGE("Geofence interface not available");
965 }
966 return JNI_FALSE;
967}
968
Lifu Tang30f95a72016-01-07 23:20:38 -0800969static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700970 jobject /* obj */, jint geofence_id) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700971 if (sGpsGeofencingInterface != NULL) {
972 sGpsGeofencingInterface->pause_geofence(geofence_id);
973 return JNI_TRUE;
974 } else {
975 ALOGE("Geofence interface not available");
976 }
977 return JNI_FALSE;
978}
979
Lifu Tang30f95a72016-01-07 23:20:38 -0800980static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700981 jobject /* obj */, jint geofence_id, jint monitor_transition) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700982 if (sGpsGeofencingInterface != NULL) {
983 sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
984 return JNI_TRUE;
985 } else {
986 ALOGE("Geofence interface not available");
987 }
988 return JNI_FALSE;
989}
990
Lifu Tang120480f2016-02-07 18:08:19 -0800991template<class T>
992class JavaMethodHelper {
993 public:
994 // Helper function to call setter on a Java object.
995 static void callJavaMethod(
996 JNIEnv* env,
997 jclass clazz,
998 jobject object,
999 const char* method_name,
1000 T value);
destradaaea8a8a62014-06-23 18:19:03 -07001001
Lifu Tang120480f2016-02-07 18:08:19 -08001002 private:
1003 static const char *const signature_;
1004};
Lifu Tange5a0e212016-01-25 18:02:17 -08001005
Lifu Tang120480f2016-02-07 18:08:19 -08001006template<class T>
1007void JavaMethodHelper<T>::callJavaMethod(
1008 JNIEnv* env,
1009 jclass clazz,
1010 jobject object,
1011 const char* method_name,
1012 T value) {
1013 jmethodID method = env->GetMethodID(clazz, method_name, signature_);
1014 env->CallVoidMethod(object, method, value);
1015}
destradaaea8a8a62014-06-23 18:19:03 -07001016
Lifu Tang120480f2016-02-07 18:08:19 -08001017class JavaObject {
1018 public:
1019 JavaObject(JNIEnv* env, const char* class_name);
1020 virtual ~JavaObject();
1021
1022 template<class T>
1023 void callSetter(const char* method_name, T value);
1024 template<class T>
1025 void callSetter(const char* method_name, T* value, size_t size);
1026 jobject get();
1027
1028 private:
1029 JNIEnv* env_;
1030 jclass clazz_;
1031 jobject object_;
1032};
1033
1034JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
1035 clazz_ = env_->FindClass(class_name);
1036 jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
1037 object_ = env_->NewObject(clazz_, ctor);
1038}
1039
1040JavaObject::~JavaObject() {
1041 env_->DeleteLocalRef(clazz_);
1042}
1043
1044template<class T>
1045void JavaObject::callSetter(const char* method_name, T value) {
1046 JavaMethodHelper<T>::callJavaMethod(
1047 env_, clazz_, object_, method_name, value);
1048}
1049
1050template<>
1051void JavaObject::callSetter(
1052 const char* method_name, uint8_t* value, size_t size) {
1053 jbyteArray array = env_->NewByteArray(size);
1054 env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
1055 jmethodID method = env_->GetMethodID(
1056 clazz_,
1057 method_name,
1058 "([B)V");
1059 env_->CallVoidMethod(object_, method, array);
1060}
1061
1062jobject JavaObject::get() {
1063 return object_;
1064}
1065
1066// Define Java method signatures for all known types.
1067
1068template<>
1069const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
1070template<>
1071const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
1072template<>
1073const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
1074template<>
1075const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
1076template<>
Lifu Tang9363b942016-02-16 18:07:00 -08001077const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
1078template<>
1079const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
Lifu Tang120480f2016-02-07 18:08:19 -08001080template<>
1081const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
1082template<>
1083const char *const JavaMethodHelper<float>::signature_ = "(F)V";
1084template<>
1085const char *const JavaMethodHelper<double>::signature_ = "(D)V";
1086template<>
1087const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
1088
1089#define SET(setter, value) object.callSetter("set" # setter, (value))
1090#define SET_IF(flag, setter, value) \
1091 if (flags & (flag)) object.callSetter("set" # setter, (value))
1092
1093static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
Lifu Tang38bce792016-02-24 17:17:38 -08001094 static uint32_t discontinuity_count_to_handle_old_lock_type = 0;
Lifu Tang120480f2016-02-07 18:08:19 -08001095 JavaObject object(env, "android/location/GnssClock");
destradaaea8a8a62014-06-23 18:19:03 -07001096 GpsClockFlags flags = clock->flags;
1097
Lifu Tang9363b942016-02-16 18:07:00 -08001098 SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
Lifu Tang38bce792016-02-24 17:17:38 -08001099
1100 // GnssClock only supports the more effective HW_CLOCK type, so type
1101 // handling and documentation complexity has been removed. To convert the
1102 // old GPS_CLOCK types (active only in a limited number of older devices),
1103 // the GPS time information is handled as an always discontinuous HW clock,
1104 // with the GPS time information put into the full_bias_ns instead - so that
1105 // time_ns + full_bias_ns = local estimate of GPS time (as remains true, in
1106 // the new GnssClock struct.)
1107 switch (clock->type) {
1108 case GPS_CLOCK_TYPE_UNKNOWN:
1109 // Clock type unsupported.
1110 ALOGE("Unknown clock type provided.");
1111 break;
1112 case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
1113 // Already local hardware time. No need to do anything.
1114 break;
1115 case GPS_CLOCK_TYPE_GPS_TIME:
1116 // GPS time, need to convert.
1117 flags |= GNSS_CLOCK_HAS_FULL_BIAS;
1118 clock->full_bias_ns = clock->time_ns;
1119 clock->time_ns = 0;
1120 SET(HardwareClockDiscontinuityCount,
1121 discontinuity_count_to_handle_old_lock_type++);
1122 break;
1123 }
1124
Lifu Tang120480f2016-02-07 18:08:19 -08001125 SET(TimeInNs, clock->time_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001126 SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001127 TimeUncertaintyInNs,
1128 clock->time_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001129 SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
1130 SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
1131 SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001132 BiasUncertaintyInNs,
1133 clock->bias_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001134 SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
1135 SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001136 DriftUncertaintyInNsPerSec,
1137 clock->drift_uncertainty_nsps);
destradaaea8a8a62014-06-23 18:19:03 -07001138
Lifu Tang120480f2016-02-07 18:08:19 -08001139 return object.get();
destradaaea8a8a62014-06-23 18:19:03 -07001140}
1141
Lifu Tang120480f2016-02-07 18:08:19 -08001142static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
1143 JavaObject object(env, "android/location/GnssClock");
1144 GpsClockFlags flags = clock->flags;
destradaaea8a8a62014-06-23 18:19:03 -07001145
Lifu Tang9363b942016-02-16 18:07:00 -08001146 SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
1147 SET(Type, static_cast<uint8_t>(GPS_CLOCK_TYPE_LOCAL_HW_TIME));
Lifu Tang120480f2016-02-07 18:08:19 -08001148 SET(TimeInNs, clock->time_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001149 SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001150 TimeUncertaintyInNs,
1151 clock->time_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001152 SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
1153 SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
1154 SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001155 BiasUncertaintyInNs,
1156 clock->bias_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001157 SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
1158 SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001159 DriftUncertaintyInNsPerSec,
1160 clock->drift_uncertainty_nsps);
destradaaea8a8a62014-06-23 18:19:03 -07001161
Lifu Tang9363b942016-02-16 18:07:00 -08001162 SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
Lifu Tang120480f2016-02-07 18:08:19 -08001163
1164 return object.get();
1165}
1166
1167static jobject translate_gps_measurement(JNIEnv* env,
1168 GpsMeasurement* measurement) {
1169 JavaObject object(env, "android/location/GnssMeasurement");
destradaaea8a8a62014-06-23 18:19:03 -07001170 GpsMeasurementFlags flags = measurement->flags;
Lifu Tang120480f2016-02-07 18:08:19 -08001171 SET(Svid, static_cast<int16_t>(measurement->prn));
Lifu Tang9363b942016-02-16 18:07:00 -08001172 if (measurement->prn >= 1 || measurement->prn <= 32) {
1173 SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
1174 } else {
1175 ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
1176 SET(ConstellationType,
1177 static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
1178 }
Lifu Tang120480f2016-02-07 18:08:19 -08001179 SET(TimeOffsetInNs, measurement->time_offset_ns);
1180 SET(State, measurement->state);
Lifu Tang9363b942016-02-16 18:07:00 -08001181 SET(ReceivedSvTimeInNs, measurement->received_gps_tow_ns);
1182 SET(ReceivedSvTimeUncertaintyInNs,
Lifu Tang120480f2016-02-07 18:08:19 -08001183 measurement->received_gps_tow_uncertainty_ns);
1184 SET(Cn0InDbHz, measurement->c_n0_dbhz);
1185 SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
1186 SET(PseudorangeRateUncertaintyInMetersPerSec,
1187 measurement->pseudorange_rate_uncertainty_mps);
1188 SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
1189 SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
1190 SET(AccumulatedDeltaRangeUncertaintyInMeters,
1191 measurement->accumulated_delta_range_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001192 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
Lifu Tang120480f2016-02-07 18:08:19 -08001193 PseudorangeInMeters,
1194 measurement->pseudorange_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001195 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001196 PseudorangeUncertaintyInMeters,
1197 measurement->pseudorange_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001198 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001199 CodePhaseInChips,
1200 measurement->code_phase_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001201 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001202 CodePhaseUncertaintyInChips,
1203 measurement->code_phase_uncertainty_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001204 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
Lifu Tang120480f2016-02-07 18:08:19 -08001205 CarrierFrequencyInHz,
1206 measurement->carrier_frequency_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001207 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
Lifu Tang120480f2016-02-07 18:08:19 -08001208 CarrierCycles,
1209 measurement->carrier_cycles);
Lifu Tang9363b942016-02-16 18:07:00 -08001210 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001211 CarrierPhase,
1212 measurement->carrier_phase);
Lifu Tang9363b942016-02-16 18:07:00 -08001213 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001214 CarrierPhaseUncertainty,
1215 measurement->carrier_phase_uncertainty);
1216 SET(LossOfLock, measurement->loss_of_lock);
Lifu Tang9363b942016-02-16 18:07:00 -08001217 SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
1218 SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
Lifu Tang120480f2016-02-07 18:08:19 -08001219 TimeFromLastBitInMs,
1220 measurement->time_from_last_bit_ms);
Lifu Tang9363b942016-02-16 18:07:00 -08001221 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
Lifu Tang120480f2016-02-07 18:08:19 -08001222 DopplerShiftInHz,
1223 measurement->doppler_shift_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001224 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001225 DopplerShiftUncertaintyInHz,
1226 measurement->doppler_shift_uncertainty_hz);
1227 SET(MultipathIndicator, measurement->multipath_indicator);
Lifu Tang9363b942016-02-16 18:07:00 -08001228 SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
1229 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
Lifu Tang120480f2016-02-07 18:08:19 -08001230 ElevationInDeg,
1231 measurement->elevation_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001232 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001233 ElevationUncertaintyInDeg,
1234 measurement->elevation_uncertainty_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001235 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
Lifu Tang120480f2016-02-07 18:08:19 -08001236 AzimuthInDeg,
1237 measurement->azimuth_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001238 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001239 AzimuthUncertaintyInDeg,
1240 measurement->azimuth_uncertainty_deg);
1241 SET(UsedInFix,
Lifu Tang9363b942016-02-16 18:07:00 -08001242 (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
destradaaea8a8a62014-06-23 18:19:03 -07001243
Lifu Tang120480f2016-02-07 18:08:19 -08001244 return object.get();
destradaaea8a8a62014-06-23 18:19:03 -07001245}
1246
Lifu Tang120480f2016-02-07 18:08:19 -08001247static jobject translate_gnss_measurement(JNIEnv* env,
1248 GnssMeasurement* measurement) {
1249 JavaObject object(env, "android/location/GnssMeasurement");
1250 GpsMeasurementFlags flags = measurement->flags;
1251
1252 SET(Svid, measurement->svid);
Lifu Tang9363b942016-02-16 18:07:00 -08001253 SET(ConstellationType, measurement->constellation);
Lifu Tang120480f2016-02-07 18:08:19 -08001254 SET(TimeOffsetInNs, measurement->time_offset_ns);
1255 SET(State, measurement->state);
Lifu Tang9363b942016-02-16 18:07:00 -08001256 SET(ReceivedSvTimeInNs, measurement->received_sv_time_in_ns);
1257 SET(ReceivedSvTimeUncertaintyInNs,
1258 measurement->received_sv_time_uncertainty_in_ns);
Lifu Tang120480f2016-02-07 18:08:19 -08001259 SET(Cn0InDbHz, measurement->c_n0_dbhz);
1260 SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
1261 SET(PseudorangeRateUncertaintyInMetersPerSec,
1262 measurement->pseudorange_rate_uncertainty_mps);
1263 SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
1264 SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
1265 SET(AccumulatedDeltaRangeUncertaintyInMeters,
1266 measurement->accumulated_delta_range_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001267 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
Lifu Tang120480f2016-02-07 18:08:19 -08001268 PseudorangeInMeters,
1269 measurement->pseudorange_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001270 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001271 PseudorangeUncertaintyInMeters,
1272 measurement->pseudorange_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001273 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001274 CodePhaseInChips,
1275 measurement->code_phase_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001276 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001277 CodePhaseUncertaintyInChips,
1278 measurement->code_phase_uncertainty_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001279 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
Lifu Tang120480f2016-02-07 18:08:19 -08001280 CarrierFrequencyInHz,
1281 measurement->carrier_frequency_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001282 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
Lifu Tang120480f2016-02-07 18:08:19 -08001283 CarrierCycles,
1284 measurement->carrier_cycles);
Lifu Tang9363b942016-02-16 18:07:00 -08001285 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001286 CarrierPhase,
1287 measurement->carrier_phase);
Lifu Tang9363b942016-02-16 18:07:00 -08001288 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001289 CarrierPhaseUncertainty,
1290 measurement->carrier_phase_uncertainty);
Lifu Tang9363b942016-02-16 18:07:00 -08001291 SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
1292 SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
Lifu Tang120480f2016-02-07 18:08:19 -08001293 TimeFromLastBitInMs,
1294 measurement->time_from_last_bit_ms);
Lifu Tang9363b942016-02-16 18:07:00 -08001295 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
Lifu Tang120480f2016-02-07 18:08:19 -08001296 DopplerShiftInHz,
1297 measurement->doppler_shift_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001298 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001299 DopplerShiftUncertaintyInHz,
1300 measurement->doppler_shift_uncertainty_hz);
1301 SET(MultipathIndicator, measurement->multipath_indicator);
Lifu Tang9363b942016-02-16 18:07:00 -08001302 SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
1303 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
Lifu Tang120480f2016-02-07 18:08:19 -08001304 ElevationInDeg,
1305 measurement->elevation_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001306 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001307 ElevationUncertaintyInDeg,
1308 measurement->elevation_uncertainty_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001309 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
Lifu Tang120480f2016-02-07 18:08:19 -08001310 AzimuthInDeg,
1311 measurement->azimuth_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001312 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001313 AzimuthUncertaintyInDeg,
1314 measurement->azimuth_uncertainty_deg);
1315 SET(UsedInFix,
Lifu Tang9363b942016-02-16 18:07:00 -08001316 (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
Lifu Tang120480f2016-02-07 18:08:19 -08001317
1318 return object.get();
1319}
1320
1321static jobjectArray translate_gps_measurements(JNIEnv* env,
1322 GpsMeasurement* measurements,
1323 size_t count) {
1324 if (count == 0) {
destradaaea8a8a62014-06-23 18:19:03 -07001325 return NULL;
1326 }
1327
Lifu Tang120480f2016-02-07 18:08:19 -08001328 jclass gnssMeasurementClass = env->FindClass(
1329 "android/location/GnssMeasurement");
Lifu Tang818aa2c2016-02-01 01:52:00 -08001330 jobjectArray gnssMeasurementArray = env->NewObjectArray(
Lifu Tang120480f2016-02-07 18:08:19 -08001331 count,
Lifu Tang818aa2c2016-02-01 01:52:00 -08001332 gnssMeasurementClass,
destradaaea8a8a62014-06-23 18:19:03 -07001333 NULL /* initialElement */);
1334
Lifu Tang120480f2016-02-07 18:08:19 -08001335 for (uint16_t i = 0; i < count; ++i) {
Lifu Tang818aa2c2016-02-01 01:52:00 -08001336 jobject gnssMeasurement = translate_gps_measurement(
Lifu Tange5a0e212016-01-25 18:02:17 -08001337 env,
Lifu Tang120480f2016-02-07 18:08:19 -08001338 &measurements[i]);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001339 env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1340 env->DeleteLocalRef(gnssMeasurement);
destradaaea8a8a62014-06-23 18:19:03 -07001341 }
1342
Lifu Tang818aa2c2016-02-01 01:52:00 -08001343 env->DeleteLocalRef(gnssMeasurementClass);
1344 return gnssMeasurementArray;
destradaaea8a8a62014-06-23 18:19:03 -07001345}
1346
Lifu Tang120480f2016-02-07 18:08:19 -08001347static jobjectArray translate_gnss_measurements(JNIEnv* env,
1348 GnssMeasurement* measurements,
1349 size_t count) {
1350 if (count == 0) {
1351 return NULL;
destradaaea8a8a62014-06-23 18:19:03 -07001352 }
Lifu Tange5a0e212016-01-25 18:02:17 -08001353
Lifu Tang120480f2016-02-07 18:08:19 -08001354 jclass gnssMeasurementClass = env->FindClass(
1355 "android/location/GnssMeasurement");
1356 jobjectArray gnssMeasurementArray = env->NewObjectArray(
1357 count,
1358 gnssMeasurementClass,
1359 NULL /* initialElement */);
1360
1361 for (uint16_t i = 0; i < count; ++i) {
1362 jobject gnssMeasurement = translate_gnss_measurement(
1363 env,
1364 &measurements[i]);
1365 env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1366 env->DeleteLocalRef(gnssMeasurement);
Lifu Tange5a0e212016-01-25 18:02:17 -08001367 }
Lifu Tang120480f2016-02-07 18:08:19 -08001368
1369 env->DeleteLocalRef(gnssMeasurementClass);
1370 return gnssMeasurementArray;
1371}
1372
1373static void set_measurement_data(JNIEnv *env,
1374 jobject clock,
1375 jobjectArray measurementArray) {
1376 jclass gnssMeasurementsEventClass = env->FindClass(
1377 "android/location/GnssMeasurementsEvent");
Lifu Tang818aa2c2016-02-01 01:52:00 -08001378 jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
1379 gnssMeasurementsEventClass,
Lifu Tange5a0e212016-01-25 18:02:17 -08001380 "<init>",
Lifu Tang818aa2c2016-02-01 01:52:00 -08001381 "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
Lifu Tange5a0e212016-01-25 18:02:17 -08001382
Lifu Tang818aa2c2016-02-01 01:52:00 -08001383 jobject gnssMeasurementsEvent = env->NewObject(
1384 gnssMeasurementsEventClass,
1385 gnssMeasurementsEventCtor,
Lifu Tang120480f2016-02-07 18:08:19 -08001386 clock,
Lifu Tange5a0e212016-01-25 18:02:17 -08001387 measurementArray);
Lifu Tang120480f2016-02-07 18:08:19 -08001388 env->CallVoidMethod(mCallbacksObj,
1389 method_reportMeasurementData,
1390 gnssMeasurementsEvent);
Lifu Tange5a0e212016-01-25 18:02:17 -08001391 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001392 env->DeleteLocalRef(gnssMeasurementsEventClass);
1393 env->DeleteLocalRef(gnssMeasurementsEvent);
destradaaea8a8a62014-06-23 18:19:03 -07001394}
1395
Lifu Tang120480f2016-02-07 18:08:19 -08001396static void measurement_callback(GpsData* data) {
1397 JNIEnv* env = AndroidRuntime::getJNIEnv();
1398 if (data == NULL) {
1399 ALOGE("Invalid data provided to gps_measurement_callback");
1400 return;
1401 }
1402 if (data->size != sizeof(GpsData)) {
1403 ALOGE("Invalid GpsData size found in gps_measurement_callback, "
1404 "size=%zd",
1405 data->size);
1406 return;
1407 }
1408
1409 jobject clock;
1410 jobjectArray measurementArray;
1411 clock = translate_gps_clock(env, &data->clock);
1412 measurementArray = translate_gps_measurements(
1413 env, data->measurements, data->measurement_count);
1414 set_measurement_data(env, clock, measurementArray);
1415
1416 env->DeleteLocalRef(clock);
1417 env->DeleteLocalRef(measurementArray);
1418}
1419
1420static void gnss_measurement_callback(GnssData* data) {
1421 JNIEnv* env = AndroidRuntime::getJNIEnv();
1422 if (data == NULL) {
1423 ALOGE("Invalid data provided to gps_measurement_callback");
1424 return;
1425 }
1426 if (data->size != sizeof(GpsData)) {
1427 ALOGE("Invalid GpsData size found in gps_measurement_callback, "
1428 "size=%zd",
1429 data->size);
1430 return;
1431 }
1432
1433 jobject clock;
1434 jobjectArray measurementArray;
1435 clock = translate_gnss_clock(env, &data->clock);
1436 measurementArray = translate_gnss_measurements(
1437 env, data->measurements, data->measurement_count);
1438 set_measurement_data(env, clock, measurementArray);
1439
1440 env->DeleteLocalRef(clock);
1441 env->DeleteLocalRef(measurementArray);
1442}
1443
destradaaea8a8a62014-06-23 18:19:03 -07001444GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
1445 sizeof(GpsMeasurementCallbacks),
1446 measurement_callback,
Lifu Tang120480f2016-02-07 18:08:19 -08001447 gnss_measurement_callback,
destradaaea8a8a62014-06-23 18:19:03 -07001448};
1449
Lifu Tang30f95a72016-01-07 23:20:38 -08001450static jboolean android_location_GnssLocationProvider_is_measurement_supported(
destradaaea8a8a62014-06-23 18:19:03 -07001451 JNIEnv* env,
destradaa4b3e3932014-07-21 18:01:47 -07001452 jclass clazz) {
destradaaea8a8a62014-06-23 18:19:03 -07001453 if (sGpsMeasurementInterface != NULL) {
1454 return JNI_TRUE;
1455 }
1456 return JNI_FALSE;
1457}
1458
Lifu Tang30f95a72016-01-07 23:20:38 -08001459static jboolean android_location_GnssLocationProvider_start_measurement_collection(
destradaaea8a8a62014-06-23 18:19:03 -07001460 JNIEnv* env,
1461 jobject obj) {
1462 if (sGpsMeasurementInterface == NULL) {
1463 ALOGE("Measurement interface is not available.");
1464 return JNI_FALSE;
1465 }
1466
1467 int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
1468 if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
1469 ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
1470 return JNI_FALSE;
1471 }
1472
1473 return JNI_TRUE;
1474}
1475
Lifu Tang30f95a72016-01-07 23:20:38 -08001476static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
destradaaea8a8a62014-06-23 18:19:03 -07001477 JNIEnv* env,
1478 jobject obj) {
1479 if (sGpsMeasurementInterface == NULL) {
1480 ALOGE("Measurement interface not available");
1481 return JNI_FALSE;
1482 }
1483
1484 sGpsMeasurementInterface->close();
1485 return JNI_TRUE;
1486}
1487
destradaa4b3e3932014-07-21 18:01:47 -07001488static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
1489 size_t dataLength = message->data_length;
1490 uint8_t* data = message->data;
1491 if (dataLength == 0 || data == NULL) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +01001492 ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
destradaa4b3e3932014-07-21 18:01:47 -07001493 return NULL;
1494 }
Lifu Tang120480f2016-02-07 18:08:19 -08001495 JavaObject object(env, "android/location/GnssNavigationMessage");
Lifu Tang120480f2016-02-07 18:08:19 -08001496 SET(Svid, static_cast<int16_t>(message->prn));
Lifu Tang9363b942016-02-16 18:07:00 -08001497 if (message->prn >=1 && message->prn <= 32) {
1498 SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
1499 // Legacy driver doesn't set the higher byte to constellation type
1500 // correctly. Set the higher byte to 'GPS'.
1501 SET(Type, static_cast<int16_t>(message->type | 0x0100));
1502 } else {
1503 ALOGD("Unknown constellation type with Svid = %d.", message->prn);
1504 SET(ConstellationType,
1505 static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
1506 SET(Type, static_cast<int16_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
1507 }
Lifu Tang120480f2016-02-07 18:08:19 -08001508 SET(MessageId, message->message_id);
1509 SET(SubmessageId, message->submessage_id);
1510 object.callSetter("setData", data, dataLength);
1511 return object.get();
1512}
destradaa4b3e3932014-07-21 18:01:47 -07001513
Lifu Tang120480f2016-02-07 18:08:19 -08001514static jobject translate_gnss_navigation_message(
1515 JNIEnv* env, GnssNavigationMessage* message) {
1516 size_t dataLength = message->data_length;
1517 uint8_t* data = message->data;
1518 if (dataLength == 0 || data == NULL) {
1519 ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
1520 return NULL;
1521 }
1522 JavaObject object(env, "android/location/GnssNavigationMessage");
1523 SET(Type, message->type);
1524 SET(Svid, message->svid);
1525 SET(MessageId, message->message_id);
1526 SET(SubmessageId, message->submessage_id);
1527 object.callSetter("setData", data, dataLength);
1528 return object.get();
1529}
destradaa4b3e3932014-07-21 18:01:47 -07001530
Lifu Tang120480f2016-02-07 18:08:19 -08001531static void set_navigation_message(jobject navigationMessage) {
1532 JNIEnv* env = AndroidRuntime::getJNIEnv();
1533 jclass navigationMessageEventClass =
1534 env->FindClass("android/location/GnssNavigationMessageEvent");
1535 jmethodID navigationMessageEventCtor = env->GetMethodID(
1536 navigationMessageEventClass,
1537 "<init>",
1538 "(Landroid/location/GnssNavigationMessage;)V");
1539 jobject navigationMessageEvent = env->NewObject(
1540 navigationMessageEventClass,
1541 navigationMessageEventCtor,
1542 navigationMessage);
1543 env->CallVoidMethod(mCallbacksObj,
1544 method_reportNavigationMessages,
1545 navigationMessageEvent);
1546 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1547 env->DeleteLocalRef(navigationMessageEventClass);
1548 env->DeleteLocalRef(navigationMessageEvent);
destradaa4b3e3932014-07-21 18:01:47 -07001549}
1550
1551static void navigation_message_callback(GpsNavigationMessage* message) {
destradaa4b3e3932014-07-21 18:01:47 -07001552 if (message == NULL) {
1553 ALOGE("Invalid Navigation Message provided to callback");
1554 return;
1555 }
Lifu Tang120480f2016-02-07 18:08:19 -08001556 if (message->size != sizeof(GpsNavigationMessage)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +01001557 ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
Lifu Tang120480f2016-02-07 18:08:19 -08001558 return;
destradaa4b3e3932014-07-21 18:01:47 -07001559 }
Lifu Tang120480f2016-02-07 18:08:19 -08001560 JNIEnv* env = AndroidRuntime::getJNIEnv();
1561 jobject navigationMessage = translate_gps_navigation_message(env, message);
1562 set_navigation_message(navigationMessage);
1563 env->DeleteLocalRef(navigationMessage);
1564}
1565
1566static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
1567 if (message == NULL) {
1568 ALOGE("Invalid Navigation Message provided to callback");
1569 return;
1570 }
1571 if (message->size != sizeof(GnssNavigationMessage)) {
1572 ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
1573 return;
1574 }
1575 JNIEnv* env = AndroidRuntime::getJNIEnv();
1576 jobject navigationMessage = translate_gnss_navigation_message(env, message);
1577 set_navigation_message(navigationMessage);
1578 env->DeleteLocalRef(navigationMessage);
destradaa4b3e3932014-07-21 18:01:47 -07001579}
1580
1581GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
1582 sizeof(GpsNavigationMessageCallbacks),
1583 navigation_message_callback,
Lifu Tang120480f2016-02-07 18:08:19 -08001584 gnss_navigation_message_callback,
destradaa4b3e3932014-07-21 18:01:47 -07001585};
1586
Lifu Tang30f95a72016-01-07 23:20:38 -08001587static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
destradaa4b3e3932014-07-21 18:01:47 -07001588 JNIEnv* env,
1589 jclass clazz) {
1590 if(sGpsNavigationMessageInterface != NULL) {
1591 return JNI_TRUE;
1592 }
1593 return JNI_FALSE;
1594}
1595
Lifu Tang30f95a72016-01-07 23:20:38 -08001596static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
destradaa4b3e3932014-07-21 18:01:47 -07001597 JNIEnv* env,
1598 jobject obj) {
1599 if (sGpsNavigationMessageInterface == NULL) {
1600 ALOGE("Navigation Message interface is not available.");
1601 return JNI_FALSE;
1602 }
1603
1604 int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
1605 if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
1606 ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
1607 return JNI_FALSE;
1608 }
1609
1610 return JNI_TRUE;
1611}
1612
Lifu Tang30f95a72016-01-07 23:20:38 -08001613static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
destradaa4b3e3932014-07-21 18:01:47 -07001614 JNIEnv* env,
1615 jobject obj) {
1616 if (sGpsNavigationMessageInterface == NULL) {
1617 ALOGE("Navigation Message interface is not available.");
1618 return JNI_FALSE;
1619 }
1620
1621 sGpsNavigationMessageInterface->close();
1622 return JNI_TRUE;
1623}
1624
Lifu Tang30f95a72016-01-07 23:20:38 -08001625static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001626 jstring config_content)
1627{
1628 if (!sGnssConfigurationInterface) {
1629 ALOGE("no GPS configuration interface in configuraiton_update");
1630 return;
1631 }
1632 const char *data = env->GetStringUTFChars(config_content, NULL);
1633 ALOGD("GPS configuration:\n %s", data);
1634 sGnssConfigurationInterface->configuration_update(
1635 data, env->GetStringUTFLength(config_content));
1636 env->ReleaseStringUTFChars(config_content, data);
1637}
1638
Daniel Micay76f6a862015-09-19 17:31:01 -04001639static const JNINativeMethod sMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 /* name, signature, funcPtr */
Lifu Tang30f95a72016-01-07 23:20:38 -08001641 {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
1642 {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
destradaaef752b62015-04-17 13:10:47 -07001643 {"native_is_agps_ril_supported", "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001644 (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
destradaaef752b62015-04-17 13:10:47 -07001645 {"native_is_gnss_configuration_supported", "()Z",
1646 (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
Lifu Tang30f95a72016-01-07 23:20:38 -08001647 {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
1648 {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
destradaaea8a8a62014-06-23 18:19:03 -07001649 {"native_set_position_mode",
1650 "(IIIII)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001651 (void*)android_location_GnssLocationProvider_set_position_mode},
1652 {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
1653 {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
destradaaea8a8a62014-06-23 18:19:03 -07001654 {"native_delete_aiding_data",
1655 "(I)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001656 (void*)android_location_GnssLocationProvider_delete_aiding_data},
destradaaea8a8a62014-06-23 18:19:03 -07001657 {"native_read_sv_status",
Lifu Tang120480f2016-02-07 18:08:19 -08001658 "([I[F[F[F)I",
Lifu Tang30f95a72016-01-07 23:20:38 -08001659 (void*)android_location_GnssLocationProvider_read_sv_status},
1660 {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
1661 {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
destradaaea8a8a62014-06-23 18:19:03 -07001662 {"native_inject_location",
1663 "(DDF)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001664 (void*)android_location_GnssLocationProvider_inject_location},
1665 {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
destradaaea8a8a62014-06-23 18:19:03 -07001666 {"native_inject_xtra_data",
1667 "([BI)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001668 (void*)android_location_GnssLocationProvider_inject_xtra_data},
destradaaea8a8a62014-06-23 18:19:03 -07001669 {"native_agps_data_conn_open",
1670 "(Ljava/lang/String;I)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001671 (void*)android_location_GnssLocationProvider_agps_data_conn_open},
destradaaea8a8a62014-06-23 18:19:03 -07001672 {"native_agps_data_conn_closed",
1673 "()V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001674 (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
destradaaea8a8a62014-06-23 18:19:03 -07001675 {"native_agps_data_conn_failed",
1676 "()V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001677 (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
destradaaea8a8a62014-06-23 18:19:03 -07001678 {"native_agps_set_id",
1679 "(ILjava/lang/String;)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001680 (void*)android_location_GnssLocationProvider_agps_set_id},
destradaaea8a8a62014-06-23 18:19:03 -07001681 {"native_agps_set_ref_location_cellid",
1682 "(IIIII)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001683 (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
destradaaea8a8a62014-06-23 18:19:03 -07001684 {"native_set_agps_server",
1685 "(ILjava/lang/String;I)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001686 (void*)android_location_GnssLocationProvider_set_agps_server},
destradaaea8a8a62014-06-23 18:19:03 -07001687 {"native_send_ni_response",
1688 "(II)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001689 (void*)android_location_GnssLocationProvider_send_ni_response},
destradaaea8a8a62014-06-23 18:19:03 -07001690 {"native_agps_ni_message",
1691 "([BI)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001692 (void *)android_location_GnssLocationProvider_agps_send_ni_message},
destradaaea8a8a62014-06-23 18:19:03 -07001693 {"native_get_internal_state",
1694 "()Ljava/lang/String;",
Lifu Tang30f95a72016-01-07 23:20:38 -08001695 (void*)android_location_GnssLocationProvider_get_internal_state},
destradaaea8a8a62014-06-23 18:19:03 -07001696 {"native_update_network_state",
1697 "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001698 (void*)android_location_GnssLocationProvider_update_network_state },
destradaaea8a8a62014-06-23 18:19:03 -07001699 {"native_is_geofence_supported",
1700 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001701 (void*) android_location_GnssLocationProvider_is_geofence_supported},
destradaaea8a8a62014-06-23 18:19:03 -07001702 {"native_add_geofence",
1703 "(IDDDIIII)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001704 (void *)android_location_GnssLocationProvider_add_geofence},
destradaaea8a8a62014-06-23 18:19:03 -07001705 {"native_remove_geofence",
1706 "(I)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001707 (void *)android_location_GnssLocationProvider_remove_geofence},
1708 {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
destradaaea8a8a62014-06-23 18:19:03 -07001709 {"native_resume_geofence",
1710 "(II)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001711 (void *)android_location_GnssLocationProvider_resume_geofence},
destradaaea8a8a62014-06-23 18:19:03 -07001712 {"native_is_measurement_supported",
1713 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001714 (void*) android_location_GnssLocationProvider_is_measurement_supported},
destradaaea8a8a62014-06-23 18:19:03 -07001715 {"native_start_measurement_collection",
1716 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001717 (void*) android_location_GnssLocationProvider_start_measurement_collection},
destradaaea8a8a62014-06-23 18:19:03 -07001718 {"native_stop_measurement_collection",
1719 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001720 (void*) android_location_GnssLocationProvider_stop_measurement_collection},
destradaa4b3e3932014-07-21 18:01:47 -07001721 {"native_is_navigation_message_supported",
1722 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001723 (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
destradaa4b3e3932014-07-21 18:01:47 -07001724 {"native_start_navigation_message_collection",
1725 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001726 (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
destradaa4b3e3932014-07-21 18:01:47 -07001727 {"native_stop_navigation_message_collection",
1728 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001729 (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001730 {"native_configuration_update",
1731 "(Ljava/lang/String;)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001732 (void*)android_location_GnssLocationProvider_configuration_update},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733};
1734
Lifu Tang30f95a72016-01-07 23:20:38 -08001735int register_android_server_location_GnssLocationProvider(JNIEnv* env)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736{
destradaaea8a8a62014-06-23 18:19:03 -07001737 return jniRegisterNativeMethods(
1738 env,
Lifu Tang30f95a72016-01-07 23:20:38 -08001739 "com/android/server/location/GnssLocationProvider",
destradaaea8a8a62014-06-23 18:19:03 -07001740 sMethods,
1741 NELEM(sMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742}
1743
1744} /* namespace android */