WifiP2pDevice.java revision 55bc5f3e0408bcb5a39a6732de0b2d1aa99a55be
1/* 2 * Copyright (C) 2011 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 17package android.net.wifi.p2p; 18 19import android.os.Parcelable; 20import android.os.Parcel; 21import android.util.Log; 22 23import java.util.regex.Pattern; 24 25/** 26 * A class representing a Wi-Fi p2p device 27 * @hide 28 */ 29public class WifiP2pDevice implements Parcelable { 30 31 private static final String TAG = "WifiP2pDevice"; 32 /** 33 * Device name 34 */ 35 public String deviceName; 36 37 /** 38 * Device MAC address 39 */ 40 public String deviceAddress; 41 42 /** 43 * interfaceAddress 44 * 45 * This address is used during group owner negotiation as the Intended 46 * P2P Interface Address and the group interface will be created with 47 * address as the local address in case of successfully completed 48 * negotiation. 49 */ 50 public String interfaceAddress; 51 52 /** 53 * Primary device type 54 */ 55 public String primaryDeviceType; 56 57 /** 58 * Secondary device type 59 */ 60 public String secondaryDeviceType; 61 62 63 // These definitions match the ones in wpa_supplicant 64 /* WPS config methods supported */ 65 private static final int WPS_CONFIG_USBA = 0x0001; 66 private static final int WPS_CONFIG_ETHERNET = 0x0002; 67 private static final int WPS_CONFIG_LABEL = 0x0004; 68 private static final int WPS_CONFIG_DISPLAY = 0x0008; 69 private static final int WPS_CONFIG_EXT_NFC_TOKEN = 0x0010; 70 private static final int WPS_CONFIG_INT_NFC_TOKEN = 0x0020; 71 private static final int WPS_CONFIG_NFC_INTERFACE = 0x0040; 72 private static final int WPS_CONFIG_PUSHBUTTON = 0x0080; 73 private static final int WPS_CONFIG_KEYPAD = 0x0100; 74 private static final int WPS_CONFIG_VIRT_PUSHBUTTON = 0x0280; 75 private static final int WPS_CONFIG_PHY_PUSHBUTTON = 0x0480; 76 private static final int WPS_CONFIG_VIRT_DISPLAY = 0x2008; 77 private static final int WPS_CONFIG_PHY_DISPLAY = 0x4008; 78 79 /* Device Capability bitmap */ 80 private static final int DEVICE_CAPAB_SERVICE_DISCOVERY = 1; 81 private static final int DEVICE_CAPAB_CLIENT_DISCOVERABILITY = 1<<1; 82 private static final int DEVICE_CAPAB_CONCURRENT_OPER = 1<<2; 83 private static final int DEVICE_CAPAB_INFRA_MANAGED = 1<<3; 84 private static final int DEVICE_CAPAB_DEVICE_LIMIT = 1<<4; 85 private static final int DEVICE_CAPAB_INVITATION_PROCEDURE = 1<<5; 86 87 /* Group Capability bitmap */ 88 private static final int GROUP_CAPAB_GROUP_OWNER = 1; 89 private static final int GROUP_CAPAB_PERSISTENT_GROUP = 1<<1; 90 private static final int GROUP_CAPAB_GROUP_LIMIT = 1<<2; 91 private static final int GROUP_CAPAB_INTRA_BSS_DIST = 1<<3; 92 private static final int GROUP_CAPAB_CROSS_CONN = 1<<4; 93 private static final int GROUP_CAPAB_PERSISTENT_RECONN = 1<<5; 94 private static final int GROUP_CAPAB_GROUP_FORMATION = 1<<6; 95 96 /** 97 * WPS config methods supported 98 */ 99 public int wpsConfigMethodsSupported; 100 101 /** 102 * Device capability 103 */ 104 public int deviceCapability; 105 106 /** 107 * Group capability 108 */ 109 public int groupCapability; 110 111 public enum Status { 112 CONNECTED, 113 INVITED, 114 FAILED, 115 AVAILABLE, 116 UNAVAILABLE, 117 } 118 119 public Status status = Status.UNAVAILABLE; 120 121 public WifiP2pDevice() { 122 } 123 124 /** 125 * @param string formats supported include 126 * P2P-DEVICE-FOUND fa:7b:7a:42:02:13 p2p_dev_addr=fa:7b:7a:42:02:13 127 * pri_dev_type=1-0050F204-1 name='p2p-TEST1' config_methods=0x188 dev_capab=0x27 128 * group_capab=0x0 129 * 130 * P2P-DEVICE-LOST p2p_dev_addr=fa:7b:7a:42:02:13 131 * 132 * fa:7b:7a:42:02:13 133 * 134 * P2P-PROV-DISC-PBC-REQ 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27 135 * pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 136 * group_capab=0x0 137 * 138 * P2P-PROV-DISC-ENTER-PIN 42:fc:89:e1:e2:27 p2p_dev_addr=42:fc:89:e1:e2:27 139 * pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 140 * group_capab=0x0 141 * 142 * P2P-PROV-DISC-SHOW-PIN 42:fc:89:e1:e2:27 44490607 p2p_dev_addr=42:fc:89:e1:e2:27 143 * pri_dev_type=1-0050F204-1 name='p2p-TEST2' config_methods=0x188 dev_capab=0x27 144 * group_capab=0x0 145 * 146 * Note: The events formats can be looked up in the wpa_supplicant code 147 */ 148 public WifiP2pDevice(String string) throws IllegalArgumentException { 149 String[] tokens = string.split(" "); 150 151 if (tokens.length < 1) { 152 throw new IllegalArgumentException("Malformed supplicant event"); 153 } 154 155 /* Just a device address */ 156 if (tokens.length == 1) { 157 deviceAddress = string; 158 return; 159 } 160 161 Pattern p = Pattern.compile("(?:[0-9a-f]{2}:){5}[0-9a-f]{2}", Pattern.CASE_INSENSITIVE); 162 if (p.matcher(tokens[1]).matches()) interfaceAddress = tokens[1]; 163 164 for (String token : tokens) { 165 String[] nameValue = token.split("="); 166 if (nameValue.length != 2) continue; 167 168 if (nameValue[0].equals("p2p_dev_addr")) { 169 deviceAddress = nameValue[1]; 170 continue; 171 } 172 173 if (nameValue[0].equals("pri_dev_type")) { 174 primaryDeviceType = nameValue[1]; 175 continue; 176 } 177 178 if (nameValue[0].equals("name")) { 179 deviceName = trimQuotes(nameValue[1]); 180 } 181 182 if (nameValue[0].equals("config_methods")) { 183 wpsConfigMethodsSupported = parseHex(nameValue[1]); 184 continue; 185 } 186 187 if (nameValue[0].equals("dev_capab")) { 188 deviceCapability = parseHex(nameValue[1]); 189 continue; 190 } 191 192 if (nameValue[0].equals("group_capab")) { 193 groupCapability = parseHex(nameValue[1]); 194 continue; 195 } 196 } 197 198 if (tokens[0].startsWith("P2P-DEVICE-FOUND")) { 199 status = Status.AVAILABLE; 200 } 201 } 202 203 public boolean isGroupOwner() { 204 return (groupCapability & GROUP_CAPAB_GROUP_OWNER) != 0; 205 } 206 207 @Override 208 public boolean equals(Object obj) { 209 if (this == obj) return true; 210 if (!(obj instanceof WifiP2pDevice)) return false; 211 212 WifiP2pDevice other = (WifiP2pDevice) obj; 213 if (other == null || other.deviceAddress == null) { 214 return (deviceAddress == null); 215 } 216 //STOPSHIP: fix later 217 //return other.deviceAddress.equals(deviceAddress); 218 return other.deviceAddress.startsWith(deviceAddress.substring(0,8)); 219 } 220 221 public String toString() { 222 StringBuffer sbuf = new StringBuffer(); 223 sbuf.append("Device: ").append(deviceName); 224 sbuf.append("\n deviceAddress: ").append(deviceAddress); 225 sbuf.append("\n interfaceAddress: ").append(interfaceAddress); 226 sbuf.append("\n primary type: ").append(primaryDeviceType); 227 sbuf.append("\n secondary type: ").append(secondaryDeviceType); 228 sbuf.append("\n wps: ").append(wpsConfigMethodsSupported); 229 sbuf.append("\n grpcapab: ").append(groupCapability); 230 sbuf.append("\n devcapab: ").append(deviceCapability); 231 sbuf.append("\n status: ").append(status); 232 return sbuf.toString(); 233 } 234 235 /** Implement the Parcelable interface {@hide} */ 236 public int describeContents() { 237 return 0; 238 } 239 240 /** copy constructor {@hide} */ 241 public WifiP2pDevice(WifiP2pDevice source) { 242 if (source != null) { 243 deviceName = source.deviceName; 244 deviceAddress = source.deviceAddress; 245 interfaceAddress = source.interfaceAddress; 246 primaryDeviceType = source.primaryDeviceType; 247 secondaryDeviceType = source.secondaryDeviceType; 248 wpsConfigMethodsSupported = source.wpsConfigMethodsSupported; 249 deviceCapability = source.deviceCapability; 250 groupCapability = source.groupCapability; 251 status = source.status; 252 } 253 } 254 255 /** Implement the Parcelable interface {@hide} */ 256 public void writeToParcel(Parcel dest, int flags) { 257 dest.writeString(deviceName); 258 dest.writeString(deviceAddress); 259 dest.writeString(interfaceAddress); 260 dest.writeString(primaryDeviceType); 261 dest.writeString(secondaryDeviceType); 262 dest.writeInt(wpsConfigMethodsSupported); 263 dest.writeInt(deviceCapability); 264 dest.writeInt(groupCapability); 265 dest.writeString(status.name()); 266 } 267 268 /** Implement the Parcelable interface {@hide} */ 269 public static final Creator<WifiP2pDevice> CREATOR = 270 new Creator<WifiP2pDevice>() { 271 public WifiP2pDevice createFromParcel(Parcel in) { 272 WifiP2pDevice device = new WifiP2pDevice(); 273 device.deviceName = in.readString(); 274 device.deviceAddress = in.readString(); 275 device.interfaceAddress = in.readString(); 276 device.primaryDeviceType = in.readString(); 277 device.secondaryDeviceType = in.readString(); 278 device.wpsConfigMethodsSupported = in.readInt(); 279 device.deviceCapability = in.readInt(); 280 device.groupCapability = in.readInt(); 281 device.status = Status.valueOf(in.readString()); 282 return device; 283 } 284 285 public WifiP2pDevice[] newArray(int size) { 286 return new WifiP2pDevice[size]; 287 } 288 }; 289 290 private String trimQuotes(String str) { 291 str = str.trim(); 292 if (str.startsWith("'") && str.endsWith("'")) { 293 return str.substring(1, str.length()-1); 294 } 295 return str; 296 } 297 298 //supported formats: 0x1abc, 0X1abc, 1abc 299 private int parseHex(String hexString) { 300 int num = 0; 301 if (hexString.startsWith("0x") || hexString.startsWith("0X")) { 302 hexString = hexString.substring(2); 303 } 304 305 try { 306 num = Integer.parseInt(hexString, 16); 307 } catch(NumberFormatException e) { 308 Log.e(TAG, "Failed to parse hex string " + hexString); 309 } 310 return num; 311 } 312} 313