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

Commit 71bf33a0 authored by Robert Greenwalt's avatar Robert Greenwalt
Browse files

Rewrite startUsingNetworkFeature for new API

bug:14993207
Change-Id: I041a80faa07bf3094af13a6c606f3b15aa03f789
parent bd67759a
Loading
Loading
Loading
Loading
+204 −15
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.util.ArrayMap;
import android.util.Log;

import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Protocol;

import java.net.InetAddress;
@@ -807,11 +808,34 @@ public class ConnectivityManager {
     * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
     */
    public int startUsingNetworkFeature(int networkType, String feature) {
        try {
            return mService.startUsingNetworkFeature(networkType, feature,
                    new Binder());
        } catch (RemoteException e) {
            return -1;
        NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
        if (netCap == null) {
            Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " +
                    feature);
            return PhoneConstants.APN_REQUEST_FAILED;
        }

        NetworkRequest request = null;
        synchronized (sLegacyRequests) {
            LegacyRequest l = sLegacyRequests.get(netCap);
            if (l != null) {
                Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest);
                renewRequestLocked(l);
                if (l.currentNetwork != null) {
                    return PhoneConstants.APN_ALREADY_ACTIVE;
                } else {
                    return PhoneConstants.APN_REQUEST_STARTED;
                }
            }

            request = requestNetworkForFeatureLocked(netCap);
        }
        if (request != null) {
            Log.d(TAG, "starting startUsingNeworkFeature for request " + request);
            return PhoneConstants.APN_REQUEST_STARTED;
        } else {
            Log.d(TAG, " request Failed");
            return PhoneConstants.APN_REQUEST_FAILED;
        }
    }

@@ -831,11 +855,169 @@ public class ConnectivityManager {
     * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
     */
    public int stopUsingNetworkFeature(int networkType, String feature) {
        try {
            return mService.stopUsingNetworkFeature(networkType, feature);
        } catch (RemoteException e) {
        NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
        if (netCap == null) {
            Log.d(TAG, "Can't satisfy stopUsingNetworkFeature for " + networkType + ", " +
                    feature);
            return -1;
        }

        NetworkRequest request = removeRequestForFeature(netCap);
        if (request != null) {
            Log.d(TAG, "stopUsingNetworkFeature for " + networkType + ", " + feature);
            releaseNetworkRequest(request);
        }
        return 1;
    }

    private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) {
        if (networkType == TYPE_MOBILE) {
            int cap = -1;
            if ("enableMMS".equals(feature)) {
                cap = NetworkCapabilities.NET_CAPABILITY_MMS;
            } else if ("enableSUPL".equals(feature)) {
                cap = NetworkCapabilities.NET_CAPABILITY_SUPL;
            } else if ("enableDUN".equals(feature) || "enableDUNAlways".equals(feature)) {
                cap = NetworkCapabilities.NET_CAPABILITY_DUN;
            } else if ("enableHIPRI".equals(feature)) {
                cap = NetworkCapabilities.NET_CAPABILITY_INTERNET;
            } else if ("enableFOTA".equals(feature)) {
                cap = NetworkCapabilities.NET_CAPABILITY_FOTA;
            } else if ("enableIMS".equals(feature)) {
                cap = NetworkCapabilities.NET_CAPABILITY_IMS;
            } else if ("enableCBS".equals(feature)) {
                cap = NetworkCapabilities.NET_CAPABILITY_CBS;
            } else {
                return null;
            }
            NetworkCapabilities netCap = new NetworkCapabilities();
            netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
            netCap.addNetworkCapability(cap);
            return netCap;
        } else if (networkType == TYPE_WIFI) {
            if ("p2p".equals(feature)) {
                NetworkCapabilities netCap = new NetworkCapabilities();
                netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
                netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P);
                return netCap;
            }
        }
        return null;
    }

    private int networkTypeForNetworkCapabilities(NetworkCapabilities netCap) {
        if (netCap == null) return TYPE_NONE;
        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
            return TYPE_MOBILE_CBS;
        }
        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
            return TYPE_MOBILE_IMS;
        }
        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
            return TYPE_MOBILE_FOTA;
        }
        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
            return TYPE_MOBILE_DUN;
        }
        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
            return TYPE_MOBILE_SUPL;
        }
        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
            return TYPE_MOBILE_MMS;
        }
        if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
            return TYPE_MOBILE_HIPRI;
        }
        return TYPE_NONE;
    }

    private static class LegacyRequest {
        NetworkCapabilities networkCapabilities;
        NetworkRequest networkRequest;
        int expireSequenceNumber;
        Network currentNetwork;
        int delay = -1;
        NetworkCallbackListener networkCallbackListener = new NetworkCallbackListener() {
            @Override
            public void onAvailable(NetworkRequest request, Network network) {
                currentNetwork = network;
                Log.d(TAG, "startUsingNetworkFeature got Network:" + network);
                network.bindProcessForHostResolution();
            }
            @Override
            public void onLost(NetworkRequest request, Network network) {
                if (network.equals(currentNetwork)) {
                    currentNetwork = null;
                    network.unbindProcessForHostResolution();
                }
                Log.d(TAG, "startUsingNetworkFeature lost Network:" + network);
            }
        };
    }

    private HashMap<NetworkCapabilities, LegacyRequest> sLegacyRequests =
            new HashMap<NetworkCapabilities, LegacyRequest>();

    private NetworkRequest findRequestForFeature(NetworkCapabilities netCap) {
        synchronized (sLegacyRequests) {
            LegacyRequest l = sLegacyRequests.get(netCap);
            if (l != null) return l.networkRequest;
        }
        return null;
    }

    private void renewRequestLocked(LegacyRequest l) {
        l.expireSequenceNumber++;
        Log.d(TAG, "renewing request to seqNum " + l.expireSequenceNumber);
        sendExpireMsgForFeature(l.networkCapabilities, l.expireSequenceNumber, l.delay);
    }

    private void expireRequest(NetworkCapabilities netCap, int sequenceNum) {
        int ourSeqNum = -1;
        synchronized (sLegacyRequests) {
            LegacyRequest l = sLegacyRequests.get(netCap);
            if (l == null) return;
            ourSeqNum = l.expireSequenceNumber;
            if (l.expireSequenceNumber == sequenceNum) {
                releaseNetworkRequest(l.networkRequest);
                sLegacyRequests.remove(netCap);
            }
        }
        Log.d(TAG, "expireRequest with " + ourSeqNum + ", " + sequenceNum);
    }

    private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) {
        int delay = -1;
        int type = networkTypeForNetworkCapabilities(netCap);
        try {
            delay = mService.getRestoreDefaultNetworkDelay(type);
        } catch (RemoteException e) {}
        LegacyRequest l = new LegacyRequest();
        l.networkCapabilities = netCap;
        l.delay = delay;
        l.expireSequenceNumber = 0;
        l.networkRequest = sendRequestForNetwork(netCap, l.networkCallbackListener, 0,
                REQUEST, true);
        if (l.networkRequest == null) return null;
        sLegacyRequests.put(netCap, l);
        sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay);
        return l.networkRequest;
    }

    private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) {
        if (delay >= 0) {
            Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay);
            Message msg = sCallbackHandler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap);
            sCallbackHandler.sendMessageDelayed(msg, delay);
        }
    }

    private NetworkRequest removeRequestForFeature(NetworkCapabilities netCap) {
        synchronized (sLegacyRequests) {
            LegacyRequest l = sLegacyRequests.remove(netCap);
            if (l == null) return null;
            return l.networkRequest;
        }
    }

    /**
@@ -1782,8 +1964,10 @@ public class ConnectivityManager {
    public static final int CALLBACK_RELEASED           = BASE + 8;
    /** @hide */
    public static final int CALLBACK_EXIT               = BASE + 9;
    /** @hide obj = NetworkCapabilities, arg1 = seq number */
    private static final int EXPIRE_LEGACY_REQUEST      = BASE + 10;

    private static class CallbackHandler extends Handler {
    private class CallbackHandler extends Handler {
        private final HashMap<NetworkRequest, NetworkCallbackListener>mCallbackMap;
        private final AtomicInteger mRefCount;
        private static final String TAG = "ConnectivityManager.CallbackHandler";
@@ -1903,6 +2087,10 @@ public class ConnectivityManager {
                    getLooper().quit();
                    break;
                }
                case EXPIRE_LEGACY_REQUEST: {
                    expireRequest((NetworkCapabilities)message.obj, message.arg1);
                    break;
                }
            }
        }

@@ -1954,8 +2142,9 @@ public class ConnectivityManager {
    private final static int LISTEN  = 1;
    private final static int REQUEST = 2;

    private NetworkRequest somethingForNetwork(NetworkCapabilities need,
            NetworkCallbackListener networkCallbackListener, int timeoutSec, int action) {
    private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
            NetworkCallbackListener networkCallbackListener, int timeoutSec, int action,
            boolean legacy) {
        NetworkRequest networkRequest = null;
        if (networkCallbackListener == null) {
            throw new IllegalArgumentException("null NetworkCallbackListener");
@@ -1968,7 +2157,7 @@ public class ConnectivityManager {
                        new Binder());
            } else {
                networkRequest = mService.requestNetwork(need, new Messenger(sCallbackHandler),
                        timeoutSec, new Binder());
                        timeoutSec, new Binder(), legacy);
            }
            if (networkRequest != null) {
                synchronized(sNetworkCallbackListener) {
@@ -1998,7 +2187,7 @@ public class ConnectivityManager {
     */
    public NetworkRequest requestNetwork(NetworkCapabilities need,
            NetworkCallbackListener networkCallbackListener) {
        return somethingForNetwork(need, networkCallbackListener, 0, REQUEST);
        return sendRequestForNetwork(need, networkCallbackListener, 0, REQUEST, false);
    }

    /**
@@ -2021,7 +2210,7 @@ public class ConnectivityManager {
     */
    public NetworkRequest requestNetwork(NetworkCapabilities need,
            NetworkCallbackListener networkCallbackListener, int timeoutSec) {
        return somethingForNetwork(need, networkCallbackListener, timeoutSec, REQUEST);
        return sendRequestForNetwork(need, networkCallbackListener, timeoutSec, REQUEST, false);
    }

    /**
@@ -2099,7 +2288,7 @@ public class ConnectivityManager {
     */
    public NetworkRequest listenForNetwork(NetworkCapabilities need,
            NetworkCallbackListener networkCallbackListener) {
        return somethingForNetwork(need, networkCallbackListener, 0, LISTEN);
        return sendRequestForNetwork(need, networkCallbackListener, 0, LISTEN, false);
    }

    /**
+3 −1
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ interface IConnectivityManager
            in NetworkCapabilities nc, int score);

    NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
            in Messenger messenger, int timeoutSec, in IBinder binder);
            in Messenger messenger, int timeoutSec, in IBinder binder, boolean legacy);

    NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities,
            in PendingIntent operation);
@@ -170,4 +170,6 @@ interface IConnectivityManager
            in PendingIntent operation);

    void releaseNetworkRequest(in NetworkRequest networkRequest);

    int getRestoreDefaultNetworkDelay(int networkType);
}
+19 −11
Original line number Diff line number Diff line
@@ -2824,7 +2824,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        }
    }

    private int getRestoreDefaultNetworkDelay(int networkType) {
    @Override
    public int getRestoreDefaultNetworkDelay(int networkType) {
        String restoreDefaultNetworkDelayStr = SystemProperties.get(
                NETWORK_RESTORE_DELAY_PROP_NAME);
        if(restoreDefaultNetworkDelayStr != null &&
@@ -3118,6 +3119,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
            } catch (Exception e) {
                loge("Exception removing network: " + e);
            }
            // TODO - if we move the logic to the network agent (have them disconnect
            // because they lost all their requests or because their score isn't good)
            // then they would disconnect organically, report their new state and then
            // disconnect the channel.
            if (nai.networkInfo.isConnected()) {
                nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
                        null, null);
            }
            notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
            nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
            mNetworkAgentInfos.remove(msg.replyTo);
@@ -3184,7 +3193,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        }
        if (bestNetwork != null) {
            if (VDBG) log("using " + bestNetwork.name());
            bestNetwork.networkRequests.put(nri.request.requestId, nri.request);
            bestNetwork.addRequest(nri.request);
            notifyNetworkCallback(bestNetwork, nri);
            score = bestNetwork.currentScore;
        }
@@ -3192,7 +3201,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        if (msg.what == EVENT_REGISTER_NETWORK_REQUEST) {
            if (DBG) log("sending new NetworkRequest to factories");
            for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
                nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
                nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score,
                        0, nri.request);
            }
        }
    }
@@ -5260,7 +5270,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {

    @Override
    public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
            Messenger messenger, int timeoutSec, IBinder binder) {
            Messenger messenger, int timeoutSec, IBinder binder, boolean legacy) {
        if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
                == false) {
            enforceConnectivityInternalPermission();
@@ -5272,7 +5282,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
            throw new IllegalArgumentException("Bad timeout specified");
        }
        NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
                networkCapabilities), false, nextNetworkRequestId());
                networkCapabilities), legacy, nextNetworkRequestId());
        if (DBG) log("requestNetwork for " + networkRequest);
        NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
                NetworkRequestInfo.REQUEST);
@@ -5373,7 +5383,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), nextNetId(),
            new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
            new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler);

        if (VDBG) log("registerNetworkAgent " + nai);
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
    }

@@ -5420,7 +5430,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
                mClat.stopClat();
            }
            // If the link requires clat to be running, then start the daemon now.
            if (newLp != null && na.networkInfo.isConnected()) {
            if (na.networkInfo.isConnected()) {
                mClat.startClat(na);
            } else {
                mClat.stopClat();
@@ -5632,7 +5642,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
                        if (VDBG) log("   accepting network in place of null");
                    }
                    mNetworkForRequestId.put(nri.request.requestId, newNetwork);
                    newNetwork.networkRequests.put(nri.request.requestId, nri.request);
                    newNetwork.addRequest(nri.request);
                    keep = true;
                    // TODO - this could get expensive if we have alot of requests for this
                    // network.  Think about if there is a way to reduce this.  Push
@@ -5777,15 +5787,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {

    protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
        if (VDBG) log("notifyType " + notifyType + " for " + networkAgent.name());
        boolean needsBroadcasts = false;
        for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
            NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
            NetworkRequestInfo nri = mNetworkRequests.get(nr);
            if (VDBG) log(" sending notification for " + nr);
            if (nr.needsBroadcasts) needsBroadcasts = true;
            callCallbackForRequest(nri, networkAgent, notifyType);
        }
        if (needsBroadcasts) {
        if (networkAgent.needsBroadcasts) {
            if (notifyType == ConnectivityManager.CALLBACK_AVAILABLE) {
                sendConnectedBroadcastDelayed(networkAgent.networkInfo,
                        getConnectivityChangeDelay());
+17 −0
Original line number Diff line number Diff line
@@ -45,6 +45,17 @@ public class NetworkAgentInfo {
    public int currentScore;
    public final NetworkMonitor networkMonitor;

    /**
     * Indicates we need to send CONNECTIVITY_ACTION broadcasts for this network.
     * For example the built-in default network request and any requsts coming from
     * the deprecated startUsingNetworkFeature API will have this set.  Networks
     * responding to the new requestNetwork API will rely on point to point callbacks.
     *
     * Gets set if any legacy requests get affiliated with this network and
     * stays set for life so we send disconnected bcasts to match the connected,
     * even if the legacy request has moved on.
     */
    public boolean needsBroadcasts = false;

    // The list of NetworkRequests being satisfied by this Network.
    public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
@@ -66,6 +77,12 @@ public class NetworkAgentInfo {
        networkMonitor = new NetworkMonitor(context, handler, this);
    }

    public void addRequest(NetworkRequest networkRequest) {
        if (networkRequest.needsBroadcasts) needsBroadcasts = true;

        networkRequests.put(networkRequest.requestId, networkRequest);
    }

    public String toString() {
        return "NetworkAgentInfo{ ni{" + networkInfo + "}  network{" +
                network + "}  lp{" +