diff --git a/api/system-current.txt b/api/system-current.txt index 4ba50c0ae990f..ca5b949a414f0 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -26114,9 +26114,10 @@ package android.net.metrics { field public static final int IPCE_IPMGR_PROVISIONING_FAIL = 4097; // 0x1001 field public static final int IPCE_IPMGR_PROVISIONING_OK = 4096; // 0x1000 field public static final int IPCE_IPRM_BASE = 0; // 0x0 - field public static final int IPCE_IPRM_MESSAGE_RECEIVED = 1; // 0x1 - field public static final int IPCE_IPRM_PROBE_RESULT = 0; // 0x0 - field public static final int IPCE_IPRM_REACHABILITY_LOST = 2; // 0x2 + field public static final int IPCE_IPRM_NUD_FAILED = 2; // 0x2 + field public static final int IPCE_IPRM_PROBE_FAILURE = 1; // 0x1 + field public static final int IPCE_IPRM_PROBE_STARTED = 0; // 0x0 + field public static final int IPCE_IPRM_PROVISIONING_LOST = 3; // 0x3 field public static final int IPCE_NETMON_BASE = 2048; // 0x800 field public static final int IPCE_NETMON_CHECK_RESULT = 2049; // 0x801 field public static final int IPCE_NETMON_STATE_CHANGE = 2048; // 0x800 @@ -26131,35 +26132,20 @@ package android.net.metrics { field public final java.lang.String ifName; } - public final class IpReachabilityMonitorLostEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable { + public final class IpReachabilityEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable { method public int describeContents(); - method public static void logEvent(java.lang.String); + method public static void logNudFailed(java.lang.String); + method public static void logProbeEvent(java.lang.String, int); + method public static void logProvisioningLost(java.lang.String); method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; + field public static final android.os.Parcelable.Creator CREATOR; + field public static final int NUD_FAILED = 512; // 0x200 + field public static final int PROBE = 256; // 0x100 + field public static final int PROVISIONING_LOST = 768; // 0x300 + field public final int eventType; field public final java.lang.String ifName; } - public final class IpReachabilityMonitorMessageEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable { - method public int describeContents(); - method public static void logEvent(java.lang.String, java.lang.String, int, int); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - field public final java.lang.String destination; - field public final java.lang.String ifName; - field public final int msgType; - field public final int nudState; - } - - public final class IpReachabilityMonitorProbeEvent extends android.net.metrics.IpConnectivityEvent implements android.os.Parcelable { - method public int describeContents(); - method public static void logEvent(java.lang.String, java.lang.String, boolean); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; - field public final java.lang.String destination; - field public final java.lang.String ifName; - field public final boolean success; - } - } package android.net.nsd { diff --git a/core/java/android/net/metrics/IpConnectivityEvent.java b/core/java/android/net/metrics/IpConnectivityEvent.java index 2eb8edb0702f7..d455a0fcdaa5d 100644 --- a/core/java/android/net/metrics/IpConnectivityEvent.java +++ b/core/java/android/net/metrics/IpConnectivityEvent.java @@ -39,9 +39,10 @@ public abstract class IpConnectivityEvent { public static final int IPCE_IPMGR_BASE = 4 * 1024; public static final int IPCE_DNS_BASE = 5 * 1024; - public static final int IPCE_IPRM_PROBE_RESULT = IPCE_IPRM_BASE + 0; - public static final int IPCE_IPRM_MESSAGE_RECEIVED = IPCE_IPRM_BASE + 1; - public static final int IPCE_IPRM_REACHABILITY_LOST = IPCE_IPRM_BASE + 2; + public static final int IPCE_IPRM_PROBE_STARTED = IPCE_IPRM_BASE + 0; + public static final int IPCE_IPRM_PROBE_FAILURE = IPCE_IPRM_BASE + 1; + public static final int IPCE_IPRM_NUD_FAILED = IPCE_IPRM_BASE + 2; + public static final int IPCE_IPRM_PROVISIONING_LOST = IPCE_IPRM_BASE + 3; public static final int IPCE_DHCP_RECV_ERROR = IPCE_DHCP_BASE + 0; public static final int IPCE_DHCP_PARSE_ERROR = IPCE_DHCP_BASE + 1; diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java new file mode 100644 index 0000000000000..73dcb947f9f68 --- /dev/null +++ b/core/java/android/net/metrics/IpReachabilityEvent.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016 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.metrics; + +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * {@hide} + */ +@SystemApi +public final class IpReachabilityEvent extends IpConnectivityEvent implements Parcelable { + + public static final int PROBE = 1 << 8; + public static final int NUD_FAILED = 2 << 8; + public static final int PROVISIONING_LOST = 3 << 8; + + public final String ifName; + // eventType byte format (MSB to LSB): + // byte 0: unused + // byte 1: unused + // byte 2: type of event: PROBE, NUD_FAILED, PROVISIONING_LOST + // byte 3: kernel errno from RTNetlink or IpReachabilityMonitor + public final int eventType; + + private IpReachabilityEvent(String ifName, int eventType) { + this.ifName = ifName; + this.eventType = eventType; + } + + private IpReachabilityEvent(Parcel in) { + this.ifName = in.readString(); + this.eventType = in.readInt(); + } + + public void writeToParcel(Parcel out, int flags) { + out.writeString(ifName); + out.writeInt(eventType); + } + + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public IpReachabilityEvent createFromParcel(Parcel in) { + return new IpReachabilityEvent(in); + } + + public IpReachabilityEvent[] newArray(int size) { + return new IpReachabilityEvent[size]; + } + }; + + public static void logProbeEvent(String ifName, int nlErrorCode) { + final int tag = (nlErrorCode == 0) ? IPCE_IPRM_PROBE_STARTED : IPCE_IPRM_PROBE_FAILURE; + final int eventType = PROBE | (nlErrorCode & 0xFF); + logEvent(tag, new IpReachabilityEvent(ifName, eventType)); + } + + public static void logNudFailed(String ifName) { + logEvent(IPCE_IPRM_NUD_FAILED, new IpReachabilityEvent(ifName, NUD_FAILED)); + } + + public static void logProvisioningLost(String ifName) { + logEvent(IPCE_IPRM_PROVISIONING_LOST, new IpReachabilityEvent(ifName, PROVISIONING_LOST)); + } +}; diff --git a/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java deleted file mode 100644 index 52159954ad705..0000000000000 --- a/core/java/android/net/metrics/IpReachabilityMonitorLostEvent.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2016 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.metrics; - -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -/** - * {@hide} - */ -@SystemApi -public final class IpReachabilityMonitorLostEvent extends IpConnectivityEvent - implements Parcelable { - public final String ifName; - - private IpReachabilityMonitorLostEvent(String ifName) { - this.ifName = ifName; - } - - private IpReachabilityMonitorLostEvent(Parcel in) { - this.ifName = in.readString(); - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(ifName); - } - - public int describeContents() { - return 0; - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public IpReachabilityMonitorLostEvent createFromParcel(Parcel in) { - return new IpReachabilityMonitorLostEvent(in); - } - - public IpReachabilityMonitorLostEvent[] newArray(int size) { - return new IpReachabilityMonitorLostEvent[size]; - } - }; - - public static void logEvent(String ifName) { - logEvent(IPCE_IPRM_REACHABILITY_LOST, new IpReachabilityMonitorLostEvent(ifName)); - } -}; diff --git a/core/java/android/net/metrics/IpReachabilityMonitorMessageEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorMessageEvent.java deleted file mode 100644 index 0ed8c1c9405bc..0000000000000 --- a/core/java/android/net/metrics/IpReachabilityMonitorMessageEvent.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2016 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.metrics; - -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -/** - * {@hide} - */ -@SystemApi -public final class IpReachabilityMonitorMessageEvent extends IpConnectivityEvent - implements Parcelable { - public final String ifName; - public final String destination; - public final int msgType; - public final int nudState; - - private IpReachabilityMonitorMessageEvent(String ifName, String destination, int msgType, - int nudState) { - this.ifName = ifName; - this.destination = destination; - this.msgType = msgType; - this.nudState = nudState; - } - - private IpReachabilityMonitorMessageEvent(Parcel in) { - this.ifName = in.readString(); - this.destination = in.readString(); - this.msgType = in.readInt(); - this.nudState = in.readInt(); - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(ifName); - out.writeString(destination); - out.writeInt(msgType); - out.writeInt(nudState); - } - - public int describeContents() { - return 0; - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public IpReachabilityMonitorMessageEvent createFromParcel(Parcel in) { - return new IpReachabilityMonitorMessageEvent(in); - } - - public IpReachabilityMonitorMessageEvent[] newArray(int size) { - return new IpReachabilityMonitorMessageEvent[size]; - } - }; - - public static void logEvent(String ifName, String destination, int msgType, int nudState) { - logEvent(IPCE_IPRM_MESSAGE_RECEIVED, - new IpReachabilityMonitorMessageEvent(ifName, destination, msgType, nudState)); - } -}; diff --git a/core/java/android/net/metrics/IpReachabilityMonitorProbeEvent.java b/core/java/android/net/metrics/IpReachabilityMonitorProbeEvent.java deleted file mode 100644 index a55c2b46f9845..0000000000000 --- a/core/java/android/net/metrics/IpReachabilityMonitorProbeEvent.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2016 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.metrics; - -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -/** - * {@hide} - */ -@SystemApi -public final class IpReachabilityMonitorProbeEvent extends IpConnectivityEvent - implements Parcelable { - public final String ifName; - public final String destination; - public final boolean success; - - private IpReachabilityMonitorProbeEvent(String ifName, String destination, boolean success) { - this.ifName = ifName; - this.destination = destination; - this.success = success; - } - - private IpReachabilityMonitorProbeEvent(Parcel in) { - this.ifName = in.readString(); - this.destination = in.readString(); - this.success = in.readByte() > 0 ? true : false; - } - - public void writeToParcel(Parcel out, int flags) { - out.writeString(ifName); - out.writeString(destination); - out.writeByte((byte)(success ? 1 : 0)); - } - - public int describeContents() { - return 0; - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public IpReachabilityMonitorProbeEvent createFromParcel(Parcel in) { - return new IpReachabilityMonitorProbeEvent(in); - } - - public IpReachabilityMonitorProbeEvent[] newArray(int size) { - return new IpReachabilityMonitorProbeEvent[size]; - } - }; - - public static void logEvent(String ifName, String destination, boolean success) { - logEvent(IPCE_IPRM_PROBE_RESULT, - new IpReachabilityMonitorProbeEvent(ifName, destination, success)); - } -}; diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java index c8dbe029394ca..27600a768896b 100644 --- a/services/net/java/android/net/ip/IpReachabilityMonitor.java +++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java @@ -24,9 +24,7 @@ import android.net.LinkProperties; import android.net.LinkProperties.ProvisioningChange; import android.net.ProxyInfo; import android.net.RouteInfo; -import android.net.metrics.IpReachabilityMonitorMessageEvent; -import android.net.metrics.IpReachabilityMonitorProbeEvent; -import android.net.metrics.IpReachabilityMonitorLostEvent; +import android.net.metrics.IpReachabilityEvent; import android.net.netlink.NetlinkConstants; import android.net.netlink.NetlinkErrorMessage; import android.net.netlink.NetlinkMessage; @@ -168,47 +166,54 @@ public class IpReachabilityMonitor { * Make the kernel perform neighbor reachability detection (IPv4 ARP or IPv6 ND) * for the given IP address on the specified interface index. * - * @return true, if the request was successfully passed to the kernel; false otherwise. + * @return 0 if the request was successfully passed to the kernel; otherwise return + * a non-zero error code. */ - public static boolean probeNeighbor(int ifIndex, InetAddress ip) { - final long IO_TIMEOUT = 300L; + private static int probeNeighbor(int ifIndex, InetAddress ip) { final String msgSnippet = "probing ip=" + ip.getHostAddress() + "%" + ifIndex; if (DBG) { Log.d(TAG, msgSnippet); } final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage( 1, ip, StructNdMsg.NUD_PROBE, ifIndex, null); - boolean returnValue = false; + int errno = -OsConstants.EPROTO; try (NetlinkSocket nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE)) { + final long IO_TIMEOUT = 300L; nlSocket.connectToKernel(); nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT); final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT); + // recvMessage() guaranteed to not return null if it did not throw. final NetlinkMessage response = NetlinkMessage.parse(bytes); if (response != null && response instanceof NetlinkErrorMessage && - (((NetlinkErrorMessage) response).getNlMsgError() != null) && - (((NetlinkErrorMessage) response).getNlMsgError().error == 0)) { - returnValue = true; - } else { - String errmsg; - if (bytes == null) { - errmsg = "null recvMessage"; - } else if (response == null) { - bytes.position(0); - errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes); - } else { + (((NetlinkErrorMessage) response).getNlMsgError() != null)) { + errno = ((NetlinkErrorMessage) response).getNlMsgError().error; + if (errno != 0) { // TODO: consider ignoring EINVAL (-22), which appears to be // normal when probing a neighbor for which the kernel does // not already have / no longer has a link layer address. + Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + response.toString()); + } + } else { + String errmsg; + if (response == null) { + bytes.position(0); + errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes); + } else { errmsg = response.toString(); } Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + errmsg); } - } catch (ErrnoException | InterruptedIOException | SocketException e) { - Log.d(TAG, "Error " + msgSnippet, e); + } catch (ErrnoException e) { + Log.e(TAG, "Error " + msgSnippet, e); + errno = -e.errno; + } catch (InterruptedIOException e) { + Log.e(TAG, "Error " + msgSnippet, e); + errno = -OsConstants.ETIMEDOUT; + } catch (SocketException e) { + Log.e(TAG, "Error " + msgSnippet, e); + errno = -OsConstants.EIO; } - IpReachabilityMonitorProbeEvent.logEvent("ifindex-" + ifIndex, ip.getHostAddress(), - returnValue); - return returnValue; + return errno; } public IpReachabilityMonitor(Context context, String ifName, Callback callback) @@ -354,7 +359,7 @@ public class IpReachabilityMonitor { } if (delta == ProvisioningChange.LOST_PROVISIONING) { - IpReachabilityMonitorLostEvent.logEvent(mInterfaceName); + IpReachabilityEvent.logProvisioningLost(mInterfaceName); final String logMsg = "FAILURE: LOST_PROVISIONING, " + msg; Log.w(TAG, logMsg); if (mCallback != null) { @@ -362,6 +367,8 @@ public class IpReachabilityMonitor { // an InetAddress argument. mCallback.notifyLost(ip, logMsg); } + } else { + IpReachabilityEvent.logNudFailed(mInterfaceName); } } @@ -385,7 +392,8 @@ public class IpReachabilityMonitor { if (!stillRunning()) { break; } - probeNeighbor(mInterfaceIndex, target); + final int returnValue = probeNeighbor(mInterfaceIndex, target); + IpReachabilityEvent.logProbeEvent(mInterfaceName, returnValue); } } @@ -523,8 +531,6 @@ public class IpReachabilityMonitor { final short msgType = neighMsg.getHeader().nlmsg_type; final short nudState = ndMsg.ndm_state; - IpReachabilityMonitorMessageEvent.logEvent(mInterfaceName, - destination.getHostAddress(), msgType, nudState); final String eventMsg = "NeighborEvent{" + "elapsedMs=" + whenMs + ", " + destination.getHostAddress() + ", "