1 /* 2 * Copyright (C) 2017 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 android.net.wifi.aware; 18 19 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_SK_128; 20 import static android.net.wifi.aware.WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR; 21 22 import android.annotation.IntRange; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.net.ConnectivityManager; 26 import android.net.Network; 27 import android.net.NetworkRequest; 28 import android.net.NetworkSpecifier; 29 import android.os.Build; 30 import android.os.Parcel; 31 import android.os.Parcelable; 32 33 import androidx.annotation.RequiresApi; 34 35 import com.android.modules.utils.build.SdkLevel; 36 37 import java.util.Arrays; 38 import java.util.Objects; 39 40 /** 41 * Network specifier object used to request a Wi-Fi Aware network. Apps should use the 42 * {@link WifiAwareNetworkSpecifier.Builder} class to create an instance. 43 */ 44 public final class WifiAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable { 45 /** 46 * TYPE: in band, specific peer: role, client_id, session_id, peer_id, pmk/passphrase optional 47 * @hide 48 */ 49 public static final int NETWORK_SPECIFIER_TYPE_IB = 0; 50 51 /** 52 * TYPE: in band, any peer: role, client_id, session_id, pmk/passphrase optional 53 * [only permitted for RESPONDER] 54 * @hide 55 */ 56 public static final int NETWORK_SPECIFIER_TYPE_IB_ANY_PEER = 1; 57 58 /** 59 * TYPE: out-of-band: role, client_id, peer_mac, pmk/passphrase optional 60 * @hide 61 */ 62 public static final int NETWORK_SPECIFIER_TYPE_OOB = 2; 63 64 /** 65 * TYPE: out-of-band, any peer: role, client_id, pmk/passphrase optional 66 * [only permitted for RESPONDER] 67 * @hide 68 */ 69 public static final int NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER = 3; 70 71 /** @hide */ 72 public static final int NETWORK_SPECIFIER_TYPE_MAX_VALID = NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER; 73 74 /** 75 * One of the NETWORK_SPECIFIER_TYPE_* constants. The type of the network specifier object. 76 * @hide 77 */ 78 public final int type; 79 80 /** 81 * The role of the device: WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR or 82 * WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER. 83 * @hide 84 */ 85 public final int role; 86 87 /** 88 * The client ID of the device. 89 * @hide 90 */ 91 public final int clientId; 92 93 /** 94 * The session ID in which context to request a data-path. Only relevant for IB requests. 95 * @hide 96 */ 97 public final int sessionId; 98 99 /** 100 * The peer ID of the device which the data-path should be connected to. Only relevant for 101 * IB requests (i.e. not IB_ANY_PEER or OOB*). 102 * @hide 103 */ 104 public final int peerId; 105 106 /** 107 * The peer MAC address of the device which the data-path should be connected to. Only relevant 108 * for OB requests (i.e. not OOB_ANY_PEER or IB*). 109 * @hide 110 */ 111 public final byte[] peerMac; 112 113 /** 114 * The PMK of the requested data-path. Can be null. Only one or none of pmk or passphrase should 115 * be specified. 116 * @hide 117 */ 118 public final byte[] pmk; 119 120 /** 121 * The Passphrase of the requested data-path. Can be null. Only one or none of the pmk or 122 * passphrase should be specified. 123 * @hide 124 */ 125 public final String passphrase; 126 127 /** 128 * The port information to be used for this link. This information will be communicated to the 129 * peer as part of the layer 2 link setup. 130 * 131 * Information only allowed on secure links since a single layer-2 link is set up for all 132 * requestors. Therefore if multiple apps on a single device request links to the same peer 133 * device they all get the same link. However, the link is only set up on the first request - 134 * hence only the first can transmit the port information. But we don't want to expose that 135 * information to other apps. Limiting to secure links would (usually) imply single app usage. 136 * 137 * @hide 138 */ 139 public final int port; 140 141 /** 142 * The transport protocol information to be used for this link. This information will be 143 * communicated to the peer as part of the layer 2 link setup. 144 * 145 * Information only allowed on secure links since a single layer-2 link is set up for all 146 * requestors. Therefore if multiple apps on a single device request links to the same peer 147 * device they all get the same link. However, the link is only set up on the first request - 148 * hence only the first can transmit the port information. But we don't want to expose that 149 * information to other apps. Limiting to secure links would (usually) imply single app usage. 150 * 151 * @hide 152 */ 153 public final int transportProtocol; 154 155 /** 156 * Channel frequency in MHz for setup data-path on. 157 */ 158 private final int mChannelInMhz; 159 160 /** 161 * Force to use the specified channel or not. If true, Channel request is specified and must be 162 * respected. If the firmware cannot honor the request then the data-path request is rejected. 163 * Otherwise, requested channel can be overridden by firmware. 164 */ 165 private final boolean mForcedChannel; 166 167 private final WifiAwareDataPathSecurityConfig mSecurityConfig; 168 169 /** 170 * Get the specified channel in MHZ for this Wi-Fi Aware network specifier. 171 * @see Builder#setChannelFrequencyMhz(int, boolean) 172 * @return Channel frequency in Mhz. A value of 0 indicates that no channel was specified. 173 */ 174 @IntRange(from = 0) getChannelFrequencyMhz()175 public int getChannelFrequencyMhz() { 176 return mChannelInMhz; 177 } 178 179 /** 180 * Check if the specified channel is required to honor or not. 181 * @see Builder#setChannelFrequencyMhz(int, boolean) 182 * @return true if forced to honer, false for recommend to use. 183 */ isChannelRequired()184 public boolean isChannelRequired() { 185 return mForcedChannel; 186 } 187 188 /** 189 * Get the security config specified in this Network Specifier to encrypt Wi-Fi Aware data-path 190 * @return {@link WifiAwareDataPathSecurityConfig} used to encrypt the data-path 191 */ getWifiAwareDataPathSecurityConfig()192 public @Nullable WifiAwareDataPathSecurityConfig getWifiAwareDataPathSecurityConfig() { 193 return mSecurityConfig; 194 } 195 196 /** @hide */ WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId, byte[] peerMac, int port, int transportProtocol, int channel, boolean forcedChannel, WifiAwareDataPathSecurityConfig securityConfig)197 public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId, 198 byte[] peerMac, int port, int transportProtocol, 199 int channel, boolean forcedChannel, WifiAwareDataPathSecurityConfig securityConfig) { 200 this.type = type; 201 this.role = role; 202 this.clientId = clientId; 203 this.sessionId = sessionId; 204 this.peerId = peerId; 205 this.peerMac = peerMac; 206 this.port = port; 207 this.transportProtocol = transportProtocol; 208 this.mChannelInMhz = channel; 209 this.mForcedChannel = forcedChannel; 210 this.mSecurityConfig = securityConfig; 211 this.passphrase = securityConfig == null ? null : securityConfig.getPskPassphrase(); 212 this.pmk = securityConfig == null ? null : securityConfig.getPmk(); 213 } 214 215 /** 216 * TODO(b/214311843): remove this when make SL4A using the public APIs 217 * @hide 218 */ WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId, byte[] peerMac, byte[] pmk, String passphrase, int port, int transportProtocol)219 public WifiAwareNetworkSpecifier(int type, int role, int clientId, int sessionId, int peerId, 220 byte[] peerMac, byte[] pmk, String passphrase, int port, int transportProtocol) { 221 this.type = type; 222 this.role = role; 223 this.clientId = clientId; 224 this.sessionId = sessionId; 225 this.peerId = peerId; 226 this.peerMac = peerMac; 227 this.port = port; 228 this.transportProtocol = transportProtocol; 229 this.mChannelInMhz = 0; 230 this.mForcedChannel = false; 231 this.pmk = pmk; 232 this.passphrase = passphrase; 233 if (pmk != null || passphrase != null) { 234 this.mSecurityConfig = new WifiAwareDataPathSecurityConfig( 235 WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, pmk, null, passphrase 236 ); 237 } else { 238 mSecurityConfig = null; 239 } 240 } 241 242 public static final @android.annotation.NonNull Creator<WifiAwareNetworkSpecifier> CREATOR = 243 new Creator<WifiAwareNetworkSpecifier>() { 244 @Override 245 public WifiAwareNetworkSpecifier createFromParcel(Parcel in) { 246 return new WifiAwareNetworkSpecifier( 247 in.readInt(), // type 248 in.readInt(), // role 249 in.readInt(), // clientId 250 in.readInt(), // sessionId 251 in.readInt(), // peerId 252 in.createByteArray(), // peerMac 253 in.readInt(), // port 254 in.readInt(), // transportProtocol 255 in.readInt(), // channel 256 in.readBoolean(), // forceChannel 257 in.readParcelable(WifiAwareDataPathSecurityConfig 258 .class.getClassLoader())); // securityConfig 259 } 260 261 @Override 262 public WifiAwareNetworkSpecifier[] newArray(int size) { 263 return new WifiAwareNetworkSpecifier[size]; 264 } 265 }; 266 267 /** 268 * Indicates whether the network specifier specifies an OOB (out-of-band) data-path - i.e. a 269 * data-path created without a corresponding Aware discovery session. 270 * 271 * @hide 272 */ isOutOfBand()273 public boolean isOutOfBand() { 274 return type == NETWORK_SPECIFIER_TYPE_OOB || type == NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER; 275 } 276 277 @Override describeContents()278 public int describeContents() { 279 return 0; 280 } 281 282 @Override writeToParcel(Parcel dest, int flags)283 public void writeToParcel(Parcel dest, int flags) { 284 dest.writeInt(type); 285 dest.writeInt(role); 286 dest.writeInt(clientId); 287 dest.writeInt(sessionId); 288 dest.writeInt(peerId); 289 dest.writeByteArray(peerMac); 290 dest.writeInt(port); 291 dest.writeInt(transportProtocol); 292 dest.writeInt(mChannelInMhz); 293 dest.writeBoolean(mForcedChannel); 294 dest.writeParcelable(mSecurityConfig, flags); 295 } 296 297 /** @hide */ 298 @Override canBeSatisfiedBy(NetworkSpecifier other)299 public boolean canBeSatisfiedBy(NetworkSpecifier other) { 300 // MatchAllNetworkSpecifier is taken care in NetworkCapabilities#satisfiedBySpecifier. 301 if (other instanceof WifiAwareAgentNetworkSpecifier) { 302 return ((WifiAwareAgentNetworkSpecifier) other).satisfiesAwareNetworkSpecifier(this); 303 } 304 return equals(other); 305 } 306 307 /** @hide */ 308 @Override hashCode()309 public int hashCode() { 310 return Objects.hash(type, role, clientId, sessionId, peerId, Arrays.hashCode(peerMac), 311 port, transportProtocol, mChannelInMhz, mForcedChannel, mSecurityConfig); 312 } 313 314 /** @hide */ 315 @Override equals(Object obj)316 public boolean equals(Object obj) { 317 if (this == obj) { 318 return true; 319 } 320 321 if (!(obj instanceof WifiAwareNetworkSpecifier)) { 322 return false; 323 } 324 325 WifiAwareNetworkSpecifier lhs = (WifiAwareNetworkSpecifier) obj; 326 327 return type == lhs.type 328 && role == lhs.role 329 && clientId == lhs.clientId 330 && sessionId == lhs.sessionId 331 && peerId == lhs.peerId 332 && Arrays.equals(peerMac, lhs.peerMac) 333 && port == lhs.port 334 && transportProtocol == lhs.transportProtocol 335 && mChannelInMhz == lhs.mChannelInMhz 336 && mForcedChannel == lhs.mForcedChannel 337 && Objects.equals(mSecurityConfig, lhs.mSecurityConfig); 338 } 339 340 /** @hide */ 341 @Override toString()342 public String toString() { 343 StringBuilder sb = new StringBuilder("WifiAwareNetworkSpecifier ["); 344 sb.append("type=").append(type) 345 .append(", role=").append(role) 346 .append(", clientId=").append(clientId) 347 .append(", sessionId=").append(sessionId) 348 .append(", peerId=").append(peerId) 349 // masking potential PII (although low impact information) 350 .append(", peerMac=").append((peerMac == null) ? "<null>" : "<non-null>") 351 // masking PII 352 .append(", securityConfig=").append(mSecurityConfig) 353 .append(", port=").append(port) 354 .append(", transportProtocol=").append(transportProtocol) 355 .append(", channel=").append(mChannelInMhz) 356 .append(", forceChannel=").append(mForcedChannel) 357 .append("]"); 358 return sb.toString(); 359 } 360 361 /** 362 * A builder class for a Wi-Fi Aware network specifier to set up an Aware connection with a 363 * peer. 364 */ 365 public static final class Builder { 366 private DiscoverySession mDiscoverySession; 367 private PeerHandle mPeerHandle; 368 private String mPskPassphrase; 369 private byte[] mPmk; 370 private int mPort = 0; // invalid value 371 private int mTransportProtocol = -1; // invalid value 372 private int mChannel = 0; 373 private boolean mIsRequired = false; 374 private WifiAwareDataPathSecurityConfig mSecurityConfig; 375 376 /** 377 * Create a builder for {@link WifiAwareNetworkSpecifier} used in requests to set up a 378 * Wi-Fi Aware connection with a specific peer. 379 * <p> 380 * To set up a connection to any peer or to multiple peers use 381 * {@link #Builder(PublishDiscoverySession)}. 382 * 383 * @param discoverySession A Wi-Fi Aware discovery session in whose context the connection 384 * is created. 385 * @param peerHandle The handle of the peer to which the Wi-Fi Aware connection is 386 * requested. The peer is discovered through Wi-Fi Aware discovery. The 387 * handle can be obtained through 388 * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)} 389 * or 390 * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}. 391 */ Builder(@onNull DiscoverySession discoverySession, @NonNull PeerHandle peerHandle)392 public Builder(@NonNull DiscoverySession discoverySession, @NonNull PeerHandle peerHandle) { 393 if (discoverySession == null) { 394 throw new IllegalArgumentException("Non-null discoverySession required"); 395 } 396 if (peerHandle == null) { 397 throw new IllegalArgumentException("Non-null peerHandle required"); 398 } 399 mDiscoverySession = discoverySession; 400 mPeerHandle = peerHandle; 401 } 402 403 /** 404 * Create a builder for {@link WifiAwareNetworkSpecifier} used in requests to set up a 405 * Wi-Fi Aware connection. This configuration allows connections to any peers or to 406 * multiple peers (as opposed to only a specific peer with 407 * {@link #Builder(DiscoverySession, PeerHandle)}). 408 * <p> 409 * Multiple connections can be triggered by this configuration and using a single request 410 * via {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)} 411 * and similar methods. Each successful connection will be signaled via the standard 412 * Connectivity Manager mechanisms - 413 * {@link ConnectivityManager.NetworkCallback#onAvailable(Network)}. 414 * Calling {@link ConnectivityManager#unregisterNetworkCallback(ConnectivityManager.NetworkCallback)} 415 * will terminate all connections. 416 */ 417 @RequiresApi(Build.VERSION_CODES.S) Builder(@onNull PublishDiscoverySession publishDiscoverySession)418 public Builder(@NonNull PublishDiscoverySession publishDiscoverySession) { 419 if (!SdkLevel.isAtLeastS()) { 420 throw new UnsupportedOperationException(); 421 } 422 if (publishDiscoverySession == null) { 423 throw new IllegalArgumentException("Non-null publishDiscoverySession required"); 424 } 425 mDiscoverySession = publishDiscoverySession; 426 mPeerHandle = null; 427 } 428 429 /** 430 * Configure the PSK Passphrase for the Wi-Fi Aware connection being requested. This method 431 * is optional - if not called, then an Open (unencrypted) connection will be created. 432 * Note: Use 433 * {@link #setDataPathSecurityConfig(WifiAwareDataPathSecurityConfig)} to avoid 434 * interoperability issues when devices support different cipher suites by explicitly 435 * specifying a cipher suite as opposed to relying on a default cipher suite. 436 * {@link WifiAwareDataPathSecurityConfig.Builder#Builder(int)} 437 * 438 * @param pskPassphrase The (optional) passphrase to be used to encrypt the link. Use the 439 * {@link #setPmk(byte[])} to specify a PMK. 440 * @return the current {@link Builder} builder, enabling chaining of builder 441 * methods. 442 */ setPskPassphrase(@onNull String pskPassphrase)443 public @NonNull Builder setPskPassphrase(@NonNull String pskPassphrase) { 444 if (!WifiAwareUtils.validatePassphrase(pskPassphrase)) { 445 throw new IllegalArgumentException("Passphrase must meet length requirements"); 446 } 447 mPskPassphrase = pskPassphrase; 448 return this; 449 } 450 451 /** 452 * Configure the PMK for the Wi-Fi Aware connection being requested. This method 453 * is optional - if not called, then an Open (unencrypted) connection will be created. 454 * Note: Use 455 * {@link #setDataPathSecurityConfig(WifiAwareDataPathSecurityConfig)} to avoid 456 * interoperability issues when devices support different cipher suites by explicitly 457 * specifying a cipher suite as opposed to relying on a default cipher suite. 458 * 459 * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for 460 * encrypting the data-path. Use the {@link #setPskPassphrase(String)} to 461 * specify a Passphrase. 462 * @return the current {@link Builder} builder, enabling chaining of builder 463 * methods. 464 */ setPmk(@onNull byte[] pmk)465 public @NonNull Builder setPmk(@NonNull byte[] pmk) { 466 if (!WifiAwareUtils.validatePmk(pmk)) { 467 throw new IllegalArgumentException("PMK must 32 bytes"); 468 } 469 mPmk = pmk; 470 return this; 471 } 472 473 /** 474 * Configure the port number which will be used to create a connection over this link. This 475 * configuration should only be done on the server device, e.g. the device creating the 476 * {@link java.net.ServerSocket}. 477 * <p>Notes: 478 * <ul> 479 * <li>The server device must be the Publisher device! 480 * <li>The port information can only be specified on secure links, specified using 481 * {@link #setDataPathSecurityConfig(WifiAwareDataPathSecurityConfig)} 482 * </ul> 483 * 484 * @param port A positive integer indicating the port to be used for communication. 485 * @return the current {@link Builder} builder, enabling chaining of builder 486 * methods. 487 */ setPort(@ntRangefrom = 0, to = 65535) int port)488 public @NonNull Builder setPort(@IntRange(from = 0, to = 65535) int port) { 489 if (port <= 0 || port > 65535) { 490 throw new IllegalArgumentException("The port must be a positive value (0, 65535]"); 491 } 492 mPort = port; 493 return this; 494 } 495 496 /** 497 * Configure the transport protocol which will be used to create a connection over this 498 * link. This configuration should only be done on the server device, e.g. the device 499 * creating the {@link java.net.ServerSocket} for TCP. 500 * <p>Notes: 501 * <ul> 502 * <li>The server device must be the Publisher device! 503 * <li>The transport protocol information can only be specified on secure links, 504 * specified using 505 * {@link #setDataPathSecurityConfig(WifiAwareDataPathSecurityConfig)}. 506 * </ul> 507 * The transport protocol number is assigned by the Internet Assigned Numbers Authority 508 * (IANA) https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml. 509 * 510 * @param transportProtocol The transport protocol to be used for communication. 511 * @return the current {@link Builder} builder, enabling chaining of builder 512 * methods. 513 */ 514 public @NonNull setTransportProtocol(@ntRangefrom = 0, to = 255) int transportProtocol)515 Builder setTransportProtocol(@IntRange(from = 0, to = 255) int transportProtocol) { 516 if (transportProtocol < 0 || transportProtocol > 255) { 517 throw new IllegalArgumentException( 518 "The transport protocol must be in range [0, 255]"); 519 } 520 mTransportProtocol = transportProtocol; 521 return this; 522 } 523 524 /** 525 * Configure the Channel frequency for the Wi-Fi Aware connection being requested. This 526 * method is optional - if not called, then channelInMhz to use will be decided by firmware. 527 * Only use this when {@link WifiAwareManager#isSetChannelOnDataPathSupported()} is true, 528 * otherwise the set channelInMhz will be ignored. 529 * @param channelInMhz Channel frequency in Mhz. 530 * @param required If set to true, Channel request is specified and must be respected. 531 * If the firmware cannot honor the request then the data-path request 532 * is rejected. Otherwise, requested channelInMhz is a recommendation and 533 * may be overridden by the firmware. 534 * @return the current {@link Builder} builder, enabling chaining of builder methods. 535 */ setChannelFrequencyMhz(@ntRangefrom = 0) int channelInMhz, boolean required)536 public @NonNull Builder setChannelFrequencyMhz(@IntRange(from = 0) int channelInMhz, 537 boolean required) { 538 mChannel = channelInMhz; 539 mIsRequired = required; 540 return this; 541 } 542 543 /** 544 * Configure security config for the Wi-Fi Aware connection being requested. This method 545 * is optional - if not called, then an Open (unencrypted) connection will be created. 546 * Note: this method is the superset of the {@link #setPmk(byte[])} and 547 * {@link #setPskPassphrase(String)}. 548 * 549 * @param securityConfig The (optional) security config to be used to encrypt the link. 550 * @return the current {@link Builder} builder, enabling chaining of builder 551 * methods. 552 */ setDataPathSecurityConfig( @onNull WifiAwareDataPathSecurityConfig securityConfig)553 public @NonNull Builder setDataPathSecurityConfig( 554 @NonNull WifiAwareDataPathSecurityConfig securityConfig) { 555 if (securityConfig == null) { 556 throw new IllegalArgumentException("The WifiAwareDataPathSecurityConfig " 557 + "should be non-null"); 558 } 559 560 if (!securityConfig.isValid()) { 561 throw new IllegalArgumentException("The WifiAwareDataPathSecurityConfig " 562 + "is invalid"); 563 } 564 mSecurityConfig = securityConfig; 565 return this; 566 } 567 568 /** 569 * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} 570 * for a WiFi Aware connection (link) to the specified peer. The 571 * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to 572 * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}. 573 * <p> The default builder constructor will initialize a NetworkSpecifier which requests an 574 * open (non-encrypted) link. To request an encrypted link use the 575 * {@link #setPskPassphrase(String)} or {@link #setPmk(byte[])} builder methods. 576 * 577 * @return A {@link NetworkSpecifier} to be used to construct 578 * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass 579 * to {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest, 580 * android.net.ConnectivityManager.NetworkCallback)} 581 * [or other varieties of that API]. 582 */ build()583 public @NonNull WifiAwareNetworkSpecifier build() { 584 if (mDiscoverySession == null) { 585 throw new IllegalStateException("Null discovery session!?"); 586 } 587 if (mPskPassphrase != null && mPmk != null) { 588 throw new IllegalStateException( 589 "Can only specify a Passphrase or a PMK - not both!"); 590 } 591 WifiAwareDataPathSecurityConfig securityConfig = mSecurityConfig; 592 if (mPskPassphrase != null || mPmk != null) { 593 if (securityConfig != null) { 594 throw new IllegalStateException( 595 "Can only specify a SecurityConfig or a PMK(Passphrase) - not both!"); 596 } 597 securityConfig = new WifiAwareDataPathSecurityConfig( 598 WIFI_AWARE_CIPHER_SUITE_NCS_SK_128, mPmk, null, 599 mPskPassphrase); 600 } 601 602 int role = mDiscoverySession instanceof SubscribeDiscoverySession 603 ? WIFI_AWARE_DATA_PATH_ROLE_INITIATOR 604 : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER; 605 606 if (mPort != 0 || mTransportProtocol != -1) { 607 if (role != WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) { 608 throw new IllegalStateException( 609 "Port and transport protocol information can only " 610 + "be specified on the Publisher device (which is the server"); 611 } 612 if (securityConfig == null) { 613 throw new IllegalStateException("Port and transport protocol information can " 614 + "only be specified on a secure link"); 615 } 616 } 617 int type = mPeerHandle == null 618 ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER : 619 WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB; 620 621 return new WifiAwareNetworkSpecifier(type, role, mDiscoverySession.mClientId, 622 mDiscoverySession.mSessionId, mPeerHandle != null ? mPeerHandle.peerId : 0, 623 null, mPort, mTransportProtocol, mChannel, mIsRequired, securityConfig); 624 } 625 } 626 } 627