• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.net.wifi.aware;
18 
19 import static android.Manifest.permission.MANAGE_WIFI_NETWORK_SELECTION;
20 import static android.net.wifi.aware.Characteristics.WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SystemApi;
26 import android.net.NetworkSpecifier;
27 import android.os.Build;
28 import android.util.CloseGuard;
29 import android.util.Log;
30 
31 import androidx.annotation.RequiresApi;
32 
33 import com.android.internal.annotations.VisibleForTesting;
34 import com.android.modules.utils.build.SdkLevel;
35 
36 import java.lang.ref.Reference;
37 import java.lang.ref.WeakReference;
38 
39 /**
40  * A class representing a single publish or subscribe Aware session. This object
41  * will not be created directly - only its child classes are available:
42  * {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This
43  * class provides functionality common to both publish and subscribe discovery sessions:
44  * <ul>
45  *      <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} method.
46  *      <li>Creating a network-specifier when requesting a Aware connection using
47  *      {@link WifiAwareNetworkSpecifier.Builder}.
48  * </ul>
49  * <p>
50  * The {@link #close()} method must be called to destroy discovery sessions once they are
51  * no longer needed.
52  */
53 public class DiscoverySession implements AutoCloseable {
54     private static final String TAG = "DiscoverySession";
55     private static final boolean DBG = false;
56     private static final boolean VDBG = false; // STOPSHIP if true
57 
58     private static final int MAX_SEND_RETRY_COUNT = 5;
59 
60     /** @hide */
61     protected WeakReference<WifiAwareManager> mMgr;
62     /** @hide */
63     protected final int mClientId;
64     /** @hide */
65     protected final int mSessionId;
66     /** @hide */
67     protected boolean mTerminated = false;
68 
69     private final CloseGuard mCloseGuard = new CloseGuard();
70 
71     /**
72      * Return the maximum permitted retry count when sending messages using
73      * {@link #sendMessage(PeerHandle, int, byte[], int)}.
74      *
75      * @return Maximum retry count when sending messages.
76      *
77      * @hide
78      */
getMaxSendRetryCount()79     public static int getMaxSendRetryCount() {
80         return MAX_SEND_RETRY_COUNT;
81     }
82 
83     /** @hide */
DiscoverySession(WifiAwareManager manager, int clientId, int sessionId)84     public DiscoverySession(WifiAwareManager manager, int clientId, int sessionId) {
85         if (VDBG) {
86             Log.v(TAG, "New discovery session created: manager=" + manager + ", clientId="
87                     + clientId + ", sessionId=" + sessionId);
88         }
89 
90         mMgr = new WeakReference<>(manager);
91         mClientId = clientId;
92         mSessionId = sessionId;
93 
94         mCloseGuard.open("close");
95     }
96 
97     /**
98      * Destroy the publish or subscribe session - free any resources, and stop
99      * transmitting packets on-air (for an active session) or listening for
100      * matches (for a passive session). The session may not be used for any
101      * additional operations after its destruction.
102      * <p>
103      *     This operation must be done on a session which is no longer needed. Otherwise system
104      *     resources will continue to be utilized until the application exits. The only
105      *     exception is a session for which we received a termination callback,
106      *     {@link DiscoverySessionCallback#onSessionTerminated()}.
107      */
108     @Override
close()109     public void close() {
110         WifiAwareManager mgr = mMgr.get();
111         if (mgr == null) {
112             Log.w(TAG, "destroy: called post GC on WifiAwareManager");
113             return;
114         }
115         mgr.terminateSession(mClientId, mSessionId);
116         mTerminated = true;
117         mMgr.clear();
118         mCloseGuard.close();
119         Reference.reachabilityFence(this);
120     }
121 
122     /**
123      * Sets the status of the session to terminated - i.e. an indication that
124      * already terminated rather than executing a termination.
125      *
126      * @hide
127      */
setTerminated()128     public void setTerminated() {
129         if (mTerminated) {
130             Log.w(TAG, "terminate: already terminated.");
131             return;
132         }
133 
134         mTerminated = true;
135         mMgr.clear();
136         mCloseGuard.close();
137     }
138 
139     /** @hide */
140     @Override
finalize()141     protected void finalize() throws Throwable {
142         try {
143             if (mCloseGuard != null) {
144                 mCloseGuard.warnIfOpen();
145             }
146 
147             if (!mTerminated) {
148                 close();
149             }
150         } finally {
151             super.finalize();
152         }
153     }
154 
155     /**
156      * Access the client ID of the Aware session.
157      *
158      * Note: internal visibility for testing.
159      *
160      * @return The internal client ID.
161      *
162      * @hide
163      */
164     @VisibleForTesting
getClientId()165     public int getClientId() {
166         return mClientId;
167     }
168 
169     /**
170      * Access the discovery session ID of the Aware session.
171      *
172      * Note: internal visibility for testing.
173      *
174      * @return The internal discovery session ID.
175      *
176      * @hide
177      */
178     @VisibleForTesting
getSessionId()179     public int getSessionId() {
180         return mSessionId;
181     }
182 
183     /**
184      * Sends a message to the specified destination. Aware messages are transmitted in the context
185      * of a discovery session - executed subsequent to a publish/subscribe
186      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
187      * byte[], java.util.List)} event.
188      * <p>
189      *     Aware messages are not guaranteed delivery. Callbacks on
190      *     {@link DiscoverySessionCallback} indicate message was transmitted successfully,
191      *     {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
192      *     failed (possibly after several retries) -
193      *     {@link DiscoverySessionCallback#onMessageSendFailed(int)}.
194      * <p>
195      *     The peer will get a callback indicating a message was received using
196      *     {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
197      *     byte[])}.
198      *
199      * @param peerHandle The peer's handle for the message. Must be a result of an
200      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
201      * byte[], java.util.List)} or
202      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
203      * byte[])} events.
204      * @param messageId An arbitrary integer used by the caller to identify the message. The same
205      *            integer ID will be returned in the callbacks indicating message send success or
206      *            failure. The {@code messageId} is not used internally by the Aware service - it
207      *                  can be arbitrary and non-unique.
208      * @param message The message to be transmitted.
209      * @param retryCount An integer specifying how many additional service-level (as opposed to PHY
210      *            or MAC level) retries should be attempted if there is no ACK from the receiver
211      *            (note: no retransmissions are attempted in other failure cases). A value of 0
212      *            indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
213      *
214      * @hide
215      */
sendMessage(@onNull PeerHandle peerHandle, int messageId, @Nullable byte[] message, int retryCount)216     public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
217             @Nullable byte[] message, int retryCount) {
218         if (mTerminated) {
219             Log.w(TAG, "sendMessage: called on terminated session");
220             return;
221         }
222 
223         WifiAwareManager mgr = mMgr.get();
224         if (mgr == null) {
225             Log.w(TAG, "sendMessage: called post GC on WifiAwareManager");
226             return;
227         }
228 
229         mgr.sendMessage(mClientId, mSessionId, peerHandle, message, messageId, retryCount);
230     }
231 
232     /**
233      * Sends a message to the specified destination. Aware messages are transmitted in the context
234      * of a discovery session - executed subsequent to a publish/subscribe
235      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
236      * byte[], java.util.List)} event.
237      * <p>
238      *     Aware messages are not guaranteed delivery. Callbacks on
239      *     {@link DiscoverySessionCallback} indicate message was transmitted successfully,
240      *     {@link DiscoverySessionCallback#onMessageSendSucceeded(int)}, or transmission
241      *     failed (possibly after several retries) -
242      *     {@link DiscoverySessionCallback#onMessageSendFailed(int)}.
243      * <p>
244      * The peer will get a callback indicating a message was received using
245      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
246      * byte[])}.
247      *
248      * @param peerHandle The peer's handle for the message. Must be a result of an
249      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
250      * byte[], java.util.List)} or
251      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
252      * byte[])} events.
253      * @param messageId An arbitrary integer used by the caller to identify the message. The same
254      *            integer ID will be returned in the callbacks indicating message send success or
255      *            failure. The {@code messageId} is not used internally by the Aware service - it
256      *                  can be arbitrary and non-unique.
257      * @param message The message to be transmitted.
258      */
sendMessage(@onNull PeerHandle peerHandle, int messageId, @Nullable byte[] message)259     public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
260             @Nullable byte[] message) {
261         sendMessage(peerHandle, messageId, message, 0);
262     }
263 
264     /**
265      * Initiate a Wi-Fi Aware Pairing setup request to create a pairing with the target peer.
266      * The Aware pairing request should be done in the context of a discovery session -
267      * after a publish/subscribe
268      * {@link DiscoverySessionCallback#onServiceDiscovered(ServiceDiscoveryInfo)} event is received.
269      * The peer will get a callback indicating a message was received using
270      * {@link DiscoverySessionCallback#onPairingSetupRequestReceived(PeerHandle, int)}.
271      * When the Aware Pairing setup is finished, both sides will receive
272      * {@link DiscoverySessionCallback#onPairingSetupSucceeded(PeerHandle, String)}
273      *
274      * @param peerHandle      The peer's handle for the pairing request. Must be a result of a
275      *                        {@link
276      *                        DiscoverySessionCallback#onServiceDiscovered(ServiceDiscoveryInfo)}
277      *                        or
278      *                        {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}
279      *                        events.
280      * @param peerDeviceAlias The alias of paired device set by caller, will help caller to identify
281      *                        the paired device.
282      * @param cipherSuite     The cipher suite to be used to encrypt the link.
283      * @param password        The password used for the pairing setup. If set to empty or null,
284      *                        opportunistic pairing will be used.
285      */
286     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
initiatePairingRequest(@onNull PeerHandle peerHandle, @NonNull String peerDeviceAlias, @Characteristics.WifiAwarePairingCipherSuites int cipherSuite, @Nullable String password)287     public void initiatePairingRequest(@NonNull PeerHandle peerHandle,
288             @NonNull String peerDeviceAlias,
289             @Characteristics.WifiAwarePairingCipherSuites int cipherSuite,
290             @Nullable String password) {
291         if (!SdkLevel.isAtLeastU()) {
292             throw new UnsupportedOperationException();
293         }
294         WifiAwareManager mgr = mMgr.get();
295         if (mgr == null) {
296             Log.w(TAG, "initiatePairingRequest: called post GC on WifiAwareManager");
297             return;
298         }
299         mgr.initiateNanPairingSetupRequest(mClientId, mSessionId, peerHandle, password,
300                 peerDeviceAlias, cipherSuite);
301     }
302 
303     /**
304      * Accept and respond to a Wi-Fi Aware Pairing setup request received from peer. This is the
305      * response to the
306      * {@link DiscoverySessionCallback#onPairingSetupRequestReceived(PeerHandle, int)}
307      * When the Aware Pairing setup is finished, both sides will receive
308      * {@link DiscoverySessionCallback#onPairingSetupSucceeded(PeerHandle, String)}
309      *
310      * @param requestId       Id to identify the received pairing session, obtained by
311      *                        {@link
312      *                        DiscoverySessionCallback#onPairingSetupRequestReceived(PeerHandle,
313      *                        int)}
314      * @param peerHandle      The peer's handle for the pairing request. Must be a result of a
315      *                        {@link
316      *                        DiscoverySessionCallback#onServiceDiscovered(ServiceDiscoveryInfo)}
317      *                        or
318      *                        {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}
319      *                        events.
320      * @param peerDeviceAlias The alias of paired device set by caller, will help caller to identify
321      *                        the paired device.
322      * @param cipherSuite     The cipher suite to be used to encrypt the link.
323      * @param password        The password is used for the pairing setup. If set to empty or null,
324      *                        opportunistic pairing will be used.
325      */
326     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
acceptPairingRequest(int requestId, @NonNull PeerHandle peerHandle, @NonNull String peerDeviceAlias, @Characteristics.WifiAwarePairingCipherSuites int cipherSuite, @Nullable String password)327     public void acceptPairingRequest(int requestId, @NonNull PeerHandle peerHandle,
328             @NonNull String peerDeviceAlias,
329             @Characteristics.WifiAwarePairingCipherSuites int cipherSuite,
330             @Nullable String password) {
331         if (!SdkLevel.isAtLeastU()) {
332             throw new UnsupportedOperationException();
333         }
334         WifiAwareManager mgr = mMgr.get();
335         if (mgr == null) {
336             Log.w(TAG, "initiatePairingRequest: called post GC on WifiAwareManager");
337             return;
338         }
339         mgr.responseNanPairingSetupRequest(mClientId, mSessionId, peerHandle, requestId, password,
340                 peerDeviceAlias, true, cipherSuite);
341     }
342 
343     /**
344      * Reject a Wi-Fi Aware Pairing setup request received from peer. This is the
345      * response to the
346      * {@link DiscoverySessionCallback#onPairingSetupRequestReceived(PeerHandle, int)}
347      *
348      * @param requestId       Id to identify the received pairing session, get by
349      *                        {@link
350      *                        DiscoverySessionCallback#onPairingSetupRequestReceived(PeerHandle,
351      *                        int)}
352      * @param peerHandle      The peer's handle for the pairing request. Must be a result of a
353      *                        {@link
354      *                        DiscoverySessionCallback#onServiceDiscovered(ServiceDiscoveryInfo)}
355      *                        or
356      *                        {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}
357      *                        events.
358      */
359     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
rejectPairingRequest(int requestId, @NonNull PeerHandle peerHandle)360     public void rejectPairingRequest(int requestId, @NonNull PeerHandle peerHandle) {
361         if (!SdkLevel.isAtLeastU()) {
362             throw new UnsupportedOperationException();
363         }
364         WifiAwareManager mgr = mMgr.get();
365         if (mgr == null) {
366             Log.w(TAG, "initiatePairingRequest: called post GC on WifiAwareManager");
367             return;
368         }
369         mgr.responseNanPairingSetupRequest(mClientId, mSessionId, peerHandle, requestId, null,
370                 null, false, WIFI_AWARE_CIPHER_SUITE_NCS_PK_PASN_128);
371     }
372 
373     /**
374      * Initiate a Wi-Fi Aware bootstrapping setup request to create a pairing with the target peer.
375      * The Aware bootstrapping request should be done in the context of a discovery session -
376      * after a publish/subscribe
377      * {@link DiscoverySessionCallback#onServiceDiscovered(ServiceDiscoveryInfo)} event is received.
378      * The peer will check if the method can be fulfilled by
379      * {@link AwarePairingConfig.Builder#setBootstrappingMethods(int)}
380      * When the Aware Bootstrapping setup finished, both side will receive
381      * {@link DiscoverySessionCallback#onBootstrappingSucceeded(PeerHandle, int)}
382      * @param peerHandle The peer's handle for the pairing request. Must be a result of an
383      * {@link DiscoverySessionCallback#onServiceDiscovered(ServiceDiscoveryInfo)} or
384      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])} events.
385      * @param method one of the AwarePairingConfig#PAIRING_BOOTSTRAPPING_ values, should be one of
386      *               the methods received from {@link ServiceDiscoveryInfo#getPairingConfig()}
387      *               {@link AwarePairingConfig#getBootstrappingMethods()}
388      */
389     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
initiateBootstrappingRequest(@onNull PeerHandle peerHandle, @AwarePairingConfig.BootstrappingMethod int method)390     public void initiateBootstrappingRequest(@NonNull PeerHandle peerHandle,
391             @AwarePairingConfig.BootstrappingMethod int method) {
392         if (!SdkLevel.isAtLeastU()) {
393             throw new UnsupportedOperationException();
394         }
395         WifiAwareManager mgr = mMgr.get();
396         if (mgr == null) {
397             Log.w(TAG, "initiatePairingRequest: called post GC on WifiAwareManager");
398             return;
399         }
400         mgr.initiateBootStrappingSetupRequest(mClientId, mSessionId, peerHandle, method);
401     }
402 
403     /**
404      * Put Aware connection into suspension mode to save power. Suspend mode pauses all Wi-Fi Aware
405      * activities for this discovery session including any active NDPs.
406      * <p>
407      * This method would work only for a {@link DiscoverySession} which has been created using
408      * a suspendable {@link PublishConfig} or {@link SubscribeConfig}.
409      *
410      * @see PublishConfig#isSuspendable()
411      * @see SubscribeConfig#isSuspendable()
412      * @hide
413      */
414     @SystemApi
415     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
416     @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
suspend()417     public void suspend() {
418         if (mTerminated) {
419             throw new IllegalStateException("Suspend called on a terminated session.");
420         }
421 
422         WifiAwareManager mgr = mMgr.get();
423         if (mgr == null) {
424             throw new IllegalStateException("Failed to get WifiAwareManager.");
425         }
426 
427         if (!SdkLevel.isAtLeastU()) {
428             throw new UnsupportedOperationException();
429         }
430 
431         mgr.suspend(mClientId, mSessionId);
432     }
433 
434     /**
435      * Wake up Aware connection from suspension mode to transmit data. Resumes all paused
436      * Wi-Fi Aware activities and any associated NDPs to a state before they were suspended. Resume
437      * operation will be faster than recreating the corresponding discovery session and NDPs with
438      * the same benefit of power.
439      * <p>
440      * This method would work only for a {@link DiscoverySession} which has been created using
441      * a suspendable {@link PublishConfig} or {@link SubscribeConfig}.
442      *
443      * @see PublishConfig#isSuspendable()
444      * @see SubscribeConfig#isSuspendable()
445      * @hide
446      */
447     @SystemApi
448     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
449     @RequiresPermission(MANAGE_WIFI_NETWORK_SELECTION)
resume()450     public void resume() {
451         if (mTerminated) {
452             throw new IllegalStateException("Resume called on a terminated session.");
453         }
454 
455         WifiAwareManager mgr = mMgr.get();
456         if (mgr == null) {
457             throw new IllegalStateException("Failed to get WifiAwareManager.");
458         }
459 
460         if (!SdkLevel.isAtLeastU()) {
461             throw new UnsupportedOperationException();
462         }
463 
464         mgr.resume(mClientId, mSessionId);
465     }
466 
467     /**
468      * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
469      * an unencrypted WiFi Aware connection (link) to the specified peer. The
470      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
471      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
472      * <p>
473      * This method should be used when setting up a connection with a peer discovered through Aware
474      * discovery or communication (in such scenarios the MAC address of the peer is shielded by
475      * an opaque peer ID handle). If an Aware connection is needed to a peer discovered using other
476      * OOB (out-of-band) mechanism then use the alternative
477      * {@link WifiAwareSession#createNetworkSpecifierOpen(int, byte[])} method - which uses the
478      * peer's MAC address.
479      * <p>
480      * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
481      * and a Publisher is a RESPONDER.
482      * <p>
483      * To set up an encrypted link use the
484      * {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} API.
485      * @deprecated Use the replacement {@link WifiAwareNetworkSpecifier.Builder}.
486      *
487      * @param peerHandle The peer's handle obtained through
488      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], java.util.List)}
489      *                   or
490      *                   {@link DiscoverySessionCallback#onMessageReceived(PeerHandle, byte[])}.
491      *                   On a RESPONDER this value is used to gate the acceptance of a connection
492      *                   request from only that peer.
493      *
494      * @return A {@link NetworkSpecifier} to be used to construct
495      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
496      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
497      * android.net.ConnectivityManager.NetworkCallback)}
498      * [or other varieties of that API].
499      */
500     @Deprecated
createNetworkSpecifierOpen(@onNull PeerHandle peerHandle)501     public NetworkSpecifier createNetworkSpecifierOpen(@NonNull PeerHandle peerHandle) {
502         if (mTerminated) {
503             Log.w(TAG, "createNetworkSpecifierOpen: called on terminated session");
504             return null;
505         }
506 
507         WifiAwareManager mgr = mMgr.get();
508         if (mgr == null) {
509             Log.w(TAG, "createNetworkSpecifierOpen: called post GC on WifiAwareManager");
510             return null;
511         }
512 
513         int role = this instanceof SubscribeDiscoverySession
514                 ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
515                 : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
516 
517         return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null, null);
518     }
519 
520     /**
521      * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
522      * an encrypted WiFi Aware connection (link) to the specified peer. The
523      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
524      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
525      * <p>
526      * This method should be used when setting up a connection with a peer discovered through Aware
527      * discovery or communication (in such scenarios the MAC address of the peer is shielded by
528      * an opaque peer ID handle). If an Aware connection is needed to a peer discovered using other
529      * OOB (out-of-band) mechanism then use the alternative
530      * {@link WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)} method -
531      * which uses the peer's MAC address.
532      * <p>
533      * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
534      * and a Publisher is a RESPONDER.
535      * @deprecated Use the replacement {@link WifiAwareNetworkSpecifier.Builder}.
536      *
537      * @param peerHandle The peer's handle obtained through
538      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
539      * byte[], java.util.List)} or
540      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
541      * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
542      *                   from only that peer.
543      * @param passphrase The passphrase to be used to encrypt the link. The PMK is generated from
544      *                   the passphrase. Use the
545      *                   {@link #createNetworkSpecifierOpen(PeerHandle)} API to
546      *                   specify an open (unencrypted) link.
547      *
548      * @return A {@link NetworkSpecifier} to be used to construct
549      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
550      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
551      * android.net.ConnectivityManager.NetworkCallback)}
552      * [or other varieties of that API].
553      */
554     @Deprecated
createNetworkSpecifierPassphrase( @onNull PeerHandle peerHandle, @NonNull String passphrase)555     public NetworkSpecifier createNetworkSpecifierPassphrase(
556             @NonNull PeerHandle peerHandle, @NonNull String passphrase) {
557         if (!WifiAwareUtils.validatePassphrase(passphrase)) {
558             throw new IllegalArgumentException("Passphrase must meet length requirements");
559         }
560 
561         if (mTerminated) {
562             Log.w(TAG, "createNetworkSpecifierPassphrase: called on terminated session");
563             return null;
564         }
565 
566         WifiAwareManager mgr = mMgr.get();
567         if (mgr == null) {
568             Log.w(TAG, "createNetworkSpecifierPassphrase: called post GC on WifiAwareManager");
569             return null;
570         }
571 
572         int role = this instanceof SubscribeDiscoverySession
573                 ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
574                 : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
575 
576         return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, null,
577                 passphrase);
578     }
579 
580     /**
581      * Create a {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} for
582      * an encrypted WiFi Aware connection (link) to the specified peer. The
583      * {@link android.net.NetworkRequest.Builder#addTransportType(int)} should be set to
584      * {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
585      * <p>
586      * This method should be used when setting up a connection with a peer discovered through Aware
587      * discovery or communication (in such scenarios the MAC address of the peer is shielded by
588      * an opaque peer ID handle). If an Aware connection is needed to a peer discovered using other
589      * OOB (out-of-band) mechanism then use the alternative
590      * {@link WifiAwareSession#createNetworkSpecifierPmk(int, byte[], byte[])} method - which uses
591      * the peer's MAC address.
592      * <p>
593      * Note: per the Wi-Fi Aware specification the roles are fixed - a Subscriber is an INITIATOR
594      * and a Publisher is a RESPONDER.
595      * @deprecated Use the replacement {@link WifiAwareNetworkSpecifier.Builder}.
596      *
597      * @param peerHandle The peer's handle obtained through
598      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
599      * byte[], java.util.List)} or
600      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
601      * byte[])}. On a RESPONDER this value is used to gate the acceptance of a connection request
602      *                   from only that peer.
603      * @param pmk A PMK (pairwise master key, see IEEE 802.11i) specifying the key to use for
604      *            encrypting the data-path. Use the
605      *            {@link #createNetworkSpecifierPassphrase(PeerHandle, String)} to specify a
606      *            Passphrase or {@link #createNetworkSpecifierOpen(PeerHandle)} to specify an
607      *            open (unencrypted) link.
608      *
609      * @return A {@link NetworkSpecifier} to be used to construct
610      * {@link android.net.NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} to pass to
611      * {@link android.net.ConnectivityManager#requestNetwork(android.net.NetworkRequest,
612      * android.net.ConnectivityManager.NetworkCallback)}
613      * [or other varieties of that API].
614      *
615      * @hide
616      */
617     @Deprecated
618     @SystemApi
createNetworkSpecifierPmk(@onNull PeerHandle peerHandle, @NonNull byte[] pmk)619     public NetworkSpecifier createNetworkSpecifierPmk(@NonNull PeerHandle peerHandle,
620             @NonNull byte[] pmk) {
621         if (!WifiAwareUtils.validatePmk(pmk)) {
622             throw new IllegalArgumentException("PMK must 32 bytes");
623         }
624 
625         if (mTerminated) {
626             Log.w(TAG, "createNetworkSpecifierPmk: called on terminated session");
627             return null;
628         }
629 
630         WifiAwareManager mgr = mMgr.get();
631         if (mgr == null) {
632             Log.w(TAG, "createNetworkSpecifierPmk: called post GC on WifiAwareManager");
633             return null;
634         }
635 
636         int role = this instanceof SubscribeDiscoverySession
637                 ? WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
638                 : WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_RESPONDER;
639 
640         return mgr.createNetworkSpecifier(mClientId, role, mSessionId, peerHandle, pmk, null);
641     }
642 }
643