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