Refactor "avoid bad wifi" logic into a utility class am: 95ecfee674 am: 567fc7861d
am: 23d83b031f
Change-Id: I7db61e54c80ec836d00bf4ae087137bb296c30f1
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index fe69320..0c0872a 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -34,9 +34,13 @@
import java.net.UnknownHostException;
import java.net.URL;
import java.net.URLConnection;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.net.SocketFactory;
import com.android.okhttp.ConnectionPool;
+import com.android.okhttp.Dns;
import com.android.okhttp.HttpHandler;
import com.android.okhttp.HttpsHandler;
import com.android.okhttp.OkHttpClient;
@@ -62,10 +66,10 @@
// Objects used to perform per-network operations such as getSocketFactory
// and openConnection, and a lock to protect access to them.
private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
- // mLock should be used to control write access to mConnectionPool and mNetwork.
+ // mLock should be used to control write access to mConnectionPool and mDns.
// maybeInitHttpClient() must be called prior to reading either variable.
private volatile ConnectionPool mConnectionPool = null;
- private volatile com.android.okhttp.internal.Network mNetwork = null;
+ private volatile Dns mDns = null;
private final Object mLock = new Object();
// Default connection pool values. These are evaluated at startup, just
@@ -219,17 +223,17 @@
// out) ConnectionPools.
private void maybeInitHttpClient() {
synchronized (mLock) {
- if (mNetwork == null) {
- mNetwork = new com.android.okhttp.internal.Network() {
+ if (mDns == null) {
+ mDns = new Dns() {
@Override
- public InetAddress[] resolveInetAddresses(String host) throws UnknownHostException {
- return Network.this.getAllByName(host);
+ public List<InetAddress> lookup(String hostname) throws UnknownHostException {
+ return Arrays.asList(Network.this.getAllByName(hostname));
}
};
}
if (mConnectionPool == null) {
mConnectionPool = new ConnectionPool(httpMaxConnections,
- httpKeepAliveDurationMs);
+ httpKeepAliveDurationMs, TimeUnit.MILLISECONDS);
}
}
}
@@ -288,9 +292,8 @@
}
OkHttpClient client = okUrlFactory.client();
client.setSocketFactory(getSocketFactory()).setConnectionPool(mConnectionPool);
-
- // Use internal APIs to change the Network.
- Internal.instance.setNetwork(client, mNetwork);
+ // Let network traffic go via mDns
+ client.setDns(mDns);
return okUrlFactory.open(url);
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 56eba4f..6196400 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -418,8 +418,15 @@
*/
public static final int TRANSPORT_VPN = 4;
+ /**
+ * Indicates this network uses a Wi-Fi NAN transport.
+ *
+ * @hide PROPOSED_NAN_API
+ */
+ public static final int TRANSPORT_WIFI_NAN = 5;
+
private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
- private static final int MAX_TRANSPORT = TRANSPORT_VPN;
+ private static final int MAX_TRANSPORT = TRANSPORT_WIFI_NAN;
/**
* Adds the given transport type to this {@code NetworkCapability} instance.
@@ -889,6 +896,7 @@
case TRANSPORT_BLUETOOTH: transports += "BLUETOOTH"; break;
case TRANSPORT_ETHERNET: transports += "ETHERNET"; break;
case TRANSPORT_VPN: transports += "VPN"; break;
+ case TRANSPORT_WIFI_NAN: transports += "WIFI_NAN"; break;
}
if (++i < types.length) transports += "|";
}
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 679e882..26a2cf0 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -25,11 +25,8 @@
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/filter.h>
-#include <linux/if.h>
#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/if_packet.h>
-#include <net/if_ether.h>
+#include <netinet/ether.h>
#include <netinet/icmp6.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 7cd1b7b..e084ff8 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -55,9 +55,9 @@
*/
public class PermissionMonitor {
private static final String TAG = "PermissionMonitor";
- private static final boolean DBG = false;
- private static final boolean SYSTEM = true;
- private static final boolean NETWORK = false;
+ private static final boolean DBG = true;
+ private static final Boolean SYSTEM = Boolean.TRUE;
+ private static final Boolean NETWORK = Boolean.FALSE;
private final Context mContext;
private final PackageManager mPackageManager;
@@ -228,30 +228,40 @@
update(users, mApps, false);
}
+
+ private Boolean highestPermissionForUid(Boolean currentPermission, String name) {
+ if (currentPermission == SYSTEM) {
+ return currentPermission;
+ }
+ try {
+ final PackageInfo app = mPackageManager.getPackageInfo(name, GET_PERMISSIONS);
+ final boolean isNetwork = hasNetworkPermission(app);
+ final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
+ if (isNetwork || hasRestrictedPermission) {
+ currentPermission = hasRestrictedPermission;
+ }
+ } catch (NameNotFoundException e) {
+ // App not found.
+ loge("NameNotFoundException " + name);
+ }
+ return currentPermission;
+ }
+
private synchronized void onAppAdded(String appName, int appUid) {
if (TextUtils.isEmpty(appName) || appUid < 0) {
loge("Invalid app in onAppAdded: " + appName + " | " + appUid);
return;
}
- try {
- PackageInfo app = mPackageManager.getPackageInfo(appName, GET_PERMISSIONS);
- boolean isNetwork = hasNetworkPermission(app);
- boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
- if (isNetwork || hasRestrictedPermission) {
- Boolean permission = mApps.get(appUid);
- // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
- // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
- if (permission == null || permission == NETWORK) {
- mApps.put(appUid, hasRestrictedPermission);
+ // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
+ // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
+ final Boolean permission = highestPermissionForUid(mApps.get(appUid), appName);
+ if (permission != mApps.get(appUid)) {
+ mApps.put(appUid, permission);
- Map<Integer, Boolean> apps = new HashMap<>();
- apps.put(appUid, hasRestrictedPermission);
- update(mUsers, apps, true);
- }
- }
- } catch (NameNotFoundException e) {
- loge("NameNotFoundException in onAppAdded: " + e);
+ Map<Integer, Boolean> apps = new HashMap<>();
+ apps.put(appUid, permission);
+ update(mUsers, apps, true);
}
}
@@ -260,11 +270,33 @@
loge("Invalid app in onAppRemoved: " + appUid);
return;
}
- mApps.remove(appUid);
-
Map<Integer, Boolean> apps = new HashMap<>();
- apps.put(appUid, NETWORK); // doesn't matter which permission we pick here
- update(mUsers, apps, false);
+
+ Boolean permission = null;
+ String[] packages = mPackageManager.getPackagesForUid(appUid);
+ if (packages != null && packages.length > 0) {
+ for (String name : packages) {
+ permission = highestPermissionForUid(permission, name);
+ if (permission == SYSTEM) {
+ // An app with this UID still has the SYSTEM permission.
+ // Therefore, this UID must already have the SYSTEM permission.
+ // Nothing to do.
+ return;
+ }
+ }
+ }
+ if (permission == mApps.get(appUid)) {
+ // The permissions of this UID have not changed. Nothing to do.
+ return;
+ } else if (permission != null) {
+ mApps.put(appUid, permission);
+ apps.put(appUid, permission);
+ update(mUsers, apps, true);
+ } else {
+ mApps.remove(appUid);
+ apps.put(appUid, NETWORK); // doesn't matter which permission we pick here
+ update(mUsers, apps, false);
+ }
}
private static void log(String s) {
diff --git a/services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
similarity index 91%
rename from services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java
rename to services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
index 033b2c9..63d5d9f 100644
--- a/services/tests/servicestests/src/com/android/server/connectivity/DnsEventListenerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/connectivity/NetdEventListenerServiceTest.java
@@ -20,7 +20,7 @@
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.metrics.DnsEvent;
-import android.net.metrics.IDnsEventListener;
+import android.net.metrics.INetdEventListener;
import android.net.metrics.IpConnectivityLog;
import junit.framework.TestCase;
@@ -47,12 +47,12 @@
import java.util.OptionalInt;
import java.util.stream.IntStream;
-public class DnsEventListenerServiceTest extends TestCase {
+public class NetdEventListenerServiceTest extends TestCase {
- // TODO: read from DnsEventListenerService after this constant is read from system property
+ // TODO: read from NetdEventListenerService after this constant is read from system property
static final int BATCH_SIZE = 100;
- static final int EVENT_TYPE = IDnsEventListener.EVENT_GETADDRINFO;
- // TODO: read from IDnsEventListener
+ static final int EVENT_TYPE = INetdEventListener.EVENT_GETADDRINFO;
+ // TODO: read from INetdEventListener
static final int RETURN_CODE = 1;
static final byte[] EVENT_TYPES = new byte[BATCH_SIZE];
@@ -66,7 +66,7 @@
}
}
- DnsEventListenerService mDnsService;
+ NetdEventListenerService mNetdEventListenerService;
@Mock ConnectivityManager mCm;
@Mock IpConnectivityLog mLog;
@@ -77,7 +77,7 @@
MockitoAnnotations.initMocks(this);
mCallbackCaptor = ArgumentCaptor.forClass(NetworkCallback.class);
mEvCaptor = ArgumentCaptor.forClass(DnsEvent.class);
- mDnsService = new DnsEventListenerService(mCm, mLog);
+ mNetdEventListenerService = new NetdEventListenerService(mCm, mLog);
verify(mCm, times(1)).registerNetworkCallback(any(), mCallbackCaptor.capture());
}
@@ -131,7 +131,7 @@
new Thread() {
public void run() {
while (System.currentTimeMillis() < stop) {
- mDnsService.dump(pw);
+ mNetdEventListenerService.dump(pw);
}
}
}.start();
@@ -158,7 +158,7 @@
void log(int netId, int[] latencies) {
for (int l : latencies) {
- mDnsService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
+ mNetdEventListenerService.onDnsEvent(netId, EVENT_TYPE, RETURN_CODE, l);
}
}