Add ConnectivityManager.getActiveNetwork().

Rework NetID allocation in ConnectivityService so registerNetworkAgent() can
return the allocated NetID.

Bug: 19416463
Change-Id: I68e395552cf27422c80b4dfae5db5d56a0d68f5d
This commit is contained in:
Paul Jensen
2015-02-13 14:18:39 -05:00
parent bf18bedced
commit 31a94f48bf
8 changed files with 99 additions and 20 deletions

View File

@ -16955,6 +16955,7 @@ package android.net {
public class ConnectivityManager { public class ConnectivityManager {
method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public boolean bindProcessToNetwork(android.net.Network); method public boolean bindProcessToNetwork(android.net.Network);
method public android.net.Network getActiveNetwork();
method public android.net.NetworkInfo getActiveNetworkInfo(); method public android.net.NetworkInfo getActiveNetworkInfo();
method public android.net.NetworkInfo[] getAllNetworkInfo(); method public android.net.NetworkInfo[] getAllNetworkInfo();
method public android.net.Network[] getAllNetworks(); method public android.net.Network[] getAllNetworks();

View File

@ -18216,6 +18216,7 @@ package android.net {
public class ConnectivityManager { public class ConnectivityManager {
method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener); method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public boolean bindProcessToNetwork(android.net.Network); method public boolean bindProcessToNetwork(android.net.Network);
method public android.net.Network getActiveNetwork();
method public android.net.NetworkInfo getActiveNetworkInfo(); method public android.net.NetworkInfo getActiveNetworkInfo();
method public android.net.NetworkInfo[] getAllNetworkInfo(); method public android.net.NetworkInfo[] getAllNetworkInfo();
method public android.net.Network[] getAllNetworks(); method public android.net.Network[] getAllNetworks();

View File

@ -601,6 +601,27 @@ public class ConnectivityManager {
} }
} }
/**
* Returns a {@link Network} object corresponding to the currently active
* default data network. In the event that the current active default data
* network disconnects, the returned {@code Network} object will no longer
* be usable. This will return {@code null} when there is no default
* network.
*
* @return a {@link Network} object for the current default network or
* {@code null} if no default network is currently active
*
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
*/
public Network getActiveNetwork() {
try {
return mService.getActiveNetwork();
} catch (RemoteException e) {
return null;
}
}
/** /**
* Returns details about the currently active default data network * Returns details about the currently active default data network
* for a given uid. This is for internal use only to avoid spying * for a given uid. This is for internal use only to avoid spying
@ -1927,12 +1948,18 @@ public class ConnectivityManager {
} catch (RemoteException e) { } } catch (RemoteException e) { }
} }
/** {@hide} */ /**
public void registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, * @hide
* Register a NetworkAgent with ConnectivityService.
* @return NetID corresponding to NetworkAgent.
*/
public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
NetworkCapabilities nc, int score, NetworkMisc misc) { NetworkCapabilities nc, int score, NetworkMisc misc) {
try { try {
mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc); return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);
} catch (RemoteException e) { } } catch (RemoteException e) {
return NETID_UNSET;
}
} }
/** /**

View File

@ -42,6 +42,7 @@ import com.android.internal.net.VpnProfile;
/** {@hide} */ /** {@hide} */
interface IConnectivityManager interface IConnectivityManager
{ {
Network getActiveNetwork();
NetworkInfo getActiveNetworkInfo(); NetworkInfo getActiveNetworkInfo();
NetworkInfo getActiveNetworkInfoForUid(int uid); NetworkInfo getActiveNetworkInfoForUid(int uid);
NetworkInfo getNetworkInfo(int networkType); NetworkInfo getNetworkInfo(int networkType);
@ -132,7 +133,7 @@ interface IConnectivityManager
void unregisterNetworkFactory(in Messenger messenger); void unregisterNetworkFactory(in Messenger messenger);
void registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
in NetworkCapabilities nc, int score, in NetworkMisc misc); in NetworkCapabilities nc, int score, in NetworkMisc misc);
NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,

View File

@ -42,6 +42,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @hide * @hide
*/ */
public abstract class NetworkAgent extends Handler { public abstract class NetworkAgent extends Handler {
// Guaranteed to be valid (not NETID_UNSET), otherwise registerNetworkAgent() would have thrown
// an exception.
public final int netId;
private volatile AsyncChannel mAsyncChannel; private volatile AsyncChannel mAsyncChannel;
private final String LOG_TAG; private final String LOG_TAG;
private static final boolean DBG = true; private static final boolean DBG = true;
@ -142,7 +146,7 @@ public abstract class NetworkAgent extends Handler {
if (VDBG) log("Registering NetworkAgent"); if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE); Context.CONNECTIVITY_SERVICE);
cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, misc); new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
} }

View File

@ -20,6 +20,7 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.getNetworkTypeName;
@ -89,6 +90,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Slog; import android.util.Slog;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.util.Xml; import android.util.Xml;
@ -691,16 +693,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
return mNextNetworkRequestId++; return mNextNetworkRequestId++;
} }
private void assignNextNetId(NetworkAgentInfo nai) { private int reserveNetId() {
synchronized (mNetworkForNetId) { synchronized (mNetworkForNetId) {
for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) { for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
int netId = mNextNetId; int netId = mNextNetId;
if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID; if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
// Make sure NetID unused. http://b/16815182 // Make sure NetID unused. http://b/16815182
if (mNetworkForNetId.get(netId) == null) { if (!mNetIdInUse.get(netId)) {
nai.network = new Network(netId); mNetIdInUse.put(netId, true);
mNetworkForNetId.put(netId, nai); return netId;
return;
} }
} }
} }
@ -859,6 +860,28 @@ public class ConnectivityService extends IConnectivityManager.Stub
return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid); return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid);
} }
@Override
public Network getActiveNetwork() {
enforceAccessPermission();
final int uid = Binder.getCallingUid();
final int user = UserHandle.getUserId(uid);
int vpnNetId = NETID_UNSET;
synchronized (mVpns) {
final Vpn vpn = mVpns.get(user);
if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
}
NetworkAgentInfo nai;
if (vpnNetId != NETID_UNSET) {
synchronized (mNetworkForNetId) {
nai = mNetworkForNetId.get(vpnNetId);
}
if (nai != null) return nai.network;
}
nai = getDefaultNetwork();
if (nai != null && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid)) nai = null;
return nai != null ? nai.network : null;
}
/** /**
* Find the first Provisioning network. * Find the first Provisioning network.
* *
@ -1942,6 +1965,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nai != null) { if (nai != null) {
synchronized (mNetworkForNetId) { synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.netId); mNetworkForNetId.remove(nai.network.netId);
mNetIdInUse.delete(nai.network.netId);
} }
// Just in case. // Just in case.
mLegacyTypeTracker.remove(nai); mLegacyTypeTracker.remove(nai);
@ -1985,6 +2009,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mLegacyTypeTracker.remove(nai); mLegacyTypeTracker.remove(nai);
synchronized (mNetworkForNetId) { synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.netId); mNetworkForNetId.remove(nai.network.netId);
mNetIdInUse.delete(nai.network.netId);
} }
// Since we've lost the network, go through all the requests that // Since we've lost the network, go through all the requests that
// it was satisfying and see if any other factory can satisfy them. // it was satisfying and see if any other factory can satisfy them.
@ -3369,14 +3394,23 @@ public class ConnectivityService extends IConnectivityManager.Stub
* and the are the highest scored network available. * and the are the highest scored network available.
* the are keyed off the Requests requestId. * the are keyed off the Requests requestId.
*/ */
// TODO: Yikes, this is accessed on multiple threads: add synchronization.
private final SparseArray<NetworkAgentInfo> mNetworkForRequestId = private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =
new SparseArray<NetworkAgentInfo>(); new SparseArray<NetworkAgentInfo>();
// NOTE: Accessed on multiple threads, must be synchronized on itself.
@GuardedBy("mNetworkForNetId")
private final SparseArray<NetworkAgentInfo> mNetworkForNetId = private final SparseArray<NetworkAgentInfo> mNetworkForNetId =
new SparseArray<NetworkAgentInfo>(); new SparseArray<NetworkAgentInfo>();
// NOTE: Accessed on multiple threads, synchronized with mNetworkForNetId.
// An entry is first added to mNetIdInUse, prior to mNetworkForNetId, so
// there may not be a strict 1:1 correlation between the two.
@GuardedBy("mNetworkForNetId")
private final SparseBooleanArray mNetIdInUse = new SparseBooleanArray();
// NetworkAgentInfo keyed off its connecting messenger // NetworkAgentInfo keyed off its connecting messenger
// TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays // TODO - eval if we can reduce the number of lists/hashmaps/sparsearrays
// NOTE: Only should be accessed on ConnectivityServiceThread, except dump().
private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos = private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos =
new HashMap<Messenger, NetworkAgentInfo>(); new HashMap<Messenger, NetworkAgentInfo>();
@ -3391,7 +3425,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nai == getDefaultNetwork(); return nai == getDefaultNetwork();
} }
public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities, LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkMisc networkMisc) { int currentScore, NetworkMisc networkMisc) {
enforceConnectivityInternalPermission(); enforceConnectivityInternalPermission();
@ -3399,20 +3433,23 @@ public class ConnectivityService extends IConnectivityManager.Stub
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest. // satisfies mDefaultRequest.
NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new NetworkInfo(networkInfo), new LinkProperties(linkProperties), new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler, linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
new NetworkMisc(networkMisc), mDefaultRequest); mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest);
synchronized (this) { synchronized (this) {
nai.networkMonitor.systemReady = mSystemReady; nai.networkMonitor.systemReady = mSystemReady;
} }
if (DBG) log("registerNetworkAgent " + nai); if (DBG) log("registerNetworkAgent " + nai);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai)); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
return nai.network.netId;
} }
private void handleRegisterNetworkAgent(NetworkAgentInfo na) { private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
if (VDBG) log("Got NetworkAgent Messenger"); if (VDBG) log("Got NetworkAgent Messenger");
mNetworkAgentInfos.put(na.messenger, na); mNetworkAgentInfos.put(na.messenger, na);
assignNextNetId(na); synchronized (mNetworkForNetId) {
mNetworkForNetId.put(na.network.netId, na);
}
na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger); na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
NetworkInfo networkInfo = na.networkInfo; NetworkInfo networkInfo = na.networkInfo;
na.networkInfo = null; na.networkInfo = null;

View File

@ -40,7 +40,10 @@ import java.util.ArrayList;
*/ */
public class NetworkAgentInfo { public class NetworkAgentInfo {
public NetworkInfo networkInfo; public NetworkInfo networkInfo;
public Network network; // This Network object should always be used if possible, so as to encourage reuse of the
// enclosed socket factory and connection pool. Avoid creating other Network objects.
// This Network object is always valid.
public final Network network;
public LinkProperties linkProperties; public LinkProperties linkProperties;
public NetworkCapabilities networkCapabilities; public NetworkCapabilities networkCapabilities;
public final NetworkMonitor networkMonitor; public final NetworkMonitor networkMonitor;
@ -83,12 +86,12 @@ public class NetworkAgentInfo {
// Used by ConnectivityService to keep track of 464xlat. // Used by ConnectivityService to keep track of 464xlat.
public Nat464Xlat clatd; public Nat464Xlat clatd;
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, NetworkInfo info, public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
NetworkMisc misc, NetworkRequest defaultRequest) { NetworkMisc misc, NetworkRequest defaultRequest) {
this.messenger = messenger; this.messenger = messenger;
asyncChannel = ac; asyncChannel = ac;
network = null; network = net;
networkInfo = info; networkInfo = info;
linkProperties = lp; linkProperties = lp;
networkCapabilities = nc; networkCapabilities = nc;

View File

@ -17,9 +17,10 @@
package com.android.server.connectivity; package com.android.server.connectivity;
import static android.Manifest.permission.BIND_VPN_SERVICE; import static android.Manifest.permission.BIND_VPN_SERVICE;
import static android.os.UserHandle.PER_USER_RANGE; import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.RouteInfo.RTN_THROW; import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE; import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.os.UserHandle.PER_USER_RANGE;
import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6; import static android.system.OsConstants.AF_INET6;
@ -339,6 +340,10 @@ public class Vpn {
return mNetworkInfo; return mNetworkInfo;
} }
public int getNetId() {
return mNetworkAgent != null ? mNetworkAgent.netId : NETID_UNSET;
}
private LinkProperties makeLinkProperties() { private LinkProperties makeLinkProperties() {
boolean allowIPv4 = mConfig.allowIPv4; boolean allowIPv4 = mConfig.allowIPv4;
boolean allowIPv6 = mConfig.allowIPv6; boolean allowIPv6 = mConfig.allowIPv6;