blob: c39890806788ffbe25aa273b2a54181d24bf84e5 [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
17#define LOG_TAG "GpsLocationProvider"
18
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"
24#include "hardware/gps.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>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032#include <string.h>
33#include <pthread.h>
destradaa96a14702014-06-05 11:36:30 -070034#include <linux/in.h>
35#include <linux/in6.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036
Mike Lockwoodf602d362010-06-20 14:28:16 -070037static jobject mCallbacksObj = NULL;
38
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039static jmethodID method_reportLocation;
40static jmethodID method_reportStatus;
41static jmethodID method_reportSvStatus;
Mike Lockwoode3635c92009-05-11 08:38:02 -040042static jmethodID method_reportAGpsStatus;
Mike Lockwoodb16e7802009-08-06 09:26:02 -040043static jmethodID method_reportNmea;
Mike Lockwood04598b62010-04-14 17:17:24 -040044static jmethodID method_setEngineCapabilities;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045static jmethodID method_xtraDownloadRequest;
Danke Xie22d1f9f2009-08-18 18:28:45 -040046static jmethodID method_reportNiNotification;
Miguel Torroja1e84da82010-07-27 07:02:24 +020047static jmethodID method_requestRefLocation;
48static jmethodID method_requestSetID;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -040049static jmethodID method_requestUtcTime;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070050static jmethodID method_reportGeofenceTransition;
51static jmethodID method_reportGeofenceStatus;
52static jmethodID method_reportGeofenceAddStatus;
53static jmethodID method_reportGeofenceRemoveStatus;
54static jmethodID method_reportGeofencePauseStatus;
55static jmethodID method_reportGeofenceResumeStatus;
destradaaea8a8a62014-06-23 18:19:03 -070056static jmethodID method_reportMeasurementData;
destradaa4b3e3932014-07-21 18:01:47 -070057static jmethodID method_reportNavigationMessages;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59static const GpsInterface* sGpsInterface = NULL;
60static const GpsXtraInterface* sGpsXtraInterface = NULL;
Mike Lockwoode3635c92009-05-11 08:38:02 -040061static const AGpsInterface* sAGpsInterface = NULL;
Danke Xie22d1f9f2009-08-18 18:28:45 -040062static const GpsNiInterface* sGpsNiInterface = NULL;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -060063static const GpsDebugInterface* sGpsDebugInterface = NULL;
Miguel Torroja1e84da82010-07-27 07:02:24 +020064static const AGpsRilInterface* sAGpsRilInterface = NULL;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070065static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
destradaaea8a8a62014-06-23 18:19:03 -070066static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
destradaa4b3e3932014-07-21 18:01:47 -070067static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068
Mike Lockwoodf602d362010-06-20 14:28:16 -070069// temporary storage for GPS callbacks
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070static GpsSvStatus sGpsSvStatus;
Mike Lockwoodf602d362010-06-20 14:28:16 -070071static const char* sNmeaString;
72static int sNmeaStringLength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073
Mike Lockwood8f5a8002010-04-07 09:05:26 -040074#define WAKE_LOCK_NAME "GPS"
75
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076namespace android {
77
Mike Lockwoodf602d362010-06-20 14:28:16 -070078static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
79 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +000080 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwoodf602d362010-06-20 14:28:16 -070081 LOGE_EX(env);
82 env->ExceptionClear();
83 }
84}
85
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086static void location_callback(GpsLocation* location)
87{
Mike Lockwoodf602d362010-06-20 14:28:16 -070088 JNIEnv* env = AndroidRuntime::getJNIEnv();
89 env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
90 (jdouble)location->latitude, (jdouble)location->longitude,
91 (jdouble)location->altitude,
92 (jfloat)location->speed, (jfloat)location->bearing,
93 (jfloat)location->accuracy, (jlong)location->timestamp);
94 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095}
96
97static void status_callback(GpsStatus* status)
98{
Mike Lockwoodf602d362010-06-20 14:28:16 -070099 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf602d362010-06-20 14:28:16 -0700100 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
101 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102}
103
104static void sv_status_callback(GpsSvStatus* sv_status)
105{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700106 JNIEnv* env = AndroidRuntime::getJNIEnv();
107 memcpy(&sGpsSvStatus, sv_status, sizeof(sGpsSvStatus));
108 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
109 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110}
111
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400112static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
113{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700114 JNIEnv* env = AndroidRuntime::getJNIEnv();
115 // The Java code will call back to read these values
116 // We do this to avoid creating unnecessary String objects
117 sNmeaString = nmea;
118 sNmeaStringLength = length;
119 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
120 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400121}
122
Mike Lockwood04598b62010-04-14 17:17:24 -0400123static void set_capabilities_callback(uint32_t capabilities)
124{
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700125 ALOGD("set_capabilities_callback: %du\n", capabilities);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700126 JNIEnv* env = AndroidRuntime::getJNIEnv();
127 env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
128 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood04598b62010-04-14 17:17:24 -0400129}
130
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400131static void acquire_wakelock_callback()
132{
133 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
134}
135
136static void release_wakelock_callback()
137{
138 release_wake_lock(WAKE_LOCK_NAME);
139}
140
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400141static void request_utc_time_callback()
142{
143 JNIEnv* env = AndroidRuntime::getJNIEnv();
144 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
145 checkAndClearExceptionFromCallback(env, __FUNCTION__);
146}
147
Mike Lockwoodf602d362010-06-20 14:28:16 -0700148static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
Mike Lockwood58bda982009-04-14 16:25:07 -0400149{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700150 return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
Mike Lockwood58bda982009-04-14 16:25:07 -0400151}
152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153GpsCallbacks sGpsCallbacks = {
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400154 sizeof(GpsCallbacks),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 location_callback,
156 status_callback,
157 sv_status_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400158 nmea_callback,
Mike Lockwood04598b62010-04-14 17:17:24 -0400159 set_capabilities_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400160 acquire_wakelock_callback,
161 release_wakelock_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700162 create_thread_callback,
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400163 request_utc_time_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164};
165
Mike Lockwoodf602d362010-06-20 14:28:16 -0700166static void xtra_download_request_callback()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700168 JNIEnv* env = AndroidRuntime::getJNIEnv();
169 env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
170 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Danke Xie22d1f9f2009-08-18 18:28:45 -0400171}
172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173GpsXtraCallbacks sGpsXtraCallbacks = {
Mike Lockwoodf602d362010-06-20 14:28:16 -0700174 xtra_download_request_callback,
175 create_thread_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176};
177
destradaa96a14702014-06-05 11:36:30 -0700178static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
179{
180 if (INADDR_NONE == ip) {
181 return NULL;
182 }
183
184 JNIEnv* env = AndroidRuntime::getJNIEnv();
185 jbyteArray byteArray = env->NewByteArray(4);
186 if (byteArray == NULL) {
187 ALOGE("Unable to allocate byte array for IPv4 address");
188 return NULL;
189 }
190
191 jbyte ipv4[4];
192 if (net_order) {
destradaa931a37f2014-08-12 16:36:59 -0700193 ALOGV("Converting IPv4 address(net_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700194 memcpy(ipv4, &ip, sizeof(ipv4));
195 } else {
destradaa931a37f2014-08-12 16:36:59 -0700196 ALOGV("Converting IPv4 address(host_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700197 //endianess transparent conversion from int to char[]
198 ipv4[0] = (jbyte) (ip & 0xFF);
199 ipv4[1] = (jbyte)((ip>>8) & 0xFF);
200 ipv4[2] = (jbyte)((ip>>16) & 0xFF);
201 ipv4[3] = (jbyte) (ip>>24);
202 }
203
204 env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
205 return byteArray;
206}
207
Mike Lockwoodf602d362010-06-20 14:28:16 -0700208static void agps_status_callback(AGpsStatus* agps_status)
209{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700210 JNIEnv* env = AndroidRuntime::getJNIEnv();
destradaa96a14702014-06-05 11:36:30 -0700211 jbyteArray byteArray = NULL;
212 bool isSupported = false;
Stephen Li8efd74d2011-03-01 20:56:00 -0800213
destradaa96a14702014-06-05 11:36:30 -0700214 size_t status_size = agps_status->size;
215 if (status_size == sizeof(AGpsStatus_v3)) {
destradaa931a37f2014-08-12 16:36:59 -0700216 ALOGV("AGpsStatus is V3: %d", status_size);
destradaa96a14702014-06-05 11:36:30 -0700217 switch (agps_status->addr.ss_family)
218 {
219 case AF_INET:
220 {
221 struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
222 uint32_t *pAddr = (uint32_t*)&(in->sin_addr);
223 byteArray = convert_to_ipv4(*pAddr, true /* net_order */);
224 if (byteArray != NULL) {
225 isSupported = true;
226 }
destradaa931a37f2014-08-12 16:36:59 -0700227 IF_ALOGD() {
228 // log the IP for reference in case there is a bogus value pushed by HAL
229 char str[INET_ADDRSTRLEN];
230 inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
231 ALOGD("AGPS IP is v4: %s", str);
232 }
destradaa96a14702014-06-05 11:36:30 -0700233 }
234 break;
235 case AF_INET6:
236 {
237 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
238 byteArray = env->NewByteArray(16);
239 if (byteArray != NULL) {
240 env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
241 isSupported = true;
242 } else {
243 ALOGE("Unable to allocate byte array for IPv6 address.");
244 }
destradaa931a37f2014-08-12 16:36:59 -0700245 IF_ALOGD() {
246 // log the IP for reference in case there is a bogus value pushed by HAL
247 char str[INET6_ADDRSTRLEN];
248 inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
249 ALOGD("AGPS IP is v6: %s", str);
250 }
destradaa96a14702014-06-05 11:36:30 -0700251 }
252 break;
253 default:
254 ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
255 break;
256 }
257 } else if (status_size >= sizeof(AGpsStatus_v2)) {
destradaa931a37f2014-08-12 16:36:59 -0700258 ALOGV("AGpsStatus is V2+: %d", status_size);
destradaa96a14702014-06-05 11:36:30 -0700259 // for back-compatibility reasons we check in v2 that the data structure size is greater or
260 // equal to the declared size in gps.h
261 uint32_t ipaddr = agps_status->ipaddr;
destradaa931a37f2014-08-12 16:36:59 -0700262 ALOGV("AGPS IP is v4: %x", ipaddr);
destradaa96a14702014-06-05 11:36:30 -0700263 byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
264 if (ipaddr == INADDR_NONE || byteArray != NULL) {
265 isSupported = true;
266 }
267 } else if (status_size >= sizeof(AGpsStatus_v1)) {
destradaa931a37f2014-08-12 16:36:59 -0700268 ALOGV("AGpsStatus is V1+: %d", status_size);
destradaa96a14702014-06-05 11:36:30 -0700269 // because we have to check for >= with regards to v2, we also need to relax the check here
270 // and only make sure that the size is at least what we expect
271 isSupported = true;
272 } else {
273 ALOGE("Invalid size of AGpsStatus found: %d.", status_size);
274 }
275
276 if (isSupported) {
destradaa931a37f2014-08-12 16:36:59 -0700277 jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
278 ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
destradaa96a14702014-06-05 11:36:30 -0700279 env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
280 agps_status->status, byteArray);
281
282 checkAndClearExceptionFromCallback(env, __FUNCTION__);
283 } else {
284 ALOGD("Skipping calling method_reportAGpsStatus.");
285 }
286
287 if (byteArray) {
288 env->DeleteLocalRef(byteArray);
289 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700290}
291
Mike Lockwoode3635c92009-05-11 08:38:02 -0400292AGpsCallbacks sAGpsCallbacks = {
293 agps_status_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700294 create_thread_callback,
Mike Lockwood58bda982009-04-14 16:25:07 -0400295};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296
Mike Lockwoodf602d362010-06-20 14:28:16 -0700297static void gps_ni_notify_callback(GpsNiNotification *notification)
298{
Steve Block5baa3a62011-12-20 16:23:08 +0000299 ALOGD("gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700300 JNIEnv* env = AndroidRuntime::getJNIEnv();
301 jstring requestor_id = env->NewStringUTF(notification->requestor_id);
302 jstring text = env->NewStringUTF(notification->text);
303 jstring extras = env->NewStringUTF(notification->extras);
304
305 if (requestor_id && text && extras) {
306 env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
307 notification->notification_id, notification->ni_type,
308 notification->notify_flags, notification->timeout,
309 notification->default_response, requestor_id, text,
310 notification->requestor_id_encoding,
311 notification->text_encoding, extras);
312 } else {
Steve Block3762c312012-01-06 19:20:56 +0000313 ALOGE("out of memory in gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700314 }
315
316 if (requestor_id)
317 env->DeleteLocalRef(requestor_id);
318 if (text)
319 env->DeleteLocalRef(text);
320 if (extras)
321 env->DeleteLocalRef(extras);
322 checkAndClearExceptionFromCallback(env, __FUNCTION__);
323}
324
Danke Xie22d1f9f2009-08-18 18:28:45 -0400325GpsNiCallbacks sGpsNiCallbacks = {
326 gps_ni_notify_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700327 create_thread_callback,
Danke Xie22d1f9f2009-08-18 18:28:45 -0400328};
329
Miguel Torroja1e84da82010-07-27 07:02:24 +0200330static void agps_request_set_id(uint32_t flags)
331{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200332 JNIEnv* env = AndroidRuntime::getJNIEnv();
333 env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
334 checkAndClearExceptionFromCallback(env, __FUNCTION__);
335}
336
337static void agps_request_ref_location(uint32_t flags)
338{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200339 JNIEnv* env = AndroidRuntime::getJNIEnv();
340 env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
341 checkAndClearExceptionFromCallback(env, __FUNCTION__);
342}
343
344AGpsRilCallbacks sAGpsRilCallbacks = {
345 agps_request_set_id,
346 agps_request_ref_location,
347 create_thread_callback,
348};
349
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700350static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location,
351 int32_t transition, GpsUtcTime timestamp)
352{
353 JNIEnv* env = AndroidRuntime::getJNIEnv();
354
355 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
356 location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
357 (jdouble)location->altitude,
358 (jfloat)location->speed, (jfloat)location->bearing,
359 (jfloat)location->accuracy, (jlong)location->timestamp,
360 transition, timestamp);
361 checkAndClearExceptionFromCallback(env, __FUNCTION__);
362};
363
364static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
365{
366 JNIEnv* env = AndroidRuntime::getJNIEnv();
367 jint flags = 0;
368 jdouble latitude = 0;
369 jdouble longitude = 0;
370 jdouble altitude = 0;
371 jfloat speed = 0;
372 jfloat bearing = 0;
373 jfloat accuracy = 0;
374 jlong timestamp = 0;
375 if (location != NULL) {
376 flags = location->flags;
377 latitude = location->latitude;
378 longitude = location->longitude;
379 altitude = location->altitude;
380 speed = location->speed;
381 bearing = location->bearing;
382 accuracy = location->accuracy;
383 timestamp = location->timestamp;
384 }
385
386 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
387 flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
388 checkAndClearExceptionFromCallback(env, __FUNCTION__);
389};
390
391static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
392{
393 JNIEnv* env = AndroidRuntime::getJNIEnv();
394 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
395 ALOGE("Error in geofence_add_callback: %d\n", status);
396 }
397 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
398 checkAndClearExceptionFromCallback(env, __FUNCTION__);
399};
400
401static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
402{
403 JNIEnv* env = AndroidRuntime::getJNIEnv();
404 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
405 ALOGE("Error in geofence_remove_callback: %d\n", status);
406 }
407 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
408 checkAndClearExceptionFromCallback(env, __FUNCTION__);
409};
410
411static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
412{
413 JNIEnv* env = AndroidRuntime::getJNIEnv();
414 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
415 ALOGE("Error in geofence_resume_callback: %d\n", status);
416 }
417 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
418 checkAndClearExceptionFromCallback(env, __FUNCTION__);
419};
420
421static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
422{
423 JNIEnv* env = AndroidRuntime::getJNIEnv();
424 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
425 ALOGE("Error in geofence_pause_callback: %d\n", status);
426 }
427 env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
428 checkAndClearExceptionFromCallback(env, __FUNCTION__);
429};
430
431GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
432 gps_geofence_transition_callback,
433 gps_geofence_status_callback,
434 gps_geofence_add_callback,
435 gps_geofence_remove_callback,
436 gps_geofence_pause_callback,
437 gps_geofence_resume_callback,
438 create_thread_callback,
439};
440
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800441static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400442 int err;
443 hw_module_t* module;
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400444
Mike Lockwoodbea31182010-10-05 14:29:53 -0400445 method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
446 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
447 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
destradaa96a14702014-06-05 11:36:30 -0700448 method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400449 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
450 method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
451 method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800452 method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
453 "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400454 method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
455 method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400456 method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700457 method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
458 "(IIDDDFFFJIJ)V");
459 method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
460 "(IIDDDFFFJ)V");
461 method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
462 "(II)V");
463 method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
464 "(II)V");
465 method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
466 "(II)V");
467 method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
468 "(II)V");
destradaaea8a8a62014-06-23 18:19:03 -0700469 method_reportMeasurementData = env->GetMethodID(
470 clazz,
471 "reportMeasurementData",
472 "(Landroid/location/GpsMeasurementsEvent;)V");
destradaa4b3e3932014-07-21 18:01:47 -0700473 method_reportNavigationMessages = env->GetMethodID(
474 clazz,
475 "reportNavigationMessage",
476 "(Landroid/location/GpsNavigationMessageEvent;)V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800477
478 err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
479 if (err == 0) {
480 hw_device_t* device;
481 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
482 if (err == 0) {
483 gps_device_t* gps_device = (gps_device_t *)device;
484 sGpsInterface = gps_device->get_gps_interface(gps_device);
485 }
486 }
487 if (sGpsInterface) {
488 sGpsXtraInterface =
489 (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
490 sAGpsInterface =
491 (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
492 sGpsNiInterface =
493 (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
494 sGpsDebugInterface =
495 (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
496 sAGpsRilInterface =
497 (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700498 sGpsGeofencingInterface =
499 (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
destradaaea8a8a62014-06-23 18:19:03 -0700500 sGpsMeasurementInterface =
501 (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
destradaa4b3e3932014-07-21 18:01:47 -0700502 sGpsNavigationMessageInterface =
503 (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
504 GPS_NAVIGATION_MESSAGE_INTERFACE);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800505 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400506}
507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000509 if (sGpsInterface != NULL) {
510 return JNI_TRUE;
511 } else {
512 return JNI_FALSE;
513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514}
515
516static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
517{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800518 // this must be set before calling into the HAL library
519 if (!mCallbacksObj)
520 mCallbacksObj = env->NewGlobalRef(obj);
521
522 // fail if the main interface fails to initialize
523 if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000524 return JNI_FALSE;
Mike Lockwood58bda982009-04-14 16:25:07 -0400525
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700526 // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800527 // but continue to allow the rest of the GPS interface to work.
528 if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
529 sGpsXtraInterface = NULL;
530 if (sAGpsInterface)
531 sAGpsInterface->init(&sAGpsCallbacks);
532 if (sGpsNiInterface)
533 sGpsNiInterface->init(&sGpsNiCallbacks);
534 if (sAGpsRilInterface)
535 sAGpsRilInterface->init(&sAGpsRilCallbacks);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700536 if (sGpsGeofencingInterface)
537 sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600538
Narayan Kamath87d6cd42014-01-08 12:26:28 +0000539 return JNI_TRUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540}
541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542static void android_location_GpsLocationProvider_cleanup(JNIEnv* env, jobject obj)
543{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800544 if (sGpsInterface)
545 sGpsInterface->cleanup();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546}
547
Mike Lockwood04598b62010-04-14 17:17:24 -0400548static jboolean android_location_GpsLocationProvider_set_position_mode(JNIEnv* env, jobject obj,
549 jint mode, jint recurrence, jint min_interval, jint preferred_accuracy, jint preferred_time)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000551 if (sGpsInterface) {
552 if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
553 preferred_time) == 0) {
554 return JNI_TRUE;
555 } else {
556 return JNI_FALSE;
557 }
558 }
Mike Lockwood42702372010-10-10 16:04:18 -0400559 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000560 return JNI_FALSE;
Mike Lockwood04598b62010-04-14 17:17:24 -0400561}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562
Mike Lockwood04598b62010-04-14 17:17:24 -0400563static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj)
564{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000565 if (sGpsInterface) {
566 if (sGpsInterface->start() == 0) {
567 return JNI_TRUE;
568 } else {
569 return JNI_FALSE;
570 }
571 }
Mike Lockwood42702372010-10-10 16:04:18 -0400572 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000573 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574}
575
576static jboolean android_location_GpsLocationProvider_stop(JNIEnv* env, jobject obj)
577{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000578 if (sGpsInterface) {
579 if (sGpsInterface->stop() == 0) {
580 return JNI_TRUE;
581 } else {
582 return JNI_FALSE;
583 }
584 }
Mike Lockwood42702372010-10-10 16:04:18 -0400585 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000586 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587}
588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* env, jobject obj, jint flags)
590{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800591 if (sGpsInterface)
592 sGpsInterface->delete_aiding_data(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593}
594
Danke Xie22d1f9f2009-08-18 18:28:45 -0400595static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj,
596 jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 jintArray maskArray)
598{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700599 // this should only be called from within a call to reportSvStatus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600
601 jint* prns = env->GetIntArrayElements(prnArray, 0);
602 jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
603 jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
604 jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
605 jint* mask = env->GetIntArrayElements(maskArray, 0);
606
Mike Lockwoodf602d362010-06-20 14:28:16 -0700607 int num_svs = sGpsSvStatus.num_svs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 for (int i = 0; i < num_svs; i++) {
Mike Lockwoodf602d362010-06-20 14:28:16 -0700609 prns[i] = sGpsSvStatus.sv_list[i].prn;
610 snrs[i] = sGpsSvStatus.sv_list[i].snr;
611 elev[i] = sGpsSvStatus.sv_list[i].elevation;
612 azim[i] = sGpsSvStatus.sv_list[i].azimuth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700614 mask[0] = sGpsSvStatus.ephemeris_mask;
615 mask[1] = sGpsSvStatus.almanac_mask;
616 mask[2] = sGpsSvStatus.used_in_fix_mask;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617
618 env->ReleaseIntArrayElements(prnArray, prns, 0);
619 env->ReleaseFloatArrayElements(snrArray, snrs, 0);
620 env->ReleaseFloatArrayElements(elevArray, elev, 0);
621 env->ReleaseFloatArrayElements(azumArray, azim, 0);
622 env->ReleaseIntArrayElements(maskArray, mask, 0);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000623 return (jint) num_svs;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624}
625
Miguel Torroja1e84da82010-07-27 07:02:24 +0200626static void android_location_GpsLocationProvider_agps_set_reference_location_cellid(JNIEnv* env,
627 jobject obj, jint type, jint mcc, jint mnc, jint lac, jint cid)
628{
629 AGpsRefLocation location;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800630
631 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000632 ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200633 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400634 }
635
Miguel Torroja1e84da82010-07-27 07:02:24 +0200636 switch(type) {
637 case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
638 case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
639 location.type = type;
640 location.u.cellID.mcc = mcc;
641 location.u.cellID.mnc = mnc;
642 location.u.cellID.lac = lac;
643 location.u.cellID.cid = cid;
644 break;
645 default:
Steve Block3762c312012-01-06 19:20:56 +0000646 ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200647 return;
648 break;
649 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800650 sAGpsRilInterface->set_ref_location(&location, sizeof(location));
Miguel Torroja1e84da82010-07-27 07:02:24 +0200651}
652
653static void android_location_GpsLocationProvider_agps_send_ni_message(JNIEnv* env,
654 jobject obj, jbyteArray ni_msg, jint size)
655{
656 size_t sz;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800657
658 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000659 ALOGE("no AGPS RIL interface in send_ni_message");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200660 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400661 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200662 if (size < 0)
663 return;
664 sz = (size_t)size;
665 jbyte* b = env->GetByteArrayElements(ni_msg, 0);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800666 sAGpsRilInterface->ni_message((uint8_t *)b,sz);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200667 env->ReleaseByteArrayElements(ni_msg,b,0);
668}
669
670static void android_location_GpsLocationProvider_agps_set_id(JNIEnv *env,
671 jobject obj, jint type, jstring setid_string)
672{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800673 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000674 ALOGE("no AGPS RIL interface in agps_set_id");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200675 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400676 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200677
678 const char *setid = env->GetStringUTFChars(setid_string, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800679 sAGpsRilInterface->set_set_id(type, setid);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200680 env->ReleaseStringUTFChars(setid_string, setid);
681}
682
Mike Lockwoodf602d362010-06-20 14:28:16 -0700683static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject obj,
684 jbyteArray nmeaArray, jint buffer_size)
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400685{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700686 // this should only be called from within a call to reportNmea
687 jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
688 int length = sNmeaStringLength;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400689 if (length > buffer_size)
690 length = buffer_size;
Mike Lockwoodf602d362010-06-20 14:28:16 -0700691 memcpy(nmea, sNmeaString, length);
692 env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000693 return (jint) length;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400694}
695
Mike Lockwoodf602d362010-06-20 14:28:16 -0700696static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobject obj,
697 jlong time, jlong timeReference, jint uncertainty)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800699 if (sGpsInterface)
700 sGpsInterface->inject_time(time, timeReference, uncertainty);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701}
702
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400703static void android_location_GpsLocationProvider_inject_location(JNIEnv* env, jobject obj,
704 jdouble latitude, jdouble longitude, jfloat accuracy)
705{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800706 if (sGpsInterface)
707 sGpsInterface->inject_location(latitude, longitude, accuracy);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400708}
709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710static jboolean android_location_GpsLocationProvider_supports_xtra(JNIEnv* env, jobject obj)
711{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000712 if (sGpsXtraInterface != NULL) {
713 return JNI_TRUE;
714 } else {
715 return JNI_FALSE;
716 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717}
718
Danke Xie22d1f9f2009-08-18 18:28:45 -0400719static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, jobject obj,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 jbyteArray data, jint length)
721{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800722 if (!sGpsXtraInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000723 ALOGE("no XTRA interface in inject_xtra_data");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800724 return;
725 }
726
Mike Lockwoodf602d362010-06-20 14:28:16 -0700727 jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700729 env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730}
731
destradaa96a14702014-06-05 11:36:30 -0700732static void android_location_GpsLocationProvider_agps_data_conn_open(
733 JNIEnv* env, jobject obj, jstring apn, jint apnIpType)
The Android Open Source Project10592532009-03-18 17:39:46 -0700734{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800735 if (!sAGpsInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000736 ALOGE("no AGPS interface in agps_data_conn_open");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400737 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700738 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400739 if (apn == NULL) {
740 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
741 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700742 }
destradaa96a14702014-06-05 11:36:30 -0700743
Mike Lockwoodbea31182010-10-05 14:29:53 -0400744 const char *apnStr = env->GetStringUTFChars(apn, NULL);
destradaa96a14702014-06-05 11:36:30 -0700745
746 size_t interface_size = sAGpsInterface->size;
747 if (interface_size == sizeof(AGpsInterface_v2)) {
748 sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
749 } else if (interface_size == sizeof(AGpsInterface_v1)) {
750 sAGpsInterface->data_conn_open(apnStr);
751 } else {
752 ALOGE("Invalid size of AGpsInterface found: %d.", interface_size);
753 }
754
Mike Lockwoodbea31182010-10-05 14:29:53 -0400755 env->ReleaseStringUTFChars(apn, apnStr);
The Android Open Source Project10592532009-03-18 17:39:46 -0700756}
757
Mike Lockwoode3635c92009-05-11 08:38:02 -0400758static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* env, jobject obj)
Mike Lockwood58bda982009-04-14 16:25:07 -0400759{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800760 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100761 ALOGE("no AGPS interface in agps_data_conn_closed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400762 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400763 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800764 sAGpsInterface->data_conn_closed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400765}
766
Mike Lockwoode3635c92009-05-11 08:38:02 -0400767static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* env, jobject obj)
Mike Lockwood58bda982009-04-14 16:25:07 -0400768{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800769 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100770 ALOGE("no AGPS interface in agps_data_conn_failed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400771 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400772 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800773 sAGpsInterface->data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400774}
775
Mike Lockwoode3635c92009-05-11 08:38:02 -0400776static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj,
Mike Lockwooda9e54612009-06-19 14:54:42 -0400777 jint type, jstring hostname, jint port)
Mike Lockwood58bda982009-04-14 16:25:07 -0400778{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800779 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100780 ALOGE("no AGPS interface in set_agps_server");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400781 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400782 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400783 const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800784 sAGpsInterface->set_server(type, c_hostname, port);
Mike Lockwoodbea31182010-10-05 14:29:53 -0400785 env->ReleaseStringUTFChars(hostname, c_hostname);
Mike Lockwood58bda982009-04-14 16:25:07 -0400786}
787
Danke Xie22d1f9f2009-08-18 18:28:45 -0400788static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* env, jobject obj,
789 jint notifId, jint response)
790{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800791 if (!sGpsNiInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000792 ALOGE("no NI interface in send_ni_response");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400793 return;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600794 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400795
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800796 sGpsNiInterface->respond(notifId, response);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600797}
798
799static jstring android_location_GpsLocationProvider_get_internal_state(JNIEnv* env, jobject obj)
800{
801 jstring result = NULL;
802 if (sGpsDebugInterface) {
803 const size_t maxLength = 2047;
804 char buffer[maxLength+1];
805 size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
806 if (length > maxLength) length = maxLength;
807 buffer[length] = 0;
808 result = env->NewStringUTF(buffer);
809 }
810 return result;
Danke Xie22d1f9f2009-08-18 18:28:45 -0400811}
812
Mike Lockwood50130bb2010-10-11 06:22:50 -0400813static void android_location_GpsLocationProvider_update_network_state(JNIEnv* env, jobject obj,
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000814 jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
Mike Lockwood50130bb2010-10-11 06:22:50 -0400815{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800816
817 if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
Mike Lockwood50130bb2010-10-11 06:22:50 -0400818 if (extraInfo) {
819 const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800820 sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400821 env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
822 } else {
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800823 sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400824 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700825
826 // update_network_availability callback was not included in original AGpsRilInterface
827 if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
828 && sAGpsRilInterface->update_network_availability) {
829 const char *c_apn = env->GetStringUTFChars(apn, NULL);
830 sAGpsRilInterface->update_network_availability(available, c_apn);
831 env->ReleaseStringUTFChars(apn, c_apn);
832 }
Mike Lockwood50130bb2010-10-11 06:22:50 -0400833 }
834}
835
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700836static jboolean android_location_GpsLocationProvider_is_geofence_supported(JNIEnv* env,
837 jobject obj) {
838 if (sGpsGeofencingInterface != NULL) {
839 return JNI_TRUE;
840 }
841 return JNI_FALSE;
842}
843
844static jboolean android_location_GpsLocationProvider_add_geofence(JNIEnv* env, jobject obj,
845 jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
846 jint last_transition, jint monitor_transition, jint notification_responsiveness,
847 jint unknown_timer) {
848 if (sGpsGeofencingInterface != NULL) {
849 sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
850 radius, last_transition, monitor_transition, notification_responsiveness,
851 unknown_timer);
852 return JNI_TRUE;
853 } else {
854 ALOGE("Geofence interface not available");
855 }
856 return JNI_FALSE;
857}
858
859static jboolean android_location_GpsLocationProvider_remove_geofence(JNIEnv* env, jobject obj,
860 jint geofence_id) {
861 if (sGpsGeofencingInterface != NULL) {
862 sGpsGeofencingInterface->remove_geofence_area(geofence_id);
863 return JNI_TRUE;
864 } else {
865 ALOGE("Geofence interface not available");
866 }
867 return JNI_FALSE;
868}
869
870static jboolean android_location_GpsLocationProvider_pause_geofence(JNIEnv* env, jobject obj,
871 jint geofence_id) {
872 if (sGpsGeofencingInterface != NULL) {
873 sGpsGeofencingInterface->pause_geofence(geofence_id);
874 return JNI_TRUE;
875 } else {
876 ALOGE("Geofence interface not available");
877 }
878 return JNI_FALSE;
879}
880
881static jboolean android_location_GpsLocationProvider_resume_geofence(JNIEnv* env, jobject obj,
882 jint geofence_id, jint monitor_transition) {
883 if (sGpsGeofencingInterface != NULL) {
884 sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
885 return JNI_TRUE;
886 } else {
887 ALOGE("Geofence interface not available");
888 }
889 return JNI_FALSE;
890}
891
destradaaea8a8a62014-06-23 18:19:03 -0700892static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
893 const char* doubleSignature = "(D)V";
destradaa2102dd72014-07-18 17:50:24 -0700894 const char* longSignature = "(J)V";
destradaaea8a8a62014-06-23 18:19:03 -0700895
896 jclass gpsClockClass = env->FindClass("android/location/GpsClock");
897 jmethodID gpsClockCtor = env->GetMethodID(gpsClockClass, "<init>", "()V");
898
899 jobject gpsClockObject = env->NewObject(gpsClockClass, gpsClockCtor);
900 GpsClockFlags flags = clock->flags;
901
902 if (flags & GPS_CLOCK_HAS_LEAP_SECOND) {
903 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setLeapSecond", "(S)V");
904 env->CallObjectMethod(gpsClockObject, setterMethod, clock->leap_second);
905 }
906
destradaa2102dd72014-07-18 17:50:24 -0700907 jmethodID typeSetterMethod = env->GetMethodID(gpsClockClass, "setType", "(B)V");
908 env->CallObjectMethod(gpsClockObject, typeSetterMethod, clock->type);
909
910 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setTimeInNs", longSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700911 env->CallObjectMethod(gpsClockObject, setterMethod, clock->time_ns);
912
913 if (flags & GPS_CLOCK_HAS_TIME_UNCERTAINTY) {
destradaa2102dd72014-07-18 17:50:24 -0700914 jmethodID setterMethod =
915 env->GetMethodID(gpsClockClass, "setTimeUncertaintyInNs", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700916 env->CallObjectMethod(gpsClockObject, setterMethod, clock->time_uncertainty_ns);
917 }
918
destradaa2102dd72014-07-18 17:50:24 -0700919 if (flags & GPS_CLOCK_HAS_FULL_BIAS) {
920 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setFullBiasInNs", longSignature);
921 env->CallObjectMethod(gpsClockObject, setterMethod, clock->full_bias_ns);
922 }
923
destradaaea8a8a62014-06-23 18:19:03 -0700924 if (flags & GPS_CLOCK_HAS_BIAS) {
925 jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setBiasInNs", doubleSignature);
926 env->CallObjectMethod(gpsClockObject, setterMethod, clock->bias_ns);
927 }
928
929 if (flags & GPS_CLOCK_HAS_BIAS_UNCERTAINTY) {
destradaa2102dd72014-07-18 17:50:24 -0700930 jmethodID setterMethod =
931 env->GetMethodID(gpsClockClass, "setBiasUncertaintyInNs", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700932 env->CallObjectMethod(gpsClockObject, setterMethod, clock->bias_uncertainty_ns);
933 }
934
935 if (flags & GPS_CLOCK_HAS_DRIFT) {
destradaa2102dd72014-07-18 17:50:24 -0700936 jmethodID setterMethod =
937 env->GetMethodID(gpsClockClass, "setDriftInNsPerSec", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700938 env->CallObjectMethod(gpsClockObject, setterMethod, clock->drift_nsps);
939 }
940
941 if (flags & GPS_CLOCK_HAS_DRIFT_UNCERTAINTY) {
destradaa2102dd72014-07-18 17:50:24 -0700942 jmethodID setterMethod =
943 env->GetMethodID(gpsClockClass, "setDriftUncertaintyInNsPerSec", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700944 env->CallObjectMethod(gpsClockObject, setterMethod, clock->drift_uncertainty_nsps);
945 }
946
947 return gpsClockObject;
948}
949
destradaa2102dd72014-07-18 17:50:24 -0700950static jobject translate_gps_measurement(JNIEnv* env, GpsMeasurement* measurement) {
951 const char* byteSignature = "(B)V";
destradaaea8a8a62014-06-23 18:19:03 -0700952 const char* shortSignature = "(S)V";
953 const char* longSignature = "(J)V";
954 const char* floatSignature = "(F)V";
955 const char* doubleSignature = "(D)V";
956
957 jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement");
958 jmethodID gpsMeasurementCtor = env->GetMethodID(gpsMeasurementClass, "<init>", "()V");
959
960 jobject gpsMeasurementObject = env->NewObject(gpsMeasurementClass, gpsMeasurementCtor);
961 GpsMeasurementFlags flags = measurement->flags;
962
destradaa2102dd72014-07-18 17:50:24 -0700963 jmethodID prnSetterMethod = env->GetMethodID(gpsMeasurementClass, "setPrn", byteSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700964 env->CallObjectMethod(gpsMeasurementObject, prnSetterMethod, measurement->prn);
965
destradaa2102dd72014-07-18 17:50:24 -0700966 jmethodID timeOffsetSetterMethod =
967 env->GetMethodID(gpsMeasurementClass, "setTimeOffsetInNs", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700968 env->CallObjectMethod(
969 gpsMeasurementObject,
destradaa2102dd72014-07-18 17:50:24 -0700970 timeOffsetSetterMethod,
971 measurement->time_offset_ns);
972
973 jmethodID stateSetterMethod = env->GetMethodID(gpsMeasurementClass, "setState", shortSignature);
974 env->CallObjectMethod(gpsMeasurementObject, stateSetterMethod, measurement->state);
destradaaea8a8a62014-06-23 18:19:03 -0700975
976 jmethodID receivedGpsTowSetterMethod =
977 env->GetMethodID(gpsMeasurementClass, "setReceivedGpsTowInNs", longSignature);
978 env->CallObjectMethod(
979 gpsMeasurementObject,
980 receivedGpsTowSetterMethod,
981 measurement->received_gps_tow_ns);
982
destradaa81cabb82014-07-22 09:59:43 -0700983 jmethodID receivedGpsTowUncertaintySetterMethod = env->GetMethodID(
984 gpsMeasurementClass,
985 "setReceivedGpsTowUncertaintyInNs",
986 longSignature);
987 env->CallVoidMethod(
988 gpsMeasurementObject,
989 receivedGpsTowUncertaintySetterMethod,
990 measurement->received_gps_tow_uncertainty_ns);
991
destradaa2102dd72014-07-18 17:50:24 -0700992 jmethodID cn0SetterMethod =
993 env->GetMethodID(gpsMeasurementClass, "setCn0InDbHz", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -0700994 env->CallObjectMethod(gpsMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz);
995
996 jmethodID pseudorangeRateSetterMethod = env->GetMethodID(
997 gpsMeasurementClass,
998 "setPseudorangeRateInMetersPerSec",
999 doubleSignature);
1000 env->CallObjectMethod(
1001 gpsMeasurementObject,
1002 pseudorangeRateSetterMethod,
destradaa2102dd72014-07-18 17:50:24 -07001003 measurement->pseudorange_rate_mps);
destradaaea8a8a62014-06-23 18:19:03 -07001004
1005 jmethodID pseudorangeRateUncertaintySetterMethod = env->GetMethodID(
1006 gpsMeasurementClass,
1007 "setPseudorangeRateUncertaintyInMetersPerSec",
1008 doubleSignature);
1009 env->CallObjectMethod(
1010 gpsMeasurementObject,
1011 pseudorangeRateUncertaintySetterMethod,
destradaa2102dd72014-07-18 17:50:24 -07001012 measurement->pseudorange_rate_uncertainty_mps);
1013
1014 jmethodID accumulatedDeltaRangeStateSetterMethod =
1015 env->GetMethodID(gpsMeasurementClass, "setAccumulatedDeltaRangeState", shortSignature);
1016 env->CallObjectMethod(
1017 gpsMeasurementObject,
1018 accumulatedDeltaRangeStateSetterMethod,
1019 measurement->accumulated_delta_range_state);
destradaaea8a8a62014-06-23 18:19:03 -07001020
1021 jmethodID accumulatedDeltaRangeSetterMethod = env->GetMethodID(
1022 gpsMeasurementClass,
1023 "setAccumulatedDeltaRangeInMeters",
1024 doubleSignature);
1025 env->CallVoidMethod(
1026 gpsMeasurementObject,
1027 accumulatedDeltaRangeSetterMethod,
1028 measurement->accumulated_delta_range_m);
1029
1030 jmethodID accumulatedDeltaRangeUncertaintySetterMethod = env->GetMethodID(
1031 gpsMeasurementClass,
1032 "setAccumulatedDeltaRangeUncertaintyInMeters",
1033 doubleSignature);
1034 env->CallVoidMethod(
1035 gpsMeasurementObject,
1036 accumulatedDeltaRangeUncertaintySetterMethod,
1037 measurement->accumulated_delta_range_uncertainty_m);
1038
destradaaea8a8a62014-06-23 18:19:03 -07001039 if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE) {
destradaa2102dd72014-07-18 17:50:24 -07001040 jmethodID setterMethod =
1041 env->GetMethodID(gpsMeasurementClass, "setPseudorangeInMeters", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001042 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->pseudorange_m);
1043 }
1044
1045 if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY) {
1046 jmethodID setterMethod = env->GetMethodID(
1047 gpsMeasurementClass,
1048 "setPseudorangeUncertaintyInMeters",
1049 doubleSignature);
1050 env->CallObjectMethod(
1051 gpsMeasurementObject,
1052 setterMethod,
1053 measurement->pseudorange_uncertainty_m);
1054 }
1055
1056 if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE) {
destradaa2102dd72014-07-18 17:50:24 -07001057 jmethodID setterMethod =
1058 env->GetMethodID(gpsMeasurementClass, "setCodePhaseInChips", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001059 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->code_phase_chips);
1060 }
1061
1062 if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY) {
1063 jmethodID setterMethod = env->GetMethodID(
1064 gpsMeasurementClass,
1065 "setCodePhaseUncertaintyInChips",
1066 doubleSignature);
1067 env->CallObjectMethod(
1068 gpsMeasurementObject,
1069 setterMethod,
1070 measurement->code_phase_uncertainty_chips);
1071 }
1072
1073 if (flags & GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
destradaa2102dd72014-07-18 17:50:24 -07001074 jmethodID setterMethod =
1075 env->GetMethodID(gpsMeasurementClass, "setCarrierFrequencyInHz", floatSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001076 env->CallObjectMethod(
1077 gpsMeasurementObject,
1078 setterMethod,
1079 measurement->carrier_frequency_hz);
1080 }
1081
1082 if (flags & GPS_MEASUREMENT_HAS_CARRIER_CYCLES) {
1083 jmethodID setterMethod =
1084 env->GetMethodID(gpsMeasurementClass, "setCarrierCycles", longSignature);
1085 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->carrier_cycles);
1086 }
1087
1088 if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE) {
1089 jmethodID setterMethod =
1090 env->GetMethodID(gpsMeasurementClass, "setCarrierPhase", doubleSignature);
1091 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->carrier_phase);
1092 }
1093
1094 if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
1095 jmethodID setterMethod = env->GetMethodID(
1096 gpsMeasurementClass,
1097 "setCarrierPhaseUncertainty",
1098 doubleSignature);
1099 env->CallObjectMethod(
1100 gpsMeasurementObject,
1101 setterMethod,
1102 measurement->carrier_phase_uncertainty);
1103 }
1104
1105 jmethodID lossOfLockSetterMethod =
destradaa2102dd72014-07-18 17:50:24 -07001106 env->GetMethodID(gpsMeasurementClass, "setLossOfLock", byteSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001107 env->CallObjectMethod(gpsMeasurementObject, lossOfLockSetterMethod, measurement->loss_of_lock);
1108
1109 if (flags & GPS_MEASUREMENT_HAS_BIT_NUMBER) {
destradaa2102dd72014-07-18 17:50:24 -07001110 jmethodID setterMethod =
1111 env->GetMethodID(gpsMeasurementClass, "setBitNumber", shortSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001112 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->bit_number);
1113 }
1114
1115 if (flags & GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT) {
destradaa2102dd72014-07-18 17:50:24 -07001116 jmethodID setterMethod =
1117 env->GetMethodID(gpsMeasurementClass, "setTimeFromLastBitInMs", shortSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001118 env->CallObjectMethod(
1119 gpsMeasurementObject,
1120 setterMethod,
destradaa2102dd72014-07-18 17:50:24 -07001121 measurement->time_from_last_bit_ms);
destradaaea8a8a62014-06-23 18:19:03 -07001122 }
1123
1124 if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT) {
destradaa2102dd72014-07-18 17:50:24 -07001125 jmethodID setterMethod =
1126 env->GetMethodID(gpsMeasurementClass, "setDopplerShiftInHz", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001127 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->doppler_shift_hz);
1128 }
1129
1130 if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY) {
1131 jmethodID setterMethod = env->GetMethodID(
1132 gpsMeasurementClass,
1133 "setDopplerShiftUncertaintyInHz",
1134 doubleSignature);
1135 env->CallObjectMethod(
1136 gpsMeasurementObject,
1137 setterMethod,
1138 measurement->doppler_shift_uncertainty_hz);
1139 }
1140
destradaa2102dd72014-07-18 17:50:24 -07001141 jmethodID multipathIndicatorSetterMethod =
1142 env->GetMethodID(gpsMeasurementClass, "setMultipathIndicator", byteSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001143 env->CallObjectMethod(
1144 gpsMeasurementObject,
1145 multipathIndicatorSetterMethod,
1146 measurement->multipath_indicator);
1147
1148 if (flags & GPS_MEASUREMENT_HAS_SNR) {
1149 jmethodID setterMethod =
1150 env->GetMethodID(gpsMeasurementClass, "setSnrInDb", doubleSignature);
1151 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->snr_db);
1152 }
1153
1154 if (flags & GPS_MEASUREMENT_HAS_ELEVATION) {
destradaa2102dd72014-07-18 17:50:24 -07001155 jmethodID setterMethod =
1156 env->GetMethodID(gpsMeasurementClass, "setElevationInDeg", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001157 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->elevation_deg);
1158 }
1159
1160 if (flags & GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY) {
destradaa2102dd72014-07-18 17:50:24 -07001161 jmethodID setterMethod =
1162 env->GetMethodID(gpsMeasurementClass, "setElevationUncertaintyInDeg", doubleSignature);
destradaaea8a8a62014-06-23 18:19:03 -07001163 env->CallObjectMethod(
1164 gpsMeasurementObject,
1165 setterMethod,
1166 measurement->elevation_uncertainty_deg);
1167 }
1168
1169 if (flags & GPS_MEASUREMENT_HAS_AZIMUTH) {
1170 jmethodID setterMethod =
1171 env->GetMethodID(gpsMeasurementClass, "setAzimuthInDeg", doubleSignature);
1172 env->CallObjectMethod(gpsMeasurementObject, setterMethod, measurement->azimuth_deg);
1173 }
1174
1175 if (flags & GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY) {
1176 jmethodID setterMethod = env->GetMethodID(
1177 gpsMeasurementClass,
1178 "setAzimuthUncertaintyInDeg",
1179 doubleSignature);
1180 env->CallObjectMethod(
1181 gpsMeasurementObject,
1182 setterMethod,
1183 measurement->azimuth_uncertainty_deg);
1184 }
1185
1186 jmethodID usedInFixSetterMethod = env->GetMethodID(gpsMeasurementClass, "setUsedInFix", "(Z)V");
1187 env->CallObjectMethod(
1188 gpsMeasurementObject,
1189 usedInFixSetterMethod,
1190 (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
1191
1192 return gpsMeasurementObject;
1193}
1194
1195static jobjectArray translate_gps_measurements(JNIEnv* env, GpsData* data) {
1196 size_t measurementCount = data->measurement_count;
1197 if (measurementCount == 0) {
1198 return NULL;
1199 }
1200
1201 jclass gpsMeasurementClass = env->FindClass("android/location/GpsMeasurement");
1202 jobjectArray gpsMeasurementArray = env->NewObjectArray(
1203 measurementCount,
1204 gpsMeasurementClass,
1205 NULL /* initialElement */);
1206
1207 GpsMeasurement* gpsMeasurements = data->measurements;
1208 for (uint16_t i = 0; i < measurementCount; ++i) {
destradaa2102dd72014-07-18 17:50:24 -07001209 jobject gpsMeasurement = translate_gps_measurement(env, &gpsMeasurements[i]);
destradaaea8a8a62014-06-23 18:19:03 -07001210 env->SetObjectArrayElement(gpsMeasurementArray, i, gpsMeasurement);
1211 env->DeleteLocalRef(gpsMeasurement);
1212 }
1213
1214 env->DeleteLocalRef(gpsMeasurementClass);
1215 return gpsMeasurementArray;
1216}
1217
1218static void measurement_callback(GpsData* data) {
1219 JNIEnv* env = AndroidRuntime::getJNIEnv();
1220 if (data == NULL) {
1221 ALOGE("Invalid data provided to gps_measurement_callback");
1222 return;
1223 }
1224
1225 if (data->size == sizeof(GpsData)) {
1226 jobject gpsClock = translate_gps_clock(env, &data->clock);
1227 jobjectArray measurementArray = translate_gps_measurements(env, data);
1228
1229 jclass gpsMeasurementsEventClass = env->FindClass("android/location/GpsMeasurementsEvent");
1230 jmethodID gpsMeasurementsEventCtor = env->GetMethodID(
1231 gpsMeasurementsEventClass,
1232 "<init>",
1233 "(Landroid/location/GpsClock;[Landroid/location/GpsMeasurement;)V");
1234
1235 jobject gpsMeasurementsEvent = env->NewObject(
1236 gpsMeasurementsEventClass,
1237 gpsMeasurementsEventCtor,
1238 gpsClock,
1239 measurementArray);
1240
1241 env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gpsMeasurementsEvent);
1242 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1243 } else {
1244 ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%d", data->size);
destradaaea8a8a62014-06-23 18:19:03 -07001245 }
1246}
1247
1248GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
1249 sizeof(GpsMeasurementCallbacks),
1250 measurement_callback,
1251};
1252
1253static jboolean android_location_GpsLocationProvider_is_measurement_supported(
1254 JNIEnv* env,
destradaa4b3e3932014-07-21 18:01:47 -07001255 jclass clazz) {
destradaaea8a8a62014-06-23 18:19:03 -07001256 if (sGpsMeasurementInterface != NULL) {
1257 return JNI_TRUE;
1258 }
1259 return JNI_FALSE;
1260}
1261
1262static jboolean android_location_GpsLocationProvider_start_measurement_collection(
1263 JNIEnv* env,
1264 jobject obj) {
1265 if (sGpsMeasurementInterface == NULL) {
1266 ALOGE("Measurement interface is not available.");
1267 return JNI_FALSE;
1268 }
1269
1270 int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
1271 if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
1272 ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
1273 return JNI_FALSE;
1274 }
1275
1276 return JNI_TRUE;
1277}
1278
1279static jboolean android_location_GpsLocationProvider_stop_measurement_collection(
1280 JNIEnv* env,
1281 jobject obj) {
1282 if (sGpsMeasurementInterface == NULL) {
1283 ALOGE("Measurement interface not available");
1284 return JNI_FALSE;
1285 }
1286
1287 sGpsMeasurementInterface->close();
1288 return JNI_TRUE;
1289}
1290
destradaa4b3e3932014-07-21 18:01:47 -07001291static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
1292 size_t dataLength = message->data_length;
1293 uint8_t* data = message->data;
1294 if (dataLength == 0 || data == NULL) {
1295 ALOGE("Invalid Navigation Message found: data=%p, length=%d", data, dataLength);
1296 return NULL;
1297 }
1298
1299 jclass navigationMessageClass = env->FindClass("android/location/GpsNavigationMessage");
1300 jmethodID navigationMessageCtor = env->GetMethodID(navigationMessageClass, "<init>", "()V");
1301 jobject navigationMessageObject = env->NewObject(navigationMessageClass, navigationMessageCtor);
1302
1303 jmethodID setTypeMethod = env->GetMethodID(navigationMessageClass, "setType", "(B)V");
1304 env->CallVoidMethod(navigationMessageObject, setTypeMethod, message->type);
1305
1306 jmethodID setPrnMethod = env->GetMethodID(navigationMessageClass, "setPrn", "(B)V");
1307 env->CallVoidMethod(navigationMessageObject, setPrnMethod, message->prn);
1308
1309 jmethodID setMessageIdMethod = env->GetMethodID(navigationMessageClass, "setMessageId", "(S)V");
1310 env->CallVoidMethod(navigationMessageObject, setMessageIdMethod, message->message_id);
1311
1312 jmethodID setSubmessageIdMethod =
1313 env->GetMethodID(navigationMessageClass, "setSubmessageId", "(S)V");
1314 env->CallVoidMethod(navigationMessageObject, setSubmessageIdMethod, message->submessage_id);
1315
1316 jbyteArray dataArray = env->NewByteArray(dataLength);
1317 env->SetByteArrayRegion(dataArray, 0, dataLength, (jbyte*) data);
1318 jmethodID setDataMethod = env->GetMethodID(navigationMessageClass, "setData", "([B)V");
1319 env->CallVoidMethod(navigationMessageObject, setDataMethod, dataArray);
1320
1321 return navigationMessageObject;
1322}
1323
1324static void navigation_message_callback(GpsNavigationMessage* message) {
1325 JNIEnv* env = AndroidRuntime::getJNIEnv();
1326 if (message == NULL) {
1327 ALOGE("Invalid Navigation Message provided to callback");
1328 return;
1329 }
1330
1331 if (message->size == sizeof(GpsNavigationMessage)) {
1332 jobject navigationMessage = translate_gps_navigation_message(env, message);
1333
1334 jclass navigationMessageEventClass =
1335 env->FindClass("android/location/GpsNavigationMessageEvent");
1336 jmethodID navigationMessageEventCtor = env->GetMethodID(
1337 navigationMessageEventClass,
1338 "<init>",
1339 "(Landroid/location/GpsNavigationMessage;)V");
1340 jobject navigationMessageEvent = env->NewObject(
1341 navigationMessageEventClass,
1342 navigationMessageEventCtor,
1343 navigationMessage);
1344
1345 env->CallVoidMethod(mCallbacksObj, method_reportNavigationMessages, navigationMessageEvent);
1346 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1347 } else {
1348 ALOGE("Invalid GpsNavigationMessage size found: %d", message->size);
1349 }
1350}
1351
1352GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
1353 sizeof(GpsNavigationMessageCallbacks),
1354 navigation_message_callback,
1355};
1356
1357static jboolean android_location_GpsLocationProvider_is_navigation_message_supported(
1358 JNIEnv* env,
1359 jclass clazz) {
1360 if(sGpsNavigationMessageInterface != NULL) {
1361 return JNI_TRUE;
1362 }
1363 return JNI_FALSE;
1364}
1365
1366static jboolean android_location_GpsLocationProvider_start_navigation_message_collection(
1367 JNIEnv* env,
1368 jobject obj) {
1369 if (sGpsNavigationMessageInterface == NULL) {
1370 ALOGE("Navigation Message interface is not available.");
1371 return JNI_FALSE;
1372 }
1373
1374 int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
1375 if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
1376 ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
1377 return JNI_FALSE;
1378 }
1379
1380 return JNI_TRUE;
1381}
1382
1383static jboolean android_location_GpsLocationProvider_stop_navigation_message_collection(
1384 JNIEnv* env,
1385 jobject obj) {
1386 if (sGpsNavigationMessageInterface == NULL) {
1387 ALOGE("Navigation Message interface is not available.");
1388 return JNI_FALSE;
1389 }
1390
1391 sGpsNavigationMessageInterface->close();
1392 return JNI_TRUE;
1393}
1394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395static JNINativeMethod sMethods[] = {
1396 /* name, signature, funcPtr */
1397 {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
Mike Lockwoode3635c92009-05-11 08:38:02 -04001398 {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
1399 {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
Mike Lockwoode3635c92009-05-11 08:38:02 -04001400 {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
destradaaea8a8a62014-06-23 18:19:03 -07001401 {"native_set_position_mode",
1402 "(IIIII)Z",
1403 (void*)android_location_GpsLocationProvider_set_position_mode},
Mike Lockwood04598b62010-04-14 17:17:24 -04001404 {"native_start", "()Z", (void*)android_location_GpsLocationProvider_start},
Mike Lockwoode3635c92009-05-11 08:38:02 -04001405 {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
destradaaea8a8a62014-06-23 18:19:03 -07001406 {"native_delete_aiding_data",
1407 "(I)V",
1408 (void*)android_location_GpsLocationProvider_delete_aiding_data},
1409 {"native_read_sv_status",
1410 "([I[F[F[F[I)I",
1411 (void*)android_location_GpsLocationProvider_read_sv_status},
Mike Lockwoodf602d362010-06-20 14:28:16 -07001412 {"native_read_nmea", "([BI)I", (void*)android_location_GpsLocationProvider_read_nmea},
Mike Lockwoode3635c92009-05-11 08:38:02 -04001413 {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
destradaaea8a8a62014-06-23 18:19:03 -07001414 {"native_inject_location",
1415 "(DDF)V",
1416 (void*)android_location_GpsLocationProvider_inject_location},
Mike Lockwoode3635c92009-05-11 08:38:02 -04001417 {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
destradaaea8a8a62014-06-23 18:19:03 -07001418 {"native_inject_xtra_data",
1419 "([BI)V",
1420 (void*)android_location_GpsLocationProvider_inject_xtra_data},
1421 {"native_agps_data_conn_open",
1422 "(Ljava/lang/String;I)V",
1423 (void*)android_location_GpsLocationProvider_agps_data_conn_open},
1424 {"native_agps_data_conn_closed",
1425 "()V",
1426 (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
1427 {"native_agps_data_conn_failed",
1428 "()V",
1429 (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
1430 {"native_agps_set_id",
1431 "(ILjava/lang/String;)V",
1432 (void*)android_location_GpsLocationProvider_agps_set_id},
1433 {"native_agps_set_ref_location_cellid",
1434 "(IIIII)V",
1435 (void*)android_location_GpsLocationProvider_agps_set_reference_location_cellid},
1436 {"native_set_agps_server",
1437 "(ILjava/lang/String;I)V",
1438 (void*)android_location_GpsLocationProvider_set_agps_server},
1439 {"native_send_ni_response",
1440 "(II)V",
1441 (void*)android_location_GpsLocationProvider_send_ni_response},
1442 {"native_agps_ni_message",
1443 "([BI)V",
1444 (void *)android_location_GpsLocationProvider_agps_send_ni_message},
1445 {"native_get_internal_state",
1446 "()Ljava/lang/String;",
1447 (void*)android_location_GpsLocationProvider_get_internal_state},
1448 {"native_update_network_state",
1449 "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
1450 (void*)android_location_GpsLocationProvider_update_network_state },
1451 {"native_is_geofence_supported",
1452 "()Z",
1453 (void*) android_location_GpsLocationProvider_is_geofence_supported},
1454 {"native_add_geofence",
1455 "(IDDDIIII)Z",
1456 (void *)android_location_GpsLocationProvider_add_geofence},
1457 {"native_remove_geofence",
1458 "(I)Z",
1459 (void *)android_location_GpsLocationProvider_remove_geofence},
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001460 {"native_pause_geofence", "(I)Z", (void *)android_location_GpsLocationProvider_pause_geofence},
destradaaea8a8a62014-06-23 18:19:03 -07001461 {"native_resume_geofence",
1462 "(II)Z",
1463 (void *)android_location_GpsLocationProvider_resume_geofence},
1464 {"native_is_measurement_supported",
1465 "()Z",
1466 (void*) android_location_GpsLocationProvider_is_measurement_supported},
1467 {"native_start_measurement_collection",
1468 "()Z",
1469 (void*) android_location_GpsLocationProvider_start_measurement_collection},
1470 {"native_stop_measurement_collection",
1471 "()Z",
destradaa4b3e3932014-07-21 18:01:47 -07001472 (void*) android_location_GpsLocationProvider_stop_measurement_collection},
1473 {"native_is_navigation_message_supported",
1474 "()Z",
1475 (void*) android_location_GpsLocationProvider_is_navigation_message_supported},
1476 {"native_start_navigation_message_collection",
1477 "()Z",
1478 (void*) android_location_GpsLocationProvider_start_navigation_message_collection},
1479 {"native_stop_navigation_message_collection",
1480 "()Z",
1481 (void*) android_location_GpsLocationProvider_stop_navigation_message_collection},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482};
1483
Mike Lockwood00b74272010-03-26 10:41:48 -04001484int register_android_server_location_GpsLocationProvider(JNIEnv* env)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485{
destradaaea8a8a62014-06-23 18:19:03 -07001486 return jniRegisterNativeMethods(
1487 env,
1488 "com/android/server/location/GpsLocationProvider",
1489 sMethods,
1490 NELEM(sMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491}
1492
1493} /* namespace android */