diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 826786b0bf..99e368d5e4 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -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 + * + *
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
* for a given uid. This is for internal use only to avoid spying
@@ -1927,12 +1948,18 @@ public class ConnectivityManager {
} 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) {
try {
- mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);
- } catch (RemoteException e) { }
+ return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);
+ } catch (RemoteException e) {
+ return NETID_UNSET;
+ }
}
/**
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 31e60e7ce5..171c7d414d 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -42,6 +42,7 @@ import com.android.internal.net.VpnProfile;
/** {@hide} */
interface IConnectivityManager
{
+ Network getActiveNetwork();
NetworkInfo getActiveNetworkInfo();
NetworkInfo getActiveNetworkInfoForUid(int uid);
NetworkInfo getNetworkInfo(int networkType);
@@ -132,7 +133,7 @@ interface IConnectivityManager
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);
NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 74d4ac23e0..ddaa808d9b 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -42,6 +42,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @hide
*/
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 final String LOG_TAG;
private static final boolean DBG = true;
@@ -142,7 +146,7 @@ public abstract class NetworkAgent extends Handler {
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
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);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3103592c2d..ee44b0990c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
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_VPN;
import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -89,6 +90,7 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.Xml;
@@ -691,16 +693,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
return mNextNetworkRequestId++;
}
- private void assignNextNetId(NetworkAgentInfo nai) {
+ private int reserveNetId() {
synchronized (mNetworkForNetId) {
for (int i = MIN_NET_ID; i <= MAX_NET_ID; i++) {
int netId = mNextNetId;
if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
// Make sure NetID unused. http://b/16815182
- if (mNetworkForNetId.get(netId) == null) {
- nai.network = new Network(netId);
- mNetworkForNetId.put(netId, nai);
- return;
+ if (!mNetIdInUse.get(netId)) {
+ mNetIdInUse.put(netId, true);
+ return netId;
}
}
}
@@ -859,6 +860,28 @@ public class ConnectivityService extends IConnectivityManager.Stub
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.
*
@@ -1942,6 +1965,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nai != null) {
synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.netId);
+ mNetIdInUse.delete(nai.network.netId);
}
// Just in case.
mLegacyTypeTracker.remove(nai);
@@ -1985,6 +2009,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mLegacyTypeTracker.remove(nai);
synchronized (mNetworkForNetId) {
mNetworkForNetId.remove(nai.network.netId);
+ mNetIdInUse.delete(nai.network.netId);
}
// Since we've lost the network, go through all the requests that
// 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.
* the are keyed off the Requests requestId.
*/
+ // TODO: Yikes, this is accessed on multiple threads: add synchronization.
private final SparseArray