From 42eadcdf3432e9fd6662ee07316db7726c1eabbf Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 11 Mar 2015 18:08:08 -0700 Subject: [PATCH 01/29] Adding hidden isWifiCallingEnabled() and isVolteEnabled() Change-Id: Ic33f8c50dfb2d81b2bdc149629724e3972aad09e --- .../android/telephony/TelephonyManager.java | 28 +++++++++++++++++++ .../internal/telephony/ITelephony.aidl | 12 ++++++++ 2 files changed, 40 insertions(+) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a7350c9a3baa3..b8de1447053a1 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -3791,6 +3791,34 @@ public class TelephonyManager { } } + /** + * Returns the Status of Volte + *@hide + */ + public boolean isVolteEnabled() { + try { + return getITelephony().isVolteEnabled(); + } catch (RemoteException ex) { + return false; + } catch (NullPointerException ex) { + return false; + } + } + + /** + * Returns the Status of Wi-Fi Calling + *@hide + */ + public boolean isWifiCallingEnabled() { + try { + return getITelephony().isWifiCallingEnabled(); + } catch (RemoteException ex) { + return false; + } catch (NullPointerException ex) { + return false; + } + } + /** * Set TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC for the default phone. * diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index bf3ee09daa970..bb0bd04d77759 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -871,6 +871,18 @@ interface ITelephony { */ boolean isImsRegistered(); + /** + * Returns the Status of Wi-Fi Calling + *@hide + */ + boolean isWifiCallingEnabled(); + + /** + * Returns the Status of Volte + *@hide + */ + boolean isVolteEnabled(); + /** * Returns the unique device ID of phone, for example, the IMEI for * GSM and the MEID for CDMA phones. Return null if device ID is not available. From b335d20628fcfc1592ec97ab182a055e030a4dfe Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Fri, 13 Mar 2015 14:06:12 -0400 Subject: [PATCH 02/29] Fix javadoc braces for ConnectivityManager.EXTRA_NETWORK. Change-Id: I5ad30a34f96e9e99a557b5bae9a30bfc08c89620 --- core/java/android/net/ConnectivityManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index eb2df0bf0dd60..3b0d567ce1dcd 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2370,7 +2370,7 @@ public class ConnectivityManager { * successfully finding a network for the applications request. Retrieve it with * {@link android.content.Intent#getParcelableExtra(String)}. *

- * Note that if you intend to invoke (@link #setProcessDefaultNetwork(Network)) or + * Note that if you intend to invoke {@link #setProcessDefaultNetwork} or * {@link Network#openConnection(java.net.URL)} then you must get a * ConnectivityManager instance before doing so. */ From e4fac93dc074a28cb76095da69b90da0e2b64922 Mon Sep 17 00:00:00 2001 From: Pavel Zhamaitsiak Date: Wed, 11 Mar 2015 17:09:13 -0700 Subject: [PATCH 03/29] Add format string for displaying SPN in Wi-Fi calling mode. Bug: 19681794 Change-Id: I31feab956d14accda73288cd43a2aa34db7175ae --- core/res/res/values-mcc310-mnc260/strings.xml | 2 ++ core/res/res/values/strings.xml | 2 ++ core/res/res/values/symbols.xml | 1 + 3 files changed, 5 insertions(+) diff --git a/core/res/res/values-mcc310-mnc260/strings.xml b/core/res/res/values-mcc310-mnc260/strings.xml index 5cadc2ae0df6c..75b1b53761847 100644 --- a/core/res/res/values-mcc310-mnc260/strings.xml +++ b/core/res/res/values-mcc310-mnc260/strings.xml @@ -29,4 +29,6 @@ Wi-Fi Calling isn\'t available. Contact your carrier to enable Wi-Fi Calling. + + %s Wi-Fi Calling diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 81db6c58776bb..9f710932f89b5 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -251,6 +251,8 @@ + + %s 0 + + 1 + + + 2 + + + 3 + + + 4 + 600 diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b417968e1320a..91328c9a185d6 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -344,6 +344,10 @@ + + + + From 5914caff06f9790238bea0536acfbf533cee9046 Mon Sep 17 00:00:00 2001 From: Pierre Vandwalle Date: Fri, 13 Mar 2015 13:58:53 -0700 Subject: [PATCH 05/29] export API to disable autojoin scan initial implementation Change-Id: I28e268dd8b859a3a22c3d6f699216bbd7124af26 --- wifi/java/android/net/wifi/IWifiManager.aidl | 4 ++++ wifi/java/android/net/wifi/WifiManager.java | 21 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index b87a1e94c6c87..ca95ec1f7358c 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -153,6 +153,10 @@ interface IWifiManager void setAllowScansWithTraffic(int enabled); + boolean getAllowScansWhileAssociated(); + + void setAllowScansWhileAssociated(boolean enabled); + WifiConnectionStatistics getConnectionStatistics(); void disableEphemeralNetwork(String SSID); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index b001bb8ce13c3..97e10dcc1f82e 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -2561,6 +2561,27 @@ public class WifiManager { } } + /** + * Set setting for allowing Scans when infrastructure is associated + * @hide + */ + public void setAllowScansWhileAssociated(boolean enabled) { + try { + mService.setAllowScansWhileAssociated(enabled); + } catch (RemoteException e) { + } + } + /** + * Get setting for allowing Scans when infrastructure is associated + * @hide + */ + public boolean getAllowScansWhileAssociated() { + try { + return mService.getAllowScansWhileAssociated(); + } catch (RemoteException e) { + } + return false; + } } From 475085b9870c49085f4b5238d84d6e5d5750f31c Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 10 Mar 2015 01:32:40 +0900 Subject: [PATCH 06/29] Add two utility methods for IPv4 netmasks. 1. Add a validating method to convert a netmask to a prefix length. 2. Add a function to get the implicit netmask of an IPv4 address. 3. Add a unit test. Bug: 19704592 Change-Id: Icb9f58d3903ea01df9e3720383c9bd5db6dd8f26 --- core/java/android/net/NetworkUtils.java | 35 ++++++++++ .../src/android/net/NetworkUtilsTest.java | 70 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 core/tests/coretests/src/android/net/NetworkUtilsTest.java diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 8003afb3e860d..4f35a22b45b66 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -229,6 +229,25 @@ public class NetworkUtils { return Integer.bitCount(netmask); } + /** + * Convert an IPv4 netmask to a prefix length, checking that the netmask is contiguous. + * @param netmask as a {@code Inet4Address}. + * @return the network prefix length + * @throws IllegalArgumentException the specified netmask was not contiguous. + * @hide + */ + public static int netmaskToPrefixLength(Inet4Address netmask) { + // inetAddressToInt returns an int in *network* byte order. + int i = Integer.reverseBytes(inetAddressToInt(netmask)); + int prefixLength = Integer.bitCount(i); + int trailingZeros = Integer.numberOfTrailingZeros(i); + if (trailingZeros != 32 - prefixLength) { + throw new IllegalArgumentException("Non-contiguous netmask: " + Integer.toHexString(i)); + } + return prefixLength; + } + + /** * Create an InetAddress from a string where the string must be a standard * representation of a V4 or V6 address. Avoids doing a DNS lookup on failure @@ -308,6 +327,22 @@ public class NetworkUtils { return netPart; } + /** + * Returns the implicit netmask of an IPv4 address, as was the custom before 1993. + */ + public static int getImplicitNetmask(Inet4Address address) { + int firstByte = address.getAddress()[0] & 0xff; // Convert to an unsigned value. + if (firstByte < 128) { + return 8; + } else if (firstByte < 192) { + return 16; + } else if (firstByte < 224) { + return 24; + } else { + return 32; // Will likely not end well for other reasons. + } + } + /** * Utility method to parse strings such as "192.0.2.5/24" or "2001:db8::cafe:d00d/64". * @hide diff --git a/core/tests/coretests/src/android/net/NetworkUtilsTest.java b/core/tests/coretests/src/android/net/NetworkUtilsTest.java new file mode 100644 index 0000000000000..8d51c3b01258f --- /dev/null +++ b/core/tests/coretests/src/android/net/NetworkUtilsTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.NetworkUtils; +import android.test.suitebuilder.annotation.SmallTest; + +import java.net.Inet4Address; +import java.net.InetAddress; + +import junit.framework.TestCase; + +public class NetworkUtilsTest extends TestCase { + + private InetAddress Address(String addr) { + return InetAddress.parseNumericAddress(addr); + } + + private Inet4Address IPv4Address(String addr) { + return (Inet4Address) Address(addr); + } + + @SmallTest + public void testGetImplicitNetmask() { + assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("4.2.2.2"))); + assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("10.5.6.7"))); + assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("173.194.72.105"))); + assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("172.23.68.145"))); + assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.0.2.1"))); + assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.168.5.1"))); + assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("224.0.0.1"))); + assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("255.6.7.8"))); + } + + private void assertInvalidNetworkMask(Inet4Address addr) { + try { + NetworkUtils.netmaskToPrefixLength(addr); + fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception"); + } catch (IllegalArgumentException expected) { + } + } + + @SmallTest + public void testNetmaskToPrefixLength() { + assertEquals(0, NetworkUtils.netmaskToPrefixLength(IPv4Address("0.0.0.0"))); + assertEquals(9, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.128.0.0"))); + assertEquals(17, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.128.0"))); + assertEquals(23, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.254.0"))); + assertEquals(31, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.254"))); + assertEquals(32, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.255"))); + + assertInvalidNetworkMask(IPv4Address("0.0.0.1")); + assertInvalidNetworkMask(IPv4Address("255.255.255.253")); + assertInvalidNetworkMask(IPv4Address("255.255.0.255")); + } +} From 5671eedda0e8e5acf63697bd9f4d8c3027440184 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 10 Mar 2015 23:59:36 +0900 Subject: [PATCH 07/29] DHCP: Add a superclass for DhcpStateMachine. This can be used to switch between different DHCP client implementations. The caller can declare objects of type BaseDhcpStateMachine, and call its methods, without needing to care what implementation is in use. Bug: 19704592 Change-Id: Icefad9b0d0f83b349681388b1fa16b5e2e37c042 --- .../android/net/BaseDhcpStateMachine.java | 35 +++++++++++++++++++ core/java/android/net/DhcpStateMachine.java | 4 ++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 core/java/android/net/BaseDhcpStateMachine.java diff --git a/core/java/android/net/BaseDhcpStateMachine.java b/core/java/android/net/BaseDhcpStateMachine.java new file mode 100644 index 0000000000000..a25847daa8f27 --- /dev/null +++ b/core/java/android/net/BaseDhcpStateMachine.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import com.android.internal.util.StateMachine; + +/** + * Interface that must be implemented by DHCP state machines. + * + * This is an abstract class instead of a Java interface so that callers can just declare an object + * of this type and be able to call all the methods defined by either StateMachine or this class. + * + * @hide + */ +public abstract class BaseDhcpStateMachine extends StateMachine { + protected BaseDhcpStateMachine(String tag) { + super(tag); + } + public abstract void registerForPreDhcpNotification(); + public abstract void doQuit(); +} diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java index 5151a04b577bf..1b8adc8e24bf7 100644 --- a/core/java/android/net/DhcpStateMachine.java +++ b/core/java/android/net/DhcpStateMachine.java @@ -47,7 +47,7 @@ import android.util.Log; * * @hide */ -public class DhcpStateMachine extends StateMachine { +public class DhcpStateMachine extends BaseDhcpStateMachine { private static final String TAG = "DhcpStateMachine"; private static final boolean DBG = false; @@ -161,6 +161,7 @@ public class DhcpStateMachine extends StateMachine { * This is used by Wifi at this time for the purpose of doing BT-Wifi coex * handling during Dhcp */ + @Override public void registerForPreDhcpNotification() { mRegisteredForPreDhcpNotification = true; } @@ -170,6 +171,7 @@ public class DhcpStateMachine extends StateMachine { * * @hide */ + @Override public void doQuit() { quit(); } From 566e0cb692ef8be5ba01c874ebd9d2576be99fe4 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 6 Mar 2015 19:57:39 +0900 Subject: [PATCH 08/29] DHCP: Add a native method for making a DHCP socket. Bug: 19704592 Change-Id: Iadd60d39c93aaabd2917e76791101a7d313b34be --- core/java/android/net/NetworkUtils.java | 7 ++++ core/jni/android_net_NetUtils.cpp | 50 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 4f35a22b45b66..01704e53630a8 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -16,9 +16,11 @@ package android.net; +import java.io.FileDescriptor; import java.net.InetAddress; import java.net.Inet4Address; import java.net.Inet6Address; +import java.net.SocketException; import java.net.UnknownHostException; import java.util.Collection; import java.util.Locale; @@ -138,6 +140,11 @@ public class NetworkUtils { */ public native static String getDhcpError(); + /** + * Attaches a socket filter that accepts DHCP packets to the given socket. + */ + public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException; + /** * Binds the current process to the network designated by {@code netId}. All sockets created * in the future (and not explicitly bound via a bound {@link SocketFactory} (see diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index e64f1defb663b..2ba8e8c16e309 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -24,6 +24,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include extern "C" { @@ -53,6 +61,8 @@ char *dhcp_get_errmsg(); namespace android { +static const uint16_t kDhcpClientPort = 68; + /* * The following remembers the jfieldID's of the fields * of the DhcpInfo Java object, so that we don't have @@ -215,6 +225,44 @@ static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz) return env->NewStringUTF(::dhcp_get_errmsg()); } +static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd) +{ + int fd = jniGetFDFromFileDescriptor(env, javaFd); + uint32_t ip_offset = sizeof(ether_header); + uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol); + uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off); + uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest); + struct sock_filter filter_code[] = { + // Check the protocol is UDP. + BPF_STMT(BPF_LD | BPF_B | BPF_ABS, proto_offset), + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_UDP, 0, 6), + + // Check this is not a fragment. + BPF_STMT(BPF_LD | BPF_H | BPF_ABS, flags_offset), + BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K, 0x1fff, 4, 0), + + // Get the IP header length. + BPF_STMT(BPF_LDX | BPF_B | BPF_MSH, ip_offset), + + // Check the destination port. + BPF_STMT(BPF_LD | BPF_H | BPF_IND, dport_indirect_offset), + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, kDhcpClientPort, 0, 1), + + // Accept or reject. + BPF_STMT(BPF_RET | BPF_K, 0xffff), + BPF_STMT(BPF_RET | BPF_K, 0) + }; + struct sock_fprog filter = { + sizeof(filter_code) / sizeof(filter_code[0]), + filter_code, + }; + + if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) { + jniThrowExceptionFmt(env, "java/net/SocketException", + "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno)); + } +} + static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId) { return (jboolean) !setNetworkForProcess(netId); @@ -242,6 +290,7 @@ static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint return (jboolean) !protectFromVpn(socket); } + // ---------------------------------------------------------------------------- /* @@ -261,6 +310,7 @@ static JNINativeMethod gNetworkUtilMethods[] = { { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution }, { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork }, { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn }, + { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter }, }; int register_android_net_NetworkUtils(JNIEnv* env) From c95a87f30d069472302f90a206e229b82bb2316a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 10 Mar 2015 01:36:14 +0900 Subject: [PATCH 09/29] DHCP: Move the packet code to frameworks/base/services. There's no need for it to be in frameworks/base/core, since it will only be used by services. Bug: 19704592 Change-Id: I2f5277eca848b7000ca46db575e8602eacb5c8bd --- services/Android.mk | 1 + services/net/Android.mk | 10 ++++++++++ .../net}/java/android/net/dhcp/DhcpAckPacket.java | 0 .../net}/java/android/net/dhcp/DhcpDeclinePacket.java | 0 .../net}/java/android/net/dhcp/DhcpDiscoverPacket.java | 0 .../net}/java/android/net/dhcp/DhcpInformPacket.java | 0 .../net}/java/android/net/dhcp/DhcpNakPacket.java | 0 .../net}/java/android/net/dhcp/DhcpOfferPacket.java | 0 .../net}/java/android/net/dhcp/DhcpPacket.java | 1 + .../net}/java/android/net/dhcp/DhcpRequestPacket.java | 0 .../net}/java/android/net/dhcp/DhcpStateMachine.java | 0 11 files changed, 12 insertions(+) create mode 100644 services/net/Android.mk rename {core => services/net}/java/android/net/dhcp/DhcpAckPacket.java (100%) rename {core => services/net}/java/android/net/dhcp/DhcpDeclinePacket.java (100%) rename {core => services/net}/java/android/net/dhcp/DhcpDiscoverPacket.java (100%) rename {core => services/net}/java/android/net/dhcp/DhcpInformPacket.java (100%) rename {core => services/net}/java/android/net/dhcp/DhcpNakPacket.java (100%) rename {core => services/net}/java/android/net/dhcp/DhcpOfferPacket.java (100%) rename {core => services/net}/java/android/net/dhcp/DhcpPacket.java (99%) rename {core => services/net}/java/android/net/dhcp/DhcpRequestPacket.java (100%) rename {core => services/net}/java/android/net/dhcp/DhcpStateMachine.java (100%) diff --git a/services/Android.mk b/services/Android.mk index 3c94f437778d4..e4b0cbb7d1836 100644 --- a/services/Android.mk +++ b/services/Android.mk @@ -24,6 +24,7 @@ services := \ appwidget \ backup \ devicepolicy \ + net \ print \ restrictions \ usage \ diff --git a/services/net/Android.mk b/services/net/Android.mk new file mode 100644 index 0000000000000..336bc45c6ab7a --- /dev/null +++ b/services/net/Android.mk @@ -0,0 +1,10 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := services.net + +LOCAL_SRC_FILES += \ + $(call all-java-files-under,java) + +include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/core/java/android/net/dhcp/DhcpAckPacket.java b/services/net/java/android/net/dhcp/DhcpAckPacket.java similarity index 100% rename from core/java/android/net/dhcp/DhcpAckPacket.java rename to services/net/java/android/net/dhcp/DhcpAckPacket.java diff --git a/core/java/android/net/dhcp/DhcpDeclinePacket.java b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java similarity index 100% rename from core/java/android/net/dhcp/DhcpDeclinePacket.java rename to services/net/java/android/net/dhcp/DhcpDeclinePacket.java diff --git a/core/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java similarity index 100% rename from core/java/android/net/dhcp/DhcpDiscoverPacket.java rename to services/net/java/android/net/dhcp/DhcpDiscoverPacket.java diff --git a/core/java/android/net/dhcp/DhcpInformPacket.java b/services/net/java/android/net/dhcp/DhcpInformPacket.java similarity index 100% rename from core/java/android/net/dhcp/DhcpInformPacket.java rename to services/net/java/android/net/dhcp/DhcpInformPacket.java diff --git a/core/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java similarity index 100% rename from core/java/android/net/dhcp/DhcpNakPacket.java rename to services/net/java/android/net/dhcp/DhcpNakPacket.java diff --git a/core/java/android/net/dhcp/DhcpOfferPacket.java b/services/net/java/android/net/dhcp/DhcpOfferPacket.java similarity index 100% rename from core/java/android/net/dhcp/DhcpOfferPacket.java rename to services/net/java/android/net/dhcp/DhcpOfferPacket.java diff --git a/core/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java similarity index 99% rename from core/java/android/net/dhcp/DhcpPacket.java rename to services/net/java/android/net/dhcp/DhcpPacket.java index c7c25f0e9ffb4..68108fe792dcb 100644 --- a/core/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -8,6 +8,7 @@ import java.nio.charset.StandardCharsets; import java.nio.ShortBuffer; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** diff --git a/core/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java similarity index 100% rename from core/java/android/net/dhcp/DhcpRequestPacket.java rename to services/net/java/android/net/dhcp/DhcpRequestPacket.java diff --git a/core/java/android/net/dhcp/DhcpStateMachine.java b/services/net/java/android/net/dhcp/DhcpStateMachine.java similarity index 100% rename from core/java/android/net/dhcp/DhcpStateMachine.java rename to services/net/java/android/net/dhcp/DhcpStateMachine.java From c8a0f49feecaf231e3f5972bd247dfbc586ccb34 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sat, 14 Mar 2015 13:52:18 +0900 Subject: [PATCH 10/29] DHCP: Minor cleanups to the packet code. 1. Delete the DhcpStateMachine, since we don't plan to use it. 2. Make all InetAddresses Inet4Addresses, since that's what they are. In order to do this, define INADDR_ANY and INADDR_BROADCAST, constants, since Inet4Address.{ANY,ALL} are not Inet4Addresses but InetAddresses. Bug: 19704592 Change-Id: I5a0499be889076992a60aaad0bd8be5ea66bd560 --- .../java/android/net/dhcp/DhcpAckPacket.java | 24 ++-- .../android/net/dhcp/DhcpDeclinePacket.java | 13 +-- .../android/net/dhcp/DhcpDiscoverPacket.java | 19 +-- .../android/net/dhcp/DhcpInformPacket.java | 17 +-- .../java/android/net/dhcp/DhcpNakPacket.java | 18 +-- .../android/net/dhcp/DhcpOfferPacket.java | 24 ++-- .../net/java/android/net/dhcp/DhcpPacket.java | 108 +++++++++--------- .../android/net/dhcp/DhcpRequestPacket.java | 20 +--- .../android/net/dhcp/DhcpStateMachine.java | 74 ------------ 9 files changed, 83 insertions(+), 234 deletions(-) delete mode 100644 services/net/java/android/net/dhcp/DhcpStateMachine.java diff --git a/services/net/java/android/net/dhcp/DhcpAckPacket.java b/services/net/java/android/net/dhcp/DhcpAckPacket.java index 7b8be9c80d772..25b80936f944f 100644 --- a/services/net/java/android/net/dhcp/DhcpAckPacket.java +++ b/services/net/java/android/net/dhcp/DhcpAckPacket.java @@ -16,7 +16,6 @@ package android.net.dhcp; -import java.net.InetAddress; import java.net.Inet4Address; import java.nio.ByteBuffer; @@ -28,12 +27,11 @@ class DhcpAckPacket extends DhcpPacket { /** * The address of the server which sent this packet. */ - private final InetAddress mSrcIp; + private final Inet4Address mSrcIp; - DhcpAckPacket(int transId, boolean broadcast, InetAddress serverAddress, - InetAddress clientIp, byte[] clientMac) { - super(transId, Inet4Address.ANY, clientIp, serverAddress, - Inet4Address.ANY, clientMac, broadcast); + DhcpAckPacket(int transId, boolean broadcast, Inet4Address serverAddress, + Inet4Address clientIp, byte[] clientMac) { + super(transId, INADDR_ANY, clientIp, serverAddress, INADDR_ANY, clientMac, broadcast); mBroadcast = broadcast; mSrcIp = serverAddress; } @@ -42,7 +40,7 @@ class DhcpAckPacket extends DhcpPacket { String s = super.toString(); String dnsServers = " DNS servers: "; - for (InetAddress dnsServer: mDnsServers) { + for (Inet4Address dnsServer: mDnsServers) { dnsServers += dnsServer.toString() + " "; } @@ -57,8 +55,8 @@ class DhcpAckPacket extends DhcpPacket { */ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); - InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp; - InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp; + Inet4Address destIp = mBroadcast ? INADDR_BROADCAST : mYourIp; + Inet4Address srcIp = mBroadcast ? INADDR_ANY : mSrcIp; fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result, DHCP_BOOTREPLY, mBroadcast); @@ -98,12 +96,4 @@ class DhcpAckPacket extends DhcpPacket { return v.intValue(); } } - - /** - * Notifies the specified state machine of the ACK packet parameters. - */ - public void doNextOp(DhcpStateMachine machine) { - machine.onAckReceived(mYourIp, mSubnetMask, mGateway, mDnsServers, - mServerIdentifier, getInt(mLeaseTime)); - } } diff --git a/services/net/java/android/net/dhcp/DhcpDeclinePacket.java b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java index 7646eb46999f9..9d985ac902136 100644 --- a/services/net/java/android/net/dhcp/DhcpDeclinePacket.java +++ b/services/net/java/android/net/dhcp/DhcpDeclinePacket.java @@ -16,7 +16,7 @@ package android.net.dhcp; -import java.net.InetAddress; +import java.net.Inet4Address; import java.nio.ByteBuffer; /** @@ -26,8 +26,8 @@ class DhcpDeclinePacket extends DhcpPacket { /** * Generates a DECLINE packet with the specified parameters. */ - DhcpDeclinePacket(int transId, InetAddress clientIp, InetAddress yourIp, - InetAddress nextIp, InetAddress relayIp, + DhcpDeclinePacket(int transId, Inet4Address clientIp, Inet4Address yourIp, + Inet4Address nextIp, Inet4Address relayIp, byte[] clientMac) { super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false); } @@ -55,11 +55,4 @@ class DhcpDeclinePacket extends DhcpPacket { void finishPacket(ByteBuffer buffer) { // None needed } - - /** - * Informs the state machine of the arrival of a DECLINE packet. - */ - public void doNextOp(DhcpStateMachine machine) { - machine.onDeclineReceived(mClientMac, mRequestedIp); - } } diff --git a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java index 0e2d39be71836..fba43e604dece 100644 --- a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java +++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java @@ -16,7 +16,6 @@ package android.net.dhcp; -import java.net.InetAddress; import java.net.Inet4Address; import java.nio.ByteBuffer; @@ -28,8 +27,7 @@ class DhcpDiscoverPacket extends DhcpPacket { * Generates a DISCOVER packet with the specified parameters. */ DhcpDiscoverPacket(int transId, byte[] clientMac, boolean broadcast) { - super(transId, Inet4Address.ANY, Inet4Address.ANY, Inet4Address.ANY, - Inet4Address.ANY, clientMac, broadcast); + super(transId, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast); } public String toString() { @@ -43,10 +41,8 @@ class DhcpDiscoverPacket extends DhcpPacket { */ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); - InetAddress destIp = Inet4Address.ALL; - - fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp, - result, DHCP_BOOTREQUEST, true); + fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp, + srcUdp, result, DHCP_BOOTREQUEST, true); result.flip(); return result; } @@ -59,13 +55,4 @@ class DhcpDiscoverPacket extends DhcpPacket { addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); addTlvEnd(buffer); } - - /** - * Informs the state machine of the arrival of a DISCOVER packet. - */ - public void doNextOp(DhcpStateMachine machine) { - // currently omitted: host name - machine.onDiscoverReceived(mBroadcast, mTransId, mClientMac, - mRequestedParams); - } } diff --git a/services/net/java/android/net/dhcp/DhcpInformPacket.java b/services/net/java/android/net/dhcp/DhcpInformPacket.java index da73216caaa93..8bc7cdd59c248 100644 --- a/services/net/java/android/net/dhcp/DhcpInformPacket.java +++ b/services/net/java/android/net/dhcp/DhcpInformPacket.java @@ -16,7 +16,7 @@ package android.net.dhcp; -import java.net.InetAddress; +import java.net.Inet4Address; import java.nio.ByteBuffer; /** @@ -26,8 +26,8 @@ class DhcpInformPacket extends DhcpPacket { /** * Generates an INFORM packet with the specified parameters. */ - DhcpInformPacket(int transId, InetAddress clientIp, InetAddress yourIp, - InetAddress nextIp, InetAddress relayIp, + DhcpInformPacket(int transId, Inet4Address clientIp, Inet4Address yourIp, + Inet4Address nextIp, Inet4Address relayIp, byte[] clientMac) { super(transId, clientIp, yourIp, nextIp, relayIp, clientMac, false); } @@ -62,15 +62,4 @@ class DhcpInformPacket extends DhcpPacket { addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); addTlvEnd(buffer); } - - /** - * Informs the state machine of the arrival of an INFORM packet. Not - * used currently. - */ - public void doNextOp(DhcpStateMachine machine) { - InetAddress clientRequest = - mRequestedIp == null ? mClientIp : mRequestedIp; - machine.onInformReceived(mTransId, mClientMac, clientRequest, - mRequestedParams); - } } diff --git a/services/net/java/android/net/dhcp/DhcpNakPacket.java b/services/net/java/android/net/dhcp/DhcpNakPacket.java index 1f340ad4f098f..1390ea7d10314 100644 --- a/services/net/java/android/net/dhcp/DhcpNakPacket.java +++ b/services/net/java/android/net/dhcp/DhcpNakPacket.java @@ -16,7 +16,6 @@ package android.net.dhcp; -import java.net.InetAddress; import java.net.Inet4Address; import java.nio.ByteBuffer; @@ -27,10 +26,10 @@ class DhcpNakPacket extends DhcpPacket { /** * Generates a NAK packet with the specified parameters. */ - DhcpNakPacket(int transId, InetAddress clientIp, InetAddress yourIp, - InetAddress nextIp, InetAddress relayIp, + DhcpNakPacket(int transId, Inet4Address clientIp, Inet4Address yourIp, + Inet4Address nextIp, Inet4Address relayIp, byte[] clientMac) { - super(transId, Inet4Address.ANY, Inet4Address.ANY, nextIp, relayIp, + super(transId, INADDR_ANY, INADDR_ANY, nextIp, relayIp, clientMac, false); } @@ -44,8 +43,8 @@ class DhcpNakPacket extends DhcpPacket { */ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); - InetAddress destIp = mClientIp; - InetAddress srcIp = mYourIp; + Inet4Address destIp = mClientIp; + Inet4Address srcIp = mYourIp; fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result, DHCP_BOOTREPLY, mBroadcast); @@ -62,11 +61,4 @@ class DhcpNakPacket extends DhcpPacket { addTlv(buffer, DHCP_MESSAGE, mMessage); addTlvEnd(buffer); } - - /** - * Notifies the specified state machine of the newly-arrived NAK packet. - */ - public void doNextOp(DhcpStateMachine machine) { - machine.onNakReceived(); - } } diff --git a/services/net/java/android/net/dhcp/DhcpOfferPacket.java b/services/net/java/android/net/dhcp/DhcpOfferPacket.java index f1c30e11675bb..b1f3bbd4a3df7 100644 --- a/services/net/java/android/net/dhcp/DhcpOfferPacket.java +++ b/services/net/java/android/net/dhcp/DhcpOfferPacket.java @@ -16,7 +16,6 @@ package android.net.dhcp; -import java.net.InetAddress; import java.net.Inet4Address; import java.nio.ByteBuffer; @@ -27,15 +26,14 @@ class DhcpOfferPacket extends DhcpPacket { /** * The IP address of the server which sent this packet. */ - private final InetAddress mSrcIp; + private final Inet4Address mSrcIp; /** * Generates a OFFER packet with the specified parameters. */ - DhcpOfferPacket(int transId, boolean broadcast, InetAddress serverAddress, - InetAddress clientIp, byte[] clientMac) { - super(transId, Inet4Address.ANY, clientIp, Inet4Address.ANY, - Inet4Address.ANY, clientMac, broadcast); + DhcpOfferPacket(int transId, boolean broadcast, Inet4Address serverAddress, + Inet4Address clientIp, byte[] clientMac) { + super(transId, INADDR_ANY, clientIp, INADDR_ANY, INADDR_ANY, clientMac, broadcast); mSrcIp = serverAddress; } @@ -44,7 +42,7 @@ class DhcpOfferPacket extends DhcpPacket { String dnsServers = ", DNS servers: "; if (mDnsServers != null) { - for (InetAddress dnsServer: mDnsServers) { + for (Inet4Address dnsServer: mDnsServers) { dnsServers += dnsServer + " "; } } @@ -59,8 +57,8 @@ class DhcpOfferPacket extends DhcpPacket { */ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); - InetAddress destIp = mBroadcast ? Inet4Address.ALL : mYourIp; - InetAddress srcIp = mBroadcast ? Inet4Address.ANY : mSrcIp; + Inet4Address destIp = mBroadcast ? INADDR_BROADCAST : mYourIp; + Inet4Address srcIp = mBroadcast ? INADDR_ANY : mSrcIp; fillInPacket(encap, destIp, srcIp, destUdp, srcUdp, result, DHCP_BOOTREPLY, mBroadcast); @@ -89,12 +87,4 @@ class DhcpOfferPacket extends DhcpPacket { addTlv(buffer, DHCP_DNS_SERVER, mDnsServers); addTlvEnd(buffer); } - - /** - * Notifies the state machine of the OFFER packet parameters. - */ - public void doNextOp(DhcpStateMachine machine) { - machine.onOfferReceived(mBroadcast, mTransId, mClientMac, mYourIp, - mServerIdentifier); - } } diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index 68108fe792dcb..238484865013f 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -1,6 +1,6 @@ package android.net.dhcp; -import java.net.InetAddress; +import java.net.Inet4Address; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -19,6 +19,9 @@ import java.util.List; abstract class DhcpPacket { protected static final String TAG = "DhcpPacket"; + public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY; + public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL; + /** * Packet encapsulations. */ @@ -86,19 +89,19 @@ abstract class DhcpPacket { * DHCP Optional Type: DHCP Subnet Mask */ protected static final byte DHCP_SUBNET_MASK = 1; - protected InetAddress mSubnetMask; + protected Inet4Address mSubnetMask; /** * DHCP Optional Type: DHCP Router */ protected static final byte DHCP_ROUTER = 3; - protected InetAddress mGateway; + protected Inet4Address mGateway; /** * DHCP Optional Type: DHCP DNS Server */ protected static final byte DHCP_DNS_SERVER = 6; - protected List mDnsServers; + protected List mDnsServers; /** * DHCP Optional Type: DHCP Host Name @@ -116,13 +119,13 @@ abstract class DhcpPacket { * DHCP Optional Type: DHCP BROADCAST ADDRESS */ protected static final byte DHCP_BROADCAST_ADDRESS = 28; - protected InetAddress mBroadcastAddress; + protected Inet4Address mBroadcastAddress; /** * DHCP Optional Type: DHCP Requested IP Address */ protected static final byte DHCP_REQUESTED_IP = 50; - protected InetAddress mRequestedIp; + protected Inet4Address mRequestedIp; /** * DHCP Optional Type: DHCP Lease Time @@ -147,7 +150,7 @@ abstract class DhcpPacket { * DHCP Optional Type: DHCP Server Identifier */ protected static final byte DHCP_SERVER_IDENTIFIER = 54; - protected InetAddress mServerIdentifier; + protected Inet4Address mServerIdentifier; /** * DHCP Optional Type: DHCP Parameter List @@ -186,10 +189,10 @@ abstract class DhcpPacket { * proposed by the client (from an earlier DHCP negotiation) or * supplied by the server. */ - protected final InetAddress mClientIp; - protected final InetAddress mYourIp; - private final InetAddress mNextIp; - private final InetAddress mRelayIp; + protected final Inet4Address mClientIp; + protected final Inet4Address mYourIp; + private final Inet4Address mNextIp; + private final Inet4Address mRelayIp; /** * Does the client request a broadcast response? @@ -201,13 +204,6 @@ abstract class DhcpPacket { */ protected final byte[] mClientMac; - /** - * Asks the packet object to signal the next operation in the DHCP - * protocol. The available actions are methods defined in the - * DhcpStateMachine interface. - */ - public abstract void doNextOp(DhcpStateMachine stateMachine); - /** * Asks the packet object to create a ByteBuffer serialization of * the packet for transmission. @@ -221,8 +217,8 @@ abstract class DhcpPacket { */ abstract void finishPacket(ByteBuffer buffer); - protected DhcpPacket(int transId, InetAddress clientIp, InetAddress yourIp, - InetAddress nextIp, InetAddress relayIp, + protected DhcpPacket(int transId, Inet4Address clientIp, Inet4Address yourIp, + Inet4Address nextIp, Inet4Address relayIp, byte[] clientMac, boolean broadcast) { mTransId = transId; mClientIp = clientIp; @@ -245,8 +241,8 @@ abstract class DhcpPacket { * DHCP udp packet. This method relies upon the delegated method * finishPacket() to insert the per-packet contents. */ - protected void fillInPacket(int encap, InetAddress destIp, - InetAddress srcIp, short destUdp, short srcUdp, ByteBuffer buf, + protected void fillInPacket(int encap, Inet4Address destIp, + Inet4Address srcIp, short destUdp, short srcUdp, ByteBuffer buf, byte requestCode, boolean broadcast) { byte[] destIpArray = destIp.getAddress(); byte[] srcIpArray = srcIp.getAddress(); @@ -433,7 +429,7 @@ abstract class DhcpPacket { /** * Adds an optional parameter containing an IP address. */ - protected void addTlv(ByteBuffer buf, byte type, InetAddress addr) { + protected void addTlv(ByteBuffer buf, byte type, Inet4Address addr) { if (addr != null) { addTlv(buf, type, addr.getAddress()); } @@ -442,12 +438,12 @@ abstract class DhcpPacket { /** * Adds an optional parameter containing a list of IP addresses. */ - protected void addTlv(ByteBuffer buf, byte type, List addrs) { + protected void addTlv(ByteBuffer buf, byte type, List addrs) { if (addrs != null && addrs.size() > 0) { buf.put(type); buf.put((byte)(4 * addrs.size())); - for (InetAddress addr : addrs) { + for (Inet4Address addr : addrs) { buf.put(addr.getAddress()); } } @@ -516,13 +512,13 @@ abstract class DhcpPacket { * Reads a four-octet value from a ByteBuffer and construct * an IPv4 address from that value. */ - private static InetAddress readIpAddress(ByteBuffer packet) { - InetAddress result = null; + private static Inet4Address readIpAddress(ByteBuffer packet) { + Inet4Address result = null; byte[] ipAddr = new byte[4]; packet.get(ipAddr); try { - result = InetAddress.getByAddress(ipAddr); + result = (Inet4Address) Inet4Address.getByAddress(ipAddr); } catch (UnknownHostException ex) { // ipAddr is numeric, so this should not be // triggered. However, if it is, just nullify @@ -554,25 +550,25 @@ abstract class DhcpPacket { { // bootp parameters int transactionId; - InetAddress clientIp; - InetAddress yourIp; - InetAddress nextIp; - InetAddress relayIp; + Inet4Address clientIp; + Inet4Address yourIp; + Inet4Address nextIp; + Inet4Address relayIp; byte[] clientMac; - List dnsServers = new ArrayList(); - InetAddress gateway = null; // aka router + List dnsServers = new ArrayList(); + Inet4Address gateway = null; // aka router Integer leaseTime = null; - InetAddress serverIdentifier = null; - InetAddress netMask = null; + Inet4Address serverIdentifier = null; + Inet4Address netMask = null; String message = null; String vendorId = null; byte[] expectedParams = null; String hostName = null; String domainName = null; - InetAddress ipSrc = null; - InetAddress ipDst = null; - InetAddress bcAddr = null; - InetAddress requestedIp = null; + Inet4Address ipSrc = null; + Inet4Address ipDst = null; + Inet4Address bcAddr = null; + Inet4Address requestedIp = null; // dhcp options byte dhcpType = (byte) 0xFF; @@ -636,13 +632,13 @@ abstract class DhcpPacket { try { packet.get(ipv4addr); - clientIp = InetAddress.getByAddress(ipv4addr); + clientIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); packet.get(ipv4addr); - yourIp = InetAddress.getByAddress(ipv4addr); + yourIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); packet.get(ipv4addr); - nextIp = InetAddress.getByAddress(ipv4addr); + nextIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); packet.get(ipv4addr); - relayIp = InetAddress.getByAddress(ipv4addr); + relayIp = (Inet4Address) Inet4Address.getByAddress(ipv4addr); } catch (UnknownHostException ex) { return null; } @@ -829,10 +825,10 @@ abstract class DhcpPacket { * parameters. */ public static ByteBuffer buildOfferPacket(int encap, int transactionId, - boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr, - byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr, - InetAddress gateway, List dnsServers, - InetAddress dhcpServerIdentifier, String domainName) { + boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, + byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, + Inet4Address gateway, List dnsServers, + Inet4Address dhcpServerIdentifier, String domainName) { DhcpPacket pkt = new DhcpOfferPacket( transactionId, broadcast, serverIpAddr, clientIpAddr, mac); pkt.mGateway = gateway; @@ -849,10 +845,10 @@ abstract class DhcpPacket { * Builds a DHCP-ACK packet from the required specified parameters. */ public static ByteBuffer buildAckPacket(int encap, int transactionId, - boolean broadcast, InetAddress serverIpAddr, InetAddress clientIpAddr, - byte[] mac, Integer timeout, InetAddress netMask, InetAddress bcAddr, - InetAddress gateway, List dnsServers, - InetAddress dhcpServerIdentifier, String domainName) { + boolean broadcast, Inet4Address serverIpAddr, Inet4Address clientIpAddr, + byte[] mac, Integer timeout, Inet4Address netMask, Inet4Address bcAddr, + Inet4Address gateway, List dnsServers, + Inet4Address dhcpServerIdentifier, String domainName) { DhcpPacket pkt = new DhcpAckPacket( transactionId, broadcast, serverIpAddr, clientIpAddr, mac); pkt.mGateway = gateway; @@ -869,7 +865,7 @@ abstract class DhcpPacket { * Builds a DHCP-NAK packet from the required specified parameters. */ public static ByteBuffer buildNakPacket(int encap, int transactionId, - InetAddress serverIpAddr, InetAddress clientIpAddr, byte[] mac) { + Inet4Address serverIpAddr, Inet4Address clientIpAddr, byte[] mac) { DhcpPacket pkt = new DhcpNakPacket(transactionId, clientIpAddr, serverIpAddr, serverIpAddr, serverIpAddr, mac); pkt.mMessage = "requested address not available"; @@ -881,9 +877,9 @@ abstract class DhcpPacket { * Builds a DHCP-REQUEST packet from the required specified parameters. */ public static ByteBuffer buildRequestPacket(int encap, - int transactionId, InetAddress clientIp, boolean broadcast, - byte[] clientMac, InetAddress requestedIpAddress, - InetAddress serverIdentifier, byte[] requestedParams, String hostName) { + int transactionId, Inet4Address clientIp, boolean broadcast, + byte[] clientMac, Inet4Address requestedIpAddress, + Inet4Address serverIdentifier, byte[] requestedParams, String hostName) { DhcpPacket pkt = new DhcpRequestPacket(transactionId, clientIp, clientMac, broadcast); pkt.mRequestedIp = requestedIpAddress; diff --git a/services/net/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java index cf32957fd3bd1..337fdf05bd24c 100644 --- a/services/net/java/android/net/dhcp/DhcpRequestPacket.java +++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java @@ -18,7 +18,6 @@ package android.net.dhcp; import android.util.Log; -import java.net.InetAddress; import java.net.Inet4Address; import java.nio.ByteBuffer; @@ -29,10 +28,9 @@ class DhcpRequestPacket extends DhcpPacket { /** * Generates a REQUEST packet with the specified parameters. */ - DhcpRequestPacket(int transId, InetAddress clientIp, byte[] clientMac, + DhcpRequestPacket(int transId, Inet4Address clientIp, byte[] clientMac, boolean broadcast) { - super(transId, clientIp, Inet4Address.ANY, Inet4Address.ANY, - Inet4Address.ANY, clientMac, broadcast); + super(transId, clientIp, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast); } public String toString() { @@ -48,7 +46,7 @@ class DhcpRequestPacket extends DhcpPacket { public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); - fillInPacket(encap, Inet4Address.ALL, Inet4Address.ANY, destUdp, srcUdp, + fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp, srcUdp, result, DHCP_BOOTREQUEST, mBroadcast); result.flip(); return result; @@ -71,16 +69,4 @@ class DhcpRequestPacket extends DhcpPacket { addTlv(buffer, DHCP_CLIENT_IDENTIFIER, clientId); addTlvEnd(buffer); } - - /** - * Notifies the specified state machine of the REQUEST packet parameters. - */ - public void doNextOp(DhcpStateMachine machine) { - InetAddress clientRequest = - mRequestedIp == null ? mClientIp : mRequestedIp; - Log.v(TAG, "requested IP is " + mRequestedIp + " and client IP is " + - mClientIp); - machine.onRequestReceived(mBroadcast, mTransId, mClientMac, - clientRequest, mRequestedParams, mHostName); - } } diff --git a/services/net/java/android/net/dhcp/DhcpStateMachine.java b/services/net/java/android/net/dhcp/DhcpStateMachine.java deleted file mode 100644 index bc9a7988c8942..0000000000000 --- a/services/net/java/android/net/dhcp/DhcpStateMachine.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.dhcp; - -import java.net.InetAddress; -import java.util.List; - -/** - * This class defines the "next steps" which occur after a given DHCP - * packet has been received. - */ -interface DhcpStateMachine { - /** - * Signals that an offer packet has been received with the specified - * parameters. - */ - public void onOfferReceived(boolean broadcast, int transactionId, - byte[] myMac, InetAddress offeredIpAddress, - InetAddress serverIpAddress); - - /** - * Signals that a NAK packet has been received. - */ - public void onNakReceived(); - - /** - * Signals that the final ACK has been received from the server. - */ - public void onAckReceived(InetAddress myIpAddress, InetAddress myNetMask, - InetAddress myGateway, List myDnsServers, - InetAddress myDhcpServer, int leaseTime); - - /** - * Signals that a client's DISCOVER packet has been received with the - * specified parameters. - */ - public void onDiscoverReceived(boolean broadcast, int transactionId, - byte[] clientMac, byte[] requestedParameterList); - - /** - * Signals that a client's REQUEST packet has been received with the - * specified parameters. - */ - public void onRequestReceived(boolean broadcast, int transactionId, - byte[] clientMac, InetAddress requestedIp, byte[] requestedParams, - String clientHostName); - - /** - * Signals that a client's INFORM packet has been received with the - * specified parameters. - */ - public void onInformReceived(int transactionId, byte[] clientMac, - InetAddress preassignedIp, byte[] requestedParams); - - /** - * Signals that a client's DECLINE packet has been received with the - * specified parameters. - */ - public void onDeclineReceived(byte[] clientMac, InetAddress declinedIp); -} From 15204d50b4220f98e4144567a9cfa4418cc9763a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 12 Mar 2015 22:36:49 +0900 Subject: [PATCH 11/29] DHCP: Ethernet/IP packet header changes. 1. Support L2_ENCAP when building packets as well as when parsing. 2. Skip IP options when parsing DHCP packets. Bug: 19704592 Change-Id: Ic27a45790ed1cf7cf5b82d63b6c0b64c909a570f --- .../net/java/android/net/dhcp/DhcpPacket.java | 38 +++++++++++++++---- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index 238484865013f..a4d0ec436e9cf 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -1,5 +1,7 @@ package android.net.dhcp; +import android.system.OsConstants; + import java.net.Inet4Address; import java.net.UnknownHostException; import java.nio.ByteBuffer; @@ -21,6 +23,10 @@ abstract class DhcpPacket { public static final Inet4Address INADDR_ANY = (Inet4Address) Inet4Address.ANY; public static final Inet4Address INADDR_BROADCAST = (Inet4Address) Inet4Address.ALL; + public static final byte[] ETHER_BROADCAST = new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, + }; /** * Packet encapsulations. @@ -246,6 +252,7 @@ abstract class DhcpPacket { byte requestCode, boolean broadcast) { byte[] destIpArray = destIp.getAddress(); byte[] srcIpArray = srcIp.getAddress(); + int ipHeaderOffset = 0; int ipLengthOffset = 0; int ipChecksumOffset = 0; int endIpHeader = 0; @@ -256,11 +263,17 @@ abstract class DhcpPacket { buf.clear(); buf.order(ByteOrder.BIG_ENDIAN); + if (encap == ENCAP_L2) { + buf.put(ETHER_BROADCAST); + buf.put(mClientMac); + buf.putShort((short) OsConstants.ETH_P_IP); + } + // if a full IP packet needs to be generated, put the IP & UDP // headers in place, and pre-populate with artificial values // needed to seed the IP checksum. - if (encap == ENCAP_L3) { - // fake IP header, used in the IP-header checksum + if (encap <= ENCAP_L3) { + ipHeaderOffset = buf.position(); buf.put(IP_VERSION_HEADER_LEN); buf.put(IP_TOS_LOWDELAY); // tos: IPTOS_LOWDELAY ipLengthOffset = buf.position(); @@ -319,7 +332,7 @@ abstract class DhcpPacket { // If an IP packet is being built, the IP & UDP checksums must be // computed. - if (encap == ENCAP_L3) { + if (encap <= ENCAP_L3) { // fix UDP header: insert length short udpLen = (short)(buf.position() - udpHeaderOffset); buf.putShort(udpLengthOffset, udpLen); @@ -342,10 +355,10 @@ abstract class DhcpPacket { udpHeaderOffset, buf.position())); // fix IP header: insert length - buf.putShort(ipLengthOffset, (short)buf.position()); + buf.putShort(ipLengthOffset, (short)(buf.position() - ipHeaderOffset)); // fixup IP-header checksum buf.putShort(ipChecksumOffset, - (short) checksum(buf, 0, 0, endIpHeader)); + (short) checksum(buf, 0, ipHeaderOffset, endIpHeader)); } } @@ -586,13 +599,18 @@ abstract class DhcpPacket { short l2type = packet.getShort(); - if (l2type != 0x0800) + if (l2type != OsConstants.ETH_P_IP) return null; } if ((pktType == ENCAP_L2) || (pktType == ENCAP_L3)) { // assume l2type is 0x0800, i.e. IP - byte ipType = packet.get(); + byte ipTypeAndLength = packet.get(); + int ipVersion = (ipTypeAndLength & 0xf0) >> 4; + if (ipVersion != 4) { + return null; + } + // System.out.println("ipType is " + ipType); byte ipDiffServicesField = packet.get(); short ipTotalLength = packet.getShort(); @@ -609,6 +627,12 @@ abstract class DhcpPacket { if (ipProto != IP_TYPE_UDP) // UDP return null; + // Skip options. + int optionWords = ((ipTypeAndLength & 0x0f) - 5); + for (int i = 0; i < optionWords; i++) { + packet.getInt(); + } + // assume UDP short udpSrcPort = packet.getShort(); short udpDstPort = packet.getShort(); From 29cb944bef7b56ef4b657cd7f2d0c2be96d670d6 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 11 Mar 2015 01:16:18 +0900 Subject: [PATCH 12/29] DHCP: glue code. 1. Add a method to make a DhcpResults object from a DHCP packet. 2. Add a method to fetch the client MAC from the packet. This is needed to check that the message is for us (lots of DHCP messages are broadcast). 3. Add a length argument to the method that parses DHCP packets, so the caller can use the same MTU-sized array all the time instead of having to pass in a new array for every packet. Bug: 19704592 Change-Id: I58223f5ec90fb5c762bc2934649e02f9122018b2 --- .../net/java/android/net/dhcp/DhcpPacket.java | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index a4d0ec436e9cf..b825a39081972 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -1,5 +1,10 @@ package android.net.dhcp; +import android.net.DhcpResults; +import android.net.LinkAddress; +import android.net.NetworkUtils; +import android.os.Build; +import android.os.SystemProperties; import android.system.OsConstants; import java.net.Inet4Address; @@ -27,6 +32,8 @@ abstract class DhcpPacket { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, }; + // Minimum length of a DHCP packet w/o options: Ethernet header, IP header, fixed bootp format. + public static final int MIN_PACKET_LENGTH_L2 = 14 + 20 + 300; /** * Packet encapsulations. @@ -179,6 +186,7 @@ abstract class DhcpPacket { * DHCP Optional Type: Vendor Class Identifier */ protected static final byte DHCP_VENDOR_CLASS_ID = 60; + protected String mVendorId; /** * DHCP Optional Type: DHCP Client Identifier @@ -242,6 +250,13 @@ abstract class DhcpPacket { return mTransId; } + /** + * Returns the client MAC. + */ + public byte[] getClientMac() { + return mClientMac; + } + /** * Creates a new L3 packet (including IP header) containing the * DHCP udp packet. This method relies upon the delegated method @@ -820,18 +835,58 @@ abstract class DhcpPacket { newPacket.mRequestedParams = expectedParams; newPacket.mServerIdentifier = serverIdentifier; newPacket.mSubnetMask = netMask; + newPacket.mVendorId = vendorId; return newPacket; } /** - * Parse a packet from an array of bytes. + * Parse a packet from an array of bytes, stopping at the given length. */ - public static DhcpPacket decodeFullPacket(byte[] packet, int pktType) + public static DhcpPacket decodeFullPacket(byte[] packet, int length, int pktType) { - ByteBuffer buffer = ByteBuffer.wrap(packet).order(ByteOrder.BIG_ENDIAN); + ByteBuffer buffer = ByteBuffer.wrap(packet, 0, length).order(ByteOrder.BIG_ENDIAN); return decodeFullPacket(buffer, pktType); } + /** + * Construct a DhcpResults object from a DHCP reply packet. + */ + public DhcpResults toDhcpResults() { + Inet4Address ipAddress = mYourIp; + if (ipAddress == Inet4Address.ANY) { + ipAddress = mClientIp; + if (ipAddress == Inet4Address.ANY) { + return null; + } + } + + int prefixLength; + if (mSubnetMask != null) { + try { + prefixLength = NetworkUtils.netmaskToPrefixLength(mSubnetMask); + } catch (IllegalArgumentException e) { + // Non-contiguous netmask. + return null; + } + } else { + prefixLength = NetworkUtils.getImplicitNetmask(ipAddress); + } + + DhcpResults results = new DhcpResults(); + try { + results.ipAddress = new LinkAddress(ipAddress, prefixLength); + } catch (IllegalArgumentException e) { + return null; + } + results.gateway = mGateway; + results.dnsServers.addAll(mDnsServers); + results.domains = mDomainName; + results.serverAddress = mServerIdentifier; + results.vendorInfo = mVendorId; + results.leaseDuration = mLeaseTime; + return results; + } + /** * Builds a DHCP-DISCOVER packet from the required specified * parameters. From 04444427d0f3421fc9791842bdce834ffed448cc Mon Sep 17 00:00:00 2001 From: Vinit Deshpande Date: Wed, 11 Mar 2015 17:43:04 -0700 Subject: [PATCH 13/29] Improve passpoint configuration validation Change-Id: I717242b2f8b2e7d0f84c3a7c74c4672289387151 --- wifi/java/android/net/wifi/WifiConfiguration.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 872eb6f2de705..943af10867056 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -926,13 +926,18 @@ public class WifiConfiguration implements Parcelable { } } - if (FQDN != null) { - /* must have a providerFriendlyName */ - if (providerFriendlyName == null) { + if (TextUtils.isEmpty(FQDN) == false) { + /* this is passpoint configuration; it must not have an SSID */ + if (TextUtils.isEmpty(SSID) == false) { + return false; + } + /* this is passpoint configuration; it must have a providerFriendlyName */ + if (TextUtils.isEmpty(providerFriendlyName)) { return false; } /* this is passpoint configuration; it must have enterprise config */ - if (enterpriseConfig == null) { + if (enterpriseConfig == null + || enterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.NONE ) { return false; } } From 04b8d3aab6acdf382c74d12a89b5fc50fd8d0158 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 11 Mar 2015 00:01:25 +0900 Subject: [PATCH 14/29] DHCP: protocol changes. 1. Define and add parsing code for MTU, max message size, T1, T2. 2. Add common TLVs (message size, hostname, vendor ID) to all packets sent by the client. 3. Don't include requested IP and server ID in renew messages, since the RFC says MUST NOT. 4. Don't hardcode the broadcast flag to true in DISCOVER packets, use what the caller passed in. 5. Make some methods static. Bug: 19704592 Change-Id: I42a0997e468b12e19cad9b403b98fe266e6cea73 --- .../android/net/dhcp/DhcpDiscoverPacket.java | 3 +- .../net/java/android/net/dhcp/DhcpPacket.java | 95 ++++++++++++++++--- .../android/net/dhcp/DhcpRequestPacket.java | 11 ++- 3 files changed, 91 insertions(+), 18 deletions(-) diff --git a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java index fba43e604dece..a031080d9a985 100644 --- a/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java +++ b/services/net/java/android/net/dhcp/DhcpDiscoverPacket.java @@ -42,7 +42,7 @@ class DhcpDiscoverPacket extends DhcpPacket { public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp, - srcUdp, result, DHCP_BOOTREQUEST, true); + srcUdp, result, DHCP_BOOTREQUEST, mBroadcast); result.flip(); return result; } @@ -52,6 +52,7 @@ class DhcpDiscoverPacket extends DhcpPacket { */ void finishPacket(ByteBuffer buffer) { addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_DISCOVER); + addCommonClientTlvs(buffer); addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); addTlvEnd(buffer); } diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index b825a39081972..fd18513443fd7 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -9,6 +9,7 @@ import android.system.OsConstants; import java.net.Inet4Address; import java.net.UnknownHostException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; @@ -32,8 +33,6 @@ abstract class DhcpPacket { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, }; - // Minimum length of a DHCP packet w/o options: Ethernet header, IP header, fixed bootp format. - public static final int MIN_PACKET_LENGTH_L2 = 14 + 20 + 300; /** * Packet encapsulations. @@ -128,6 +127,12 @@ abstract class DhcpPacket { protected static final byte DHCP_DOMAIN_NAME = 15; protected String mDomainName; + /** + * DHCP Optional Type: DHCP Interface MTU + */ + protected static final byte DHCP_MTU = 26; + protected Short mMtu; + /** * DHCP Optional Type: DHCP BROADCAST ADDRESS */ @@ -177,10 +182,23 @@ abstract class DhcpPacket { protected static final byte DHCP_MESSAGE = 56; protected String mMessage; + /** + * DHCP Optional Type: Maximum DHCP Message Size + */ + protected static final byte DHCP_MAX_MESSAGE_SIZE = 57; + protected Short mMaxMessageSize; + /** * DHCP Optional Type: DHCP Renewal Time Value */ protected static final byte DHCP_RENEWAL_TIME = 58; + protected Integer mT1; + + /** + * DHCP Optional Type: Rebinding Time Value + */ + protected static final byte DHCP_REBINDING_TIME = 59; + protected Integer mT2; /** * DHCP Optional Type: Vendor Class Identifier @@ -437,7 +455,7 @@ abstract class DhcpPacket { /** * Adds an optional parameter containing a single byte value. */ - protected void addTlv(ByteBuffer buf, byte type, byte value) { + protected static void addTlv(ByteBuffer buf, byte type, byte value) { buf.put(type); buf.put((byte) 1); buf.put(value); @@ -446,7 +464,7 @@ abstract class DhcpPacket { /** * Adds an optional parameter containing an array of bytes. */ - protected void addTlv(ByteBuffer buf, byte type, byte[] payload) { + protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) { if (payload != null) { buf.put(type); buf.put((byte) payload.length); @@ -457,7 +475,7 @@ abstract class DhcpPacket { /** * Adds an optional parameter containing an IP address. */ - protected void addTlv(ByteBuffer buf, byte type, Inet4Address addr) { + protected static void addTlv(ByteBuffer buf, byte type, Inet4Address addr) { if (addr != null) { addTlv(buf, type, addr.getAddress()); } @@ -466,7 +484,7 @@ abstract class DhcpPacket { /** * Adds an optional parameter containing a list of IP addresses. */ - protected void addTlv(ByteBuffer buf, byte type, List addrs) { + protected static void addTlv(ByteBuffer buf, byte type, List addrs) { if (addrs != null && addrs.size() > 0) { buf.put(type); buf.put((byte)(4 * addrs.size())); @@ -477,10 +495,21 @@ abstract class DhcpPacket { } } + /** + * Adds an optional parameter containing a short integer + */ + protected static void addTlv(ByteBuffer buf, byte type, Short value) { + if (value != null) { + buf.put(type); + buf.put((byte) 2); + buf.putShort(value.shortValue()); + } + } + /** * Adds an optional parameter containing a simple integer */ - protected void addTlv(ByteBuffer buf, byte type, Integer value) { + protected static void addTlv(ByteBuffer buf, byte type, Integer value) { if (value != null) { buf.put(type); buf.put((byte) 4); @@ -491,7 +520,7 @@ abstract class DhcpPacket { /** * Adds an optional parameter containing and ASCII string. */ - protected void addTlv(ByteBuffer buf, byte type, String str) { + protected static void addTlv(ByteBuffer buf, byte type, String str) { if (str != null) { buf.put(type); buf.put((byte) str.length()); @@ -505,10 +534,22 @@ abstract class DhcpPacket { /** * Adds the special end-of-optional-parameters indicator. */ - protected void addTlvEnd(ByteBuffer buf) { + protected static void addTlvEnd(ByteBuffer buf) { buf.put((byte) 0xFF); } + /** + * Adds common client TLVs. + * + * TODO: Does this belong here? The alternative would be to modify all the buildXyzPacket + * methods to take them. + */ + protected void addCommonClientTlvs(ByteBuffer buf) { + addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH); + addTlv(buf, DHCP_VENDOR_CLASS_ID, "android-dhcp-" + Build.VERSION.RELEASE); + addTlv(buf, DHCP_HOST_NAME, SystemProperties.get("net.hostname")); + } + /** * Converts a MAC from an array of octets to an ASCII string. */ @@ -585,7 +626,6 @@ abstract class DhcpPacket { byte[] clientMac; List dnsServers = new ArrayList(); Inet4Address gateway = null; // aka router - Integer leaseTime = null; Inet4Address serverIdentifier = null; Inet4Address netMask = null; String message = null; @@ -598,6 +638,16 @@ abstract class DhcpPacket { Inet4Address bcAddr = null; Inet4Address requestedIp = null; + // The following are all unsigned integers. Internally we store them as signed integers of + // the same length because that way we're guaranteed that they can't be out of the range of + // the unsigned field in the packet. Callers wanting to pass in an unsigned value will need + // to cast it. + Short mtu = null; + Short maxMessageSize = null; + Integer leaseTime = null; + Integer T1 = null; + Integer T2 = null; + // dhcp options byte dhcpType = (byte) 0xFF; @@ -605,7 +655,6 @@ abstract class DhcpPacket { // check to see if we need to parse L2, IP, and UDP encaps if (pktType == ENCAP_L2) { - // System.out.println("buffer len " + packet.limit()); byte[] l2dst = new byte[6]; byte[] l2src = new byte[6]; @@ -618,8 +667,7 @@ abstract class DhcpPacket { return null; } - if ((pktType == ENCAP_L2) || (pktType == ENCAP_L3)) { - // assume l2type is 0x0800, i.e. IP + if (pktType <= ENCAP_L3) { byte ipTypeAndLength = packet.get(); int ipVersion = (ipTypeAndLength & 0xf0) >> 4; if (ipVersion != 4) { @@ -658,7 +706,6 @@ abstract class DhcpPacket { return null; } - // assume bootp byte type = packet.get(); byte hwType = packet.get(); byte addrLen = packet.get(); @@ -728,6 +775,10 @@ abstract class DhcpPacket { expectedLen = optionLen; hostName = readAsciiString(packet, optionLen); break; + case DHCP_MTU: + expectedLen = 2; + mtu = Short.valueOf(packet.getShort()); + break; case DHCP_DOMAIN_NAME: expectedLen = optionLen; domainName = readAsciiString(packet, optionLen); @@ -761,6 +812,18 @@ abstract class DhcpPacket { expectedLen = optionLen; message = readAsciiString(packet, optionLen); break; + case DHCP_MAX_MESSAGE_SIZE: + expectedLen = 2; + maxMessageSize = Short.valueOf(packet.getShort()); + break; + case DHCP_RENEWAL_TIME: + expectedLen = 4; + T1 = Integer.valueOf(packet.getInt()); + break; + case DHCP_REBINDING_TIME: + expectedLen = 4; + T2 = Integer.valueOf(packet.getInt()); + break; case DHCP_VENDOR_CLASS_ID: expectedLen = optionLen; vendorId = readAsciiString(packet, optionLen); @@ -831,10 +894,14 @@ abstract class DhcpPacket { newPacket.mHostName = hostName; newPacket.mLeaseTime = leaseTime; newPacket.mMessage = message; + newPacket.mMtu = mtu; newPacket.mRequestedIp = requestedIp; newPacket.mRequestedParams = expectedParams; newPacket.mServerIdentifier = serverIdentifier; newPacket.mSubnetMask = netMask; + newPacket.mMaxMessageSize = maxMessageSize; + newPacket.mT1 = T1; + newPacket.mT2 = T2; newPacket.mVendorId = vendorId; return newPacket; } diff --git a/services/net/java/android/net/dhcp/DhcpRequestPacket.java b/services/net/java/android/net/dhcp/DhcpRequestPacket.java index 337fdf05bd24c..42b7b0c945c37 100644 --- a/services/net/java/android/net/dhcp/DhcpRequestPacket.java +++ b/services/net/java/android/net/dhcp/DhcpRequestPacket.java @@ -63,10 +63,15 @@ class DhcpRequestPacket extends DhcpPacket { System.arraycopy(mClientMac, 0, clientId, 1, 6); addTlv(buffer, DHCP_MESSAGE_TYPE, DHCP_MESSAGE_TYPE_REQUEST); - addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); - addTlv(buffer, DHCP_REQUESTED_IP, mRequestedIp); - addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier); + if (!INADDR_ANY.equals(mRequestedIp)) { + addTlv(buffer, DHCP_REQUESTED_IP, mRequestedIp); + } + if (!INADDR_ANY.equals(mServerIdentifier)) { + addTlv(buffer, DHCP_SERVER_IDENTIFIER, mServerIdentifier); + } addTlv(buffer, DHCP_CLIENT_IDENTIFIER, clientId); + addCommonClientTlvs(buffer); + addTlv(buffer, DHCP_PARAMETER_LIST, mRequestedParams); addTlvEnd(buffer); } } From 4ff9f0fd9fdddb760d10fc6677b57655a9fbdb0d Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 17 Mar 2015 17:56:10 +0900 Subject: [PATCH 15/29] Add a protectFromVpn method that takes a FileDescriptor Bug: 19704592 Change-Id: I9aeb29c2f6cf55fa010bc606c99b21a797ac5a19 --- core/java/android/net/NetworkUtils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 01704e53630a8..02fbe7350b672 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -177,6 +177,15 @@ public class NetworkUtils { */ public native static int bindSocketToNetwork(int socketfd, int netId); + /** + * Protect {@code fd} from VPN connections. After protecting, data sent through + * this socket will go directly to the underlying network, so its traffic will not be + * forwarded through the VPN. + */ + public static boolean protectFromVpn(FileDescriptor fd) { + return protectFromVpn(fd.getInt$()); + } + /** * Protect {@code socketfd} from VPN connections. After protecting, data sent through * this socket will go directly to the underlying network, so its traffic will not be From a071edce46fa3d8d539c0d807b77147e184e5a51 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 10 Mar 2015 01:38:38 +0900 Subject: [PATCH 16/29] DHCP: Add a Java DHCP client. The behaviour of the client is intended to mirror the behaviour of the current DhcpStateMachine + dhcpcd combination, except it does not store leases across network changes. Bug: 19704592 Change-Id: I110b58003da2d8293059d48a0181e16f7f7f145c --- .../net/java/android/net/dhcp/DhcpClient.java | 807 ++++++++++++++++++ 1 file changed, 807 insertions(+) create mode 100644 services/net/java/android/net/dhcp/DhcpClient.java diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java new file mode 100644 index 0000000000000..57cc251649a3f --- /dev/null +++ b/services/net/java/android/net/dhcp/DhcpClient.java @@ -0,0 +1,807 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.dhcp; + +import com.android.internal.util.HexDump; +import com.android.internal.util.Protocol; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.DhcpResults; +import android.net.BaseDhcpStateMachine; +import android.net.DhcpStateMachine; +import android.net.InterfaceConfiguration; +import android.net.LinkAddress; +import android.net.NetworkUtils; +import android.os.IBinder; +import android.os.INetworkManagementService; +import android.os.Message; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.system.ErrnoException; +import android.system.Os; +import android.system.PacketSocketAddress; +import android.util.Log; +import android.util.TimeUtils; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.lang.Thread; +import java.net.Inet4Address; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Random; + +import libcore.io.IoUtils; + +import static android.system.OsConstants.*; +import static android.net.dhcp.DhcpPacket.*; + +/** + * A DHCPv4 client. + * + * Written to behave similarly to the DhcpStateMachine + dhcpcd 5.5.6 combination used in Android + * 5.1 and below, as configured on Nexus 6. The interface is the same as DhcpStateMachine. + * + * TODO: + * + * - Exponential backoff when receiving NAKs (not specified by the RFC, but current behaviour). + * - Support persisting lease state and support INIT-REBOOT. Android 5.1 does this, but it does not + * do so correctly: instead of requesting the lease last obtained on a particular network (e.g., a + * given SSID), it requests the last-leased IP address on the same interface, causing a delay if + * the server NAKs or a timeout if it doesn't. + * + * Known differences from current behaviour: + * + * - Does not request the "static routes" option. + * - Does not support BOOTP servers. DHCP has been around since 1993, should be everywhere now. + * - Requests the "broadcast" option, but does nothing with it. + * - Rejects invalid subnet masks such as 255.255.255.1 (current code treats that as 255.255.255.0). + * + * @hide + */ +public class DhcpClient extends BaseDhcpStateMachine { + + private static final String TAG = "DhcpClient"; + private static final boolean DBG = true; + private static final boolean STATE_DBG = false; + private static final boolean MSG_DBG = false; + + // Timers and timeouts. + private static final int SECONDS = 1000; + private static final int FIRST_TIMEOUT_MS = 2 * SECONDS; + private static final int MAX_TIMEOUT_MS = 128 * SECONDS; + + // This is not strictly needed, since the client is asynchronous and implements exponential + // backoff. It's maintained for backwards compatibility with the previous DHCP code, which was + // a blocking operation with a 30-second timeout. We pick 36 seconds so we can send packets at + // t=0, t=2, t=6, t=14, t=30, allowing for 10% jitter. + private static final int DHCP_TIMEOUT_MS = 36 * SECONDS; + + // Messages. + private static final int BASE = Protocol.BASE_DHCP + 100; + private static final int CMD_KICK = BASE + 1; + private static final int CMD_RECEIVED_PACKET = BASE + 2; + private static final int CMD_TIMEOUT = BASE + 3; + + // DHCP parameters that we request. + private static final byte[] REQUESTED_PARAMS = new byte[] { + DHCP_SUBNET_MASK, + DHCP_ROUTER, + DHCP_DNS_SERVER, + DHCP_DOMAIN_NAME, + DHCP_MTU, + DHCP_BROADCAST_ADDRESS, // TODO: currently ignored. + DHCP_LEASE_TIME, + DHCP_RENEWAL_TIME, + DHCP_REBINDING_TIME, + }; + + // DHCP flag that means "yes, we support unicast." + private static final boolean DO_UNICAST = false; + + // System services / libraries we use. + private final Context mContext; + private final AlarmManager mAlarmManager; + private final Random mRandom; + private final INetworkManagementService mNMService; + + // Sockets. + // - We use a packet socket to receive, because servers send us packets bound for IP addresses + // which we have not yet configured, and the kernel protocol stack drops these. + // - We use a UDP socket to send, so the kernel handles ARP and routing for us (DHCP servers can + // be off-link as well as on-link). + private FileDescriptor mPacketSock; + private FileDescriptor mUdpSock; + private ReceiveThread mReceiveThread; + + // State variables. + private final StateMachine mController; + private final PendingIntent mKickIntent; + private final PendingIntent mTimeoutIntent; + private final PendingIntent mRenewIntent; + private final String mIfaceName; + + private boolean mRegisteredForPreDhcpNotification; + private NetworkInterface mIface; + private byte[] mHwAddr; + private PacketSocketAddress mInterfaceBroadcastAddr; + private int mTransactionId; + private DhcpResults mDhcpLease; + private long mDhcpLeaseExpiry; + private DhcpResults mOffer; + + // States. + private State mStoppedState = new StoppedState(); + private State mDhcpState = new DhcpState(); + private State mDhcpInitState = new DhcpInitState(); + private State mDhcpSelectingState = new DhcpSelectingState(); + private State mDhcpRequestingState = new DhcpRequestingState(); + private State mDhcpBoundState = new DhcpBoundState(); + private State mDhcpRenewingState = new DhcpRenewingState(); + private State mDhcpRebindingState = new DhcpRebindingState(); + private State mDhcpInitRebootState = new DhcpInitRebootState(); + private State mDhcpRebootingState = new DhcpRebootingState(); + private State mWaitBeforeStartState = new WaitBeforeStartState(mDhcpInitState); + private State mWaitBeforeRenewalState = new WaitBeforeRenewalState(mDhcpRenewingState); + + private DhcpClient(Context context, StateMachine controller, String iface) { + super(TAG); + + mContext = context; + mController = controller; + mIfaceName = iface; + + addState(mStoppedState); + addState(mDhcpState); + addState(mDhcpInitState, mDhcpState); + addState(mWaitBeforeStartState, mDhcpState); + addState(mDhcpSelectingState, mDhcpState); + addState(mDhcpRequestingState, mDhcpState); + addState(mDhcpBoundState, mDhcpState); + addState(mWaitBeforeRenewalState, mDhcpState); + addState(mDhcpRenewingState, mDhcpState); + addState(mDhcpRebindingState, mDhcpState); + addState(mDhcpInitRebootState, mDhcpState); + addState(mDhcpRebootingState, mDhcpState); + + setInitialState(mStoppedState); + + mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + mNMService = INetworkManagementService.Stub.asInterface(b); + + mRandom = new Random(); + + mKickIntent = createStateMachineCommandIntent("KICK", CMD_KICK); + mTimeoutIntent = createStateMachineCommandIntent("TIMEOUT", CMD_TIMEOUT); + mRenewIntent = createStateMachineCommandIntent("RENEW", DhcpStateMachine.CMD_RENEW_DHCP); + } + + @Override + public void registerForPreDhcpNotification() { + mRegisteredForPreDhcpNotification = true; + } + + public static BaseDhcpStateMachine makeDhcpStateMachine( + Context context, StateMachine controller, String intf) { + DhcpClient client = new DhcpClient(context, controller, intf); + client.start(); + return client; + } + + /** + * Constructs a PendingIntent that sends the specified command to the state machine. This is + * implemented by creating an Intent with the specified parameters, and creating and registering + * a BroadcastReceiver for it. The broadcast must be sent by a process that holds the + * {@code CONNECTIVITY_INTERNAL} permission. + * + * @param cmdName the name of the command. The intent's action will be + * {@code android.net.dhcp.DhcpClient.} + * @param cmd the command to send to the state machine when the PendingIntent is triggered. + * @return the PendingIntent + */ + private PendingIntent createStateMachineCommandIntent(final String cmdName, final int cmd) { + String action = DhcpClient.class.getName() + "." + cmdName; + + // TODO: figure out what values to pass to intent.setPackage() and intent.setClass() that + // result in the Intent being received by this class and nowhere else, and use them. + Intent intent = new Intent(action, null) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, cmd, intent, 0); + + mContext.registerReceiver( + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + sendMessage(cmd); + } + }, + new IntentFilter(action), + android.Manifest.permission.CONNECTIVITY_INTERNAL, + null); + + return pendingIntent; + } + + private boolean initInterface() { + try { + mIface = NetworkInterface.getByName(mIfaceName); + mHwAddr = mIface.getHardwareAddress(); + mInterfaceBroadcastAddr = new PacketSocketAddress(mIface.getIndex(), + DhcpPacket.ETHER_BROADCAST); + return true; + } catch(SocketException e) { + Log.wtf(TAG, "Can't determine ifindex or MAC address for " + mIfaceName); + return false; + } + } + + private void initTransactionId() { + mTransactionId = mRandom.nextInt(); + } + + private boolean initSockets() { + try { + mPacketSock = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IP); + PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IP, mIface.getIndex()); + Os.bind(mPacketSock, addr); + NetworkUtils.attachDhcpFilter(mPacketSock); + } catch(SocketException|ErrnoException e) { + Log.e(TAG, "Error creating packet socket", e); + return false; + } + try { + mUdpSock = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_REUSEADDR, 1); + Os.setsockoptIfreq(mUdpSock, SOL_SOCKET, SO_BINDTODEVICE, mIfaceName); + Os.setsockoptInt(mUdpSock, SOL_SOCKET, SO_BROADCAST, 1); + Os.bind(mUdpSock, Inet4Address.ANY, DhcpPacket.DHCP_CLIENT); + NetworkUtils.protectFromVpn(mUdpSock); + } catch(SocketException|ErrnoException e) { + Log.e(TAG, "Error creating UDP socket", e); + return false; + } + return true; + } + + private void closeSockets() { + IoUtils.closeQuietly(mUdpSock); + IoUtils.closeQuietly(mPacketSock); + } + + private boolean setIpAddress(LinkAddress address) { + InterfaceConfiguration ifcg = new InterfaceConfiguration(); + ifcg.setLinkAddress(address); + try { + mNMService.setInterfaceConfig(mIfaceName, ifcg); + } catch (RemoteException|IllegalStateException e) { + Log.e(TAG, "Error configuring IP address : " + e); + return false; + } + return true; + } + + class ReceiveThread extends Thread { + + private final byte[] mPacket = new byte[DhcpPacket.MAX_LENGTH]; + private boolean stopped = false; + + public void halt() { + stopped = true; + closeSockets(); // Interrupts the read() call the thread is blocked in. + } + + @Override + public void run() { + maybeLog("Starting receive thread"); + while (!stopped) { + try { + int length = Os.read(mPacketSock, mPacket, 0, mPacket.length); + DhcpPacket packet = null; + packet = DhcpPacket.decodeFullPacket(mPacket, length, DhcpPacket.ENCAP_L2); + if (packet != null) { + maybeLog("Received packet: " + packet); + sendMessage(CMD_RECEIVED_PACKET, packet); + } + } catch(IOException|ErrnoException e) { + Log.e(TAG, "Read error", e); + } + } + maybeLog("Stopping receive thread"); + } + } + + private boolean transmitPacket(ByteBuffer buf, String description, Inet4Address to) { + try { + if (to.equals(INADDR_BROADCAST)) { + maybeLog("Broadcasting " + description); + Os.sendto(mPacketSock, buf.array(), 0, buf.limit(), 0, mInterfaceBroadcastAddr); + } else { + maybeLog("Unicasting " + description + " to " + to.getHostAddress()); + Os.sendto(mUdpSock, buf, 0, to, DhcpPacket.DHCP_SERVER); + } + } catch(ErrnoException|IOException e) { + Log.e(TAG, "Can't send packet: ", e); + return false; + } + return true; + } + + private boolean sendDiscoverPacket() { + ByteBuffer packet = DhcpPacket.buildDiscoverPacket( + DhcpPacket.ENCAP_L2, mTransactionId, mHwAddr, DO_UNICAST, REQUESTED_PARAMS); + return transmitPacket(packet, "DHCPDISCOVER", INADDR_BROADCAST); + } + + private boolean sendRequestPacket( + Inet4Address clientAddress, Inet4Address requestedAddress, + Inet4Address serverAddress, Inet4Address to) { + // TODO: should we use the transaction ID from the server? + int encap = to.equals(INADDR_BROADCAST) ? DhcpPacket.ENCAP_L2 : DhcpPacket.ENCAP_BOOTP; + + ByteBuffer packet = DhcpPacket.buildRequestPacket( + encap, mTransactionId, clientAddress, + DO_UNICAST, mHwAddr, requestedAddress, + serverAddress, REQUESTED_PARAMS, null); + String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() + + " request=" + requestedAddress.getHostAddress() + + " to=" + serverAddress.getHostAddress(); + return transmitPacket(packet, description, to); + } + + private void scheduleRenew() { + long now = SystemClock.elapsedRealtime(); + long alarmTime = (now + mDhcpLeaseExpiry) / 2; + mAlarmManager.cancel(mRenewIntent); + mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mRenewIntent); + Log.d(TAG, "Scheduling renewal in " + ((alarmTime - now) / 1000) + "s"); + } + + private void notifyLease() { + mController.sendMessage(DhcpStateMachine.CMD_POST_DHCP_ACTION, + DhcpStateMachine.DHCP_SUCCESS, 0, mDhcpLease); + } + + private void notifyFailure() { + mController.sendMessage(DhcpStateMachine.CMD_POST_DHCP_ACTION, + DhcpStateMachine.DHCP_FAILURE, 0, null); + } + + private void clearDhcpState() { + mDhcpLease = null; + mDhcpLeaseExpiry = 0; + mOffer = null; + } + + /** + * Quit the DhcpStateMachine. + * + * @hide + */ + @Override + public void doQuit() { + Log.d(TAG, "doQuit"); + quit(); + } + + protected void onQuitting() { + Log.d(TAG, "onQuitting"); + mController.sendMessage(DhcpStateMachine.CMD_ON_QUIT); + } + + private void maybeLog(String msg) { + if (DBG) Log.d(TAG, msg); + } + + abstract class LoggingState extends State { + public void enter() { + if (STATE_DBG) Log.d(TAG, "Entering state " + getName()); + } + + private String messageName(int what) { + switch (what) { + case DhcpStateMachine.CMD_START_DHCP: + return "CMD_START_DHCP"; + case DhcpStateMachine.CMD_STOP_DHCP: + return "CMD_STOP_DHCP"; + case DhcpStateMachine.CMD_RENEW_DHCP: + return "CMD_RENEW_DHCP"; + case DhcpStateMachine.CMD_PRE_DHCP_ACTION: + return "CMD_PRE_DHCP_ACTION"; + case DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE: + return "CMD_PRE_DHCP_ACTION_COMPLETE"; + case DhcpStateMachine.CMD_POST_DHCP_ACTION: + return "CMD_POST_DHCP_ACTION"; + case CMD_KICK: + return "CMD_KICK"; + case CMD_RECEIVED_PACKET: + return "CMD_RECEIVED_PACKET"; + default: + return Integer.toString(what); + } + } + + private String messageToString(Message message) { + long now = SystemClock.uptimeMillis(); + StringBuilder b = new StringBuilder(" "); + TimeUtils.formatDuration(message.getWhen() - now, b); + b.append(" ").append(messageName(message.what)) + .append(" ").append(message.arg1) + .append(" ").append(message.arg2) + .append(" ").append(message.obj); + return b.toString(); + } + + @Override + public boolean processMessage(Message message) { + if (MSG_DBG) { + Log.d(TAG, getName() + messageToString(message)); + } + return NOT_HANDLED; + } + } + + // Sends CMD_PRE_DHCP_ACTION to the controller, waits for the controller to respond with + // CMD_PRE_DHCP_ACTION_COMPLETE, and then transitions to mOtherState. + abstract class WaitBeforeOtherState extends LoggingState { + protected State mOtherState; + + @Override + public void enter() { + super.enter(); + mController.sendMessage(DhcpStateMachine.CMD_PRE_DHCP_ACTION); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case DhcpStateMachine.CMD_PRE_DHCP_ACTION_COMPLETE: + transitionTo(mOtherState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + class StoppedState extends LoggingState { + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case DhcpStateMachine.CMD_START_DHCP: + if (mRegisteredForPreDhcpNotification) { + transitionTo(mWaitBeforeStartState); + } else { + transitionTo(mDhcpInitState); + } + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + class WaitBeforeStartState extends WaitBeforeOtherState { + public WaitBeforeStartState(State otherState) { + super(); + mOtherState = otherState; + } + } + + class WaitBeforeRenewalState extends WaitBeforeOtherState { + public WaitBeforeRenewalState(State otherState) { + super(); + mOtherState = otherState; + } + } + + class DhcpState extends LoggingState { + @Override + public void enter() { + super.enter(); + clearDhcpState(); + if (initInterface() && initSockets()) { + mReceiveThread = new ReceiveThread(); + mReceiveThread.start(); + } else { + notifyFailure(); + transitionTo(mStoppedState); + } + } + + @Override + public void exit() { + mReceiveThread.halt(); // Also closes sockets. + clearDhcpState(); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case DhcpStateMachine.CMD_STOP_DHCP: + transitionTo(mStoppedState); + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + public boolean isValidPacket(DhcpPacket packet) { + // TODO: check checksum. + int xid = packet.getTransactionId(); + if (xid != mTransactionId) { + Log.d(TAG, "Unexpected transaction ID " + xid + ", expected " + mTransactionId); + return false; + } + if (!Arrays.equals(packet.getClientMac(), mHwAddr)) { + Log.d(TAG, "MAC addr mismatch: got " + + HexDump.toHexString(packet.getClientMac()) + ", expected " + + HexDump.toHexString(packet.getClientMac())); + return false; + } + return true; + } + + /** + * Retransmits packets using jittered exponential backoff with an optional timeout. Packet + * transmission is triggered by CMD_KICK, which is sent by an AlarmManager alarm. + * + * Concrete subclasses must implement sendPacket, which is called when the alarm fires and a + * packet needs to be transmitted, and receivePacket, which is triggered by CMD_RECEIVED_PACKET + * sent by the receive thread. They may implement timeout, which is called when the timeout + * fires. + */ + abstract class PacketRetransmittingState extends LoggingState { + + private int mTimer; + protected int mTimeout = 0; + + @Override + public void enter() { + super.enter(); + initTimer(); + maybeInitTimeout(); + sendMessage(CMD_KICK); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case CMD_KICK: + sendPacket(); + scheduleKick(); + return HANDLED; + case CMD_RECEIVED_PACKET: + receivePacket((DhcpPacket) message.obj); + return HANDLED; + case CMD_TIMEOUT: + timeout(); + return HANDLED; + default: + return NOT_HANDLED; + } + } + + public void exit() { + mAlarmManager.cancel(mKickIntent); + mAlarmManager.cancel(mTimeoutIntent); + } + + abstract protected boolean sendPacket(); + abstract protected void receivePacket(DhcpPacket packet); + protected void timeout() {} + + protected void initTimer() { + mTimer = FIRST_TIMEOUT_MS; + } + + protected int jitterTimer(int baseTimer) { + int maxJitter = baseTimer / 10; + int jitter = mRandom.nextInt(2 * maxJitter) - maxJitter; + return baseTimer + jitter; + } + + protected void scheduleKick() { + long now = SystemClock.elapsedRealtime(); + long timeout = jitterTimer(mTimer); + long alarmTime = now + timeout; + mAlarmManager.cancel(mKickIntent); + mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mKickIntent); + mTimer *= 2; + if (mTimer > MAX_TIMEOUT_MS) { + mTimer = MAX_TIMEOUT_MS; + } + } + + protected void maybeInitTimeout() { + if (mTimeout > 0) { + long alarmTime = SystemClock.elapsedRealtime() + mTimeout; + mAlarmManager.setExact( + AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime, mTimeoutIntent); + } + } + } + + class DhcpInitState extends PacketRetransmittingState { + public DhcpInitState() { + super(); + mTimeout = DHCP_TIMEOUT_MS; + } + + @Override + public void enter() { + super.enter(); + initTransactionId(); + } + + protected boolean sendPacket() { + return sendDiscoverPacket(); + } + + protected void timeout() { + maybeLog("Timeout"); + notifyFailure(); + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if (!(packet instanceof DhcpOfferPacket)) return; + mOffer = packet.toDhcpResults(); + if (mOffer != null) { + Log.d(TAG, "Got pending lease: " + mOffer); + transitionTo(mDhcpRequestingState); + } + } + } + + // Not implemented. We request the first offer we receive. + class DhcpSelectingState extends LoggingState { + } + + class DhcpRequestingState extends PacketRetransmittingState { + public DhcpRequestingState() { + super(); + mTimeout = DHCP_TIMEOUT_MS / 2; + } + + protected boolean sendPacket() { + return sendRequestPacket( + INADDR_ANY, // ciaddr + (Inet4Address) mOffer.ipAddress.getAddress(), // DHCP_REQUESTED_IP + (Inet4Address) mOffer.serverAddress, // DHCP_SERVER_IDENTIFIER + INADDR_BROADCAST); // packet destination address + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if ((packet instanceof DhcpAckPacket)) { + DhcpResults results = packet.toDhcpResults(); + if (results != null) { + mDhcpLease = results; + Log.d(TAG, "Confirmed lease: " + mDhcpLease); + mDhcpLeaseExpiry = SystemClock.elapsedRealtime() + + mDhcpLease.leaseDuration * 1000; + mOffer = null; + transitionTo(mDhcpBoundState); + } + } else if (packet instanceof DhcpNakPacket) { + Log.d(TAG, "Received NAK, returning to INIT"); + mOffer = null; + transitionTo(mDhcpInitState); + } + } + + protected void timeout() { + notifyFailure(); + transitionTo(mDhcpInitState); + } + } + + class DhcpBoundState extends LoggingState { + @Override + public void enter() { + super.enter(); + if (!setIpAddress(mDhcpLease.ipAddress)) { + notifyFailure(); + transitionTo(mStoppedState); + } + notifyLease(); + // TODO: DhcpStateMachine only supports renewing at 50% of the lease time, and does not + // support rebinding. Fix this. + scheduleRenew(); + } + + @Override + public boolean processMessage(Message message) { + super.processMessage(message); + switch (message.what) { + case DhcpStateMachine.CMD_RENEW_DHCP: + if (mRegisteredForPreDhcpNotification) { + transitionTo(mWaitBeforeRenewalState); + } else { + transitionTo(mDhcpRenewingState); + } + return HANDLED; + default: + return NOT_HANDLED; + } + } + } + + // TODO: timeout. + class DhcpRenewingState extends PacketRetransmittingState { + public DhcpRenewingState() { + super(); + mTimeout = DHCP_TIMEOUT_MS; + } + + @Override + public void enter() { + super.enter(); + initTransactionId(); + } + + protected boolean sendPacket() { + return sendRequestPacket( + (Inet4Address) mDhcpLease.ipAddress.getAddress(), // ciaddr + INADDR_ANY, // DHCP_REQUESTED_IP + INADDR_ANY, // DHCP_SERVER_IDENTIFIER + (Inet4Address) mDhcpLease.serverAddress); // packet destination address + } + + protected void receivePacket(DhcpPacket packet) { + if (!isValidPacket(packet)) return; + if ((packet instanceof DhcpAckPacket)) { + DhcpResults results = packet.toDhcpResults(); + mDhcpLease.leaseDuration = results.leaseDuration; + mDhcpLeaseExpiry = SystemClock.elapsedRealtime() + + mDhcpLease.leaseDuration * 1000; + transitionTo(mDhcpBoundState); + } else if (packet instanceof DhcpNakPacket) { + transitionTo(mDhcpInitState); + } + } + } + + // Not implemented. DhcpStateMachine does not implement it either. + class DhcpRebindingState extends LoggingState { + } + + class DhcpInitRebootState extends LoggingState { + } + + class DhcpRebootingState extends LoggingState { + } +} From cac9a63cf1709ea86745e921609b847abfc73744 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 16 Mar 2015 23:46:24 +0900 Subject: [PATCH 17/29] DHCP: Add a hidden setting to use the legacy DHCP client. Change-Id: I5505bd2c20ddc895df0e9b176e1ed770ad74a3f4 --- core/java/android/provider/Settings.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d773d4aef5c2c..2647247102d28 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5435,6 +5435,14 @@ public final class Settings { public static final String HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED = "hdmi_control_auto_device_off_enabled"; + /** + * Whether to use the DHCP client from Lollipop and earlier instead of the newer Android DHCP + * client. + * (0 = false, 1 = true) + * @hide + */ + public static final String LEGACY_DHCP_CLIENT = "legacy_dhcp_client"; + /** * Whether TV will switch to MHL port when a mobile device is plugged in. * (0 = false, 1 = true) From 2ed489f4100e058eb8713280c06a5a5e15cb1f3d Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 17 Mar 2015 13:18:31 +0900 Subject: [PATCH 18/29] DHCP: parsing robustness fixes. 1. Check the length of the fixed-length portions of the packet. 2. Catch BufferUnderflowException while parsing options. Change-Id: If907f49f02a04a4a3360f46a3192e94ab099af0e --- .../net/java/android/net/dhcp/DhcpPacket.java | 222 ++++++++++-------- 1 file changed, 120 insertions(+), 102 deletions(-) diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index fd18513443fd7..770f5c1a43874 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -41,6 +41,13 @@ abstract class DhcpPacket { public static final int ENCAP_L3 = 1; // IP/UDP header included public static final int ENCAP_BOOTP = 2; // BOOTP contents only + /** + * Minimum length of a DHCP packet, excluding options, in the above encapsulations. + */ + public static final int MIN_PACKET_LENGTH_BOOTP = 236; // See diagram in RFC 2131, section 2. + public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8; + public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14; + /** * IP layer definitions. */ @@ -399,13 +406,8 @@ abstract class DhcpPacket { * Converts a signed short value to an unsigned int value. Needed * because Java does not have unsigned types. */ - private int intAbs(short v) { - if (v < 0) { - int r = v + 65536; - return r; - } else { - return(v); - } + private static int intAbs(short v) { + return v & 0xFFFF; } /** @@ -655,6 +657,10 @@ abstract class DhcpPacket { // check to see if we need to parse L2, IP, and UDP encaps if (pktType == ENCAP_L2) { + if (packet.remaining() < MIN_PACKET_LENGTH_L2) { + return null; + } + byte[] l2dst = new byte[6]; byte[] l2src = new byte[6]; @@ -668,6 +674,10 @@ abstract class DhcpPacket { } if (pktType <= ENCAP_L3) { + if (packet.remaining() < MIN_PACKET_LENGTH_L3) { + return null; + } + byte ipTypeAndLength = packet.get(); int ipVersion = (ipTypeAndLength & 0xf0) >> 4; if (ipVersion != 4) { @@ -690,7 +700,9 @@ abstract class DhcpPacket { if (ipProto != IP_TYPE_UDP) // UDP return null; - // Skip options. + // Skip options. This cannot cause us to read beyond the end of the buffer because the + // IPv4 header cannot be more than (0x0f * 4) = 60 bytes long, and that is less than + // MIN_PACKET_LENGTH_L3. int optionWords = ((ipTypeAndLength & 0x0f) - 5); for (int i = 0; i < optionWords; i++) { packet.getInt(); @@ -706,6 +718,11 @@ abstract class DhcpPacket { return null; } + // We need to check the length even for ENCAP_L3 because the IPv4 header is variable-length. + if (pktType > ENCAP_BOOTP || packet.remaining() < MIN_PACKET_LENGTH_BOOTP) { + return null; + } + byte type = packet.get(); byte hwType = packet.get(); byte addrLen = packet.get(); @@ -746,104 +763,105 @@ abstract class DhcpPacket { boolean notFinishedOptions = true; while ((packet.position() < packet.limit()) && notFinishedOptions) { - byte optionType = packet.get(); + try { + byte optionType = packet.get(); - if (optionType == (byte) 0xFF) { - notFinishedOptions = false; - } else { - byte optionLen = packet.get(); - int expectedLen = 0; + if (optionType == (byte) 0xFF) { + notFinishedOptions = false; + } else { + int optionLen = packet.get() & 0xFF; + int expectedLen = 0; - switch(optionType) { - case DHCP_SUBNET_MASK: - netMask = readIpAddress(packet); - expectedLen = 4; - break; - case DHCP_ROUTER: - gateway = readIpAddress(packet); - expectedLen = 4; - break; - case DHCP_DNS_SERVER: - expectedLen = 0; + switch(optionType) { + case DHCP_SUBNET_MASK: + netMask = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_ROUTER: + gateway = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_DNS_SERVER: + for (expectedLen = 0; expectedLen < optionLen; expectedLen += 4) { + dnsServers.add(readIpAddress(packet)); + } + break; + case DHCP_HOST_NAME: + expectedLen = optionLen; + hostName = readAsciiString(packet, optionLen); + break; + case DHCP_MTU: + expectedLen = 2; + mtu = Short.valueOf(packet.getShort()); + break; + case DHCP_DOMAIN_NAME: + expectedLen = optionLen; + domainName = readAsciiString(packet, optionLen); + break; + case DHCP_BROADCAST_ADDRESS: + bcAddr = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_REQUESTED_IP: + requestedIp = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_LEASE_TIME: + leaseTime = Integer.valueOf(packet.getInt()); + expectedLen = 4; + break; + case DHCP_MESSAGE_TYPE: + dhcpType = packet.get(); + expectedLen = 1; + break; + case DHCP_SERVER_IDENTIFIER: + serverIdentifier = readIpAddress(packet); + expectedLen = 4; + break; + case DHCP_PARAMETER_LIST: + expectedParams = new byte[optionLen]; + packet.get(expectedParams); + expectedLen = optionLen; + break; + case DHCP_MESSAGE: + expectedLen = optionLen; + message = readAsciiString(packet, optionLen); + break; + case DHCP_MAX_MESSAGE_SIZE: + expectedLen = 2; + maxMessageSize = Short.valueOf(packet.getShort()); + break; + case DHCP_RENEWAL_TIME: + expectedLen = 4; + T1 = Integer.valueOf(packet.getInt()); + break; + case DHCP_REBINDING_TIME: + expectedLen = 4; + T2 = Integer.valueOf(packet.getInt()); + break; + case DHCP_VENDOR_CLASS_ID: + expectedLen = optionLen; + vendorId = readAsciiString(packet, optionLen); + break; + case DHCP_CLIENT_IDENTIFIER: { // Client identifier + byte[] id = new byte[optionLen]; + packet.get(id); + expectedLen = optionLen; + } break; + default: + // ignore any other parameters + for (int i = 0; i < optionLen; i++) { + expectedLen++; + byte throwaway = packet.get(); + } + } - for (expectedLen = 0; expectedLen < optionLen; - expectedLen += 4) { - dnsServers.add(readIpAddress(packet)); - } - break; - case DHCP_HOST_NAME: - expectedLen = optionLen; - hostName = readAsciiString(packet, optionLen); - break; - case DHCP_MTU: - expectedLen = 2; - mtu = Short.valueOf(packet.getShort()); - break; - case DHCP_DOMAIN_NAME: - expectedLen = optionLen; - domainName = readAsciiString(packet, optionLen); - break; - case DHCP_BROADCAST_ADDRESS: - bcAddr = readIpAddress(packet); - expectedLen = 4; - break; - case DHCP_REQUESTED_IP: - requestedIp = readIpAddress(packet); - expectedLen = 4; - break; - case DHCP_LEASE_TIME: - leaseTime = Integer.valueOf(packet.getInt()); - expectedLen = 4; - break; - case DHCP_MESSAGE_TYPE: - dhcpType = packet.get(); - expectedLen = 1; - break; - case DHCP_SERVER_IDENTIFIER: - serverIdentifier = readIpAddress(packet); - expectedLen = 4; - break; - case DHCP_PARAMETER_LIST: - expectedParams = new byte[optionLen]; - packet.get(expectedParams); - expectedLen = optionLen; - break; - case DHCP_MESSAGE: - expectedLen = optionLen; - message = readAsciiString(packet, optionLen); - break; - case DHCP_MAX_MESSAGE_SIZE: - expectedLen = 2; - maxMessageSize = Short.valueOf(packet.getShort()); - break; - case DHCP_RENEWAL_TIME: - expectedLen = 4; - T1 = Integer.valueOf(packet.getInt()); - break; - case DHCP_REBINDING_TIME: - expectedLen = 4; - T2 = Integer.valueOf(packet.getInt()); - break; - case DHCP_VENDOR_CLASS_ID: - expectedLen = optionLen; - vendorId = readAsciiString(packet, optionLen); - break; - case DHCP_CLIENT_IDENTIFIER: { // Client identifier - byte[] id = new byte[optionLen]; - packet.get(id); - expectedLen = optionLen; - } break; - default: - // ignore any other parameters - for (int i = 0; i < optionLen; i++) { - expectedLen++; - byte throwaway = packet.get(); - } - } - - if (expectedLen != optionLen) { - return null; + if (expectedLen != optionLen) { + return null; + } } + } catch (BufferUnderflowException e) { + return null; } } From 3698af5f644fa5d34a1619886c66617ed2eab5a5 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 17 Mar 2015 15:55:39 +0900 Subject: [PATCH 19/29] DHCP: Don't write options longer than 255 bytes. Change-Id: Iddc971c7ac97253af3063850cde3dee10c3829ff --- .../net/java/android/net/dhcp/DhcpPacket.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index 770f5c1a43874..a232a6eb273f3 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -7,6 +7,7 @@ import android.os.Build; import android.os.SystemProperties; import android.system.OsConstants; +import java.io.UnsupportedEncodingException; import java.net.Inet4Address; import java.net.UnknownHostException; import java.nio.BufferUnderflowException; @@ -48,6 +49,7 @@ abstract class DhcpPacket { public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8; public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14; + public static final int MAX_OPTION_LEN = 255; /** * IP layer definitions. */ @@ -468,6 +470,10 @@ abstract class DhcpPacket { */ protected static void addTlv(ByteBuffer buf, byte type, byte[] payload) { if (payload != null) { + if (payload.length > MAX_OPTION_LEN) { + throw new IllegalArgumentException("DHCP option too long: " + + payload.length + " vs. " + MAX_OPTION_LEN); + } buf.put(type); buf.put((byte) payload.length); buf.put(payload); @@ -487,13 +493,19 @@ abstract class DhcpPacket { * Adds an optional parameter containing a list of IP addresses. */ protected static void addTlv(ByteBuffer buf, byte type, List addrs) { - if (addrs != null && addrs.size() > 0) { - buf.put(type); - buf.put((byte)(4 * addrs.size())); + if (addrs == null || addrs.size() == 0) return; - for (Inet4Address addr : addrs) { - buf.put(addr.getAddress()); - } + int optionLen = 4 * addrs.size(); + if (optionLen > MAX_OPTION_LEN) { + throw new IllegalArgumentException("DHCP option too long: " + + optionLen + " vs. " + MAX_OPTION_LEN); + } + + buf.put(type); + buf.put((byte)(optionLen)); + + for (Inet4Address addr : addrs) { + buf.put(addr.getAddress()); } } @@ -520,16 +532,13 @@ abstract class DhcpPacket { } /** - * Adds an optional parameter containing and ASCII string. + * Adds an optional parameter containing an ASCII string. */ protected static void addTlv(ByteBuffer buf, byte type, String str) { - if (str != null) { - buf.put(type); - buf.put((byte) str.length()); - - for (int i = 0; i < str.length(); i++) { - buf.put((byte) str.charAt(i)); - } + try { + addTlv(buf, type, str.getBytes("US-ASCII")); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException("String is not US-ASCII: " + str); } } From 4190762d94e05e6c51e25e2743f8d622848d0945 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Mon, 12 Jan 2015 20:02:37 -0800 Subject: [PATCH 20/29] Add opportunistic ble scan mode. (1/2) Bug: 19003667 Change-Id: Ibed7e9ec604cb11a58736d168d3d19ece53fc77a (cherry picked from commit 7508ddf8b53bf350a3424ef71f1ce62ea17006b8) --- core/java/android/bluetooth/le/ScanSettings.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 7eae4398e59d7..5bdfdb544c449 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -25,6 +25,15 @@ import android.os.Parcelable; * parameters for the scan. */ public final class ScanSettings implements Parcelable { + + /** + * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for + * other scan results without starting BLE scans themselves. + * + * @hide + */ + public static final int SCAN_MODE_OPPORTUNISTIC = -1; + /** * Perform Bluetooth LE scan in low power mode. This is the default scan mode as it consumes the * least power. @@ -177,7 +186,7 @@ public final class ScanSettings implements Parcelable { * @throws IllegalArgumentException If the {@code scanMode} is invalid. */ public Builder setScanMode(int scanMode) { - if (scanMode < SCAN_MODE_LOW_POWER || scanMode > SCAN_MODE_LOW_LATENCY) { + if (scanMode < SCAN_MODE_OPPORTUNISTIC || scanMode > SCAN_MODE_LOW_LATENCY) { throw new IllegalArgumentException("invalid scan mode " + scanMode); } mScanMode = scanMode; From f5bd6a97192c9b9eb414acd43ae822391fa92669 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Wed, 18 Mar 2015 08:08:57 +0900 Subject: [PATCH 21/29] Fix missing printf argument. Change-Id: Ifd1eebfbcefa06570882da54a1c410eabf26bce7 --- core/jni/android_net_NetUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index 2ba8e8c16e309..e97d61e54c6d7 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -118,7 +118,7 @@ static jboolean android_net_utils_getDhcpResults(JNIEnv* env, jobject clazz, jst result = ::dhcp_get_results(nameStr, ipaddr, gateway, &prefixLength, dns, server, &lease, vendorInfo, domains, mtu); if (result != 0) { - ALOGD("dhcp_get_results failed : %s (%s)", nameStr); + ALOGD("dhcp_get_results failed : %s (%s)", nameStr, ::dhcp_get_errmsg()); } env->ReleaseStringUTFChars(ifname, nameStr); From 2522c830a3ad3ae2ca7f675f13fafab8835d4f0c Mon Sep 17 00:00:00 2001 From: Vinit Deshpande Date: Thu, 12 Mar 2015 17:04:35 -0700 Subject: [PATCH 22/29] Fix scan results to hold passpoint data Change-Id: I8ab75ec49226a59b04de6463de596cc9f5f6d800 --- api/current.txt | 4 ++ api/system-current.txt | 4 ++ wifi/java/android/net/wifi/ScanResult.java | 43 +++++++++++-------- .../android/net/wifi/WifiConfiguration.java | 11 +++++ .../wifi/passpoint/WifiPasspointManager.java | 2 +- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/api/current.txt b/api/current.txt index 4663a0d613da0..87ed7a95791c6 100644 --- a/api/current.txt +++ b/api/current.txt @@ -17880,7 +17880,10 @@ package android.net.wifi { field public int frequency; field public boolean is80211McRTTResponder; field public int level; + field public java.lang.String operatorFriendlyName; + field public boolean passpointNetwork; field public long timestamp; + field public java.lang.String venueName; } public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable { @@ -17907,6 +17910,7 @@ package android.net.wifi { public class WifiConfiguration implements android.os.Parcelable { ctor public WifiConfiguration(); method public int describeContents(); + method public boolean isPasspoint(); method public void writeToParcel(android.os.Parcel, int); field public java.lang.String BSSID; field public java.lang.String FQDN; diff --git a/api/system-current.txt b/api/system-current.txt index ec0559fc6f674..3bf40c13e5c68 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -19307,7 +19307,10 @@ package android.net.wifi { field public int frequency; field public boolean is80211McRTTResponder; field public int level; + field public java.lang.String operatorFriendlyName; + field public boolean passpointNetwork; field public long timestamp; + field public java.lang.String venueName; } public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable { @@ -19334,6 +19337,7 @@ package android.net.wifi { public class WifiConfiguration implements android.os.Parcelable { ctor public WifiConfiguration(); method public int describeContents(); + method public boolean isPasspoint(); method public void writeToParcel(android.os.Parcel, int); field public java.lang.String BSSID; field public java.lang.String FQDN; diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index b4f49276a1d67..e8a51e336f7d8 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -16,8 +16,6 @@ package android.net.wifi; -import android.net.wifi.passpoint.WifiPasspointInfo; -import android.net.wifi.passpoint.WifiPasspointManager; import android.os.Parcel; import android.os.Parcelable; @@ -215,11 +213,19 @@ public class ScanResult implements Parcelable { public int distanceSdCm; /** - * Passpoint ANQP information. This is not fetched automatically. - * Use {@link WifiPasspointManager#requestAnqpInfo} to request ANQP info. - * {@hide} + * Indicates if the scan result represents a passpoint AP */ - public WifiPasspointInfo passpoint; + public boolean passpointNetwork; + + /** + * Indicates if venue name + */ + public String venueName; + + /** + * Indicates operator name + */ + public String operatorFriendlyName; /** * {@hide} @@ -292,6 +298,7 @@ public class ScanResult implements Parcelable { this.centerFreq0 = UNSPECIFIED; this.centerFreq1 = UNSPECIFIED; this.is80211McRTTResponder = false; + this.passpointNetwork = false; } /** {@hide} */ @@ -310,6 +317,7 @@ public class ScanResult implements Parcelable { this.centerFreq0 = UNSPECIFIED; this.centerFreq1 = UNSPECIFIED; this.is80211McRTTResponder = false; + this.passpointNetwork = false; } /** {@hide} */ @@ -329,6 +337,7 @@ public class ScanResult implements Parcelable { this.centerFreq0 = centerFreq0; this.centerFreq1 = centerFreq1; this.is80211McRTTResponder = is80211McRTTResponder; + this.passpointNetwork = false; } /** copy constructor {@hide} */ @@ -348,13 +357,15 @@ public class ScanResult implements Parcelable { distanceCm = source.distanceCm; distanceSdCm = source.distanceSdCm; seen = source.seen; - passpoint = source.passpoint; autoJoinStatus = source.autoJoinStatus; untrusted = source.untrusted; numConnection = source.numConnection; numUsage = source.numUsage; numIpConfigFailures = source.numIpConfigFailures; isAutoJoinCandidate = source.isAutoJoinCandidate; + passpointNetwork = source.passpointNetwork; + venueName = source.venueName; + operatorFriendlyName = source.operatorFriendlyName; } } @@ -388,7 +399,7 @@ public class ScanResult implements Parcelable { sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")). append("(cm)"); - sb.append(", passpoint: ").append(passpoint != null ? "yes" : "no"); + sb.append(", passpoint: ").append(passpointNetwork ? "yes" : "no"); if (autoJoinStatus != 0) { sb.append(", status: ").append(autoJoinStatus); } @@ -431,12 +442,10 @@ public class ScanResult implements Parcelable { dest.writeInt(numUsage); dest.writeInt(numIpConfigFailures); dest.writeInt(isAutoJoinCandidate); - if (passpoint != null) { - dest.writeInt(1); - passpoint.writeToParcel(dest, flags); - } else { - dest.writeInt(0); - } + dest.writeInt(passpointNetwork ? 1 : 0); + dest.writeString(venueName); + dest.writeString(operatorFriendlyName); + if (informationElements != null) { dest.writeInt(informationElements.length); for (int i = 0; i < informationElements.length; i++) { @@ -478,9 +487,9 @@ public class ScanResult implements Parcelable { sr.numUsage = in.readInt(); sr.numIpConfigFailures = in.readInt(); sr.isAutoJoinCandidate = in.readInt(); - if (in.readInt() == 1) { - sr.passpoint = WifiPasspointInfo.CREATOR.createFromParcel(in); - } + sr.passpointNetwork = in.readInt() == 1; + sr.venueName = in.readString(); + sr.operatorFriendlyName = in.readString(); int n = in.readInt(); if (n != 0) { sr.informationElements = new InformationElement[n]; diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 943af10867056..50beda7f1fb8e 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -946,6 +946,17 @@ public class WifiConfiguration implements Parcelable { return true; } + /** + * Identify if this configuration represents a passpoint network + */ + public boolean isPasspoint() { + return TextUtils.isEmpty(SSID) + && !TextUtils.isEmpty(FQDN) + && !TextUtils.isEmpty(providerFriendlyName) + && enterpriseConfig != null + && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; + } + /** * Helper function, identify if a configuration is linked * @hide diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java index b9b17ebedd041..0245a3d0617ab 100644 --- a/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java +++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java @@ -262,7 +262,7 @@ public class WifiPasspointManager { for (ScanResult sr : mAnqpRequest) if (sr.BSSID.equals(result.bssid)) { Log.d(TAG, "find hit " + result.bssid); - sr.passpoint = result; + /* sr.passpoint = result; */ mAnqpRequest.remove(sr); Log.d(TAG, "mAnqpRequest.len=" + mAnqpRequest.size()); break; From 76b610a9a105097e11bf6293b716bcefb8d8a2a2 Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Wed, 18 Mar 2015 09:33:07 -0400 Subject: [PATCH 23/29] Make NetworkCapabilities.NOT_VPN javadoc visible. Also adjust wording to be more suitable for NetworkRequests and NetworkAgents. Change-Id: I1cc93cb20779cf02d6ffa0fa11ad2916c199b365 --- core/java/android/net/NetworkCapabilities.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index a7f9c5bcc0ab0..8c8bfab9c76de 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -148,9 +148,9 @@ public final class NetworkCapabilities implements Parcelable { */ public static final int NET_CAPABILITY_TRUSTED = 14; - /* + /** * Indicates that this network is not a VPN. This capability is set by default and should be - * explicitly cleared when creating VPN networks. + * explicitly cleared for VPN networks. */ public static final int NET_CAPABILITY_NOT_VPN = 15; From 43564472ee3d9c1ebce34d23d75522b0e4bd56e9 Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Wed, 18 Mar 2015 12:29:13 -0400 Subject: [PATCH 24/29] Remove dead code, mostly DataStateTracker. (cherry picked from AOSP commit 7fad4eb4b52bc6c7ddad47f70e0c310093fbde3b) Change-Id: I18c44cd08dfb51e02a96d0b726e9af1db21e3058 --- .../android/net/BaseNetworkStateTracker.java | 205 ---- .../java/android/net/ConnectivityManager.java | 33 - .../android/net/IConnectivityManager.aidl | 4 - .../android/net/MobileDataStateTracker.java | 910 ------------------ .../java/android/net/NetworkStateTracker.java | 250 ----- core/java/android/net/ProxyDataTracker.java | 207 ---- .../java/android/net/SamplingDataTracker.java | 300 ------ .../android/server/ConnectivityService.java | 294 ------ .../server/ConnectivityServiceTest.java | 1 - 9 files changed, 2204 deletions(-) delete mode 100644 core/java/android/net/BaseNetworkStateTracker.java delete mode 100644 core/java/android/net/MobileDataStateTracker.java delete mode 100644 core/java/android/net/NetworkStateTracker.java delete mode 100644 core/java/android/net/ProxyDataTracker.java delete mode 100644 core/java/android/net/SamplingDataTracker.java diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java deleted file mode 100644 index e4e5b1e35d6c8..0000000000000 --- a/core/java/android/net/BaseNetworkStateTracker.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.content.Context; -import android.os.Handler; -import android.os.Messenger; - -import java.util.concurrent.atomic.AtomicBoolean; - -import com.android.internal.util.Preconditions; - -/** - * Interface to control and observe state of a specific network, hiding - * network-specific details from {@link ConnectivityManager}. Surfaces events - * through the registered {@link Handler} to enable {@link ConnectivityManager} - * to respond to state changes over time. - * - * @hide - */ -public abstract class BaseNetworkStateTracker implements NetworkStateTracker { - // TODO: better document threading expectations - // TODO: migrate to make NetworkStateTracker abstract class - - public static final String PROP_TCP_BUFFER_UNKNOWN = "net.tcp.buffersize.unknown"; - public static final String PROP_TCP_BUFFER_WIFI = "net.tcp.buffersize.wifi"; - - protected Context mContext; - private Handler mTarget; - - protected NetworkInfo mNetworkInfo; - protected LinkProperties mLinkProperties; - protected NetworkCapabilities mNetworkCapabilities; - protected Network mNetwork = new Network(ConnectivityManager.NETID_UNSET); - - private AtomicBoolean mTeardownRequested = new AtomicBoolean(false); - private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false); - private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false); - - public BaseNetworkStateTracker(int networkType) { - mNetworkInfo = new NetworkInfo( - networkType, -1, ConnectivityManager.getNetworkTypeName(networkType), null); - mLinkProperties = new LinkProperties(); - mNetworkCapabilities = new NetworkCapabilities(); - } - - protected BaseNetworkStateTracker() { - // By default, let the sub classes construct everything - } - - @Deprecated - protected Handler getTargetHandler() { - return mTarget; - } - - protected final void dispatchStateChanged() { - // TODO: include snapshot of other fields when sending - mTarget.obtainMessage(EVENT_STATE_CHANGED, getNetworkInfo()).sendToTarget(); - } - - protected final void dispatchConfigurationChanged() { - // TODO: include snapshot of other fields when sending - mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED, getNetworkInfo()).sendToTarget(); - } - - @Override - public void startMonitoring(Context context, Handler target) { - mContext = Preconditions.checkNotNull(context); - mTarget = Preconditions.checkNotNull(target); - startMonitoringInternal(); - } - - protected void startMonitoringInternal() { - - } - - @Override - public NetworkInfo getNetworkInfo() { - return new NetworkInfo(mNetworkInfo); - } - - @Override - public LinkProperties getLinkProperties() { - return new LinkProperties(mLinkProperties); - } - - @Override - public NetworkCapabilities getNetworkCapabilities() { - return new NetworkCapabilities(mNetworkCapabilities); - } - - @Override - public LinkQualityInfo getLinkQualityInfo() { - return null; - } - - @Override - public void captivePortalCheckCompleted(boolean isCaptivePortal) { - // not implemented - } - - @Override - public boolean setRadio(boolean turnOn) { - // Base tracker doesn't handle radios - return true; - } - - @Override - public boolean isAvailable() { - return mNetworkInfo.isAvailable(); - } - - @Override - public void setUserDataEnable(boolean enabled) { - // Base tracker doesn't handle enabled flags - } - - @Override - public void setPolicyDataEnable(boolean enabled) { - // Base tracker doesn't handle enabled flags - } - - @Override - public boolean isPrivateDnsRouteSet() { - return mPrivateDnsRouteSet.get(); - } - - @Override - public void privateDnsRouteSet(boolean enabled) { - mPrivateDnsRouteSet.set(enabled); - } - - @Override - public boolean isDefaultRouteSet() { - return mDefaultRouteSet.get(); - } - - @Override - public void defaultRouteSet(boolean enabled) { - mDefaultRouteSet.set(enabled); - } - - @Override - public boolean isTeardownRequested() { - return mTeardownRequested.get(); - } - - @Override - public void setTeardownRequested(boolean isRequested) { - mTeardownRequested.set(isRequested); - } - - @Override - public void setDependencyMet(boolean met) { - // Base tracker doesn't handle dependencies - } - - @Override - public void supplyMessenger(Messenger messenger) { - // not supported on this network - } - - @Override - public String getNetworkInterfaceName() { - if (mLinkProperties != null) { - return mLinkProperties.getInterfaceName(); - } else { - return null; - } - } - - @Override - public void startSampling(SamplingDataTracker.SamplingSnapshot s) { - // nothing to do - } - - @Override - public void stopSampling(SamplingDataTracker.SamplingSnapshot s) { - // nothing to do - } - - @Override - public void setNetId(int netId) { - mNetwork = new Network(netId); - } - - @Override - public Network getNetwork() { - return mNetwork; - } -} diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 3b0d567ce1dcd..a00246fd99b4a 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1792,25 +1792,6 @@ public class ConnectivityManager { } } - /** - * Sets a secondary requirement bit for the given networkType. - * This requirement bit is generally under the control of the carrier - * or its agents and is not directly controlled by the user. - * - * @param networkType The network who's dependence has changed - * @param met Boolean - true if network use is OK, false if not - * - *

This method requires the call to hold the permission - * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}. - * {@hide} - */ - public void setDataDependency(int networkType, boolean met) { - try { - mService.setDataDependency(networkType, met); - } catch (RemoteException e) { - } - } - /** * Returns true if the hardware supports the given network type * else it returns false. This doesn't indicate we have coverage @@ -1891,20 +1872,6 @@ public class ConnectivityManager { } } - /** - * Supply the backend messenger for a network tracker - * - * @param networkType NetworkType to set - * @param messenger {@link Messenger} - * {@hide} - */ - public void supplyMessenger(int networkType, Messenger messenger) { - try { - mService.supplyMessenger(networkType, messenger); - } catch (RemoteException e) { - } - } - /** * Check mobile provisioning. * diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 46af112d1d495..d8852f882caeb 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -102,8 +102,6 @@ interface IConnectivityManager ProxyInfo getDefaultProxy(); - void setDataDependency(int networkType, boolean met); - boolean prepareVpn(String oldPackage, String newPackage); void setVpnPackageAuthorization(boolean authorized); @@ -120,8 +118,6 @@ interface IConnectivityManager void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal); - void supplyMessenger(int networkType, in Messenger messenger); - int findConnectionTypeForIface(in String iface); int checkMobileProvisioning(int suggestedTimeOutMs); diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java deleted file mode 100644 index abbb7b8eeb4e5..0000000000000 --- a/core/java/android/net/MobileDataStateTracker.java +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.net.NetworkInfo.DetailedState; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.telephony.PhoneStateListener; -import android.telephony.SignalStrength; -import android.telephony.TelephonyManager; -import android.text.TextUtils; -import android.util.Slog; - -import com.android.internal.telephony.DctConstants; -import com.android.internal.telephony.ITelephony; -import com.android.internal.telephony.PhoneConstants; -import com.android.internal.telephony.TelephonyIntents; -import com.android.internal.util.AsyncChannel; - -import java.io.CharArrayWriter; -import java.io.PrintWriter; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Track the state of mobile data connectivity. This is done by - * receiving broadcast intents from the Phone process whenever - * the state of data connectivity changes. - * - * {@hide} - */ -public class MobileDataStateTracker extends BaseNetworkStateTracker { - - private static final String TAG = "MobileDataStateTracker"; - private static final boolean DBG = false; - private static final boolean VDBG = false; - - private PhoneConstants.DataState mMobileDataState; - private ITelephony mPhoneService; - - private String mApnType; - private NetworkInfo mNetworkInfo; - private boolean mTeardownRequested = false; - private Handler mTarget; - private Context mContext; - private LinkProperties mLinkProperties; - private boolean mPrivateDnsRouteSet = false; - private boolean mDefaultRouteSet = false; - - // NOTE: these are only kept for debugging output; actual values are - // maintained in DataConnectionTracker. - protected boolean mUserDataEnabled = true; - protected boolean mPolicyDataEnabled = true; - - private Handler mHandler; - private AsyncChannel mDataConnectionTrackerAc; - - private AtomicBoolean mIsCaptivePortal = new AtomicBoolean(false); - - private SignalStrength mSignalStrength; - - private SamplingDataTracker mSamplingDataTracker = new SamplingDataTracker(); - - private static final int UNKNOWN = LinkQualityInfo.UNKNOWN_INT; - - /** - * Create a new MobileDataStateTracker - * @param netType the ConnectivityManager network type - * @param tag the name of this network - */ - public MobileDataStateTracker(int netType, String tag) { - mNetworkInfo = new NetworkInfo(netType, - TelephonyManager.getDefault().getNetworkType(), tag, - TelephonyManager.getDefault().getNetworkTypeName()); - mApnType = networkTypeToApnType(netType); - } - - /** - * Begin monitoring data connectivity. - * - * @param context is the current Android context - * @param target is the Hander to which to return the events. - */ - public void startMonitoring(Context context, Handler target) { - mTarget = target; - mContext = context; - - mHandler = new MdstHandler(target.getLooper(), this); - - IntentFilter filter = new IntentFilter(); - filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); - filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN); - filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); - - mContext.registerReceiver(new MobileDataStateReceiver(), filter); - mMobileDataState = PhoneConstants.DataState.DISCONNECTED; - - TelephonyManager tm = (TelephonyManager)mContext.getSystemService( - Context.TELEPHONY_SERVICE); - tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); - } - - private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() { - @Override - public void onSignalStrengthsChanged(SignalStrength signalStrength) { - mSignalStrength = signalStrength; - } - }; - - static class MdstHandler extends Handler { - private MobileDataStateTracker mMdst; - - MdstHandler(Looper looper, MobileDataStateTracker mdst) { - super(looper); - mMdst = mdst; - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - if (VDBG) { - mMdst.log("MdstHandler connected"); - } - mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj; - } else { - if (VDBG) { - mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1); - } - } - break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - if (VDBG) mMdst.log("Disconnected from DataStateTracker"); - mMdst.mDataConnectionTrackerAc = null; - break; - default: { - if (VDBG) mMdst.log("Ignorning unknown message=" + msg); - break; - } - } - } - } - - public boolean isPrivateDnsRouteSet() { - return mPrivateDnsRouteSet; - } - - public void privateDnsRouteSet(boolean enabled) { - mPrivateDnsRouteSet = enabled; - } - - public NetworkInfo getNetworkInfo() { - return mNetworkInfo; - } - - public boolean isDefaultRouteSet() { - return mDefaultRouteSet; - } - - public void defaultRouteSet(boolean enabled) { - mDefaultRouteSet = enabled; - } - - /** - * This is not implemented. - */ - public void releaseWakeLock() { - } - - private void updateLinkProperitesAndCapatilities(Intent intent) { - mLinkProperties = intent.getParcelableExtra( - PhoneConstants.DATA_LINK_PROPERTIES_KEY); - if (mLinkProperties == null) { - loge("CONNECTED event did not supply link properties."); - mLinkProperties = new LinkProperties(); - } - mLinkProperties.setMtu(mContext.getResources().getInteger( - com.android.internal.R.integer.config_mobile_mtu)); - mNetworkCapabilities = intent.getParcelableExtra( - PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY); - if (mNetworkCapabilities == null) { - loge("CONNECTED event did not supply network capabilities."); - mNetworkCapabilities = new NetworkCapabilities(); - } - } - - private class MobileDataStateReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(TelephonyIntents. - ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) { - String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); - String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); - if (!TextUtils.equals(mApnType, apnType)) { - return; - } - if (DBG) { - log("Broadcast received: " + intent.getAction() + " apnType=" + apnType - + " apnName=" + apnName); - } - - // Make us in the connecting state until we make a new TYPE_MOBILE_PROVISIONING - mMobileDataState = PhoneConstants.DataState.CONNECTING; - updateLinkProperitesAndCapatilities(intent); - mNetworkInfo.setIsConnectedToProvisioningNetwork(true); - - // Change state to SUSPENDED so setDetailedState - // sends EVENT_STATE_CHANGED to connectivityService - setDetailedState(DetailedState.SUSPENDED, "", apnName); - } else if (intent.getAction().equals(TelephonyIntents. - ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { - String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); - if (VDBG) { - log(String.format("Broadcast received: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED" - + "mApnType=%s %s received apnType=%s", mApnType, - TextUtils.equals(apnType, mApnType) ? "==" : "!=", apnType)); - } - if (!TextUtils.equals(apnType, mApnType)) { - return; - } - // Assume this isn't a provisioning network. - mNetworkInfo.setIsConnectedToProvisioningNetwork(false); - if (DBG) { - log("Broadcast received: " + intent.getAction() + " apnType=" + apnType); - } - - int oldSubtype = mNetworkInfo.getSubtype(); - int newSubType = TelephonyManager.getDefault().getNetworkType(); - String subTypeName = TelephonyManager.getDefault().getNetworkTypeName(); - mNetworkInfo.setSubtype(newSubType, subTypeName); - if (newSubType != oldSubtype && mNetworkInfo.isConnected()) { - Message msg = mTarget.obtainMessage(EVENT_NETWORK_SUBTYPE_CHANGED, - oldSubtype, 0, mNetworkInfo); - msg.sendToTarget(); - } - - PhoneConstants.DataState state = Enum.valueOf(PhoneConstants.DataState.class, - intent.getStringExtra(PhoneConstants.STATE_KEY)); - String reason = intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY); - String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); - mNetworkInfo.setRoaming(intent.getBooleanExtra( - PhoneConstants.DATA_NETWORK_ROAMING_KEY, false)); - if (VDBG) { - log(mApnType + " setting isAvailable to " + - intent.getBooleanExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY,false)); - } - mNetworkInfo.setIsAvailable(!intent.getBooleanExtra( - PhoneConstants.NETWORK_UNAVAILABLE_KEY, false)); - - if (DBG) { - log("Received state=" + state + ", old=" + mMobileDataState + - ", reason=" + (reason == null ? "(unspecified)" : reason)); - } - if (mMobileDataState != state) { - mMobileDataState = state; - switch (state) { - case DISCONNECTED: - if(isTeardownRequested()) { - setTeardownRequested(false); - } - - setDetailedState(DetailedState.DISCONNECTED, reason, apnName); - // can't do this here - ConnectivityService needs it to clear stuff - // it's ok though - just leave it to be refreshed next time - // we connect. - //if (DBG) log("clearing mInterfaceName for "+ mApnType + - // " as it DISCONNECTED"); - //mInterfaceName = null; - break; - case CONNECTING: - setDetailedState(DetailedState.CONNECTING, reason, apnName); - break; - case SUSPENDED: - setDetailedState(DetailedState.SUSPENDED, reason, apnName); - break; - case CONNECTED: - updateLinkProperitesAndCapatilities(intent); - setDetailedState(DetailedState.CONNECTED, reason, apnName); - break; - } - - if (VDBG) { - Slog.d(TAG, "TelephonyMgr.DataConnectionStateChanged"); - if (mNetworkInfo != null) { - Slog.d(TAG, "NetworkInfo = " + mNetworkInfo); - Slog.d(TAG, "subType = " + mNetworkInfo.getSubtype()); - Slog.d(TAG, "subType = " + mNetworkInfo.getSubtypeName()); - } - if (mLinkProperties != null) { - Slog.d(TAG, "LinkProperties = " + mLinkProperties); - } else { - Slog.d(TAG, "LinkProperties = " ); - } - - if (mNetworkCapabilities != null) { - Slog.d(TAG, mNetworkCapabilities.toString()); - } else { - Slog.d(TAG, "NetworkCapabilities = " ); - } - } - - - /* lets not sample traffic data across state changes */ - mSamplingDataTracker.resetSamplingData(); - } else { - // There was no state change. Check if LinkProperties has been updated. - if (TextUtils.equals(reason, PhoneConstants.REASON_LINK_PROPERTIES_CHANGED)) { - mLinkProperties = intent.getParcelableExtra( - PhoneConstants.DATA_LINK_PROPERTIES_KEY); - if (mLinkProperties == null) { - loge("No link property in LINK_PROPERTIES change event."); - mLinkProperties = new LinkProperties(); - } - // Just update reason field in this NetworkInfo - mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason, - mNetworkInfo.getExtraInfo()); - Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED, - mNetworkInfo); - msg.sendToTarget(); - } - } - } else if (intent.getAction(). - equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) { - String apnType = intent.getStringExtra(PhoneConstants.DATA_APN_TYPE_KEY); - if (!TextUtils.equals(apnType, mApnType)) { - if (DBG) { - log(String.format( - "Broadcast received: ACTION_ANY_DATA_CONNECTION_FAILED ignore, " + - "mApnType=%s != received apnType=%s", mApnType, apnType)); - } - return; - } - // Assume this isn't a provisioning network. - mNetworkInfo.setIsConnectedToProvisioningNetwork(false); - String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY); - String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); - if (DBG) { - log("Broadcast received: " + intent.getAction() + - " reason=" + reason == null ? "null" : reason); - } - setDetailedState(DetailedState.FAILED, reason, apnName); - } else { - if (DBG) log("Broadcast received: ignore " + intent.getAction()); - } - } - } - - private void getPhoneService(boolean forceRefresh) { - if ((mPhoneService == null) || forceRefresh) { - mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone")); - } - } - - /** - * Report whether data connectivity is possible. - */ - public boolean isAvailable() { - return mNetworkInfo.isAvailable(); - } - - /** - * Return the system properties name associated with the tcp buffer sizes - * for this network. - */ - public String getTcpBufferSizesPropName() { - String networkTypeStr = "unknown"; - TelephonyManager tm = new TelephonyManager(mContext); - //TODO We have to edit the parameter for getNetworkType regarding CDMA - switch(tm.getNetworkType()) { - case TelephonyManager.NETWORK_TYPE_GPRS: - networkTypeStr = "gprs"; - break; - case TelephonyManager.NETWORK_TYPE_EDGE: - networkTypeStr = "edge"; - break; - case TelephonyManager.NETWORK_TYPE_UMTS: - networkTypeStr = "umts"; - break; - case TelephonyManager.NETWORK_TYPE_HSDPA: - networkTypeStr = "hsdpa"; - break; - case TelephonyManager.NETWORK_TYPE_HSUPA: - networkTypeStr = "hsupa"; - break; - case TelephonyManager.NETWORK_TYPE_HSPA: - networkTypeStr = "hspa"; - break; - case TelephonyManager.NETWORK_TYPE_HSPAP: - networkTypeStr = "hspap"; - break; - case TelephonyManager.NETWORK_TYPE_CDMA: - networkTypeStr = "cdma"; - break; - case TelephonyManager.NETWORK_TYPE_1xRTT: - networkTypeStr = "1xrtt"; - break; - case TelephonyManager.NETWORK_TYPE_EVDO_0: - networkTypeStr = "evdo"; - break; - case TelephonyManager.NETWORK_TYPE_EVDO_A: - networkTypeStr = "evdo"; - break; - case TelephonyManager.NETWORK_TYPE_EVDO_B: - networkTypeStr = "evdo"; - break; - case TelephonyManager.NETWORK_TYPE_IDEN: - networkTypeStr = "iden"; - break; - case TelephonyManager.NETWORK_TYPE_LTE: - case TelephonyManager.NETWORK_TYPE_IWLAN: - networkTypeStr = "lte"; - break; - case TelephonyManager.NETWORK_TYPE_EHRPD: - networkTypeStr = "ehrpd"; - break; - default: - loge("unknown network type: " + tm.getNetworkType()); - } - return "net.tcp.buffersize." + networkTypeStr; - } - - /** - * Tear down mobile data connectivity, i.e., disable the ability to create - * mobile data connections. - * TODO - make async and return nothing? - */ - public boolean teardown() { - setTeardownRequested(true); - return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED); - } - - /** - * @return true if this is ready to operate - */ - public boolean isReady() { - return mDataConnectionTrackerAc != null; - } - - @Override - public void captivePortalCheckCompleted(boolean isCaptivePortal) { - if (mIsCaptivePortal.getAndSet(isCaptivePortal) != isCaptivePortal) { - // Captive portal change enable/disable failing fast - setEnableFailFastMobileData( - isCaptivePortal ? DctConstants.ENABLED : DctConstants.DISABLED); - } - } - - /** - * Record the detailed state of a network, and if it is a - * change from the previous state, send a notification to - * any listeners. - * @param state the new {@code DetailedState} - * @param reason a {@code String} indicating a reason for the state change, - * if one was supplied. May be {@code null}. - * @param extraInfo optional {@code String} providing extra information about the state change - */ - private void setDetailedState(NetworkInfo.DetailedState state, String reason, - String extraInfo) { - if (DBG) log("setDetailed state, old =" - + mNetworkInfo.getDetailedState() + " and new state=" + state); - if (state != mNetworkInfo.getDetailedState()) { - boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING); - String lastReason = mNetworkInfo.getReason(); - /* - * If a reason was supplied when the CONNECTING state was entered, and no - * reason was supplied for entering the CONNECTED state, then retain the - * reason that was supplied when going to CONNECTING. - */ - if (wasConnecting && state == NetworkInfo.DetailedState.CONNECTED && reason == null - && lastReason != null) - reason = lastReason; - mNetworkInfo.setDetailedState(state, reason, extraInfo); - Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo)); - msg.sendToTarget(); - } - } - - public void setTeardownRequested(boolean isRequested) { - mTeardownRequested = isRequested; - } - - public boolean isTeardownRequested() { - return mTeardownRequested; - } - - /** - * Re-enable mobile data connectivity after a {@link #teardown()}. - * TODO - make async and always get a notification? - */ - public boolean reconnect() { - boolean retValue = false; //connected or expect to be? - setTeardownRequested(false); - switch (setEnableApn(mApnType, true)) { - case PhoneConstants.APN_ALREADY_ACTIVE: - // need to set self to CONNECTING so the below message is handled. - retValue = true; - break; - case PhoneConstants.APN_REQUEST_STARTED: - // set IDLE here , avoid the following second FAILED not sent out - mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null); - retValue = true; - break; - case PhoneConstants.APN_REQUEST_FAILED: - case PhoneConstants.APN_TYPE_NOT_AVAILABLE: - break; - default: - loge("Error in reconnect - unexpected response."); - break; - } - return retValue; - } - - /** - * Turn on or off the mobile radio. No connectivity will be possible while the - * radio is off. The operation is a no-op if the radio is already in the desired state. - * @param turnOn {@code true} if the radio should be turned on, {@code false} if - */ - public boolean setRadio(boolean turnOn) { - getPhoneService(false); - /* - * If the phone process has crashed in the past, we'll get a - * RemoteException and need to re-reference the service. - */ - for (int retry = 0; retry < 2; retry++) { - if (mPhoneService == null) { - loge("Ignoring mobile radio request because could not acquire PhoneService"); - break; - } - - try { - return mPhoneService.setRadio(turnOn); - } catch (RemoteException e) { - if (retry == 0) getPhoneService(true); - } - } - - loge("Could not set radio power to " + (turnOn ? "on" : "off")); - return false; - } - - - public void setInternalDataEnable(boolean enabled) { - if (DBG) log("setInternalDataEnable: E enabled=" + enabled); - final AsyncChannel channel = mDataConnectionTrackerAc; - if (channel != null) { - channel.sendMessage(DctConstants.EVENT_SET_INTERNAL_DATA_ENABLE, - enabled ? DctConstants.ENABLED : DctConstants.DISABLED); - } - if (VDBG) log("setInternalDataEnable: X enabled=" + enabled); - } - - @Override - public void setUserDataEnable(boolean enabled) { - if (DBG) log("setUserDataEnable: E enabled=" + enabled); - final AsyncChannel channel = mDataConnectionTrackerAc; - if (channel != null) { - channel.sendMessage(DctConstants.CMD_SET_USER_DATA_ENABLE, - enabled ? DctConstants.ENABLED : DctConstants.DISABLED); - mUserDataEnabled = enabled; - } - if (VDBG) log("setUserDataEnable: X enabled=" + enabled); - } - - @Override - public void setPolicyDataEnable(boolean enabled) { - if (DBG) log("setPolicyDataEnable(enabled=" + enabled + ")"); - final AsyncChannel channel = mDataConnectionTrackerAc; - if (channel != null) { - channel.sendMessage(DctConstants.CMD_SET_POLICY_DATA_ENABLE, - enabled ? DctConstants.ENABLED : DctConstants.DISABLED); - mPolicyDataEnabled = enabled; - } - } - - /** - * Eanble/disable FailFast - * - * @param enabled is DctConstants.ENABLED/DISABLED - */ - public void setEnableFailFastMobileData(int enabled) { - if (DBG) log("setEnableFailFastMobileData(enabled=" + enabled + ")"); - final AsyncChannel channel = mDataConnectionTrackerAc; - if (channel != null) { - channel.sendMessage(DctConstants.CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA, enabled); - } - } - - /** - * carrier dependency is met/unmet - * @param met - */ - public void setDependencyMet(boolean met) { - Bundle bundle = Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType); - try { - if (DBG) log("setDependencyMet: E met=" + met); - Message msg = Message.obtain(); - msg.what = DctConstants.CMD_SET_DEPENDENCY_MET; - msg.arg1 = (met ? DctConstants.ENABLED : DctConstants.DISABLED); - msg.setData(bundle); - mDataConnectionTrackerAc.sendMessage(msg); - if (VDBG) log("setDependencyMet: X met=" + met); - } catch (NullPointerException e) { - loge("setDependencyMet: X mAc was null" + e); - } - } - - /** - * Inform DCT mobile provisioning has started, it ends when provisioning completes. - */ - public void enableMobileProvisioning(String url) { - if (DBG) log("enableMobileProvisioning(url=" + url + ")"); - final AsyncChannel channel = mDataConnectionTrackerAc; - if (channel != null) { - Message msg = Message.obtain(); - msg.what = DctConstants.CMD_ENABLE_MOBILE_PROVISIONING; - msg.setData(Bundle.forPair(DctConstants.PROVISIONING_URL_KEY, url)); - channel.sendMessage(msg); - } - } - - /** - * Return if this network is the provisioning network. Valid only if connected. - * @param met - */ - public boolean isProvisioningNetwork() { - boolean retVal; - try { - Message msg = Message.obtain(); - msg.what = DctConstants.CMD_IS_PROVISIONING_APN; - msg.setData(Bundle.forPair(DctConstants.APN_TYPE_KEY, mApnType)); - Message result = mDataConnectionTrackerAc.sendMessageSynchronously(msg); - retVal = result.arg1 == DctConstants.ENABLED; - } catch (NullPointerException e) { - loge("isProvisioningNetwork: X " + e); - retVal = false; - } - if (DBG) log("isProvisioningNetwork: retVal=" + retVal); - return retVal; - } - - @Override - public String toString() { - final CharArrayWriter writer = new CharArrayWriter(); - final PrintWriter pw = new PrintWriter(writer); - pw.print("Mobile data state: "); pw.println(mMobileDataState); - pw.print("Data enabled: user="); pw.print(mUserDataEnabled); - pw.print(", policy="); pw.println(mPolicyDataEnabled); - return writer.toString(); - } - - /** - * Internal method supporting the ENABLE_MMS feature. - * @param apnType the type of APN to be enabled or disabled (e.g., mms) - * @param enable {@code true} to enable the specified APN type, - * {@code false} to disable it. - * @return an integer value representing the outcome of the request. - */ - private int setEnableApn(String apnType, boolean enable) { - getPhoneService(false); - /* - * If the phone process has crashed in the past, we'll get a - * RemoteException and need to re-reference the service. - */ - for (int retry = 0; retry < 2; retry++) { - if (mPhoneService == null) { - loge("Ignoring feature request because could not acquire PhoneService"); - break; - } - -// try { -// if (enable) { -// return mPhoneService.enableApnType(apnType); -// } else { -// return mPhoneService.disableApnType(apnType); -// } -// } catch (RemoteException e) { -// if (retry == 0) getPhoneService(true); -// } - } - - loge("Could not " + (enable ? "enable" : "disable") + " APN type \"" + apnType + "\""); - return PhoneConstants.APN_REQUEST_FAILED; - } - - public static String networkTypeToApnType(int netType) { - switch(netType) { - case ConnectivityManager.TYPE_MOBILE: - return PhoneConstants.APN_TYPE_DEFAULT; // TODO - use just one of these - case ConnectivityManager.TYPE_MOBILE_MMS: - return PhoneConstants.APN_TYPE_MMS; - case ConnectivityManager.TYPE_MOBILE_SUPL: - return PhoneConstants.APN_TYPE_SUPL; - case ConnectivityManager.TYPE_MOBILE_DUN: - return PhoneConstants.APN_TYPE_DUN; - case ConnectivityManager.TYPE_MOBILE_HIPRI: - return PhoneConstants.APN_TYPE_HIPRI; - case ConnectivityManager.TYPE_MOBILE_FOTA: - return PhoneConstants.APN_TYPE_FOTA; - case ConnectivityManager.TYPE_MOBILE_IMS: - return PhoneConstants.APN_TYPE_IMS; - case ConnectivityManager.TYPE_MOBILE_CBS: - return PhoneConstants.APN_TYPE_CBS; - case ConnectivityManager.TYPE_MOBILE_IA: - return PhoneConstants.APN_TYPE_IA; - case ConnectivityManager.TYPE_MOBILE_EMERGENCY: - return PhoneConstants.APN_TYPE_EMERGENCY; - default: - sloge("Error mapping networkType " + netType + " to apnType."); - return null; - } - } - - - /** - * @see android.net.NetworkStateTracker#getLinkProperties() - */ - @Override - public LinkProperties getLinkProperties() { - return new LinkProperties(mLinkProperties); - } - - public void supplyMessenger(Messenger messenger) { - if (VDBG) log(mApnType + " got supplyMessenger"); - AsyncChannel ac = new AsyncChannel(); - ac.connect(mContext, MobileDataStateTracker.this.mHandler, messenger); - } - - private void log(String s) { - Slog.d(TAG, mApnType + ": " + s); - } - - private void loge(String s) { - Slog.e(TAG, mApnType + ": " + s); - } - - static private void sloge(String s) { - Slog.e(TAG, s); - } - - @Override - public LinkQualityInfo getLinkQualityInfo() { - if (mNetworkInfo == null || mNetworkInfo.getType() == ConnectivityManager.TYPE_NONE) { - // no data available yet; just return - return null; - } - - MobileLinkQualityInfo li = new MobileLinkQualityInfo(); - - li.setNetworkType(mNetworkInfo.getType()); - - mSamplingDataTracker.setCommonLinkQualityInfoFields(li); - - if (mNetworkInfo.getSubtype() != TelephonyManager.NETWORK_TYPE_UNKNOWN) { - li.setMobileNetworkType(mNetworkInfo.getSubtype()); - - NetworkDataEntry entry = getNetworkDataEntry(mNetworkInfo.getSubtype()); - if (entry != null) { - li.setTheoreticalRxBandwidth(entry.downloadBandwidth); - li.setTheoreticalRxBandwidth(entry.uploadBandwidth); - li.setTheoreticalLatency(entry.latency); - } - - if (mSignalStrength != null) { - li.setNormalizedSignalStrength(getNormalizedSignalStrength( - li.getMobileNetworkType(), mSignalStrength)); - } - } - - SignalStrength ss = mSignalStrength; - if (ss != null) { - - li.setRssi(ss.getGsmSignalStrength()); - li.setGsmErrorRate(ss.getGsmBitErrorRate()); - li.setCdmaDbm(ss.getCdmaDbm()); - li.setCdmaEcio(ss.getCdmaEcio()); - li.setEvdoDbm(ss.getEvdoDbm()); - li.setEvdoEcio(ss.getEvdoEcio()); - li.setEvdoSnr(ss.getEvdoSnr()); - li.setLteSignalStrength(ss.getLteSignalStrength()); - li.setLteRsrp(ss.getLteRsrp()); - li.setLteRsrq(ss.getLteRsrq()); - li.setLteRssnr(ss.getLteRssnr()); - li.setLteCqi(ss.getLteCqi()); - } - - if (VDBG) { - Slog.d(TAG, "Returning LinkQualityInfo with" - + " MobileNetworkType = " + String.valueOf(li.getMobileNetworkType()) - + " Theoretical Rx BW = " + String.valueOf(li.getTheoreticalRxBandwidth()) - + " gsm Signal Strength = " + String.valueOf(li.getRssi()) - + " cdma Signal Strength = " + String.valueOf(li.getCdmaDbm()) - + " evdo Signal Strength = " + String.valueOf(li.getEvdoDbm()) - + " Lte Signal Strength = " + String.valueOf(li.getLteSignalStrength())); - } - - return li; - } - - static class NetworkDataEntry { - public int networkType; - public int downloadBandwidth; // in kbps - public int uploadBandwidth; // in kbps - public int latency; // in millisecond - - NetworkDataEntry(int i1, int i2, int i3, int i4) { - networkType = i1; - downloadBandwidth = i2; - uploadBandwidth = i3; - latency = i4; - } - } - - private static NetworkDataEntry [] mTheoreticalBWTable = new NetworkDataEntry[] { - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EDGE, 237, 118, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_GPRS, 48, 40, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_UMTS, 384, 64, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSDPA, 14400, UNKNOWN, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSUPA, 14400, 5760, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSPA, 14400, 5760, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_HSPAP, 21000, 5760, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_CDMA, UNKNOWN, UNKNOWN, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_1xRTT, UNKNOWN, UNKNOWN, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_0, 2468, 153, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_A, 3072, 1800, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EVDO_B, 14700, 1800, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_IDEN, UNKNOWN, UNKNOWN, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_LTE, 100000, 50000, UNKNOWN), - new NetworkDataEntry(TelephonyManager.NETWORK_TYPE_EHRPD, UNKNOWN, UNKNOWN, UNKNOWN), - }; - - private static NetworkDataEntry getNetworkDataEntry(int networkType) { - for (NetworkDataEntry entry : mTheoreticalBWTable) { - if (entry.networkType == networkType) { - return entry; - } - } - - Slog.e(TAG, "Could not find Theoretical BW entry for " + String.valueOf(networkType)); - return null; - } - - private static int getNormalizedSignalStrength(int networkType, SignalStrength ss) { - - int level; - - switch(networkType) { - case TelephonyManager.NETWORK_TYPE_EDGE: - case TelephonyManager.NETWORK_TYPE_GPRS: - case TelephonyManager.NETWORK_TYPE_UMTS: - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - level = ss.getGsmLevel(); - break; - case TelephonyManager.NETWORK_TYPE_CDMA: - case TelephonyManager.NETWORK_TYPE_1xRTT: - level = ss.getCdmaLevel(); - break; - case TelephonyManager.NETWORK_TYPE_EVDO_0: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - level = ss.getEvdoLevel(); - break; - case TelephonyManager.NETWORK_TYPE_LTE: - level = ss.getLteLevel(); - break; - case TelephonyManager.NETWORK_TYPE_IDEN: - case TelephonyManager.NETWORK_TYPE_EHRPD: - default: - return UNKNOWN; - } - - return (level * LinkQualityInfo.NORMALIZED_SIGNAL_STRENGTH_RANGE) / - SignalStrength.NUM_SIGNAL_STRENGTH_BINS; - } - - @Override - public void startSampling(SamplingDataTracker.SamplingSnapshot s) { - mSamplingDataTracker.startSampling(s); - } - - @Override - public void stopSampling(SamplingDataTracker.SamplingSnapshot s) { - mSamplingDataTracker.stopSampling(s); - } -} diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java deleted file mode 100644 index c80782c4fd602..0000000000000 --- a/core/java/android/net/NetworkStateTracker.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.content.Context; -import android.os.Handler; -import android.os.Messenger; - -import static com.android.internal.util.Protocol.BASE_NETWORK_STATE_TRACKER; - -/** - * Interface provides the {@link com.android.server.ConnectivityService} - * with three services. Events to the ConnectivityService when - * changes occur, an API for controlling the network and storage - * for network specific information. - * - * The Connectivity will call startMonitoring before any other - * method is called. - * - * {@hide} - */ -public interface NetworkStateTracker { - - /** - * ------------------------------------------------------------- - * Event Interface back to ConnectivityService. - * - * The events that are to be sent back to the Handler passed - * to startMonitoring when the particular event occurs. - * ------------------------------------------------------------- - */ - - /** - * The network state has changed and the NetworkInfo object - * contains the new state. - * - * msg.what = EVENT_STATE_CHANGED - * msg.obj = NetworkInfo object - */ - public static final int EVENT_STATE_CHANGED = BASE_NETWORK_STATE_TRACKER; - - /** - * msg.what = EVENT_CONFIGURATION_CHANGED - * msg.obj = NetworkInfo object - */ - public static final int EVENT_CONFIGURATION_CHANGED = BASE_NETWORK_STATE_TRACKER + 1; - - /** - * msg.what = EVENT_RESTORE_DEFAULT_NETWORK - * msg.obj = FeatureUser object - */ - public static final int EVENT_RESTORE_DEFAULT_NETWORK = BASE_NETWORK_STATE_TRACKER + 2; - - /** - * msg.what = EVENT_NETWORK_SUBTYPE_CHANGED - * msg.obj = NetworkInfo object - */ - public static final int EVENT_NETWORK_SUBTYPE_CHANGED = BASE_NETWORK_STATE_TRACKER + 3; - - /** - * msg.what = EVENT_NETWORK_CONNECTED - * msg.obj = LinkProperties object - */ - public static final int EVENT_NETWORK_CONNECTED = BASE_NETWORK_STATE_TRACKER + 4; - - /** - * msg.what = EVENT_NETWORK_CONNECTION_DISCONNECTED - * msg.obj = LinkProperties object, same iface name - */ - public static final int EVENT_NETWORK_DISCONNECTED = BASE_NETWORK_STATE_TRACKER + 5; - - /** - * ------------------------------------------------------------- - * Control Interface - * ------------------------------------------------------------- - */ - /** - * Begin monitoring data connectivity. - * - * This is the first method called when this interface is used. - * - * @param context is the current Android context - * @param target is the Hander to which to return the events. - */ - public void startMonitoring(Context context, Handler target); - - /** - * Fetch NetworkInfo for the network - */ - public NetworkInfo getNetworkInfo(); - - /** - * Return the LinkProperties for the connection. - * - * @return a copy of the LinkProperties, is never null. - */ - public LinkProperties getLinkProperties(); - - /** - * @return a copy of this connections capabilities, may be empty but never null. - */ - public NetworkCapabilities getNetworkCapabilities(); - - /** - * Get interesting information about this network link - * @return a copy of link information, null if not available - */ - public LinkQualityInfo getLinkQualityInfo(); - - /** - * Return the system properties name associated with the tcp buffer sizes - * for this network. - */ - public String getTcpBufferSizesPropName(); - - /** - * Disable connectivity to a network - * @return {@code true} if a teardown occurred, {@code false} if the - * teardown did not occur. - */ - public boolean teardown(); - - /** - * Reenable connectivity to a network after a {@link #teardown()}. - * @return {@code true} if we're connected or expect to be connected - */ - public boolean reconnect(); - - /** - * Captive portal check has completed - */ - public void captivePortalCheckCompleted(boolean isCaptive); - - /** - * Turn the wireless radio off for a network. - * @param turnOn {@code true} to turn the radio on, {@code false} - */ - public boolean setRadio(boolean turnOn); - - /** - * Returns an indication of whether this network is available for - * connections. A value of {@code false} means that some quasi-permanent - * condition prevents connectivity to this network. - * - * NOTE that this is broken on multi-connection devices. Should be fixed in J release - * TODO - fix on multi-pdp devices - */ - public boolean isAvailable(); - - /** - * User control of data connection through this network, typically persisted - * internally. - */ - public void setUserDataEnable(boolean enabled); - - /** - * Policy control of data connection through this network, typically not - * persisted internally. Usually used when {@link NetworkPolicy#limitBytes} - * is passed. - */ - public void setPolicyDataEnable(boolean enabled); - - /** - * ------------------------------------------------------------- - * Storage API used by ConnectivityService for saving - * Network specific information. - * ------------------------------------------------------------- - */ - - /** - * Check if private DNS route is set for the network - */ - public boolean isPrivateDnsRouteSet(); - - /** - * Set a flag indicating private DNS route is set - */ - public void privateDnsRouteSet(boolean enabled); - - /** - * Check if default route is set - */ - public boolean isDefaultRouteSet(); - - /** - * Set a flag indicating default route is set for the network - */ - public void defaultRouteSet(boolean enabled); - - /** - * Check if tear down was requested - */ - public boolean isTeardownRequested(); - - /** - * Indicate tear down requested from connectivity - */ - public void setTeardownRequested(boolean isRequested); - - /** - * An external dependency has been met/unmet - */ - public void setDependencyMet(boolean met); - - /* - * Called once to setup async channel between this and - * the underlying network specific code. - */ - public void supplyMessenger(Messenger messenger); - - /* - * Network interface name that we'll lookup for sampling data - */ - public String getNetworkInterfaceName(); - - /* - * Save the starting sample - */ - public void startSampling(SamplingDataTracker.SamplingSnapshot s); - - /* - * Save the ending sample - */ - public void stopSampling(SamplingDataTracker.SamplingSnapshot s); - - /* - * Record the current netId - */ - public void setNetId(int netId); - - /* - * ? - */ - public Network getNetwork(); - -} diff --git a/core/java/android/net/ProxyDataTracker.java b/core/java/android/net/ProxyDataTracker.java deleted file mode 100644 index 7d231256525ba..0000000000000 --- a/core/java/android/net/ProxyDataTracker.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; -import android.os.RemoteException; -import android.os.UserHandle; -import android.util.Log; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * A data tracker responsible for bringing up and tearing down the system proxy server. - * - * {@hide} - */ -public class ProxyDataTracker extends BaseNetworkStateTracker { - private static final String TAG = "ProxyDataTracker"; - private static final String NETWORK_TYPE = "PROXY"; - - // TODO: investigate how to get these DNS addresses from the system. - private static final String DNS1 = "8.8.8.8"; - private static final String DNS2 = "8.8.4.4"; - private static final String INTERFACE_NAME = "ifb0"; - private static final String REASON_ENABLED = "enabled"; - private static final String REASON_DISABLED = "disabled"; - private static final String REASON_PROXY_DOWN = "proxy_down"; - - private static final int MSG_TEAR_DOWN_REQUEST = 1; - private static final int MSG_SETUP_REQUEST = 2; - - private static final String PERMISSION_PROXY_STATUS_SENDER = - "android.permission.ACCESS_NETWORK_CONDITIONS"; - private static final String ACTION_PROXY_STATUS_CHANGE = - "com.android.net.PROXY_STATUS_CHANGE"; - private static final String KEY_IS_PROXY_AVAILABLE = "is_proxy_available"; - private static final String KEY_REPLY_TO_MESSENGER_BINDER = "reply_to_messenger_binder"; - private static final String KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE = - "reply_to_messenger_binder_bundle"; - - private Handler mTarget; - private Messenger mProxyStatusService; - private AtomicBoolean mReconnectRequested = new AtomicBoolean(false); - private AtomicBoolean mIsProxyAvailable = new AtomicBoolean(false); - private final AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0); - - private final BroadcastReceiver mProxyStatusServiceListener = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(ACTION_PROXY_STATUS_CHANGE)) { - mIsProxyAvailable.set(intent.getBooleanExtra(KEY_IS_PROXY_AVAILABLE, false)); - if (mIsProxyAvailable.get()) { - Bundle bundle = intent.getBundleExtra(KEY_REPLY_TO_MESSENGER_BINDER_BUNDLE); - if (bundle == null || bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER) == null) { - Log.e(TAG, "no messenger binder in the intent to send future requests"); - mIsProxyAvailable.set(false); - return; - } - mProxyStatusService = - new Messenger(bundle.getBinder(KEY_REPLY_TO_MESSENGER_BINDER)); - // If there is a pending reconnect request, do it now. - if (mReconnectRequested.get()) { - reconnect(); - } - } else { - setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, - REASON_PROXY_DOWN, null); - } - } else { - Log.d(TAG, "Unrecognized broadcast intent"); - } - } - }; - - /** - * Create a new ProxyDataTracker - */ - public ProxyDataTracker() { - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_PROXY, 0, NETWORK_TYPE, ""); - mLinkProperties = new LinkProperties(); - mNetworkCapabilities = new NetworkCapabilities(); - mNetworkInfo.setIsAvailable(true); - try { - mLinkProperties.addDnsServer(InetAddress.getByName(DNS1)); - mLinkProperties.addDnsServer(InetAddress.getByName(DNS2)); - mLinkProperties.setInterfaceName(INTERFACE_NAME); - } catch (UnknownHostException e) { - Log.e(TAG, "Could not add DNS address", e); - } - } - - @Override - public Object clone() throws CloneNotSupportedException { - throw new CloneNotSupportedException(); - } - - @Override - public void startMonitoring(Context context, Handler target) { - mContext = context; - mTarget = target; - mContext.registerReceiver(mProxyStatusServiceListener, - new IntentFilter(ACTION_PROXY_STATUS_CHANGE), - PERMISSION_PROXY_STATUS_SENDER, - null); - } - - /** - * Disable connectivity to the network. - */ - public boolean teardown() { - setTeardownRequested(true); - mReconnectRequested.set(false); - try { - if (mIsProxyAvailable.get() && mProxyStatusService != null) { - mProxyStatusService.send(Message.obtain(null, MSG_TEAR_DOWN_REQUEST)); - } - } catch (RemoteException e) { - Log.e(TAG, "Unable to connect to proxy status service", e); - return false; - } - setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_DISABLED, null); - return true; - } - - /** - * Re-enable proxy data connectivity after a {@link #teardown()}. - */ - public boolean reconnect() { - mReconnectRequested.set(true); - setTeardownRequested(false); - if (!mIsProxyAvailable.get()) { - Log.w(TAG, "Reconnect requested even though proxy service is not up. Bailing."); - return false; - } - setDetailedState(NetworkInfo.DetailedState.CONNECTING, REASON_ENABLED, null); - - try { - mProxyStatusService.send(Message.obtain(null, MSG_SETUP_REQUEST)); - } catch (RemoteException e) { - Log.e(TAG, "Unable to connect to proxy status service", e); - setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, REASON_PROXY_DOWN, null); - return false; - } - // We'll assume proxy is set up successfully. If not, a status change broadcast will be - // received afterwards to indicate any failure. - setDetailedState(NetworkInfo.DetailedState.CONNECTED, REASON_ENABLED, null); - return true; - } - - /** - * Fetch default gateway address for the network - */ - public int getDefaultGatewayAddr() { - return mDefaultGatewayAddr.get(); - } - - /** - * Return the system properties name associated with the tcp buffer sizes - * for this network. - */ - public String getTcpBufferSizesPropName() { - return "net.tcp.buffersize.wifi"; - } - - /** - * Record the detailed state of a network, and if it is a - * change from the previous state, send a notification to - * any listeners. - * @param state the new @{code DetailedState} - * @param reason a {@code String} indicating a reason for the state change, - * if one was supplied. May be {@code null}. - * @param extraInfo optional {@code String} providing extra information about the state change - */ - private void setDetailedState(NetworkInfo.DetailedState state, String reason, - String extraInfo) { - mNetworkInfo.setDetailedState(state, reason, extraInfo); - Message msg = mTarget.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); - msg.sendToTarget(); - } -} diff --git a/core/java/android/net/SamplingDataTracker.java b/core/java/android/net/SamplingDataTracker.java deleted file mode 100644 index acd56f2dfdad3..0000000000000 --- a/core/java/android/net/SamplingDataTracker.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - - -import android.os.SystemClock; -import android.util.Slog; - -import java.io.BufferedReader; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.Iterator; -import java.util.Map; - -/** - * @hide - */ -public class SamplingDataTracker -{ - private static final boolean DBG = false; - private static final String TAG = "SamplingDataTracker"; - - public static class SamplingSnapshot - { - public long mTxByteCount; - public long mRxByteCount; - public long mTxPacketCount; - public long mRxPacketCount; - public long mTxPacketErrorCount; - public long mRxPacketErrorCount; - public long mTimestamp; - } - - public static void getSamplingSnapshots(Map mapIfaceToSample) { - - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader("/proc/net/dev")); - - // Skip over the line bearing column titles (there are 2 lines) - String line; - reader.readLine(); - reader.readLine(); - - while ((line = reader.readLine()) != null) { - - // remove leading whitespace - line = line.trim(); - - String[] tokens = line.split("[ ]+"); - if (tokens.length < 17) { - continue; - } - - /* column format is - * Interface (Recv)bytes packets errs drop fifo frame compressed multicast \ - * (Transmit)bytes packets errs drop fifo colls carrier compress - */ - - String currentIface = tokens[0].split(":")[0]; - if (DBG) Slog.d(TAG, "Found data for interface " + currentIface); - if (mapIfaceToSample.containsKey(currentIface)) { - - try { - SamplingSnapshot ss = new SamplingSnapshot(); - - ss.mTxByteCount = Long.parseLong(tokens[1]); - ss.mTxPacketCount = Long.parseLong(tokens[2]); - ss.mTxPacketErrorCount = Long.parseLong(tokens[3]); - ss.mRxByteCount = Long.parseLong(tokens[9]); - ss.mRxPacketCount = Long.parseLong(tokens[10]); - ss.mRxPacketErrorCount = Long.parseLong(tokens[11]); - - ss.mTimestamp = SystemClock.elapsedRealtime(); - - if (DBG) { - Slog.d(TAG, "Interface = " + currentIface); - Slog.d(TAG, "ByteCount = " + String.valueOf(ss.mTxByteCount)); - Slog.d(TAG, "TxPacketCount = " + String.valueOf(ss.mTxPacketCount)); - Slog.d(TAG, "TxPacketErrorCount = " - + String.valueOf(ss.mTxPacketErrorCount)); - Slog.d(TAG, "RxByteCount = " + String.valueOf(ss.mRxByteCount)); - Slog.d(TAG, "RxPacketCount = " + String.valueOf(ss.mRxPacketCount)); - Slog.d(TAG, "RxPacketErrorCount = " - + String.valueOf(ss.mRxPacketErrorCount)); - Slog.d(TAG, "Timestamp = " + String.valueOf(ss.mTimestamp)); - Slog.d(TAG, "---------------------------"); - } - - mapIfaceToSample.put(currentIface, ss); - - } catch (NumberFormatException e) { - // just ignore this data point - } - } - } - - if (DBG) { - Iterator it = mapIfaceToSample.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry kvpair = (Map.Entry)it.next(); - if (kvpair.getValue() == null) { - Slog.d(TAG, "could not find snapshot for interface " + kvpair.getKey()); - } - } - } - } catch(FileNotFoundException e) { - Slog.e(TAG, "could not find /proc/net/dev"); - } catch (IOException e) { - Slog.e(TAG, "could not read /proc/net/dev"); - } finally { - try { - if (reader != null) { - reader.close(); - } - } catch (IOException e) { - Slog.e(TAG, "could not close /proc/net/dev"); - } - } - } - - // Snapshots from previous sampling interval - private SamplingSnapshot mBeginningSample; - private SamplingSnapshot mEndingSample; - - // Starting snapshot of current interval - private SamplingSnapshot mLastSample; - - // Protects sampling data from concurrent access - public final Object mSamplingDataLock = new Object(); - - // We need long enough time for a good sample - private final int MINIMUM_SAMPLING_INTERVAL = 15 * 1000; - - // statistics is useless unless we have enough data - private final int MINIMUM_SAMPLED_PACKETS = 30; - - public void startSampling(SamplingSnapshot s) { - synchronized(mSamplingDataLock) { - mLastSample = s; - } - } - - public void stopSampling(SamplingSnapshot s) { - synchronized(mSamplingDataLock) { - if (mLastSample != null) { - if (s.mTimestamp - mLastSample.mTimestamp > MINIMUM_SAMPLING_INTERVAL - && getSampledPacketCount(mLastSample, s) > MINIMUM_SAMPLED_PACKETS) { - mBeginningSample = mLastSample; - mEndingSample = s; - mLastSample = null; - } else { - if (DBG) Slog.d(TAG, "Throwing current sample away because it is too small"); - } - } - } - } - - public void resetSamplingData() { - if (DBG) Slog.d(TAG, "Resetting sampled network data"); - synchronized(mSamplingDataLock) { - - // We could just take another sample here and treat it as an - // 'ending sample' effectively shortening sampling interval, but that - // requires extra work (specifically, reading the sample needs to be - // done asynchronously) - - mLastSample = null; - } - } - - public long getSampledTxByteCount() { - synchronized(mSamplingDataLock) { - if (mBeginningSample != null && mEndingSample != null) { - return mEndingSample.mTxByteCount - mBeginningSample.mTxByteCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - } - - public long getSampledTxPacketCount() { - synchronized(mSamplingDataLock) { - if (mBeginningSample != null && mEndingSample != null) { - return mEndingSample.mTxPacketCount - mBeginningSample.mTxPacketCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - } - - public long getSampledTxPacketErrorCount() { - synchronized(mSamplingDataLock) { - if (mBeginningSample != null && mEndingSample != null) { - return mEndingSample.mTxPacketErrorCount - mBeginningSample.mTxPacketErrorCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - } - - public long getSampledRxByteCount() { - synchronized(mSamplingDataLock) { - if (mBeginningSample != null && mEndingSample != null) { - return mEndingSample.mRxByteCount - mBeginningSample.mRxByteCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - } - - public long getSampledRxPacketCount() { - synchronized(mSamplingDataLock) { - if (mBeginningSample != null && mEndingSample != null) { - return mEndingSample.mRxPacketCount - mBeginningSample.mRxPacketCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - } - - public long getSampledPacketCount() { - return getSampledPacketCount(mBeginningSample, mEndingSample); - } - - public long getSampledPacketCount(SamplingSnapshot begin, SamplingSnapshot end) { - if (begin != null && end != null) { - long rxPacketCount = end.mRxPacketCount - begin.mRxPacketCount; - long txPacketCount = end.mTxPacketCount - begin.mTxPacketCount; - return rxPacketCount + txPacketCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - - public long getSampledPacketErrorCount() { - if (mBeginningSample != null && mEndingSample != null) { - long rxPacketErrorCount = getSampledRxPacketErrorCount(); - long txPacketErrorCount = getSampledTxPacketErrorCount(); - return rxPacketErrorCount + txPacketErrorCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - - public long getSampledRxPacketErrorCount() { - synchronized(mSamplingDataLock) { - if (mBeginningSample != null && mEndingSample != null) { - return mEndingSample.mRxPacketErrorCount - mBeginningSample.mRxPacketErrorCount; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - } - - public long getSampleTimestamp() { - synchronized(mSamplingDataLock) { - if (mEndingSample != null) { - return mEndingSample.mTimestamp; - } else { - return LinkQualityInfo.UNKNOWN_LONG; - } - } - } - - public int getSampleDuration() { - synchronized(mSamplingDataLock) { - if (mBeginningSample != null && mEndingSample != null) { - return (int) (mEndingSample.mTimestamp - mBeginningSample.mTimestamp); - } else { - return LinkQualityInfo.UNKNOWN_INT; - } - } - } - - public void setCommonLinkQualityInfoFields(LinkQualityInfo li) { - synchronized(mSamplingDataLock) { - li.setLastDataSampleTime(getSampleTimestamp()); - li.setDataSampleDuration(getSampleDuration()); - li.setPacketCount(getSampledPacketCount()); - li.setPacketErrorCount(getSampledPacketErrorCount()); - } - } -} - diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b72b29dbb1d28..d9ef766f2b71b 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -48,7 +48,6 @@ import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.LinkProperties; import android.net.LinkProperties.CompareResult; -import android.net.MobileDataStateTracker; import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkCapabilities; @@ -59,12 +58,10 @@ import android.net.NetworkMisc; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; import android.net.NetworkState; -import android.net.NetworkStateTracker; import android.net.NetworkUtils; import android.net.Proxy; import android.net.ProxyInfo; import android.net.RouteInfo; -import android.net.SamplingDataTracker; import android.net.UidRange; import android.net.Uri; import android.os.Binder; @@ -153,9 +150,6 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final boolean DBG = true; private static final boolean VDBG = false; - // network sampling debugging - private static final boolean SAMPLE_DBG = false; - private static final boolean LOGD_RULES = false; // TODO: create better separation between radio types and network types @@ -166,33 +160,10 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final String NETWORK_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore"; - // Default value if FAIL_FAST_TIME_MS is not set - private static final int DEFAULT_FAIL_FAST_TIME_MS = 1 * 60 * 1000; - // system property that can override DEFAULT_FAIL_FAST_TIME_MS - private static final String FAIL_FAST_TIME_MS = - "persist.radio.fail_fast_time_ms"; - - private static final String ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED = - "android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED"; - - private static final int SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE = 0; - // How long to delay to removal of a pending intent based request. // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS private final int mReleasePendingIntentDelayMs; - private PendingIntent mSampleIntervalElapsedIntent; - - // Set network sampling interval at 12 minutes, this way, even if the timers get - // aggregated, it will fire at around 15 minutes, which should allow us to - // aggregate this timer with other timers (specially the socket keep alive timers) - private static final int DEFAULT_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 12 * 60); - - // start network sampling a minute after booting ... - private static final int DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS = (SAMPLE_DBG ? 30 : 60); - - AlarmManager mAlarmManager; - private Tethering mTethering; private final PermissionMonitor mPermissionMonitor; @@ -212,13 +183,6 @@ public class ConnectivityService extends IConnectivityManager.Stub /** Set of ifaces that are costly. */ private HashSet mMeteredIfaces = Sets.newHashSet(); - /** - * Sometimes we want to refer to the individual network state - * trackers separately, and sometimes we just want to treat them - * abstractly. - */ - private NetworkStateTracker mNetTrackers[]; - private Context mContext; private int mNetworkPreference; // 0 is full bad, 100 is full good @@ -277,28 +241,11 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 9; - /** - * used internally to set external dependency met/unmet - * arg1 = ENABLED (met) or DISABLED (unmet) - * arg2 = NetworkType - */ - private static final int EVENT_SET_DEPENDENCY_MET = 10; - /** * used internally to send a sticky broadcast delayed. */ private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11; - /** - * Used internally to disable fail fast of mobile data - */ - private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 14; - - /** - * used internally to indicate that data sampling interval is up - */ - private static final int EVENT_SAMPLE_INTERVAL_ELAPSED = 15; - /** * PAC manager has received new port. */ @@ -419,8 +366,6 @@ public class ConnectivityService extends IConnectivityManager.Stub private DataConnectionStats mDataConnectionStats; - private AtomicInteger mEnableFailFastMobileDataTag = new AtomicInteger(0); - TelephonyManager mTelephonyManager; // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp @@ -650,9 +595,6 @@ public class ConnectivityService extends IConnectivityManager.Stub com.android.internal.R.integer.config_networkTransitionTimeout); mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mNetTrackers = new NetworkStateTracker[ - ConnectivityManager.MAX_NETWORK_TYPE+1]; - mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; // TODO: What is the "correct" way to do determine if this is a wifi only device? @@ -740,23 +682,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mDataConnectionStats = new DataConnectionStats(mContext); mDataConnectionStats.startMonitoring(); - mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); - - IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED); - mContext.registerReceiver( - new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED)) { - mHandler.sendMessage(mHandler.obtainMessage - (EVENT_SAMPLE_INTERVAL_ELAPSED)); - } - } - }, - new IntentFilter(filter)); - mPacManager = new PacManager(mContext, mHandler, EVENT_PROXY_HAS_CHANGED); mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); @@ -782,15 +707,6 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new IllegalStateException("No free netIds"); } - private boolean teardown(NetworkStateTracker netTracker) { - if (netTracker.teardown()) { - netTracker.setTeardownRequested(true); - return true; - } else { - return false; - } - } - private NetworkState getFilteredNetworkState(int networkType, int uid) { NetworkInfo info = null; LinkProperties lp = null; @@ -1350,22 +1266,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return true; } - public void setDataDependency(int networkType, boolean met) { - enforceConnectivityInternalPermission(); - - mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET, - (met ? ENABLED : DISABLED), networkType)); - } - - private void handleSetDependencyMet(int networkType, boolean met) { - if (mNetTrackers[networkType] != null) { - if (DBG) { - log("handleSetDependencyMet(" + networkType + ", " + met + ")"); - } - mNetTrackers[networkType].setDependencyMet(met); - } - } - private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() { @Override public void onUidRulesChanged(int uid, int uidRules) { @@ -1406,21 +1306,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (LOGD_RULES) { log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")"); } - - // kick off connectivity change broadcast for active network, since - // global background policy change is radical. - // TODO: Dead code; remove. - // - // final int networkType = mActiveDefaultNetwork; - // if (isNetworkTypeValid(networkType)) { - // final NetworkStateTracker tracker = mNetTrackers[networkType]; - // if (tracker != null) { - // final NetworkInfo info = tracker.getNetworkInfo(); - // if (info != null && info.isConnected()) { - // sendConnectedBroadcast(info); - // } - // } - // } } }; @@ -1536,14 +1421,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } void systemReady() { - // start network sampling .. - Intent intent = new Intent(ACTION_PKT_CNT_SAMPLE_INTERVAL_ELAPSED); - intent.setPackage(mContext.getPackageName()); - - mSampleIntervalElapsedIntent = PendingIntent.getBroadcast(mContext, - SAMPLE_INTERVAL_ELAPSED_REQUEST_CODE, intent, 0); - setAlarm(DEFAULT_START_SAMPLING_INTERVAL_IN_SECONDS * 1000, mSampleIntervalElapsedIntent); - loadGlobalProxy(); synchronized(this) { @@ -2015,66 +1892,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } break; } - case NetworkStateTracker.EVENT_STATE_CHANGED: { - info = (NetworkInfo) msg.obj; - NetworkInfo.State state = info.getState(); - - if (VDBG || (state == NetworkInfo.State.CONNECTED) || - (state == NetworkInfo.State.DISCONNECTED) || - (state == NetworkInfo.State.SUSPENDED)) { - log("ConnectivityChange for " + - info.getTypeName() + ": " + - state + "/" + info.getDetailedState()); - } - - EventLogTags.writeConnectivityStateChanged( - info.getType(), info.getSubtype(), info.getDetailedState().ordinal()); - - if (info.isConnectedToProvisioningNetwork()) { - /** - * TODO: Create ConnectivityManager.TYPE_MOBILE_PROVISIONING - * for now its an in between network, its a network that - * is actually a default network but we don't want it to be - * announced as such to keep background applications from - * trying to use it. It turns out that some still try so we - * take the additional step of clearing any default routes - * to the link that may have incorrectly setup by the lower - * levels. - */ - LinkProperties lp = getLinkPropertiesForType(info.getType()); - if (DBG) { - log("EVENT_STATE_CHANGED: connected to provisioning network, lp=" + lp); - } - - // Clear any default routes setup by the radio so - // any activity by applications trying to use this - // connection will fail until the provisioning network - // is enabled. - /* - for (RouteInfo r : lp.getRoutes()) { - removeRoute(lp, r, TO_DEFAULT_TABLE, - mNetTrackers[info.getType()].getNetwork().netId); - } - */ - } else if (state == NetworkInfo.State.DISCONNECTED) { - } else if (state == NetworkInfo.State.SUSPENDED) { - } else if (state == NetworkInfo.State.CONNECTED) { - // handleConnect(info); - } - notifyLockdownVpn(null); - break; - } - case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: { - info = (NetworkInfo) msg.obj; - // TODO: Temporary allowing network configuration - // change not resetting sockets. - // @see bug/4455071 - /* - handleConnectivityChange(info.getType(), mCurrentLinkProperties[info.getType()], - false); - */ - break; - } } } } @@ -2439,34 +2256,11 @@ public class ConnectivityService extends IConnectivityManager.Stub handleDeprecatedGlobalHttpProxy(); break; } - case EVENT_SET_DEPENDENCY_MET: { - boolean met = (msg.arg1 == ENABLED); - handleSetDependencyMet(msg.arg2, met); - break; - } case EVENT_SEND_STICKY_BROADCAST_INTENT: { Intent intent = (Intent)msg.obj; sendStickyBroadcast(intent); break; } - case EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: { - int tag = mEnableFailFastMobileDataTag.get(); - if (msg.arg1 == tag) { - MobileDataStateTracker mobileDst = - (MobileDataStateTracker) mNetTrackers[ConnectivityManager.TYPE_MOBILE]; - if (mobileDst != null) { - mobileDst.setEnableFailFastMobileData(msg.arg2); - } - } else { - log("EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: stale arg1:" + msg.arg1 - + " != tag:" + tag); - } - break; - } - case EVENT_SAMPLE_INTERVAL_ELAPSED: { - handleNetworkSamplingTimeout(); - break; - } case EVENT_PROXY_HAS_CHANGED: { handleApplyDefaultProxy((ProxyInfo)msg.obj); break; @@ -3066,14 +2860,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - public void supplyMessenger(int networkType, Messenger messenger) { - enforceConnectivityInternalPermission(); - - if (isNetworkTypeValid(networkType) && mNetTrackers[networkType] != null) { - mNetTrackers[networkType].supplyMessenger(messenger); - } - } - public int findConnectionTypeForIface(String iface) { enforceConnectivityInternalPermission(); @@ -3091,23 +2877,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return ConnectivityManager.TYPE_NONE; } - /** - * Have mobile data fail fast if enabled. - * - * @param enabled DctConstants.ENABLED/DISABLED - */ - private void setEnableFailFastMobileData(int enabled) { - int tag; - - if (enabled == DctConstants.ENABLED) { - tag = mEnableFailFastMobileDataTag.incrementAndGet(); - } else { - tag = mEnableFailFastMobileDataTag.get(); - } - mHandler.sendMessage(mHandler.obtainMessage(EVENT_ENABLE_FAIL_FAST_MOBILE_DATA, tag, - enabled)); - } - @Override public int checkMobileProvisioning(int suggestedTimeOutMs) { // TODO: Remove? Any reason to trigger a provisioning check? @@ -3392,69 +3161,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } }; - /* Infrastructure for network sampling */ - - private void handleNetworkSamplingTimeout() { - - if (SAMPLE_DBG) log("Sampling interval elapsed, updating statistics .."); - - // initialize list of interfaces .. - Map mapIfaceToSample = - new HashMap(); - for (NetworkStateTracker tracker : mNetTrackers) { - if (tracker != null) { - String ifaceName = tracker.getNetworkInterfaceName(); - if (ifaceName != null) { - mapIfaceToSample.put(ifaceName, null); - } - } - } - - // Read samples for all interfaces - SamplingDataTracker.getSamplingSnapshots(mapIfaceToSample); - - // process samples for all networks - for (NetworkStateTracker tracker : mNetTrackers) { - if (tracker != null) { - String ifaceName = tracker.getNetworkInterfaceName(); - SamplingDataTracker.SamplingSnapshot ss = mapIfaceToSample.get(ifaceName); - if (ss != null) { - // end the previous sampling cycle - tracker.stopSampling(ss); - // start a new sampling cycle .. - tracker.startSampling(ss); - } - } - } - - if (SAMPLE_DBG) log("Done."); - - int samplingIntervalInSeconds = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS, - DEFAULT_SAMPLING_INTERVAL_IN_SECONDS); - - if (SAMPLE_DBG) { - log("Setting timer for " + String.valueOf(samplingIntervalInSeconds) + "seconds"); - } - - setAlarm(samplingIntervalInSeconds * 1000, mSampleIntervalElapsedIntent); - } - - /** - * Sets a network sampling alarm. - */ - void setAlarm(int timeoutInMilliseconds, PendingIntent intent) { - long wakeupTime = SystemClock.elapsedRealtime() + timeoutInMilliseconds; - int alarmType; - if (Resources.getSystem().getBoolean( - R.bool.config_networkSamplingWakesDevice)) { - alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP; - } else { - alarmType = AlarmManager.ELAPSED_REALTIME; - } - mAlarmManager.set(alarmType, wakeupTime, intent); - } - private final HashMap mNetworkFactoryInfos = new HashMap(); private final HashMap mNetworkRequests = diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index beb353a6cf29c..c19890075a253 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -20,7 +20,6 @@ import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.getNetworkTypeName; -import static android.net.NetworkStateTracker.EVENT_STATE_CHANGED; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; From 9954faa70d4172617b8b77743d1fdd599e2e6277 Mon Sep 17 00:00:00 2001 From: xinhe Date: Thu, 12 Mar 2015 18:43:05 -0700 Subject: [PATCH 25/29] Change rtt Framework interface Bug:19735392 Change-Id: I0886d3c0e40a6dd5477c81a5df5dbc2746942ec3 --- api/system-current.txt | 97 +++- wifi/java/android/net/wifi/IRttManager.aidl | 3 +- wifi/java/android/net/wifi/RttManager.aidl | 18 + wifi/java/android/net/wifi/RttManager.java | 545 ++++++++++++++++++-- 4 files changed, 596 insertions(+), 67 deletions(-) create mode 100644 wifi/java/android/net/wifi/RttManager.aidl diff --git a/api/system-current.txt b/api/system-current.txt index 3bf40c13e5c68..34fb8ca1c3216 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -19197,7 +19197,8 @@ package android.net.wifi { } public class RttManager { - method public android.net.wifi.RttManager.Capabilities getCapabilities(); + method public deprecated android.net.wifi.RttManager.Capabilities getCapabilities(); + method public android.net.wifi.RttManager.RttCapabilities getRttCapabilities(); method public void startRanging(android.net.wifi.RttManager.RttParams[], android.net.wifi.RttManager.RttListener); method public void stopRanging(android.net.wifi.RttManager.RttListener); field public static final int BASE = 160256; // 0x27200 @@ -19207,10 +19208,19 @@ package android.net.wifi { field public static final int CMD_OP_STOP_RANGING = 160257; // 0x27201 field public static final int CMD_OP_SUCCEEDED = 160259; // 0x27203 field public static final java.lang.String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description"; + field public static final int PREAMBLE_HT = 2; // 0x2 + field public static final int PREAMBLE_LEGACY = 1; // 0x1 + field public static final int PREAMBLE_VHT = 4; // 0x4 field public static final int REASON_INVALID_LISTENER = -3; // 0xfffffffd field public static final int REASON_INVALID_REQUEST = -4; // 0xfffffffc field public static final int REASON_NOT_AVAILABLE = -2; // 0xfffffffe field public static final int REASON_UNSPECIFIED = -1; // 0xffffffff + field public static final int RTT_BW_10_SUPPORT = 2; // 0x2 + field public static final int RTT_BW_160_SUPPORT = 32; // 0x20 + field public static final int RTT_BW_20_SUPPORT = 4; // 0x4 + field public static final int RTT_BW_40_SUPPORT = 8; // 0x8 + field public static final int RTT_BW_5_SUPPORT = 1; // 0x1 + field public static final int RTT_BW_80_SUPPORT = 16; // 0x10 field public static final int RTT_CHANNEL_WIDTH_10 = 6; // 0x6 field public static final int RTT_CHANNEL_WIDTH_160 = 3; // 0x3 field public static final int RTT_CHANNEL_WIDTH_20 = 0; // 0x0 @@ -19218,26 +19228,31 @@ package android.net.wifi { field public static final int RTT_CHANNEL_WIDTH_5 = 5; // 0x5 field public static final int RTT_CHANNEL_WIDTH_80 = 2; // 0x2 field public static final int RTT_CHANNEL_WIDTH_80P80 = 4; // 0x4 - field public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff + field public static final deprecated int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; // 0xffffffff field public static final int RTT_PEER_TYPE_AP = 1; // 0x1 field public static final int RTT_PEER_TYPE_STA = 2; // 0x2 field public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; // 0x0 field public static final int RTT_STATUS_ABORTED = 8; // 0x8 field public static final int RTT_STATUS_FAILURE = 1; // 0x1 field public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; // 0x6 + field public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; // 0xc + field public static final int RTT_STATUS_FAIL_INVALID_TS = 9; // 0x9 field public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4; // 0x4 field public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; // 0x7 field public static final int RTT_STATUS_FAIL_NO_RSP = 2; // 0x2 + field public static final int RTT_STATUS_FAIL_PROTOCOL = 10; // 0xa field public static final int RTT_STATUS_FAIL_REJECTED = 3; // 0x3 + field public static final int RTT_STATUS_FAIL_SCHEDULE = 11; // 0xb field public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5; // 0x5 field public static final int RTT_STATUS_SUCCESS = 0; // 0x0 - field public static final int RTT_TYPE_11_MC = 4; // 0x4 - field public static final int RTT_TYPE_11_V = 2; // 0x2 + field public static final deprecated int RTT_TYPE_11_MC = 4; // 0x4 + field public static final deprecated int RTT_TYPE_11_V = 2; // 0x2 field public static final int RTT_TYPE_ONE_SIDED = 1; // 0x1 - field public static final int RTT_TYPE_UNSPECIFIED = 0; // 0x0 + field public static final int RTT_TYPE_TWO_SIDED = 4; // 0x4 + field public static final deprecated int RTT_TYPE_UNSPECIFIED = 0; // 0x0 } - public class RttManager.Capabilities { + public deprecated class RttManager.Capabilities { ctor public RttManager.Capabilities(); field public int supportedPeerType; field public int supportedType; @@ -19256,6 +19271,20 @@ package android.net.wifi { field public android.net.wifi.RttManager.RttResult[] mResults; } + public static class RttManager.RttCapabilities implements android.os.Parcelable { + ctor public RttManager.RttCapabilities(); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public int bwSupported; + field public boolean lciSupported; + field public boolean lcrSupported; + field public boolean oneSidedRttSupported; + field public int preambleSupported; + field public deprecated boolean supportedPeerType; + field public deprecated boolean supportedType; + field public boolean twoSided11McRttSupported; + } + public static abstract interface RttManager.RttListener { method public abstract void onAborted(); method public abstract void onFailure(int, java.lang.String); @@ -19264,30 +19293,64 @@ package android.net.wifi { public static class RttManager.RttParams { ctor public RttManager.RttParams(); + field public boolean LCIRequest; + field public boolean LCRRequest; + field public int bandwidth; field public java.lang.String bssid; + field public int burstTimeout; + field public int centerFreq0; + field public int centerFreq1; field public int channelWidth; field public int deviceType; field public int frequency; - field public int num_retries; - field public int num_samples; + field public int interval; + field public int numRetriesPerFTMR; + field public int numRetriesPerMeasurementFrame; + field public int numSamplesPerBurst; + field public deprecated int num_retries; + field public deprecated int num_samples; + field public int numberBurst; + field public int preamble; field public int requestType; } public static class RttManager.RttResult { ctor public RttManager.RttResult(); field public java.lang.String bssid; - field public int distance_cm; - field public int distance_sd_cm; - field public int distance_spread_cm; - field public int requestType; + field public int burstDuration; + field public int burstNumber; + field public int distance; + field public int distanceSpread; + field public int distanceStandardDeviation; + field public deprecated int distance_cm; + field public deprecated int distance_sd_cm; + field public deprecated int distance_spread_cm; + field public int frameNumberPerBurstPeer; + field public int measurementFrameNumber; + field public int measurementType; + field public deprecated int requestType; + field public int retryAfterDuration; field public int rssi; - field public int rssi_spread; - field public long rtt_ns; - field public long rtt_sd_ns; - field public long rtt_spread_ns; + field public int rssiSpread; + field public deprecated int rssi_spread; + field public long rtt; + field public long rttSpread; + field public long rttStandardDeviation; + field public deprecated long rtt_ns; + field public deprecated long rtt_sd_ns; + field public deprecated long rtt_spread_ns; + field public int rxRate; field public int status; + field public int successMeasurementFrameNumber; field public long ts; - field public int tx_rate; + field public int txRate; + field public deprecated int tx_rate; + } + + public class RttManager.wifiInformationElement { + ctor public RttManager.wifiInformationElement(); + field public java.lang.String data; + field public int id; } public class ScanResult implements android.os.Parcelable { diff --git a/wifi/java/android/net/wifi/IRttManager.aidl b/wifi/java/android/net/wifi/IRttManager.aidl index d929f55987ee7..90f66c4adc1a5 100644 --- a/wifi/java/android/net/wifi/IRttManager.aidl +++ b/wifi/java/android/net/wifi/IRttManager.aidl @@ -15,8 +15,8 @@ */ package android.net.wifi; - import android.os.Messenger; +import android.net.wifi.RttManager; /** * {@hide} @@ -24,4 +24,5 @@ import android.os.Messenger; interface IRttManager { Messenger getMessenger(); + RttManager.RttCapabilities getRttCapabilities(); } diff --git a/wifi/java/android/net/wifi/RttManager.aidl b/wifi/java/android/net/wifi/RttManager.aidl new file mode 100644 index 0000000000000..5c6d44710ea5c --- /dev/null +++ b/wifi/java/android/net/wifi/RttManager.aidl @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2015, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; +parcelable RttManager.RttCapabilities; \ No newline at end of file diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index 57343c52262d2..65ecf5d728a6b 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -26,10 +26,19 @@ public class RttManager { private static final boolean DBG = true; private static final String TAG = "RttManager"; - public static final int RTT_TYPE_UNSPECIFIED = 0; - public static final int RTT_TYPE_ONE_SIDED = 1; - public static final int RTT_TYPE_11_V = 2; - public static final int RTT_TYPE_11_MC = 4; + /** @deprecated Type must be specified*/ + @Deprecated + public static final int RTT_TYPE_UNSPECIFIED = 0; + public static final int RTT_TYPE_ONE_SIDED = 1; + + /** @deprecated It is not supported*/ + @Deprecated + public static final int RTT_TYPE_11_V = 2; + public static final int RTT_TYPE_TWO_SIDED = 4; + + /** @deprecated It is not supported*/ + @Deprecated + public static final int RTT_TYPE_11_MC = 4; public static final int RTT_PEER_TYPE_UNSPECIFIED = 0; public static final int RTT_PEER_TYPE_AP = 1; @@ -42,6 +51,9 @@ public class RttManager { public static final int RTT_CHANNEL_WIDTH_80P80 = 4; public static final int RTT_CHANNEL_WIDTH_5 = 5; public static final int RTT_CHANNEL_WIDTH_10 = 6; + + /** @deprecated channel info must be specified*/ + @Deprecated public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1; public static final int RTT_STATUS_SUCCESS = 0; @@ -53,6 +65,12 @@ public class RttManager { public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6; public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7; public static final int RTT_STATUS_ABORTED = 8; + //if the T1-T4 or TOD/TOA Timestamp is illegal + public static final int RTT_STATUS_FAIL_INVALID_TS = 9; + //11mc protocol failed, eg, unrecognized FTMR/FTM + public static final int RTT_STATUS_FAIL_PROTOCOL = 10; + public static final int RTT_STATUS_FAIL_SCHEDULE = 11; + public static final int RTT_STATUS_FAIL_BUSY_TRY_LATER = 12; public static final int REASON_UNSPECIFIED = -1; public static final int REASON_NOT_AVAILABLE = -2; @@ -61,41 +79,269 @@ public class RttManager { public static final String DESCRIPTION_KEY = "android.net.wifi.RttManager.Description"; + /** + * RTT BW supported bit mask + */ + public static final int RTT_BW_5_SUPPORT = 0x1; + public static final int RTT_BW_10_SUPPORT = 0x2; + public static final int RTT_BW_20_SUPPORT = 0x4; + public static final int RTT_BW_40_SUPPORT = 0x8; + public static final int RTT_BW_80_SUPPORT = 0x10; + public static final int RTT_BW_160_SUPPORT = 0x20; + + /** + * RTT Preamble Support bit mask + */ + public static final int PREAMBLE_LEGACY = 0x1; + public static final int PREAMBLE_HT = 0x2; + public static final int PREAMBLE_VHT = 0x4; + + /** @deprecated It has been replaced by RttCapabilities*/ + @Deprecated public class Capabilities { public int supportedType; public int supportedPeerType; } + /** @deprecated It has been replaced by getRttCapabilities*/ + @Deprecated public Capabilities getCapabilities() { return new Capabilities(); } + /** + * This class describe the RTT capability of the Hardware + */ + public static class RttCapabilities implements Parcelable { + /** @deprecated It is not supported*/ + @Deprecated + public boolean supportedType; + /** @deprecated It is not supported*/ + @Deprecated + public boolean supportedPeerType; + //1-sided rtt measurement is supported + public boolean oneSidedRttSupported; + //11mc 2-sided rtt measurement is supported + public boolean twoSided11McRttSupported; + //location configuration information supported + public boolean lciSupported; + //location civic records supported + public boolean lcrSupported; + //preamble supported, see bit mask definition above + public int preambleSupported; + //RTT bandwidth supported + public int bwSupported; + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("oneSidedRtt "). + append(oneSidedRttSupported ? "is Supported. " : "is not supported. "). + append("twoSided11McRtt "). + append(twoSided11McRttSupported ? "is Supported. " : "is not supported. "). + append("lci "). + append(lciSupported ? "is Supported. " : "is not supported. "). + append("lcr "). + append(lcrSupported ? "is Supported. " : "is not supported. "); + + if ((preambleSupported & PREAMBLE_LEGACY) != 0) { + sb.append("Legacy "); + } + + if ((preambleSupported & PREAMBLE_HT) != 0) { + sb.append("HT "); + } + + if ((preambleSupported & PREAMBLE_VHT) != 0) { + sb.append("VHT "); + } + + sb.append("is supported. \n"); + + if ((bwSupported & RTT_BW_5_SUPPORT) != 0) { + sb.append("5 MHz "); + } + + if ((bwSupported & RTT_BW_10_SUPPORT) != 0) { + sb.append("10 MHz "); + } + + if ((bwSupported & RTT_BW_20_SUPPORT) != 0) { + sb.append("20 MHz "); + } + + if ((bwSupported & RTT_BW_40_SUPPORT) != 0) { + sb.append("40 MHz "); + } + + if ((bwSupported & RTT_BW_80_SUPPORT) != 0) { + sb.append("80 MHz "); + } + + if ((bwSupported & RTT_BW_160_SUPPORT) != 0) { + sb.append("160 MHz "); + } + + sb.append("is supported."); + + return sb.toString(); + } + /** Implement the Parcelable interface {@hide} */ + @Override + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface {@hide} */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(oneSidedRttSupported ? 1 : 0); + dest.writeInt(twoSided11McRttSupported ? 1 : 0); + dest.writeInt(lciSupported ? 1 : 0); + dest.writeInt(lcrSupported ? 1 : 0); + dest.writeInt(preambleSupported); + dest.writeInt(bwSupported); + + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator CREATOR = + new Creator() { + public RttCapabilities createFromParcel(Parcel in) { + RttCapabilities capabilities = new RttCapabilities(); + capabilities.oneSidedRttSupported = in.readInt() == 1 ? true : false; + capabilities.twoSided11McRttSupported = in.readInt() == 1 ? true : false; + capabilities.lciSupported = in.readInt() == 1 ? true : false; + capabilities.lcrSupported = in.readInt() == 1 ? true : false; + capabilities.preambleSupported = in.readInt(); + capabilities.bwSupported = in.readInt(); + return capabilities; + } + /** Implement the Parcelable interface {@hide} */ + @Override + public RttCapabilities[] newArray(int size) { + return new RttCapabilities[size]; + } + }; + } + + public RttCapabilities getRttCapabilities() { + synchronized (sCapabilitiesLock) { + if (mRttCapabilities == null) { + try { + mRttCapabilities = mService.getRttCapabilities(); + } catch (RemoteException e) { + Log.e(TAG, "Can not get RTT Capabilities"); + } + } + return mRttCapabilities; + } + } + /** specifies parameters for RTT request */ public static class RttParams { - - /** type of device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA */ + /** + * type of destination device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA + */ public int deviceType; - /** type of RTT being sought; one of RTT_TYPE_ONE_SIDED - * RTT_TYPE_11_V or RTT_TYPE_11_MC or RTT_TYPE_UNSPECIFIED */ + /** + * type of RTT measurement method; one of RTT_TYPE_ONE_SIDED or RTT_TYPE_TWO_SIDED. + */ public int requestType; /** mac address of the device being ranged */ public String bssid; - /** channel frequency that the device is on; optional */ + /** + * The primary 20 MHz frequency (in MHz) of the channel over which the client is + * communicating with the access point.Similar as ScanResult.frequency + */ public int frequency; - /** optional channel width. wider channels result in better accuracy, - * but they take longer time, and even get aborted may times; use - * RTT_CHANNEL_WIDTH_UNSPECIFIED if not specifying */ + /** + * channel width used for RTT measurement. User need verify the highest BW the destination + * support (from scan result etc) before set this value. Wider channels result usually give + * better accuracy. However, the frame loss can increase. Similar as ScanResult.channelWidth + */ public int channelWidth; - /** number of samples to be taken */ + /** + * Not used if the AP bandwidth is 20 MHz + * If the AP use 40, 80 or 160 MHz, this is the center frequency + * if the AP use 80 + 80 MHz, this is the center frequency of the first segment + * similar as ScanResult.centerFreq0 + */ + public int centerFreq0; + + /** + * Only used if the AP bandwidth is 80 + 80 MHz + * if the AP use 80 + 80 MHz, this is the center frequency of the second segment + * similar as ScanResult.centerFreq1 + */ + public int centerFreq1; + /** + * number of samples to be taken + * @deprecated It has been replaced by numSamplesPerBurst + */ + @Deprecated public int num_samples; - /** number of retries if a sample fails */ + /** + * number of retries if a sample fails + * @deprecated It has been replaced by numRetriesPerMeasurementFrame + */ + @Deprecated public int num_retries; + + /** Number of burst. fixed to 1 for single side RTT*/ + public int numberBurst; + + /** valid only if numberBurst > 1, interval between burst(ms). Not used by singe side RTT */ + public int interval; + + /** number of samples to be taken in one burst*/ + public int numSamplesPerBurst; + + /** number of retries for each measurement frame if a sample fails + * Only used by single side RTT + */ + public int numRetriesPerMeasurementFrame; + + /** number of retries for FTMR frame if fails Only used by 80211MC double side RTT */ + public int numRetriesPerFTMR; + + /** Request LCI information */ + public boolean LCIRequest; + + /** Request LCR information */ + public boolean LCRRequest; + + /** Timeout for each burst, unit of 250 us*/ + public int burstTimeout; + + /** preamble used for RTT measurement + * should be one of PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT + */ + public int preamble; + + /** bandWidth used for RTT measurement.User need verify the highest BW the destination + * support (from scan result etc) before set this value. Wider channels result usually give + * better accuracy. However, the frame loss can increase too. + * should be one of RTT_CHANNEL_WIDTH_20 to RTT_CHANNEL_WIDTH_80 + */ + public int bandwidth; + + public RttParams() { + //provide initial value for RttParams + deviceType = RTT_PEER_TYPE_AP; + numberBurst = 1; + numSamplesPerBurst = 8; + numRetriesPerMeasurementFrame = 0; + burstTimeout = 40 + numSamplesPerBurst *4; + preamble = PREAMBLE_LEGACY; + bandwidth = RTT_CHANNEL_WIDTH_20; + } } /** pseudo-private class used to parcel arguments */ @@ -121,10 +367,20 @@ public class RttManager { dest.writeInt(params.deviceType); dest.writeInt(params.requestType); dest.writeString(params.bssid); - dest.writeInt(params.frequency); dest.writeInt(params.channelWidth); - dest.writeInt(params.num_samples); - dest.writeInt(params.num_retries); + dest.writeInt(params.frequency); + dest.writeInt(params.centerFreq0); + dest.writeInt(params.centerFreq1); + dest.writeInt(params.numberBurst); + dest.writeInt(params.interval); + dest.writeInt(params.numSamplesPerBurst); + dest.writeInt(params.numRetriesPerMeasurementFrame); + dest.writeInt(params.numRetriesPerFTMR); + dest.writeInt(params.LCIRequest ? 1 : 0); + dest.writeInt(params.LCRRequest ? 1 : 0); + dest.writeInt(params.burstTimeout); + dest.writeInt(params.preamble); + dest.writeInt(params.bandwidth); } } else { dest.writeInt(0); @@ -148,11 +404,20 @@ public class RttManager { params[i].deviceType = in.readInt(); params[i].requestType = in.readInt(); params[i].bssid = in.readString(); - params[i].frequency = in.readInt(); params[i].channelWidth = in.readInt(); - params[i].num_samples = in.readInt(); - params[i].num_retries = in.readInt(); - + params[i].frequency = in.readInt(); + params[i].centerFreq0 = in.readInt(); + params[i].centerFreq1 = in.readInt(); + params[i].numberBurst = in.readInt(); + params[i].interval = in.readInt(); + params[i].numSamplesPerBurst = in.readInt(); + params[i].numRetriesPerMeasurementFrame = in.readInt(); + params[i].numRetriesPerFTMR = in.readInt(); + params[i].LCIRequest = in.readInt() == 1 ? true : false; + params[i].LCRRequest = in.readInt() == 1 ? true : false; + params[i].burstTimeout = in.readInt(); + params[i].preamble = in.readInt(); + params[i].bandwidth = in.readInt(); } ParcelableRttParams parcelableParams = new ParcelableRttParams(params); @@ -165,46 +430,143 @@ public class RttManager { }; } + public class wifiInformationElement { + /** Information Element ID*/ + public int id; + public String data; + } /** specifies RTT results */ public static class RttResult { /** mac address of the device being ranged */ public String bssid; + /** # of burst for this measurement*/ + public int burstNumber; + + /** total number of measurement frames in this measurement*/ + public int measurementFrameNumber; + + /** total successful number of measurement frames in this measurement*/ + public int successMeasurementFrameNumber; + + /** Maximum number of frames per burst supported by peer */ + public int frameNumberPerBurstPeer; + /** status of the request */ public int status; - /** type of the request used */ + /** + * type of the request used + * @deprecated It has been replaced by measurementType + */ + @Deprecated public int requestType; + /** RTT measurement method type used, shoudl be one of RTT_TYPE_ONE_SIDED or + * RTT_TYPE_TWO_SIDED. + */ + public int measurementType; + + /** please retry RTT measurement after this S since peer indicate busy at ths moment*/ + public int retryAfterDuration; + /** timestamp of completion, in microsecond since boot */ public long ts; - /** average RSSI observed */ + /** average RSSI observed, unit of 0.5 dB */ public int rssi; - /** RSSI spread (i.e. max - min) */ + /** + * RSSI spread (i.e. max - min) + * @deprecated It has been replaced by rssi_spread + */ + @Deprecated public int rssi_spread; - /** average transmit rate */ + /**RSSI spread (i.e. max - min), unit of 0.5 dB */ + public int rssiSpread; + + /** + * average transmit rate + * @deprecated It has been replaced by txRate + */ + @Deprecated public int tx_rate; - /** average round trip time in nano second */ + /** average transmit rate */ + public int txRate; + + /** average receiving rate */ + public int rxRate; + + /** + * average round trip time in nano second + * @deprecated It has been replaced by rtt + */ + @Deprecated public long rtt_ns; - /** standard deviation observed in round trip time */ + /** average round trip time in 0.1 nano second */ + public long rtt; + + /** + * standard deviation observed in round trip time + * @deprecated It has been replaced by rttStandardDeviation + */ + @Deprecated public long rtt_sd_ns; - /** spread (i.e. max - min) round trip time */ + /** standard deviation of RTT in 0.1 ns */ + public long rttStandardDeviation; + + /** + * spread (i.e. max - min) round trip time + * @deprecated It has been replaced by rttSpread + */ + @Deprecated public long rtt_spread_ns; - /** average distance in centimeter, computed based on rtt_ns */ + /** spread (i.e. max - min) RTT in 0.1 ns */ + public long rttSpread; + + /** + * average distance in centimeter, computed based on rtt_ns + * @deprecated It has been replaced by distance + */ + @Deprecated public int distance_cm; - /** standard deviation observed in distance */ + /** average distance in cm, computed based on rtt */ + public int distance; + + /** + * standard deviation observed in distance + * @deprecated It has been replaced with distanceStandardDeviation + */ + @Deprecated public int distance_sd_cm; - /** spread (i.e. max - min) distance */ + /** standard deviation observed in distance in cm*/ + public int distanceStandardDeviation; + + /** + * spread (i.e. max - min) distance + * @deprecated It has been replaced by distanceSpread + */ + @Deprecated public int distance_spread_cm; + + /** spread (i.e. max - min) distance in cm */ + public int distanceSpread; + + /** the duration of this measurement burst*/ + public int burstDuration; + + /** LCI information Element*/ + wifiInformationElement LCI; + + /** LCR information Element*/ + wifiInformationElement LCR; } @@ -228,18 +590,28 @@ public class RttManager { dest.writeInt(mResults.length); for (RttResult result : mResults) { dest.writeString(result.bssid); + dest.writeInt(result.burstNumber); + dest.writeInt(result.measurementFrameNumber); + dest.writeInt(result.successMeasurementFrameNumber); + dest.writeInt(result.frameNumberPerBurstPeer); dest.writeInt(result.status); - dest.writeInt(result.requestType); + dest.writeInt(result.measurementType); + dest.writeInt(result.retryAfterDuration); dest.writeLong(result.ts); dest.writeInt(result.rssi); - dest.writeInt(result.rssi_spread); - dest.writeInt(result.tx_rate); - dest.writeLong(result.rtt_ns); - dest.writeLong(result.rtt_sd_ns); - dest.writeLong(result.rtt_spread_ns); - dest.writeInt(result.distance_cm); - dest.writeInt(result.distance_sd_cm); - dest.writeInt(result.distance_spread_cm); + dest.writeInt(result.rssiSpread); + dest.writeInt(result.txRate); + dest.writeLong(result.rtt); + dest.writeLong(result.rttStandardDeviation); + dest.writeLong(result.rttSpread); + dest.writeInt(result.distance); + dest.writeInt(result.distanceStandardDeviation); + dest.writeInt(result.distanceSpread); + dest.writeInt(result.burstDuration); + //dest.writeInt(result.LCI.id); + //dest.writeString(result.LCI.data); + //dest.writeInt(result.LCR.id); + //dest.writeString(result.LCR.data); } } else { dest.writeInt(0); @@ -261,18 +633,28 @@ public class RttManager { for (int i = 0; i < num; i++) { results[i] = new RttResult(); results[i].bssid = in.readString(); + results[i].burstNumber = in.readInt(); + results[i].measurementFrameNumber = in.readInt(); + results[i].successMeasurementFrameNumber = in.readInt(); + results[i].frameNumberPerBurstPeer = in.readInt(); results[i].status = in.readInt(); - results[i].requestType = in.readInt(); + results[i].measurementType = in.readInt(); + results[i].retryAfterDuration = in.readInt(); results[i].ts = in.readLong(); results[i].rssi = in.readInt(); - results[i].rssi_spread = in.readInt(); - results[i].tx_rate = in.readInt(); - results[i].rtt_ns = in.readLong(); - results[i].rtt_sd_ns = in.readLong(); - results[i].rtt_spread_ns = in.readLong(); - results[i].distance_cm = in.readInt(); - results[i].distance_sd_cm = in.readInt(); - results[i].distance_spread_cm = in.readInt(); + results[i].rssiSpread = in.readInt(); + results[i].txRate = in.readInt(); + results[i].rtt = in.readLong(); + results[i].rttStandardDeviation = in.readLong(); + results[i].rttSpread = in.readLong(); + results[i].distance = in.readInt(); + results[i].distanceStandardDeviation = in.readInt(); + results[i].distanceSpread = in.readInt(); + results[i].burstDuration = in.readInt(); + //results[i].LCI.id = in.readInt(); + //results[i].LCI.data = in.readString(); + //results[i].LCR.id = in.readInt(); + //results[i].LCR.data = in.readString(); } ParcelableRttResults parcelableResults = new ParcelableRttResults(results); @@ -292,7 +674,70 @@ public class RttManager { public void onAborted(); } + private boolean rttParamSanity(RttParams params, int index) { + if (mRttCapabilities == null) { + if(getRttCapabilities() == null) { + Log.e(TAG, "Can not get RTT capabilities"); + //throw new IllegalStateException("RTT chip is not working"); + } + } + + if (params.deviceType != RTT_PEER_TYPE_AP) { + return false; + } else if (params.requestType != RTT_TYPE_ONE_SIDED && params.requestType != + RTT_TYPE_TWO_SIDED) { + Log.e(TAG, "Request " + index + ": Illegal Request Type: " + params.requestType); + return false; + } else if (params.requestType == RTT_TYPE_ONE_SIDED && + !mRttCapabilities.oneSidedRttSupported) { + Log.e(TAG, "Request " + index + ": One side RTT is not supported"); + return false; + } else if (params.requestType == RTT_TYPE_TWO_SIDED && + !mRttCapabilities.twoSided11McRttSupported) { + Log.e(TAG, "Request " + index + ": two side RTT is not supported"); + return false; + } else if ( params.numberBurst <= 0 ) { + Log.e(TAG, "Request " + index + ": Illegal number of burst: " + params.numberBurst); + return false; + } else if (params.numberBurst > 1 && params.interval <= 0) { + Log.e(TAG, "Request " + index + ": Illegal interval value: " + params.interval); + return false; + } else if (params.numSamplesPerBurst <= 0) { + Log.e(TAG, "Request " + index + ": Illegal sample number per burst: " + + params.numSamplesPerBurst); + return false; + } else if (params.numRetriesPerMeasurementFrame < 0 || params.numRetriesPerFTMR < 0) { + Log.e(TAG, "Request " + index + ": Illegal retry number"); + return false; + } else if (params.LCIRequest && !mRttCapabilities.lciSupported) { + Log.e(TAG, "Request " + index + ": LCI is not supported"); + return false; + } else if (params.LCRRequest && !mRttCapabilities.lcrSupported) { + Log.e(TAG, "Request " + index + ": LCR is not supported"); + return false; + } else if (params.burstTimeout <= 0){ + Log.e(TAG, "Request " + index + ": Illegal burst timeout: " + params.burstTimeout); + return false; + } else if ((params.preamble & mRttCapabilities.preambleSupported) == 0) { + Log.e(TAG, "Request " + index + ": Do not support this preamble: " + params.preamble); + return false; + } else if ((params.bandwidth & mRttCapabilities.bwSupported) == 0) { + Log.e(TAG, "Request " + index + ": Do not support this bandwidth: " + params.bandwidth); + return false; + } + + return true; + } + public void startRanging(RttParams[] params, RttListener listener) { + int index = 0; + for(RttParams rttParam : params) { + if (!rttParamSanity(rttParam, index)) { + throw new IllegalArgumentException("RTT Request Parameter Illegal"); + } + index++; + } + validateChannel(); ParcelableRttParams parcelableParams = new ParcelableRttParams(params); sAsyncChannel.sendMessage(CMD_OP_START_RANGING, @@ -315,12 +760,14 @@ public class RttManager { private Context mContext; private IRttManager mService; + private RttCapabilities mRttCapabilities; private static final int INVALID_KEY = 0; private static int sListenerKey = 1; private static final SparseArray sListenerMap = new SparseArray(); private static final Object sListenerMapLock = new Object(); + private static final Object sCapabilitiesLock = new Object(); private static AsyncChannel sAsyncChannel; private static CountDownLatch sConnected; From 2877877d4cb9ca220be28c136eee385550262354 Mon Sep 17 00:00:00 2001 From: Pierre Vandwalle Date: Mon, 16 Mar 2015 11:31:47 -0700 Subject: [PATCH 26/29] add BASE_WIFI_LOGGER to system protocol messages Change-Id: I4bb59b220208d5cb4fa415ad092970312392d8e4 --- core/java/com/android/internal/util/Protocol.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index d9ebc258a8b1b..a106f48745cfb 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -52,6 +52,7 @@ public class Protocol { public static final int BASE_WIFI_RTT_SERVICE = 0x00027300; public static final int BASE_WIFI_PASSPOINT_MANAGER = 0x00028000; public static final int BASE_WIFI_PASSPOINT_SERVICE = 0x00028100; + public static final int BASE_WIFI_LOGGER = 0x00028300; public static final int BASE_DHCP = 0x00030000; public static final int BASE_DATA_CONNECTION = 0x00040000; public static final int BASE_DATA_CONNECTION_AC = 0x00041000; From fd69e2a258c76300c47aff703d34281263d2a373 Mon Sep 17 00:00:00 2001 From: Naveen Kalla Date: Tue, 17 Mar 2015 15:20:53 -0700 Subject: [PATCH 27/29] Fix setSurfaceTexture to handle surface caching TextureView contains its surfaceTexture (i.e. mSurface) and its OnFrameAvailableListener(i.e. mUpdateListener). In order to apply a cached/pre-existing SurfaceTexture s1 to a TextureView, if we call TextureView.setSurfaceTexture(s1), the OnFrameAvailableListener of s1 should get set to mUpdateListener of TextureView since the mSurface has been updated. The existing code doesn't apply this and causes the frames to not be updated on a TextureView that uses setSurfaceTexture. This change fixes setSurfaceTexture method by setting s1's OnFrameAvailableListener to mUpdateListener. Change-Id: I4c1a704c587e977ab7a6b1fe3a7d3e0d20d00218 --- core/java/android/view/TextureView.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 59ec058b35dd6..ad34f020fa9d5 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -723,6 +723,12 @@ public class TextureView extends View { mSurface.release(); } mSurface = surfaceTexture; + + // If the view is visible, update the listener in the new surface to use + // the existing listener in the view. + if (((mViewFlags & VISIBILITY_MASK) == VISIBLE)) { + mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler); + } mUpdateSurface = true; invalidateParentIfNeeded(); } From e1d0f58aa85531e261f10ff132018a0e8fac8370 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Wed, 18 Mar 2015 16:38:08 -0700 Subject: [PATCH 28/29] Make Opportunistic Scan API public. Change-Id: I47da0f7e385f0a72815e493852283a44370aa1ce --- api/current.txt | 1 + api/system-current.txt | 1 + core/java/android/bluetooth/le/ScanSettings.java | 2 -- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/current.txt b/api/current.txt index 87ed7a95791c6..f9ea1a7ad1a5b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6662,6 +6662,7 @@ package android.bluetooth.le { field public static final int SCAN_MODE_BALANCED = 1; // 0x1 field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 + field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff } public static final class ScanSettings.Builder { diff --git a/api/system-current.txt b/api/system-current.txt index 34fb8ca1c3216..a1b53c1441d00 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -6889,6 +6889,7 @@ package android.bluetooth.le { field public static final int SCAN_MODE_BALANCED = 1; // 0x1 field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2 field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0 + field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1 field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0 } diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 5bdfdb544c449..0106686f8f823 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -29,8 +29,6 @@ public final class ScanSettings implements Parcelable { /** * A special Bluetooth LE scan mode. Applications using this scan mode will passively listen for * other scan results without starting BLE scans themselves. - * - * @hide */ public static final int SCAN_MODE_OPPORTUNISTIC = -1; From ad25bb89251c0552cfbc6c254853c79b7d9c121a Mon Sep 17 00:00:00 2001 From: Vinit Deshpande Date: Wed, 18 Mar 2015 17:00:30 -0700 Subject: [PATCH 29/29] More fixes to get passpoint working Change-Id: If8639bb0fd3bdaad7ee09217a9152c1695cb9354 --- wifi/java/android/net/wifi/WifiConfiguration.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 50beda7f1fb8e..34ae386fa45e9 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -950,8 +950,7 @@ public class WifiConfiguration implements Parcelable { * Identify if this configuration represents a passpoint network */ public boolean isPasspoint() { - return TextUtils.isEmpty(SSID) - && !TextUtils.isEmpty(FQDN) + return !TextUtils.isEmpty(FQDN) && !TextUtils.isEmpty(providerFriendlyName) && enterpriseConfig != null && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;