• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "GpsLocationProvider"
18 
19 //#define LOG_NDDEBUG 0
20 
21 #include "JNIHelp.h"
22 #include "jni.h"
23 #include "hardware_legacy/gps.h"
24 #include "hardware_legacy/gps_ni.h"
25 #include "utils/Log.h"
26 #include "utils/misc.h"
27 
28 #include <string.h>
29 #include <pthread.h>
30 
31 static pthread_mutex_t sEventMutex = PTHREAD_MUTEX_INITIALIZER;
32 static pthread_cond_t sEventCond = PTHREAD_COND_INITIALIZER;
33 static jmethodID method_reportLocation;
34 static jmethodID method_reportStatus;
35 static jmethodID method_reportSvStatus;
36 static jmethodID method_reportAGpsStatus;
37 static jmethodID method_reportNmea;
38 static jmethodID method_xtraDownloadRequest;
39 static jmethodID method_reportNiNotification;
40 
41 static const GpsInterface* sGpsInterface = NULL;
42 static const GpsXtraInterface* sGpsXtraInterface = NULL;
43 static const AGpsInterface* sAGpsInterface = NULL;
44 static const GpsNiInterface* sGpsNiInterface = NULL;
45 
46 // data written to by GPS callbacks
47 static GpsLocation  sGpsLocation;
48 static GpsStatus    sGpsStatus;
49 static GpsSvStatus  sGpsSvStatus;
50 static AGpsStatus   sAGpsStatus;
51 static GpsNiNotification  sGpsNiNotification;
52 
53 // buffer for NMEA data
54 #define NMEA_SENTENCE_LENGTH    100
55 #define NMEA_SENTENCE_COUNT     40
56 struct NmeaSentence {
57     GpsUtcTime  timestamp;
58     char        nmea[NMEA_SENTENCE_LENGTH];
59 };
60 static NmeaSentence sNmeaBuffer[NMEA_SENTENCE_LENGTH];
61 static int mNmeaSentenceCount = 0;
62 
63 // a copy of the data shared by android_location_GpsLocationProvider_wait_for_event
64 // and android_location_GpsLocationProvider_read_status
65 static GpsLocation  sGpsLocationCopy;
66 static GpsStatus    sGpsStatusCopy;
67 static GpsSvStatus  sGpsSvStatusCopy;
68 static AGpsStatus   sAGpsStatusCopy;
69 static NmeaSentence sNmeaBufferCopy[NMEA_SENTENCE_LENGTH];
70 static GpsNiNotification  sGpsNiNotificationCopy;
71 
72 enum CallbackType {
73     kLocation = 1,
74     kStatus = 2,
75     kSvStatus = 4,
76     kAGpsStatus = 8,
77     kXtraDownloadRequest = 16,
78     kDisableRequest = 32,
79     kNmeaAvailable = 64,
80     kNiNotification = 128,
81 };
82 static int sPendingCallbacks;
83 
84 namespace android {
85 
location_callback(GpsLocation * location)86 static void location_callback(GpsLocation* location)
87 {
88     pthread_mutex_lock(&sEventMutex);
89 
90     sPendingCallbacks |= kLocation;
91     memcpy(&sGpsLocation, location, sizeof(sGpsLocation));
92 
93     pthread_cond_signal(&sEventCond);
94     pthread_mutex_unlock(&sEventMutex);
95 }
96 
status_callback(GpsStatus * status)97 static void status_callback(GpsStatus* status)
98 {
99     pthread_mutex_lock(&sEventMutex);
100 
101     sPendingCallbacks |= kStatus;
102     memcpy(&sGpsStatus, status, sizeof(sGpsStatus));
103 
104     pthread_cond_signal(&sEventCond);
105     pthread_mutex_unlock(&sEventMutex);
106 }
107 
sv_status_callback(GpsSvStatus * sv_status)108 static void sv_status_callback(GpsSvStatus* sv_status)
109 {
110     pthread_mutex_lock(&sEventMutex);
111 
112     sPendingCallbacks |= kSvStatus;
113     memcpy(&sGpsSvStatus, sv_status, sizeof(GpsSvStatus));
114 
115     pthread_cond_signal(&sEventCond);
116     pthread_mutex_unlock(&sEventMutex);
117 }
118 
nmea_callback(GpsUtcTime timestamp,const char * nmea,int length)119 static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length)
120 {
121     pthread_mutex_lock(&sEventMutex);
122 
123     if (length >= NMEA_SENTENCE_LENGTH) {
124         LOGE("NMEA data too long in nmea_callback (length = %d)\n", length);
125         length = NMEA_SENTENCE_LENGTH - 1;
126     }
127     if (mNmeaSentenceCount >= NMEA_SENTENCE_COUNT) {
128         LOGE("NMEA data overflowed buffer\n");
129         pthread_mutex_unlock(&sEventMutex);
130         return;
131     }
132 
133     sPendingCallbacks |= kNmeaAvailable;
134     sNmeaBuffer[mNmeaSentenceCount].timestamp = timestamp;
135     memcpy(sNmeaBuffer[mNmeaSentenceCount].nmea, nmea, length);
136     sNmeaBuffer[mNmeaSentenceCount].nmea[length] = 0;
137     mNmeaSentenceCount++;
138 
139     pthread_cond_signal(&sEventCond);
140     pthread_mutex_unlock(&sEventMutex);
141 }
142 
agps_status_callback(AGpsStatus * agps_status)143 static void agps_status_callback(AGpsStatus* agps_status)
144 {
145     pthread_mutex_lock(&sEventMutex);
146 
147     sPendingCallbacks |= kAGpsStatus;
148     memcpy(&sAGpsStatus, agps_status, sizeof(AGpsStatus));
149 
150     pthread_cond_signal(&sEventCond);
151     pthread_mutex_unlock(&sEventMutex);
152 }
153 
154 GpsCallbacks sGpsCallbacks = {
155     location_callback,
156     status_callback,
157     sv_status_callback,
158     nmea_callback
159 };
160 
161 static void
download_request_callback()162 download_request_callback()
163 {
164     pthread_mutex_lock(&sEventMutex);
165     sPendingCallbacks |= kXtraDownloadRequest;
166     pthread_cond_signal(&sEventCond);
167     pthread_mutex_unlock(&sEventMutex);
168 }
169 
170 static void
gps_ni_notify_callback(GpsNiNotification * notification)171 gps_ni_notify_callback(GpsNiNotification *notification)
172 {
173    LOGD("gps_ni_notify_callback: notif=%d", notification->notification_id);
174 
175    pthread_mutex_lock(&sEventMutex);
176 
177    sPendingCallbacks |= kNiNotification;
178    memcpy(&sGpsNiNotification, notification, sizeof(GpsNiNotification));
179 
180    pthread_cond_signal(&sEventCond);
181    pthread_mutex_unlock(&sEventMutex);
182 }
183 
184 GpsXtraCallbacks sGpsXtraCallbacks = {
185     download_request_callback,
186 };
187 
188 AGpsCallbacks sAGpsCallbacks = {
189     agps_status_callback,
190 };
191 
192 GpsNiCallbacks sGpsNiCallbacks = {
193     gps_ni_notify_callback,
194 };
195 
android_location_GpsLocationProvider_class_init_native(JNIEnv * env,jclass clazz)196 static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
197     method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
198     method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
199     method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
200     method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V");
201     method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(IJ)V");
202     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
203     method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification", "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
204 }
205 
android_location_GpsLocationProvider_is_supported(JNIEnv * env,jclass clazz)206 static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
207     if (!sGpsInterface)
208         sGpsInterface = gps_get_interface();
209     return (sGpsInterface != NULL);
210 }
211 
android_location_GpsLocationProvider_init(JNIEnv * env,jobject obj)212 static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject obj)
213 {
214     if (!sGpsInterface)
215         sGpsInterface = gps_get_interface();
216     if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
217         return false;
218 
219     if (!sAGpsInterface)
220         sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
221     if (sAGpsInterface)
222         sAGpsInterface->init(&sAGpsCallbacks);
223 
224     if (!sGpsNiInterface)
225        sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
226     if (sGpsNiInterface)
227        sGpsNiInterface->init(&sGpsNiCallbacks);
228 
229     return true;
230 }
231 
android_location_GpsLocationProvider_disable(JNIEnv * env,jobject obj)232 static void android_location_GpsLocationProvider_disable(JNIEnv* env, jobject obj)
233 {
234     pthread_mutex_lock(&sEventMutex);
235     sPendingCallbacks |= kDisableRequest;
236     pthread_cond_signal(&sEventCond);
237     pthread_mutex_unlock(&sEventMutex);
238 }
239 
android_location_GpsLocationProvider_cleanup(JNIEnv * env,jobject obj)240 static void android_location_GpsLocationProvider_cleanup(JNIEnv* env, jobject obj)
241 {
242     sGpsInterface->cleanup();
243 }
244 
android_location_GpsLocationProvider_start(JNIEnv * env,jobject obj,jint positionMode,jboolean singleFix,jint fixFrequency)245 static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jint positionMode,
246         jboolean singleFix, jint fixFrequency)
247 {
248     int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency));
249     if (result) {
250         return false;
251     }
252 
253     return (sGpsInterface->start() == 0);
254 }
255 
android_location_GpsLocationProvider_stop(JNIEnv * env,jobject obj)256 static jboolean android_location_GpsLocationProvider_stop(JNIEnv* env, jobject obj)
257 {
258     return (sGpsInterface->stop() == 0);
259 }
260 
android_location_GpsLocationProvider_delete_aiding_data(JNIEnv * env,jobject obj,jint flags)261 static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* env, jobject obj, jint flags)
262 {
263     sGpsInterface->delete_aiding_data(flags);
264 }
265 
android_location_GpsLocationProvider_wait_for_event(JNIEnv * env,jobject obj)266 static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, jobject obj)
267 {
268     pthread_mutex_lock(&sEventMutex);
269     while (sPendingCallbacks == 0) {
270         pthread_cond_wait(&sEventCond, &sEventMutex);
271     }
272 
273     // copy and clear the callback flags
274     int pendingCallbacks = sPendingCallbacks;
275     sPendingCallbacks = 0;
276     int nmeaSentenceCount = mNmeaSentenceCount;
277     mNmeaSentenceCount = 0;
278 
279     // copy everything and unlock the mutex before calling into Java code to avoid the possibility
280     // of timeouts in the GPS engine.
281     if (pendingCallbacks & kLocation)
282         memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));
283     if (pendingCallbacks & kStatus)
284         memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy));
285     if (pendingCallbacks & kSvStatus)
286         memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy));
287     if (pendingCallbacks & kAGpsStatus)
288         memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy));
289     if (pendingCallbacks & kNmeaAvailable)
290         memcpy(&sNmeaBufferCopy, &sNmeaBuffer, nmeaSentenceCount * sizeof(sNmeaBuffer[0]));
291     if (pendingCallbacks & kNiNotification)
292         memcpy(&sGpsNiNotificationCopy, &sGpsNiNotification, sizeof(sGpsNiNotificationCopy));
293     pthread_mutex_unlock(&sEventMutex);
294 
295     if (pendingCallbacks & kLocation) {
296         env->CallVoidMethod(obj, method_reportLocation, sGpsLocationCopy.flags,
297                 (jdouble)sGpsLocationCopy.latitude, (jdouble)sGpsLocationCopy.longitude,
298                 (jdouble)sGpsLocationCopy.altitude,
299                 (jfloat)sGpsLocationCopy.speed, (jfloat)sGpsLocationCopy.bearing,
300                 (jfloat)sGpsLocationCopy.accuracy, (jlong)sGpsLocationCopy.timestamp);
301     }
302     if (pendingCallbacks & kStatus) {
303         env->CallVoidMethod(obj, method_reportStatus, sGpsStatusCopy.status);
304     }
305     if (pendingCallbacks & kSvStatus) {
306         env->CallVoidMethod(obj, method_reportSvStatus);
307     }
308     if (pendingCallbacks & kAGpsStatus) {
309         env->CallVoidMethod(obj, method_reportAGpsStatus, sAGpsStatusCopy.type, sAGpsStatusCopy.status);
310     }
311     if (pendingCallbacks & kNmeaAvailable) {
312         for (int i = 0; i < nmeaSentenceCount; i++) {
313             env->CallVoidMethod(obj, method_reportNmea, i, sNmeaBuffer[i].timestamp);
314         }
315     }
316     if (pendingCallbacks & kXtraDownloadRequest) {
317         env->CallVoidMethod(obj, method_xtraDownloadRequest);
318     }
319     if (pendingCallbacks & kDisableRequest) {
320         // don't need to do anything - we are just poking so wait_for_event will return.
321     }
322     if (pendingCallbacks & kNiNotification) {
323        LOGD("android_location_GpsLocationProvider_wait_for_event: sent notification callback.");
324        jstring reqId = env->NewStringUTF(sGpsNiNotificationCopy.requestor_id);
325        jstring text = env->NewStringUTF(sGpsNiNotificationCopy.text);
326        jstring extras = env->NewStringUTF(sGpsNiNotificationCopy.extras);
327        env->CallVoidMethod(obj, method_reportNiNotification,
328              sGpsNiNotificationCopy.notification_id,
329              sGpsNiNotificationCopy.ni_type,
330              sGpsNiNotificationCopy.notify_flags,
331              sGpsNiNotificationCopy.timeout,
332              sGpsNiNotificationCopy.default_response,
333              reqId,
334              text,
335              sGpsNiNotificationCopy.requestor_id_encoding,
336              sGpsNiNotificationCopy.text_encoding,
337              extras
338        );
339     }
340 }
341 
android_location_GpsLocationProvider_read_sv_status(JNIEnv * env,jobject obj,jintArray prnArray,jfloatArray snrArray,jfloatArray elevArray,jfloatArray azumArray,jintArray maskArray)342 static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj,
343         jintArray prnArray, jfloatArray snrArray, jfloatArray elevArray, jfloatArray azumArray,
344         jintArray maskArray)
345 {
346     // this should only be called from within a call to reportStatus, so we don't need to lock here
347 
348     jint* prns = env->GetIntArrayElements(prnArray, 0);
349     jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
350     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
351     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
352     jint* mask = env->GetIntArrayElements(maskArray, 0);
353 
354     int num_svs = sGpsSvStatusCopy.num_svs;
355     for (int i = 0; i < num_svs; i++) {
356         prns[i] = sGpsSvStatusCopy.sv_list[i].prn;
357         snrs[i] = sGpsSvStatusCopy.sv_list[i].snr;
358         elev[i] = sGpsSvStatusCopy.sv_list[i].elevation;
359         azim[i] = sGpsSvStatusCopy.sv_list[i].azimuth;
360     }
361     mask[0] = sGpsSvStatusCopy.ephemeris_mask;
362     mask[1] = sGpsSvStatusCopy.almanac_mask;
363     mask[2] = sGpsSvStatusCopy.used_in_fix_mask;
364 
365     env->ReleaseIntArrayElements(prnArray, prns, 0);
366     env->ReleaseFloatArrayElements(snrArray, snrs, 0);
367     env->ReleaseFloatArrayElements(elevArray, elev, 0);
368     env->ReleaseFloatArrayElements(azumArray, azim, 0);
369     env->ReleaseIntArrayElements(maskArray, mask, 0);
370     return num_svs;
371 }
372 
android_location_GpsLocationProvider_read_nmea(JNIEnv * env,jobject obj,jint index,jbyteArray nmeaArray,jint buffer_size)373 static jint android_location_GpsLocationProvider_read_nmea(JNIEnv* env, jobject obj, jint index, jbyteArray nmeaArray, jint buffer_size)
374 {
375     // this should only be called from within a call to reportNmea, so we don't need to lock here
376 
377     jbyte* nmea = env->GetByteArrayElements(nmeaArray, 0);
378 
379     int length = strlen(sNmeaBufferCopy[index].nmea);
380     if (length > buffer_size)
381         length = buffer_size;
382     memcpy(nmea, sNmeaBufferCopy[index].nmea, length);
383 
384     env->ReleaseByteArrayElements(nmeaArray, nmea, 0);
385     return length;
386 }
387 
android_location_GpsLocationProvider_inject_time(JNIEnv * env,jobject obj,jlong time,jlong timeReference,jint uncertainty)388 static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobject obj, jlong time,
389         jlong timeReference, jint uncertainty)
390 {
391     sGpsInterface->inject_time(time, timeReference, uncertainty);
392 }
393 
android_location_GpsLocationProvider_inject_location(JNIEnv * env,jobject obj,jdouble latitude,jdouble longitude,jfloat accuracy)394 static void android_location_GpsLocationProvider_inject_location(JNIEnv* env, jobject obj,
395         jdouble latitude, jdouble longitude, jfloat accuracy)
396 {
397     sGpsInterface->inject_location(latitude, longitude, accuracy);
398 }
399 
android_location_GpsLocationProvider_supports_xtra(JNIEnv * env,jobject obj)400 static jboolean android_location_GpsLocationProvider_supports_xtra(JNIEnv* env, jobject obj)
401 {
402     if (!sGpsXtraInterface) {
403         sGpsXtraInterface = (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);
404         if (sGpsXtraInterface) {
405             int result = sGpsXtraInterface->init(&sGpsXtraCallbacks);
406             if (result) {
407                 sGpsXtraInterface = NULL;
408             }
409         }
410     }
411 
412     return (sGpsXtraInterface != NULL);
413 }
414 
android_location_GpsLocationProvider_inject_xtra_data(JNIEnv * env,jobject obj,jbyteArray data,jint length)415 static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, jobject obj,
416         jbyteArray data, jint length)
417 {
418     jbyte* bytes = env->GetByteArrayElements(data, 0);
419     sGpsXtraInterface->inject_xtra_data((char *)bytes, length);
420     env->ReleaseByteArrayElements(data, bytes, 0);
421 }
422 
android_location_GpsLocationProvider_agps_data_conn_open(JNIEnv * env,jobject obj,jstring apn)423 static void android_location_GpsLocationProvider_agps_data_conn_open(JNIEnv* env, jobject obj, jstring apn)
424 {
425     if (!sAGpsInterface) {
426         sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
427     }
428     if (sAGpsInterface) {
429         if (apn == NULL) {
430             jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
431             return;
432         }
433         const char *apnStr = env->GetStringUTFChars(apn, NULL);
434         sAGpsInterface->data_conn_open(apnStr);
435         env->ReleaseStringUTFChars(apn, apnStr);
436     }
437 }
438 
android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv * env,jobject obj)439 static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* env, jobject obj)
440 {
441     if (!sAGpsInterface) {
442         sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
443     }
444     if (sAGpsInterface) {
445         sAGpsInterface->data_conn_closed();
446     }
447 }
448 
android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv * env,jobject obj)449 static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* env, jobject obj)
450 {
451     if (!sAGpsInterface) {
452         sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
453     }
454     if (sAGpsInterface) {
455         sAGpsInterface->data_conn_failed();
456     }
457 }
458 
android_location_GpsLocationProvider_set_agps_server(JNIEnv * env,jobject obj,jint type,jstring hostname,jint port)459 static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj,
460         jint type, jstring hostname, jint port)
461 {
462     if (!sAGpsInterface) {
463         sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
464     }
465     if (sAGpsInterface) {
466         const char *c_hostname = env->GetStringUTFChars(hostname, NULL);
467         sAGpsInterface->set_server(type, c_hostname, port);
468         env->ReleaseStringUTFChars(hostname, c_hostname);
469     }
470 }
471 
android_location_GpsLocationProvider_send_ni_response(JNIEnv * env,jobject obj,jint notifId,jint response)472 static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* env, jobject obj,
473       jint notifId, jint response)
474 {
475    if (!sGpsNiInterface)
476       sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
477    if (sGpsNiInterface) {
478       sGpsNiInterface->respond(notifId, response);
479    }
480 }
481 
482 static JNINativeMethod sMethods[] = {
483      /* name, signature, funcPtr */
484     {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
485     {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
486     {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
487     {"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable},
488     {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
489     {"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start},
490     {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
491     {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},
492     {"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event},
493     {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},
494     {"native_read_nmea", "(I[BI)I", (void*)android_location_GpsLocationProvider_read_nmea},
495     {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
496     {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location},
497     {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
498     {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},
499     {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open},
500     {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
501     {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
502     {"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},
503     {"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},
504 };
505 
register_android_location_GpsLocationProvider(JNIEnv * env)506 int register_android_location_GpsLocationProvider(JNIEnv* env)
507 {
508     return jniRegisterNativeMethods(env, "com/android/internal/location/GpsLocationProvider", sMethods, NELEM(sMethods));
509 }
510 
511 } /* namespace android */
512