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 17 package com.android.server.wifi.aware; 18 19 import android.Manifest; 20 import android.content.Context; 21 import android.content.pm.PackageManager; 22 import android.hardware.wifi.V1_0.NanDataPathChannelCfg; 23 import android.hardware.wifi.V1_0.NanStatusType; 24 import android.hardware.wifi.V1_2.NanDataPathChannelInfo; 25 import android.net.ConnectivityManager; 26 import android.net.IpPrefix; 27 import android.net.LinkAddress; 28 import android.net.LinkProperties; 29 import android.net.MacAddress; 30 import android.net.MatchAllNetworkSpecifier; 31 import android.net.NetworkAgent; 32 import android.net.NetworkCapabilities; 33 import android.net.NetworkFactory; 34 import android.net.NetworkInfo; 35 import android.net.NetworkRequest; 36 import android.net.NetworkSpecifier; 37 import android.net.RouteInfo; 38 import android.net.wifi.aware.WifiAwareAgentNetworkSpecifier; 39 import android.net.wifi.aware.WifiAwareManager; 40 import android.net.wifi.aware.WifiAwareNetworkSpecifier; 41 import android.net.wifi.aware.WifiAwareUtils; 42 import android.os.Build; 43 import android.os.IBinder; 44 import android.os.INetworkManagementService; 45 import android.os.Looper; 46 import android.os.ServiceManager; 47 import android.os.SystemClock; 48 import android.text.TextUtils; 49 import android.util.ArrayMap; 50 import android.util.Log; 51 52 import com.android.internal.annotations.VisibleForTesting; 53 import com.android.server.wifi.util.WifiPermissionsUtil; 54 import com.android.server.wifi.util.WifiPermissionsWrapper; 55 56 import libcore.util.HexEncoding; 57 58 import java.io.FileDescriptor; 59 import java.io.PrintWriter; 60 import java.net.Inet6Address; 61 import java.net.InetAddress; 62 import java.net.NetworkInterface; 63 import java.net.SocketException; 64 import java.util.Arrays; 65 import java.util.Enumeration; 66 import java.util.HashSet; 67 import java.util.Iterator; 68 import java.util.List; 69 import java.util.Map; 70 import java.util.Set; 71 import java.util.SortedSet; 72 import java.util.TreeSet; 73 74 /** 75 * Manages Aware data-path lifetime: interface creation/deletion, data-path setup and tear-down. 76 * The Aware network configuration is: 77 * - transport = TRANSPORT_WIFI_AWARE 78 * - capabilities = NET_CAPABILITY_NOT_VPN 79 * - network specifier generated by DiscoverySession.createNetworkSpecifier(...) or 80 * WifiAwareManager.createNetworkSpecifier(...). 81 */ 82 public class WifiAwareDataPathStateManager { 83 private static final String TAG = "WifiAwareDataPathStMgr"; 84 private static final boolean VDBG = false; // STOPSHIP if true 85 /* package */ boolean mDbg = false; 86 87 private static final String AWARE_INTERFACE_PREFIX = "aware_data"; 88 private static final String NETWORK_TAG = "WIFI_AWARE_FACTORY"; 89 private static final String AGENT_TAG_PREFIX = "WIFI_AWARE_AGENT_"; 90 private static final int NETWORK_FACTORY_SCORE_AVAIL = 1; 91 private static final int NETWORK_FACTORY_BANDWIDTH_AVAIL = 1; 92 private static final int NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL = 1; 93 94 private final WifiAwareStateManager mMgr; 95 public NetworkInterfaceWrapper mNiWrapper = new NetworkInterfaceWrapper(); 96 private static final NetworkCapabilities sNetworkCapabilitiesFilter = new NetworkCapabilities(); 97 private final Set<String> mInterfaces = new HashSet<>(); 98 private final Map<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> 99 mNetworkRequestsCache = new ArrayMap<>(); 100 private Context mContext; 101 private WifiAwareMetrics mAwareMetrics; 102 private WifiPermissionsUtil mWifiPermissionsUtil; 103 private WifiPermissionsWrapper mPermissionsWrapper; 104 private Looper mLooper; 105 private WifiAwareNetworkFactory mNetworkFactory; 106 public INetworkManagementService mNwService; 107 108 // internal debug flag to override API check 109 /* package */ boolean mAllowNdpResponderFromAnyOverride = false; 110 111 public WifiAwareDataPathStateManager(WifiAwareStateManager mgr) { 112 mMgr = mgr; 113 } 114 115 /** 116 * Initialize the Aware data-path state manager. Specifically register the network factory with 117 * connectivity service. 118 */ 119 public void start(Context context, Looper looper, WifiAwareMetrics awareMetrics, 120 WifiPermissionsUtil wifiPermissionsUtil, WifiPermissionsWrapper permissionsWrapper) { 121 if (VDBG) Log.v(TAG, "start"); 122 123 mContext = context; 124 mAwareMetrics = awareMetrics; 125 mWifiPermissionsUtil = wifiPermissionsUtil; 126 mPermissionsWrapper = permissionsWrapper; 127 mLooper = looper; 128 129 sNetworkCapabilitiesFilter.clearAll(); 130 sNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE); 131 sNetworkCapabilitiesFilter 132 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) 133 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) 134 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) 135 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) 136 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 137 .addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED); 138 sNetworkCapabilitiesFilter.setNetworkSpecifier(new MatchAllNetworkSpecifier()); 139 sNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL); 140 sNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(NETWORK_FACTORY_BANDWIDTH_AVAIL); 141 sNetworkCapabilitiesFilter.setSignalStrength(NETWORK_FACTORY_SIGNAL_STRENGTH_AVAIL); 142 143 mNetworkFactory = new WifiAwareNetworkFactory(looper, context, sNetworkCapabilitiesFilter); 144 mNetworkFactory.setScoreFilter(NETWORK_FACTORY_SCORE_AVAIL); 145 mNetworkFactory.register(); 146 147 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 148 mNwService = INetworkManagementService.Stub.asInterface(b); 149 } 150 151 private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> 152 getNetworkRequestByNdpId(int ndpId) { 153 for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : 154 mNetworkRequestsCache.entrySet()) { 155 if (entry.getValue().ndpId == ndpId) { 156 return entry; 157 } 158 } 159 160 return null; 161 } 162 163 private Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> 164 getNetworkRequestByCanonicalDescriptor(CanonicalConnectionInfo cci) { 165 if (VDBG) Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: cci=" + cci); 166 for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : 167 mNetworkRequestsCache.entrySet()) { 168 if (VDBG) { 169 Log.v(TAG, "getNetworkRequestByCanonicalDescriptor: entry=" + entry.getValue() 170 + " --> cci=" + entry.getValue().getCanonicalDescriptor()); 171 } 172 if (entry.getValue().getCanonicalDescriptor().matches(cci)) { 173 return entry; 174 } 175 } 176 177 return null; 178 } 179 180 /** 181 * Create all Aware data-path interfaces which are possible on the device - based on the 182 * capabilities of the firmware. 183 */ 184 public void createAllInterfaces() { 185 if (VDBG) Log.v(TAG, "createAllInterfaces"); 186 187 if (mMgr.getCapabilities() == null) { 188 Log.e(TAG, "createAllInterfaces: capabilities aren't initialized yet!"); 189 return; 190 } 191 192 for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) { 193 String name = AWARE_INTERFACE_PREFIX + i; 194 if (mInterfaces.contains(name)) { 195 Log.e(TAG, "createAllInterfaces(): interface already up, " + name 196 + ", possibly failed to delete - deleting/creating again to be safe"); 197 mMgr.deleteDataPathInterface(name); 198 199 // critical to remove so that don't get infinite loop if the delete fails again 200 mInterfaces.remove(name); 201 } 202 203 mMgr.createDataPathInterface(name); 204 } 205 } 206 207 /** 208 * Delete all Aware data-path interfaces which are currently up. 209 */ 210 public void deleteAllInterfaces() { 211 if (VDBG) Log.v(TAG, "deleteAllInterfaces"); 212 onAwareDownCleanupDataPaths(); 213 214 if (mMgr.getCapabilities() == null) { 215 Log.e(TAG, "deleteAllInterfaces: capabilities aren't initialized yet!"); 216 return; 217 } 218 219 for (int i = 0; i < mMgr.getCapabilities().maxNdiInterfaces; ++i) { 220 String name = AWARE_INTERFACE_PREFIX + i; 221 mMgr.deleteDataPathInterface(name); 222 } 223 mMgr.releaseAwareInterface(); 224 } 225 226 /** 227 * Called when firmware indicates the an interface was created. 228 */ 229 public void onInterfaceCreated(String interfaceName) { 230 if (VDBG) Log.v(TAG, "onInterfaceCreated: interfaceName=" + interfaceName); 231 232 if (mInterfaces.contains(interfaceName)) { 233 Log.w(TAG, "onInterfaceCreated: already contains interface -- " + interfaceName); 234 } 235 236 mInterfaces.add(interfaceName); 237 } 238 239 /** 240 * Called when firmware indicates the an interface was deleted. 241 */ 242 public void onInterfaceDeleted(String interfaceName) { 243 if (VDBG) Log.v(TAG, "onInterfaceDeleted: interfaceName=" + interfaceName); 244 245 if (!mInterfaces.contains(interfaceName)) { 246 Log.w(TAG, "onInterfaceDeleted: interface not on list -- " + interfaceName); 247 } 248 249 mInterfaces.remove(interfaceName); 250 } 251 252 /** 253 * Response to initiating data-path request. Indicates that request is successful (not 254 * complete!) and is now in progress. 255 * 256 * @param networkSpecifier The network specifier provided as part of the initiate request. 257 * @param ndpId The ID assigned to the data-path. 258 */ 259 public void onDataPathInitiateSuccess(WifiAwareNetworkSpecifier networkSpecifier, int ndpId) { 260 if (VDBG) { 261 Log.v(TAG, 262 "onDataPathInitiateSuccess: networkSpecifier=" + networkSpecifier + ", ndpId=" 263 + ndpId); 264 } 265 266 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 267 if (nnri == null) { 268 Log.w(TAG, "onDataPathInitiateSuccess: network request not found for networkSpecifier=" 269 + networkSpecifier); 270 mMgr.endDataPath(ndpId); 271 return; 272 } 273 274 if (nnri.state 275 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { 276 Log.w(TAG, "onDataPathInitiateSuccess: network request in incorrect state: state=" 277 + nnri.state); 278 mNetworkRequestsCache.remove(networkSpecifier); 279 mMgr.endDataPath(ndpId); 280 return; 281 } 282 283 nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM; 284 nnri.ndpId = ndpId; 285 } 286 287 /** 288 * Response to an attempt to set up a data-path (on the initiator side). 289 * 290 * @param networkSpecifier The network specifier provided as part of the initiate request. 291 * @param reason Failure reason. 292 */ 293 public void onDataPathInitiateFail(WifiAwareNetworkSpecifier networkSpecifier, int reason) { 294 if (VDBG) { 295 Log.v(TAG, 296 "onDataPathInitiateFail: networkSpecifier=" + networkSpecifier + ", reason=" 297 + reason); 298 } 299 300 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier); 301 if (nnri == null) { 302 Log.w(TAG, "onDataPathInitiateFail: network request not found for networkSpecifier=" 303 + networkSpecifier); 304 return; 305 } 306 307 if (nnri.state 308 != AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE) { 309 Log.w(TAG, "onDataPathInitiateFail: network request in incorrect state: state=" 310 + nnri.state); 311 } 312 313 mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), nnri.startTimestamp); 314 } 315 316 317 /** 318 * Notification (unsolicited/asynchronous) that a peer has requested to set up a data-path 319 * connection with us. 320 * 321 * @param pubSubId The ID of the discovery session context for the data-path - or 0 if not 322 * related to a discovery session. 323 * @param mac The discovery MAC address of the peer. 324 * @param ndpId The locally assigned ID for the data-path. 325 * @return The network specifier of the data-path (or null if none/error) 326 */ 327 public WifiAwareNetworkSpecifier onDataPathRequest(int pubSubId, byte[] mac, int ndpId) { 328 if (VDBG) { 329 Log.v(TAG, 330 "onDataPathRequest: pubSubId=" + pubSubId + ", mac=" + String.valueOf( 331 HexEncoding.encode(mac)) + ", ndpId=" + ndpId); 332 } 333 334 WifiAwareNetworkSpecifier networkSpecifier = null; 335 AwareNetworkRequestInformation nnri = null; 336 for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : 337 mNetworkRequestsCache.entrySet()) { 338 /* 339 * Checking that the incoming request (from the Initiator) matches the request 340 * we (the Responder) already have set up. The rules are: 341 * - The discovery session (pub/sub ID) must match. 342 * - The peer MAC address (if specified - i.e. non-null) must match. A null peer MAC == 343 * accept (otherwise matching) requests from any peer MAC. 344 * - The request must be pending (i.e. we could have completed requests for the same 345 * parameters) 346 */ 347 if (entry.getValue().pubSubId != 0 && entry.getValue().pubSubId != pubSubId) { 348 continue; 349 } 350 351 if (entry.getValue().peerDiscoveryMac != null && !Arrays.equals( 352 entry.getValue().peerDiscoveryMac, mac)) { 353 continue; 354 } 355 356 if (entry.getValue().state 357 != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST) { 358 continue; 359 } 360 361 networkSpecifier = entry.getKey(); 362 nnri = entry.getValue(); 363 break; 364 } 365 366 if (nnri == null) { 367 Log.w(TAG, "onDataPathRequest: can't find a request with specified pubSubId=" + pubSubId 368 + ", mac=" + String.valueOf(HexEncoding.encode(mac))); 369 if (VDBG) { 370 Log.v(TAG, "onDataPathRequest: network request cache = " + mNetworkRequestsCache); 371 } 372 mMgr.respondToDataPathRequest(false, ndpId, "", null, null, false); 373 return null; 374 } 375 376 if (nnri.peerDiscoveryMac == null) { 377 // the "accept anyone" request is now specific 378 nnri.peerDiscoveryMac = mac; 379 } 380 nnri.interfaceName = selectInterfaceForRequest(nnri); 381 if (nnri.interfaceName == null) { 382 Log.w(TAG, 383 "onDataPathRequest: request " + networkSpecifier + " no interface available"); 384 mMgr.respondToDataPathRequest(false, ndpId, "", null, null, false); 385 mNetworkRequestsCache.remove(networkSpecifier); 386 return null; 387 } 388 389 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE; 390 nnri.ndpId = ndpId; 391 nnri.startTimestamp = SystemClock.elapsedRealtime(); 392 mMgr.respondToDataPathRequest(true, ndpId, nnri.interfaceName, nnri.networkSpecifier.pmk, 393 nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand()); 394 395 return networkSpecifier; 396 } 397 398 /** 399 * Called on the RESPONDER when the response to data-path request has been completed. 400 * 401 * @param ndpId The ID of the data-path (NDP) 402 * @param success Whether or not the 'RespondToDataPathRequest' operation was a success. 403 */ 404 public void onRespondToDataPathRequest(int ndpId, boolean success, int reasonOnFailure) { 405 if (VDBG) { 406 Log.v(TAG, "onRespondToDataPathRequest: ndpId=" + ndpId + ", success=" + success); 407 } 408 409 WifiAwareNetworkSpecifier networkSpecifier = null; 410 AwareNetworkRequestInformation nnri = null; 411 for (Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> entry : 412 mNetworkRequestsCache.entrySet()) { 413 if (entry.getValue().ndpId == ndpId) { 414 networkSpecifier = entry.getKey(); 415 nnri = entry.getValue(); 416 break; 417 } 418 } 419 420 if (nnri == null) { 421 Log.w(TAG, "onRespondToDataPathRequest: can't find a request with specified ndpId=" 422 + ndpId); 423 if (VDBG) { 424 Log.v(TAG, "onRespondToDataPathRequest: network request cache = " 425 + mNetworkRequestsCache); 426 } 427 return; 428 } 429 430 if (!success) { 431 Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier 432 + " failed responding"); 433 mMgr.endDataPath(ndpId); 434 mNetworkRequestsCache.remove(networkSpecifier); 435 mAwareMetrics.recordNdpStatus(reasonOnFailure, networkSpecifier.isOutOfBand(), 436 nnri.startTimestamp); 437 return; 438 } 439 440 if (nnri.state 441 != AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE) { 442 Log.w(TAG, "onRespondToDataPathRequest: request " + networkSpecifier 443 + " is incorrect state=" + nnri.state); 444 mMgr.endDataPath(ndpId); 445 mNetworkRequestsCache.remove(networkSpecifier); 446 return; 447 } 448 449 nnri.state = AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM; 450 } 451 452 /** 453 * Notification (unsolicited/asynchronous) that the data-path (which we've been setting up) 454 * is possibly (if {@code accept} is {@code true}) ready for use from the firmware's 455 * perspective - now can do L3 configuration. 456 * 457 * @param ndpId Id of the data-path 458 * @param mac The MAC address of the peer's data-path (not discovery interface). Only 459 * valid 460 * if {@code accept} is {@code true}. 461 * @param accept Indicates whether the data-path setup has succeeded (been accepted) or 462 * failed (been rejected). 463 * @param reason If {@code accept} is {@code false} provides a reason code for the 464 * rejection/failure. 465 * @param message The message provided by the peer as part of the data-path setup 466 * process. 467 * @param channelInfo Lists of channels used for this NDP. 468 * @return The network specifier of the data-path or a null if none/error. 469 */ 470 public WifiAwareNetworkSpecifier onDataPathConfirm(int ndpId, byte[] mac, boolean accept, 471 int reason, byte[] message, List<NanDataPathChannelInfo> channelInfo) { 472 if (VDBG) { 473 Log.v(TAG, "onDataPathConfirm: ndpId=" + ndpId + ", mac=" + String.valueOf( 474 HexEncoding.encode(mac)) + ", accept=" + accept + ", reason=" + reason 475 + ", channelInfo=" + channelInfo); 476 } 477 478 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 479 getNetworkRequestByNdpId(ndpId); 480 if (nnriE == null) { 481 Log.w(TAG, "onDataPathConfirm: network request not found for ndpId=" + ndpId); 482 if (accept) { 483 mMgr.endDataPath(ndpId); 484 } 485 return null; 486 } 487 488 WifiAwareNetworkSpecifier networkSpecifier = nnriE.getKey(); 489 AwareNetworkRequestInformation nnri = nnriE.getValue(); 490 491 // validate state 492 if (nnri.state != AwareNetworkRequestInformation.STATE_WAIT_FOR_CONFIRM) { 493 Log.w(TAG, "onDataPathConfirm: invalid state=" + nnri.state); 494 mNetworkRequestsCache.remove(networkSpecifier); 495 if (accept) { 496 mMgr.endDataPath(ndpId); 497 } 498 return networkSpecifier; 499 } 500 501 if (accept) { 502 nnri.state = AwareNetworkRequestInformation.STATE_CONFIRMED; 503 nnri.peerDataMac = mac; 504 nnri.channelInfo = channelInfo; 505 506 NetworkInfo networkInfo = new NetworkInfo(ConnectivityManager.TYPE_NONE, 0, 507 NETWORK_TAG, ""); 508 NetworkCapabilities networkCapabilities = new NetworkCapabilities( 509 sNetworkCapabilitiesFilter); 510 LinkProperties linkProperties = new LinkProperties(); 511 512 boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri); 513 if (!interfaceUsedByAnotherNdp) { 514 try { 515 mNwService.setInterfaceUp(nnri.interfaceName); 516 mNwService.enableIpv6(nnri.interfaceName); 517 } catch (Exception e) { // NwService throws runtime exceptions for errors 518 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 519 + ": can't configure network - " 520 + e); 521 mMgr.endDataPath(ndpId); 522 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 523 return networkSpecifier; 524 } 525 } else { 526 if (VDBG) { 527 Log.v(TAG, "onDataPathConfirm: interface already configured: " 528 + nnri.interfaceName); 529 } 530 } 531 532 if (!mNiWrapper.configureAgentProperties(nnri, nnri.equivalentSpecifiers, ndpId, 533 networkInfo, networkCapabilities, linkProperties)) { 534 return networkSpecifier; 535 } 536 537 nnri.networkAgent = new WifiAwareNetworkAgent(mLooper, mContext, 538 AGENT_TAG_PREFIX + nnri.ndpId, 539 new NetworkInfo(ConnectivityManager.TYPE_NONE, 0, NETWORK_TAG, ""), 540 networkCapabilities, linkProperties, NETWORK_FACTORY_SCORE_AVAIL, 541 nnri); 542 nnri.networkAgent.sendNetworkInfo(networkInfo); 543 544 mAwareMetrics.recordNdpStatus(NanStatusType.SUCCESS, networkSpecifier.isOutOfBand(), 545 nnri.startTimestamp); 546 nnri.startTimestamp = SystemClock.elapsedRealtime(); // update time-stamp for duration 547 mAwareMetrics.recordNdpCreation(nnri.uid, mNetworkRequestsCache); 548 } else { 549 if (VDBG) { 550 Log.v(TAG, "onDataPathConfirm: data-path for networkSpecifier=" + networkSpecifier 551 + " rejected - reason=" + reason); 552 } 553 mNetworkRequestsCache.remove(networkSpecifier); 554 mAwareMetrics.recordNdpStatus(reason, networkSpecifier.isOutOfBand(), 555 nnri.startTimestamp); 556 } 557 558 return networkSpecifier; 559 } 560 561 /** 562 * Notification (unsolicited/asynchronous) from the firmware that the specified data-path has 563 * been terminated. 564 * 565 * @param ndpId The ID of the terminated data-path. 566 */ 567 public void onDataPathEnd(int ndpId) { 568 if (VDBG) Log.v(TAG, "onDataPathEnd: ndpId=" + ndpId); 569 570 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 571 getNetworkRequestByNdpId(ndpId); 572 if (nnriE == null) { 573 if (VDBG) { 574 Log.v(TAG, "onDataPathEnd: network request not found for ndpId=" + ndpId); 575 } 576 return; 577 } 578 579 tearDownInterfaceIfPossible(nnriE.getValue()); 580 if (nnriE.getValue().state == AwareNetworkRequestInformation.STATE_CONFIRMED 581 || nnriE.getValue().state == AwareNetworkRequestInformation.STATE_TERMINATING) { 582 mAwareMetrics.recordNdpSessionDuration(nnriE.getValue().startTimestamp); 583 } 584 mNetworkRequestsCache.remove(nnriE.getKey()); 585 586 mNetworkFactory.tickleConnectivityIfWaiting(); 587 } 588 589 /** 590 * Notification (unsolicited/asynchronous) from the firmware that the channel for the specified 591 * NDP ids has been updated. 592 */ 593 public void onDataPathSchedUpdate(byte[] peerMac, List<Integer> ndpIds, 594 List<NanDataPathChannelInfo> channelInfo) { 595 if (VDBG) { 596 Log.v(TAG, "onDataPathSchedUpdate: peerMac=" + MacAddress.fromBytes(peerMac).toString() 597 + ", ndpIds=" + ndpIds + ", channelInfo=" + channelInfo); 598 } 599 600 for (int ndpId : ndpIds) { 601 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> nnriE = 602 getNetworkRequestByNdpId(ndpId); 603 if (nnriE == null) { 604 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + " - not found"); 605 continue; 606 } 607 if (!Arrays.equals(peerMac, nnriE.getValue().peerDiscoveryMac)) { 608 Log.e(TAG, "onDataPathSchedUpdate: ndpId=" + ndpId + ", report NMI=" 609 + MacAddress.fromBytes(peerMac).toString() + " doesn't match NDP NMI=" 610 + MacAddress.fromBytes(nnriE.getValue().peerDiscoveryMac).toString()); 611 continue; 612 } 613 614 nnriE.getValue().channelInfo = channelInfo; 615 } 616 } 617 618 /** 619 * Called whenever Aware comes down. Clean up all pending and up network requests and agents. 620 */ 621 public void onAwareDownCleanupDataPaths() { 622 if (VDBG) Log.v(TAG, "onAwareDownCleanupDataPaths"); 623 624 Iterator<Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation>> it = 625 mNetworkRequestsCache.entrySet().iterator(); 626 while (it.hasNext()) { 627 tearDownInterfaceIfPossible(it.next().getValue()); 628 it.remove(); 629 } 630 } 631 632 /** 633 * Called when timed-out waiting for confirmation of the data-path setup (i.e. 634 * onDataPathConfirm). Started on the initiator when executing the request for the data-path 635 * and on the responder when received a request for data-path (in both cases only on success 636 * - i.e. when we're proceeding with data-path setup). 637 */ 638 public void handleDataPathTimeout(NetworkSpecifier networkSpecifier) { 639 if (mDbg) Log.v(TAG, "handleDataPathTimeout: networkSpecifier=" + networkSpecifier); 640 641 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.remove(networkSpecifier); 642 if (nnri == null) { 643 if (mDbg) { 644 Log.v(TAG, 645 "handleDataPathTimeout: network request not found for networkSpecifier=" 646 + networkSpecifier); 647 } 648 return; 649 } 650 mAwareMetrics.recordNdpStatus(NanStatusType.INTERNAL_FAILURE, 651 nnri.networkSpecifier.isOutOfBand(), nnri.startTimestamp); 652 653 mMgr.endDataPath(nnri.ndpId); 654 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 655 } 656 657 private class WifiAwareNetworkFactory extends NetworkFactory { 658 // Request received while waiting for confirmation that a canonically identical data-path 659 // (NDP) is in the process of being terminated 660 private boolean mWaitingForTermination = false; 661 662 WifiAwareNetworkFactory(Looper looper, Context context, NetworkCapabilities filter) { 663 super(looper, context, NETWORK_TAG, filter); 664 } 665 666 public void tickleConnectivityIfWaiting() { 667 if (mWaitingForTermination) { 668 if (VDBG) Log.v(TAG, "tickleConnectivityIfWaiting: was waiting!"); 669 mWaitingForTermination = false; 670 reevaluateAllRequests(); 671 } 672 } 673 674 @Override 675 public boolean acceptRequest(NetworkRequest request, int score) { 676 if (VDBG) { 677 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request + ", score=" 678 + score); 679 } 680 681 if (!mMgr.isUsageEnabled()) { 682 if (VDBG) { 683 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 684 + " -- Aware disabled"); 685 } 686 return false; 687 } 688 689 if (mInterfaces.isEmpty()) { 690 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 691 + " -- No Aware interfaces are up"); 692 return false; 693 } 694 695 NetworkSpecifier networkSpecifierBase = 696 request.networkCapabilities.getNetworkSpecifier(); 697 if (!(networkSpecifierBase instanceof WifiAwareNetworkSpecifier)) { 698 Log.w(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 699 + " - not a WifiAwareNetworkSpecifier"); 700 return false; 701 } 702 703 WifiAwareNetworkSpecifier networkSpecifier = 704 (WifiAwareNetworkSpecifier) networkSpecifierBase; 705 706 // look up specifier - are we being called again? 707 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 708 if (nnri != null) { 709 if (VDBG) { 710 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 711 + " - already in cache with state=" + nnri.state); 712 } 713 714 if (nnri.state == AwareNetworkRequestInformation.STATE_TERMINATING) { 715 mWaitingForTermination = true; 716 return false; 717 } 718 719 // seems to happen after a network agent is created - trying to rematch all 720 // requests again!? 721 return true; 722 } 723 724 nnri = AwareNetworkRequestInformation.processNetworkSpecifier(networkSpecifier, mMgr, 725 mWifiPermissionsUtil, mPermissionsWrapper, mAllowNdpResponderFromAnyOverride); 726 if (nnri == null) { 727 Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 728 + " - can't parse network specifier"); 729 return false; 730 } 731 732 // check to see if a canonical version exists 733 Map.Entry<WifiAwareNetworkSpecifier, AwareNetworkRequestInformation> primaryRequest = 734 getNetworkRequestByCanonicalDescriptor(nnri.getCanonicalDescriptor()); 735 if (primaryRequest != null) { 736 if (VDBG) { 737 Log.v(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request 738 + ", already has a primary request=" + primaryRequest.getKey() 739 + " with state=" + primaryRequest.getValue().state); 740 } 741 742 if (primaryRequest.getValue().state 743 == AwareNetworkRequestInformation.STATE_TERMINATING) { 744 mWaitingForTermination = true; 745 } else { 746 primaryRequest.getValue().updateToSupportNewRequest(networkSpecifier); 747 } 748 return false; 749 } 750 751 mNetworkRequestsCache.put(networkSpecifier, nnri); 752 753 return true; 754 } 755 756 @Override 757 protected void needNetworkFor(NetworkRequest networkRequest, int score) { 758 if (VDBG) { 759 Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 760 + networkRequest + ", score=" + score); 761 } 762 763 NetworkSpecifier networkSpecifierObj = 764 networkRequest.networkCapabilities.getNetworkSpecifier(); 765 WifiAwareNetworkSpecifier networkSpecifier = null; 766 if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) { 767 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj; 768 } 769 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 770 if (nnri == null) { 771 Log.e(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 772 + networkRequest + " not in cache!?"); 773 return; 774 } 775 776 if (nnri.state != AwareNetworkRequestInformation.STATE_IDLE) { 777 if (VDBG) { 778 Log.v(TAG, "WifiAwareNetworkFactory.needNetworkFor: networkRequest=" 779 + networkRequest + " - already in progress"); 780 // TODO: understand how/when can be called again/while in progress (seems 781 // to be related to score re-calculation after a network agent is created) 782 } 783 return; 784 } 785 if (nnri.networkSpecifier.role 786 == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR) { 787 nnri.interfaceName = selectInterfaceForRequest(nnri); 788 if (nnri.interfaceName == null) { 789 Log.w(TAG, "needNetworkFor: request " + networkSpecifier 790 + " no interface available"); 791 mNetworkRequestsCache.remove(networkSpecifier); 792 return; 793 } 794 795 mMgr.initiateDataPathSetup(networkSpecifier, nnri.peerInstanceId, 796 NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED, selectChannelForRequest(nnri), 797 nnri.peerDiscoveryMac, nnri.interfaceName, nnri.networkSpecifier.pmk, 798 nnri.networkSpecifier.passphrase, nnri.networkSpecifier.isOutOfBand()); 799 nnri.state = 800 AwareNetworkRequestInformation.STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE; 801 nnri.startTimestamp = SystemClock.elapsedRealtime(); 802 } else { 803 nnri.state = AwareNetworkRequestInformation.STATE_RESPONDER_WAIT_FOR_REQUEST; 804 } 805 } 806 807 @Override 808 protected void releaseNetworkFor(NetworkRequest networkRequest) { 809 if (VDBG) { 810 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 811 + networkRequest); 812 } 813 814 NetworkSpecifier networkSpecifierObj = 815 networkRequest.networkCapabilities.getNetworkSpecifier(); 816 WifiAwareNetworkSpecifier networkSpecifier = null; 817 if (networkSpecifierObj instanceof WifiAwareNetworkSpecifier) { 818 networkSpecifier = (WifiAwareNetworkSpecifier) networkSpecifierObj; 819 } 820 821 AwareNetworkRequestInformation nnri = mNetworkRequestsCache.get(networkSpecifier); 822 if (nnri == null) { 823 Log.e(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 824 + networkRequest + " not in cache!?"); 825 return; 826 } 827 828 if (nnri.networkAgent != null) { 829 if (VDBG) { 830 Log.v(TAG, "WifiAwareNetworkFactory.releaseNetworkFor: networkRequest=" 831 + networkRequest + ", nnri=" + nnri 832 + ": agent already created - deferring ending data-path to agent" 833 + ".unwanted()"); 834 } 835 return; 836 } 837 838 /* 839 * Since there's no agent it means we're in the process of setting up the NDP. 840 * However, it is possible that there were other equivalent requests for this NDP. We 841 * should keep going in that case. 842 */ 843 nnri.removeSupportForRequest(networkSpecifier); 844 if (nnri.equivalentSpecifiers.isEmpty()) { 845 if (VDBG) { 846 Log.v(TAG, "releaseNetworkFor: there are no further requests, networkRequest=" 847 + networkRequest); 848 } 849 if (nnri.ndpId != 0) { // 0 is never a valid ID! 850 if (VDBG) Log.v(TAG, "releaseNetworkFor: in progress NDP being terminated"); 851 mMgr.endDataPath(nnri.ndpId); 852 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 853 } else { 854 mNetworkRequestsCache.remove(networkSpecifier); 855 } 856 } else { 857 if (VDBG) { 858 Log.v(TAG, "releaseNetworkFor: equivalent requests exist - not terminating " 859 + "networkRequest=" + networkRequest); 860 } 861 } 862 } 863 } 864 865 private class WifiAwareNetworkAgent extends NetworkAgent { 866 private NetworkInfo mNetworkInfo; 867 private AwareNetworkRequestInformation mAwareNetworkRequestInfo; 868 869 WifiAwareNetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, 870 NetworkCapabilities nc, LinkProperties lp, int score, 871 AwareNetworkRequestInformation anri) { 872 super(looper, context, logTag, ni, nc, lp, score); 873 874 mNetworkInfo = ni; 875 mAwareNetworkRequestInfo = anri; 876 } 877 878 @Override 879 protected void unwanted() { 880 if (VDBG) { 881 Log.v(TAG, "WifiAwareNetworkAgent.unwanted: request=" + mAwareNetworkRequestInfo); 882 } 883 884 mMgr.endDataPath(mAwareNetworkRequestInfo.ndpId); 885 mAwareNetworkRequestInfo.state = AwareNetworkRequestInformation.STATE_TERMINATING; 886 887 // Will get a callback (on both initiator and responder) when data-path actually 888 // terminated. At that point will inform the agent and will clear the cache. 889 } 890 891 void reconfigureAgentAsDisconnected() { 892 if (VDBG) { 893 Log.v(TAG, "WifiAwareNetworkAgent.reconfigureAgentAsDisconnected: request=" 894 + mAwareNetworkRequestInfo); 895 } 896 897 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, ""); 898 sendNetworkInfo(mNetworkInfo); 899 } 900 } 901 902 private void tearDownInterfaceIfPossible(AwareNetworkRequestInformation nnri) { 903 if (VDBG) Log.v(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri); 904 905 if (!TextUtils.isEmpty(nnri.interfaceName)) { 906 boolean interfaceUsedByAnotherNdp = isInterfaceUpAndUsedByAnotherNdp(nnri); 907 if (interfaceUsedByAnotherNdp) { 908 if (VDBG) { 909 Log.v(TAG, "tearDownInterfaceIfPossible: interfaceName=" + nnri.interfaceName 910 + ", still in use - not turning down"); 911 } 912 } else { 913 try { 914 mNwService.setInterfaceDown(nnri.interfaceName); 915 } catch (Exception e) { // NwService throws runtime exceptions for errors 916 Log.e(TAG, "tearDownInterfaceIfPossible: nnri=" + nnri 917 + ": can't bring interface down - " + e); 918 } 919 } 920 } 921 922 if (nnri.networkAgent != null) { 923 nnri.networkAgent.reconfigureAgentAsDisconnected(); 924 } 925 } 926 927 private boolean isInterfaceUpAndUsedByAnotherNdp(AwareNetworkRequestInformation nri) { 928 for (AwareNetworkRequestInformation lnri : mNetworkRequestsCache.values()) { 929 if (lnri == nri) { 930 continue; 931 } 932 933 if (nri.interfaceName.equals(lnri.interfaceName) && ( 934 lnri.state == AwareNetworkRequestInformation.STATE_CONFIRMED 935 || lnri.state == AwareNetworkRequestInformation.STATE_TERMINATING)) { 936 return true; 937 } 938 } 939 940 return false; 941 } 942 943 /** 944 * Select one of the existing interfaces for the new network request. A request is canonical 945 * (otherwise it wouldn't be executed). 946 * 947 * Construct a list of all interfaces currently used to communicate to the peer. The remaining 948 * interfaces are available for use for this request - if none are left then the request should 949 * fail (signaled to the caller by returning a null). 950 */ 951 private String selectInterfaceForRequest(AwareNetworkRequestInformation req) { 952 SortedSet<String> potential = new TreeSet<>(mInterfaces); 953 Set<String> used = new HashSet<>(); 954 955 if (VDBG) { 956 Log.v(TAG, "selectInterfaceForRequest: req=" + req + ", mNetworkRequestsCache=" 957 + mNetworkRequestsCache); 958 } 959 960 for (AwareNetworkRequestInformation nnri : mNetworkRequestsCache.values()) { 961 if (nnri == req) { 962 continue; 963 } 964 965 if (Arrays.equals(req.peerDiscoveryMac, nnri.peerDiscoveryMac)) { 966 used.add(nnri.interfaceName); 967 } 968 } 969 970 if (VDBG) { 971 Log.v(TAG, "selectInterfaceForRequest: potential=" + potential + ", used=" + used); 972 } 973 974 for (String ifName: potential) { 975 if (!used.contains(ifName)) { 976 return ifName; 977 } 978 } 979 980 Log.e(TAG, "selectInterfaceForRequest: req=" + req + " - no interfaces available!"); 981 return null; 982 } 983 984 /** 985 * Select a channel for the network request. 986 * 987 * TODO (b/38209409): The value from this function isn't currently used - the channel selection 988 * is delegated to the HAL. 989 */ 990 private int selectChannelForRequest(AwareNetworkRequestInformation req) { 991 return 2437; 992 } 993 994 /** 995 * Aware network request. State object: contains network request information/state through its 996 * lifetime. 997 */ 998 @VisibleForTesting 999 public static class AwareNetworkRequestInformation { 1000 static final int STATE_IDLE = 100; 1001 static final int STATE_WAIT_FOR_CONFIRM = 101; 1002 static final int STATE_CONFIRMED = 102; 1003 static final int STATE_INITIATOR_WAIT_FOR_REQUEST_RESPONSE = 103; 1004 static final int STATE_RESPONDER_WAIT_FOR_REQUEST = 104; 1005 static final int STATE_RESPONDER_WAIT_FOR_RESPOND_RESPONSE = 105; 1006 static final int STATE_TERMINATING = 106; 1007 1008 public int state; 1009 1010 public int uid; 1011 public String interfaceName; 1012 public int pubSubId = 0; 1013 public int peerInstanceId = 0; 1014 public byte[] peerDiscoveryMac = null; 1015 public int ndpId = 0; // 0 is never a valid ID! 1016 public byte[] peerDataMac; 1017 public WifiAwareNetworkSpecifier networkSpecifier; 1018 public List<NanDataPathChannelInfo> channelInfo; 1019 public long startTimestamp = 0; // request is made (initiator) / get request (responder) 1020 1021 public WifiAwareNetworkAgent networkAgent; 1022 1023 /* A collection of specifiers which are equivalent to the current request and are 1024 * supported by it's agent. This list DOES include the original (first) network specifier 1025 * (which is stored separately above). 1026 */ 1027 public Set<WifiAwareNetworkSpecifier> equivalentSpecifiers = new HashSet<>(); 1028 1029 void updateToSupportNewRequest(WifiAwareNetworkSpecifier ns) { 1030 if (VDBG) Log.v(TAG, "updateToSupportNewRequest: ns=" + ns); 1031 if (equivalentSpecifiers.add(ns) && state == STATE_CONFIRMED) { 1032 if (networkAgent == null) { 1033 Log.wtf(TAG, "updateToSupportNewRequest: null agent in CONFIRMED state!?"); 1034 return; 1035 } 1036 1037 networkAgent.sendNetworkCapabilities(getNetworkCapabilities()); 1038 } 1039 } 1040 1041 void removeSupportForRequest(WifiAwareNetworkSpecifier ns) { 1042 if (VDBG) Log.v(TAG, "removeSupportForRequest: ns=" + ns); 1043 equivalentSpecifiers.remove(ns); 1044 1045 // we will not update the agent: 1046 // 1. this will only get called before the agent is created 1047 // 2. connectivity service does not allow (WTF) updates with reduced capabilities 1048 } 1049 1050 private NetworkCapabilities getNetworkCapabilities() { 1051 NetworkCapabilities nc = new NetworkCapabilities(sNetworkCapabilitiesFilter); 1052 nc.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier(equivalentSpecifiers.toArray( 1053 new WifiAwareNetworkSpecifier[equivalentSpecifiers.size()]))); 1054 return nc; 1055 } 1056 1057 /** 1058 * Returns a canonical descriptor for the network request. 1059 */ 1060 CanonicalConnectionInfo getCanonicalDescriptor() { 1061 return new CanonicalConnectionInfo(peerDiscoveryMac, networkSpecifier.pmk, 1062 networkSpecifier.sessionId, networkSpecifier.passphrase); 1063 } 1064 1065 static AwareNetworkRequestInformation processNetworkSpecifier(WifiAwareNetworkSpecifier ns, 1066 WifiAwareStateManager mgr, WifiPermissionsUtil wifiPermissionsUtil, 1067 WifiPermissionsWrapper permissionWrapper, 1068 boolean allowNdpResponderFromAnyOverride) { 1069 int uid, pubSubId = 0; 1070 int peerInstanceId = 0; 1071 byte[] peerMac = ns.peerMac; 1072 1073 if (VDBG) { 1074 Log.v(TAG, "processNetworkSpecifier: networkSpecifier=" + ns); 1075 } 1076 1077 // type: always valid 1078 if (ns.type < 0 1079 || ns.type > WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_MAX_VALID) { 1080 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1081 + ", invalid 'type' value"); 1082 return null; 1083 } 1084 1085 // role: always valid 1086 if (ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 1087 && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { 1088 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1089 + " -- invalid 'role' value"); 1090 return null; 1091 } 1092 1093 if (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 1094 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 1095 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) { 1096 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1097 + " -- invalid 'type' value for INITIATOR (only IB and OOB are " 1098 + "permitted)"); 1099 return null; 1100 } 1101 1102 // look up network specifier information in Aware state manager 1103 WifiAwareClientState client = mgr.getClient(ns.clientId); 1104 if (client == null) { 1105 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1106 + " -- not client with this id -- clientId=" + ns.clientId); 1107 return null; 1108 } 1109 uid = client.getUid(); 1110 1111 // API change post 27: no longer allow "ANY"-style responders (initiators were never 1112 // permitted). 1113 // Note: checks are done on the manager. This is a backup for apps which bypass the 1114 // check. 1115 if (!allowNdpResponderFromAnyOverride && !wifiPermissionsUtil.isLegacyVersion( 1116 client.getCallingPackage(), Build.VERSION_CODES.P)) { 1117 if (ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 1118 && ns.type != WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB) { 1119 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1120 + " -- no ANY specifications allowed for this API level"); 1121 return null; 1122 } 1123 } 1124 1125 // validate the role (if session ID provided: i.e. session 1xx) 1126 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB 1127 || ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER) { 1128 WifiAwareDiscoverySessionState session = client.getSession(ns.sessionId); 1129 if (session == null) { 1130 Log.e(TAG, 1131 "processNetworkSpecifier: networkSpecifier=" + ns 1132 + " -- no session with this id -- sessionId=" + ns.sessionId); 1133 return null; 1134 } 1135 1136 if ((session.isPublishSession() 1137 && ns.role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) || ( 1138 !session.isPublishSession() && ns.role 1139 != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)) { 1140 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1141 + " -- invalid role for session type"); 1142 return null; 1143 } 1144 1145 if (ns.type == WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB) { 1146 pubSubId = session.getPubSubId(); 1147 WifiAwareDiscoverySessionState.PeerInfo peerInfo = session.getPeerInfo( 1148 ns.peerId); 1149 if (peerInfo == null) { 1150 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1151 + " -- no peer info associated with this peer id -- peerId=" 1152 + ns.peerId); 1153 return null; 1154 } 1155 peerInstanceId = peerInfo.mInstanceId; 1156 try { 1157 peerMac = peerInfo.mMac; 1158 if (peerMac == null || peerMac.length != 6) { 1159 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" 1160 + ns + " -- invalid peer MAC address"); 1161 return null; 1162 } 1163 } catch (IllegalArgumentException e) { 1164 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns 1165 + " -- invalid peer MAC address -- e=" + e); 1166 return null; 1167 } 1168 } 1169 } 1170 1171 // validate UID 1172 if (ns.requestorUid != uid) { 1173 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() 1174 + " -- UID mismatch to clientId's uid=" + uid); 1175 return null; 1176 } 1177 1178 // validate permission if PMK is used (SystemApi) 1179 if (ns.pmk != null && ns.pmk.length != 0) { 1180 if (permissionWrapper.getUidPermission(Manifest.permission.CONNECTIVITY_INTERNAL, 1181 ns.requestorUid) != PackageManager.PERMISSION_GRANTED) { 1182 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() 1183 + " -- UID doesn't have permission to use PMK API"); 1184 return null; 1185 } 1186 } 1187 1188 // validate passphrase & PMK (if provided) 1189 if (!TextUtils.isEmpty(ns.passphrase)) { // non-null indicates usage 1190 if (!WifiAwareUtils.validatePassphrase(ns.passphrase)) { 1191 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() 1192 + " -- invalid passphrase length: " + ns.passphrase.length()); 1193 return null; 1194 } 1195 } 1196 if (ns.pmk != null && !WifiAwareUtils.validatePmk(ns.pmk)) { // non-null indicates usage 1197 Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString() 1198 + " -- invalid pmk length: " + ns.pmk.length); 1199 return null; 1200 } 1201 1202 // create container and populate 1203 AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation(); 1204 nnri.state = AwareNetworkRequestInformation.STATE_IDLE; 1205 nnri.uid = uid; 1206 nnri.pubSubId = pubSubId; 1207 nnri.peerInstanceId = peerInstanceId; 1208 nnri.peerDiscoveryMac = peerMac; 1209 nnri.networkSpecifier = ns; 1210 nnri.equivalentSpecifiers.add(ns); 1211 1212 return nnri; 1213 } 1214 1215 @Override 1216 public String toString() { 1217 StringBuilder sb = new StringBuilder("AwareNetworkRequestInformation: "); 1218 sb.append("state=").append(state).append(", ns=").append(networkSpecifier).append( 1219 ", uid=").append(uid).append(", interfaceName=").append(interfaceName).append( 1220 ", pubSubId=").append(pubSubId).append(", peerInstanceId=").append( 1221 peerInstanceId).append(", peerDiscoveryMac=").append( 1222 peerDiscoveryMac == null ? "" 1223 : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append( 1224 ", ndpId=").append(ndpId).append(", peerDataMac=").append( 1225 peerDataMac == null ? "" 1226 : String.valueOf(HexEncoding.encode(peerDataMac))).append( 1227 ", startTimestamp=").append(startTimestamp).append(", channelInfo=").append( 1228 channelInfo).append(", equivalentSpecifiers=["); 1229 for (WifiAwareNetworkSpecifier ns: equivalentSpecifiers) { 1230 sb.append(ns.toString()).append(", "); 1231 } 1232 return sb.append("]").toString(); 1233 } 1234 } 1235 1236 /** 1237 * A canonical (unique) descriptor of the peer connection. 1238 */ 1239 static class CanonicalConnectionInfo { 1240 CanonicalConnectionInfo(byte[] peerDiscoveryMac, byte[] pmk, int sessionId, 1241 String passphrase) { 1242 this.peerDiscoveryMac = peerDiscoveryMac; 1243 this.pmk = pmk; 1244 this.sessionId = sessionId; 1245 this.passphrase = passphrase; 1246 } 1247 1248 public final byte[] peerDiscoveryMac; 1249 1250 /* 1251 * Security configuration matching: 1252 * - open: pmk/passphrase = null 1253 * - pmk: pmk != null, passphrase = null 1254 * - passphrase: passphrase != null, sessionId used (==0 for OOB), pmk=null 1255 */ 1256 public final byte[] pmk; 1257 1258 public final int sessionId; 1259 public final String passphrase; 1260 1261 public boolean matches(CanonicalConnectionInfo other) { 1262 return (other.peerDiscoveryMac == null || Arrays 1263 .equals(peerDiscoveryMac, other.peerDiscoveryMac)) 1264 && Arrays.equals(pmk, other.pmk) 1265 && TextUtils.equals(passphrase, other.passphrase) 1266 && (TextUtils.isEmpty(passphrase) || sessionId == other.sessionId); 1267 } 1268 1269 @Override 1270 public String toString() { 1271 StringBuilder sb = new StringBuilder("CanonicalConnectionInfo: ["); 1272 sb.append("peerDiscoveryMac=").append(peerDiscoveryMac == null ? "" 1273 : String.valueOf(HexEncoding.encode(peerDiscoveryMac))).append(", pmk=").append( 1274 pmk == null ? "" : "*").append(", sessionId=").append(sessionId).append( 1275 ", passphrase=").append(passphrase == null ? "" : "*").append("]"); 1276 return sb.toString(); 1277 } 1278 } 1279 1280 /** 1281 * Enables mocking. 1282 */ 1283 @VisibleForTesting 1284 public class NetworkInterfaceWrapper { 1285 /** 1286 * Configures network agent properties: link-local address, connected status, interface 1287 * name. Delegated to enable mocking. 1288 */ 1289 public boolean configureAgentProperties(AwareNetworkRequestInformation nnri, 1290 Set<WifiAwareNetworkSpecifier> networkSpecifiers, int ndpId, 1291 NetworkInfo networkInfo, NetworkCapabilities networkCapabilities, 1292 LinkProperties linkProperties) { 1293 // find link-local address 1294 InetAddress linkLocal = null; 1295 NetworkInterface ni; 1296 try { 1297 ni = NetworkInterface.getByName(nnri.interfaceName); 1298 } catch (SocketException e) { 1299 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 1300 + ": can't get network interface - " + e); 1301 mMgr.endDataPath(ndpId); 1302 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 1303 return false; 1304 } 1305 if (ni == null) { 1306 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri 1307 + ": can't get network interface (null)"); 1308 mMgr.endDataPath(ndpId); 1309 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 1310 return false; 1311 } 1312 Enumeration<InetAddress> addresses = ni.getInetAddresses(); 1313 while (addresses.hasMoreElements()) { 1314 InetAddress ip = addresses.nextElement(); 1315 if (ip instanceof Inet6Address && ip.isLinkLocalAddress()) { 1316 linkLocal = ip; 1317 break; 1318 } 1319 } 1320 1321 if (linkLocal == null) { 1322 Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses"); 1323 mMgr.endDataPath(ndpId); 1324 nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING; 1325 return false; 1326 } 1327 1328 // configure agent 1329 networkInfo.setIsAvailable(true); 1330 networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); 1331 1332 networkCapabilities.setNetworkSpecifier(new WifiAwareAgentNetworkSpecifier( 1333 networkSpecifiers.toArray(new WifiAwareNetworkSpecifier[0]))); 1334 1335 linkProperties.setInterfaceName(nnri.interfaceName); 1336 linkProperties.addLinkAddress(new LinkAddress(linkLocal, 64)); 1337 linkProperties.addRoute( 1338 new RouteInfo(new IpPrefix("fe80::/64"), null, nnri.interfaceName)); 1339 1340 return true; 1341 } 1342 } 1343 1344 /** 1345 * Dump the internal state of the class. 1346 */ 1347 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1348 pw.println("WifiAwareDataPathStateManager:"); 1349 pw.println(" mInterfaces: " + mInterfaces); 1350 pw.println(" sNetworkCapabilitiesFilter: " + sNetworkCapabilitiesFilter); 1351 pw.println(" mNetworkRequestsCache: " + mNetworkRequestsCache); 1352 pw.println(" mNetworkFactory:"); 1353 mNetworkFactory.dump(fd, pw, args); 1354 } 1355 } 1356