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