Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dffe0cee authored by Dante Russo's avatar Dante Russo Committed by Joe Huang
Browse files

Set the Network Specifier on Emergency SUPL

The sub ID of a SIM that the emergency call
was made on needs to be specified while
requesting a SUPL Emergency connection. This
is done by setting the Network Specifier in
the SUPL Emergency connection request so that
connection is made on the correct sub for a
device that can have more that one SIM.

Bug: 150115901
Change-Id: Id0d85125d1aa8c019ecb8f622b604a6eacec7380
CRs-fixed: 2563763
parent 7ed187c6
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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) {
+114 −1
Original line number Diff line number Diff line
@@ -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,