diff options
-rw-r--r-- | core/java/android/net/ConnectivityManager.java | 91 | ||||
-rw-r--r-- | services/core/java/com/android/server/ConnectivityService.java | 56 |
2 files changed, 98 insertions, 49 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 12cd5f1..01334c3 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2081,23 +2081,6 @@ public class ConnectivityManager { * changes. Should be extended by applications wanting notifications. */ public static class NetworkCallback { - /** @hide */ - public static final int PRECHECK = 1; - /** @hide */ - public static final int AVAILABLE = 2; - /** @hide */ - public static final int LOSING = 3; - /** @hide */ - public static final int LOST = 4; - /** @hide */ - public static final int UNAVAIL = 5; - /** @hide */ - public static final int CAP_CHANGED = 6; - /** @hide */ - public static final int PROP_CHANGED = 7; - /** @hide */ - public static final int CANCELED = 8; - /** * Called when the framework connects to a new network to evaluate whether it satisfies this * request. If evaluation succeeds, this callback may be followed by an {@link #onAvailable} @@ -2174,30 +2157,54 @@ public class ConnectivityManager { */ public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {} + /** + * Called when the network the framework connected to for this request + * goes into {@link NetworkInfo.DetailedState.SUSPENDED}. + * This generally means that while the TCP connections are still live, + * temporarily network data fails to transfer. Specifically this is used + * on cellular networks to mask temporary outages when driving through + * a tunnel, etc. + * @hide + */ + public void onNetworkSuspended(Network network) {} + + /** + * Called when the network the framework connected to for this request + * returns from a {@link NetworkInfo.DetailedState.SUSPENDED} state. + * This should always be preceeded by a matching {@code onNetworkSuspended} + * call. + * @hide + */ + public void onNetworkResumed(Network network) {} + private NetworkRequest networkRequest; } private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER; - /** @hide obj = pair(NetworkRequest, Network) */ - public static final int CALLBACK_PRECHECK = BASE + 1; - /** @hide obj = pair(NetworkRequest, Network) */ - public static final int CALLBACK_AVAILABLE = BASE + 2; - /** @hide obj = pair(NetworkRequest, Network), arg1 = ttl */ - public static final int CALLBACK_LOSING = BASE + 3; - /** @hide obj = pair(NetworkRequest, Network) */ - public static final int CALLBACK_LOST = BASE + 4; - /** @hide obj = NetworkRequest */ - public static final int CALLBACK_UNAVAIL = BASE + 5; - /** @hide obj = pair(NetworkRequest, Network) */ - public static final int CALLBACK_CAP_CHANGED = BASE + 6; - /** @hide obj = pair(NetworkRequest, Network) */ - public static final int CALLBACK_IP_CHANGED = BASE + 7; - /** @hide obj = NetworkRequest */ - public static final int CALLBACK_RELEASED = BASE + 8; /** @hide */ - public static final int CALLBACK_EXIT = BASE + 9; + public static final int CALLBACK_PRECHECK = BASE + 1; + /** @hide */ + public static final int CALLBACK_AVAILABLE = BASE + 2; + /** @hide arg1 = TTL */ + public static final int CALLBACK_LOSING = BASE + 3; + /** @hide */ + public static final int CALLBACK_LOST = BASE + 4; + /** @hide */ + public static final int CALLBACK_UNAVAIL = BASE + 5; + /** @hide */ + public static final int CALLBACK_CAP_CHANGED = BASE + 6; + /** @hide */ + public static final int CALLBACK_IP_CHANGED = BASE + 7; + /** @hide */ + 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 final int EXPIRE_LEGACY_REQUEST = BASE + 10; + /** @hide */ + public static final int CALLBACK_SUSPENDED = BASE + 11; + /** @hide */ + public static final int CALLBACK_RESUMED = BASE + 12; private class CallbackHandler extends Handler { private final HashMap<NetworkRequest, NetworkCallback>mCallbackMap; @@ -2274,6 +2281,20 @@ public class ConnectivityManager { } break; } + case CALLBACK_SUSPENDED: { + NetworkCallback callback = getCallback(request, "SUSPENDED"); + if (callback != null) { + callback.onNetworkSuspended(network); + } + break; + } + case CALLBACK_RESUMED: { + NetworkCallback callback = getCallback(request, "RESUMED"); + if (callback != null) { + callback.onNetworkResumed(network); + } + break; + } case CALLBACK_RELEASED: { NetworkCallback callback = null; synchronized(mCallbackMap) { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 7f124dc..8ca075f 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -493,10 +493,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void maybeLogBroadcast(NetworkAgentInfo nai, boolean connected, int type, + private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type, boolean isDefaultNetwork) { if (DBG) { - log("Sending " + (connected ? "connected" : "disconnected") + + log("Sending " + state + " broadcast for type " + type + " " + nai.name() + " isDefaultNetwork=" + isDefaultNetwork); } @@ -520,8 +520,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Send a broadcast if this is the first network of its type or if it's the default. final boolean isDefaultNetwork = isDefaultNetwork(nai); if (list.size() == 1 || isDefaultNetwork) { - maybeLogBroadcast(nai, true, type, isDefaultNetwork); - sendLegacyNetworkBroadcast(nai, true, type); + maybeLogBroadcast(nai, DetailedState.CONNECTED, type, isDefaultNetwork); + sendLegacyNetworkBroadcast(nai, DetailedState.CONNECTED, type); } } @@ -538,17 +538,19 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } + final DetailedState state = DetailedState.DISCONNECTED; + if (wasFirstNetwork || wasDefault) { - maybeLogBroadcast(nai, false, type, wasDefault); - sendLegacyNetworkBroadcast(nai, false, type); + maybeLogBroadcast(nai, state, type, wasDefault); + sendLegacyNetworkBroadcast(nai, state, type); } if (!list.isEmpty() && wasFirstNetwork) { if (DBG) log("Other network available for type " + type + ", sending connected broadcast"); final NetworkAgentInfo replacement = list.get(0); - maybeLogBroadcast(replacement, false, type, isDefaultNetwork(replacement)); - sendLegacyNetworkBroadcast(replacement, false, type); + maybeLogBroadcast(replacement, state, type, isDefaultNetwork(replacement)); + sendLegacyNetworkBroadcast(replacement, state, type); } } @@ -560,6 +562,21 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + // send out another legacy broadcast - currently only used for suspend/unsuspend + // toggle + public void update(NetworkAgentInfo nai) { + final boolean isDefault = isDefaultNetwork(nai); + final DetailedState state = nai.networkInfo.getDetailedState(); + for (int type = 0; type < mTypeLists.length; type++) { + final ArrayList<NetworkAgentInfo> list = mTypeLists[type]; + final boolean isFirst = (list != null && list.size() > 0 && nai == list.get(0)); + if (isFirst || isDefault) { + maybeLogBroadcast(nai, state, type, isDefault); + sendLegacyNetworkBroadcast(nai, state, type); + } + } + } + private String naiToString(NetworkAgentInfo nai) { String name = (nai != null) ? nai.name() : "null"; String state = (nai.networkInfo != null) ? @@ -4502,6 +4519,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) { NetworkInfo.State state = newInfo.getState(); NetworkInfo oldInfo = null; + final int oldScore = networkAgent.getCurrentScore(); synchronized (networkAgent) { oldInfo = networkAgent.networkInfo; networkAgent.networkInfo = newInfo; @@ -4560,8 +4578,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // This has to happen after matching the requests, because callbacks are just requests. notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK); - } else if (state == NetworkInfo.State.DISCONNECTED || - state == NetworkInfo.State.SUSPENDED) { + } else if (state == NetworkInfo.State.DISCONNECTED) { networkAgent.asyncChannel.disconnect(); if (networkAgent.isVPN()) { synchronized (mProxyLock) { @@ -4573,6 +4590,17 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } + } else if ((oldInfo != null && oldInfo.getState() == NetworkInfo.State.SUSPENDED) || + state == NetworkInfo.State.SUSPENDED) { + // going into or coming out of SUSPEND: rescore and notify + if (networkAgent.getCurrentScore() != oldScore) { + rematchAllNetworksAndRequests(networkAgent, oldScore, + NascentState.NOT_JUST_VALIDATED); + } + notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ? + ConnectivityManager.CALLBACK_SUSPENDED : + ConnectivityManager.CALLBACK_RESUMED)); + mLegacyTypeTracker.update(networkAgent); } } @@ -4608,7 +4636,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) { + private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, DetailedState state, int type) { // The NetworkInfo we actually send out has no bearing on the real // state of affairs. For example, if the default connection is mobile, // and a request for HIPRI has just gone away, we need to pretend that @@ -4617,11 +4645,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // and is still connected. NetworkInfo info = new NetworkInfo(nai.networkInfo); info.setType(type); - if (connected) { - info.setDetailedState(DetailedState.CONNECTED, null, info.getExtraInfo()); + if (state != DetailedState.DISCONNECTED) { + info.setDetailedState(state, null, info.getExtraInfo()); sendConnectedBroadcast(info); } else { - info.setDetailedState(DetailedState.DISCONNECTED, info.getReason(), info.getExtraInfo()); + info.setDetailedState(state, info.getReason(), info.getExtraInfo()); Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType()); |