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