diff options
| -rw-r--r-- | services/core/java/com/android/server/location/GnssLocationProvider.java | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java | 115 |
2 files changed, 117 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java index 58e332ab6d1d..c1fbcfba864a 100644 --- a/services/core/java/com/android/server/location/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/GnssLocationProvider.java @@ -653,9 +653,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0); mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0); - mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context, - GnssLocationProvider.this::onNetworkAvailable, mLooper); - // App ops service to keep track of who is accessing the GPS mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -677,6 +674,9 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mNIHandler = new GpsNetInitiatedHandler(context, mNetInitiatedListener, mSuplEsEnabled); + mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context, + GnssLocationProvider.this::onNetworkAvailable, mLooper, mNIHandler); + sendMessage(INITIALIZE_HANDLER, 0, null); mGnssStatusListenerHelper = new GnssStatusListenerHelper(mContext, mHandler) { diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java index 9ee9dcba9a81..5d6474bdbccc 100644 --- a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java +++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java @@ -29,12 +29,22 @@ import android.os.PowerManager; import android.provider.Telephony.Carriers; import android.telephony.ServiceState; import android.telephony.TelephonyManager; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.PreciseCallState; +import android.telephony.PhoneStateListener; import android.util.Log; +import com.android.internal.location.GpsNetInitiatedHandler; + import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; +import java.util.Map; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Iterator; /** * Handles network connection requests and network state change updates for AGPS data download. @@ -86,6 +96,9 @@ class GnssNetworkConnectivityHandler { private HashMap<Network, NetworkAttributes> mAvailableNetworkAttributes = new HashMap<>(HASH_MAP_INITIAL_CAPACITY_TO_TRACK_CONNECTED_NETWORKS); + // Phone State Listeners to track all the active sub IDs + private HashMap<Integer, SubIdPhoneStateListener> mPhoneStateListeners; + private final ConnectivityManager mConnMgr; private final Handler mHandler; @@ -94,6 +107,9 @@ class GnssNetworkConnectivityHandler { private int mAGpsDataConnectionState; private InetAddress mAGpsDataConnectionIpAddr; private int mAGpsType; + private int mActiveSubId = -1; + private final GpsNetInitiatedHandler mNiHandler; + private final Context mContext; @@ -166,18 +182,109 @@ class GnssNetworkConnectivityHandler { GnssNetworkConnectivityHandler(Context context, GnssNetworkListener gnssNetworkListener, - Looper looper) { + Looper looper, + GpsNetInitiatedHandler niHandler) { mContext = context; mGnssNetworkListener = gnssNetworkListener; + SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class); + if (subManager != null) { + subManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener); + } + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); mHandler = new Handler(looper); + mNiHandler = niHandler; mConnMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); mSuplConnectivityCallback = createSuplConnectivityCallback(); } + /** + * SubId Phone State Listener is used cache the last active Sub ID when a call is made, + * which will be used during an emergency call to set the Network Specifier to the particular + * sub when an emergency supl connection is requested + */ + private final class SubIdPhoneStateListener extends PhoneStateListener { + private Integer mSubId; + SubIdPhoneStateListener(Integer subId) { + mSubId = subId; + } + @Override + public void onPreciseCallStateChanged(PreciseCallState state) { + if (state.PRECISE_CALL_STATE_ACTIVE == state.getForegroundCallState()) { + mActiveSubId = mSubId; + if (DEBUG) Log.d(TAG, "mActiveSubId: " + mActiveSubId); + } + } + }; + + /** + * Subscription Changed Listener is used to get all active subscriptions and create a + * Phone State Listener for each Sub ID that we find in the active subscription list + */ + private final SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangeListener + = new SubscriptionManager.OnSubscriptionsChangedListener() { + @Override + public void onSubscriptionsChanged() { + if (mPhoneStateListeners == null) { + // Capacity=2 Load-Factor=1.0, as typically no more than 2 SIMs + mPhoneStateListeners = new HashMap<Integer, SubIdPhoneStateListener>(2,1); + } + SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class); + TelephonyManager telManager = mContext.getSystemService(TelephonyManager.class); + if (subManager != null && telManager != null) { + List<SubscriptionInfo> subscriptionInfoList = + subManager.getActiveSubscriptionInfoList(); + HashSet<Integer> activeSubIds = new HashSet<Integer>(); + if (subscriptionInfoList != null) { + if (DEBUG) Log.d(TAG, "Active Sub List size: " + subscriptionInfoList.size()); + // populate phone state listeners with all new active subs + for (SubscriptionInfo subInfo : subscriptionInfoList) { + activeSubIds.add(subInfo.getSubscriptionId()); + if (!mPhoneStateListeners.containsKey(subInfo.getSubscriptionId())) { + TelephonyManager subIdTelManager = + telManager.createForSubscriptionId(subInfo.getSubscriptionId()); + if (subIdTelManager != null) { + if (DEBUG) Log.d(TAG, "Listener sub" + subInfo.getSubscriptionId()); + SubIdPhoneStateListener subIdPhoneStateListener = + new SubIdPhoneStateListener(subInfo.getSubscriptionId()); + mPhoneStateListeners.put(subInfo.getSubscriptionId(), + subIdPhoneStateListener); + subIdTelManager.listen(subIdPhoneStateListener, + PhoneStateListener.LISTEN_PRECISE_CALL_STATE); + } + } + } + } + // clean up phone state listeners than no longer have active subs + Iterator<Map.Entry<Integer, SubIdPhoneStateListener> > iterator = + mPhoneStateListeners.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry<Integer, SubIdPhoneStateListener> element = iterator.next(); + if (!activeSubIds.contains(element.getKey())) { + TelephonyManager subIdTelManager = + telManager.createForSubscriptionId(element.getKey()); + if (subIdTelManager != null) { + if (DEBUG) Log.d(TAG, "unregister listener sub " + element.getKey()); + subIdTelManager.listen(element.getValue(), + PhoneStateListener.LISTEN_NONE); + // removes the element from mPhoneStateListeners + iterator.remove(); + } else { + Log.e(TAG, "Telephony Manager for Sub " + element.getKey() + " null"); + } + } + } + // clean up cached active phone call sub if it is no longer an active sub + if (!activeSubIds.contains(mActiveSubId)) { + mActiveSubId = -1; + } + } + } + }; + void registerNetworkCallbacks() { // register for connectivity change events. NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder(); @@ -467,6 +574,12 @@ class GnssNetworkConnectivityHandler { NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder(); networkRequestBuilder.addCapability(getNetworkCapability(mAGpsType)); networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); + // During an emergency call, and when we have cached the Active Sub Id, we set the + // Network Specifier so that the network request goes to the correct Sub Id + if (mNiHandler.getInEmergency() && mActiveSubId >= 0) { + if (DEBUG) Log.d(TAG, "Adding Network Specifier: " + Integer.toString(mActiveSubId)); + networkRequestBuilder.setNetworkSpecifier(Integer.toString(mActiveSubId)); + } NetworkRequest networkRequest = networkRequestBuilder.build(); mConnMgr.requestNetwork( networkRequest, |