Merge "GNSS HAL must be notified correctly when networks disconnect"

This commit is contained in:
Anil Admal
2018-11-12 17:05:29 +00:00
committed by Android (Google) Code Review
3 changed files with 679 additions and 457 deletions

View File

@@ -24,7 +24,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.hardware.location.GeofenceHardware;
import android.hardware.location.GeofenceHardwareImpl;
import android.location.Criteria;
@@ -42,12 +41,6 @@ import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.location.LocationRequest;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.BatteryStats;
import android.os.Binder;
@@ -67,7 +60,6 @@ import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.provider.Settings;
import android.provider.Telephony.Carriers;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
@@ -92,8 +84,6 @@ import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -135,14 +125,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
private static final int GPS_STATUS_ENGINE_ON = 3;
private static final int GPS_STATUS_ENGINE_OFF = 4;
// these need to match AGnssStatusValue enum in IAGnssCallback.hal
/** 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 GnssLocationFlags enum in types.hal
private static final int LOCATION_INVALID = 0;
private static final int LOCATION_HAS_LAT_LONG = 1;
@@ -188,17 +170,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
private static final int AGPS_TYPE_SUPL = 1;
private static final int AGPS_TYPE_C2K = 2;
// these must match the ApnIpType enum in IAGnss.hal
private static final int APN_INVALID = 0;
private static final int APN_IPV4 = 1;
private static final int APN_IPV6 = 2;
private static final int APN_IPV4V6 = 3;
// 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;
// Handler messages
private static final int CHECK_LOCATION = 1;
private static final int ENABLE = 2;
@@ -254,9 +225,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
private static final long LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS = 1000;
// Default update duration in milliseconds for REQUEST_LOCATION.
private static final long LOCATION_UPDATE_DURATION_MILLIS = 10 * 1000;
// 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;
/** simpler wrapper for ProviderRequest + Worksource */
private static class GpsRequest {
@@ -427,12 +395,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
// Handler for processing events
private Handler mHandler;
/** It must be accessed only inside {@link #mHandler}. */
private int mAGpsDataConnectionState;
/** It must be accessed only inside {@link #mHandler}. */
private InetAddress mAGpsDataConnectionIpAddr;
private final ConnectivityManager mConnMgr;
private final GnssNetworkConnectivityHandler mNetworkConnectivityHandler;
private final GpsNetInitiatedHandler mNIHandler;
// Wakelocks
@@ -507,60 +470,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
return mGnssNavigationMessageProvider;
}
/**
* Callback used to listen for data connectivity changes.
*/
private final ConnectivityManager.NetworkCallback mNetworkConnectivityCallback =
new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
mNtpTimeHelper.onNetworkAvailable();
if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
if (mSupportsXtra) {
// Download only if supported, (prevents an unneccesary on-boot
// download)
xtraDownloadRequest();
}
}
// Always on, notify HAL so it can get data it needs
sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
}
@Override
public void onLost(Network network) {
sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
}
};
/**
* Callback used to listen for availability of a requested SUPL connection.
* It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
* manage the registration/un-registration lifetimes separate.
*/
private final ConnectivityManager.NetworkCallback mSuplConnectivityCallback =
new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
if (DEBUG) Log.d(TAG, "SUPL network connection available.");
// Specific to a change to a SUPL enabled network becoming ready
sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
}
@Override
public void onLost(Network network) {
Log.i(TAG, "SUPL network connection lost.");
releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
}
@Override
public void onUnavailable() {
Log.i(TAG, "SUPL network connection request timed out.");
// Could not setup the connection to the network in the specified time duration.
releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
}
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -793,7 +702,10 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
mConnMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(
context,
GnssLocationProvider.this::onNetworkAvailable,
looper);
// App ops service to keep track of who is accessing the GPS
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -843,8 +755,8 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
return isEnabled();
}
};
mGnssMetrics = new GnssMetrics(mBatteryStats);
mGnssMetrics = new GnssMetrics(mBatteryStats);
mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this);
mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
looper, this);
@@ -866,7 +778,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
return PROPERTIES;
}
/**
* Implements {@link InjectNtpTimeCallback#injectTime}
*/
@@ -875,124 +786,17 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
native_inject_time(time, timeReference, uncertainty);
}
private void handleUpdateNetworkState(Network network) {
// retrieve NetworkInfo for this UID
NetworkInfo info = mConnMgr.getNetworkInfo(network);
boolean networkAvailable = false;
boolean isConnected = false;
int type = ConnectivityManager.TYPE_NONE;
boolean isRoaming = false;
String apnName = null;
if (info != null) {
networkAvailable = info.isAvailable() && TelephonyManager.getDefault().getDataEnabled();
isConnected = info.isConnected();
type = info.getType();
isRoaming = info.isRoaming();
apnName = info.getExtraInfo();
}
if (DEBUG) {
String message = String.format(
"UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
agpsDataConnStateAsString(),
isConnected,
info,
mConnMgr.getNetworkCapabilities(network));
Log.d(TAG, message);
}
if (native_is_agps_ril_supported()) {
String defaultApn = getSelectedApn();
if (defaultApn == null) {
defaultApn = "dummy-apn";
/**
* Implements {@link GnssNetworkConnectivityHandler.GnssNetworkListener#onNetworkAvailable()}
*/
private void onNetworkAvailable() {
mNtpTimeHelper.onNetworkAvailable();
if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
if (mSupportsXtra) {
// Download only if supported, (prevents an unneccesary on-boot
// download)
xtraDownloadRequest();
}
native_update_network_state(
isConnected,
type,
isRoaming,
networkAvailable,
apnName,
defaultApn);
} else if (DEBUG) {
Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
}
if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
if (isConnected) {
if (apnName == null) {
// assign a dummy value in the case of C2K as otherwise we will have a runtime
// exception in the following call to native_agps_data_conn_open
apnName = "dummy-apn";
}
int apnIpType = getApnIpType(apnName);
setRouting();
if (DEBUG) {
String message = String.format(
"native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
apnName,
apnIpType);
Log.d(TAG, message);
}
native_agps_data_conn_open(apnName, apnIpType);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
} else {
handleReleaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
}
}
}
private void handleRequestSuplConnection(InetAddress address) {
if (DEBUG) {
String message = String.format(
"requestSuplConnection, state=%s, address=%s",
agpsDataConnStateAsString(),
address);
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);
NetworkRequest request = requestBuilder.build();
mConnMgr.requestNetwork(
request,
mSuplConnectivityCallback,
SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS);
}
private void handleReleaseSuplConnection(int agpsDataConnStatus) {
if (DEBUG) {
String message = String.format(
"releaseSuplConnection, state=%s, status=%s",
agpsDataConnStateAsString(),
agpsDataConnStatusAsString(agpsDataConnStatus));
Log.d(TAG, message);
}
if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
return;
}
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
switch (agpsDataConnStatus) {
case GPS_AGPS_DATA_CONN_FAILED:
native_agps_data_conn_failed();
break;
case GPS_RELEASE_AGPS_DATA_CONN:
native_agps_data_conn_closed();
break;
default:
Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
}
}
@@ -1091,7 +895,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
// already downloading data
return;
}
if (!isDataNetworkConnected()) {
if (!mNetworkConnectivityHandler.isDataNetworkConnected()) {
// try again when network is up
mDownloadXtraDataPending = STATE_PENDING_NETWORK;
return;
@@ -1822,41 +1626,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
* called from native code to update AGPS status
*/
private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
switch (status) {
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);
}
}
sendMessage(REQUEST_SUPL_CONNECTION, 0 /*arg*/, connectionIpAddress);
break;
case GPS_RELEASE_AGPS_DATA_CONN:
if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
break;
case GPS_AGPS_DATA_CONNECTED:
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
break;
case GPS_AGPS_DATA_CONN_DONE:
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
break;
case GPS_AGPS_DATA_CONN_FAILED:
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
break;
default:
if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
}
}
private void releaseSuplConnection(int connStatus) {
sendMessage(RELEASE_SUPL_CONNECTION, connStatus, null /*obj*/);
mNetworkConnectivityHandler.onReportAGpsStatus(type, status, ipaddr);
}
/**
@@ -2332,15 +2102,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
GpsRequest gpsRequest = (GpsRequest) msg.obj;
handleSetRequest(gpsRequest.request, gpsRequest.source);
break;
case UPDATE_NETWORK_STATE:
handleUpdateNetworkState((Network) msg.obj);
break;
case REQUEST_SUPL_CONNECTION:
handleRequestSuplConnection((InetAddress) msg.obj);
break;
case RELEASE_SUPL_CONNECTION:
handleReleaseSuplConnection(msg.arg1);
break;
case INJECT_NTP_TIME:
mNtpTimeHelper.retrieveAndInjectNtpTime();
break;
@@ -2426,14 +2187,7 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
intentFilter.addAction(SIM_STATE_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
// register for connectivity change events, this is equivalent to the deprecated way of
// registering for CONNECTIVITY_ACTION broadcasts
NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
networkRequestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
NetworkRequest networkRequest = networkRequestBuilder.build();
mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
mNetworkConnectivityHandler.registerNetworkCallbacks();
// listen for PASSIVE_PROVIDER updates
LocationManager locManager =
@@ -2491,160 +2245,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
}
}
private String getSelectedApn() {
Uri uri = Uri.parse("content://telephony/carriers/preferapn");
Cursor cursor = null;
try {
cursor = mContext.getContentResolver().query(
uri,
new String[]{"apn"},
null /* selection */,
null /* selectionArgs */,
Carriers.DEFAULT_SORT_ORDER);
if (cursor != null && cursor.moveToFirst()) {
return cursor.getString(0);
} else {
Log.e(TAG, "No APN found to select.");
}
} catch (Exception e) {
Log.e(TAG, "Error encountered on selecting the APN.", e);
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
private int getApnIpType(String apn) {
ensureInHandlerThread();
if (apn == null) {
return APN_INVALID;
}
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
// Carrier configuration may override framework roaming state, we need to use the actual
// modem roaming state instead of the framework roaming state.
boolean isDataRoamingFromRegistration = phone.getServiceState().
getDataRoamingFromRegistration();
String projection = isDataRoamingFromRegistration ? Carriers.ROAMING_PROTOCOL :
Carriers.PROTOCOL;
String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
Cursor cursor = null;
try {
cursor = mContext.getContentResolver().query(
Carriers.CONTENT_URI,
new String[]{projection},
selection,
null,
Carriers.DEFAULT_SORT_ORDER);
if (null != cursor && cursor.moveToFirst()) {
return translateToApnIpType(cursor.getString(0), apn);
} else {
Log.e(TAG, "No entry found in query for APN: " + apn);
}
} catch (Exception e) {
Log.e(TAG, "Error encountered on APN query for: " + apn, e);
} finally {
if (cursor != null) {
cursor.close();
}
}
return APN_INVALID;
}
private int translateToApnIpType(String ipProtocol, String apn) {
if ("IP".equals(ipProtocol)) {
return APN_IPV4;
}
if ("IPV6".equals(ipProtocol)) {
return APN_IPV6;
}
if ("IPV4V6".equals(ipProtocol)) {
return APN_IPV4V6;
}
// we hit the default case so the ipProtocol is not recognized
String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
Log.e(TAG, message);
return APN_INVALID;
}
private void setRouting() {
if (mAGpsDataConnectionIpAddr == null) {
return;
}
// TODO: replace the use of this deprecated API
boolean result = mConnMgr.requestRouteToHostAddress(
ConnectivityManager.TYPE_MOBILE_SUPL,
mAGpsDataConnectionIpAddr);
if (!result) {
Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
} else if (DEBUG) {
Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
}
}
/**
* @return {@code true} if there is a data network available for outgoing connections,
* {@code false} otherwise.
*/
private boolean isDataNetworkConnected() {
NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
/**
* Ensures the calling function is running in the thread associated with {@link #mHandler}.
*/
private void ensureInHandlerThread() {
if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
return;
}
throw new RuntimeException("This method must run on the Handler thread.");
}
/**
* @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
*/
private String agpsDataConnStateAsString() {
switch (mAGpsDataConnectionState) {
case AGPS_DATA_CONNECTION_CLOSED:
return "CLOSED";
case AGPS_DATA_CONNECTION_OPEN:
return "OPEN";
case AGPS_DATA_CONNECTION_OPENING:
return "OPENING";
default:
return "<Unknown>";
}
}
/**
* @return A string representing the given GPS_AGPS_DATA status.
*/
private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
switch (agpsDataConnStatus) {
case GPS_AGPS_DATA_CONNECTED:
return "CONNECTED";
case GPS_AGPS_DATA_CONN_DONE:
return "DONE";
case GPS_AGPS_DATA_CONN_FAILED:
return "FAILED";
case GPS_RELEASE_AGPS_DATA_CONN:
return "RELEASE";
case GPS_REQUEST_AGPS_DATA_CONN:
return "REQUEST";
default:
return "<Unknown>";
}
}
/**
* @return A string representing the given message ID.
*/
@@ -2654,12 +2254,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
return "ENABLE";
case SET_REQUEST:
return "SET_REQUEST";
case UPDATE_NETWORK_STATE:
return "UPDATE_NETWORK_STATE";
case REQUEST_SUPL_CONNECTION:
return "REQUEST_SUPL_CONNECTION";
case RELEASE_SUPL_CONNECTION:
return "RELEASE_SUPL_CONNECTION";
case INJECT_NTP_TIME:
return "INJECT_NTP_TIME";
case REQUEST_LOCATION:
@@ -2683,7 +2277,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
}
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
StringBuilder s = new StringBuilder();
@@ -2723,8 +2316,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
private static native boolean native_is_supported();
private static native boolean native_is_agps_ril_supported();
private static native boolean native_is_gnss_configuration_supported();
private static native void native_init_once();
@@ -2770,12 +2361,6 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
private native String native_get_internal_state();
// AGPS Support
private native void native_agps_data_conn_open(String apn, int apnIpType);
private native void native_agps_data_conn_closed();
private native void native_agps_data_conn_failed();
private native void native_agps_ni_message(byte[] msg, int length);
private native void native_set_agps_server(int type, String hostname, int port);
@@ -2783,15 +2368,12 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
// Network-initiated (NI) Support
private native void native_send_ni_response(int notificationId, int userResponse);
// AGPS ril suport
// AGPS ril support
private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
int lac, int cid);
private native void native_agps_set_id(int type, String setid);
private native void native_update_network_state(boolean connected, int type,
boolean roaming, boolean available, String extraInfo, String defaultAPN);
// GNSS Configuration
private static native boolean native_set_supl_version(int version);

View File

@@ -0,0 +1,631 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.location;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.provider.Telephony.Carriers;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* Handles network connection requests and network state change updates for AGPS data download.
*/
class GnssNetworkConnectivityHandler {
static final String TAG = "GnssNetworkConnectivityHandler";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
// 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;
// these need to match AGnssStatusValue enum in IAGnssCallback.hal
/** 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 must match the ApnIpType enum in IAGnss.hal
private static final int APN_INVALID = 0;
private static final int APN_IPV4 = 1;
private static final int APN_IPV6 = 2;
private static final int APN_IPV4V6 = 3;
// 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;
private static final int HASH_MAP_INITIAL_CAPACITY_TO_TRACK_CONNECTED_NETWORKS = 5;
// keeps track of networks and their state as notified by the network request callbacks.
// Limit initial capacity to 5 as the number of connected networks will likely be small.
private ConcurrentHashMap<Network, NetworkAttributes> mAvailableNetworkAttributes =
new ConcurrentHashMap<>(HASH_MAP_INITIAL_CAPACITY_TO_TRACK_CONNECTED_NETWORKS);
private final ConnectivityManager mConnMgr;
private final Handler mHandler;
private final GnssNetworkListener mGnssNetworkListener;
private int mAGpsDataConnectionState;
private InetAddress mAGpsDataConnectionIpAddr;
private final Context mContext;
// Wakelocks
private static final String WAKELOCK_KEY = "GnssNetworkConnectivityHandler";
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
private final PowerManager.WakeLock mWakeLock;
/**
* Network attributes needed when updating HAL about network connectivity status changes.
*/
private static class NetworkAttributes {
NetworkCapabilities mCapabilities;
String mApn;
int mType = ConnectivityManager.TYPE_NONE;
/**
* Returns true if the capabilities that we pass on to HAL change between {@curCapabilities}
* and {@code newCapabilities}.
*/
static boolean hasCapabilitiesChanged(NetworkCapabilities curCapabilities,
NetworkCapabilities newCapabilities) {
if (curCapabilities == null || newCapabilities == null) {
return true;
}
return curCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
!= newCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
}
}
/**
* Callback used to listen for data connectivity changes.
*/
private ConnectivityManager.NetworkCallback mNetworkConnectivityCallback;
/**
* Callback used to listen for availability of a requested SUPL connection.
* It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
* manage the registration/un-registration lifetimes separately.
*/
private ConnectivityManager.NetworkCallback mSuplConnectivityCallback;
/**
* Interface to listen for network availability changes.
*/
public interface GnssNetworkListener {
void onNetworkAvailable();
}
GnssNetworkConnectivityHandler(Context context,
GnssNetworkListener gnssNetworkListener,
Looper looper) {
mContext = context;
mGnssNetworkListener = gnssNetworkListener;
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
mHandler = new Handler(looper);
mConnMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mSuplConnectivityCallback = createSuplConnectivityCallback();
}
public void registerNetworkCallbacks() {
mAvailableNetworkAttributes.clear();
if (mNetworkConnectivityCallback != null) {
mConnMgr.unregisterNetworkCallback(mNetworkConnectivityCallback);
}
// register for connectivity change events.
NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
networkRequestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
NetworkRequest networkRequest = networkRequestBuilder.build();
mNetworkConnectivityCallback = createNetworkConnectivityCallback();
mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
}
/**
* @return {@code true} if there is a data network available for outgoing connections,
* {@code false} otherwise.
*/
public boolean isDataNetworkConnected() {
NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
/**
* called from native code to update AGPS status
*/
public void onReportAGpsStatus(int type, int status, byte[] ipaddr) {
switch (status) {
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);
break;
case GPS_RELEASE_AGPS_DATA_CONN:
if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
break;
case GPS_AGPS_DATA_CONNECTED:
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
break;
case GPS_AGPS_DATA_CONN_DONE:
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
break;
case GPS_AGPS_DATA_CONN_FAILED:
if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
break;
default:
if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
}
}
private ConnectivityManager.NetworkCallback createNetworkConnectivityCallback() {
return new ConnectivityManager.NetworkCallback() {
// Used to filter out network capabilities changes that we are not interested in.
// NOTE: Not using a ConcurrentHashMap and also not using locking around updates
// and access to the map object because it is all done inside the same
// handler thread invoking the callback methods.
private HashMap<Network, NetworkCapabilities>
mAvailableNetworkCapabilities = new HashMap<>(
HASH_MAP_INITIAL_CAPACITY_TO_TRACK_CONNECTED_NETWORKS);
@Override
public void onCapabilitiesChanged(Network network,
NetworkCapabilities capabilities) {
// This callback is invoked for any change in the network capabilities including
// initial availability, and changes while still available. Only process if the
// capabilities that we pass on to HAL change.
if (!NetworkAttributes.hasCapabilitiesChanged(
mAvailableNetworkCapabilities.get(network), capabilities)) {
if (VERBOSE) {
Log.v(TAG, "Relevant network capabilities unchanged. Capabilities: "
+ capabilities);
}
return;
}
mAvailableNetworkCapabilities.put(network, capabilities);
if (DEBUG) {
Log.d(TAG, "Network connected/capabilities updated. Available networks count: "
+ mAvailableNetworkCapabilities.size());
}
mGnssNetworkListener.onNetworkAvailable();
// Always on, notify HAL so it can get data it needs
updateNetworkState(network, true, capabilities);
}
@Override
public void onLost(Network network) {
if (mAvailableNetworkCapabilities.remove(network) == null) {
Log.w(TAG, "Incorrectly received network callback onLost() before"
+ " onCapabilitiesChanged() for network: " + network);
return;
}
Log.i(TAG, "Network connection lost. Available networks count: "
+ mAvailableNetworkCapabilities.size());
updateNetworkState(network, false, null);
}
};
}
private ConnectivityManager.NetworkCallback createSuplConnectivityCallback() {
return new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
if (DEBUG) Log.d(TAG, "SUPL network connection available.");
// Specific to a change to a SUPL enabled network becoming ready
suplConnectionAvailable(network);
}
@Override
public void onLost(Network network) {
Log.i(TAG, "SUPL network connection lost.");
releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
}
@Override
public void onUnavailable() {
Log.i(TAG, "SUPL network connection request timed out.");
// Could not setup the connection to the network in the specified time duration.
releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
}
};
}
private void requestSuplConnection(InetAddress inetAddress) {
postEvent(() -> handleRequestSuplConnection(inetAddress));
}
private void suplConnectionAvailable(Network network) {
postEvent(() -> handleSuplConnectionAvailable(network));
}
private void releaseSuplConnection(int connStatus) {
postEvent(() -> handleReleaseSuplConnection(connStatus));
}
private void updateNetworkState(Network network, boolean isConnected,
NetworkCapabilities capabilities) {
postEvent(() -> handleUpdateNetworkState(network, isConnected, capabilities));
}
private void postEvent(Runnable event) {
// hold a wake lock until this message is delivered
// note that this assumes the message will not be removed from the queue before
// it is handled (otherwise the wake lock would be leaked).
mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
if (!mHandler.post(runEventAndReleaseWakeLock(event))) {
mWakeLock.release();
}
}
private Runnable runEventAndReleaseWakeLock(Runnable event) {
return () -> {
try {
event.run();
} finally {
mWakeLock.release();
}
};
}
private void handleUpdateNetworkState(Network network, boolean isConnected,
NetworkCapabilities capabilities) {
boolean networkAvailable = isConnected && TelephonyManager.getDefault().getDataEnabled();
NetworkAttributes networkAttributes = updateTrackedNetworksState(isConnected, network,
capabilities);
String apnName = networkAttributes.mApn;
int type = networkAttributes.mType;
// When isConnected is false, capabilities argument is null. So, use last received
// capabilities.
capabilities = networkAttributes.mCapabilities;
boolean isRoaming = !capabilities.hasTransport(
NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
Log.i(TAG, String.format(
"updateNetworkState, state=%s, connected=%s, network=%s, capabilities=%s"
+ ", availableNetworkCount: %d",
agpsDataConnStateAsString(),
isConnected,
network,
capabilities,
mAvailableNetworkAttributes.size()));
if (native_is_agps_ril_supported()) {
String defaultApn = getSelectedApn();
if (defaultApn == null) {
defaultApn = "dummy-apn";
}
native_update_network_state(
isConnected,
type,
isRoaming,
networkAvailable,
apnName,
defaultApn);
} else if (DEBUG) {
Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
}
}
private NetworkAttributes updateTrackedNetworksState(boolean isConnected, Network network,
NetworkCapabilities capabilities) {
if (!isConnected) {
// Connection lost event. So, remove it from tracked networks.
return mAvailableNetworkAttributes.remove(network);
}
NetworkAttributes networkAttributes = mAvailableNetworkAttributes.get(network);
if (networkAttributes != null) {
// Capabilities updated event for the connected network.
networkAttributes.mCapabilities = capabilities;
return networkAttributes;
}
// Initial capabilities event (equivalent to connection available event).
networkAttributes = new NetworkAttributes();
networkAttributes.mCapabilities = capabilities;
// TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
// not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
NetworkInfo info = mConnMgr.getNetworkInfo(network);
if (info != null) {
networkAttributes.mApn = info.getExtraInfo();
networkAttributes.mType = info.getType();
}
// Start tracking this network for connection status updates.
mAvailableNetworkAttributes.put(network, networkAttributes);
return networkAttributes;
}
private void handleSuplConnectionAvailable(Network network) {
// TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
// not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
NetworkInfo info = mConnMgr.getNetworkInfo(network);
String apnName = null;
if (info != null) {
apnName = info.getExtraInfo();
}
if (DEBUG) {
String message = String.format(
"handleSuplConnectionAvailable: state=%s, suplNetwork=%s, info=%s",
agpsDataConnStateAsString(),
network,
info);
Log.d(TAG, message);
}
if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
if (apnName == null) {
// assign a dummy value in the case of C2K as otherwise we will have a runtime
// exception in the following call to native_agps_data_conn_open
apnName = "dummy-apn";
}
int apnIpType = getApnIpType(apnName);
setRouting();
if (DEBUG) {
String message = String.format(
"native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
apnName,
apnIpType);
Log.d(TAG, message);
}
native_agps_data_conn_open(apnName, apnIpType);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
}
}
private void handleRequestSuplConnection(InetAddress address) {
if (DEBUG) {
String message = String.format(
"requestSuplConnection, state=%s, address=%s",
agpsDataConnStateAsString(),
address);
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);
NetworkRequest request = requestBuilder.build();
mConnMgr.requestNetwork(
request,
mSuplConnectivityCallback,
SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS);
}
private void handleReleaseSuplConnection(int agpsDataConnStatus) {
if (DEBUG) {
String message = String.format(
"releaseSuplConnection, state=%s, status=%s",
agpsDataConnStateAsString(),
agpsDataConnStatusAsString(agpsDataConnStatus));
Log.d(TAG, message);
}
if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
return;
}
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
switch (agpsDataConnStatus) {
case GPS_AGPS_DATA_CONN_FAILED:
native_agps_data_conn_failed();
break;
case GPS_RELEASE_AGPS_DATA_CONN:
native_agps_data_conn_closed();
break;
default:
Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
}
}
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);
if (!result) {
Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
} else if (DEBUG) {
Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
}
}
/**
* Ensures the calling function is running in the thread associated with {@link #mHandler}.
*/
private void ensureInHandlerThread() {
if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
return;
}
throw new IllegalStateException("This method must run on the Handler thread.");
}
/**
* @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
*/
private String agpsDataConnStateAsString() {
switch (mAGpsDataConnectionState) {
case AGPS_DATA_CONNECTION_CLOSED:
return "CLOSED";
case AGPS_DATA_CONNECTION_OPEN:
return "OPEN";
case AGPS_DATA_CONNECTION_OPENING:
return "OPENING";
default:
return "<Unknown>";
}
}
/**
* @return A string representing the given GPS_AGPS_DATA status.
*/
private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
switch (agpsDataConnStatus) {
case GPS_AGPS_DATA_CONNECTED:
return "CONNECTED";
case GPS_AGPS_DATA_CONN_DONE:
return "DONE";
case GPS_AGPS_DATA_CONN_FAILED:
return "FAILED";
case GPS_RELEASE_AGPS_DATA_CONN:
return "RELEASE";
case GPS_REQUEST_AGPS_DATA_CONN:
return "REQUEST";
default:
return "<Unknown>";
}
}
private int getApnIpType(String apn) {
ensureInHandlerThread();
if (apn == null) {
return APN_INVALID;
}
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
// Carrier configuration may override framework roaming state, we need to use the actual
// modem roaming state instead of the framework roaming state.
boolean isDataRoamingFromRegistration = phone.getServiceState()
.getDataRoamingFromRegistration();
String projection = isDataRoamingFromRegistration ? Carriers.ROAMING_PROTOCOL :
Carriers.PROTOCOL;
String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
try (Cursor cursor = mContext.getContentResolver().query(
Carriers.CONTENT_URI,
new String[]{projection},
selection,
null,
Carriers.DEFAULT_SORT_ORDER)) {
if (null != cursor && cursor.moveToFirst()) {
return translateToApnIpType(cursor.getString(0), apn);
} else {
Log.e(TAG, "No entry found in query for APN: " + apn);
}
} catch (Exception e) {
Log.e(TAG, "Error encountered on APN query for: " + apn, e);
}
return APN_INVALID;
}
private int translateToApnIpType(String ipProtocol, String apn) {
if ("IP".equals(ipProtocol)) {
return APN_IPV4;
}
if ("IPV6".equals(ipProtocol)) {
return APN_IPV6;
}
if ("IPV4V6".equals(ipProtocol)) {
return APN_IPV4V6;
}
// we hit the default case so the ipProtocol is not recognized
String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
Log.e(TAG, message);
return APN_INVALID;
}
private String getSelectedApn() {
Uri uri = Uri.parse("content://telephony/carriers/preferapn");
try (Cursor cursor = mContext.getContentResolver().query(
uri,
new String[]{"apn"},
null /* selection */,
null /* selectionArgs */,
Carriers.DEFAULT_SORT_ORDER)) {
if (cursor != null && cursor.moveToFirst()) {
return cursor.getString(0);
} else {
Log.e(TAG, "No APN found to select.");
}
} catch (Exception e) {
Log.e(TAG, "Error encountered on selecting the APN.", e);
}
return null;
}
// AGPS support
private native void native_agps_data_conn_open(String apn, int apnIpType);
private native void native_agps_data_conn_closed();
private native void native_agps_data_conn_failed();
// AGPS ril support
private static native boolean native_is_agps_ril_supported();
private native void native_update_network_state(boolean connected, int type,
boolean roaming, boolean available, String extraInfo, String defaultAPN);
}

View File

@@ -1299,7 +1299,7 @@ static jboolean android_location_GnssLocationProvider_is_supported(
return (gnssHal != nullptr) ? JNI_TRUE : JNI_FALSE;
}
static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
static jboolean android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported(
JNIEnv* /* env */, jclass /* clazz */) {
return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE;
}
@@ -1571,7 +1571,7 @@ static void android_location_GnssLocationProvider_inject_xtra_data(JNIEnv* env,
env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
}
static void android_location_GnssLocationProvider_agps_data_conn_open(
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");
@@ -1591,7 +1591,7 @@ static void android_location_GnssLocationProvider_agps_data_conn_open(
env->ReleaseStringUTFChars(apn, apnStr);
}
static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed(JNIEnv* /* env */,
jobject /* obj */) {
if (agnssIface == nullptr) {
ALOGE("%s: AGPS interface not supported", __func__);
@@ -1604,7 +1604,7 @@ static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv*
}
}
static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed(JNIEnv* /* env */,
jobject /* obj */) {
if (agnssIface == nullptr) {
ALOGE("%s: AGPS interface not supported", __func__);
@@ -1718,7 +1718,7 @@ static jstring android_location_GnssLocationProvider_get_internal_state(JNIEnv*
return result;
}
static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env,
static void android_location_GnssNetworkConnectivityHandler_update_network_state(JNIEnv* env,
jobject /* obj */,
jboolean connected,
jint type,
@@ -2118,8 +2118,6 @@ static const JNINativeMethod sMethods[] = {
android_location_GnssLocationProvider_class_init_native)},
{"native_is_supported", "()Z", reinterpret_cast<void *>(
android_location_GnssLocationProvider_is_supported)},
{"native_is_agps_ril_supported", "()Z",
reinterpret_cast<void *>(android_location_GnssLocationProvider_is_agps_ril_supported)},
{"native_is_gnss_configuration_supported", "()Z",
reinterpret_cast<void *>(
android_location_gpsLocationProvider_is_gnss_configuration_supported)},
@@ -2151,15 +2149,6 @@ static const JNINativeMethod sMethods[] = {
{"native_inject_xtra_data",
"([BI)V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_xtra_data)},
{"native_agps_data_conn_open",
"(Ljava/lang/String;I)V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_open)},
{"native_agps_data_conn_closed",
"()V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_closed)},
{"native_agps_data_conn_failed",
"()V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_failed)},
{"native_agps_set_id",
"(ILjava/lang/String;)V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_set_id)},
@@ -2176,9 +2165,6 @@ static const JNINativeMethod sMethods[] = {
{"native_get_internal_state",
"()Ljava/lang/String;",
reinterpret_cast<void *>(android_location_GnssLocationProvider_get_internal_state)},
{"native_update_network_state",
"(ZIZZLjava/lang/String;Ljava/lang/String;)V",
reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
{"native_set_supl_es",
"(I)Z",
reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_es)},
@@ -2278,6 +2264,24 @@ static const JNINativeMethod sNavigationMessageMethods[] = {
android_location_GnssNavigationMessageProvider_stop_navigation_message_collection)},
};
static const JNINativeMethod sNetworkConnectivityMethods[] = {
/* name, signature, funcPtr */
{"native_is_agps_ril_supported", "()Z",
reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported)},
{"native_update_network_state",
"(ZIZZLjava/lang/String;Ljava/lang/String;)V",
reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_update_network_state)},
{"native_agps_data_conn_open",
"(Ljava/lang/String;I)V",
reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_agps_data_conn_open)},
{"native_agps_data_conn_closed",
"()V",
reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed)},
{"native_agps_data_conn_failed",
"()V",
reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed)},
};
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
jniRegisterNativeMethods(
env,
@@ -2299,6 +2303,11 @@ int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
"com/android/server/location/GnssNavigationMessageProvider",
sNavigationMessageMethods,
NELEM(sNavigationMessageMethods));
jniRegisterNativeMethods(
env,
"com/android/server/location/GnssNetworkConnectivityHandler",
sNetworkConnectivityMethods,
NELEM(sNetworkConnectivityMethods));
return jniRegisterNativeMethods(
env,
"com/android/server/location/GnssLocationProvider",