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