blob: e8d4c58213cc910bb30676754be4178e62031656 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Lifu Tang30f95a72016-01-07 23:20:38 -080017#define LOG_TAG "GnssLocationProvider"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Mike Lockwoodb8d90332010-10-18 17:59:48 -040019#define LOG_NDEBUG 0
Danke Xie22d1f9f2009-08-18 18:28:45 -040020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021#include "JNIHelp.h"
22#include "jni.h"
Mike Lockwoodb7ff4572010-04-05 15:24:34 -040023#include "hardware/hardware.h"
Lifu Tanga8b7bb52016-01-26 01:22:10 -080024#include "hardware/gps_internal.h"
Mike Lockwood8f5a8002010-04-07 09:05:26 -040025#include "hardware_legacy/power.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include "utils/Log.h"
27#include "utils/misc.h"
Mike Lockwoodf602d362010-06-20 14:28:16 -070028#include "android_runtime/AndroidRuntime.h"
Ruben Brunk87eac992013-09-09 17:44:59 -070029#include "android_runtime/Log.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030
destradaa931a37f2014-08-12 16:36:59 -070031#include <arpa/inet.h>
Lifu Tang38bce792016-02-24 17:17:38 -080032#include <limits>
destradaa96a14702014-06-05 11:36:30 -070033#include <linux/in.h>
34#include <linux/in6.h>
Lifu Tang38bce792016-02-24 17:17:38 -080035#include <pthread.h>
36#include <string.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
Mike Lockwoodf602d362010-06-20 14:28:16 -070038static jobject mCallbacksObj = NULL;
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040static jmethodID method_reportLocation;
41static jmethodID method_reportStatus;
42static jmethodID method_reportSvStatus;
Mike Lockwoode3635c92009-05-11 08:38:02 -040043static jmethodID method_reportAGpsStatus;
Mike Lockwoodb16e7802009-08-06 09:26:02 -040044static jmethodID method_reportNmea;
Mike Lockwood04598b62010-04-14 17:17:24 -040045static jmethodID method_setEngineCapabilities;
Lifu Tang9363b942016-02-16 18:07:00 -080046static jmethodID method_setGnssYearOfHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047static jmethodID method_xtraDownloadRequest;
Danke Xie22d1f9f2009-08-18 18:28:45 -040048static jmethodID method_reportNiNotification;
Miguel Torroja1e84da82010-07-27 07:02:24 +020049static jmethodID method_requestRefLocation;
50static jmethodID method_requestSetID;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -040051static jmethodID method_requestUtcTime;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070052static jmethodID method_reportGeofenceTransition;
53static jmethodID method_reportGeofenceStatus;
54static jmethodID method_reportGeofenceAddStatus;
55static jmethodID method_reportGeofenceRemoveStatus;
56static jmethodID method_reportGeofencePauseStatus;
57static jmethodID method_reportGeofenceResumeStatus;
destradaaea8a8a62014-06-23 18:19:03 -070058static jmethodID method_reportMeasurementData;
destradaa4b3e3932014-07-21 18:01:47 -070059static jmethodID method_reportNavigationMessages;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060
61static const GpsInterface* sGpsInterface = NULL;
62static const GpsXtraInterface* sGpsXtraInterface = NULL;
Mike Lockwoode3635c92009-05-11 08:38:02 -040063static const AGpsInterface* sAGpsInterface = NULL;
Danke Xie22d1f9f2009-08-18 18:28:45 -040064static const GpsNiInterface* sGpsNiInterface = NULL;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -060065static const GpsDebugInterface* sGpsDebugInterface = NULL;
Miguel Torroja1e84da82010-07-27 07:02:24 +020066static const AGpsRilInterface* sAGpsRilInterface = NULL;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070067static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
destradaaea8a8a62014-06-23 18:19:03 -070068static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
destradaa4b3e3932014-07-21 18:01:47 -070069static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
Tsuwei Chen52617bb2014-08-25 11:49:11 -070070static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
Lifu Tang120480f2016-02-07 18:08:19 -080072#define GPS_MAX_SATELLITE_COUNT 32
73#define GNSS_MAX_SATELLITE_COUNT 64
Lifu Tang30f95a72016-01-07 23:20:38 -080074
Wyatt Rileyf6527ae2016-05-23 15:23:12 -070075// Let these through, with ID remapped down to 1, 2... by offset
Wyatt Riley49d98912016-05-17 16:14:48 -070076#define GLONASS_SVID_OFFSET 64
77#define GLONASS_SVID_COUNT 24
78#define BEIDOU_SVID_OFFSET 200
79#define BEIDOU_SVID_COUNT 35
80
Wyatt Rileyf6527ae2016-05-23 15:23:12 -070081// Let these through, with ID remapped up (33->120 ... 64->151, etc.)
82#define SBAS_SVID_MIN 33
83#define SBAS_SVID_MAX 64
84#define SBAS_SVID_ADD 87
85
Wyatt Riley49d98912016-05-17 16:14:48 -070086// Let these through, with no ID remapping
Wyatt Riley49d98912016-05-17 16:14:48 -070087#define QZSS_SVID_MIN 193
88#define QZSS_SVID_MAX 200
89
Lifu Tang120480f2016-02-07 18:08:19 -080090#define SVID_SHIFT_WIDTH 7
91#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
Lifu Tang30f95a72016-01-07 23:20:38 -080092
Mike Lockwoodf602d362010-06-20 14:28:16 -070093// temporary storage for GPS callbacks
Lifu Tang120480f2016-02-07 18:08:19 -080094static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
Lifu Tang30f95a72016-01-07 23:20:38 -080095static size_t sGnssSvListSize;
Mike Lockwoodf602d362010-06-20 14:28:16 -070096static const char* sNmeaString;
97static int sNmeaStringLength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098
Mike Lockwood8f5a8002010-04-07 09:05:26 -040099#define WAKE_LOCK_NAME "GPS"
100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101namespace android {
102
Mike Lockwoodf602d362010-06-20 14:28:16 -0700103static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
104 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +0000105 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700106 LOGE_EX(env);
107 env->ExceptionClear();
108 }
109}
110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111static void location_callback(GpsLocation* location)
112{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700113 JNIEnv* env = AndroidRuntime::getJNIEnv();
114 env->CallVoidMethod(mCallbacksObj, method_reportLocation, location->flags,
115 (jdouble)location->latitude, (jdouble)location->longitude,
116 (jdouble)location->altitude,
117 (jfloat)location->speed, (jfloat)location->bearing,
118 (jfloat)location->accuracy, (jlong)location->timestamp);
119 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120}
121
122static void status_callback(GpsStatus* status)
123{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700124 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf602d362010-06-20 14:28:16 -0700125 env->CallVoidMethod(mCallbacksObj, method_reportStatus, status->status);
126 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127}
128
129static void sv_status_callback(GpsSvStatus* sv_status)
130{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700131 JNIEnv* env = AndroidRuntime::getJNIEnv();
Lifu Tang30f95a72016-01-07 23:20:38 -0800132 size_t status_size = sv_status->size;
Lifu Tang120480f2016-02-07 18:08:19 -0800133 // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
134 // if it doesn't provide a valid size.
Lifu Tang30f95a72016-01-07 23:20:38 -0800135 if (status_size == 0) {
Lifu Tang120480f2016-02-07 18:08:19 -0800136 ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
Lifu Tang30f95a72016-01-07 23:20:38 -0800137 }
Lifu Tang120480f2016-02-07 18:08:19 -0800138 sGnssSvListSize = sv_status->num_svs;
139 // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
140 if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
Lifu Tanga2b74fd2016-02-11 12:57:59 -0800141 ALOGW("Too many satellites %zd. Clamps to %d.",
Lifu Tang120480f2016-02-07 18:08:19 -0800142 sGnssSvListSize,
143 GPS_MAX_SATELLITE_COUNT);
144 sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
145 }
146 uint32_t ephemeris_mask = sv_status->ephemeris_mask;
147 uint32_t almanac_mask = sv_status->almanac_mask;
148 uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
149 for (size_t i = 0; i < sGnssSvListSize; i++) {
150 GnssSvInfo& info = sGnssSvList[i];
151 info.svid = sv_status->sv_list[i].prn;
Wyatt Riley49d98912016-05-17 16:14:48 -0700152 // Defacto mapping from the overused API that was designed for GPS-only
Lifu Tang120480f2016-02-07 18:08:19 -0800153 if (info.svid >=1 && info.svid <= 32) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800154 info.constellation = GNSS_CONSTELLATION_GPS;
Wyatt Riley49d98912016-05-17 16:14:48 -0700155 } else if (info.svid > GLONASS_SVID_OFFSET &&
156 info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
157 info.constellation = GNSS_CONSTELLATION_GLONASS;
158 info.svid -= GLONASS_SVID_OFFSET;
159 } else if (info.svid > BEIDOU_SVID_OFFSET &&
160 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
161 info.constellation = GNSS_CONSTELLATION_BEIDOU;
162 info.svid -= BEIDOU_SVID_OFFSET;
163 } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
164 info.constellation = GNSS_CONSTELLATION_SBAS;
Wyatt Rileyf6527ae2016-05-23 15:23:12 -0700165 info.svid += SBAS_SVID_ADD;
Wyatt Riley49d98912016-05-17 16:14:48 -0700166 } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
167 info.constellation = GNSS_CONSTELLATION_QZSS;
Lifu Tang120480f2016-02-07 18:08:19 -0800168 } else {
Lifu Tang9363b942016-02-16 18:07:00 -0800169 ALOGD("Unknown constellation type with Svid = %d.", info.svid);
Lifu Tang120480f2016-02-07 18:08:19 -0800170 info.constellation = GNSS_CONSTELLATION_UNKNOWN;
171 }
Lifu Tang76a620f2016-02-26 19:53:01 -0800172 info.c_n0_dbhz = sv_status->sv_list[i].snr;
Lifu Tang120480f2016-02-07 18:08:19 -0800173 info.elevation = sv_status->sv_list[i].elevation;
174 info.azimuth = sv_status->sv_list[i].azimuth;
175 info.flags = GNSS_SV_FLAGS_NONE;
Wyatt Riley49d98912016-05-17 16:14:48 -0700176 // Only GPS info is valid for these fields, as these masks are just 32 bits, by GPS prn
177 if (info.constellation == GNSS_CONSTELLATION_GPS) {
Lifu Tang120480f2016-02-07 18:08:19 -0800178 int32_t this_svid_mask = (1 << (info.svid - 1));
179 if ((ephemeris_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800180 info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
Lifu Tang120480f2016-02-07 18:08:19 -0800181 }
182 if ((almanac_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800183 info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
Lifu Tang120480f2016-02-07 18:08:19 -0800184 }
185 if ((used_in_fix_mask & this_svid_mask) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -0800186 info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
187 }
188 }
Lifu Tang120480f2016-02-07 18:08:19 -0800189 }
190 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
191 checkAndClearExceptionFromCallback(env, __FUNCTION__);
192}
193
194static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
195 JNIEnv* env = AndroidRuntime::getJNIEnv();
196 size_t status_size = sv_status->size;
197 // Check the size, and reject the object that has invalid size.
198 if (status_size != sizeof(GnssSvStatus)) {
199 ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
Lifu Tang30f95a72016-01-07 23:20:38 -0800200 return;
201 }
Lifu Tang120480f2016-02-07 18:08:19 -0800202 sGnssSvListSize = sv_status->num_svs;
203 // Clamp the list size
204 if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
Lifu Tanga2b74fd2016-02-11 12:57:59 -0800205 ALOGD("Too many satellites %zd. Clamps to %d.",
Lifu Tang120480f2016-02-07 18:08:19 -0800206 sGnssSvListSize,
207 GNSS_MAX_SATELLITE_COUNT);
208 sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
209 }
210 // Copy GNSS SV info into sGnssSvList, if any.
211 if (sGnssSvListSize > 0) {
212 memcpy(sGnssSvList,
213 sv_status->gnss_sv_list,
214 sizeof(GnssSvInfo) * sGnssSvListSize);
215 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700216 env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
217 checkAndClearExceptionFromCallback(env, __FUNCTION__);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218}
219
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400220static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
221{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700222 JNIEnv* env = AndroidRuntime::getJNIEnv();
223 // The Java code will call back to read these values
224 // We do this to avoid creating unnecessary String objects
225 sNmeaString = nmea;
226 sNmeaStringLength = length;
227 env->CallVoidMethod(mCallbacksObj, method_reportNmea, timestamp);
228 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400229}
230
Lifu Tang9363b942016-02-16 18:07:00 -0800231static void set_system_info_callback(const GnssSystemInfo* info) {
Lifu Tang82f893d2016-01-21 18:15:33 -0800232 ALOGD("set_system_info_callback: year_of_hw=%d\n", info->year_of_hw);
233 JNIEnv* env = AndroidRuntime::getJNIEnv();
Lifu Tang9363b942016-02-16 18:07:00 -0800234 env->CallVoidMethod(mCallbacksObj, method_setGnssYearOfHardware,
Lifu Tang82f893d2016-01-21 18:15:33 -0800235 info->year_of_hw);
236 checkAndClearExceptionFromCallback(env, __FUNCTION__);
237}
238
Mike Lockwood04598b62010-04-14 17:17:24 -0400239static void set_capabilities_callback(uint32_t capabilities)
240{
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700241 ALOGD("set_capabilities_callback: %du\n", capabilities);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700242 JNIEnv* env = AndroidRuntime::getJNIEnv();
243 env->CallVoidMethod(mCallbacksObj, method_setEngineCapabilities, capabilities);
244 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood04598b62010-04-14 17:17:24 -0400245}
246
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400247static void acquire_wakelock_callback()
248{
249 acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
250}
251
252static void release_wakelock_callback()
253{
254 release_wake_lock(WAKE_LOCK_NAME);
255}
256
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400257static void request_utc_time_callback()
258{
259 JNIEnv* env = AndroidRuntime::getJNIEnv();
260 env->CallVoidMethod(mCallbacksObj, method_requestUtcTime);
261 checkAndClearExceptionFromCallback(env, __FUNCTION__);
262}
263
Mike Lockwoodf602d362010-06-20 14:28:16 -0700264static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg)
Mike Lockwood58bda982009-04-14 16:25:07 -0400265{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700266 return (pthread_t)AndroidRuntime::createJavaThread(name, start, arg);
Mike Lockwood58bda982009-04-14 16:25:07 -0400267}
268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269GpsCallbacks sGpsCallbacks = {
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400270 sizeof(GpsCallbacks),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 location_callback,
272 status_callback,
273 sv_status_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400274 nmea_callback,
Mike Lockwood04598b62010-04-14 17:17:24 -0400275 set_capabilities_callback,
Mike Lockwood8f5a8002010-04-07 09:05:26 -0400276 acquire_wakelock_callback,
277 release_wakelock_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700278 create_thread_callback,
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400279 request_utc_time_callback,
Lifu Tang82f893d2016-01-21 18:15:33 -0800280 set_system_info_callback,
Lifu Tang120480f2016-02-07 18:08:19 -0800281 gnss_sv_status_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282};
283
Mike Lockwoodf602d362010-06-20 14:28:16 -0700284static void xtra_download_request_callback()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700286 JNIEnv* env = AndroidRuntime::getJNIEnv();
287 env->CallVoidMethod(mCallbacksObj, method_xtraDownloadRequest);
288 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Danke Xie22d1f9f2009-08-18 18:28:45 -0400289}
290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291GpsXtraCallbacks sGpsXtraCallbacks = {
Mike Lockwoodf602d362010-06-20 14:28:16 -0700292 xtra_download_request_callback,
293 create_thread_callback,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294};
295
destradaa96a14702014-06-05 11:36:30 -0700296static jbyteArray convert_to_ipv4(uint32_t ip, bool net_order)
297{
298 if (INADDR_NONE == ip) {
299 return NULL;
300 }
301
302 JNIEnv* env = AndroidRuntime::getJNIEnv();
303 jbyteArray byteArray = env->NewByteArray(4);
304 if (byteArray == NULL) {
305 ALOGE("Unable to allocate byte array for IPv4 address");
306 return NULL;
307 }
308
309 jbyte ipv4[4];
310 if (net_order) {
destradaa931a37f2014-08-12 16:36:59 -0700311 ALOGV("Converting IPv4 address(net_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700312 memcpy(ipv4, &ip, sizeof(ipv4));
313 } else {
destradaa931a37f2014-08-12 16:36:59 -0700314 ALOGV("Converting IPv4 address(host_order) %x", ip);
destradaa96a14702014-06-05 11:36:30 -0700315 //endianess transparent conversion from int to char[]
316 ipv4[0] = (jbyte) (ip & 0xFF);
317 ipv4[1] = (jbyte)((ip>>8) & 0xFF);
318 ipv4[2] = (jbyte)((ip>>16) & 0xFF);
319 ipv4[3] = (jbyte) (ip>>24);
320 }
321
322 env->SetByteArrayRegion(byteArray, 0, 4, (const jbyte*) ipv4);
323 return byteArray;
324}
325
Mike Lockwoodf602d362010-06-20 14:28:16 -0700326static void agps_status_callback(AGpsStatus* agps_status)
327{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700328 JNIEnv* env = AndroidRuntime::getJNIEnv();
destradaa96a14702014-06-05 11:36:30 -0700329 jbyteArray byteArray = NULL;
330 bool isSupported = false;
Stephen Li8efd74d2011-03-01 20:56:00 -0800331
destradaa96a14702014-06-05 11:36:30 -0700332 size_t status_size = agps_status->size;
Lifu Tanga8b7bb52016-01-26 01:22:10 -0800333 if (status_size == sizeof(AGpsStatus)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100334 ALOGV("AGpsStatus is V3: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700335 switch (agps_status->addr.ss_family)
336 {
337 case AF_INET:
338 {
339 struct sockaddr_in *in = (struct sockaddr_in*)&(agps_status->addr);
destradaace48c1c2015-05-29 13:47:39 -0700340 uint32_t ipAddr = *(uint32_t*)&(in->sin_addr);
341 byteArray = convert_to_ipv4(ipAddr, true /* net_order */);
342 if (ipAddr == INADDR_NONE || byteArray != NULL) {
destradaa96a14702014-06-05 11:36:30 -0700343 isSupported = true;
344 }
destradaa931a37f2014-08-12 16:36:59 -0700345 IF_ALOGD() {
346 // log the IP for reference in case there is a bogus value pushed by HAL
347 char str[INET_ADDRSTRLEN];
348 inet_ntop(AF_INET, &(in->sin_addr), str, INET_ADDRSTRLEN);
349 ALOGD("AGPS IP is v4: %s", str);
350 }
destradaa96a14702014-06-05 11:36:30 -0700351 }
352 break;
353 case AF_INET6:
354 {
355 struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&(agps_status->addr);
356 byteArray = env->NewByteArray(16);
357 if (byteArray != NULL) {
358 env->SetByteArrayRegion(byteArray, 0, 16, (const jbyte *)&(in6->sin6_addr));
359 isSupported = true;
360 } else {
361 ALOGE("Unable to allocate byte array for IPv6 address.");
362 }
destradaa931a37f2014-08-12 16:36:59 -0700363 IF_ALOGD() {
364 // log the IP for reference in case there is a bogus value pushed by HAL
365 char str[INET6_ADDRSTRLEN];
366 inet_ntop(AF_INET6, &(in6->sin6_addr), str, INET6_ADDRSTRLEN);
367 ALOGD("AGPS IP is v6: %s", str);
368 }
destradaa96a14702014-06-05 11:36:30 -0700369 }
370 break;
371 default:
372 ALOGE("Invalid ss_family found: %d", agps_status->addr.ss_family);
373 break;
374 }
375 } else if (status_size >= sizeof(AGpsStatus_v2)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100376 ALOGV("AGpsStatus is V2+: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700377 // for back-compatibility reasons we check in v2 that the data structure size is greater or
378 // equal to the declared size in gps.h
379 uint32_t ipaddr = agps_status->ipaddr;
destradaa931a37f2014-08-12 16:36:59 -0700380 ALOGV("AGPS IP is v4: %x", ipaddr);
destradaa96a14702014-06-05 11:36:30 -0700381 byteArray = convert_to_ipv4(ipaddr, false /* net_order */);
382 if (ipaddr == INADDR_NONE || byteArray != NULL) {
383 isSupported = true;
384 }
385 } else if (status_size >= sizeof(AGpsStatus_v1)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100386 ALOGV("AGpsStatus is V1+: %zd", status_size);
destradaa96a14702014-06-05 11:36:30 -0700387 // because we have to check for >= with regards to v2, we also need to relax the check here
388 // and only make sure that the size is at least what we expect
389 isSupported = true;
390 } else {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100391 ALOGE("Invalid size of AGpsStatus found: %zd.", status_size);
destradaa96a14702014-06-05 11:36:30 -0700392 }
393
394 if (isSupported) {
destradaa931a37f2014-08-12 16:36:59 -0700395 jsize byteArrayLength = byteArray != NULL ? env->GetArrayLength(byteArray) : 0;
396 ALOGV("Passing AGPS IP addr: size %d", byteArrayLength);
destradaa96a14702014-06-05 11:36:30 -0700397 env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, agps_status->type,
398 agps_status->status, byteArray);
399
400 checkAndClearExceptionFromCallback(env, __FUNCTION__);
401 } else {
402 ALOGD("Skipping calling method_reportAGpsStatus.");
403 }
404
405 if (byteArray) {
406 env->DeleteLocalRef(byteArray);
407 }
Mike Lockwoodf602d362010-06-20 14:28:16 -0700408}
409
Mike Lockwoode3635c92009-05-11 08:38:02 -0400410AGpsCallbacks sAGpsCallbacks = {
411 agps_status_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700412 create_thread_callback,
Mike Lockwood58bda982009-04-14 16:25:07 -0400413};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414
Mike Lockwoodf602d362010-06-20 14:28:16 -0700415static void gps_ni_notify_callback(GpsNiNotification *notification)
416{
Steve Block5baa3a62011-12-20 16:23:08 +0000417 ALOGD("gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700418 JNIEnv* env = AndroidRuntime::getJNIEnv();
419 jstring requestor_id = env->NewStringUTF(notification->requestor_id);
420 jstring text = env->NewStringUTF(notification->text);
421 jstring extras = env->NewStringUTF(notification->extras);
422
423 if (requestor_id && text && extras) {
424 env->CallVoidMethod(mCallbacksObj, method_reportNiNotification,
425 notification->notification_id, notification->ni_type,
426 notification->notify_flags, notification->timeout,
427 notification->default_response, requestor_id, text,
428 notification->requestor_id_encoding,
429 notification->text_encoding, extras);
430 } else {
Steve Block3762c312012-01-06 19:20:56 +0000431 ALOGE("out of memory in gps_ni_notify_callback\n");
Mike Lockwoodf602d362010-06-20 14:28:16 -0700432 }
433
434 if (requestor_id)
435 env->DeleteLocalRef(requestor_id);
436 if (text)
437 env->DeleteLocalRef(text);
438 if (extras)
439 env->DeleteLocalRef(extras);
440 checkAndClearExceptionFromCallback(env, __FUNCTION__);
441}
442
Danke Xie22d1f9f2009-08-18 18:28:45 -0400443GpsNiCallbacks sGpsNiCallbacks = {
444 gps_ni_notify_callback,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700445 create_thread_callback,
Danke Xie22d1f9f2009-08-18 18:28:45 -0400446};
447
Miguel Torroja1e84da82010-07-27 07:02:24 +0200448static void agps_request_set_id(uint32_t flags)
449{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200450 JNIEnv* env = AndroidRuntime::getJNIEnv();
451 env->CallVoidMethod(mCallbacksObj, method_requestSetID, flags);
452 checkAndClearExceptionFromCallback(env, __FUNCTION__);
453}
454
455static void agps_request_ref_location(uint32_t flags)
456{
Miguel Torroja1e84da82010-07-27 07:02:24 +0200457 JNIEnv* env = AndroidRuntime::getJNIEnv();
458 env->CallVoidMethod(mCallbacksObj, method_requestRefLocation, flags);
459 checkAndClearExceptionFromCallback(env, __FUNCTION__);
460}
461
462AGpsRilCallbacks sAGpsRilCallbacks = {
463 agps_request_set_id,
464 agps_request_ref_location,
465 create_thread_callback,
466};
467
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700468static void gps_geofence_transition_callback(int32_t geofence_id, GpsLocation* location,
469 int32_t transition, GpsUtcTime timestamp)
470{
471 JNIEnv* env = AndroidRuntime::getJNIEnv();
472
473 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceTransition, geofence_id,
474 location->flags, (jdouble)location->latitude, (jdouble)location->longitude,
475 (jdouble)location->altitude,
476 (jfloat)location->speed, (jfloat)location->bearing,
477 (jfloat)location->accuracy, (jlong)location->timestamp,
478 transition, timestamp);
479 checkAndClearExceptionFromCallback(env, __FUNCTION__);
480};
481
482static void gps_geofence_status_callback(int32_t status, GpsLocation* location)
483{
484 JNIEnv* env = AndroidRuntime::getJNIEnv();
485 jint flags = 0;
486 jdouble latitude = 0;
487 jdouble longitude = 0;
488 jdouble altitude = 0;
489 jfloat speed = 0;
490 jfloat bearing = 0;
491 jfloat accuracy = 0;
492 jlong timestamp = 0;
493 if (location != NULL) {
494 flags = location->flags;
495 latitude = location->latitude;
496 longitude = location->longitude;
497 altitude = location->altitude;
498 speed = location->speed;
499 bearing = location->bearing;
500 accuracy = location->accuracy;
501 timestamp = location->timestamp;
502 }
503
504 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
505 flags, latitude, longitude, altitude, speed, bearing, accuracy, timestamp);
506 checkAndClearExceptionFromCallback(env, __FUNCTION__);
507};
508
509static void gps_geofence_add_callback(int32_t geofence_id, int32_t status)
510{
511 JNIEnv* env = AndroidRuntime::getJNIEnv();
512 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
513 ALOGE("Error in geofence_add_callback: %d\n", status);
514 }
515 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceAddStatus, geofence_id, status);
516 checkAndClearExceptionFromCallback(env, __FUNCTION__);
517};
518
519static void gps_geofence_remove_callback(int32_t geofence_id, int32_t status)
520{
521 JNIEnv* env = AndroidRuntime::getJNIEnv();
522 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
523 ALOGE("Error in geofence_remove_callback: %d\n", status);
524 }
525 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceRemoveStatus, geofence_id, status);
526 checkAndClearExceptionFromCallback(env, __FUNCTION__);
527};
528
529static void gps_geofence_resume_callback(int32_t geofence_id, int32_t status)
530{
531 JNIEnv* env = AndroidRuntime::getJNIEnv();
532 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
533 ALOGE("Error in geofence_resume_callback: %d\n", status);
534 }
535 env->CallVoidMethod(mCallbacksObj, method_reportGeofenceResumeStatus, geofence_id, status);
536 checkAndClearExceptionFromCallback(env, __FUNCTION__);
537};
538
539static void gps_geofence_pause_callback(int32_t geofence_id, int32_t status)
540{
541 JNIEnv* env = AndroidRuntime::getJNIEnv();
542 if (status != GPS_GEOFENCE_OPERATION_SUCCESS) {
543 ALOGE("Error in geofence_pause_callback: %d\n", status);
544 }
545 env->CallVoidMethod(mCallbacksObj, method_reportGeofencePauseStatus, geofence_id, status);
546 checkAndClearExceptionFromCallback(env, __FUNCTION__);
547};
548
549GpsGeofenceCallbacks sGpsGeofenceCallbacks = {
550 gps_geofence_transition_callback,
551 gps_geofence_status_callback,
552 gps_geofence_add_callback,
553 gps_geofence_remove_callback,
554 gps_geofence_pause_callback,
555 gps_geofence_resume_callback,
556 create_thread_callback,
557};
558
Lifu Tang30f95a72016-01-07 23:20:38 -0800559static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400560 int err;
561 hw_module_t* module;
Mike Lockwoodb7ff4572010-04-05 15:24:34 -0400562
Mike Lockwoodbea31182010-10-05 14:29:53 -0400563 method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
564 method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
565 method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
destradaa96a14702014-06-05 11:36:30 -0700566 method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II[B)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400567 method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");
568 method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
Lifu Tang9363b942016-02-16 18:07:00 -0800569 method_setGnssYearOfHardware = env->GetMethodID(clazz, "setGnssYearOfHardware", "(I)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400570 method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800571 method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
572 "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400573 method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");
574 method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400575 method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700576 method_reportGeofenceTransition = env->GetMethodID(clazz,"reportGeofenceTransition",
577 "(IIDDDFFFJIJ)V");
578 method_reportGeofenceStatus = env->GetMethodID(clazz,"reportGeofenceStatus",
579 "(IIDDDFFFJ)V");
580 method_reportGeofenceAddStatus = env->GetMethodID(clazz,"reportGeofenceAddStatus",
581 "(II)V");
582 method_reportGeofenceRemoveStatus = env->GetMethodID(clazz,"reportGeofenceRemoveStatus",
583 "(II)V");
584 method_reportGeofenceResumeStatus = env->GetMethodID(clazz,"reportGeofenceResumeStatus",
585 "(II)V");
586 method_reportGeofencePauseStatus = env->GetMethodID(clazz,"reportGeofencePauseStatus",
587 "(II)V");
destradaaea8a8a62014-06-23 18:19:03 -0700588 method_reportMeasurementData = env->GetMethodID(
589 clazz,
590 "reportMeasurementData",
Lifu Tang818aa2c2016-02-01 01:52:00 -0800591 "(Landroid/location/GnssMeasurementsEvent;)V");
destradaa4b3e3932014-07-21 18:01:47 -0700592 method_reportNavigationMessages = env->GetMethodID(
593 clazz,
594 "reportNavigationMessage",
Lifu Tang5b49d8a2016-04-12 14:00:14 -0700595 "(Landroid/location/GnssNavigationMessage;)V");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800596
597 err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
598 if (err == 0) {
599 hw_device_t* device;
600 err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
601 if (err == 0) {
602 gps_device_t* gps_device = (gps_device_t *)device;
603 sGpsInterface = gps_device->get_gps_interface(gps_device);
604 }
605 }
606 if (sGpsInterface) {
607 sGpsXtraInterface =
608 (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
609 sAGpsInterface =
610 (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
611 sGpsNiInterface =
612 (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
613 sGpsDebugInterface =
614 (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);
615 sAGpsRilInterface =
616 (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700617 sGpsGeofencingInterface =
618 (const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
destradaaea8a8a62014-06-23 18:19:03 -0700619 sGpsMeasurementInterface =
620 (const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
destradaa4b3e3932014-07-21 18:01:47 -0700621 sGpsNavigationMessageInterface =
622 (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
623 GPS_NAVIGATION_MESSAGE_INTERFACE);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700624 sGnssConfigurationInterface =
625 (const GnssConfigurationInterface*)sGpsInterface->get_extension(
626 GNSS_CONFIGURATION_INTERFACE);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800627 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400628}
629
Lifu Tang30f95a72016-01-07 23:20:38 -0800630static jboolean android_location_GnssLocationProvider_is_supported(
destradaaef752b62015-04-17 13:10:47 -0700631 JNIEnv* /* env */, jclass /* clazz */)
632{
633 return (sGpsInterface != NULL) ? JNI_TRUE : JNI_FALSE;
634}
635
Lifu Tang30f95a72016-01-07 23:20:38 -0800636static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
destradaaef752b62015-04-17 13:10:47 -0700637 JNIEnv* /* env */, jclass /* clazz */)
638{
639 return (sAGpsRilInterface != NULL) ? JNI_TRUE : JNI_FALSE;
640}
641
642static jboolean android_location_gpsLocationProvider_is_gnss_configuration_supported(
643 JNIEnv* /* env */, jclass /* jclazz */)
644{
645 return (sGnssConfigurationInterface != NULL) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646}
647
Lifu Tang30f95a72016-01-07 23:20:38 -0800648static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800650 // this must be set before calling into the HAL library
651 if (!mCallbacksObj)
652 mCallbacksObj = env->NewGlobalRef(obj);
653
654 // fail if the main interface fails to initialize
655 if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000656 return JNI_FALSE;
Mike Lockwood58bda982009-04-14 16:25:07 -0400657
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700658 // if XTRA initialization fails we will disable it by sGpsXtraInterface to NULL,
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800659 // but continue to allow the rest of the GPS interface to work.
660 if (sGpsXtraInterface && sGpsXtraInterface->init(&sGpsXtraCallbacks) != 0)
661 sGpsXtraInterface = NULL;
662 if (sAGpsInterface)
663 sAGpsInterface->init(&sAGpsCallbacks);
664 if (sGpsNiInterface)
665 sGpsNiInterface->init(&sGpsNiCallbacks);
666 if (sAGpsRilInterface)
667 sAGpsRilInterface->init(&sAGpsRilCallbacks);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700668 if (sGpsGeofencingInterface)
669 sGpsGeofencingInterface->init(&sGpsGeofenceCallbacks);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600670
Narayan Kamath87d6cd42014-01-08 12:26:28 +0000671 return JNI_TRUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672}
673
Lifu Tang30f95a72016-01-07 23:20:38 -0800674static void android_location_GnssLocationProvider_cleanup(JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800676 if (sGpsInterface)
677 sGpsInterface->cleanup();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678}
679
Lifu Tang30f95a72016-01-07 23:20:38 -0800680static jboolean android_location_GnssLocationProvider_set_position_mode(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700681 jobject /* obj */, jint mode, jint recurrence, jint min_interval, jint preferred_accuracy,
682 jint preferred_time)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000684 if (sGpsInterface) {
685 if (sGpsInterface->set_position_mode(mode, recurrence, min_interval, preferred_accuracy,
686 preferred_time) == 0) {
687 return JNI_TRUE;
688 } else {
689 return JNI_FALSE;
690 }
691 }
Mike Lockwood42702372010-10-10 16:04:18 -0400692 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000693 return JNI_FALSE;
Mike Lockwood04598b62010-04-14 17:17:24 -0400694}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695
Lifu Tang30f95a72016-01-07 23:20:38 -0800696static jboolean android_location_GnssLocationProvider_start(JNIEnv* /* env */, jobject /* obj */)
Mike Lockwood04598b62010-04-14 17:17:24 -0400697{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000698 if (sGpsInterface) {
699 if (sGpsInterface->start() == 0) {
700 return JNI_TRUE;
701 } else {
702 return JNI_FALSE;
703 }
704 }
Mike Lockwood42702372010-10-10 16:04:18 -0400705 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000706 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707}
708
Lifu Tang30f95a72016-01-07 23:20:38 -0800709static jboolean android_location_GnssLocationProvider_stop(JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710{
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000711 if (sGpsInterface) {
712 if (sGpsInterface->stop() == 0) {
713 return JNI_TRUE;
714 } else {
715 return JNI_FALSE;
716 }
717 }
Mike Lockwood42702372010-10-10 16:04:18 -0400718 else
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000719 return JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720}
721
Lifu Tang30f95a72016-01-07 23:20:38 -0800722static void android_location_GnssLocationProvider_delete_aiding_data(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700723 jobject /* obj */,
724 jint flags)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800726 if (sGpsInterface)
727 sGpsInterface->delete_aiding_data(flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728}
729
Lifu Tang30f95a72016-01-07 23:20:38 -0800730static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
Lifu Tang76a620f2016-02-26 19:53:01 -0800731 jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
Lifu Tang120480f2016-02-07 18:08:19 -0800732 jfloatArray azumArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700734 // this should only be called from within a call to reportSvStatus
Lifu Tang120480f2016-02-07 18:08:19 -0800735 jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
Lifu Tang76a620f2016-02-26 19:53:01 -0800736 jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
738 jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739
Lifu Tang30f95a72016-01-07 23:20:38 -0800740 // GNSS SV info.
741 for (size_t i = 0; i < sGnssSvListSize; ++i) {
742 const GnssSvInfo& info = sGnssSvList[i];
Lifu Tang120480f2016-02-07 18:08:19 -0800743 svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
744 (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
745 info.flags;
Lifu Tang76a620f2016-02-26 19:53:01 -0800746 cn0s[i] = info.c_n0_dbhz;
Lifu Tang30f95a72016-01-07 23:20:38 -0800747 elev[i] = info.elevation;
748 azim[i] = info.azimuth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750
Lifu Tang120480f2016-02-07 18:08:19 -0800751 env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
Lifu Tang76a620f2016-02-26 19:53:01 -0800752 env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 env->ReleaseFloatArrayElements(elevArray, elev, 0);
754 env->ReleaseFloatArrayElements(azumArray, azim, 0);
Lifu Tang30f95a72016-01-07 23:20:38 -0800755 return (jint) sGnssSvListSize;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756}
757
Lifu Tang30f95a72016-01-07 23:20:38 -0800758static void android_location_GnssLocationProvider_agps_set_reference_location_cellid(
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700759 JNIEnv* /* env */, jobject /* obj */, jint type, jint mcc, jint mnc, jint lac, jint cid)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200760{
761 AGpsRefLocation location;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800762
763 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000764 ALOGE("no AGPS RIL interface in agps_set_reference_location_cellid");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200765 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400766 }
767
Miguel Torroja1e84da82010-07-27 07:02:24 +0200768 switch(type) {
769 case AGPS_REF_LOCATION_TYPE_GSM_CELLID:
770 case AGPS_REF_LOCATION_TYPE_UMTS_CELLID:
771 location.type = type;
772 location.u.cellID.mcc = mcc;
773 location.u.cellID.mnc = mnc;
774 location.u.cellID.lac = lac;
775 location.u.cellID.cid = cid;
776 break;
777 default:
Steve Block3762c312012-01-06 19:20:56 +0000778 ALOGE("Neither a GSM nor a UMTS cellid (%s:%d).",__FUNCTION__,__LINE__);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200779 return;
780 break;
781 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800782 sAGpsRilInterface->set_ref_location(&location, sizeof(location));
Miguel Torroja1e84da82010-07-27 07:02:24 +0200783}
784
Lifu Tang30f95a72016-01-07 23:20:38 -0800785static void android_location_GnssLocationProvider_agps_send_ni_message(JNIEnv* env,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700786 jobject /* obj */, jbyteArray ni_msg, jint size)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200787{
788 size_t sz;
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800789
790 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000791 ALOGE("no AGPS RIL interface in send_ni_message");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200792 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400793 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200794 if (size < 0)
795 return;
796 sz = (size_t)size;
797 jbyte* b = env->GetByteArrayElements(ni_msg, 0);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800798 sAGpsRilInterface->ni_message((uint8_t *)b,sz);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200799 env->ReleaseByteArrayElements(ni_msg,b,0);
800}
801
Lifu Tang30f95a72016-01-07 23:20:38 -0800802static void android_location_GnssLocationProvider_agps_set_id(JNIEnv *env, jobject /* obj */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700803 jint type, jstring setid_string)
Miguel Torroja1e84da82010-07-27 07:02:24 +0200804{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800805 if (!sAGpsRilInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000806 ALOGE("no AGPS RIL interface in agps_set_id");
Miguel Torroja1e84da82010-07-27 07:02:24 +0200807 return;
Mike Lockwoodbea31182010-10-05 14:29:53 -0400808 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200809
810 const char *setid = env->GetStringUTFChars(setid_string, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800811 sAGpsRilInterface->set_set_id(type, setid);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200812 env->ReleaseStringUTFChars(setid_string, setid);
813}
814
Lifu Tang30f95a72016-01-07 23:20:38 -0800815static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700816 jbyteArray nmeaArray, jint buffer_size)
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400817{
Mike Lockwoodf602d362010-06-20 14:28:16 -0700818 // this should only be called from within a call to reportNmea
819 jbyte* nmea = (jbyte *)env->GetPrimitiveArrayCritical(nmeaArray, 0);
820 int length = sNmeaStringLength;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400821 if (length > buffer_size)
822 length = buffer_size;
Mike Lockwoodf602d362010-06-20 14:28:16 -0700823 memcpy(nmea, sNmeaString, length);
824 env->ReleasePrimitiveArrayCritical(nmeaArray, nmea, JNI_ABORT);
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000825 return (jint) length;
Mike Lockwoodb16e7802009-08-06 09:26:02 -0400826}
827
Lifu Tang30f95a72016-01-07 23:20:38 -0800828static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */, jobject /* obj */,
Mike Lockwoodf602d362010-06-20 14:28:16 -0700829 jlong time, jlong timeReference, jint uncertainty)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800831 if (sGpsInterface)
832 sGpsInterface->inject_time(time, timeReference, uncertainty);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833}
834
Lifu Tang30f95a72016-01-07 23:20:38 -0800835static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700836 jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy)
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400837{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800838 if (sGpsInterface)
839 sGpsInterface->inject_location(latitude, longitude, accuracy);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400840}
841
Lifu Tang30f95a72016-01-07 23:20:38 -0800842static jboolean android_location_GnssLocationProvider_supports_xtra(
destradaaef752b62015-04-17 13:10:47 -0700843 JNIEnv* /* env */, jobject /* obj */)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844{
destradaaef752b62015-04-17 13:10:47 -0700845 return (sGpsXtraInterface != NULL) ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846}
847
Lifu Tang30f95a72016-01-07 23:20:38 -0800848static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env, jobject /* obj */,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 jbyteArray data, jint length)
850{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800851 if (!sGpsXtraInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000852 ALOGE("no XTRA interface in inject_xtra_data");
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800853 return;
854 }
855
Mike Lockwoodf602d362010-06-20 14:28:16 -0700856 jbyte* bytes = (jbyte *)env->GetPrimitiveArrayCritical(data, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
Mike Lockwoodf602d362010-06-20 14:28:16 -0700858 env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859}
860
Lifu Tang30f95a72016-01-07 23:20:38 -0800861static void android_location_GnssLocationProvider_agps_data_conn_open(
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700862 JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType)
The Android Open Source Project10592532009-03-18 17:39:46 -0700863{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800864 if (!sAGpsInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000865 ALOGE("no AGPS interface in agps_data_conn_open");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400866 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700867 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400868 if (apn == NULL) {
869 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
870 return;
The Android Open Source Project10592532009-03-18 17:39:46 -0700871 }
destradaa96a14702014-06-05 11:36:30 -0700872
Mike Lockwoodbea31182010-10-05 14:29:53 -0400873 const char *apnStr = env->GetStringUTFChars(apn, NULL);
destradaa96a14702014-06-05 11:36:30 -0700874
875 size_t interface_size = sAGpsInterface->size;
Lifu Tanga8b7bb52016-01-26 01:22:10 -0800876 if (interface_size == sizeof(AGpsInterface)) {
destradaa96a14702014-06-05 11:36:30 -0700877 sAGpsInterface->data_conn_open_with_apn_ip_type(apnStr, apnIpType);
878 } else if (interface_size == sizeof(AGpsInterface_v1)) {
879 sAGpsInterface->data_conn_open(apnStr);
880 } else {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +0100881 ALOGE("Invalid size of AGpsInterface found: %zd.", interface_size);
destradaa96a14702014-06-05 11:36:30 -0700882 }
883
Mike Lockwoodbea31182010-10-05 14:29:53 -0400884 env->ReleaseStringUTFChars(apn, apnStr);
The Android Open Source Project10592532009-03-18 17:39:46 -0700885}
886
Lifu Tang30f95a72016-01-07 23:20:38 -0800887static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700888 jobject /* obj */)
Mike Lockwood58bda982009-04-14 16:25:07 -0400889{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800890 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100891 ALOGE("no AGPS interface in agps_data_conn_closed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400892 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400893 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800894 sAGpsInterface->data_conn_closed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400895}
896
Lifu Tang30f95a72016-01-07 23:20:38 -0800897static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700898 jobject /* obj */)
Mike Lockwood58bda982009-04-14 16:25:07 -0400899{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800900 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100901 ALOGE("no AGPS interface in agps_data_conn_failed");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400902 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400903 }
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800904 sAGpsInterface->data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -0400905}
906
Lifu Tang30f95a72016-01-07 23:20:38 -0800907static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
Mike Lockwooda9e54612009-06-19 14:54:42 -0400908 jint type, jstring hostname, jint port)
Mike Lockwood58bda982009-04-14 16:25:07 -0400909{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800910 if (!sAGpsInterface) {
Magnus Eriksson160c1ca2012-12-21 21:07:28 +0100911 ALOGE("no AGPS interface in set_agps_server");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400912 return;
Mike Lockwood58bda982009-04-14 16:25:07 -0400913 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400914 const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800915 sAGpsInterface->set_server(type, c_hostname, port);
Mike Lockwoodbea31182010-10-05 14:29:53 -0400916 env->ReleaseStringUTFChars(hostname, c_hostname);
Mike Lockwood58bda982009-04-14 16:25:07 -0400917}
918
Lifu Tang30f95a72016-01-07 23:20:38 -0800919static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700920 jobject /* obj */, jint notifId, jint response)
Danke Xie22d1f9f2009-08-18 18:28:45 -0400921{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800922 if (!sGpsNiInterface) {
Steve Block3762c312012-01-06 19:20:56 +0000923 ALOGE("no NI interface in send_ni_response");
Mike Lockwoodbea31182010-10-05 14:29:53 -0400924 return;
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600925 }
Mike Lockwoodbea31182010-10-05 14:29:53 -0400926
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800927 sGpsNiInterface->respond(notifId, response);
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600928}
929
Lifu Tang30f95a72016-01-07 23:20:38 -0800930static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv* env,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700931 jobject /* obj */) {
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -0600932 jstring result = NULL;
933 if (sGpsDebugInterface) {
934 const size_t maxLength = 2047;
935 char buffer[maxLength+1];
936 size_t length = sGpsDebugInterface->get_internal_state(buffer, maxLength);
937 if (length > maxLength) length = maxLength;
938 buffer[length] = 0;
939 result = env->NewStringUTF(buffer);
940 }
941 return result;
Danke Xie22d1f9f2009-08-18 18:28:45 -0400942}
943
Lifu Tang30f95a72016-01-07 23:20:38 -0800944static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env, jobject /* obj */,
Ashok Bhat7e2a9dc2014-01-02 19:43:30 +0000945 jboolean connected, jint type, jboolean roaming, jboolean available, jstring extraInfo, jstring apn)
Mike Lockwood50130bb2010-10-11 06:22:50 -0400946{
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800947
948 if (sAGpsRilInterface && sAGpsRilInterface->update_network_state) {
Mike Lockwood50130bb2010-10-11 06:22:50 -0400949 if (extraInfo) {
950 const char *extraInfoStr = env->GetStringUTFChars(extraInfo, NULL);
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800951 sAGpsRilInterface->update_network_state(connected, type, roaming, extraInfoStr);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400952 env->ReleaseStringUTFChars(extraInfo, extraInfoStr);
953 } else {
Mike Lockwood58ec34c2011-02-23 08:21:00 -0800954 sAGpsRilInterface->update_network_state(connected, type, roaming, NULL);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400955 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700956
957 // update_network_availability callback was not included in original AGpsRilInterface
958 if (sAGpsRilInterface->size >= sizeof(AGpsRilInterface)
959 && sAGpsRilInterface->update_network_availability) {
960 const char *c_apn = env->GetStringUTFChars(apn, NULL);
961 sAGpsRilInterface->update_network_availability(available, c_apn);
962 env->ReleaseStringUTFChars(apn, c_apn);
963 }
Mike Lockwood50130bb2010-10-11 06:22:50 -0400964 }
965}
966
Lifu Tang30f95a72016-01-07 23:20:38 -0800967static jboolean android_location_GnssLocationProvider_is_geofence_supported(
destradaaef752b62015-04-17 13:10:47 -0700968 JNIEnv* /* env */, jobject /* obj */)
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700969{
destradaaef752b62015-04-17 13:10:47 -0700970 return (sGpsGeofencingInterface != NULL) ? JNI_TRUE : JNI_FALSE;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700971}
972
Lifu Tang30f95a72016-01-07 23:20:38 -0800973static jboolean android_location_GnssLocationProvider_add_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700974 jobject /* obj */, jint geofence_id, jdouble latitude, jdouble longitude, jdouble radius,
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700975 jint last_transition, jint monitor_transition, jint notification_responsiveness,
976 jint unknown_timer) {
977 if (sGpsGeofencingInterface != NULL) {
978 sGpsGeofencingInterface->add_geofence_area(geofence_id, latitude, longitude,
979 radius, last_transition, monitor_transition, notification_responsiveness,
980 unknown_timer);
981 return JNI_TRUE;
982 } else {
983 ALOGE("Geofence interface not available");
984 }
985 return JNI_FALSE;
986}
987
Lifu Tang30f95a72016-01-07 23:20:38 -0800988static jboolean android_location_GnssLocationProvider_remove_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -0700989 jobject /* obj */, jint geofence_id) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700990 if (sGpsGeofencingInterface != NULL) {
991 sGpsGeofencingInterface->remove_geofence_area(geofence_id);
992 return JNI_TRUE;
993 } else {
994 ALOGE("Geofence interface not available");
995 }
996 return JNI_FALSE;
997}
998
Lifu Tang30f95a72016-01-07 23:20:38 -0800999static jboolean android_location_GnssLocationProvider_pause_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -07001000 jobject /* obj */, jint geofence_id) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001001 if (sGpsGeofencingInterface != NULL) {
1002 sGpsGeofencingInterface->pause_geofence(geofence_id);
1003 return JNI_TRUE;
1004 } else {
1005 ALOGE("Geofence interface not available");
1006 }
1007 return JNI_FALSE;
1008}
1009
Lifu Tang30f95a72016-01-07 23:20:38 -08001010static jboolean android_location_GnssLocationProvider_resume_geofence(JNIEnv* /* env */,
Andreas Gampe184e3ed2014-09-29 15:04:06 -07001011 jobject /* obj */, jint geofence_id, jint monitor_transition) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001012 if (sGpsGeofencingInterface != NULL) {
1013 sGpsGeofencingInterface->resume_geofence(geofence_id, monitor_transition);
1014 return JNI_TRUE;
1015 } else {
1016 ALOGE("Geofence interface not available");
1017 }
1018 return JNI_FALSE;
1019}
1020
Lifu Tang120480f2016-02-07 18:08:19 -08001021template<class T>
1022class JavaMethodHelper {
1023 public:
1024 // Helper function to call setter on a Java object.
1025 static void callJavaMethod(
1026 JNIEnv* env,
1027 jclass clazz,
1028 jobject object,
1029 const char* method_name,
1030 T value);
destradaaea8a8a62014-06-23 18:19:03 -07001031
Lifu Tang120480f2016-02-07 18:08:19 -08001032 private:
1033 static const char *const signature_;
1034};
Lifu Tange5a0e212016-01-25 18:02:17 -08001035
Lifu Tang120480f2016-02-07 18:08:19 -08001036template<class T>
1037void JavaMethodHelper<T>::callJavaMethod(
1038 JNIEnv* env,
1039 jclass clazz,
1040 jobject object,
1041 const char* method_name,
1042 T value) {
1043 jmethodID method = env->GetMethodID(clazz, method_name, signature_);
1044 env->CallVoidMethod(object, method, value);
1045}
destradaaea8a8a62014-06-23 18:19:03 -07001046
Lifu Tang120480f2016-02-07 18:08:19 -08001047class JavaObject {
1048 public:
1049 JavaObject(JNIEnv* env, const char* class_name);
1050 virtual ~JavaObject();
1051
1052 template<class T>
1053 void callSetter(const char* method_name, T value);
1054 template<class T>
1055 void callSetter(const char* method_name, T* value, size_t size);
1056 jobject get();
1057
1058 private:
1059 JNIEnv* env_;
1060 jclass clazz_;
1061 jobject object_;
1062};
1063
1064JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
1065 clazz_ = env_->FindClass(class_name);
1066 jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
1067 object_ = env_->NewObject(clazz_, ctor);
1068}
1069
1070JavaObject::~JavaObject() {
1071 env_->DeleteLocalRef(clazz_);
1072}
1073
1074template<class T>
1075void JavaObject::callSetter(const char* method_name, T value) {
1076 JavaMethodHelper<T>::callJavaMethod(
1077 env_, clazz_, object_, method_name, value);
1078}
1079
1080template<>
1081void JavaObject::callSetter(
1082 const char* method_name, uint8_t* value, size_t size) {
1083 jbyteArray array = env_->NewByteArray(size);
1084 env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
1085 jmethodID method = env_->GetMethodID(
1086 clazz_,
1087 method_name,
1088 "([B)V");
1089 env_->CallVoidMethod(object_, method, array);
1090}
1091
1092jobject JavaObject::get() {
1093 return object_;
1094}
1095
1096// Define Java method signatures for all known types.
1097
1098template<>
1099const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
1100template<>
1101const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
1102template<>
1103const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
1104template<>
1105const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
1106template<>
Lifu Tang9363b942016-02-16 18:07:00 -08001107const char *const JavaMethodHelper<int32_t>::signature_ = "(I)V";
1108template<>
1109const char *const JavaMethodHelper<uint32_t>::signature_ = "(I)V";
Lifu Tang120480f2016-02-07 18:08:19 -08001110template<>
1111const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
1112template<>
1113const char *const JavaMethodHelper<float>::signature_ = "(F)V";
1114template<>
1115const char *const JavaMethodHelper<double>::signature_ = "(D)V";
1116template<>
1117const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
1118
1119#define SET(setter, value) object.callSetter("set" # setter, (value))
Lifu Tangccb44882016-03-09 19:32:29 -08001120
1121// If you want to check if a flag is not set, use SET_IF_NOT(FLAG, setter,
1122// value) to do that. SET_IF(!FLAG, setter, value) won't compile.
1123//
1124// This macros generates compilation error if the provided 'flag' is not a
1125// single token. For example, 'GNSS_CLOCK_HAS_BIAS' can be accepted, but
1126// '!GNSS_CLOCK_HAS_DRIFT' will fail to compile.
1127#define SET_IF(flag, setter, value) do { \
1128 if (flags & flag) { \
1129 JavaObject& name_check_##flag = object; \
1130 name_check_##flag.callSetter("set" # setter, (value)); \
1131 } \
1132 } while (false)
1133#define SET_IF_NOT(flag, setter, value) do { \
1134 if (!(flags & flag)) { \
1135 JavaObject& name_check_##flag = object; \
1136 name_check_##flag.callSetter("set" # setter, (value)); \
1137 } \
1138 } while (false)
Lifu Tang120480f2016-02-07 18:08:19 -08001139
1140static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
Lifu Tang17350f92016-03-22 13:56:52 -07001141 static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
Lifu Tang120480f2016-02-07 18:08:19 -08001142 JavaObject object(env, "android/location/GnssClock");
destradaaea8a8a62014-06-23 18:19:03 -07001143 GpsClockFlags flags = clock->flags;
1144
Lifu Tange50607e2016-04-07 19:25:24 -07001145 SET_IF(GPS_CLOCK_HAS_LEAP_SECOND,
Lifu Tang76a620f2016-02-26 19:53:01 -08001146 LeapSecond,
1147 static_cast<int32_t>(clock->leap_second));
Lifu Tang38bce792016-02-24 17:17:38 -08001148
1149 // GnssClock only supports the more effective HW_CLOCK type, so type
1150 // handling and documentation complexity has been removed. To convert the
1151 // old GPS_CLOCK types (active only in a limited number of older devices),
1152 // the GPS time information is handled as an always discontinuous HW clock,
1153 // with the GPS time information put into the full_bias_ns instead - so that
Lifu Tange50607e2016-04-07 19:25:24 -07001154 // time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
1155 // sign of full_bias_ns and bias_ns has flipped between GpsClock &
1156 // GnssClock, so that is also handled below.
Lifu Tang38bce792016-02-24 17:17:38 -08001157 switch (clock->type) {
1158 case GPS_CLOCK_TYPE_UNKNOWN:
1159 // Clock type unsupported.
1160 ALOGE("Unknown clock type provided.");
1161 break;
1162 case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
1163 // Already local hardware time. No need to do anything.
1164 break;
1165 case GPS_CLOCK_TYPE_GPS_TIME:
1166 // GPS time, need to convert.
Lifu Tange50607e2016-04-07 19:25:24 -07001167 flags |= GPS_CLOCK_HAS_FULL_BIAS;
Lifu Tang38bce792016-02-24 17:17:38 -08001168 clock->full_bias_ns = clock->time_ns;
1169 clock->time_ns = 0;
1170 SET(HardwareClockDiscontinuityCount,
Lifu Tang17350f92016-03-22 13:56:52 -07001171 discontinuity_count_to_handle_old_clock_type++);
Lifu Tang38bce792016-02-24 17:17:38 -08001172 break;
1173 }
1174
Lifu Tang76a620f2016-02-26 19:53:01 -08001175 SET(TimeNanos, clock->time_ns);
Lifu Tange50607e2016-04-07 19:25:24 -07001176 SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001177 TimeUncertaintyNanos,
Lifu Tang120480f2016-02-07 18:08:19 -08001178 clock->time_uncertainty_ns);
Lifu Tange50607e2016-04-07 19:25:24 -07001179
1180 // Definition of sign for full_bias_ns & bias_ns has been changed since N,
1181 // so flip signs here.
1182 SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, -(clock->full_bias_ns));
1183 SET_IF(GPS_CLOCK_HAS_BIAS, BiasNanos, -(clock->bias_ns));
1184
1185 SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001186 BiasUncertaintyNanos,
Lifu Tang120480f2016-02-07 18:08:19 -08001187 clock->bias_uncertainty_ns);
Lifu Tange50607e2016-04-07 19:25:24 -07001188 SET_IF(GPS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
1189 SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001190 DriftUncertaintyNanosPerSecond,
Lifu Tang120480f2016-02-07 18:08:19 -08001191 clock->drift_uncertainty_nsps);
destradaaea8a8a62014-06-23 18:19:03 -07001192
Lifu Tang120480f2016-02-07 18:08:19 -08001193 return object.get();
destradaaea8a8a62014-06-23 18:19:03 -07001194}
1195
Lifu Tang120480f2016-02-07 18:08:19 -08001196static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
1197 JavaObject object(env, "android/location/GnssClock");
Mike Cailean96635bd2016-03-24 19:34:16 -07001198 GnssClockFlags flags = clock->flags;
destradaaea8a8a62014-06-23 18:19:03 -07001199
Lifu Tang76a620f2016-02-26 19:53:01 -08001200 SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
1201 LeapSecond,
1202 static_cast<int32_t>(clock->leap_second));
1203 SET(TimeNanos, clock->time_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001204 SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001205 TimeUncertaintyNanos,
Lifu Tang120480f2016-02-07 18:08:19 -08001206 clock->time_uncertainty_ns);
Lifu Tang76a620f2016-02-26 19:53:01 -08001207 SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
1208 SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
Lifu Tang9363b942016-02-16 18:07:00 -08001209 SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001210 BiasUncertaintyNanos,
Lifu Tang120480f2016-02-07 18:08:19 -08001211 clock->bias_uncertainty_ns);
Lifu Tang76a620f2016-02-26 19:53:01 -08001212 SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
Lifu Tang9363b942016-02-16 18:07:00 -08001213 SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001214 DriftUncertaintyNanosPerSecond,
Lifu Tang120480f2016-02-07 18:08:19 -08001215 clock->drift_uncertainty_nsps);
destradaaea8a8a62014-06-23 18:19:03 -07001216
Lifu Tang9363b942016-02-16 18:07:00 -08001217 SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
Lifu Tang120480f2016-02-07 18:08:19 -08001218
1219 return object.get();
1220}
1221
1222static jobject translate_gps_measurement(JNIEnv* env,
1223 GpsMeasurement* measurement) {
1224 JavaObject object(env, "android/location/GnssMeasurement");
destradaaea8a8a62014-06-23 18:19:03 -07001225 GpsMeasurementFlags flags = measurement->flags;
Lifu Tang76a620f2016-02-26 19:53:01 -08001226 SET(Svid, static_cast<int32_t>(measurement->prn));
Lifu Tang8ad44302016-04-20 11:48:16 -07001227 if (measurement->prn >= 1 && measurement->prn <= 32) {
Lifu Tang76a620f2016-02-26 19:53:01 -08001228 SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
Lifu Tang9363b942016-02-16 18:07:00 -08001229 } else {
1230 ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
1231 SET(ConstellationType,
Lifu Tang76a620f2016-02-26 19:53:01 -08001232 static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
Lifu Tang9363b942016-02-16 18:07:00 -08001233 }
Lifu Tang76a620f2016-02-26 19:53:01 -08001234 SET(TimeOffsetNanos, measurement->time_offset_ns);
1235 SET(State, static_cast<int32_t>(measurement->state));
1236 SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
1237 SET(ReceivedSvTimeUncertaintyNanos,
Lifu Tang120480f2016-02-07 18:08:19 -08001238 measurement->received_gps_tow_uncertainty_ns);
Lifu Tang76a620f2016-02-26 19:53:01 -08001239 SET(Cn0DbHz, measurement->c_n0_dbhz);
1240 SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
1241 SET(PseudorangeRateUncertaintyMetersPerSecond,
Lifu Tang120480f2016-02-07 18:08:19 -08001242 measurement->pseudorange_rate_uncertainty_mps);
Lifu Tang76a620f2016-02-26 19:53:01 -08001243 SET(AccumulatedDeltaRangeState,
1244 static_cast<int32_t>(measurement->accumulated_delta_range_state));
1245 SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
1246 SET(AccumulatedDeltaRangeUncertaintyMeters,
Lifu Tang120480f2016-02-07 18:08:19 -08001247 measurement->accumulated_delta_range_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001248 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001249 CarrierFrequencyHz,
Lifu Tang120480f2016-02-07 18:08:19 -08001250 measurement->carrier_frequency_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001251 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
Lifu Tang120480f2016-02-07 18:08:19 -08001252 CarrierCycles,
1253 measurement->carrier_cycles);
Lifu Tang9363b942016-02-16 18:07:00 -08001254 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001255 CarrierPhase,
1256 measurement->carrier_phase);
Lifu Tang9363b942016-02-16 18:07:00 -08001257 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001258 CarrierPhaseUncertainty,
1259 measurement->carrier_phase_uncertainty);
Lifu Tang235bbb12016-03-04 17:01:06 -08001260 SET(MultipathIndicator,
1261 static_cast<int32_t>(measurement->multipath_indicator));
Lifu Tang9363b942016-02-16 18:07:00 -08001262 SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
destradaaea8a8a62014-06-23 18:19:03 -07001263
Lifu Tang120480f2016-02-07 18:08:19 -08001264 return object.get();
destradaaea8a8a62014-06-23 18:19:03 -07001265}
1266
Lifu Tang120480f2016-02-07 18:08:19 -08001267static jobject translate_gnss_measurement(JNIEnv* env,
1268 GnssMeasurement* measurement) {
1269 JavaObject object(env, "android/location/GnssMeasurement");
Lifu Tang120480f2016-02-07 18:08:19 -08001270
Mike Cailean96635bd2016-03-24 19:34:16 -07001271 GnssMeasurementFlags flags = measurement->flags;
1272
1273 SET(Svid, static_cast<int32_t>(measurement->svid));
Lifu Tang76a620f2016-02-26 19:53:01 -08001274 SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
1275 SET(TimeOffsetNanos, measurement->time_offset_ns);
1276 SET(State, static_cast<int32_t>(measurement->state));
1277 SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
1278 SET(ReceivedSvTimeUncertaintyNanos,
Lifu Tang9363b942016-02-16 18:07:00 -08001279 measurement->received_sv_time_uncertainty_in_ns);
Lifu Tang76a620f2016-02-26 19:53:01 -08001280 SET(Cn0DbHz, measurement->c_n0_dbhz);
1281 SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
1282 SET(PseudorangeRateUncertaintyMetersPerSecond,
Lifu Tang120480f2016-02-07 18:08:19 -08001283 measurement->pseudorange_rate_uncertainty_mps);
Lifu Tang76a620f2016-02-26 19:53:01 -08001284 SET(AccumulatedDeltaRangeState,
1285 static_cast<int32_t>(measurement->accumulated_delta_range_state));
1286 SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
1287 SET(AccumulatedDeltaRangeUncertaintyMeters,
Lifu Tang120480f2016-02-07 18:08:19 -08001288 measurement->accumulated_delta_range_uncertainty_m);
Lifu Tang9363b942016-02-16 18:07:00 -08001289 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
Lifu Tang76a620f2016-02-26 19:53:01 -08001290 CarrierFrequencyHz,
Lifu Tang120480f2016-02-07 18:08:19 -08001291 measurement->carrier_frequency_hz);
Lifu Tang9363b942016-02-16 18:07:00 -08001292 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
Lifu Tang120480f2016-02-07 18:08:19 -08001293 CarrierCycles,
1294 measurement->carrier_cycles);
Lifu Tang9363b942016-02-16 18:07:00 -08001295 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE,
Lifu Tang120480f2016-02-07 18:08:19 -08001296 CarrierPhase,
1297 measurement->carrier_phase);
Lifu Tang9363b942016-02-16 18:07:00 -08001298 SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
Lifu Tang120480f2016-02-07 18:08:19 -08001299 CarrierPhaseUncertainty,
1300 measurement->carrier_phase_uncertainty);
Lifu Tang235bbb12016-03-04 17:01:06 -08001301 SET(MultipathIndicator,
1302 static_cast<int32_t>(measurement->multipath_indicator));
Lifu Tang9363b942016-02-16 18:07:00 -08001303 SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
Lifu Tang120480f2016-02-07 18:08:19 -08001304
1305 return object.get();
1306}
1307
1308static jobjectArray translate_gps_measurements(JNIEnv* env,
1309 GpsMeasurement* measurements,
1310 size_t count) {
1311 if (count == 0) {
destradaaea8a8a62014-06-23 18:19:03 -07001312 return NULL;
1313 }
1314
Lifu Tang120480f2016-02-07 18:08:19 -08001315 jclass gnssMeasurementClass = env->FindClass(
1316 "android/location/GnssMeasurement");
Lifu Tang818aa2c2016-02-01 01:52:00 -08001317 jobjectArray gnssMeasurementArray = env->NewObjectArray(
Lifu Tang120480f2016-02-07 18:08:19 -08001318 count,
Lifu Tang818aa2c2016-02-01 01:52:00 -08001319 gnssMeasurementClass,
destradaaea8a8a62014-06-23 18:19:03 -07001320 NULL /* initialElement */);
1321
Lifu Tang120480f2016-02-07 18:08:19 -08001322 for (uint16_t i = 0; i < count; ++i) {
Lifu Tang818aa2c2016-02-01 01:52:00 -08001323 jobject gnssMeasurement = translate_gps_measurement(
Lifu Tange5a0e212016-01-25 18:02:17 -08001324 env,
Lifu Tang120480f2016-02-07 18:08:19 -08001325 &measurements[i]);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001326 env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1327 env->DeleteLocalRef(gnssMeasurement);
destradaaea8a8a62014-06-23 18:19:03 -07001328 }
1329
Lifu Tang818aa2c2016-02-01 01:52:00 -08001330 env->DeleteLocalRef(gnssMeasurementClass);
1331 return gnssMeasurementArray;
destradaaea8a8a62014-06-23 18:19:03 -07001332}
1333
Lifu Tang120480f2016-02-07 18:08:19 -08001334static jobjectArray translate_gnss_measurements(JNIEnv* env,
1335 GnssMeasurement* measurements,
1336 size_t count) {
1337 if (count == 0) {
1338 return NULL;
destradaaea8a8a62014-06-23 18:19:03 -07001339 }
Lifu Tange5a0e212016-01-25 18:02:17 -08001340
Lifu Tang120480f2016-02-07 18:08:19 -08001341 jclass gnssMeasurementClass = env->FindClass(
1342 "android/location/GnssMeasurement");
1343 jobjectArray gnssMeasurementArray = env->NewObjectArray(
1344 count,
1345 gnssMeasurementClass,
1346 NULL /* initialElement */);
1347
1348 for (uint16_t i = 0; i < count; ++i) {
1349 jobject gnssMeasurement = translate_gnss_measurement(
1350 env,
1351 &measurements[i]);
1352 env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
1353 env->DeleteLocalRef(gnssMeasurement);
Lifu Tange5a0e212016-01-25 18:02:17 -08001354 }
Lifu Tang120480f2016-02-07 18:08:19 -08001355
1356 env->DeleteLocalRef(gnssMeasurementClass);
1357 return gnssMeasurementArray;
1358}
1359
1360static void set_measurement_data(JNIEnv *env,
1361 jobject clock,
1362 jobjectArray measurementArray) {
1363 jclass gnssMeasurementsEventClass = env->FindClass(
1364 "android/location/GnssMeasurementsEvent");
Lifu Tang818aa2c2016-02-01 01:52:00 -08001365 jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
1366 gnssMeasurementsEventClass,
Lifu Tange5a0e212016-01-25 18:02:17 -08001367 "<init>",
Lifu Tang818aa2c2016-02-01 01:52:00 -08001368 "(Landroid/location/GnssClock;[Landroid/location/GnssMeasurement;)V");
Lifu Tange5a0e212016-01-25 18:02:17 -08001369
Lifu Tang818aa2c2016-02-01 01:52:00 -08001370 jobject gnssMeasurementsEvent = env->NewObject(
1371 gnssMeasurementsEventClass,
1372 gnssMeasurementsEventCtor,
Lifu Tang120480f2016-02-07 18:08:19 -08001373 clock,
Lifu Tange5a0e212016-01-25 18:02:17 -08001374 measurementArray);
Lifu Tang120480f2016-02-07 18:08:19 -08001375 env->CallVoidMethod(mCallbacksObj,
1376 method_reportMeasurementData,
1377 gnssMeasurementsEvent);
Lifu Tange5a0e212016-01-25 18:02:17 -08001378 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001379 env->DeleteLocalRef(gnssMeasurementsEventClass);
1380 env->DeleteLocalRef(gnssMeasurementsEvent);
destradaaea8a8a62014-06-23 18:19:03 -07001381}
1382
Lifu Tang120480f2016-02-07 18:08:19 -08001383static void measurement_callback(GpsData* data) {
1384 JNIEnv* env = AndroidRuntime::getJNIEnv();
1385 if (data == NULL) {
1386 ALOGE("Invalid data provided to gps_measurement_callback");
1387 return;
1388 }
1389 if (data->size != sizeof(GpsData)) {
1390 ALOGE("Invalid GpsData size found in gps_measurement_callback, "
1391 "size=%zd",
1392 data->size);
1393 return;
1394 }
1395
1396 jobject clock;
1397 jobjectArray measurementArray;
1398 clock = translate_gps_clock(env, &data->clock);
1399 measurementArray = translate_gps_measurements(
1400 env, data->measurements, data->measurement_count);
1401 set_measurement_data(env, clock, measurementArray);
1402
1403 env->DeleteLocalRef(clock);
1404 env->DeleteLocalRef(measurementArray);
1405}
1406
1407static void gnss_measurement_callback(GnssData* data) {
1408 JNIEnv* env = AndroidRuntime::getJNIEnv();
1409 if (data == NULL) {
1410 ALOGE("Invalid data provided to gps_measurement_callback");
1411 return;
1412 }
Mike Cailean96635bd2016-03-24 19:34:16 -07001413 if (data->size != sizeof(GnssData)) {
1414 ALOGE("Invalid GnssData size found in gnss_measurement_callback, "
Lifu Tang120480f2016-02-07 18:08:19 -08001415 "size=%zd",
1416 data->size);
1417 return;
1418 }
1419
1420 jobject clock;
1421 jobjectArray measurementArray;
1422 clock = translate_gnss_clock(env, &data->clock);
1423 measurementArray = translate_gnss_measurements(
1424 env, data->measurements, data->measurement_count);
1425 set_measurement_data(env, clock, measurementArray);
1426
1427 env->DeleteLocalRef(clock);
1428 env->DeleteLocalRef(measurementArray);
1429}
1430
destradaaea8a8a62014-06-23 18:19:03 -07001431GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
1432 sizeof(GpsMeasurementCallbacks),
1433 measurement_callback,
Lifu Tang120480f2016-02-07 18:08:19 -08001434 gnss_measurement_callback,
destradaaea8a8a62014-06-23 18:19:03 -07001435};
1436
Lifu Tang30f95a72016-01-07 23:20:38 -08001437static jboolean android_location_GnssLocationProvider_is_measurement_supported(
destradaaea8a8a62014-06-23 18:19:03 -07001438 JNIEnv* env,
destradaa4b3e3932014-07-21 18:01:47 -07001439 jclass clazz) {
destradaaea8a8a62014-06-23 18:19:03 -07001440 if (sGpsMeasurementInterface != NULL) {
1441 return JNI_TRUE;
1442 }
1443 return JNI_FALSE;
1444}
1445
Lifu Tang30f95a72016-01-07 23:20:38 -08001446static jboolean android_location_GnssLocationProvider_start_measurement_collection(
destradaaea8a8a62014-06-23 18:19:03 -07001447 JNIEnv* env,
1448 jobject obj) {
1449 if (sGpsMeasurementInterface == NULL) {
1450 ALOGE("Measurement interface is not available.");
1451 return JNI_FALSE;
1452 }
1453
1454 int result = sGpsMeasurementInterface->init(&sGpsMeasurementCallbacks);
1455 if (result != GPS_GEOFENCE_OPERATION_SUCCESS) {
1456 ALOGE("An error has been found on GpsMeasurementInterface::init, status=%d", result);
1457 return JNI_FALSE;
1458 }
1459
1460 return JNI_TRUE;
1461}
1462
Lifu Tang30f95a72016-01-07 23:20:38 -08001463static jboolean android_location_GnssLocationProvider_stop_measurement_collection(
destradaaea8a8a62014-06-23 18:19:03 -07001464 JNIEnv* env,
1465 jobject obj) {
1466 if (sGpsMeasurementInterface == NULL) {
1467 ALOGE("Measurement interface not available");
1468 return JNI_FALSE;
1469 }
1470
1471 sGpsMeasurementInterface->close();
1472 return JNI_TRUE;
1473}
1474
destradaa4b3e3932014-07-21 18:01:47 -07001475static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
1476 size_t dataLength = message->data_length;
1477 uint8_t* data = message->data;
1478 if (dataLength == 0 || data == NULL) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +01001479 ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
destradaa4b3e3932014-07-21 18:01:47 -07001480 return NULL;
1481 }
Lifu Tang120480f2016-02-07 18:08:19 -08001482 JavaObject object(env, "android/location/GnssNavigationMessage");
Lifu Tang76a620f2016-02-26 19:53:01 -08001483 SET(Svid, static_cast<int32_t>(message->prn));
Lifu Tang9363b942016-02-16 18:07:00 -08001484 if (message->prn >=1 && message->prn <= 32) {
Lifu Tang76a620f2016-02-26 19:53:01 -08001485 SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
Lifu Tang9363b942016-02-16 18:07:00 -08001486 // Legacy driver doesn't set the higher byte to constellation type
1487 // correctly. Set the higher byte to 'GPS'.
Lifu Tang76a620f2016-02-26 19:53:01 -08001488 SET(Type, static_cast<int32_t>(message->type | 0x0100));
Lifu Tang9363b942016-02-16 18:07:00 -08001489 } else {
1490 ALOGD("Unknown constellation type with Svid = %d.", message->prn);
1491 SET(ConstellationType,
Lifu Tang76a620f2016-02-26 19:53:01 -08001492 static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
1493 SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
Lifu Tang9363b942016-02-16 18:07:00 -08001494 }
Lifu Tang76a620f2016-02-26 19:53:01 -08001495 SET(MessageId, static_cast<int32_t>(message->message_id));
1496 SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
Lifu Tang120480f2016-02-07 18:08:19 -08001497 object.callSetter("setData", data, dataLength);
Lifu Tang76a620f2016-02-26 19:53:01 -08001498 SET(Status, static_cast<int32_t>(message->status));
Lifu Tang120480f2016-02-07 18:08:19 -08001499 return object.get();
1500}
destradaa4b3e3932014-07-21 18:01:47 -07001501
Lifu Tang120480f2016-02-07 18:08:19 -08001502static jobject translate_gnss_navigation_message(
1503 JNIEnv* env, GnssNavigationMessage* message) {
1504 size_t dataLength = message->data_length;
1505 uint8_t* data = message->data;
1506 if (dataLength == 0 || data == NULL) {
1507 ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
1508 return NULL;
1509 }
1510 JavaObject object(env, "android/location/GnssNavigationMessage");
Lifu Tang76a620f2016-02-26 19:53:01 -08001511 SET(Type, static_cast<int32_t>(message->type));
1512 SET(Svid, static_cast<int32_t>(message->svid));
1513 SET(MessageId, static_cast<int32_t>(message->message_id));
1514 SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
Lifu Tang120480f2016-02-07 18:08:19 -08001515 object.callSetter("setData", data, dataLength);
Lifu Tang76a620f2016-02-26 19:53:01 -08001516 SET(Status, static_cast<int32_t>(message->status));
Lifu Tang120480f2016-02-07 18:08:19 -08001517 return object.get();
1518}
destradaa4b3e3932014-07-21 18:01:47 -07001519
destradaa4b3e3932014-07-21 18:01:47 -07001520static void navigation_message_callback(GpsNavigationMessage* message) {
destradaa4b3e3932014-07-21 18:01:47 -07001521 if (message == NULL) {
1522 ALOGE("Invalid Navigation Message provided to callback");
1523 return;
1524 }
Lifu Tang120480f2016-02-07 18:08:19 -08001525 if (message->size != sizeof(GpsNavigationMessage)) {
Bernhard Rosenkränzer46c82b42014-11-30 11:04:10 +01001526 ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
Lifu Tang120480f2016-02-07 18:08:19 -08001527 return;
destradaa4b3e3932014-07-21 18:01:47 -07001528 }
Lifu Tang120480f2016-02-07 18:08:19 -08001529 JNIEnv* env = AndroidRuntime::getJNIEnv();
1530 jobject navigationMessage = translate_gps_navigation_message(env, message);
Lifu Tang5b49d8a2016-04-12 14:00:14 -07001531 env->CallVoidMethod(mCallbacksObj,
1532 method_reportNavigationMessages,
1533 navigationMessage);
Lifu Tang120480f2016-02-07 18:08:19 -08001534 env->DeleteLocalRef(navigationMessage);
1535}
1536
1537static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
1538 if (message == NULL) {
1539 ALOGE("Invalid Navigation Message provided to callback");
1540 return;
1541 }
1542 if (message->size != sizeof(GnssNavigationMessage)) {
1543 ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
1544 return;
1545 }
1546 JNIEnv* env = AndroidRuntime::getJNIEnv();
1547 jobject navigationMessage = translate_gnss_navigation_message(env, message);
Lifu Tang5b49d8a2016-04-12 14:00:14 -07001548 env->CallVoidMethod(mCallbacksObj,
1549 method_reportNavigationMessages,
1550 navigationMessage);
Lifu Tang120480f2016-02-07 18:08:19 -08001551 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 */