WifiAwareDataPathStateManager.java revision 86e4c343394565f8e59e02d25334589f96de38f0
1/* 2 * Copyright (C) 2016 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 com.android.server.wifi.aware; 18 19import android.content.Context; 20import android.hardware.wifi.V1_0.NanDataPathChannelCfg; 21import android.net.ConnectivityManager; 22import android.net.IpPrefix; 23import android.net.LinkAddress; 24import android.net.LinkProperties; 25import android.net.NetworkAgent; 26import android.net.NetworkCapabilities; 27import android.net.NetworkFactory; 28import android.net.NetworkInfo; 29import android.net.NetworkRequest; 30import android.net.RouteInfo; 31import android.net.wifi.aware.WifiAwareManager; 32import android.os.IBinder; 33import android.os.INetworkManagementService; 34import android.os.Looper; 35import android.os.ServiceManager; 36import android.text.TextUtils; 37import android.util.ArrayMap; 38import android.util.Base64; 39import android.util.Log; 40 41import com.android.internal.annotations.VisibleForTesting; 42 43import libcore.util.HexEncoding; 44 45import org.json.JSONException; 46import org.json.JSONObject; 47 48import java.io.FileDescriptor; 49import java.io.PrintWriter; 50import java.net.Inet6Address; 51import java.net.InetAddress; 52import java.net.NetworkInterface; 53import java.net.SocketException; 54import java.util.Arrays; 55import java.util.Enumeration; 56import java.util.HashSet; 57import java.util.Iterator; 58import java.util.Map; 59import java.util.Set; 60 61/** 62 * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down. 63 * The Aware network configuration is: 64 * - transport = TRANSPORT_WIFI_AWARE 65 * - capabilities = NET_CAPABILITY_NOT_VPN 66 * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or 67 * WifiAwareManager.createNetworkSpecifier(...). 68 * The network specifier is encoded as a JSON string with the following key combos: 69 * TYPE_1A: type, role, client_id, session_id, peer_id, token 70 * TYPE_1B: type, role, client_id, session_id, peer_id [only permitted for RESPONDER] 71 * TYPE_2A: type, role, client_id, peer_mac, token 72 * TYPE_2B: type, role, client_id, peer_mac [only permitted for RESPONDER] 73 * TYPE_2C: type, role, client_id, token [only permitted for RESPONDER] 74 * TYPE_2D: type, role, client_id [only permitted for RESPONDER] 75 */ 76public class WifiAwareDataPathStateManager { 77 private static final String TAG = "WifiAwareDataPathStMgr"; 78 79 private static final boolean DBG = false; 80 private static final boolean VDBG = false; // STOPSHIP if true 81 82 private static final String AWARE_INTERFACE_PREFIX = "aware_data"; 83 private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY"; 84 private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_"; 85 private static final int NETWORK_FACTORY_SCORE_AVAIL = 1; 86 private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1; 87 private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1; 88 89 private final WifiAwareStateManager mMgr; 90 private final NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper(); 91 private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities(); 92 private final Set<String> mInterfaces = new HashSet<>(); 93 private final Map<String, AwareNetworkRequestInformation> mNetworkRequestsCache = 94 new ArrayMap<>(); 95 private Context mContext; 96 private Looper mLooper; 97 private WifiAwareNetworkFactory mNetworkFactory; 98 private INetworkManagementService mNwService; 99 100 public WifiAwareDataPathStateManager(WifiAwareStateManager mgr) { 101 mMgr = mgr; 102 } 103 104 /** 105 * Initialize the Aware data-path state manager. Specifically register the network factory with 106 * connectivity service. 107 */ 108 public void start(Context context, Looper looper) { 109 if (VDBG) Log.v(TAG, "start"); 110 111 mContext = context; 112 mLooper = looper; 113 114 mNetworkCapabilitiesFilter.clearAll(); 115 mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE); 116 mNetworkCapabilitiesFilter 117 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 118 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) 119 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 120 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); 121 mNetworkCapabilitiesFilter 122 .setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER); 123 mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL); 124 mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL); 125 mNetworkCapabilitiesFilter.setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL); 126 127 mNetworkFactory = new WifiAwareNetworkFactory(looper, context, mNetworkCapabilitiesFilter); 128 mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL); 129 mNetworkFactory.register(); 130 131 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 132 mNwService = INetworkManagementService.Stub.asInterface(b); 133 } 134 135 private Map.Entry<String, AwareNetworkRequestInformation> getNetworkRequestByNdpId(int ndpId) { 136 for (Map.Entry<String, AwareNetworkRequestInformation> entry : mNetworkRequestsCache 137 .entrySet()) { 138 if (entry.getValue().ndpId == ndpId) { 139 return entry; 140 } 141 } 142 143 return null; 144 } 145 146 /** 147 * Create all Aware data-path interfaces which are possible on the device - based on the 148 * capabilities of the firmware. 149 */ 150 public void createAllInterfaces() { 151 if (VDBG) Log.v(TAG, "createAllInterfaces"); 152 153 if (mMgr.getCapabilities() == null) { 154 Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!"); 155 return; 156 } 157 158 for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) { 159 String name = AWARE_INTERFACE_PREFIX + i; 160 if (mInterfaces.contains(name)) { 161 Log.e(TAG, "createAllInterfaces(): interface already up, " + name 162 + ", possibly failed to delete - deleting/creating again to be safe"); 163 mMgr.deleteDataPathInterface(name); 164 165 // critical to remove so that don't get infinite loop if the delete fails again 166 mInterfaces.remove(name); 167 } 168 169 mMgr.createDataPathInterface(name); 170 } 171 } 172 173 /** 174 * Delete all Aware data-path interfaces which are currently up. 175 */ 176 public void deleteAllInterfaces() { 177 if (VDBG) Log.v(TAG, "deleteAllInterfaces"); 178 179 for (String name : mInterfaces) { 180 mMgr.deleteDataPathInterface(name); 181 } 182 } 183 184 /** 185 * Called when firmware indicates the an interface was created. 186 */ 187 public void onInterfaceCreated(String interfaceName) { 188 if (VDBG) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName); 189 190 if (mInterfaces.contains(interfaceName)) { 191 Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName); 192 } 193 194 mInterfaces.add(interfaceName); 195 } 196 197 /** 198 * Called when firmware indicates the an interface was deleted. 199 */ 200 public void onInterfaceDeleted(String interfaceName) { 201 if (VDBG) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName); 202 203 if (!mInterfaces.contains(interfaceName)) { 204 Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName); 205 } 206 207 mInterfaces.remove(interfaceName); 208 } 209 210 /** 211 * Response to initiating data-path request. Indicates that request is successful (not 212 * complete!) and is now in progress. 213 * 214 * @param networkSpecifier The network specifier provided as part of the initiate request. 215 * @param ndpId The ID assigned to the data-path. 216 */ 217 public void onDataPathInitiateSuccess(String networkSpecifier, int ndpId) { 218 if (VDBG) { 219 Log.v(TAG, 220 "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId=" 221 + ndpId); 222 } 223 224 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 225 if (nnri == null) { 226 Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier=" 227 + networkSpecifier); 228 mMgr.endDataPath(ndpId); 229 return; 230 } 231 232 if (nnri.state 233 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { 234 Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state=" 235 + nnri.state); 236 mNetworkRequestsCache.remove(networkSpecifier); 237 mMgr.endDataPath(ndpId); 238 return; 239 } 240 241 nnri.state = AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_CONFIRM; 242 nnri.ndpId = ndpId; 243 } 244 245 /** 246 * Response to an attempt to set up a data-path (on the initiator side). 247 * 248 * @param networkSpecifier The network specifier provided as part of the initiate request. 249 * @param reason Failure reason. 250 */ 251 public void onDataPathInitiateFail(String networkSpecifier, int reason) { 252 if (VDBG) { 253 Log.v(TAG, 254 "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason=" 255 + reason); 256 } 257 258 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier); 259 if (nnri == null) { 260 Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier=" 261 + networkSpecifier); 262 return; 263 } 264 265 if (nnri.state 266 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { 267 Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state=" 268 + nnri.state); 269 } 270 271 mNetworkRequestsCache.remove(networkSpecifier); 272 } 273 274 275 /** 276 * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path 277 * connection with us. 278 * 279 * @param pubSubId The ID of the discovery session context for the data-path - or 0 if not 280 * related to a discovery session. 281 * @param mac The discovery MAC address of the peer. 282 * @param ndpId The locally assigned ID for the data-path. 283 * @param message A message sent from the peer as part of the data-path setup process. 284 * @return The network specifier of the data-path (or null if none/error) 285 */ 286 public String onDataPathRequest(int pubSubId, byte[] mac, int ndpId, byte[] message) { 287 if (VDBG) { 288 Log.v(TAG, 289 "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf( 290 HexEncoding.encode(mac)) + ", ndpId=" + ndpId); 291 } 292 293 String networkSpecifier = null; 294 AwareNetworkRequestInformation nnri = null; 295 for (Map.Entry<String, AwareNetworkRequestInformation> entry : mNetworkRequestsCache 296 .entrySet()) { 297 /* 298 * Checking that the incoming request (from the Initiator) matches the request 299 * we (the Responder) already have set up. The rules are: 300 * - The discovery session (pub/sub ID) must match. 301 * - The token (if specified - i.e. non-null) must match. A null token == accept any 302 * Initiator token. 303 * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC == 304 * accept (otherwise matching) requests from any peer MAC. 305 */ 306 if (entry.getValue().pubSubId != 0 && entry.getValue().pubSubId != pubSubId) { 307 continue; 308 } 309 310 if (entry.getValue().token != null && !Arrays.equals(entry.getValue().token, message)) { 311 continue; 312 } 313 314 if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals( 315 entry.getValue().peerDiscoveryMac, mac)) { 316 continue; 317 } 318 319 networkSpecifier = entry.getKey(); 320 nnri = entry.getValue(); 321 break; 322 } 323 324 if (nnri == null) { 325 Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId 326 + ", mac=" + String.valueOf(HexEncoding.encode(mac)) + ", message=" + message); 327 if (DBG) { 328 Log.d(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache); 329 } 330 mMgr.respondToDataPathRequest(false, ndpId, "", ""); 331 return null; 332 } 333 334 if (nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) { 335 Log.w(TAG, "onDataPathRequest: request " + networkSpecifier + " is incorrect state=" 336 + nnri.state); 337 mMgr.respondToDataPathRequest(false, ndpId, "", ""); 338 mNetworkRequestsCache.remove(networkSpecifier); 339 return null; 340 } 341 342 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE; 343 nnri.ndpId = ndpId; 344 nnri.interfaceName = selectInterfaceForRequest(nnri); 345 mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, ""); 346 347 return networkSpecifier; 348 } 349 350 /** 351 * Called on the RESPONDER when the response to data-path request has been completed. 352 * 353 * @param ndpId The ID of the data-path (NDP) 354 * @param success Whether or not the 'RespondToDataPathRequest' operation was a success. 355 */ 356 public void onRespondToDataPathRequest(int ndpId, boolean success) { 357 if (VDBG) { 358 Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success); 359 } 360 361 String networkSpecifier = null; 362 AwareNetworkRequestInformation nnri = null; 363 for (Map.Entry<String, AwareNetworkRequestInformation> entry : mNetworkRequestsCache 364 .entrySet()) { 365 if (entry.getValue().ndpId == ndpId) { 366 networkSpecifier = entry.getKey(); 367 nnri = entry.getValue(); 368 break; 369 } 370 } 371 372 if (nnri == null) { 373 Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId=" 374 + ndpId); 375 if (DBG) { 376 Log.d(TAG, "onRespondToDataPathRequest: network request cache = " 377 + mNetworkRequestsCache); 378 } 379 return; 380 } 381 382 if (!success) { 383 Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier 384 + " failed responding"); 385 mMgr.endDataPath(ndpId); 386 mNetworkRequestsCache.remove(networkSpecifier); 387 return; 388 } 389 390 if (nnri.state 391 != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE) { 392 Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier 393 + " is incorrect state=" + nnri.state); 394 mMgr.endDataPath(ndpId); 395 mNetworkRequestsCache.remove(networkSpecifier); 396 return; 397 } 398 399 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_CONFIRM; 400 } 401 402 /** 403 * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up) 404 * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's 405 * perspective - now can do L3 configuration. 406 * 407 * @param ndpId Id of the data-path 408 * @param mac The MAC address of the peer's data-path (not discovery interface). Only 409 * valid 410 * if {@code accept} is {@code true}. 411 * @param accept Indicates whether the data-path setup has succeeded (been accepted) or 412 * failed (been rejected). 413 * @param reason If {@code accept} is {@code false} provides a reason code for the 414 * rejection/failure. 415 * @param message The message provided by the peer as part of the data-path setup 416 * process. 417 * @return The network specifier of the data-path or a null if none/error. 418 */ 419 public String onDataPathConfirm(int ndpId, byte[] mac, boolean accept, int reason, 420 byte[] message) { 421 if (VDBG) { 422 Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf( 423 HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason); 424 } 425 426 Map.Entry<String, AwareNetworkRequestInformation> nnriE = getNetworkRequestByNdpId(ndpId); 427 if (nnriE == null) { 428 Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId); 429 if (accept) { 430 mMgr.endDataPath(ndpId); 431 } 432 return null; 433 } 434 435 String networkSpecifier = nnriE.getKey(); 436 AwareNetworkRequestInformation nnri = nnriE.getValue(); 437 438 // validate state 439 if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 440 && nnri.state != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_CONFIRM) { 441 Log.w(TAG, "onDataPathConfirm: INITIATOR in invalid state=" + nnri.state); 442 mNetworkRequestsCache.remove(networkSpecifier); 443 if (accept) { 444 mMgr.endDataPath(ndpId); 445 } 446 return networkSpecifier; 447 } 448 if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER 449 && nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_CONFIRM) { 450 Log.w(TAG, "onDataPathConfirm: RESPONDER in invalid state=" + nnri.state); 451 mNetworkRequestsCache.remove(networkSpecifier); 452 if (accept) { 453 mMgr.endDataPath(ndpId); 454 } 455 return networkSpecifier; 456 } 457 458 if (accept) { 459 nnri.state = (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) 460 ? AwareNetworkRequestInformation.STATE_INITIATOR_CONFIRMED 461 : AwareNetworkRequestInformation.STATE_RESPONDER_CONFIRMED; 462 nnri.peerDataMac = mac; 463 464 NetworkInfo networkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, 465 NETWORK_TAG, ""); 466 NetworkCapabilities networkCapabilities = new NetworkCapabilities( 467 mNetworkCapabilitiesFilter); 468 LinkProperties linkProperties = new LinkProperties(); 469 470 try { 471 mNwService.setInterfaceUp(nnri.interfaceName); 472 mNwService.enableIpv6(nnri.interfaceName); 473 } catch (Exception e) { // NwService throws runtime exceptions for errors 474 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": can't configure network - " 475 + e); 476 mMgr.endDataPath(ndpId); 477 return networkSpecifier; 478 } 479 480 if (!mNiWrapper.configureAgentProperties(nnri, networkSpecifier, ndpId, networkInfo, 481 networkCapabilities, linkProperties)) { 482 return networkSpecifier; 483 } 484 485 nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext, 486 AGENT_TAG_PREFIX + nnri.ndpId, 487 new NetworkInfo(ConnectivityManager.TYPE_WIFI_P2P, 0, NETWORK_TAG, ""), 488 networkCapabilities, new LinkProperties(), NETWORK_FACTORY_SCORE_AVAIL, 489 networkSpecifier, ndpId); 490 nnri.networkAgent.sendNetworkInfo(networkInfo); 491 nnri.networkAgent.sendLinkProperties(linkProperties); 492 } else { 493 if (DBG) { 494 Log.d(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier 495 + " rejected - reason=" + reason); 496 } 497 mNetworkRequestsCache.remove(networkSpecifier); 498 } 499 500 return networkSpecifier; 501 } 502 503 /** 504 * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has 505 * been terminated. 506 * 507 * @param ndpId The ID of the terminated data-path. 508 */ 509 public void onDataPathEnd(int ndpId) { 510 if (VDBG) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId); 511 512 Map.Entry<String, AwareNetworkRequestInformation> nnriE = getNetworkRequestByNdpId(ndpId); 513 if (nnriE == null) { 514 if (DBG) { 515 Log.d(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId); 516 } 517 return; 518 } 519 520 tearDownInterface(nnriE.getValue()); 521 mNetworkRequestsCache.remove(nnriE.getKey()); 522 } 523 524 /** 525 * Called whenever Aware comes down. Clean up all pending and up network requeests and agents. 526 */ 527 public void onAwareDownCleanupDataPaths() { 528 if (VDBG) Log.v(TAG, "onAwareDownCleanupDataPaths"); 529 530 for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) { 531 tearDownInterface(nnri); 532 } 533 mNetworkRequestsCache.clear(); 534 } 535 536 /** 537 * Called when timed-out waiting for confirmation of the data-path setup (i.e. 538 * onDataPathConfirm). Started on the initiator when executing the request for the data-path 539 * and on the responder when received a request for data-path (in both cases only on success 540 * - i.e. when we're proceeding with data-path setup). 541 */ 542 public void handleDataPathTimeout(String networkSpecifier) { 543 if (VDBG) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + networkSpecifier); 544 545 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier); 546 if (nnri == null) { 547 if (DBG) { 548 Log.d(TAG, 549 "handleDataPathTimeout: network request not found for networkSpecifier=" 550 + networkSpecifier); 551 } 552 return; 553 } 554 555 mMgr.endDataPath(nnri.ndpId); 556 } 557 558 private class WifiAwareNetworkFactory extends NetworkFactory { 559 WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) { 560 super(looper, context, NETWORK_TAG, filter); 561 } 562 563 @Override 564 public boolean acceptRequest(NetworkRequest request, int score) { 565 if (VDBG) { 566 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score=" 567 + score); 568 } 569 570 if (!mMgr.isUsageEnabled()) { 571 if (VDBG) { 572 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 573 + " -- Aware disabled"); 574 } 575 return false; 576 } 577 578 if (mInterfaces.isEmpty()) { 579 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 580 + " -- No Aware interfaces are up"); 581 return false; 582 } 583 584 String networkSpecifier = request.networkCapabilities.getNetworkSpecifier(); 585 if (TextUtils.isEmpty(networkSpecifier)) { 586 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 587 + " - empty (or null) NetworkSpecifier"); 588 return false; 589 } 590 591 // look up specifier - are we being called again? 592 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 593 if (nnri != null) { 594 if (DBG) { 595 Log.d(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 596 + " - already in cache!?"); 597 } 598 599 // seems to happen after a network agent is created - trying to rematch all 600 // requests again!? 601 return true; 602 } 603 604 // parse network specifier (JSON) & cache 605 // TODO: validate that the client ID actually comes from the correct process and is 606 // not faked? 607 nnri = AwareNetworkRequestInformation.parseNetworkSpecifier(networkSpecifier, mMgr); 608 if (nnri == null) { 609 Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 610 + " - can't parse network specifier"); 611 return false; 612 } 613 mNetworkRequestsCache.put(networkSpecifier, nnri); 614 615 return true; 616 } 617 618 @Override 619 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 620 if (VDBG) { 621 Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 622 + networkRequest + ", score=" + score); 623 } 624 625 String networkSpecifier = networkRequest.networkCapabilities.getNetworkSpecifier(); 626 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 627 if (nnri == null) { 628 Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 629 + networkRequest + " not in cache!?"); 630 return; 631 } 632 633 if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { 634 if (nnri.state != AwareNetworkRequestInformation.STATE_INITIATOR_IDLE) { 635 if (DBG) { 636 Log.d(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 637 + networkRequest + " - already in progress"); 638 // TODO: understand how/when can be called again/while in progress (seems 639 // to be related to score re-calculation after a network agent is created) 640 } 641 return; 642 } 643 644 nnri.interfaceName = selectInterfaceForRequest(nnri); 645 mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerId, 646 NanDataPathChannelCfg.REQUEST_CHANNEL_SETUP, selectChannelForRequest(nnri), 647 nnri.peerDiscoveryMac, nnri.interfaceName, nnri.token); 648 nnri.state = 649 AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE; 650 } else { 651 if (nnri.state != AwareNetworkRequestInformation.STATE_RESPONDER_IDLE) { 652 if (DBG) { 653 Log.d(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 654 + networkRequest + " - already in progress"); 655 // TODO: understand how/when can be called again/while in progress (seems 656 // to be related to score re-calculation after a network agent is created) 657 } 658 return; 659 } 660 661 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST; 662 } 663 } 664 665 @Override 666 protected void releaseNetworkFor(NetworkRequest networkRequest) { 667 if (VDBG) { 668 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 669 + networkRequest); 670 } 671 672 String networkSpecifier = networkRequest.networkCapabilities.getNetworkSpecifier(); 673 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 674 if (nnri == null) { 675 Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 676 + networkRequest + " not in cache!?"); 677 return; 678 } 679 680 if (nnri.networkAgent != null) { 681 if (VDBG) { 682 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 683 + networkRequest + ", nnri=" + nnri 684 + ": agent already created - deferring ending data-path to agent" 685 + ".unwanted()"); 686 } 687 return; 688 } 689 690 if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR && nnri.state 691 > AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { 692 mMgr.endDataPath(nnri.ndpId); 693 } 694 if (nnri.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER && nnri.state 695 > AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) { 696 mMgr.endDataPath(nnri.ndpId); 697 } 698 699 // Will get a callback (on both initiator and responder) when data-path actually 700 // terminated. At that point will inform the agent and will clear the cache. 701 } 702 } 703 704 private class WifiAwareNetworkAgent extends NetworkAgent { 705 private NetworkInfo mNetworkInfo; 706 private String mNetworkSpecifier; 707 private int mNdpId; 708 709 WifiAwareNetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, 710 NetworkCapabilities nc, LinkProperties lp, int score, String networkSpecifier, 711 int ndpId) { 712 super(looper, context, logTag, ni, nc, lp, score); 713 714 mNetworkInfo = ni; 715 mNetworkSpecifier = networkSpecifier; 716 mNdpId = ndpId; 717 } 718 719 @Override 720 protected void unwanted() { 721 if (VDBG) { 722 Log.v(TAG, "WifiAwareNetworkAgent.unwanted: networkSpecifier=" + mNetworkSpecifier 723 + ", ndpId=" + mNdpId); 724 } 725 726 mMgr.endDataPath(mNdpId); 727 728 // Will get a callback (on both initiator and responder) when data-path actually 729 // terminated. At that point will inform the agent and will clear the cache. 730 } 731 732 void reconfigureAgentAsDisconnected() { 733 if (VDBG) { 734 Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: networkSpecifier=" 735 + mNetworkSpecifier + ", ndpId=" + mNdpId); 736 } 737 738 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, ""); 739 sendNetworkInfo(mNetworkInfo); 740 } 741 } 742 743 private void tearDownInterface(AwareNetworkRequestInformation nnri) { 744 if (VDBG) Log.v(TAG, "tearDownInterface: nnri=" + nnri); 745 746 if (nnri.interfaceName != null && !nnri.interfaceName.isEmpty()) { 747 try { 748 mNwService.setInterfaceDown(nnri.interfaceName); 749 } catch (Exception e) { // NwService throws runtime exceptions for errors 750 Log.e(TAG, 751 "tearDownInterface: nnri=" + nnri + ": can't bring interface down - " + e); 752 } 753 } 754 755 if (nnri.networkAgent != null) { 756 nnri.networkAgent.reconfigureAgentAsDisconnected(); 757 } 758 } 759 760 /** 761 * Select one of the existing interfaces for the new network request. 762 * 763 * TODO: for now there is only a single interface - simply pick it. 764 */ 765 private String selectInterfaceForRequest(AwareNetworkRequestInformation req) { 766 Iterator<String> it = mInterfaces.iterator(); 767 if (it.hasNext()) { 768 return it.next(); 769 } 770 771 Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - but no interfaces available!"); 772 773 return ""; 774 } 775 776 /** 777 * Select a channel for the network request. 778 * 779 * TODO: for now simply select channel 6 780 */ 781 private int selectChannelForRequest(AwareNetworkRequestInformation req) { 782 return 2437; 783 } 784 785 /** 786 * Aware network request. State object: contains network request information/state through its 787 * lifetime. 788 */ 789 @VisibleForTesting 790 public static class AwareNetworkRequestInformation { 791 static final int STATE_INITIATOR_IDLE = 100; 792 static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 101; 793 static final int STATE_INITIATOR_WAIT_FOR_CONFIRM = 102; 794 static final int STATE_INITIATOR_CONFIRMED = 103; 795 796 static final int STATE_RESPONDER_IDLE = 200; 797 static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 201; 798 static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 202; 799 static final int STATE_RESPONDER_WAIT_FOR_CONFIRM = 203; 800 static final int STATE_RESPONDER_CONFIRMED = 204; 801 802 public int state; 803 public int role; 804 805 public int uid; 806 public String interfaceName; 807 public int pubSubId = 0; 808 public int peerId = 0; 809 public byte[] peerDiscoveryMac = null; 810 public byte[] token = null; 811 public int ndpId; 812 public byte[] peerDataMac; 813 814 public WifiAwareNetworkAgent networkAgent; 815 816 static AwareNetworkRequestInformation parseNetworkSpecifier(String networkSpecifier, 817 WifiAwareStateManager mgr) { 818 int type, role, uid, clientId, sessionId = 0, peerId = 0, pubSubId = 0; 819 byte[] peerMac = null; 820 byte[] token = null; 821 822 if (VDBG) { 823 Log.v(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier); 824 } 825 826 try { 827 JSONObject jsonObject = new JSONObject(networkSpecifier); 828 829 // type: always present 830 type = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_TYPE); 831 if (type < 0 || type > WifiAwareManager.NETWORK_SPECIFIER_TYPE_MAX_VALID) { 832 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 833 + ", invalid 'type' value"); 834 return null; 835 } 836 837 // role: always present 838 role = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_ROLE); 839 if (role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 840 && role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { 841 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 842 + " -- invalid 'role' value"); 843 return null; 844 } 845 846 if (role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 847 && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A 848 && type != WifiAwareManager.NETWORK_SPECIFIER_TYPE_2A) { 849 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 850 + " -- invalid 'type' value for INITIATOR (only 1A and 2A are " 851 + "permitted)"); 852 return null; 853 } 854 855 // clientId: always present 856 clientId = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_CLIENT_ID); 857 858 // sessionId: present for types 1A, 1B, 1C, 1D 859 if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A 860 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B 861 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1C 862 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1D) { 863 sessionId = jsonObject.getInt( 864 WifiAwareManager.NETWORK_SPECIFIER_KEY_SESSION_ID); 865 } 866 867 // peer Id: present for types 1A, 1B 868 if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A 869 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B) { 870 peerId = jsonObject.getInt(WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_ID); 871 } 872 873 // peerMac: present for types 2A, 2B 874 if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2A 875 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2B) { 876 try { 877 peerMac = HexEncoding.decode(jsonObject.getString( 878 WifiAwareManager.NETWORK_SPECIFIER_KEY_PEER_MAC).toCharArray(), 879 false); 880 if (peerMac == null || peerMac.length != 6) { 881 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 882 + " -- invalid peer MAC address - null or not 6 bytes"); 883 return null; 884 } 885 } catch (IllegalArgumentException e) { 886 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" 887 + networkSpecifier + " -- invalid peer MAC address -- e=" + e); 888 return null; 889 } 890 } 891 892 // token: present for types 1A, 1C, 2A, 2C 893 if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A 894 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1C 895 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2A 896 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_2C) { 897 token = Base64.decode( 898 jsonObject.getString(WifiAwareManager.NETWORK_SPECIFIER_KEY_TOKEN), 899 Base64.DEFAULT); 900 } 901 } catch (JSONException e) { 902 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 903 + " -- invalid JSON format -- e=" + e); 904 return null; 905 } 906 907 // look up network specifier information in Aware state manager 908 WifiAwareClientState client = mgr.getClient(clientId); 909 if (client == null) { 910 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 911 + " -- not client with this id -- clientId=" + clientId); 912 return null; 913 } 914 uid = client.getUid(); 915 916 // validate the role (if session ID provided: i.e. session 1xx) 917 if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A 918 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B 919 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1C 920 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1D) { 921 WifiAwareDiscoverySessionState session = client.getSession(sessionId); 922 if (session == null) { 923 Log.e(TAG, 924 "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 925 + " -- no session with this id -- sessionId=" + sessionId); 926 return null; 927 } 928 929 if ((session.isPublishSession() 930 && role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || ( 931 !session.isPublishSession() 932 && role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) { 933 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 934 + " -- invalid role for session type"); 935 return null; 936 } 937 938 if (type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1A 939 || type == WifiAwareManager.NETWORK_SPECIFIER_TYPE_1B) { 940 pubSubId = session.getPubSubId(); 941 String peerMacStr = session.getMac(peerId, null); 942 if (peerMacStr == null) { 943 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 944 + " -- no MAC address associated with this peer id -- peerId=" 945 + peerId); 946 return null; 947 } 948 try { 949 peerMac = HexEncoding.decode(peerMacStr.toCharArray(), false); 950 if (peerMac == null || peerMac.length != 6) { 951 Log.e(TAG, "parseNetworkSpecifier: networkSpecifier=" 952 + networkSpecifier + " -- invalid peer MAC address"); 953 return null; 954 } 955 } catch (IllegalArgumentException e) { 956 Log.e(TAG, 957 "parseNetworkSpecifier: networkSpecifier=" + networkSpecifier 958 + " -- invalid peer MAC address -- e=" + e); 959 return null; 960 } 961 } 962 } 963 964 // create container and populate 965 AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation(); 966 nnri.state = (role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) 967 ? AwareNetworkRequestInformation.STATE_INITIATOR_IDLE 968 : AwareNetworkRequestInformation.STATE_RESPONDER_IDLE; 969 nnri.role = role; 970 nnri.uid = uid; 971 nnri.pubSubId = pubSubId; 972 nnri.peerId = peerId; 973 nnri.peerDiscoveryMac = peerMac; 974 nnri.token = token; 975 976 return nnri; 977 } 978 979 @Override 980 public String toString() { 981 StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: "); 982 sb.append("state=").append(state).append(", role=").append(role).append( 983 ", uid=").append(uid).append(", interfaceName=").append(interfaceName).append( 984 ", pubSubId=").append(pubSubId).append(", peerDiscoveryMac=").append( 985 peerDiscoveryMac == null ? "" 986 : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append( 987 ", token=").append(token).append(", ndpId=").append(ndpId).append( 988 ", peerDataMac=").append( 989 peerDataMac == null ? "" : String.valueOf(HexEncoding.encode(peerDataMac))); 990 return sb.toString(); 991 } 992 } 993 994 /** 995 * Enables mocking. 996 */ 997 @VisibleForTesting 998 public class NetworkInterfaceWrapper { 999 /** 1000 * Configures network agent properties: link-local address, connected status, interface 1001 * name. Delegated to enable mocking. 1002 */ 1003 public boolean configureAgentProperties(AwareNetworkRequestInformation nnri, 1004 String networkSpecifier, int ndpId, NetworkInfo networkInfo, 1005 NetworkCapabilities networkCapabilities, LinkProperties linkProperties) { 1006 // find link-local address 1007 InetAddress linkLocal = null; 1008 NetworkInterface ni; 1009 try { 1010 ni = NetworkInterface.getByName(nnri.interfaceName); 1011 } catch (SocketException e) { 1012 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 1013 + ": can't get network interface - " + e); 1014 mMgr.endDataPath(ndpId); 1015 return false; 1016 } 1017 if (ni == null) { 1018 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 1019 + ": can't get network interface (null)"); 1020 mMgr.endDataPath(ndpId); 1021 return false; 1022 } 1023 Enumeration<InetAddress> addresses = ni.getInetAddresses(); 1024 while (addresses.hasMoreElements()) { 1025 InetAddress ip = addresses.nextElement(); 1026 if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) { 1027 linkLocal = ip; 1028 break; 1029 } 1030 } 1031 1032 if (linkLocal == null) { 1033 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses"); 1034 mMgr.endDataPath(ndpId); 1035 return false; 1036 } 1037 1038 // configure agent 1039 networkInfo.setIsAvailable(true); 1040 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); 1041 1042 networkCapabilities.setNetworkSpecifier(networkSpecifier); 1043 1044 linkProperties.setInterfaceName(nnri.interfaceName); 1045 linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64)); 1046 linkProperties.addRoute( 1047 new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName)); 1048 1049 return true; 1050 } 1051 } 1052 1053 /** 1054 * Dump the internal state of the class. 1055 */ 1056 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1057 pw.println("WifiAwareDataPathStateManager:"); 1058 pw.println(" mInterfaces: " + mInterfaces); 1059 pw.println(" mNetworkCapabilitiesFilter: " + mNetworkCapabilitiesFilter); 1060 pw.println(" mNetworkRequestsCache: " + mNetworkRequestsCache); 1061 pw.println(" mNetworkFactory:"); 1062 mNetworkFactory.dump(fd, pw, args); 1063 } 1064} 1065