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

Commit 8f379986 authored by Robert Greenwalt's avatar Robert Greenwalt Committed by Android (Google) Code Review
Browse files

Merge "Rewrite startUsingNetworkFeature for new API"

parents 982e28ca 71bf33a0
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
@@ -2843,7 +2843,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 &&
@@ -3137,6 +3138,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);
@@ -3203,7 +3212,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;
        }
@@ -3211,7 +3220,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);
            }
        }
    }
@@ -5279,7 +5289,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();
@@ -5291,7 +5301,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);
@@ -5392,7 +5402,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));
    }

@@ -5439,7 +5449,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();
@@ -5658,7 +5668,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
@@ -5810,15 +5820,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{" +