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 // TODO: validate that the client ID actually comes from the correct process and is 596 // not faked? 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.REQUEST_CHANNEL_SETUP, selectChannelForRequest(nnri), 643 nnri.peerDiscoveryMac, nnri.interfaceName, nnri.networkSpecifier.pmk, 644 nnri.networkSpecifier.passphrase); 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: for now simply select channel 6 785 */ 786 private int selectChannelForRequest(AwareNetworkRequestInformation req) { 787 return 2437; 788 } 789 790 /** 791 * Aware network request. State object: contains network request information/state through its 792 * lifetime. 793 */ 794 @VisibleForTesting 795 public static class AwareNetworkRequestInformation { 796 static final int STATE_INITIATOR_IDLE = 100; 797 static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 101; 798 static final int STATE_INITIATOR_WAIT_FOR_CONFIRM = 102; 799 static final int STATE_INITIATOR_CONFIRMED = 103; 800 801 static final int STATE_RESPONDER_IDLE = 200; 802 static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 201; 803 static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 202; 804 static final int STATE_RESPONDER_WAIT_FOR_CONFIRM = 203; 805 static final int STATE_RESPONDER_CONFIRMED = 204; 806 807 public int state; 808 809 public int uid; 810 public String interfaceName; 811 public int pubSubId = 0; 812 public byte[] peerDiscoveryMac = null; 813 public int ndpId; 814 public byte[] peerDataMac; 815 public WifiAwareNetworkSpecifier networkSpecifier; 816 817 public WifiAwareNetworkAgent networkAgent; 818 819 static AwareNetworkRequestInformation processNetworkSpecifier(WifiAwareNetworkSpecifier ns, 820 WifiAwareStateManager mgr) { 821 int uid, pubSubId = 0; 822 byte[] peerMac = ns.peerMac; 823 824 if (VDBG) { 825 Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns); 826 } 827 828 // type: always valid 829 if (ns.type < 0 830 || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) { 831 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 832 + ", invalid 'type' value"); 833 return null; 834 } 835 836 // role: always valid 837 if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 838 && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { 839 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 840 + " -- invalid 'role' value"); 841 return null; 842 } 843 844 if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 845 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 846 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) { 847 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 848 + " -- invalid 'type' value for INITIATOR (only IB and OOB are " 849 + "permitted)"); 850 return null; 851 } 852 853 // look up network specifier information in Aware state manager 854 WifiAwareClientState client = mgr.getClient(ns.clientId); 855 if (client == null) { 856 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 857 + " -- not client with this id -- clientId=" + ns.clientId); 858 return null; 859 } 860 uid = client.getUid(); 861 862 // validate the role (if session ID provided: i.e. session 1xx) 863 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 864 || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) { 865 WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId); 866 if (session == null) { 867 Log.e(TAG, 868 "processNetworkSpecifier: networkSpecifier=" + ns 869 + " -- no session with this id -- sessionId=" + ns.sessionId); 870 return null; 871 } 872 873 if ((session.isPublishSession() 874 && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || ( 875 !session.isPublishSession() && ns.role 876 != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) { 877 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 878 + " -- invalid role for session type"); 879 return null; 880 } 881 882 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) { 883 pubSubId = session.getPubSubId(); 884 String peerMacStr = session.getMac(ns.peerId, null); 885 if (peerMacStr == null) { 886 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 887 + " -- no MAC address associated with this peer id -- peerId=" 888 + ns.peerId); 889 return null; 890 } 891 try { 892 peerMac = HexEncoding.decode(peerMacStr.toCharArray(), false); 893 if (peerMac == null || peerMac.length != 6) { 894 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" 895 + ns + " -- invalid peer MAC address"); 896 return null; 897 } 898 } catch (IllegalArgumentException e) { 899 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 900 + " -- invalid peer MAC address -- e=" + e); 901 return null; 902 } 903 } 904 } 905 906 // create container and populate 907 AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation(); 908 nnri.state = (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) 909 ? AwareNetworkRequestInformation.STATE_INITIATOR_IDLE 910 : AwareNetworkRequestInformation.STATE_RESPONDER_IDLE; 911 nnri.uid = uid; 912 nnri.pubSubId = pubSubId; 913 nnri.peerDiscoveryMac = peerMac; 914 nnri.networkSpecifier = ns; 915 916 return nnri; 917 } 918 919 @Override 920 public String toString() { 921 StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: "); 922 sb.append("state=").append(state).append(", ns=").append(networkSpecifier).append( 923 ", uid=").append(uid).append(", interfaceName=").append(interfaceName).append( 924 ", pubSubId=").append(pubSubId).append(", peerDiscoveryMac=").append( 925 peerDiscoveryMac == null ? "" 926 : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append( 927 ", ndpId=").append(ndpId).append(", peerDataMac=").append( 928 peerDataMac == null ? "" : String.valueOf(HexEncoding.encode(peerDataMac))); 929 return sb.toString(); 930 } 931 } 932 933 /** 934 * Enables mocking. 935 */ 936 @VisibleForTesting 937 public class NetworkInterfaceWrapper { 938 /** 939 * Configures network agent properties: link-local address, connected status, interface 940 * name. Delegated to enable mocking. 941 */ 942 public boolean configureAgentProperties(AwareNetworkRequestInformation nnri, 943 WifiAwareNetworkSpecifier networkSpecifier, int ndpId, NetworkInfo networkInfo, 944 NetworkCapabilities networkCapabilities, LinkProperties linkProperties) { 945 // find link-local address 946 InetAddress linkLocal = null; 947 NetworkInterface ni; 948 try { 949 ni = NetworkInterface.getByName(nnri.interfaceName); 950 } catch (SocketException e) { 951 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 952 + ": can't get network interface - " + e); 953 mMgr.endDataPath(ndpId); 954 return false; 955 } 956 if (ni == null) { 957 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 958 + ": can't get network interface (null)"); 959 mMgr.endDataPath(ndpId); 960 return false; 961 } 962 Enumeration<InetAddress> addresses = ni.getInetAddresses(); 963 while (addresses.hasMoreElements()) { 964 InetAddress ip = addresses.nextElement(); 965 if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) { 966 linkLocal = ip; 967 break; 968 } 969 } 970 971 if (linkLocal == null) { 972 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses"); 973 mMgr.endDataPath(ndpId); 974 return false; 975 } 976 977 // configure agent 978 networkInfo.setIsAvailable(true); 979 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); 980 981 networkCapabilities.setNetworkSpecifier(networkSpecifier); 982 983 linkProperties.setInterfaceName(nnri.interfaceName); 984 linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64)); 985 linkProperties.addRoute( 986 new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName)); 987 988 return true; 989 } 990 } 991 992 /** 993 * Dump the internal state of the class. 994 */ 995 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 996 pw.println("WifiAwareDataPathStateManager:"); 997 pw.println(" mInterfaces: " + mInterfaces); 998 pw.println(" mNetworkCapabilitiesFilter: " + mNetworkCapabilitiesFilter); 999 pw.println(" mNetworkRequestsCache: " + mNetworkRequestsCache); 1000 pw.println(" mNetworkFactory:"); 1001 mNetworkFactory.dump(fd, pw, args); 1002 } 1003} 1004