blob: e39445af78d30fb2f9f153ce5749a12999656c78 [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>
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;
Lifu Tang9363b942016-02-16 18:07:00 -080045static jmethodID method_setGnssYearOfHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046static jmethodID method_xtraDownloadRequest;
Danke Xie22d1f9f2009-08-18 18:28:45 -040047static jmethodID method_reportNiNotification;
Miguel Torroja1e84da82010-07-27 07:02:24 +020048static jmethodID method_requestRefLocation;
49static jmethodID method_requestSetID;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -040050static jmethodID method_requestUtcTime;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070051static jmethodID method_reportGeofenceTransition;
52static jmethodID method_reportGeofenceStatus;
53static jmethodID method_reportGeofenceAddStatus;
54static jmethodID method_reportGeofenceRemoveStatus;
55static jmethodID method_reportGeofencePauseStatus;
56static jmethodID method_reportGeofenceResumeStatus;
destradaaea8a8a62014-06-23 18:19:03 -070057static jmethodID method_reportMeasurementData;
destradaa4b3e3932014-07-21 18:01:47 -070058static jmethodID method_reportNavigationMessages;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059
60static const GpsInterface* sGpsInterface = NULL;
61static const GpsXtraInterface* sGpsXtraInterface = NULL;
Mike Lockwoode3635c92009-05-11 08:38:02 -040062static const AGpsInterface* sAGpsInterface = NULL;
Danke Xie22d1f9f2009-08-18 18:28:45 -040063static const GpsNiInterface* sGpsNiInterface = NULL;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -060064static const GpsDebugInterface* sGpsDebugInterface = NULL;
Miguel Torroja1e84da82010-07-27 07:02:24 +020065static const AGpsRilInterface* sAGpsRilInterface = NULL;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070066static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
destradaaea8a8a62014-06-23 18:19:03 -070067static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
destradaa4b3e3932014-07-21 18:01:47 -070068static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
Tsuwei Chen52617bb2014-08-25 11:49:11 -070069static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070
Lifu Tang120480f2016-02-07 18:08:19 -080071#define GPS_MAX_SATELLITE_COUNT 32
72#define GNSS_MAX_SATELLITE_COUNT 64
Lifu Tang30f95a72016-01-07 23:20:38 -080073
Lifu Tang120480f2016-02-07 18:08:19 -080074#define SVID_SHIFT_WIDTH 7
75#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
Lifu Tang30f95a72016-01-07 23:20:38 -080076
Mike Lockwoodf602d362010-06-20 14:28:16 -070077// temporary storage for GPS callbacks
Lifu Tang120480f2016-02-07 18:08:19 -080078static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
Lifu Tang30f95a72016-01-07 23:20:38 -080079static size_t sGnssSvListSize;
Mike Lockwoodf602d362010-06-20 14:28:16 -070080static const char* sNmeaString;
81static int sNmeaStringLength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082
Mike Lockwood8f5a8002010-04-07 09:05:26 -040083#define WAKE_LOCK_NAME "GPS"
84
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085namespace android {
86
Mike Lockwoodf602d362010-06-20 14:28:16 -070087static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
88 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +000089 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwoodf602d362010-06-20 14:28:16 -070090 LOGE_EX(env);
91 env->ExceptionClear();
92 }
93}
94
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095static void location_callback(GpsLocation* location)
96{
Mike Lockwoodf602d362010-06-20 14:28:16 -070097 JNIEnv* env = AndroidRuntime::getJNIEnv();
98 env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
99 (jdouble)location->latitude, (jdouble)location->longitude,
100 (jdouble)location->altitude,
101 (jfloat)location->speed, (jfloat)location->bearing,
102 (jfloat)location->accuracy, (jlong)location->timestamp);
103 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104}
105
106static void status_callback(GpsStatus* status)
107{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700108 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf602d362010-06-20 14:28:16 -0700109 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
110 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111}
112
113static void sv_status_callback(GpsSvStatus* sv_status)
114{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700115 JNIEnv* env = AndroidRuntime::getJNIEnv();
Lifu Tang30f95a72016-01-07 23:20:38 -0800116 size_t status_size = sv_status->size;
Lifu Tang120480f2016-02-07 18:08:19 -0800117 // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
118 // if it doesn't provide a valid size.
Lifu Tang30f95a72016-01-07 23:20:38 -0800119 if (status_size == 0) {
Lifu Tang120480f2016-02-07 18:08:19 -0800120 ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
Lifu Tang30f95a72016-01-07 23:20:38 -0800121 }
Lifu Tang120480f2016-02-07 18:08:19 -0800122 sGnssSvListSize = sv_status->num_svs;
123 // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
124 if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
Lifu Tanga2b74fd2016-02-11 12:57:59 -0800125 ALOGW("Too many satellites %zd. Clamps to %d.",
Lifu Tang120480f2016-02-07 18:08:19 -0800126 sGnssSvListSize,
127 GPS_MAX_SATELLITE_COUNT);
128 sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
129 }
130 uint32_t ephemeris_mask = sv_status->ephemeris_mask;
131 uint32_t almanac_mask = sv_status->almanac_mask;
132 uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
133 for (size_t i = 0; i < sGnssSvListSize; i++) {
134 GnssSvInfo& info = sGnssSvList[i];
135 info.svid = sv_status->sv_list[i].prn;
Lifu Tang120480f2016-02-07 18:08:19 -0800136 if (info.svid >=1 && info.svid <= 32) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800137 info.constellation = GNSS_CONSTELLATION_GPS;
Lifu Tang120480f2016-02-07 18:08:19 -0800138 } else {
Lifu Tang9363b942016-02-16 18:07:00 -0800139 ALOGD("Unknown constellation type with Svid = %d.", info.svid);
Lifu Tang120480f2016-02-07 18:08:19 -0800140 info.constellation = GNSS_CONSTELLATION_UNKNOWN;
141 }
142 info.snr = sv_status->sv_list[i].snr;
143 info.elevation = sv_status->sv_list[i].elevation;
144 info.azimuth = sv_status->sv_list[i].azimuth;
145 info.flags = GNSS_SV_FLAGS_NONE;
146 if (info.svid > 0 && info.svid <= 32) {
147 int32_t this_svid_mask = (1 << (info.svid - 1));
148 if ((ephemeris_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800149 info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
Lifu Tang120480f2016-02-07 18:08:19 -0800150 }
151 if ((almanac_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800152 info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
Lifu Tang120480f2016-02-07 18:08:19 -0800153 }
154 if ((used_in_fix_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800155 info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
156 }
157 }
Lifu Tang120480f2016-02-07 18:08:19 -0800158 }
159 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
160 checkAndClearExceptionFromCallback(env, __FUNCTION__);
161}
162
163static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
164 JNIEnv* env = AndroidRuntime::getJNIEnv();
165 size_t status_size = sv_status->size;
166 // Check the size, and reject the object that has invalid size.
167 if (status_size != sizeof(GnssSvStatus)) {
168 ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
Lifu Tang30f95a72016-01-07 23:20:38 -0800169 return;
170 }
Lifu Tang120480f2016-02-07 18:08:19 -0800171 sGnssSvListSize = sv_status->num_svs;
172 // Clamp the list size
173 if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
Lifu Tanga2b74fd2016-02-11 12:57:59 -0800174 ALOGD("Too many satellites %zd. Clamps to %d.",
Lifu Tang120480f2016-02-07 18:08:19 -0800175 sGnssSvListSize,
176 GNSS_MAX_SATELLITE_COUNT);
177 sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
178 }
179 // Copy GNSS SV info into sGnssSvList, if any.
180 if (sGnssSvListSize > 0) {
181 memcpy(sGnssSvList,
182 sv_status->gnss_sv_list,
183 sizeof(GnssSvInfo) * sGnssSvListSize);
184 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700185 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
186 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187}
188
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400189static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
190{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700191 JNIEnv* env = AndroidRuntime::getJNIEnv();
192 // The Java code will call back to read these values
193 // We do this to avoid creating unnecessary String objects
194 sNmeaString = nmea;
195 sNmeaStringLength = length;
196 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
197 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400198}
199
Lifu Tang9363b942016-02-16 18:07:00 -0800200static void set_system_info_callback(const GnssSystemInfo* info) {
Lifu Tang82f893d2016-01-21 18:15:33 -0800201 ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
202 JNIEnv* env = AndroidRuntime::getJNIEnv();
Lifu Tang9363b942016-02-16 18:07:00 -0800203 env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
Lifu Tang82f893d2016-01-21 18:15:33 -0800204 info->year_of_hw);
205 checkAndClearExceptionFromCallback(env, __FUNCTION__);
206}
207
Mike Lockwood04598b62010-04-14 17:17:24 -0400208static void set_capabilities_callback(uint32_t capabilities)
209{
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700210 ALOGD("set_capabilities_callback: %du\n", capabilities);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700211 JNIEnv* env = AndroidRuntime::getJNIEnv();
212 env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
213 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood04598b62010-04-14 17:17:24 -0400214}
215
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400216static void acquire_wakelock_callback()
217{
218 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
219}
220
221static void release_wakelock_callback()
222{
223 release_wake_lock(WAKE_LOCK_NAME);
224}
225
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400226static void request_utc_time_callback()
227{
228 JNIEnv* env = AndroidRuntime::getJNIEnv();
229 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
230 checkAndClearExceptionFromCallback(env, __FUNCTION__);
231}
232
Mike Lockwoodf602d362010-06-20 14:28:16 -0700233static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
Mike Lockwood58bda982009-04-14 16:25:07 -0400234{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700235 return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
Mike Lockwood58bda982009-04-14 16:25:07 -0400236}
237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238GpsCallbacks sGpsCallbacks = {
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400239 sizeof(GpsCallbacks),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 location_callback,
241 status_callback,
242 sv_status_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400243 nmea_callback,
Mike Lockwood04598b62010-04-14 17:17:24 -0400244 set_capabilities_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400245 acquire_wakelock_callback,
246 release_wakelock_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700247 create_thread_callback,
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400248 request_utc_time_callback,
Lifu Tang82f893d2016-01-21 18:15:33 -0800249 set_system_info_callback,
Lifu Tang120480f2016-02-07 18:08:19 -0800250 gnss_sv_status_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251};
252
Mike Lockwoodf602d362010-06-20 14:28:16 -0700253static void xtra_download_request_callback()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700255 JNIEnv* env = AndroidRuntime::getJNIEnv();
256 env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
257 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Danke Xie22d1f9f2009-08-18 18:28:45 -0400258}
259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260GpsXtraCallbacks sGpsXtraCallbacks = {
Mike Lockwoodf602d362010-06-20 14:28:16 -0700261 xtra_download_request_callback,
262 create_thread_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263};
264
destradaa96a14702014-06-05 11:36:30 -0700265static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
266{
267 if (INADDR_NONE == ip) {
268 return NULL;
269 }
270
271 JNIEnv* env = AndroidRuntime::getJNIEnv();
272 jbyteArray byteArray = env->NewByteArray(4);
273 if (byteArray == NULL) {
274 ALOGE("Unable to allocate byte array for IPv4 address");
275 return NULL;
276 }
277
278 jbyte ipv4[4];
279 if (net_order) {
destradaa931a37f2014-08-12 16:36:59 -0700280 ALOGV("Converting IPv4 address(net_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700281 memcpy(ipv4, &ip, sizeof(ipv4));
282 } else {
destradaa931a37f2014-08-12 16:36:59 -0700283 ALOGV("Converting IPv4 address(host_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700284 //endianess transparent conversion from int to char[]
285 ipv4[0] = (jbyte) (ip & 0xFF);
286 ipv4[1] = (jbyte)((ip>>8) & 0xFF);
287 ipv4[2] = (jbyte)((ip>>16) & 0xFF);
288 ipv4[3] = (jbyte) (ip>>24);
289 }
290
291 env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
292 return byteArray;
293}
294
Mike Lockwoodf602d362010-06-20 14:28:16 -0700295static void agps_status_callback(AGpsStatus* agps_status)
296{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700297 JNIEnv* env = AndroidRuntime::getJNIEnv();
destradaa96a14702014-06-05 11:36:30 -0700298 jbyteArray byteArray = NULL;
299 bool isSupported = false;
Stephen Li8efd74d2011-03-01 20:56:00 -0800300
destradaa96a14702014-06-05 11:36:30 -0700301 size_t status_size = agps_status->size;
Lifu Tanga8b7bb52016-01-26 01:22:10 -0800302 if (status_size == sizeof(AGpsStatus)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100303 ALOGV("AGpsStatus is V3: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700304 switch (agps_status->addr.ss_family)
305 {
306 case AF_INET:
307 {
308 struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
destradaace48c1c2015-05-29 13:47:39 -0700309 uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
310 byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
311 if (ipAddr == INADDR_NONE || byteArray != NULL) {
destradaa96a14702014-06-05 11:36:30 -0700312 isSupported = true;
313 }
destradaa931a37f2014-08-12 16:36:59 -0700314 IF_ALOGD() {
315 // log the IP for reference in case there is a bogus value pushed by HAL
316 char str[INET_ADDRSTRLEN];
317 inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
318 ALOGD("AGPS IP is v4: %s", str);
319 }
destradaa96a14702014-06-05 11:36:30 -0700320 }
321 break;
322 case AF_INET6:
323 {
324 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
325 byteArray = env->NewByteArray(16);
326 if (byteArray != NULL) {
327 env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
328 isSupported = true;
329 } else {
330 ALOGE("Unable to allocate byte array for IPv6 address.");
331 }
destradaa931a37f2014-08-12 16:36:59 -0700332 IF_ALOGD() {
333 // log the IP for reference in case there is a bogus value pushed by HAL
334 char str[INET6_ADDRSTRLEN];
335 inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
336 ALOGD("AGPS IP is v6: %s", str);
337 }
destradaa96a14702014-06-05 11:36:30 -0700338 }
339 break;
340 default:
341 ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
342 break;
343 }
344 } else if (status_size >= sizeof(AGpsStatus_v2)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100345 ALOGV("AGpsStatus is V2+: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700346 // for back-compatibility reasons we check in v2 that the data structure size is greater or
347 // equal to the declared size in gps.h
348 uint32_t ipaddr = agps_status->ipaddr;
destradaa931a37f2014-08-12 16:36:59 -0700349 ALOGV("AGPS IP is v4: %x", ipaddr);
destradaa96a14702014-06-05 11:36:30 -0700350 byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
351 if (ipaddr == INADDR_NONE || byteArray != NULL) {
352 isSupported = true;
353 }
354 } else if (status_size >= sizeof(AGpsStatus_v1)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100355 ALOGV("AGpsStatus is V1+: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700356 // because we have to check for >= with regards to v2, we also need to relax the check here
357 // and only make sure that the size is at least what we expect
358 isSupported = true;
359 } else {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100360 ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
destradaa96a14702014-06-05 11:36:30 -0700361 }
362
363 if (isSupported) {
destradaa931a37f2014-08-12 16:36:59 -0700364 jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
365 ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
destradaa96a14702014-06-05 11:36:30 -0700366 env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
367 agps_status->status, byteArray);
368
369 checkAndClearExceptionFromCallback(env, __FUNCTION__);
370 } else {
371 ALOGD("Skipping calling method_reportAGpsStatus.");
372 }
373
374 if (byteArray) {
375 env->DeleteLocalRef(byteArray);
376 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700377}
378
Mike Lockwoode3635c92009-05-11 08:38:02 -0400379AGpsCallbacks sAGpsCallbacks = {
380 agps_status_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700381 create_thread_callback,
Mike Lockwood58bda982009-04-14 16:25:07 -0400382};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383
Mike Lockwoodf602d362010-06-20 14:28:16 -0700384static void gps_ni_notify_callback(GpsNiNotification *notification)
385{
Steve Block5baa3a62011-12-20 16:23:08 +0000386 ALOGD("gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700387 JNIEnv* env = AndroidRuntime::getJNIEnv();
388 jstring requestor_id = env->NewStringUTF(notification->requestor_id);
389 jstring text = env->NewStringUTF(notification->text);
390 jstring extras = env->NewStringUTF(notification->extras);
391
392 if (requestor_id && text && extras) {
393 env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
394 notification->notification_id, notification->ni_type,
395 notification->notify_flags, notification->timeout,
396 notification->default_response, requestor_id, text,
397 notification->requestor_id_encoding,
398 notification->text_encoding, extras);
399 } else {
Steve Block3762c312012-01-06 19:20:56 +0000400 ALOGE("out of memory in gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700401 }
402
403 if (requestor_id)
404 env->DeleteLocalRef(requestor_id);
405 if (text)
406 env->DeleteLocalRef(text);
407 if (extras)
408 env->DeleteLocalRef(extras);
409 checkAndClearExceptionFromCallback(env, __FUNCTION__);
410}
411
Danke Xie22d1f9f2009-08-18 18:28:45 -0400412GpsNiCallbacks sGpsNiCallbacks = {
413 gps_ni_notify_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700414 create_thread_callback,
Danke Xie22d1f9f2009-08-18 18:28:45 -0400415};
416
Miguel Torroja1e84da82010-07-27 07:02:24 +0200417static void agps_request_set_id(uint32_t flags)
418{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200419 JNIEnv* env = AndroidRuntime::getJNIEnv();
420 env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
421 checkAndClearExceptionFromCallback(env, __FUNCTION__);
422}
423
424static void agps_request_ref_location(uint32_t flags)
425{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200426 JNIEnv* env = AndroidRuntime::getJNIEnv();
427 env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
428 checkAndClearExceptionFromCallback(env, __FUNCTION__);
429}
430
431AGpsRilCallbacks sAGpsRilCallbacks = {
432 agps_request_set_id,
433 agps_request_ref_location,
434 create_thread_callback,
435};
436
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700437static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location,
438 int32_t transition, GpsUtcTime timestamp)
439{
440 JNIEnv* env = AndroidRuntime::getJNIEnv();
441
442 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
443 location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
444 (jdouble)location->altitude,
445 (jfloat)location->speed, (jfloat)location->bearing,
446 (jfloat)location->accuracy, (jlong)location->timestamp,
447 transition, timestamp);
448 checkAndClearExceptionFromCallback(env, __FUNCTION__);
449};
450
451static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
452{
453 JNIEnv* env = AndroidRuntime::getJNIEnv();
454 jint flags = 0;
455 jdouble latitude = 0;
456 jdouble longitude = 0;
457 jdouble altitude = 0;
458 jfloat speed = 0;
459 jfloat bearing = 0;
460 jfloat accuracy = 0;
461 jlong timestamp = 0;
462 if (location != NULL) {
463 flags = location->flags;
464 latitude = location->latitude;
465 longitude = location->longitude;
466 altitude = location->altitude;
467 speed = location->speed;
468 bearing = location->bearing;
469 accuracy = location->accuracy;
470 timestamp = location->timestamp;
471 }
472
473 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
474 flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
475 checkAndClearExceptionFromCallback(env, __FUNCTION__);
476};
477
478static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
479{
480 JNIEnv* env = AndroidRuntime::getJNIEnv();
481 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
482 ALOGE("Error in geofence_add_callback: %d\n", status);
483 }
484 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
485 checkAndClearExceptionFromCallback(env, __FUNCTION__);
486};
487
488static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
489{
490 JNIEnv* env = AndroidRuntime::getJNIEnv();
491 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
492 ALOGE("Error in geofence_remove_callback: %d\n", status);
493 }
494 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
495 checkAndClearExceptionFromCallback(env, __FUNCTION__);
496};
497
498static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
499{
500 JNIEnv* env = AndroidRuntime::getJNIEnv();
501 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
502 ALOGE("Error in geofence_resume_callback: %d\n", status);
503 }
504 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
505 checkAndClearExceptionFromCallback(env, __FUNCTION__);
506};
507
508static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
509{
510 JNIEnv* env = AndroidRuntime::getJNIEnv();
511 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
512 ALOGE("Error in geofence_pause_callback: %d\n", status);
513 }
514 env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
515 checkAndClearExceptionFromCallback(env, __FUNCTION__);
516};
517
518GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
519 gps_geofence_transition_callback,
520 gps_geofence_status_callback,
521 gps_geofence_add_callback,
522 gps_geofence_remove_callback,
523 gps_geofence_pause_callback,
524 gps_geofence_resume_callback,
525 create_thread_callback,
526};
527
Lifu Tang30f95a72016-01-07 23:20:38 -0800528static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400529 int err;
530 hw_module_t* module;
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400531
Mike Lockwoodbea31182010-10-05 14:29:53 -0400532 method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
533 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
534 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
destradaa96a14702014-06-05 11:36:30 -0700535 method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400536 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
537 method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
Lifu Tang9363b942016-02-16 18:07:00 -0800538 method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400539 method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800540 method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
541 "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400542 method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
543 method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400544 method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700545 method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
546 "(IIDDDFFFJIJ)V");
547 method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
548 "(IIDDDFFFJ)V");
549 method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
550 "(II)V");
551 method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
552 "(II)V");
553 method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
554 "(II)V");
555 method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
556 "(II)V");
destradaaea8a8a62014-06-23 18:19:03 -0700557 method_reportMeasurementData = env->GetMethodID(
558 clazz,
559 "reportMeasurementData",
Lifu Tang818aa2c2016-02-01 01:52:00 -0800560 "(Landroid/location/GnssMeasurementsEvent;)V");
destradaa4b3e3932014-07-21 18:01:47 -0700561 method_reportNavigationMessages = env->GetMethodID(
562 clazz,
563 "reportNavigationMessage",
Lifu Tang818aa2c2016-02-01 01:52:00 -0800564 "(Landroid/location/GnssNavigationMessageEvent;)V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800565
566 err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
567 if (err == 0) {
568 hw_device_t* device;
569 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
570 if (err == 0) {
571 gps_device_t* gps_device = (gps_device_t *)device;
572 sGpsInterface = gps_device->get_gps_interface(gps_device);
573 }
574 }
575 if (sGpsInterface) {
576 sGpsXtraInterface =
577 (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
578 sAGpsInterface =
579 (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
580 sGpsNiInterface =
581 (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
582 sGpsDebugInterface =
583 (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
584 sAGpsRilInterface =
585 (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700586 sGpsGeofencingInterface =
587 (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
destradaaea8a8a62014-06-23 18:19:03 -0700588 sGpsMeasurementInterface =
589 (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
destradaa4b3e3932014-07-21 18:01:47 -0700590 sGpsNavigationMessageInterface =
591 (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
592 GPS_NAVIGATION_MESSAGE_INTERFACE);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700593 sGnssConfigurationInterface =
594 (const GnssConfigurationInterface*)sGpsInterface->get_extension(
595 GNSS_CONFIGURATION_INTERFACE);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800596 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400597}
598
Lifu Tang30f95a72016-01-07 23:20:38 -0800599static jboolean android_location_GnssLocationProvider_is_supported(
destradaaef752b62015-04-17 13:10:47 -0700600 JNIEnv* /* env */, jclass /* clazz */)
601{
602 return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE;
603}
604
Lifu Tang30f95a72016-01-07 23:20:38 -0800605static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
destradaaef752b62015-04-17 13:10:47 -0700606 JNIEnv* /* env */, jclass /* clazz */)
607{
608 return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
609}
610
611static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
612 JNIEnv* /* env */, jclass /* jclazz */)
613{
614 return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615}
616
Lifu Tang30f95a72016-01-07 23:20:38 -0800617static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800619 // this must be set before calling into the HAL library
620 if (!mCallbacksObj)
621 mCallbacksObj = env->NewGlobalRef(obj);
622
623 // fail if the main interface fails to initialize
624 if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000625 return JNI_FALSE;
Mike Lockwood58bda982009-04-14 16:25:07 -0400626
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700627 // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800628 // but continue to allow the rest of the GPS interface to work.
629 if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
630 sGpsXtraInterface = NULL;
631 if (sAGpsInterface)
632 sAGpsInterface->init(&sAGpsCallbacks);
633 if (sGpsNiInterface)
634 sGpsNiInterface->init(&sGpsNiCallbacks);
635 if (sAGpsRilInterface)
636 sAGpsRilInterface->init(&sAGpsRilCallbacks);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700637 if (sGpsGeofencingInterface)
638 sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600639
Narayan Kamath87d6cd42014-01-08 12:26:28 +0000640 return JNI_TRUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641}
642
Lifu Tang30f95a72016-01-07 23:20:38 -0800643static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800645 if (sGpsInterface)
646 sGpsInterface->cleanup();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647}
648
Lifu Tang30f95a72016-01-07 23:20:38 -0800649static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700650 jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
651 jint preferred_time)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000653 if (sGpsInterface) {
654 if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
655 preferred_time) == 0) {
656 return JNI_TRUE;
657 } else {
658 return JNI_FALSE;
659 }
660 }
Mike Lockwood42702372010-10-10 16:04:18 -0400661 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000662 return JNI_FALSE;
Mike Lockwood04598b62010-04-14 17:17:24 -0400663}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
Lifu Tang30f95a72016-01-07 23:20:38 -0800665static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
Mike Lockwood04598b62010-04-14 17:17:24 -0400666{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000667 if (sGpsInterface) {
668 if (sGpsInterface->start() == 0) {
669 return JNI_TRUE;
670 } else {
671 return JNI_FALSE;
672 }
673 }
Mike Lockwood42702372010-10-10 16:04:18 -0400674 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000675 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676}
677
Lifu Tang30f95a72016-01-07 23:20:38 -0800678static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000680 if (sGpsInterface) {
681 if (sGpsInterface->stop() == 0) {
682 return JNI_TRUE;
683 } else {
684 return JNI_FALSE;
685 }
686 }
Mike Lockwood42702372010-10-10 16:04:18 -0400687 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000688 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689}
690
Lifu Tang30f95a72016-01-07 23:20:38 -0800691static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700692 jobject /* obj */,
693 jint flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800695 if (sGpsInterface)
696 sGpsInterface->delete_aiding_data(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697}
698
Lifu Tang30f95a72016-01-07 23:20:38 -0800699static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
Lifu Tang120480f2016-02-07 18:08:19 -0800700 jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
701 jfloatArray azumArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700703 // this should only be called from within a call to reportSvStatus
Lifu Tang120480f2016-02-07 18:08:19 -0800704 jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
706 jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
707 jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708
Lifu Tang30f95a72016-01-07 23:20:38 -0800709 // GNSS SV info.
710 for (size_t i = 0; i < sGnssSvListSize; ++i) {
711 const GnssSvInfo& info = sGnssSvList[i];
Lifu Tang120480f2016-02-07 18:08:19 -0800712 svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
713 (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
714 info.flags;
Lifu Tang30f95a72016-01-07 23:20:38 -0800715 snrs[i] = info.snr;
716 elev[i] = info.elevation;
717 azim[i] = info.azimuth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719
Lifu Tang120480f2016-02-07 18:08:19 -0800720 env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 env->ReleaseFloatArrayElements(snrArray, snrs, 0);
722 env->ReleaseFloatArrayElements(elevArray, elev, 0);
723 env->ReleaseFloatArrayElements(azumArray, azim, 0);
Lifu Tang30f95a72016-01-07 23:20:38 -0800724 return (jint) sGnssSvListSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725}
726
Lifu Tang30f95a72016-01-07 23:20:38 -0800727static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700728 JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200729{
730 AGpsRefLocation location;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800731
732 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000733 ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200734 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400735 }
736
Miguel Torroja1e84da82010-07-27 07:02:24 +0200737 switch(type) {
738 case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
739 case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
740 location.type = type;
741 location.u.cellID.mcc = mcc;
742 location.u.cellID.mnc = mnc;
743 location.u.cellID.lac = lac;
744 location.u.cellID.cid = cid;
745 break;
746 default:
Steve Block3762c312012-01-06 19:20:56 +0000747 ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200748 return;
749 break;
750 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800751 sAGpsRilInterface->set_ref_location(&location, sizeof(location));
Miguel Torroja1e84da82010-07-27 07:02:24 +0200752}
753
Lifu Tang30f95a72016-01-07 23:20:38 -0800754static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700755 jobject /* obj */, jbyteArray ni_msg, jint size)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200756{
757 size_t sz;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800758
759 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000760 ALOGE("no AGPS RIL interface in send_ni_message");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200761 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400762 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200763 if (size < 0)
764 return;
765 sz = (size_t)size;
766 jbyte* b = env->GetByteArrayElements(ni_msg, 0);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800767 sAGpsRilInterface->ni_message((uint8_t *)b,sz);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200768 env->ReleaseByteArrayElements(ni_msg,b,0);
769}
770
Lifu Tang30f95a72016-01-07 23:20:38 -0800771static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700772 jint type, jstring setid_string)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200773{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800774 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000775 ALOGE("no AGPS RIL interface in agps_set_id");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200776 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400777 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200778
779 const char *setid = env->GetStringUTFChars(setid_string, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800780 sAGpsRilInterface->set_set_id(type, setid);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200781 env->ReleaseStringUTFChars(setid_string, setid);
782}
783
Lifu Tang30f95a72016-01-07 23:20:38 -0800784static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700785 jbyteArray nmeaArray, jint buffer_size)
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400786{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700787 // this should only be called from within a call to reportNmea
788 jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
789 int length = sNmeaStringLength;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400790 if (length > buffer_size)
791 length = buffer_size;
Mike Lockwoodf602d362010-06-20 14:28:16 -0700792 memcpy(nmea, sNmeaString, length);
793 env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000794 return (jint) length;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400795}
796
Lifu Tang30f95a72016-01-07 23:20:38 -0800797static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700798 jlong time, jlong timeReference, jint uncertainty)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800800 if (sGpsInterface)
801 sGpsInterface->inject_time(time, timeReference, uncertainty);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802}
803
Lifu Tang30f95a72016-01-07 23:20:38 -0800804static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700805 jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400806{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800807 if (sGpsInterface)
808 sGpsInterface->inject_location(latitude, longitude, accuracy);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400809}
810
Lifu Tang30f95a72016-01-07 23:20:38 -0800811static jboolean android_location_GnssLocationProvider_supports_xtra(
destradaaef752b62015-04-17 13:10:47 -0700812 JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813{
destradaaef752b62015-04-17 13:10:47 -0700814 return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815}
816
Lifu Tang30f95a72016-01-07 23:20:38 -0800817static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 jbyteArray data, jint length)
819{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800820 if (!sGpsXtraInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000821 ALOGE("no XTRA interface in inject_xtra_data");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800822 return;
823 }
824
Mike Lockwoodf602d362010-06-20 14:28:16 -0700825 jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700827 env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828}
829
Lifu Tang30f95a72016-01-07 23:20:38 -0800830static void android_location_GnssLocationProvider_agps_data_conn_open(
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700831 JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
The Android Open Source Project10592532009-03-18 17:39:46 -0700832{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800833 if (!sAGpsInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000834 ALOGE("no AGPS interface in agps_data_conn_open");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400835 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700836 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400837 if (apn == NULL) {
838 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
839 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700840 }
destradaa96a14702014-06-05 11:36:30 -0700841
Mike Lockwoodbea31182010-10-05 14:29:53 -0400842 const char *apnStr = env->GetStringUTFChars(apn, NULL);
destradaa96a14702014-06-05 11:36:30 -0700843
844 size_t interface_size = sAGpsInterface->size;
Lifu Tanga8b7bb52016-01-26 01:22:10 -0800845 if (interface_size == sizeof(AGpsInterface)) {
destradaa96a14702014-06-05 11:36:30 -0700846 sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
847 } else if (interface_size == sizeof(AGpsInterface_v1)) {
848 sAGpsInterface->data_conn_open(apnStr);
849 } else {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100850 ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
destradaa96a14702014-06-05 11:36:30 -0700851 }
852
Mike Lockwoodbea31182010-10-05 14:29:53 -0400853 env->ReleaseStringUTFChars(apn, apnStr);
The Android Open Source Project10592532009-03-18 17:39:46 -0700854}
855
Lifu Tang30f95a72016-01-07 23:20:38 -0800856static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700857 jobject /* obj */)
Mike Lockwood58bda982009-04-14 16:25:07 -0400858{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800859 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100860 ALOGE("no AGPS interface in agps_data_conn_closed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400861 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400862 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800863 sAGpsInterface->data_conn_closed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400864}
865
Lifu Tang30f95a72016-01-07 23:20:38 -0800866static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700867 jobject /* obj */)
Mike Lockwood58bda982009-04-14 16:25:07 -0400868{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800869 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100870 ALOGE("no AGPS interface in agps_data_conn_failed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400871 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400872 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800873 sAGpsInterface->data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400874}
875
Lifu Tang30f95a72016-01-07 23:20:38 -0800876static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
Mike Lockwooda9e54612009-06-19 14:54:42 -0400877 jint type, jstring hostname, jint port)
Mike Lockwood58bda982009-04-14 16:25:07 -0400878{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800879 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100880 ALOGE("no AGPS interface in set_agps_server");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400881 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400882 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400883 const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800884 sAGpsInterface->set_server(type, c_hostname, port);
Mike Lockwoodbea31182010-10-05 14:29:53 -0400885 env->ReleaseStringUTFChars(hostname, c_hostname);
Mike Lockwood58bda982009-04-14 16:25:07 -0400886}
887
Lifu Tang30f95a72016-01-07 23:20:38 -0800888static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700889 jobject /* obj */, jint notifId, jint response)
Danke Xie22d1f9f2009-08-18 18:28:45 -0400890{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800891 if (!sGpsNiInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000892 ALOGE("no NI interface in send_ni_response");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400893 return;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600894 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400895
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800896 sGpsNiInterface->respond(notifId, response);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600897}
898
Lifu Tang30f95a72016-01-07 23:20:38 -0800899static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700900 jobject /* obj */) {
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600901 jstring result = NULL;
902 if (sGpsDebugInterface) {
903 const size_t maxLength = 2047;
904 char buffer[maxLength+1];
905 size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
906 if (length > maxLength) length = maxLength;
907 buffer[length] = 0;
908 result = env->NewStringUTF(buffer);
909 }
910 return result;
Danke Xie22d1f9f2009-08-18 18:28:45 -0400911}
912
Lifu Tang30f95a72016-01-07 23:20:38 -0800913static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000914 jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
Mike Lockwood50130bb2010-10-11 06:22:50 -0400915{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800916
917 if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
Mike Lockwood50130bb2010-10-11 06:22:50 -0400918 if (extraInfo) {
919 const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800920 sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400921 env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
922 } else {
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800923 sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400924 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700925
926 // update_network_availability callback was not included in original AGpsRilInterface
927 if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
928 && sAGpsRilInterface->update_network_availability) {
929 const char *c_apn = env->GetStringUTFChars(apn, NULL);
930 sAGpsRilInterface->update_network_availability(available, c_apn);
931 env->ReleaseStringUTFChars(apn, c_apn);
932 }
Mike Lockwood50130bb2010-10-11 06:22:50 -0400933 }
934}
935
Lifu Tang30f95a72016-01-07 23:20:38 -0800936static jboolean android_location_GnssLocationProvider_is_geofence_supported(
destradaaef752b62015-04-17 13:10:47 -0700937 JNIEnv* /* env */, jobject /* obj */)
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700938{
destradaaef752b62015-04-17 13:10:47 -0700939 return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700940}
941
Lifu Tang30f95a72016-01-07 23:20:38 -0800942static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700943 jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700944 jint last_transition, jint monitor_transition, jint notification_responsiveness,
945 jint unknown_timer) {
946 if (sGpsGeofencingInterface != NULL) {
947 sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
948 radius, last_transition, monitor_transition, notification_responsiveness,
949 unknown_timer);
950 return JNI_TRUE;
951 } else {
952 ALOGE("Geofence interface not available");
953 }
954 return JNI_FALSE;
955}
956
Lifu Tang30f95a72016-01-07 23:20:38 -0800957static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700958 jobject /* obj */, jint geofence_id) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700959 if (sGpsGeofencingInterface != NULL) {
960 sGpsGeofencingInterface->remove_geofence_area(geofence_id);
961 return JNI_TRUE;
962 } else {
963 ALOGE("Geofence interface not available");
964 }
965 return JNI_FALSE;
966}
967
Lifu Tang30f95a72016-01-07 23:20:38 -0800968static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700969 jobject /* obj */, jint geofence_id) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700970 if (sGpsGeofencingInterface != NULL) {
971 sGpsGeofencingInterface->pause_geofence(geofence_id);
972 return JNI_TRUE;
973 } else {
974 ALOGE("Geofence interface not available");
975 }
976 return JNI_FALSE;
977}
978
Lifu Tang30f95a72016-01-07 23:20:38 -0800979static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700980 jobject /* obj */, jint geofence_id, jint monitor_transition) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700981 if (sGpsGeofencingInterface != NULL) {
982 sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
983 return JNI_TRUE;
984 } else {
985 ALOGE("Geofence interface not available");
986 }
987 return JNI_FALSE;
988}
989
Lifu Tang120480f2016-02-07 18:08:19 -0800990template<class T>
991class JavaMethodHelper {
992 public:
993 // Helper function to call setter on a Java object.
994 static void callJavaMethod(
995 JNIEnv* env,
996 jclass clazz,
997 jobject object,
998 const char* method_name,
999 T value);
destradaaea8a8a62014-06-23 18:19:03 -07001000
Lifu Tang120480f2016-02-07 18:08:19 -08001001 private:
1002 static const char *const signature_;
1003};
Lifu Tange5a0e212016-01-25 18:02:17 -08001004
Lifu Tang120480f2016-02-07 18:08:19 -08001005template<class T>
1006void JavaMethodHelper<T>::callJavaMethod(
1007 JNIEnv* env,
1008 jclass clazz,
1009 jobject object,
1010 const char* method_name,
1011 T value) {
1012 jmethodID method = env->GetMethodID(clazz, method_name, signature_);
1013 env->CallVoidMethod(object, method, value);
1014}
destradaaea8a8a62014-06-23 18:19:03 -07001015
Lifu Tang120480f2016-02-07 18:08:19 -08001016class JavaObject {
1017 public:
1018 JavaObject(JNIEnv* env, const char* class_name);
1019 virtual ~JavaObject();
1020
1021 template<class T>
1022 void callSetter(const char* method_name, T value);
1023 template<class T>
1024 void callSetter(const char* method_name, T* value, size_t size);
1025 jobject get();
1026
1027 private:
1028 JNIEnv* env_;
1029 jclass clazz_;
1030 jobject object_;
1031};
1032
1033JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
1034 clazz_ = env_->FindClass(class_name);
1035 jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
1036 object_ = env_->NewObject(clazz_, ctor);
1037}
1038
1039JavaObject::~JavaObject() {
1040 env_->DeleteLocalRef(clazz_);
1041}
1042
1043template<class T>
1044void JavaObject::callSetter(const char* method_name, T value) {
1045 JavaMethodHelper<T>::callJavaMethod(
1046 env_, clazz_, object_, method_name, value);
1047}
1048
1049template<>
1050void JavaObject::callSetter(
1051 const char* method_name, uint8_t* value, size_t size) {
1052 jbyteArray array = env_->NewByteArray(size);
1053 env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
1054 jmethodID method = env_->GetMethodID(
1055 clazz_,
1056 method_name,
1057 "([B)V");
1058 env_->CallVoidMethod(object_, method, array);
1059}
1060
1061jobject JavaObject::get() {
1062 return object_;
1063}
1064
1065// Define Java method signatures for all known types.
1066
1067template<>
1068const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
1069template<>
1070const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
1071template<>
1072const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
1073template<>
1074const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
1075template<>
Lifu Tang9363b942016-02-16 18:07:00 -08001076const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
1077template<>
1078const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
Lifu Tang120480f2016-02-07 18:08:19 -08001079template<>
1080const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
1081template<>
1082const char *const JavaMethodHelper<float>::signature_ = "(F)V";
1083template<>
1084const char *const JavaMethodHelper<double>::signature_ = "(D)V";
1085template<>
1086const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
1087
1088#define SET(setter, value) object.callSetter("set" # setter, (value))
1089#define SET_IF(flag, setter, value) \
1090 if (flags & (flag)) object.callSetter("set" # setter, (value))
1091
1092static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
1093 JavaObject object(env, "android/location/GnssClock");
destradaaea8a8a62014-06-23 18:19:03 -07001094 GpsClockFlags flags = clock->flags;
1095
Lifu Tang9363b942016-02-16 18:07:00 -08001096 SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
Lifu Tang120480f2016-02-07 18:08:19 -08001097 SET(Type, clock->type);
1098 SET(TimeInNs, clock->time_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001099 SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001100 TimeUncertaintyInNs,
1101 clock->time_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001102 SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
1103 SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
1104 SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001105 BiasUncertaintyInNs,
1106 clock->bias_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001107 SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
1108 SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001109 DriftUncertaintyInNsPerSec,
1110 clock->drift_uncertainty_nsps);
destradaaea8a8a62014-06-23 18:19:03 -07001111
Lifu Tang120480f2016-02-07 18:08:19 -08001112 return object.get();
destradaaea8a8a62014-06-23 18:19:03 -07001113}
1114
Lifu Tang120480f2016-02-07 18:08:19 -08001115static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
1116 JavaObject object(env, "android/location/GnssClock");
1117 GpsClockFlags flags = clock->flags;
destradaaea8a8a62014-06-23 18:19:03 -07001118
Lifu Tang9363b942016-02-16 18:07:00 -08001119 SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
1120 SET(Type, static_cast<uint8_t>(GPS_CLOCK_TYPE_LOCAL_HW_TIME));
Lifu Tang120480f2016-02-07 18:08:19 -08001121 SET(TimeInNs, clock->time_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001122 SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001123 TimeUncertaintyInNs,
1124 clock->time_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001125 SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
1126 SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
1127 SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001128 BiasUncertaintyInNs,
1129 clock->bias_uncertainty_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001130 SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
1131 SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001132 DriftUncertaintyInNsPerSec,
1133 clock->drift_uncertainty_nsps);
destradaaea8a8a62014-06-23 18:19:03 -07001134
Lifu Tang9363b942016-02-16 18:07:00 -08001135 SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
Lifu Tang120480f2016-02-07 18:08:19 -08001136
1137 return object.get();
1138}
1139
1140static jobject translate_gps_measurement(JNIEnv* env,
1141 GpsMeasurement* measurement) {
1142 JavaObject object(env, "android/location/GnssMeasurement");
destradaaea8a8a62014-06-23 18:19:03 -07001143 GpsMeasurementFlags flags = measurement->flags;
Lifu Tang120480f2016-02-07 18:08:19 -08001144 SET(Svid, static_cast<int16_t>(measurement->prn));
Lifu Tang9363b942016-02-16 18:07:00 -08001145 if (measurement->prn >= 1 || measurement->prn <= 32) {
1146 SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
1147 } else {
1148 ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
1149 SET(ConstellationType,
1150 static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
1151 }
Lifu Tang120480f2016-02-07 18:08:19 -08001152 SET(TimeOffsetInNs, measurement->time_offset_ns);
1153 SET(State, measurement->state);
Lifu Tang9363b942016-02-16 18:07:00 -08001154 SET(ReceivedSvTimeInNs, measurement->received_gps_tow_ns);
1155 SET(ReceivedSvTimeUncertaintyInNs,
Lifu Tang120480f2016-02-07 18:08:19 -08001156 measurement->received_gps_tow_uncertainty_ns);
1157 SET(Cn0InDbHz, measurement->c_n0_dbhz);
1158 SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
1159 SET(PseudorangeRateUncertaintyInMetersPerSec,
1160 measurement->pseudorange_rate_uncertainty_mps);
1161 SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
1162 SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
1163 SET(AccumulatedDeltaRangeUncertaintyInMeters,
1164 measurement->accumulated_delta_range_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001165 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
Lifu Tang120480f2016-02-07 18:08:19 -08001166 PseudorangeInMeters,
1167 measurement->pseudorange_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001168 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001169 PseudorangeUncertaintyInMeters,
1170 measurement->pseudorange_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001171 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001172 CodePhaseInChips,
1173 measurement->code_phase_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001174 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001175 CodePhaseUncertaintyInChips,
1176 measurement->code_phase_uncertainty_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001177 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
Lifu Tang120480f2016-02-07 18:08:19 -08001178 CarrierFrequencyInHz,
1179 measurement->carrier_frequency_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001180 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
Lifu Tang120480f2016-02-07 18:08:19 -08001181 CarrierCycles,
1182 measurement->carrier_cycles);
Lifu Tang9363b942016-02-16 18:07:00 -08001183 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001184 CarrierPhase,
1185 measurement->carrier_phase);
Lifu Tang9363b942016-02-16 18:07:00 -08001186 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001187 CarrierPhaseUncertainty,
1188 measurement->carrier_phase_uncertainty);
1189 SET(LossOfLock, measurement->loss_of_lock);
Lifu Tang9363b942016-02-16 18:07:00 -08001190 SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
1191 SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
Lifu Tang120480f2016-02-07 18:08:19 -08001192 TimeFromLastBitInMs,
1193 measurement->time_from_last_bit_ms);
Lifu Tang9363b942016-02-16 18:07:00 -08001194 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
Lifu Tang120480f2016-02-07 18:08:19 -08001195 DopplerShiftInHz,
1196 measurement->doppler_shift_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001197 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001198 DopplerShiftUncertaintyInHz,
1199 measurement->doppler_shift_uncertainty_hz);
1200 SET(MultipathIndicator, measurement->multipath_indicator);
Lifu Tang9363b942016-02-16 18:07:00 -08001201 SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
1202 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
Lifu Tang120480f2016-02-07 18:08:19 -08001203 ElevationInDeg,
1204 measurement->elevation_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001205 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001206 ElevationUncertaintyInDeg,
1207 measurement->elevation_uncertainty_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001208 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
Lifu Tang120480f2016-02-07 18:08:19 -08001209 AzimuthInDeg,
1210 measurement->azimuth_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001211 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001212 AzimuthUncertaintyInDeg,
1213 measurement->azimuth_uncertainty_deg);
1214 SET(UsedInFix,
Lifu Tang9363b942016-02-16 18:07:00 -08001215 (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
destradaaea8a8a62014-06-23 18:19:03 -07001216
Lifu Tang120480f2016-02-07 18:08:19 -08001217 return object.get();
destradaaea8a8a62014-06-23 18:19:03 -07001218}
1219
Lifu Tang120480f2016-02-07 18:08:19 -08001220static jobject translate_gnss_measurement(JNIEnv* env,
1221 GnssMeasurement* measurement) {
1222 JavaObject object(env, "android/location/GnssMeasurement");
1223 GpsMeasurementFlags flags = measurement->flags;
1224
1225 SET(Svid, measurement->svid);
Lifu Tang9363b942016-02-16 18:07:00 -08001226 SET(ConstellationType, measurement->constellation);
Lifu Tang120480f2016-02-07 18:08:19 -08001227 SET(TimeOffsetInNs, measurement->time_offset_ns);
1228 SET(State, measurement->state);
Lifu Tang9363b942016-02-16 18:07:00 -08001229 SET(ReceivedSvTimeInNs, measurement->received_sv_time_in_ns);
1230 SET(ReceivedSvTimeUncertaintyInNs,
1231 measurement->received_sv_time_uncertainty_in_ns);
Lifu Tang120480f2016-02-07 18:08:19 -08001232 SET(Cn0InDbHz, measurement->c_n0_dbhz);
1233 SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
1234 SET(PseudorangeRateUncertaintyInMetersPerSec,
1235 measurement->pseudorange_rate_uncertainty_mps);
1236 SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
1237 SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
1238 SET(AccumulatedDeltaRangeUncertaintyInMeters,
1239 measurement->accumulated_delta_range_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001240 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
Lifu Tang120480f2016-02-07 18:08:19 -08001241 PseudorangeInMeters,
1242 measurement->pseudorange_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001243 SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001244 PseudorangeUncertaintyInMeters,
1245 measurement->pseudorange_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001246 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001247 CodePhaseInChips,
1248 measurement->code_phase_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001249 SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001250 CodePhaseUncertaintyInChips,
1251 measurement->code_phase_uncertainty_chips);
Lifu Tang9363b942016-02-16 18:07:00 -08001252 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
Lifu Tang120480f2016-02-07 18:08:19 -08001253 CarrierFrequencyInHz,
1254 measurement->carrier_frequency_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001255 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
Lifu Tang120480f2016-02-07 18:08:19 -08001256 CarrierCycles,
1257 measurement->carrier_cycles);
Lifu Tang9363b942016-02-16 18:07:00 -08001258 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001259 CarrierPhase,
1260 measurement->carrier_phase);
Lifu Tang9363b942016-02-16 18:07:00 -08001261 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001262 CarrierPhaseUncertainty,
1263 measurement->carrier_phase_uncertainty);
Lifu Tang9363b942016-02-16 18:07:00 -08001264 SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
1265 SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
Lifu Tang120480f2016-02-07 18:08:19 -08001266 TimeFromLastBitInMs,
1267 measurement->time_from_last_bit_ms);
Lifu Tang9363b942016-02-16 18:07:00 -08001268 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
Lifu Tang120480f2016-02-07 18:08:19 -08001269 DopplerShiftInHz,
1270 measurement->doppler_shift_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001271 SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001272 DopplerShiftUncertaintyInHz,
1273 measurement->doppler_shift_uncertainty_hz);
1274 SET(MultipathIndicator, measurement->multipath_indicator);
Lifu Tang9363b942016-02-16 18:07:00 -08001275 SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
1276 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
Lifu Tang120480f2016-02-07 18:08:19 -08001277 ElevationInDeg,
1278 measurement->elevation_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001279 SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001280 ElevationUncertaintyInDeg,
1281 measurement->elevation_uncertainty_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001282 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
Lifu Tang120480f2016-02-07 18:08:19 -08001283 AzimuthInDeg,
1284 measurement->azimuth_deg);
Lifu Tang9363b942016-02-16 18:07:00 -08001285 SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001286 AzimuthUncertaintyInDeg,
1287 measurement->azimuth_uncertainty_deg);
1288 SET(UsedInFix,
Lifu Tang9363b942016-02-16 18:07:00 -08001289 (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
Lifu Tang120480f2016-02-07 18:08:19 -08001290
1291 return object.get();
1292}
1293
1294static jobjectArray translate_gps_measurements(JNIEnv* env,
1295 GpsMeasurement* measurements,
1296 size_t count) {
1297 if (count == 0) {
destradaaea8a8a62014-06-23 18:19:03 -07001298 return NULL;
1299 }
1300
Lifu Tang120480f2016-02-07 18:08:19 -08001301 jclass gnssMeasurementClass = env->FindClass(
1302 "android/location/GnssMeasurement");
Lifu Tang818aa2c2016-02-01 01:52:00 -08001303 jobjectArray gnssMeasurementArray = env->NewObjectArray(
Lifu Tang120480f2016-02-07 18:08:19 -08001304 count,
Lifu Tang818aa2c2016-02-01 01:52:00 -08001305 gnssMeasurementClass,
destradaaea8a8a62014-06-23 18:19:03 -07001306 NULL /* initialElement */);
1307
Lifu Tang120480f2016-02-07 18:08:19 -08001308 for (uint16_t i = 0; i < count; ++i) {
Lifu Tang818aa2c2016-02-01 01:52:00 -08001309 jobject gnssMeasurement = translate_gps_measurement(
Lifu Tange5a0e212016-01-25 18:02:17 -08001310 env,
Lifu Tang120480f2016-02-07 18:08:19 -08001311 &measurements[i]);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001312 env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1313 env->DeleteLocalRef(gnssMeasurement);
destradaaea8a8a62014-06-23 18:19:03 -07001314 }
1315
Lifu Tang818aa2c2016-02-01 01:52:00 -08001316 env->DeleteLocalRef(gnssMeasurementClass);
1317 return gnssMeasurementArray;
destradaaea8a8a62014-06-23 18:19:03 -07001318}
1319
Lifu Tang120480f2016-02-07 18:08:19 -08001320static jobjectArray translate_gnss_measurements(JNIEnv* env,
1321 GnssMeasurement* measurements,
1322 size_t count) {
1323 if (count == 0) {
1324 return NULL;
destradaaea8a8a62014-06-23 18:19:03 -07001325 }
Lifu Tange5a0e212016-01-25 18:02:17 -08001326
Lifu Tang120480f2016-02-07 18:08:19 -08001327 jclass gnssMeasurementClass = env->FindClass(
1328 "android/location/GnssMeasurement");
1329 jobjectArray gnssMeasurementArray = env->NewObjectArray(
1330 count,
1331 gnssMeasurementClass,
1332 NULL /* initialElement */);
1333
1334 for (uint16_t i = 0; i < count; ++i) {
1335 jobject gnssMeasurement = translate_gnss_measurement(
1336 env,
1337 &measurements[i]);
1338 env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1339 env->DeleteLocalRef(gnssMeasurement);
Lifu Tange5a0e212016-01-25 18:02:17 -08001340 }
Lifu Tang120480f2016-02-07 18:08:19 -08001341
1342 env->DeleteLocalRef(gnssMeasurementClass);
1343 return gnssMeasurementArray;
1344}
1345
1346static void set_measurement_data(JNIEnv *env,
1347 jobject clock,
1348 jobjectArray measurementArray) {
1349 jclass gnssMeasurementsEventClass = env->FindClass(
1350 "android/location/GnssMeasurementsEvent");
Lifu Tang818aa2c2016-02-01 01:52:00 -08001351 jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
1352 gnssMeasurementsEventClass,
Lifu Tange5a0e212016-01-25 18:02:17 -08001353 "<init>",
Lifu Tang818aa2c2016-02-01 01:52:00 -08001354 "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
Lifu Tange5a0e212016-01-25 18:02:17 -08001355
Lifu Tang818aa2c2016-02-01 01:52:00 -08001356 jobject gnssMeasurementsEvent = env->NewObject(
1357 gnssMeasurementsEventClass,
1358 gnssMeasurementsEventCtor,
Lifu Tang120480f2016-02-07 18:08:19 -08001359 clock,
Lifu Tange5a0e212016-01-25 18:02:17 -08001360 measurementArray);
Lifu Tang120480f2016-02-07 18:08:19 -08001361 env->CallVoidMethod(mCallbacksObj,
1362 method_reportMeasurementData,
1363 gnssMeasurementsEvent);
Lifu Tange5a0e212016-01-25 18:02:17 -08001364 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001365 env->DeleteLocalRef(gnssMeasurementsEventClass);
1366 env->DeleteLocalRef(gnssMeasurementsEvent);
destradaaea8a8a62014-06-23 18:19:03 -07001367}
1368
Lifu Tang120480f2016-02-07 18:08:19 -08001369static void measurement_callback(GpsData* data) {
1370 JNIEnv* env = AndroidRuntime::getJNIEnv();
1371 if (data == NULL) {
1372 ALOGE("Invalid data provided to gps_measurement_callback");
1373 return;
1374 }
1375 if (data->size != sizeof(GpsData)) {
1376 ALOGE("Invalid GpsData size found in gps_measurement_callback, "
1377 "size=%zd",
1378 data->size);
1379 return;
1380 }
1381
1382 jobject clock;
1383 jobjectArray measurementArray;
1384 clock = translate_gps_clock(env, &data->clock);
1385 measurementArray = translate_gps_measurements(
1386 env, data->measurements, data->measurement_count);
1387 set_measurement_data(env, clock, measurementArray);
1388
1389 env->DeleteLocalRef(clock);
1390 env->DeleteLocalRef(measurementArray);
1391}
1392
1393static void gnss_measurement_callback(GnssData* data) {
1394 JNIEnv* env = AndroidRuntime::getJNIEnv();
1395 if (data == NULL) {
1396 ALOGE("Invalid data provided to gps_measurement_callback");
1397 return;
1398 }
1399 if (data->size != sizeof(GpsData)) {
1400 ALOGE("Invalid GpsData size found in gps_measurement_callback, "
1401 "size=%zd",
1402 data->size);
1403 return;
1404 }
1405
1406 jobject clock;
1407 jobjectArray measurementArray;
1408 clock = translate_gnss_clock(env, &data->clock);
1409 measurementArray = translate_gnss_measurements(
1410 env, data->measurements, data->measurement_count);
1411 set_measurement_data(env, clock, measurementArray);
1412
1413 env->DeleteLocalRef(clock);
1414 env->DeleteLocalRef(measurementArray);
1415}
1416
destradaaea8a8a62014-06-23 18:19:03 -07001417GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
1418 sizeof(GpsMeasurementCallbacks),
1419 measurement_callback,
Lifu Tang120480f2016-02-07 18:08:19 -08001420 gnss_measurement_callback,
destradaaea8a8a62014-06-23 18:19:03 -07001421};
1422
Lifu Tang30f95a72016-01-07 23:20:38 -08001423static jboolean android_location_GnssLocationProvider_is_measurement_supported(
destradaaea8a8a62014-06-23 18:19:03 -07001424 JNIEnv* env,
destradaa4b3e3932014-07-21 18:01:47 -07001425 jclass clazz) {
destradaaea8a8a62014-06-23 18:19:03 -07001426 if (sGpsMeasurementInterface != NULL) {
1427 return JNI_TRUE;
1428 }
1429 return JNI_FALSE;
1430}
1431
Lifu Tang30f95a72016-01-07 23:20:38 -08001432static jboolean android_location_GnssLocationProvider_start_measurement_collection(
destradaaea8a8a62014-06-23 18:19:03 -07001433 JNIEnv* env,
1434 jobject obj) {
1435 if (sGpsMeasurementInterface == NULL) {
1436 ALOGE("Measurement interface is not available.");
1437 return JNI_FALSE;
1438 }
1439
1440 int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
1441 if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
1442 ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
1443 return JNI_FALSE;
1444 }
1445
1446 return JNI_TRUE;
1447}
1448
Lifu Tang30f95a72016-01-07 23:20:38 -08001449static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
destradaaea8a8a62014-06-23 18:19:03 -07001450 JNIEnv* env,
1451 jobject obj) {
1452 if (sGpsMeasurementInterface == NULL) {
1453 ALOGE("Measurement interface not available");
1454 return JNI_FALSE;
1455 }
1456
1457 sGpsMeasurementInterface->close();
1458 return JNI_TRUE;
1459}
1460
destradaa4b3e3932014-07-21 18:01:47 -07001461static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
1462 size_t dataLength = message->data_length;
1463 uint8_t* data = message->data;
1464 if (dataLength == 0 || data == NULL) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +01001465 ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
destradaa4b3e3932014-07-21 18:01:47 -07001466 return NULL;
1467 }
Lifu Tang120480f2016-02-07 18:08:19 -08001468 JavaObject object(env, "android/location/GnssNavigationMessage");
Lifu Tang120480f2016-02-07 18:08:19 -08001469 SET(Svid, static_cast<int16_t>(message->prn));
Lifu Tang9363b942016-02-16 18:07:00 -08001470 if (message->prn >=1 && message->prn <= 32) {
1471 SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
1472 // Legacy driver doesn't set the higher byte to constellation type
1473 // correctly. Set the higher byte to 'GPS'.
1474 SET(Type, static_cast<int16_t>(message->type | 0x0100));
1475 } else {
1476 ALOGD("Unknown constellation type with Svid = %d.", message->prn);
1477 SET(ConstellationType,
1478 static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
1479 SET(Type, static_cast<int16_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
1480 }
Lifu Tang120480f2016-02-07 18:08:19 -08001481 SET(MessageId, message->message_id);
1482 SET(SubmessageId, message->submessage_id);
1483 object.callSetter("setData", data, dataLength);
1484 return object.get();
1485}
destradaa4b3e3932014-07-21 18:01:47 -07001486
Lifu Tang120480f2016-02-07 18:08:19 -08001487static jobject translate_gnss_navigation_message(
1488 JNIEnv* env, GnssNavigationMessage* message) {
1489 size_t dataLength = message->data_length;
1490 uint8_t* data = message->data;
1491 if (dataLength == 0 || data == NULL) {
1492 ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
1493 return NULL;
1494 }
1495 JavaObject object(env, "android/location/GnssNavigationMessage");
1496 SET(Type, message->type);
1497 SET(Svid, message->svid);
1498 SET(MessageId, message->message_id);
1499 SET(SubmessageId, message->submessage_id);
1500 object.callSetter("setData", data, dataLength);
1501 return object.get();
1502}
destradaa4b3e3932014-07-21 18:01:47 -07001503
Lifu Tang120480f2016-02-07 18:08:19 -08001504static void set_navigation_message(jobject navigationMessage) {
1505 JNIEnv* env = AndroidRuntime::getJNIEnv();
1506 jclass navigationMessageEventClass =
1507 env->FindClass("android/location/GnssNavigationMessageEvent");
1508 jmethodID navigationMessageEventCtor = env->GetMethodID(
1509 navigationMessageEventClass,
1510 "<init>",
1511 "(Landroid/location/GnssNavigationMessage;)V");
1512 jobject navigationMessageEvent = env->NewObject(
1513 navigationMessageEventClass,
1514 navigationMessageEventCtor,
1515 navigationMessage);
1516 env->CallVoidMethod(mCallbacksObj,
1517 method_reportNavigationMessages,
1518 navigationMessageEvent);
1519 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1520 env->DeleteLocalRef(navigationMessageEventClass);
1521 env->DeleteLocalRef(navigationMessageEvent);
destradaa4b3e3932014-07-21 18:01:47 -07001522}
1523
1524static void navigation_message_callback(GpsNavigationMessage* message) {
destradaa4b3e3932014-07-21 18:01:47 -07001525 if (message == NULL) {
1526 ALOGE("Invalid Navigation Message provided to callback");
1527 return;
1528 }
Lifu Tang120480f2016-02-07 18:08:19 -08001529 if (message->size != sizeof(GpsNavigationMessage)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +01001530 ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
Lifu Tang120480f2016-02-07 18:08:19 -08001531 return;
destradaa4b3e3932014-07-21 18:01:47 -07001532 }
Lifu Tang120480f2016-02-07 18:08:19 -08001533 JNIEnv* env = AndroidRuntime::getJNIEnv();
1534 jobject navigationMessage = translate_gps_navigation_message(env, message);
1535 set_navigation_message(navigationMessage);
1536 env->DeleteLocalRef(navigationMessage);
1537}
1538
1539static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
1540 if (message == NULL) {
1541 ALOGE("Invalid Navigation Message provided to callback");
1542 return;
1543 }
1544 if (message->size != sizeof(GnssNavigationMessage)) {
1545 ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
1546 return;
1547 }
1548 JNIEnv* env = AndroidRuntime::getJNIEnv();
1549 jobject navigationMessage = translate_gnss_navigation_message(env, message);
1550 set_navigation_message(navigationMessage);
1551 env->DeleteLocalRef(navigationMessage);
destradaa4b3e3932014-07-21 18:01:47 -07001552}
1553
1554GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
1555 sizeof(GpsNavigationMessageCallbacks),
1556 navigation_message_callback,
Lifu Tang120480f2016-02-07 18:08:19 -08001557 gnss_navigation_message_callback,
destradaa4b3e3932014-07-21 18:01:47 -07001558};
1559
Lifu Tang30f95a72016-01-07 23:20:38 -08001560static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
destradaa4b3e3932014-07-21 18:01:47 -07001561 JNIEnv* env,
1562 jclass clazz) {
1563 if(sGpsNavigationMessageInterface != NULL) {
1564 return JNI_TRUE;
1565 }
1566 return JNI_FALSE;
1567}
1568
Lifu Tang30f95a72016-01-07 23:20:38 -08001569static jboolean android_location_GnssLocationProvider_start_navigation_message_collection(
destradaa4b3e3932014-07-21 18:01:47 -07001570 JNIEnv* env,
1571 jobject obj) {
1572 if (sGpsNavigationMessageInterface == NULL) {
1573 ALOGE("Navigation Message interface is not available.");
1574 return JNI_FALSE;
1575 }
1576
1577 int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
1578 if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
1579 ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
1580 return JNI_FALSE;
1581 }
1582
1583 return JNI_TRUE;
1584}
1585
Lifu Tang30f95a72016-01-07 23:20:38 -08001586static jboolean android_location_GnssLocationProvider_stop_navigation_message_collection(
destradaa4b3e3932014-07-21 18:01:47 -07001587 JNIEnv* env,
1588 jobject obj) {
1589 if (sGpsNavigationMessageInterface == NULL) {
1590 ALOGE("Navigation Message interface is not available.");
1591 return JNI_FALSE;
1592 }
1593
1594 sGpsNavigationMessageInterface->close();
1595 return JNI_TRUE;
1596}
1597
Lifu Tang30f95a72016-01-07 23:20:38 -08001598static void android_location_GnssLocationProvider_configuration_update(JNIEnv* env, jobject obj,
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001599 jstring config_content)
1600{
1601 if (!sGnssConfigurationInterface) {
1602 ALOGE("no GPS configuration interface in configuraiton_update");
1603 return;
1604 }
1605 const char *data = env->GetStringUTFChars(config_content, NULL);
1606 ALOGD("GPS configuration:\n %s", data);
1607 sGnssConfigurationInterface->configuration_update(
1608 data, env->GetStringUTFLength(config_content));
1609 env->ReleaseStringUTFChars(config_content, data);
1610}
1611
Daniel Micay76f6a862015-09-19 17:31:01 -04001612static const JNINativeMethod sMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 /* name, signature, funcPtr */
Lifu Tang30f95a72016-01-07 23:20:38 -08001614 {"class_init_native", "()V", (void *)android_location_GnssLocationProvider_class_init_native},
1615 {"native_is_supported", "()Z", (void*)android_location_GnssLocationProvider_is_supported},
destradaaef752b62015-04-17 13:10:47 -07001616 {"native_is_agps_ril_supported", "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001617 (void*)android_location_GnssLocationProvider_is_agps_ril_supported},
destradaaef752b62015-04-17 13:10:47 -07001618 {"native_is_gnss_configuration_supported", "()Z",
1619 (void*)android_location_gpsLocationProvider_is_gnss_configuration_supported},
Lifu Tang30f95a72016-01-07 23:20:38 -08001620 {"native_init", "()Z", (void*)android_location_GnssLocationProvider_init},
1621 {"native_cleanup", "()V", (void*)android_location_GnssLocationProvider_cleanup},
destradaaea8a8a62014-06-23 18:19:03 -07001622 {"native_set_position_mode",
1623 "(IIIII)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001624 (void*)android_location_GnssLocationProvider_set_position_mode},
1625 {"native_start", "()Z", (void*)android_location_GnssLocationProvider_start},
1626 {"native_stop", "()Z", (void*)android_location_GnssLocationProvider_stop},
destradaaea8a8a62014-06-23 18:19:03 -07001627 {"native_delete_aiding_data",
1628 "(I)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001629 (void*)android_location_GnssLocationProvider_delete_aiding_data},
destradaaea8a8a62014-06-23 18:19:03 -07001630 {"native_read_sv_status",
Lifu Tang120480f2016-02-07 18:08:19 -08001631 "([I[F[F[F)I",
Lifu Tang30f95a72016-01-07 23:20:38 -08001632 (void*)android_location_GnssLocationProvider_read_sv_status},
1633 {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
1634 {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},
destradaaea8a8a62014-06-23 18:19:03 -07001635 {"native_inject_location",
1636 "(DDF)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001637 (void*)android_location_GnssLocationProvider_inject_location},
1638 {"native_supports_xtra", "()Z", (void*)android_location_GnssLocationProvider_supports_xtra},
destradaaea8a8a62014-06-23 18:19:03 -07001639 {"native_inject_xtra_data",
1640 "([BI)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001641 (void*)android_location_GnssLocationProvider_inject_xtra_data},
destradaaea8a8a62014-06-23 18:19:03 -07001642 {"native_agps_data_conn_open",
1643 "(Ljava/lang/String;I)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001644 (void*)android_location_GnssLocationProvider_agps_data_conn_open},
destradaaea8a8a62014-06-23 18:19:03 -07001645 {"native_agps_data_conn_closed",
1646 "()V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001647 (void*)android_location_GnssLocationProvider_agps_data_conn_closed},
destradaaea8a8a62014-06-23 18:19:03 -07001648 {"native_agps_data_conn_failed",
1649 "()V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001650 (void*)android_location_GnssLocationProvider_agps_data_conn_failed},
destradaaea8a8a62014-06-23 18:19:03 -07001651 {"native_agps_set_id",
1652 "(ILjava/lang/String;)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001653 (void*)android_location_GnssLocationProvider_agps_set_id},
destradaaea8a8a62014-06-23 18:19:03 -07001654 {"native_agps_set_ref_location_cellid",
1655 "(IIIII)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001656 (void*)android_location_GnssLocationProvider_agps_set_reference_location_cellid},
destradaaea8a8a62014-06-23 18:19:03 -07001657 {"native_set_agps_server",
1658 "(ILjava/lang/String;I)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001659 (void*)android_location_GnssLocationProvider_set_agps_server},
destradaaea8a8a62014-06-23 18:19:03 -07001660 {"native_send_ni_response",
1661 "(II)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001662 (void*)android_location_GnssLocationProvider_send_ni_response},
destradaaea8a8a62014-06-23 18:19:03 -07001663 {"native_agps_ni_message",
1664 "([BI)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001665 (void *)android_location_GnssLocationProvider_agps_send_ni_message},
destradaaea8a8a62014-06-23 18:19:03 -07001666 {"native_get_internal_state",
1667 "()Ljava/lang/String;",
Lifu Tang30f95a72016-01-07 23:20:38 -08001668 (void*)android_location_GnssLocationProvider_get_internal_state},
destradaaea8a8a62014-06-23 18:19:03 -07001669 {"native_update_network_state",
1670 "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001671 (void*)android_location_GnssLocationProvider_update_network_state },
destradaaea8a8a62014-06-23 18:19:03 -07001672 {"native_is_geofence_supported",
1673 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001674 (void*) android_location_GnssLocationProvider_is_geofence_supported},
destradaaea8a8a62014-06-23 18:19:03 -07001675 {"native_add_geofence",
1676 "(IDDDIIII)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001677 (void *)android_location_GnssLocationProvider_add_geofence},
destradaaea8a8a62014-06-23 18:19:03 -07001678 {"native_remove_geofence",
1679 "(I)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001680 (void *)android_location_GnssLocationProvider_remove_geofence},
1681 {"native_pause_geofence", "(I)Z", (void *)android_location_GnssLocationProvider_pause_geofence},
destradaaea8a8a62014-06-23 18:19:03 -07001682 {"native_resume_geofence",
1683 "(II)Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001684 (void *)android_location_GnssLocationProvider_resume_geofence},
destradaaea8a8a62014-06-23 18:19:03 -07001685 {"native_is_measurement_supported",
1686 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001687 (void*) android_location_GnssLocationProvider_is_measurement_supported},
destradaaea8a8a62014-06-23 18:19:03 -07001688 {"native_start_measurement_collection",
1689 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001690 (void*) android_location_GnssLocationProvider_start_measurement_collection},
destradaaea8a8a62014-06-23 18:19:03 -07001691 {"native_stop_measurement_collection",
1692 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001693 (void*) android_location_GnssLocationProvider_stop_measurement_collection},
destradaa4b3e3932014-07-21 18:01:47 -07001694 {"native_is_navigation_message_supported",
1695 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001696 (void*) android_location_GnssLocationProvider_is_navigation_message_supported},
destradaa4b3e3932014-07-21 18:01:47 -07001697 {"native_start_navigation_message_collection",
1698 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001699 (void*) android_location_GnssLocationProvider_start_navigation_message_collection},
destradaa4b3e3932014-07-21 18:01:47 -07001700 {"native_stop_navigation_message_collection",
1701 "()Z",
Lifu Tang30f95a72016-01-07 23:20:38 -08001702 (void*) android_location_GnssLocationProvider_stop_navigation_message_collection},
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001703 {"native_configuration_update",
1704 "(Ljava/lang/String;)V",
Lifu Tang30f95a72016-01-07 23:20:38 -08001705 (void*)android_location_GnssLocationProvider_configuration_update},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706};
1707
Lifu Tang30f95a72016-01-07 23:20:38 -08001708int register_android_server_location_GnssLocationProvider(JNIEnv* env)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709{
destradaaea8a8a62014-06-23 18:19:03 -07001710 return jniRegisterNativeMethods(
1711 env,
Lifu Tang30f95a72016-01-07 23:20:38 -08001712 "com/android/server/location/GnssLocationProvider",
destradaaea8a8a62014-06-23 18:19:03 -07001713 sMethods,
1714 NELEM(sMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715}
1716
1717} /* namespace android */