Address SUPL connection requestRouteToHost deprecation
The method ConnectivityManager.requestRouteToHost() has long been
deprecated. The IAGnss.hal interface, implementation, and the
corresponding framework code must be changed to address this issue.
See b/25876485 for details and solution.
Bug: 25876485
Test: Tested with code instrumentation to verify that the
@2.0::AGnss.hal dataConnOpen() method implementation
is called with correct arguments.
Test: Verified @1.0::AGnss.hal backward compatibility on a
Pixel 3 device.
Change-Id: Ide8030a3d792755a515c936d2fb40ad3726d8fb9
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 9c6cb20..b6954fc 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -177,10 +177,6 @@
private static final int AGPS_SUPL_MODE_MSA = 0x02;
private static final int AGPS_SUPL_MODE_MSB = 0x01;
- // these need to match AGnssType enum in IAGnssCallback.hal
- private static final int AGPS_TYPE_SUPL = 1;
- private static final int AGPS_TYPE_C2K = 2;
-
// Handler messages
private static final int CHECK_LOCATION = 1;
private static final int ENABLE = 2;
@@ -973,7 +969,8 @@
if (mSuplServerHost != null
&& mSuplServerPort > TCP_MIN_PORT
&& mSuplServerPort <= TCP_MAX_PORT) {
- native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
+ native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_SUPL,
+ mSuplServerHost, mSuplServerPort);
}
}
@@ -1025,10 +1022,12 @@
// TODO: remove the following native calls if we can make sure they are redundant.
if (mSuplServerHost != null) {
- native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
+ native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_SUPL,
+ mSuplServerHost, mSuplServerPort);
}
if (mC2KServerHost != null) {
- native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
+ native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_C2K,
+ mC2KServerHost, mC2KServerPort);
}
mGnssMeasurementsProvider.onGpsEnabledChanged();
@@ -1575,8 +1574,8 @@
}
@NativeEntryPoint
- private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
- mNetworkConnectivityHandler.onReportAGpsStatus(type, status, ipaddr);
+ private void reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr) {
+ mNetworkConnectivityHandler.onReportAGpsStatus(agpsType, agpsStatus, suplIpAddr);
}
@NativeEntryPoint
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
index 3903f2a..c38373f 100644
--- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
@@ -68,6 +68,12 @@
private static final int AGNSS_NET_CAPABILITY_NOT_METERED = 1 << 0;
private static final int AGNSS_NET_CAPABILITY_NOT_ROAMING = 1 << 1;
+ // these need to match AGnssType enum in IAGnssCallback.hal
+ public static final int AGPS_TYPE_SUPL = 1;
+ public static final int AGPS_TYPE_C2K = 2;
+ private static final int AGPS_TYPE_EIMS = 3;
+ private static final int AGPS_TYPE_IMS = 4;
+
// Default time limit in milliseconds for the ConnectivityManager to find a suitable
// network with SUPL connectivity or report an error.
private static final int SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS = 10 * 1000;
@@ -86,6 +92,7 @@
private int mAGpsDataConnectionState;
private InetAddress mAGpsDataConnectionIpAddr;
+ private int mAGpsType;
private final Context mContext;
@@ -198,21 +205,11 @@
/**
* called from native code to update AGPS status
*/
- public void onReportAGpsStatus(int type, int status, byte[] ipaddr) {
- switch (status) {
+ public void onReportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr) {
+ switch (agpsStatus) {
case GPS_REQUEST_AGPS_DATA_CONN:
if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
- Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
- InetAddress connectionIpAddress = null;
- if (ipaddr != null) {
- try {
- connectionIpAddress = InetAddress.getByAddress(ipaddr);
- if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
- } catch (UnknownHostException e) {
- Log.e(TAG, "Bad IP Address: " + ipaddr, e);
- }
- }
- requestSuplConnection(connectionIpAddress);
+ requestSuplConnection(agpsType, suplIpAddr);
break;
case GPS_RELEASE_AGPS_DATA_CONN:
if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
@@ -228,7 +225,7 @@
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
break;
default:
- if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
+ if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + agpsStatus);
}
}
@@ -308,8 +305,8 @@
};
}
- private void requestSuplConnection(InetAddress inetAddress) {
- postEvent(() -> handleRequestSuplConnection(inetAddress));
+ private void requestSuplConnection(int agpsType, byte[] suplIpAddr) {
+ postEvent(() -> handleRequestSuplConnection(agpsType, suplIpAddr));
}
private void suplConnectionAvailable(Network network) {
@@ -435,8 +432,15 @@
// exception in the following call to native_agps_data_conn_open
apn = "dummy-apn";
}
+
+ // Setting route to host is needed for GNSS HAL implementations earlier than
+ // @2.0::IAgnssCallback. The HAL @2.0::IAgnssCallback.agnssStatusCb() method does
+ // not require setting route to SUPL host and hence does not provide an IP address.
+ if (mAGpsDataConnectionIpAddr != null) {
+ setRouting();
+ }
+
int apnIpType = getApnIpType(apn);
- setRouting();
if (DEBUG) {
String message = String.format(
"native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
@@ -444,29 +448,40 @@
apnIpType);
Log.d(TAG, message);
}
- native_agps_data_conn_open(apn, apnIpType);
+ native_agps_data_conn_open(network.getNetworkHandle(), apn, apnIpType);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
}
}
- private void handleRequestSuplConnection(InetAddress address) {
+ private void handleRequestSuplConnection(int agpsType, byte[] suplIpAddr) {
+ mAGpsDataConnectionIpAddr = null;
+ mAGpsType = agpsType;
+ if (suplIpAddr != null) {
+ if (VERBOSE) Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(suplIpAddr));
+ try {
+ mAGpsDataConnectionIpAddr = InetAddress.getByAddress(suplIpAddr);
+ if (DEBUG) Log.d(TAG, "IP address converted to: " + mAGpsDataConnectionIpAddr);
+ } catch (UnknownHostException e) {
+ Log.e(TAG, "Bad IP Address: " + suplIpAddr, e);
+ }
+ }
+
if (DEBUG) {
String message = String.format(
- "requestSuplConnection, state=%s, address=%s",
+ "requestSuplConnection, state=%s, agpsType=%s, address=%s",
agpsDataConnStateAsString(),
- address);
+ agpsTypeAsString(agpsType),
+ mAGpsDataConnectionIpAddr);
Log.d(TAG, message);
}
if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
return;
}
- mAGpsDataConnectionIpAddr = address;
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
- requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
+ requestBuilder.addCapability(getNetworkCapability(mAGpsType));
NetworkRequest request = requestBuilder.build();
mConnMgr.requestNetwork(
request,
@@ -474,6 +489,20 @@
SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS);
}
+ private int getNetworkCapability(int agpsType) {
+ switch (agpsType) {
+ case AGPS_TYPE_C2K:
+ case AGPS_TYPE_SUPL:
+ return NetworkCapabilities.NET_CAPABILITY_SUPL;
+ case AGPS_TYPE_EIMS:
+ return NetworkCapabilities.NET_CAPABILITY_EIMS;
+ case AGPS_TYPE_IMS:
+ return NetworkCapabilities.NET_CAPABILITY_IMS;
+ default:
+ throw new IllegalArgumentException("agpsType: " + agpsType);
+ }
+ }
+
private void handleReleaseSuplConnection(int agpsDataConnStatus) {
if (DEBUG) {
String message = String.format(
@@ -486,8 +515,8 @@
if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
return;
}
- mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
+ mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
switch (agpsDataConnStatus) {
case GPS_AGPS_DATA_CONN_FAILED:
@@ -501,12 +530,9 @@
}
}
+ // TODO(25876485): Delete this method when all devices upgrade to HAL @2.0::IAGnssCallback
+ // interface which does not require setting route to host.
private void setRouting() {
- if (mAGpsDataConnectionIpAddr == null) {
- return;
- }
-
- // TODO(25876485): replace the use of this deprecated API
boolean result = mConnMgr.requestRouteToHostAddress(
ConnectivityManager.TYPE_MOBILE_SUPL,
mAGpsDataConnectionIpAddr);
@@ -564,6 +590,21 @@
}
}
+ private String agpsTypeAsString(int agpsType) {
+ switch (agpsType) {
+ case AGPS_TYPE_SUPL:
+ return "SUPL";
+ case AGPS_TYPE_C2K:
+ return "C2K";
+ case AGPS_TYPE_EIMS:
+ return "EIMS";
+ case AGPS_TYPE_IMS:
+ return "IMS";
+ default:
+ return "<Unknown>";
+ }
+ }
+
private int getApnIpType(String apn) {
ensureInHandlerThread();
if (apn == null) {
@@ -614,7 +655,7 @@
}
// AGPS support
- private native void native_agps_data_conn_open(String apn, int apnIpType);
+ private native void native_agps_data_conn_open(long networkHandle, String apn, int apnIpType);
private native void native_agps_data_conn_closed();
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 729aed1..6d8fc1c 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -104,14 +104,12 @@
using android::hardware::Return;
using android::hardware::Void;
using android::hardware::hidl_vec;
+using android::hardware::hidl_string;
using android::hardware::hidl_death_recipient;
using android::hardware::gnss::V1_0::GnssConstellationType;
using android::hardware::gnss::V1_0::GnssLocation;
using android::hardware::gnss::V1_0::GnssLocationFlags;
-using android::hardware::gnss::V1_0::IAGnss;
-using android::hardware::gnss::V1_0::IAGnssCallback;
-using android::hardware::gnss::V1_0::IAGnssCallback;
using android::hardware::gnss::V1_0::IAGnssRilCallback;
using android::hardware::gnss::V1_0::IGnssBatching;
using android::hardware::gnss::V1_0::IGnssBatchingCallback;
@@ -145,6 +143,10 @@
using IGnssMeasurementCallback_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
using IAGnssRil_V1_0 = android::hardware::gnss::V1_0::IAGnssRil;
using IAGnssRil_V2_0 = android::hardware::gnss::V2_0::IAGnssRil;
+using IAGnss_V1_0 = android::hardware::gnss::V1_0::IAGnss;
+using IAGnss_V2_0 = android::hardware::gnss::V2_0::IAGnss;
+using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback;
+using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
using IMeasurementCorrections =
android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
@@ -171,7 +173,8 @@
sp<IAGnssRil_V1_0> agnssRilIface = nullptr;
sp<IAGnssRil_V2_0> agnssRilIface_V2_0 = nullptr;
sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
-sp<IAGnss> agnssIface = nullptr;
+sp<IAGnss_V1_0> agnssIface = nullptr;
+sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr;
sp<IGnssBatching> gnssBatchingIface = nullptr;
sp<IGnssDebug> gnssDebugIface = nullptr;
sp<IGnssConfiguration_V1_0> gnssConfigurationIface = nullptr;
@@ -310,6 +313,34 @@
}
}
+struct ScopedJniString {
+ ScopedJniString(JNIEnv* env, jstring javaString) : mEnv(env), mJavaString(javaString) {
+ mNativeString = mEnv->GetStringUTFChars(mJavaString, nullptr);
+ }
+
+ ~ScopedJniString() {
+ if (mNativeString != nullptr) {
+ mEnv->ReleaseStringUTFChars(mJavaString, mNativeString);
+ }
+ }
+
+ const char* c_str() const {
+ return mNativeString;
+ }
+
+ operator hidl_string() const {
+ return hidl_string(mNativeString);
+ }
+
+private:
+ ScopedJniString(const ScopedJniString&) = delete;
+ ScopedJniString& operator=(const ScopedJniString&) = delete;
+
+ JNIEnv* mEnv;
+ jstring mJavaString;
+ const char* mNativeString;
+};
+
class ScopedJniThreadAttach {
public:
ScopedJniThreadAttach() {
@@ -1038,21 +1069,21 @@
}
/*
- * AGnssCallback implements callback methods required by the IAGnss interface.
+ * AGnssCallback_V1_0 implements callback methods required by the IAGnssCallback 1.0 interface.
*/
-struct AGnssCallback : public IAGnssCallback {
+struct AGnssCallback_V1_0 : public IAGnssCallback_V1_0 {
// Methods from ::android::hardware::gps::V1_0::IAGnssCallback follow.
Return<void> agnssStatusIpV6Cb(
- const IAGnssCallback::AGnssStatusIpV6& agps_status) override;
+ const IAGnssCallback_V1_0::AGnssStatusIpV6& agps_status) override;
Return<void> agnssStatusIpV4Cb(
- const IAGnssCallback::AGnssStatusIpV4& agps_status) override;
+ const IAGnssCallback_V1_0::AGnssStatusIpV4& agps_status) override;
private:
jbyteArray convertToIpV4(uint32_t ip);
};
-Return<void> AGnssCallback::agnssStatusIpV6Cb(
- const IAGnssCallback::AGnssStatusIpV6& agps_status) {
+Return<void> AGnssCallback_V1_0::agnssStatusIpV6Cb(
+ const IAGnssCallback_V1_0::AGnssStatusIpV6& agps_status) {
JNIEnv* env = getJniEnv();
jbyteArray byteArray = nullptr;
@@ -1085,8 +1116,8 @@
return Void();
}
-Return<void> AGnssCallback::agnssStatusIpV4Cb(
- const IAGnssCallback::AGnssStatusIpV4& agps_status) {
+Return<void> AGnssCallback_V1_0::agnssStatusIpV4Cb(
+ const IAGnssCallback_V1_0::AGnssStatusIpV4& agps_status) {
JNIEnv* env = getJniEnv();
jbyteArray byteArray = nullptr;
@@ -1117,7 +1148,7 @@
return Void();
}
-jbyteArray AGnssCallback::convertToIpV4(uint32_t ip) {
+jbyteArray AGnssCallback_V1_0::convertToIpV4(uint32_t ip) {
if (INADDR_NONE == ip) {
return nullptr;
}
@@ -1137,6 +1168,23 @@
}
/*
+ * AGnssCallback_V2_0 implements callback methods required by the IAGnssCallback 2.0 interface.
+ */
+struct AGnssCallback_V2_0 : public IAGnssCallback_V2_0 {
+ // Methods from ::android::hardware::gps::V2_0::IAGnssCallback follow.
+ Return<void> agnssStatusCb(IAGnssCallback_V2_0::AGnssType type,
+ IAGnssCallback_V2_0::AGnssStatusValue status) override;
+};
+
+Return<void> AGnssCallback_V2_0::agnssStatusCb(IAGnssCallback_V2_0::AGnssType type,
+ IAGnssCallback_V2_0::AGnssStatusValue status) {
+ JNIEnv* env = getJniEnv();
+ env->CallVoidMethod(mCallbacksObj, method_reportAGpsStatus, type, status, nullptr);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ return Void();
+}
+
+/*
* AGnssRilCallback implements the callback methods required by the AGnssRil
* interface.
*/
@@ -1303,11 +1351,20 @@
}
}
- auto gnssAgnss = gnssHal->getExtensionAGnss();
- if (!gnssAgnss.isOk()) {
- ALOGD("Unable to get a handle to AGnss");
+ if (gnssHal_V2_0 != nullptr) {
+ auto agnss_V2_0 = gnssHal_V2_0->getExtensionAGnss_2_0();
+ if (!agnss_V2_0.isOk()) {
+ ALOGD("Unable to get a handle to AGnss_V2_0");
+ } else {
+ agnssIface_V2_0 = agnss_V2_0;
+ }
} else {
- agnssIface = gnssAgnss;
+ auto agnss_V1_0 = gnssHal->getExtensionAGnss();
+ if (!agnss_V1_0.isOk()) {
+ ALOGD("Unable to get a handle to AGnss");
+ } else {
+ agnssIface = agnss_V1_0;
+ }
}
auto gnssNavigationMessage = gnssHal->getExtensionGnssNavigationMessage();
@@ -1453,11 +1510,14 @@
}
}
- sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
- if (agnssIface != nullptr) {
+ if (agnssIface_V2_0 != nullptr) {
+ sp<IAGnssCallback_V2_0> aGnssCbIface = new AGnssCallback_V2_0();
+ agnssIface_V2_0->setCallback(aGnssCbIface);
+ } else if (agnssIface != nullptr) {
+ sp<IAGnssCallback_V1_0> aGnssCbIface = new AGnssCallback_V1_0();
agnssIface->setCallback(aGnssCbIface);
} else {
- ALOGI("Unable to Initialize AGnss interface\n");
+ ALOGI("Unable to initialize AGnss interface\n");
}
sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
@@ -1586,9 +1646,8 @@
return;
}
- const char *setid = env->GetStringUTFChars(setid_string, nullptr);
- agnssRilIface->setSetId((IAGnssRil_V1_0::SetIDType)type, setid);
- env->ReleaseStringUTFChars(setid_string, setid);
+ ScopedJniString jniSetId{env, setid_string};
+ agnssRilIface->setSetId((IAGnssRil_V1_0::SetIDType)type, jniSetId);
}
static jint android_location_GnssLocationProvider_read_nmea(JNIEnv* env, jobject /* obj */,
@@ -1676,68 +1735,126 @@
env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
}
-static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open(
- JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) {
- if (agnssIface == nullptr) {
- ALOGE("no AGPS interface in agps_data_conn_open");
- return;
- }
- if (apn == nullptr) {
- jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
- return;
- }
+struct AGnssDispatcher {
+ static void dataConnOpen(sp<IAGnss_V1_0> agnssIface, JNIEnv* env, jstring apn, jint apnIpType);
+ static void dataConnOpen(sp<IAGnss_V2_0> agnssIface_V2_0, JNIEnv* env, jlong networkHandle,
+ jstring apn, jint apnIpType);
- const char *apnStr = env->GetStringUTFChars(apn, nullptr);
+ template <class T>
+ static void dataConnClosed(sp<T> agnssIface);
- auto result = agnssIface->dataConnOpen(apnStr, static_cast<IAGnss::ApnIpType>(apnIpType));
+ template <class T>
+ static void dataConnFailed(sp<T> agnssIface);
+
+ template <class T, class U>
+ static void setServer(sp<T> agnssIface, JNIEnv* env, jint type, jstring hostname, jint port);
+
+private:
+ AGnssDispatcher() = delete;
+ AGnssDispatcher(const AGnssDispatcher&) = delete;
+ AGnssDispatcher& operator=(const AGnssDispatcher&) = delete;
+};
+
+void AGnssDispatcher::dataConnOpen(sp<IAGnss_V1_0> agnssIface, JNIEnv* env, jstring apn,
+ jint apnIpType) {
+ ScopedJniString jniApn{env, apn};
+ auto result = agnssIface->dataConnOpen(jniApn,
+ static_cast<IAGnss_V1_0::ApnIpType>(apnIpType));
if (!result.isOk() || !result){
ALOGE("%s: Failed to set APN and its IP type", __func__);
}
- env->ReleaseStringUTFChars(apn, apnStr);
}
-static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed(JNIEnv* /* env */,
- jobject /* obj */) {
- if (agnssIface == nullptr) {
- ALOGE("%s: AGPS interface not supported", __func__);
- return;
+void AGnssDispatcher::dataConnOpen(sp<IAGnss_V2_0> agnssIface_V2_0, JNIEnv* env,
+ jlong networkHandle, jstring apn, jint apnIpType) {
+ ScopedJniString jniApn{env, apn};
+ auto result = agnssIface_V2_0->dataConnOpen(static_cast<uint64_t>(networkHandle), jniApn,
+ static_cast<IAGnss_V2_0::ApnIpType>(apnIpType));
+ if (!result.isOk() || !result){
+ ALOGE("%s: Failed to set APN and its IP type", __func__);
}
+}
+template<class T>
+void AGnssDispatcher::dataConnClosed(sp<T> agnssIface) {
auto result = agnssIface->dataConnClosed();
if (!result.isOk() || !result) {
ALOGE("%s: Failed to close AGnss data connection", __func__);
}
}
-static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed(JNIEnv* /* env */,
- jobject /* obj */) {
- if (agnssIface == nullptr) {
- ALOGE("%s: AGPS interface not supported", __func__);
- return;
- }
-
+template<class T>
+void AGnssDispatcher::dataConnFailed(sp<T> agnssIface) {
auto result = agnssIface->dataConnFailed();
if (!result.isOk() || !result) {
ALOGE("%s: Failed to notify unavailability of AGnss data connection", __func__);
}
}
-static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
- jint type, jstring hostname, jint port) {
- if (agnssIface == nullptr) {
- ALOGE("no AGPS interface in set_agps_server");
- return;
- }
-
- const char *c_hostname = env->GetStringUTFChars(hostname, nullptr);
- auto result = agnssIface->setServer(static_cast<IAGnssCallback::AGnssType>(type),
- c_hostname,
- port);
+template <class T, class U>
+void AGnssDispatcher::setServer(sp<T> agnssIface, JNIEnv* env, jint type, jstring hostname,
+ jint port) {
+ ScopedJniString jniHostName{env, hostname};
+ auto result = agnssIface->setServer(static_cast<typename U::AGnssType>(type),
+ jniHostName, port);
if (!result.isOk() || !result) {
ALOGE("%s: Failed to set AGnss host name and port", __func__);
}
+}
- env->ReleaseStringUTFChars(hostname, c_hostname);
+static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open(
+ JNIEnv* env, jobject /* obj */, jlong networkHandle, jstring apn, jint apnIpType) {
+ if (apn == nullptr) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", nullptr);
+ return;
+ }
+
+ if (agnssIface_V2_0 != nullptr) {
+ AGnssDispatcher::dataConnOpen(agnssIface_V2_0, env, networkHandle, apn, apnIpType);
+ } else if (agnssIface != nullptr) {
+ AGnssDispatcher::dataConnOpen(agnssIface, env, apn, apnIpType);
+ } else {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
+}
+
+static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed(JNIEnv* /* env */,
+ jobject /* obj */) {
+ if (agnssIface_V2_0 != nullptr) {
+ AGnssDispatcher::dataConnClosed(agnssIface_V2_0);
+ } else if (agnssIface != nullptr) {
+ AGnssDispatcher::dataConnClosed(agnssIface);
+ } else {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
+}
+
+static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed(JNIEnv* /* env */,
+ jobject /* obj */) {
+ if (agnssIface_V2_0 != nullptr) {
+ AGnssDispatcher::dataConnFailed(agnssIface_V2_0);
+ } else if (agnssIface != nullptr) {
+ AGnssDispatcher::dataConnFailed(agnssIface);
+ } else {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
+}
+
+static void android_location_GnssLocationProvider_set_agps_server(JNIEnv* env, jobject /* obj */,
+ jint type, jstring hostname, jint port) {
+ if (agnssIface_V2_0 != nullptr) {
+ AGnssDispatcher::setServer<IAGnss_V2_0, IAGnssCallback_V2_0>(agnssIface_V2_0, env, type,
+ hostname, port);
+ } else if (agnssIface != nullptr) {
+ AGnssDispatcher::setServer<IAGnss_V1_0, IAGnssCallback_V1_0>(agnssIface, env, type,
+ hostname, port);
+ } else {
+ ALOGE("%s: AGPS interface not supported", __func__);
+ return;
+ }
}
static void android_location_GnssLocationProvider_send_ni_response(JNIEnv* /* env */,
@@ -1832,41 +1949,37 @@
jstring apn,
jlong networkHandle,
jshort capabilities) {
- if (agnssRilIface == nullptr) {
- ALOGE("AGnssRilInterface does not exist");
- return;
- }
-
- const char *c_apn = env->GetStringUTFChars(apn, nullptr);
- const android::hardware::hidl_string hidl_apn{c_apn};
if (agnssRilIface_V2_0 != nullptr) {
+ ScopedJniString jniApn{env, apn};
IAGnssRil_V2_0::NetworkAttributes networkAttributes = {
.networkHandle = static_cast<uint64_t>(networkHandle),
.isConnected = static_cast<bool>(connected),
.capabilities = static_cast<uint16_t>(capabilities),
- .apn = hidl_apn
+ .apn = jniApn
};
auto result = agnssRilIface_V2_0->updateNetworkState_2_0(networkAttributes);
if (!result.isOk() || !result) {
ALOGE("updateNetworkState_2_0 failed");
}
- } else {
+ } else if (agnssRilIface != nullptr) {
+ ScopedJniString jniApn{env, apn};
+ hidl_string hidlApn{jniApn};
auto result = agnssRilIface->updateNetworkState(connected,
static_cast<IAGnssRil_V1_0::NetworkType>(type), roaming);
if (!result.isOk() || !result) {
ALOGE("updateNetworkState failed");
}
- if (!hidl_apn.empty()) {
- result = agnssRilIface->updateNetworkAvailability(available, hidl_apn);
+ if (!hidlApn.empty()) {
+ result = agnssRilIface->updateNetworkAvailability(available, hidlApn);
if (!result.isOk() || !result) {
ALOGE("updateNetworkAvailability failed");
}
}
+ } else {
+ ALOGE("AGnssRilInterface does not exist");
}
-
- env->ReleaseStringUTFChars(apn, c_apn);
}
static jboolean android_location_GnssGeofenceProvider_is_geofence_supported(
@@ -2540,7 +2653,7 @@
"(ZIZZLjava/lang/String;JS)V",
reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_update_network_state)},
{"native_agps_data_conn_open",
- "(Ljava/lang/String;I)V",
+ "(JLjava/lang/String;I)V",
reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_agps_data_conn_open)},
{"native_agps_data_conn_closed",
"()V",