1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.wifi.aware; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.net.NetworkCapabilities; 22 import android.net.TransportInfo; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import java.net.Inet6Address; 27 import java.net.NetworkInterface; 28 import java.net.SocketException; 29 import java.net.UnknownHostException; 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.List; 33 import java.util.Objects; 34 35 /** 36 * Wi-Fi Aware-specific network information. The information can be extracted from the 37 * {@link android.net.NetworkCapabilities} of the network using 38 * {@link NetworkCapabilities#getTransportInfo()}. 39 * The {@link NetworkCapabilities} is provided by the connectivity service to apps, e.g. received 40 * through the 41 * {@link android.net.ConnectivityManager.NetworkCallback#onCapabilitiesChanged(android.net.Network, 42 * android.net.NetworkCapabilities)} callback. 43 * <p> 44 * The Wi-Fi Aware-specific network information include the peer's scoped link-local IPv6 address 45 * for the Wi-Fi Aware link, as well as (optionally) the port and transport protocol specified by 46 * the peer. 47 * The scoped link-local IPv6, port, and transport protocol can then be used to create a 48 * {@link java.net.Socket} connection to the peer. 49 * <p> 50 * Note: these are the peer's IPv6 and port information - not the local device's! 51 */ 52 public final class WifiAwareNetworkInfo implements TransportInfo, Parcelable { 53 private final Inet6Address mIpv6Addr; 54 private final int mPort; 55 private final int mTransportProtocol; 56 private final List<WifiAwareChannelInfo> mChannelInfos; 57 58 /** @hide */ WifiAwareNetworkInfo()59 public WifiAwareNetworkInfo() { 60 mIpv6Addr = null; 61 mPort = 0; // a value of 0 is considered invalid 62 mTransportProtocol = -1; // a value of -1 is considered invalid 63 mChannelInfos = Collections.emptyList(); 64 } 65 66 /** @hide */ WifiAwareNetworkInfo(Inet6Address ipv6Addr)67 public WifiAwareNetworkInfo(Inet6Address ipv6Addr) { 68 mIpv6Addr = ipv6Addr; 69 mPort = 0; // a value of 0 is considered invalid 70 mTransportProtocol = -1; // a value of -1 is considered invalid 71 mChannelInfos = Collections.emptyList(); 72 } 73 74 /** @hide */ WifiAwareNetworkInfo(Inet6Address ipv6Addr, int port, int transportProtocol, List<WifiAwareChannelInfo> channelInfos)75 public WifiAwareNetworkInfo(Inet6Address ipv6Addr, int port, int transportProtocol, 76 List<WifiAwareChannelInfo> channelInfos) { 77 mIpv6Addr = ipv6Addr; 78 mPort = port; 79 mTransportProtocol = transportProtocol; 80 mChannelInfos = channelInfos; 81 } 82 WifiAwareNetworkInfo(@ullable WifiAwareNetworkInfo source)83 private WifiAwareNetworkInfo(@Nullable WifiAwareNetworkInfo source) { 84 mIpv6Addr = source != null ? source.mIpv6Addr : null; 85 mPort = source != null ? source.mPort : 0; 86 mTransportProtocol = source != null ? source.mTransportProtocol : -1; 87 mChannelInfos = source != null ? source.mChannelInfos : Collections.emptyList(); 88 } 89 90 /** 91 * Get the scoped link-local IPv6 address of the Wi-Fi Aware peer (not of the local device!). 92 * 93 * @return An IPv6 address. 94 */ 95 @Nullable getPeerIpv6Addr()96 public Inet6Address getPeerIpv6Addr() { 97 return mIpv6Addr; 98 } 99 100 /** 101 * Get the port number to be used to create a network connection to the Wi-Fi Aware peer. 102 * The port information is provided by the app running on the peer which requested the 103 * connection, using the {@link WifiAwareNetworkSpecifier.Builder#setPort(int)}. 104 * 105 * @return A port number on the peer. A value of 0 indicates that no port was specified by the 106 * peer. 107 */ getPort()108 public int getPort() { 109 return mPort; 110 } 111 112 /** 113 * Get the transport protocol to be used to communicate over a network connection to the Wi-Fi 114 * Aware peer. The transport protocol is provided by the app running on the peer which requested 115 * the connection, using the 116 * {@link WifiAwareNetworkSpecifier.Builder#setTransportProtocol(int)}. 117 * <p> 118 * The transport protocol number is assigned by the Internet Assigned Numbers Authority 119 * (IANA) https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml. 120 * 121 * @return A transport protocol id. A value of -1 indicates that no transport protocol was 122 * specified by the peer. 123 */ getTransportProtocol()124 public int getTransportProtocol() { 125 return mTransportProtocol; 126 } 127 128 /** 129 * Get a list {@link WifiAwareChannelInfo} which is used by this Aware data-path 130 * 131 * @return A list of {@link WifiAwareChannelInfo} 132 */ 133 @NonNull getChannelInfoList()134 public List<WifiAwareChannelInfo> getChannelInfoList() { 135 return mChannelInfos; 136 } 137 138 // parcelable methods 139 140 @Override describeContents()141 public int describeContents() { 142 return 0; 143 } 144 145 @Override writeToParcel(Parcel dest, int flags)146 public void writeToParcel(Parcel dest, int flags) { 147 dest.writeByteArray(mIpv6Addr.getAddress()); 148 NetworkInterface ni = mIpv6Addr.getScopedInterface(); 149 dest.writeString(ni == null ? null : ni.getName()); 150 dest.writeInt(mPort); 151 dest.writeInt(mTransportProtocol); 152 dest.writeTypedList(mChannelInfos); 153 } 154 155 public static final @NonNull Creator<WifiAwareNetworkInfo> CREATOR = 156 new Creator<WifiAwareNetworkInfo>() { 157 @Override 158 public WifiAwareNetworkInfo createFromParcel(Parcel in) { 159 byte[] addr = in.createByteArray(); 160 String interfaceName = in.readString(); 161 int port = in.readInt(); 162 int transportProtocol = in.readInt(); 163 Inet6Address ipv6Addr; 164 List<WifiAwareChannelInfo> channelInfos = new ArrayList<>(); 165 in.readTypedList(channelInfos, WifiAwareChannelInfo.CREATOR); 166 try { 167 NetworkInterface ni = null; 168 if (interfaceName != null) { 169 try { 170 ni = NetworkInterface.getByName(interfaceName); 171 } catch (SocketException e) { 172 e.printStackTrace(); 173 } 174 } 175 ipv6Addr = Inet6Address.getByAddress(null, addr, ni); 176 } catch (UnknownHostException e) { 177 e.printStackTrace(); 178 return new WifiAwareNetworkInfo(); 179 } 180 return new WifiAwareNetworkInfo(ipv6Addr, port, transportProtocol, 181 channelInfos); 182 } 183 184 @Override 185 public WifiAwareNetworkInfo[] newArray(int size) { 186 return new WifiAwareNetworkInfo[size]; 187 } 188 }; 189 190 191 // object methods 192 193 @Override toString()194 public String toString() { 195 return new StringBuilder("AwareNetworkInfo: IPv6=").append(mIpv6Addr) 196 .append(", port=").append(mPort) 197 .append(", transportProtocol=").append(mTransportProtocol) 198 .append(", channelInfos=").append(mChannelInfos) 199 .toString(); 200 } 201 202 /** @hide */ 203 @Override equals(Object obj)204 public boolean equals(Object obj) { 205 if (this == obj) { 206 return true; 207 } 208 209 if (!(obj instanceof WifiAwareNetworkInfo)) { 210 return false; 211 } 212 213 WifiAwareNetworkInfo lhs = (WifiAwareNetworkInfo) obj; 214 return Objects.equals(mIpv6Addr, lhs.mIpv6Addr) && mPort == lhs.mPort 215 && mTransportProtocol == lhs.mTransportProtocol 216 && mChannelInfos.equals(lhs.mChannelInfos); 217 } 218 219 /** @hide */ 220 @Override hashCode()221 public int hashCode() { 222 return Objects.hash(mIpv6Addr, mPort, mTransportProtocol, mChannelInfos); 223 } 224 } 225