Merge change 1355 into donut

* changes:
  GPS: Generalize SUPL support to include AGPS for CDMA
This commit is contained in:
Android (Google) Code Review
2009-05-11 10:34:33 -07:00
2 changed files with 155 additions and 129 deletions

View File

@@ -31,31 +31,31 @@ 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_reportAGpsStatus;
static jmethodID method_xtraDownloadRequest;
static const GpsInterface* sGpsInterface = NULL;
static const GpsXtraInterface* sGpsXtraInterface = NULL;
static const GpsSuplInterface* sGpsSuplInterface = NULL;
static const AGpsInterface* sAGpsInterface = NULL;
// data written to by GPS callbacks
static GpsLocation sGpsLocation;
static GpsStatus sGpsStatus;
static GpsSvStatus sGpsSvStatus;
static GpsSuplStatus sGpsSuplStatus;
static AGpsStatus sAGpsStatus;
// 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;
static AGpsStatus sAGpsStatusCopy;
enum CallbackType {
kLocation = 1,
kStatus = 2,
kSvStatus = 4,
kSuplStatus = 8,
kAGpsStatus = 8,
kXtraDownloadRequest = 16,
kDisableRequest = 32,
};
@@ -96,12 +96,12 @@ static void sv_status_callback(GpsSvStatus* sv_status)
pthread_mutex_unlock(&sEventMutex);
}
static void supl_status_callback(GpsSuplStatus* supl_status)
static void agps_status_callback(AGpsStatus* agps_status)
{
pthread_mutex_lock(&sEventMutex);
sPendingCallbacks |= kSuplStatus;
memcpy(&sGpsSuplStatus, supl_status, sizeof(GpsSuplStatus));
sPendingCallbacks |= kAGpsStatus;
memcpy(&sAGpsStatus, agps_status, sizeof(AGpsStatus));
pthread_cond_signal(&sEventCond);
pthread_mutex_unlock(&sEventMutex);
@@ -126,15 +126,15 @@ GpsXtraCallbacks sGpsXtraCallbacks = {
download_request_callback,
};
GpsSuplCallbacks sGpsSuplCallbacks = {
supl_status_callback,
AGpsCallbacks sAGpsCallbacks = {
agps_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_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V");
method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
}
@@ -151,10 +151,10 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o
if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
return false;
if (!sGpsSuplInterface)
sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
if (sGpsSuplInterface)
sGpsSuplInterface->init(&sGpsSuplCallbacks);
if (!sAGpsInterface)
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
if (sAGpsInterface)
sAGpsInterface->init(&sAGpsCallbacks);
return true;
}
@@ -187,12 +187,6 @@ static jboolean android_location_GpsLocationProvider_stop(JNIEnv* env, jobject o
return (sGpsInterface->stop() == 0);
}
static void android_location_GpsLocationProvider_set_fix_frequency(JNIEnv* env, jobject obj, jint fixFrequency)
{
if (sGpsInterface->set_fix_frequency)
sGpsInterface->set_fix_frequency(fixFrequency);
}
static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* env, jobject obj, jint flags)
{
sGpsInterface->delete_aiding_data(flags);
@@ -212,7 +206,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));
memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy));
pthread_mutex_unlock(&sEventMutex);
if (pendingCallbacks & kLocation) {
@@ -228,8 +222,8 @@ 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 & kAGpsStatus) {
env->CallVoidMethod(obj, method_reportAGpsStatus, sAGpsStatusCopy.type, sAGpsStatusCopy.status);
}
if (pendingCallbacks & kXtraDownloadRequest) {
env->CallVoidMethod(obj, method_xtraDownloadRequest);
@@ -299,73 +293,72 @@ static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, j
env->ReleaseByteArrayElements(data, bytes, 0);
}
static void android_location_GpsLocationProvider_supl_data_conn_open(JNIEnv* env, jobject obj, jstring apn)
static void android_location_GpsLocationProvider_agps_data_conn_open(JNIEnv* env, jobject obj, jstring apn)
{
if (!sGpsSuplInterface) {
sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
if (!sAGpsInterface) {
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
}
if (sGpsSuplInterface) {
if (sAGpsInterface) {
if (apn == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return;
}
const char *apnStr = env->GetStringUTFChars(apn, NULL);
sGpsSuplInterface->data_conn_open(apnStr);
sAGpsInterface->data_conn_open(apnStr);
env->ReleaseStringUTFChars(apn, apnStr);
}
}
static void android_location_GpsLocationProvider_supl_data_conn_closed(JNIEnv* env, jobject obj)
static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* env, jobject obj)
{
if (!sGpsSuplInterface) {
sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
if (!sAGpsInterface) {
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
}
if (sGpsSuplInterface) {
sGpsSuplInterface->data_conn_closed();
if (sAGpsInterface) {
sAGpsInterface->data_conn_closed();
}
}
static void android_location_GpsLocationProvider_supl_data_conn_failed(JNIEnv* env, jobject obj)
static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* env, jobject obj)
{
if (!sGpsSuplInterface) {
sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
if (!sAGpsInterface) {
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
}
if (sGpsSuplInterface) {
sGpsSuplInterface->data_conn_failed();
if (sAGpsInterface) {
sAGpsInterface->data_conn_failed();
}
}
static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj,
jint addr, jint port)
static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj,
jint type, jint addr, jint port)
{
if (!sGpsSuplInterface) {
sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
if (!sAGpsInterface) {
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
}
if (sGpsSuplInterface) {
sGpsSuplInterface->set_server(addr, port);
if (sAGpsInterface) {
sAGpsInterface->set_server(type, addr, port);
}
}
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
{"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
{"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
{"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable},
{"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
{"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start},
{"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
{"native_set_fix_frequency", "(I)V", (void*)android_location_GpsLocationProvider_set_fix_frequency},
{"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},
{"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event},
{"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},
{"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_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported},
{"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
{"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable},
{"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
{"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start},
{"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
{"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},
{"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event},
{"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status},
{"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_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open},
{"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
{"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
{"native_set_agps_server", "(III)V", (void*)android_location_GpsLocationProvider_set_agps_server},
};
int register_android_location_GpsLocationProvider(JNIEnv* env)

View File

@@ -109,13 +109,13 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
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 GpsApgsStatusValue defines in gps.h
/** AGPS status event values. */
private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
private static final int GPS_AGPS_DATA_CONNECTED = 3;
private static final int GPS_AGPS_DATA_CONN_DONE = 4;
private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
// these need to match GpsLocationFlags enum in gps.h
private static final int LOCATION_INVALID = 0;
@@ -124,8 +124,8 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
private static final int LOCATION_HAS_SPEED = 4;
private static final int LOCATION_HAS_BEARING = 8;
private static final int LOCATION_HAS_ACCURACY = 16;
// IMPORTANT - the GPS_DELETE_* symbols here must match constants in GpsLocationProvider.java
// IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
private static final int GPS_DELETE_EPHEMERIS = 0x0001;
private static final int GPS_DELETE_ALMANAC = 0x0002;
private static final int GPS_DELETE_POSITION = 0x0004;
@@ -140,10 +140,14 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
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;
// these need to match AGpsType enum in gps.h
private static final int AGPS_TYPE_SUPL = 1;
private static final int AGPS_TYPE_C2K = 2;
// for mAGpsDataConnectionState
private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
private static final int AGPS_DATA_CONNECTION_OPENING = 1;
private static final int AGPS_DATA_CONNECTION_OPEN = 2;
private static final String PROPERTIES_FILE = "/etc/gps.conf";
@@ -203,9 +207,12 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
private String mSuplHost;
private int mSuplPort;
private String mC2KHost;
private int mC2KPort;
private boolean mSetSuplServer;
private String mSuplApn;
private int mSuplDataConnectionState;
private boolean mSetC2KServer;
private String mAGpsApn;
private int mAGpsDataConnectionState;
private final ConnectivityManager mConnMgr;
// Wakelocks
@@ -293,11 +300,12 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
if (Config.LOGD) {
Log.d(TAG, "state: " + state + " apnName: " + apnName + " reason: " + reason);
}
// FIXME - might not have an APN on CDMA
if ("CONNECTED".equals(state) && apnName != null && apnName.length() > 0) {
mSuplApn = apnName;
if (mSuplDataConnectionState == SUPL_DATA_CONNECTION_OPENING) {
native_supl_data_conn_open(mSuplApn);
mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPEN;
mAGpsApn = apnName;
if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
native_agps_data_conn_open(mAGpsApn);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
}
}
}
@@ -336,14 +344,26 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
mProperties.load(stream);
stream.close();
mNtpServer = mProperties.getProperty("NTP_SERVER", null);
mSuplHost = mProperties.getProperty("SUPL_HOST");
String suplPortString = mProperties.getProperty("SUPL_PORT");
if (mSuplHost != null && suplPortString != null) {
String portString = mProperties.getProperty("SUPL_PORT");
if (mSuplHost != null && portString != null) {
try {
mSuplPort = Integer.parseInt(suplPortString);
mSuplPort = Integer.parseInt(portString);
mSetSuplServer = true;
} catch (NumberFormatException e) {
Log.e(TAG, "unable to parse SUPL_PORT: " + suplPortString);
Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
}
}
mC2KHost = mProperties.getProperty("C2K_HOST");
portString = mProperties.getProperty("C2K_PORT");
if (mC2KHost != null && portString != null) {
try {
mC2KPort = Integer.parseInt(portString);
mSetC2KServer = true;
} catch (NumberFormatException e) {
Log.e(TAG, "unable to parse C2K_PORT: " + portString);
}
}
} catch (IOException e) {
@@ -358,7 +378,8 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
public boolean requiresNetwork() {
// We want updateNetworkState() to get called when the network state changes
// for XTRA and NTP time injection support.
return (mNtpServer != null || native_supports_xtra() || mSuplHost != null);
return (mNtpServer != null || native_supports_xtra() ||
mSuplHost != null || mC2KHost != null);
}
public void updateNetworkState(int state) {
@@ -561,7 +582,6 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
interval = 1;
}
mFixInterval = interval;
native_set_fix_frequency(mFixInterval);
}
}
@@ -871,38 +891,38 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
}
/**
* called from native code to update SUPL status
* called from native code to update AGPS status
*/
private void reportSuplStatus(int status) {
private void reportAGpsStatus(int type, int status) {
switch (status) {
case GPS_REQUEST_SUPL_DATA_CONN:
case GPS_REQUEST_AGPS_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;
native_agps_data_conn_open(mAGpsApn);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
} else if (result == Phone.APN_REQUEST_STARTED) {
mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPENING;
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
} else {
native_supl_data_conn_failed();
native_agps_data_conn_failed();
}
break;
case GPS_RELEASE_SUPL_DATA_CONN:
if (mSuplDataConnectionState != SUPL_DATA_CONNECTION_CLOSED) {
case GPS_RELEASE_AGPS_DATA_CONN:
if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
mConnMgr.stopUsingNetworkFeature(
ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
native_supl_data_conn_closed();
mSuplDataConnectionState = SUPL_DATA_CONNECTION_CLOSED;
native_agps_data_conn_closed();
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
}
break;
case GPS_SUPL_DATA_CONNECTED:
// Log.d(TAG, "GPS_SUPL_DATA_CONNECTED");
case GPS_AGPS_DATA_CONNECTED:
// Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
break;
case GPS_SUPL_DATA_CONN_DONE:
// Log.d(TAG, "GPS_SUPL_DATA_CONN_DONE");
case GPS_AGPS_DATA_CONN_DONE:
// Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
break;
case GPS_SUPL_DATA_CONN_FAILED:
// Log.d(TAG, "GPS_SUPL_DATA_CONN_FAILED");
case GPS_AGPS_DATA_CONN_FAILED:
// Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
break;
}
}
@@ -914,6 +934,29 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
}
}
private boolean setAGpsServer(int type, String host, int port) {
try {
InetAddress inetAddress = InetAddress.getByName(host);
if (inetAddress != null) {
byte[] addrBytes = inetAddress.getAddress();
long addr = 0;
for (int i = 0; i < addrBytes.length; i++) {
int temp = addrBytes[i];
// signed -> unsigned
if (temp < 0) temp = 256 + temp;
addr = addr * 256 + temp;
}
// use MS-Based position mode if SUPL support is enabled
mPositionMode = GPS_POSITION_MODE_MS_BASED;
native_set_agps_server(type, (int)addr, port);
}
} catch (UnknownHostException e) {
Log.e(TAG, "unknown host for server " + host);
return false;
}
return true;
}
private class GpsEventThread extends Thread {
public GpsEventThread() {
@@ -985,7 +1028,8 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
}
}
waitTime = getWaitTime();
} while (!mDone && ((!mXtraDownloadRequested && !mSetSuplServer && waitTime > 0)
} while (!mDone && ((!mXtraDownloadRequested &&
!mSetSuplServer && !mSetC2KServer && waitTime > 0)
|| !mNetworkAvailable));
if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop");
@@ -1012,26 +1056,15 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
}
}
// Set the SUPL server address if we have not yet
// Set the AGPS server addresses if we have not yet
if (mSetSuplServer) {
try {
InetAddress inetAddress = InetAddress.getByName(mSuplHost);
if (inetAddress != null) {
byte[] addrBytes = inetAddress.getAddress();
long addr = 0;
for (int i = 0; i < addrBytes.length; i++) {
int temp = addrBytes[i];
// signed -> unsigned
if (temp < 0) temp = 256 + temp;
addr = addr * 256 + temp;
}
// use MS-Based position mode if SUPL support is enabled
mPositionMode = GPS_POSITION_MODE_MS_BASED;
native_set_supl_server((int)addr, mSuplPort);
mSetSuplServer = false;
}
} catch (UnknownHostException e) {
Log.e(TAG, "unknown host for SUPL server " + mSuplHost);
if (setAGpsServer(AGPS_TYPE_SUPL, mSuplHost, mSuplPort)) {
mSetSuplServer = false;
}
}
if (mSetC2KServer) {
if (setAGpsServer(AGPS_TYPE_C2K, mC2KHost, mC2KPort)) {
mSetC2KServer = false;
}
}
@@ -1125,9 +1158,9 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
private native boolean native_supports_xtra();
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);
// AGPS Support
private native void native_agps_data_conn_open(String apn);
private native void native_agps_data_conn_closed();
private native void native_agps_data_conn_failed();
private native void native_set_agps_server(int type, int addr, int port);
}