Merge "Stop complaining about failure to remove routes"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index de16985..ef4209f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -373,10 +373,11 @@
}
/**
- * Gets you info about the current data network.
- * Call {@link NetworkInfo#isConnected()} on the returned {@link NetworkInfo}
- * to check if the device has a data connection.
- */
+ * Returns details about the currently active data network. When connected,
+ * this network is the default route for outgoing connections. You should
+ * always check {@link NetworkInfo#isConnected()} before initiating network
+ * traffic. This may return {@code null} when no networks are available.
+ */
public NetworkInfo getActiveNetworkInfo() {
try {
return mService.getActiveNetworkInfo();
@@ -856,4 +857,19 @@
} catch (RemoteException e) {}
return false;
}
+
+ /**
+ * Returns if the currently active data network is metered. A network is
+ * classified as metered when the user is sensitive to heavy data usage on
+ * that connection. You should check this before doing large data transfers,
+ * and warn the user or delay the operation until another network is
+ * available.
+ */
+ public boolean isActiveNetworkMetered() {
+ try {
+ return mService.isActiveNetworkMetered();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 7046008..92aeff2 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -51,6 +51,7 @@
NetworkState[] getAllNetworkState();
NetworkQuotaInfo getActiveNetworkQuotaInfo();
+ boolean isActiveNetworkMetered();
boolean setRadios(boolean onOff);
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 724d9fb..1f2b1ae 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -31,20 +31,22 @@
int dhcp_do_request(const char *ifname,
const char *ipaddr,
const char *gateway,
- uint32_t *prefixLength,
+ uint32_t *prefixLength,
const char *dns1,
const char *dns2,
const char *server,
- uint32_t *lease);
+ uint32_t *lease,
+ const char *vendorInfo);
int dhcp_do_request_renew(const char *ifname,
const char *ipaddr,
const char *gateway,
- uint32_t *prefixLength,
+ uint32_t *prefixLength,
const char *dns1,
const char *dns2,
const char *server,
- uint32_t *lease);
+ uint32_t *lease,
+ const char *vendorInfo);
int dhcp_stop(const char *ifname);
int dhcp_release_lease(const char *ifname);
@@ -68,6 +70,7 @@
jfieldID dns2;
jfieldID serverAddress;
jfieldID leaseDuration;
+ jfieldID vendorInfo;
} dhcpInfoInternalFieldIds;
static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
@@ -116,16 +119,17 @@
char dns2[PROPERTY_VALUE_MAX];
char server[PROPERTY_VALUE_MAX];
uint32_t lease;
+ char vendorInfo[PROPERTY_VALUE_MAX];
const char *nameStr = env->GetStringUTFChars(ifname, NULL);
if (nameStr == NULL) return (jboolean)false;
if (renew) {
result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease);
+ dns1, dns2, server, &lease, vendorInfo);
} else {
result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease);
+ dns1, dns2, server, &lease, vendorInfo);
}
env->ReleaseStringUTFChars(ifname, nameStr);
@@ -161,6 +165,7 @@
env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress,
env->NewStringUTF(server));
env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease);
+ env->SetObjectField(info, dhcpInfoInternalFieldIds.vendorInfo, env->NewStringUTF(vendorInfo));
}
return (jboolean)(result == 0);
}
@@ -230,6 +235,7 @@
dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
dhcpInfoInternalFieldIds.serverAddress = env->GetFieldID(dhcpInfoInternalClass, "serverAddress", "Ljava/lang/String;");
dhcpInfoInternalFieldIds.leaseDuration = env->GetFieldID(dhcpInfoInternalClass, "leaseDuration", "I");
+ dhcpInfoInternalFieldIds.vendorInfo = env->GetFieldID(dhcpInfoInternalClass, "vendorInfo", "Ljava/lang/String;");
return AndroidRuntime::registerNativeMethods(env,
NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c91b268..faa8d3c 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -865,14 +865,39 @@
@Override
public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
enforceAccessPermission();
- final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
- if (state != null) {
- try {
- return mPolicyManager.getNetworkQuotaInfo(state);
- } catch (RemoteException e) {
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
+ if (state != null) {
+ try {
+ return mPolicyManager.getNetworkQuotaInfo(state);
+ } catch (RemoteException e) {
+ }
}
+ return null;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
- return null;
+ }
+
+ @Override
+ public boolean isActiveNetworkMetered() {
+ enforceAccessPermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork);
+ if (state != null) {
+ try {
+ return mPolicyManager.isNetworkMetered(state);
+ } catch (RemoteException e) {
+ }
+ }
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
public boolean setRadios(boolean turnOn) {