diff options
-rw-r--r-- | core/jni/android_location_GpsLocationProvider.cpp | 81 | ||||
-rw-r--r-- | location/java/com/android/internal/location/GpsLocationProvider.java | 70 |
2 files changed, 131 insertions, 20 deletions
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp index f0b35e9..bbde8d5 100644 --- a/core/jni/android_location_GpsLocationProvider.cpp +++ b/core/jni/android_location_GpsLocationProvider.cpp @@ -31,6 +31,7 @@ static pthread_cond_t sEventCond = PTHREAD_COND_INITIALIZER; static jmethodID method_reportLocation; static jmethodID method_reportStatus; static jmethodID method_reportSvStatus; +static jmethodID method_reportSuplStatus; static jmethodID method_xtraDownloadRequest; static const GpsInterface* sGpsInterface = NULL; @@ -41,19 +42,22 @@ static const GpsSuplInterface* sGpsSuplInterface = NULL; static GpsLocation sGpsLocation; static GpsStatus sGpsStatus; static GpsSvStatus sGpsSvStatus; +static GpsSuplStatus sGpsSuplStatus; // a copy of the data shared by android_location_GpsLocationProvider_wait_for_event // and android_location_GpsLocationProvider_read_status static GpsLocation sGpsLocationCopy; static GpsStatus sGpsStatusCopy; static GpsSvStatus sGpsSvStatusCopy; +static GpsSuplStatus sGpsSuplStatusCopy; enum CallbackType { kLocation = 1, kStatus = 2, kSvStatus = 4, - kXtraDownloadRequest = 8, - kDisableRequest = 16, + kSuplStatus = 8, + kXtraDownloadRequest = 16, + kDisableRequest = 32, }; static int sPendingCallbacks; @@ -92,6 +96,17 @@ static void sv_status_callback(GpsSvStatus* sv_status) pthread_mutex_unlock(&sEventMutex); } +static void supl_status_callback(GpsSuplStatus* supl_status) +{ + pthread_mutex_lock(&sEventMutex); + + sPendingCallbacks |= kSuplStatus; + memcpy(&sGpsSuplStatus, supl_status, sizeof(GpsSuplStatus)); + + pthread_cond_signal(&sEventCond); + pthread_mutex_unlock(&sEventMutex); +} + GpsCallbacks sGpsCallbacks = { location_callback, status_callback, @@ -111,11 +126,15 @@ GpsXtraCallbacks sGpsXtraCallbacks = { download_request_callback, }; +GpsSuplCallbacks sGpsSuplCallbacks = { + supl_status_callback, +}; static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V"); method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V"); method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V"); + method_reportSuplStatus = env->GetMethodID(clazz, "reportSuplStatus", "(I)V"); method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V"); } @@ -129,7 +148,13 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o { if (!sGpsInterface) sGpsInterface = gps_get_interface(); - return (sGpsInterface && sGpsInterface->init(&sGpsCallbacks) == 0); + if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) + return false; + + if (!sGpsSuplInterface) + sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + if (sGpsSuplInterface) + sGpsSuplInterface->init(&sGpsSuplCallbacks); } static void android_location_GpsLocationProvider_disable(JNIEnv* env, jobject obj) @@ -186,6 +211,7 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy)); memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy)); memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy)); + memcpy(&sGpsSuplStatusCopy, &sGpsSuplStatus, sizeof(sGpsSuplStatusCopy)); pthread_mutex_unlock(&sEventMutex); if (pendingCallbacks & kLocation) { @@ -201,6 +227,9 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job if (pendingCallbacks & kSvStatus) { env->CallVoidMethod(obj, method_reportSvStatus); } + if (pendingCallbacks & kSuplStatus) { + env->CallVoidMethod(obj, method_reportSuplStatus, sGpsSuplStatusCopy.status); + } if (pendingCallbacks & kXtraDownloadRequest) { env->CallVoidMethod(obj, method_xtraDownloadRequest); } @@ -269,30 +298,50 @@ static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, j env->ReleaseByteArrayElements(data, bytes, 0); } -static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj, - jint addr, jint port) +static void android_location_GpsLocationProvider_supl_data_conn_open(JNIEnv* env, jobject obj, jstring apn) { if (!sGpsSuplInterface) { sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); } if (sGpsSuplInterface) { - sGpsSuplInterface->set_server(addr, port); + if (apn == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + return; + } + const char *apnStr = env->GetStringUTFChars(apn, NULL); + sGpsSuplInterface->data_conn_open(apnStr); + env->ReleaseStringUTFChars(apn, apnStr); } } -static void android_location_GpsLocationProvider_set_supl_apn(JNIEnv* env, jobject obj, jstring apn) +static void android_location_GpsLocationProvider_supl_data_conn_closed(JNIEnv* env, jobject obj) { if (!sGpsSuplInterface) { sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); } if (sGpsSuplInterface) { - if (apn == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - return; - } - const char *apnStr = env->GetStringUTFChars(apn, NULL); - sGpsSuplInterface->set_apn(apnStr); - env->ReleaseStringUTFChars(apn, apnStr); + sGpsSuplInterface->data_conn_closed(); + } +} + +static void android_location_GpsLocationProvider_supl_data_conn_failed(JNIEnv* env, jobject obj) +{ + if (!sGpsSuplInterface) { + sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + } + if (sGpsSuplInterface) { + sGpsSuplInterface->data_conn_failed(); + } +} + +static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj, + jint addr, jint port) +{ + if (!sGpsSuplInterface) { + sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + } + if (sGpsSuplInterface) { + sGpsSuplInterface->set_server(addr, port); } } @@ -312,8 +361,10 @@ static JNINativeMethod sMethods[] = { {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, + {"native_supl_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_supl_data_conn_open}, + {"native_supl_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_closed}, + {"native_supl_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_failed}, {"native_set_supl_server", "(II)V", (void*)android_location_GpsLocationProvider_set_supl_server}, - {"native_set_supl_apn", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_set_supl_apn}, }; int register_android_location_GpsLocationProvider(JNIEnv* env) diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java index 8a33574..d56594e 100644 --- a/location/java/com/android/internal/location/GpsLocationProvider.java +++ b/location/java/com/android/internal/location/GpsLocationProvider.java @@ -28,6 +28,7 @@ import android.location.Location; import android.location.LocationManager; import android.location.LocationProvider; import android.location.LocationProviderImpl; +import android.net.ConnectivityManager; import android.net.SntpClient; import android.os.Bundle; import android.os.IBinder; @@ -99,6 +100,14 @@ public class GpsLocationProvider extends LocationProviderImpl { private static final int GPS_STATUS_ENGINE_ON = 3; private static final int GPS_STATUS_ENGINE_OFF = 4; + // these need to match GpsSuplStatusValue defines in gps.h + /** SUPL status event values. */ + private static final int GPS_REQUEST_SUPL_DATA_CONN = 1; + private static final int GPS_RELEASE_SUPL_DATA_CONN = 2; + private static final int GPS_SUPL_DATA_CONNECTED = 3; + private static final int GPS_SUPL_DATA_CONN_DONE = 4; + private static final int GPS_SUPL_DATA_CONN_FAILED = 5; + // these need to match GpsLocationFlags enum in gps.h private static final int LOCATION_INVALID = 0; private static final int LOCATION_HAS_LAT_LONG = 1; @@ -122,6 +131,11 @@ public class GpsLocationProvider extends LocationProviderImpl { private static final int GPS_DELETE_CELLDB_INFO = 0x8000; private static final int GPS_DELETE_ALL = 0xFFFF; + // for mSuplDataConnectionState + private static final int SUPL_DATA_CONNECTION_CLOSED = 0; + private static final int SUPL_DATA_CONNECTION_OPENING = 1; + private static final int SUPL_DATA_CONNECTION_OPEN = 2; + private static final String PROPERTIES_FILE = "/etc/gps.conf"; private int mLocationFlags = LOCATION_INVALID; @@ -176,6 +190,9 @@ public class GpsLocationProvider extends LocationProviderImpl { private String mSuplHost; private int mSuplPort; private boolean mSetSuplServer; + private String mSuplApn; + private int mSuplDataConnectionState; + private ConnectivityManager mConnMgr; // how often to request NTP time, in milliseconds // current setting 4 hours @@ -199,9 +216,11 @@ public class GpsLocationProvider extends LocationProviderImpl { Log.d(TAG, "state: " + state + " apnName: " + apnName + " reason: " + reason); } if ("CONNECTED".equals(state)) { - native_set_supl_apn(apnName); - } else { - native_set_supl_apn(""); + mSuplApn = apnName; + if (mSuplDataConnectionState == SUPL_DATA_CONNECTION_OPENING) { + native_supl_data_conn_open(mSuplApn); + mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPEN; + } } } } @@ -220,6 +239,8 @@ public class GpsLocationProvider extends LocationProviderImpl { intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); context.registerReceiver(receiver, intentFilter); + mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + mProperties = new Properties(); try { File file = new File(PROPERTIES_FILE); @@ -782,7 +803,44 @@ public class GpsLocationProvider extends LocationProviderImpl { updateStatus(TEMPORARILY_UNAVAILABLE, mSvCount); } } - + + /** + * called from native code to update SUPL status + */ + private void reportSuplStatus(int status) { + switch (status) { + case GPS_REQUEST_SUPL_DATA_CONN: + int result = mConnMgr.startUsingNetworkFeature( + ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL); + if (result == Phone.APN_ALREADY_ACTIVE) { + native_supl_data_conn_open(mSuplApn); + mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPEN; + } else if (result == Phone.APN_REQUEST_STARTED) { + mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPENING; + } else { + native_supl_data_conn_failed(); + } + break; + case GPS_RELEASE_SUPL_DATA_CONN: + if (mSuplDataConnectionState != SUPL_DATA_CONNECTION_CLOSED) { + mConnMgr.stopUsingNetworkFeature( + ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL); + native_supl_data_conn_closed(); + mSuplDataConnectionState = SUPL_DATA_CONNECTION_CLOSED; + } + break; + case GPS_SUPL_DATA_CONNECTED: + // Log.d(TAG, "GPS_SUPL_DATA_CONNECTED"); + break; + case GPS_SUPL_DATA_CONN_DONE: + // Log.d(TAG, "GPS_SUPL_DATA_CONN_DONE"); + break; + case GPS_SUPL_DATA_CONN_FAILED: + // Log.d(TAG, "GPS_SUPL_DATA_CONN_FAILED"); + break; + } + } + private void xtraDownloadRequest() { if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest"); if (mNetworkThread != null) { @@ -1002,6 +1060,8 @@ public class GpsLocationProvider extends LocationProviderImpl { private native void native_inject_xtra_data(byte[] data, int length); // SUPL Support + private native void native_supl_data_conn_open(String apn); + private native void native_supl_data_conn_closed(); + private native void native_supl_data_conn_failed(); private native void native_set_supl_server(int addr, int port); - private native void native_set_supl_apn(String apn); } |