Loading core/java/android/net/ConnectivityManager.java +204 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading @@ -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; } } /** Loading Loading @@ -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"; Loading Loading @@ -1903,6 +2087,10 @@ public class ConnectivityManager { getLooper().quit(); break; } case EXPIRE_LEGACY_REQUEST: { expireRequest((NetworkCapabilities)message.obj, message.arg1); break; } } } Loading Loading @@ -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"); Loading @@ -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) { Loading Loading @@ -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); } /** Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading core/java/android/net/IConnectivityManager.aidl +3 −1 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -170,4 +170,6 @@ interface IConnectivityManager in PendingIntent operation); void releaseNetworkRequest(in NetworkRequest networkRequest); int getRestoreDefaultNetworkDelay(int networkType); } services/core/java/com/android/server/ConnectivityService.java +19 −11 Original line number Diff line number Diff line Loading @@ -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 && Loading Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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); } } } Loading Loading @@ -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(); Loading @@ -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); Loading Loading @@ -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)); } Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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()); Loading services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -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>(); Loading @@ -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{" + Loading Loading
core/java/android/net/ConnectivityManager.java +204 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading @@ -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; } } /** Loading Loading @@ -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"; Loading Loading @@ -1903,6 +2087,10 @@ public class ConnectivityManager { getLooper().quit(); break; } case EXPIRE_LEGACY_REQUEST: { expireRequest((NetworkCapabilities)message.obj, message.arg1); break; } } } Loading Loading @@ -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"); Loading @@ -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) { Loading Loading @@ -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); } /** Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading
core/java/android/net/IConnectivityManager.aidl +3 −1 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -170,4 +170,6 @@ interface IConnectivityManager in PendingIntent operation); void releaseNetworkRequest(in NetworkRequest networkRequest); int getRestoreDefaultNetworkDelay(int networkType); }
services/core/java/com/android/server/ConnectivityService.java +19 −11 Original line number Diff line number Diff line Loading @@ -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 && Loading Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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); } } } Loading Loading @@ -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(); Loading @@ -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); Loading Loading @@ -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)); } Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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()); Loading
services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +17 −0 Original line number Diff line number Diff line Loading @@ -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>(); Loading @@ -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{" + Loading