summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lorenzo Colitti <lorenzo@google.com> 2014-11-28 11:21:30 +0900
committer Jeff Davidson <jpd@google.com> 2014-12-02 10:27:05 -0800
commit403aa2684e0e93b4792aabc0bbe1f32ac5e417af (patch)
tree79716af3091615cbc20fbefce2271900d5d13f4a
parentdc1baa16b1c559b07d392f7d899fcfe18fa7036c (diff)
Make StatusBar display all default networks.
The basic principle is: if an app's traffic could possibly go over a network without the app using the multinetwork APIs (hence "by default"), then the status bar should show that network's connectivity. In the normal case, app traffic only goes over the system's default network connection, so that's the only network returned. With a VPN in force, some app traffic may go into the VPN, and thus over whatever underlying networks the VPN specifies, while other app traffic may go over the system default network (e.g.: a split-tunnel VPN, or an app disallowed by the VPN), so the set of networks returned includes the VPN's underlying networks and the system default. Specifically: 1. Add a NETWORK_CAPABILITY_VALIDATED bit to NetworkCapabilities. 2. Add a hidden API to retrieve the NetworkCapabilities of all default networks for a given macro-user. 3. Modify the status bar code that used getActiveNetworkInfo to determine which network was active, and make it consider all validated networks instead. 4. Because the set of active networks depends on which VPN app the user is running, make the status bar re-evaluate the networking situation when the active user changes. Bug: 17460017 Change-Id: Ie4965f35fb5936b088e6060ee06e362c22297ab2
-rw-r--r--core/java/android/net/ConnectivityManager.java13
-rw-r--r--core/java/android/net/IConnectivityManager.aidl1
-rw-r--r--core/java/android/net/NetworkCapabilities.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java116
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java72
7 files changed, 158 insertions, 57 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ff1a4414ebce..4215f207eae0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -721,6 +721,19 @@ public class ConnectivityManager {
}
/**
+ * Returns an array of of {@link NetworkCapabilities} objects, representing
+ * the Networks that applications run by the given user will use by default.
+ * @hide
+ */
+ public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
+ try {
+ return mService.getDefaultNetworkCapabilitiesForUser(userId);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* Returns details about the Provisioning or currently active default data network. When
* connected, this network is the default route for outgoing connections.
* You should always check {@link NetworkInfo#isConnected()} before initiating
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 79f920e0c28f..802121093a64 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -49,6 +49,7 @@ interface IConnectivityManager
NetworkInfo[] getAllNetworkInfo();
Network getNetworkForType(int networkType);
Network[] getAllNetworks();
+ NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId);
NetworkInfo getProvisioningOrActiveNetworkInfo();
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index ce7ad65fef2d..a7f9c5bcc0ab 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -154,9 +154,16 @@ public final class NetworkCapabilities implements Parcelable {
*/
public static final int NET_CAPABILITY_NOT_VPN = 15;
+ /**
+ * Indicates that connectivity on this network was successfully validated. For example, for a
+ * network with NET_CAPABILITY_INTERNET, it means that Internet connectivity was successfully
+ * detected.
+ * @hide
+ */
+ public static final int NET_CAPABILITY_VALIDATED = 16;
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
- private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VPN;
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_VALIDATED;
/**
* Adds the given capability to this {@code NetworkCapability} instance.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 8ce608c016b5..45a138610b1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -122,7 +122,7 @@ public class QSTileHost implements QSTile.Host {
tile.userSwitch(newUserId);
}
mSecurity.onUserSwitched(newUserId);
- mNetwork.getAccessPointController().onUserSwitched(newUserId);
+ mNetwork.onUserSwitched(newUserId);
mObserver.register();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 58bf2469e09c..bcf08ff57862 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -22,6 +22,7 @@ public interface NetworkController {
void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb);
void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb);
void setWifiEnabled(boolean enabled);
+ void onUserSwitched(int newUserId);
AccessPointController getAccessPointController();
MobileDataController getMobileDataController();
@@ -49,7 +50,6 @@ public interface NetworkController {
void scanForAccessPoints();
boolean connect(AccessPoint ap);
boolean canConfigWifi();
- void onUserSwitched(int newUserId);
public interface AccessPointCallback {
void onAccessPointsChanged(AccessPoint[] accessPoints);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 5e710473f65b..39610e9976a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -16,12 +16,19 @@
package com.android.systemui.statusbar.policy;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
@@ -55,6 +62,7 @@ import com.android.systemui.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -98,16 +106,19 @@ public class NetworkControllerImpl extends BroadcastReceiver
private final AccessPointControllerImpl mAccessPoints;
private final MobileDataControllerImpl mMobileDataController;
- // bluetooth
+ // Network types that replace the carrier label if the device does not support mobile data.
private boolean mBluetoothTethered = false;
+ private boolean mEthernetConnected = false;
- // data connectivity (regardless of state, can we access the internet?)
- // state of inet connection - 0 not connected, 100 connected
+ // state of inet connection
private boolean mConnected = false;
- private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
- private String mConnectedNetworkTypeName;
private boolean mInetCondition; // Used for Logging and demo.
+ // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are
+ // connected and validated, respectively.
+ private final BitSet mConnectedTransports = new BitSet();
+ private final BitSet mValidatedTransports = new BitSet();
+
// States that don't belong to a subcontroller.
private boolean mAirplaneMode = false;
private boolean mHasNoSims;
@@ -125,6 +136,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
new ArrayList<NetworkSignalChangedCallback>();
private boolean mListening;
+ // The current user ID.
+ private int mCurrentUserId;
+
/**
* Construct this controller object and register for updates.
*/
@@ -344,6 +358,14 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
@Override
+ public void onUserSwitched(int newUserId) {
+ mCurrentUserId = newUserId;
+ mAccessPoints.onUserSwitched(newUserId);
+ updateConnectivity();
+ refreshCarrierLabel();
+ }
+
+ @Override
public void onReceive(Context context, Intent intent) {
if (CHATTY) {
Log.d(TAG, "onReceive: intent=" + intent);
@@ -351,7 +373,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
final String action = intent.getAction();
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) ||
action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
- updateConnectivity(intent);
+ updateConnectivity();
refreshCarrierLabel();
} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
refreshLocale();
@@ -498,14 +520,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
/**
- * Turns inet condition into a boolean indexing for a specific network.
- * @return 0 for bad connectivity on this network, 1 for good connectivity
- */
- private int inetConditionForNetwork(int networkType, boolean inetCondition) {
- return (inetCondition && mConnectedNetworkType == networkType) ? 1 : 0;
- }
-
- /**
* Forces update of all callbacks on both SignalClusters and
* NetworkSignalChangedCallbacks.
*/
@@ -539,41 +553,37 @@ public class NetworkControllerImpl extends BroadcastReceiver
/**
* Update the Inet conditions and what network we are connected to.
*/
- private void updateConnectivity(Intent intent) {
- final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
-
- // Are we connected at all, by any interface?
- mConnected = info != null && info.isConnected();
- if (mConnected) {
- mConnectedNetworkType = info.getType();
- mConnectedNetworkTypeName = info.getTypeName();
- } else {
- mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
- mConnectedNetworkTypeName = null;
+ private void updateConnectivity() {
+ mConnectedTransports.clear();
+ mValidatedTransports.clear();
+ for (NetworkCapabilities nc :
+ mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
+ for (int transportType : nc.getTransportTypes()) {
+ mConnectedTransports.set(transportType);
+ if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
+ mValidatedTransports.set(transportType);
+ }
+ }
}
- int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
-
if (CHATTY) {
- Log.d(TAG, "updateConnectivity: networkInfo=" + info);
- Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
+ Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
+ Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
}
- mInetCondition = connectionStatus > INET_CONDITION_THRESHOLD;
-
- if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) {
- mBluetoothTethered = info.isConnected();
- } else {
- mBluetoothTethered = false;
- }
+ mConnected = !mConnectedTransports.isEmpty();
+ mInetCondition = !mValidatedTransports.isEmpty();
+ mBluetoothTethered = mConnectedTransports.get(TRANSPORT_BLUETOOTH);
+ mEthernetConnected = mConnectedTransports.get(TRANSPORT_ETHERNET);
// We want to update all the icons, all at once, for any condition change
for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
- mobileSignalController.setInetCondition(mInetCondition ? 1 : 0, inetConditionForNetwork(
- mobileSignalController.getNetworkType(), mInetCondition));
+ mobileSignalController.setInetCondition(
+ mInetCondition ? 1 : 0,
+ mValidatedTransports.get(mobileSignalController.getTransportType()) ? 1 : 0);
}
mWifiSignalController.setInetCondition(
- inetConditionForNetwork(mWifiSignalController.getNetworkType(), mInetCondition));
+ mValidatedTransports.get(mWifiSignalController.getTransportType()) ? 1 : 0);
}
/**
@@ -594,9 +604,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
label = mContext.getString(R.string.bluetooth_tethered);
}
- final boolean ethernetConnected =
- (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
- if (ethernetConnected && !mHasMobileDataFeature) {
+ if (mEthernetConnected && !mHasMobileDataFeature) {
label = context.getString(R.string.ethernet_label);
}
@@ -612,7 +620,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
}
} else if (!isMobileDataConnected() && !wifiState.connected && !mBluetoothTethered &&
- !ethernetConnected && !mHasMobileDataFeature) {
+ !mEthernetConnected && !mHasMobileDataFeature) {
// Pretty much no connection.
label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
}
@@ -633,9 +641,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("NetworkController state:");
- pw.println(String.format(" %s network type %d (%s)",
- mConnected ? "CONNECTED" : "DISCONNECTED",
- mConnectedNetworkType, mConnectedNetworkTypeName));
+
pw.println(" - telephony ------");
pw.print(" hasVoiceCallingFeature()=");
pw.println(hasVoiceCallingFeature());
@@ -645,6 +651,10 @@ public class NetworkControllerImpl extends BroadcastReceiver
pw.println(mBluetoothTethered);
pw.println(" - connectivity ------");
+ pw.print(" mConnectedTransports=");
+ pw.println(mConnectedTransports);
+ pw.print(" mValidatedTransports=");
+ pw.println(mValidatedTransports);
pw.print(" mInetCondition=");
pw.println(mInetCondition);
pw.print(" mAirplaneMode=");
@@ -795,8 +805,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
public WifiSignalController(Context context, boolean hasMobileData,
List<NetworkSignalChangedCallback> signalCallbacks,
List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
- super("WifiSignalController", context, ConnectivityManager.TYPE_WIFI, signalCallbacks,
- signalClusters, networkController);
+ super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
+ signalCallbacks, signalClusters, networkController);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mHasMobileData = hasMobileData;
Handler handler = new WifiHandler();
@@ -989,7 +999,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
List<SignalCluster> signalClusters, NetworkControllerImpl networkController,
SubscriptionInfo info) {
super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
- ConnectivityManager.TYPE_MOBILE, signalCallbacks, signalClusters,
+ NetworkCapabilities.TRANSPORT_CELLULAR, signalCallbacks, signalClusters,
networkController);
mConfig = config;
mPhone = phone;
@@ -1460,7 +1470,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
protected final String mTag;
protected final T mCurrentState;
protected final T mLastState;
- protected final int mNetworkType;
+ protected final int mTransportType;
protected final Context mContext;
// The owner of the SignalController (i.e. NetworkController will maintain the following
// lists and call notifyListeners whenever the list has changed to ensure everyone
@@ -1479,7 +1489,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
mTag = TAG + "." + tag;
mNetworkController = networkController;
- mNetworkType = type;
+ mTransportType = type;
mContext = context;
mSignalsChangedCallbacks = signalCallbacks;
mSignalClusters = signalClusters;
@@ -1497,8 +1507,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
return mCurrentState;
}
- public int getNetworkType() {
- return mNetworkType;
+ public int getTransportType() {
+ return mTransportType;
}
public void setInetCondition(int inetCondition) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5eec0b7692f9..c5af085d87ee 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1065,6 +1065,72 @@ public class ConnectivityService extends IConnectivityManager.Stub
return result.toArray(new Network[result.size()]);
}
+ private NetworkCapabilities getNetworkCapabilitiesAndValidation(NetworkAgentInfo nai) {
+ if (nai != null) {
+ synchronized (nai) {
+ if (nai.created) {
+ NetworkCapabilities nc = new NetworkCapabilities(nai.networkCapabilities);
+ if (nai.validated) {
+ nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+ } else {
+ nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+ }
+ return nc;
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
+ // The basic principle is: if an app's traffic could possibly go over a
+ // network, without the app doing anything multinetwork-specific,
+ // (hence, by "default"), then include that network's capabilities in
+ // the array.
+ //
+ // In the normal case, app traffic only goes over the system's default
+ // network connection, so that's the only network returned.
+ //
+ // With a VPN in force, some app traffic may go into the VPN, and thus
+ // over whatever underlying networks the VPN specifies, while other app
+ // traffic may go over the system default network (e.g.: a split-tunnel
+ // VPN, or an app disallowed by the VPN), so the set of networks
+ // returned includes the VPN's underlying networks and the system
+ // default.
+ enforceAccessPermission();
+
+ HashMap<Network, NetworkCapabilities> result = new HashMap<Network, NetworkCapabilities>();
+
+ NetworkAgentInfo nai = getDefaultNetwork();
+ NetworkCapabilities nc = getNetworkCapabilitiesAndValidation(getDefaultNetwork());
+ if (nc != null) {
+ result.put(nai.network, nc);
+ }
+
+ if (!mLockdownEnabled) {
+ synchronized (mVpns) {
+ Vpn vpn = mVpns.get(userId);
+ if (vpn != null) {
+ Network[] networks = vpn.getUnderlyingNetworks();
+ if (networks != null) {
+ for (Network network : networks) {
+ nai = getNetworkAgentInfoForNetwork(network);
+ nc = getNetworkCapabilitiesAndValidation(nai);
+ if (nc != null) {
+ result.put(nai.network, nc);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ NetworkCapabilities[] out = new NetworkCapabilities[result.size()];
+ out = result.values().toArray(out);
+ return out;
+ }
+
@Override
public boolean isNetworkSupported(int networkType) {
enforceAccessPermission();
@@ -3544,8 +3610,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated.
private final NetworkRequest mDefaultRequest;
+ private NetworkAgentInfo getDefaultNetwork() {
+ return mNetworkForRequestId.get(mDefaultRequest.requestId);
+ }
+
private boolean isDefaultNetwork(NetworkAgentInfo nai) {
- return mNetworkForRequestId.get(mDefaultRequest.requestId) == nai;
+ return nai == getDefaultNetwork();
}
public void registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,