• 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.ACCESS_FINE_LOCATION;
20 import static android.Manifest.permission.ACCESS_WIFI_STATE;
21 import static android.Manifest.permission.CHANGE_WIFI_STATE;
22 import static android.Manifest.permission.NEARBY_WIFI_DEVICES;
23 import static android.Manifest.permission.OVERRIDE_WIFI_CONFIG;
24 
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.RequiresPermission;
29 import android.annotation.SdkConstant;
30 import android.annotation.SdkConstant.SdkConstantType;
31 import android.annotation.SystemApi;
32 import android.annotation.SystemService;
33 import android.content.Context;
34 import android.net.ConnectivityManager;
35 import android.net.NetworkRequest;
36 import android.net.NetworkSpecifier;
37 import android.net.wifi.WifiManager;
38 import android.net.wifi.util.HexEncoding;
39 import android.os.Binder;
40 import android.os.Build;
41 import android.os.Bundle;
42 import android.os.Handler;
43 import android.os.Looper;
44 import android.os.Message;
45 import android.os.RemoteException;
46 import android.util.Log;
47 
48 import androidx.annotation.RequiresApi;
49 
50 import com.android.modules.utils.build.SdkLevel;
51 
52 import java.lang.annotation.Retention;
53 import java.lang.annotation.RetentionPolicy;
54 import java.lang.ref.WeakReference;
55 import java.nio.BufferOverflowException;
56 import java.util.Collections;
57 import java.util.List;
58 
59 /**
60  * This class provides the primary API for managing Wi-Fi Aware operations:
61  * discovery and peer-to-peer data connections.
62  * <p>
63  * The class provides access to:
64  * <ul>
65  * <li>Initialize a Aware cluster (peer-to-peer synchronization). Refer to
66  * {@link #attach(AttachCallback, Handler)}.
67  * <li>Create discovery sessions (publish or subscribe sessions). Refer to
68  * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)} and
69  * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}.
70  * <li>Create a Aware network specifier to be used with
71  * {@link ConnectivityManager#requestNetwork(NetworkRequest, ConnectivityManager.NetworkCallback)}
72  * to set-up a Aware connection with a peer. Refer to {@link WifiAwareNetworkSpecifier.Builder}.
73  * </ul>
74  * <p>
75  *     Aware may not be usable when Wi-Fi is disabled (and other conditions). To validate that
76  *     the functionality is available use the {@link #isAvailable()} function. To track
77  *     changes in Aware usability register for the {@link #ACTION_WIFI_AWARE_STATE_CHANGED}
78  *     broadcast. Note that this broadcast is not sticky - you should register for it and then
79  *     check the above API to avoid a race condition.
80  * <p>
81  *     An application must use {@link #attach(AttachCallback, Handler)} to initialize a
82  *     Aware cluster - before making any other Aware operation. Aware cluster membership is a
83  *     device-wide operation - the API guarantees that the device is in a cluster or joins a
84  *     Aware cluster (or starts one if none can be found). Information about attach success (or
85  *     failure) are returned in callbacks of {@link AttachCallback}. Proceed with Aware
86  *     discovery or connection setup only after receiving confirmation that Aware attach
87  *     succeeded - {@link AttachCallback#onAttached(WifiAwareSession)}. When an
88  *     application is finished using Aware it <b>must</b> use the
89  *     {@link WifiAwareSession#close()} API to indicate to the Aware service that the device
90  *     may detach from the Aware cluster. The device will actually disable Aware once the last
91  *     application detaches.
92  * <p>
93  *     Once a Aware attach is confirmed use the
94  *     {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)}
95  *     or
96  *     {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback,
97  *     Handler)} to create publish or subscribe Aware discovery sessions. Events are called on the
98  *     provided callback object {@link DiscoverySessionCallback}. Specifically, the
99  *     {@link DiscoverySessionCallback#onPublishStarted(PublishDiscoverySession)}
100  *     and
101  *     {@link DiscoverySessionCallback#onSubscribeStarted(
102  *SubscribeDiscoverySession)}
103  *     return {@link PublishDiscoverySession} and
104  *     {@link SubscribeDiscoverySession}
105  *     objects respectively on which additional session operations can be performed, e.g. updating
106  *     the session {@link PublishDiscoverySession#updatePublish(PublishConfig)} and
107  *     {@link SubscribeDiscoverySession#updateSubscribe(SubscribeConfig)}. Sessions can
108  *     also be used to send messages using the
109  *     {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} APIs. When an
110  *     application is finished with a discovery session it <b>must</b> terminate it using the
111  *     {@link DiscoverySession#close()} API.
112  * <p>
113  *    Creating connections between Aware devices is managed by the standard
114  *    {@link ConnectivityManager#requestNetwork(NetworkRequest,
115  *    ConnectivityManager.NetworkCallback)}.
116  *    The {@link NetworkRequest} object should be constructed with:
117  *    <ul>
118  *        <li>{@link NetworkRequest.Builder#addTransportType(int)} of
119  *        {@link android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE}.
120  *        <li>{@link NetworkRequest.Builder#setNetworkSpecifier(String)} using
121  *        {@link WifiAwareNetworkSpecifier.Builder}.
122  *    </ul>
123  */
124 @SystemService(Context.WIFI_AWARE_SERVICE)
125 public class WifiAwareManager {
126     private static final String TAG = "WifiAwareManager";
127     private static final boolean DBG = false;
128     private static final boolean VDBG = false; // STOPSHIP if true
129 
130     /**
131      * Broadcast intent action to indicate that the state of Wi-Fi Aware availability has changed
132      * and all active Aware sessions are no longer usable. Use the {@link #isAvailable()} to query
133      * the current status.
134      * This broadcast is <b>not</b> sticky, use the {@link #isAvailable()} API after registering
135      * the broadcast to check the current state of Wi-Fi Aware.
136      * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
137      * components will be launched.
138      */
139     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
140     public static final String ACTION_WIFI_AWARE_STATE_CHANGED =
141             "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED";
142     /**
143      * Intent broadcast sent whenever Wi-Fi Aware resource availability has changed. The resources
144      * are attached with the {@link #EXTRA_AWARE_RESOURCES} extra. The resources can also be
145      * obtained using the {@link #getAvailableAwareResources()} method. To receive this broadcast,
146      * apps must hold {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
147      * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
148      * components will be launched.
149      */
150     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
151     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
152     @RequiresPermission(ACCESS_WIFI_STATE)
153     public static final String ACTION_WIFI_AWARE_RESOURCE_CHANGED =
154             "android.net.wifi.aware.action.WIFI_AWARE_RESOURCE_CHANGED";
155 
156     /**
157      * Sent as a part of {@link #ACTION_WIFI_AWARE_RESOURCE_CHANGED} that contains an instance of
158      * {@link AwareResources} representing the current Wi-Fi Aware resources.
159      */
160     public static final String EXTRA_AWARE_RESOURCES =
161             "android.net.wifi.aware.extra.AWARE_RESOURCES";
162 
163     /** @hide */
164     @IntDef({
165             WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, WIFI_AWARE_DATA_PATH_ROLE_RESPONDER})
166     @Retention(RetentionPolicy.SOURCE)
167     public @interface DataPathRole {
168     }
169 
170     /**
171      * Connection creation role is that of INITIATOR. Used to create a network specifier string
172      * when requesting a Aware network.
173      *
174      * @see WifiAwareSession#createNetworkSpecifierOpen(int, byte[])
175      * @see WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)
176      */
177     public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0;
178 
179     /**
180      * Connection creation role is that of RESPONDER. Used to create a network specifier string
181      * when requesting a Aware network.
182      *
183      * @see WifiAwareSession#createNetworkSpecifierOpen(int, byte[])
184      * @see WifiAwareSession#createNetworkSpecifierPassphrase(int, byte[], String)
185      */
186     public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1;
187 
188     /** @hide */
189     @IntDef({
190             WIFI_AWARE_DISCOVERY_LOST_REASON_UNKNOWN,
191             WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE})
192     @Retention(RetentionPolicy.SOURCE)
193     public @interface DiscoveryLostReasonCode {
194     }
195 
196     /**
197      * Reason code provided in {@link DiscoverySessionCallback#onServiceLost(PeerHandle, int)}
198      * indicating that the service was lost for unknown reason.
199      */
200     public static final int WIFI_AWARE_DISCOVERY_LOST_REASON_UNKNOWN = 0;
201 
202     /**
203      * Reason code provided in {@link DiscoverySessionCallback#onServiceLost(PeerHandle, int)}
204      * indicating that the service advertised by the peer is no longer visible. This may be because
205      * the peer is out of range or because the peer stopped advertising this service.
206      */
207     public static final int WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE = 1;
208 
209     private final Context mContext;
210     private final IWifiAwareManager mService;
211 
212     private final Object mLock = new Object(); // lock access to the following vars
213 
214     /** @hide */
WifiAwareManager(@onNull Context context, @NonNull IWifiAwareManager service)215     public WifiAwareManager(@NonNull Context context, @NonNull IWifiAwareManager service) {
216         mContext = context;
217         mService = service;
218     }
219 
220     /**
221      * Returns the current status of Aware API: whether or not Aware is available. To track
222      * changes in the state of Aware API register for the
223      * {@link #ACTION_WIFI_AWARE_STATE_CHANGED} broadcast.
224      *
225      * @return A boolean indicating whether the app can use the Aware API at this time (true) or
226      * not (false).
227      */
228     @RequiresPermission(ACCESS_WIFI_STATE)
isAvailable()229     public boolean isAvailable() {
230         try {
231             return mService.isUsageEnabled();
232         } catch (RemoteException e) {
233             throw e.rethrowFromSystemServer();
234         }
235     }
236 
237     /**
238      * Return the current status of the Aware service: whether or not the device is already attached
239      * to an Aware cluster. To attach to an Aware cluster, please use
240      * {@link #attach(AttachCallback, Handler)} or
241      * {@link #attach(AttachCallback, IdentityChangedListener, Handler)}.
242      * @return A boolean indicating whether the device is attached to a cluster at this time (true)
243      *         or not (false).
244      */
245     @RequiresPermission(ACCESS_WIFI_STATE)
isDeviceAttached()246     public boolean isDeviceAttached() {
247         try {
248             return mService.isDeviceAttached();
249         } catch (RemoteException e) {
250             throw e.rethrowFromSystemServer();
251         }
252     }
253 
254     /**
255      * Return the device support for setting a channel requirement in a data-path request. If true
256      * the channel set by
257      * {@link WifiAwareNetworkSpecifier.Builder#setChannelFrequencyMhz(int, boolean)} will be
258      * honored, otherwise it will be ignored.
259      * @return True is the device support set channel on data-path request, false otherwise.
260      */
261     @RequiresPermission(ACCESS_WIFI_STATE)
isSetChannelOnDataPathSupported()262     public boolean isSetChannelOnDataPathSupported() {
263         try {
264             return mService.isSetChannelOnDataPathSupported();
265         } catch (RemoteException e) {
266             throw e.rethrowFromSystemServer();
267         }
268     }
269 
270     /**
271      * Enable the Wifi Aware Instant communication mode. If the device doesn't support this feature
272      * calling this API will result no action.
273      * <p>
274      * Note: before {@link android.os.Build.VERSION_CODES#TIRAMISU}, only system app can use this
275      * API. Start with {@link android.os.Build.VERSION_CODES#TIRAMISU} apps hold
276      * {@link android.Manifest.permission#OVERRIDE_WIFI_CONFIG} are allowed to use it.
277      *
278      * @see Characteristics#isInstantCommunicationModeSupported()
279      * @param enable true for enable, false otherwise.
280      * @hide
281      */
282     @SystemApi
283     @RequiresApi(Build.VERSION_CODES.S)
284     @RequiresPermission(allOf = {CHANGE_WIFI_STATE, OVERRIDE_WIFI_CONFIG})
enableInstantCommunicationMode(boolean enable)285     public void enableInstantCommunicationMode(boolean enable) {
286         if (!SdkLevel.isAtLeastS()) {
287             throw new UnsupportedOperationException();
288         }
289         try {
290             mService.enableInstantCommunicationMode(mContext.getOpPackageName(), enable);
291         } catch (RemoteException e) {
292             throw e.rethrowFromSystemServer();
293         }
294     }
295 
296     /**
297      * Return the current status of the Wifi Aware instant communication mode.
298      * If the device doesn't support this feature, return will always be false.
299      * @see Characteristics#isInstantCommunicationModeSupported()
300      * @return true if it is enabled, false otherwise.
301      */
302     @RequiresApi(Build.VERSION_CODES.S)
303     @RequiresPermission(ACCESS_WIFI_STATE)
isInstantCommunicationModeEnabled()304     public boolean isInstantCommunicationModeEnabled() {
305         if (!SdkLevel.isAtLeastS()) {
306             throw new UnsupportedOperationException();
307         }
308         try {
309             return mService.isInstantCommunicationModeEnabled();
310         } catch (RemoteException e) {
311             throw e.rethrowFromSystemServer();
312         }
313     }
314 
315     /**
316      * Returns the characteristics of the Wi-Fi Aware interface: a set of parameters which specify
317      * limitations on configurations, e.g. the maximum service name length.
318      * <p>
319      * May return {@code null} if the Wi-Fi Aware service is not initialized. Use
320      * {@link #attach(AttachCallback, Handler)} or
321      * {@link #attach(AttachCallback, IdentityChangedListener, Handler)} to initialize the Wi-Fi
322      * Aware service.
323      *
324      * @return An object specifying configuration limitations of Aware.
325      */
326     @RequiresPermission(ACCESS_WIFI_STATE)
getCharacteristics()327     public @Nullable Characteristics getCharacteristics() {
328         try {
329             return mService.getCharacteristics();
330         } catch (RemoteException e) {
331             throw e.rethrowFromSystemServer();
332         }
333     }
334 
335     /**
336      * Return the available resources of the Wi-Fi aware service: a set of parameters which specify
337      * limitations on service usage, e.g the number of data-paths which could be created.
338      * <p>
339      * May return {@code null} if the Wi-Fi Aware service is not initialized. Use
340      * {@link #attach(AttachCallback, Handler)} or
341      * {@link #attach(AttachCallback, IdentityChangedListener, Handler)} to initialize the Wi-Fi
342      * Aware service.
343      *
344      * @return An object specifying the currently available resource of the Wi-Fi Aware service.
345      */
346     @RequiresPermission(ACCESS_WIFI_STATE)
getAvailableAwareResources()347     public @Nullable AwareResources getAvailableAwareResources() {
348         try {
349             return mService.getAvailableAwareResources();
350         } catch (RemoteException e) {
351             throw e.rethrowFromSystemServer();
352         }
353     }
354 
355     /**
356      * Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
357      * create connections to peers. The device will attach to an existing cluster if it can find
358      * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
359      * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
360      * An application <b>must</b> call {@link WifiAwareSession#close()} when done with the
361      * Wi-Fi Aware object.
362      * <p>
363      * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster
364      * then this function will simply indicate success immediately using the same {@code
365      * attachCallback}.
366      *
367      * @param attachCallback A callback for attach events, extended from
368      * {@link AttachCallback}.
369      * @param handler The Handler on whose thread to execute the callbacks of the {@code
370      * attachCallback} object. If a null is provided then the application's main thread will be
371      *                used.
372      */
373     @RequiresPermission(allOf = {
374             ACCESS_WIFI_STATE,
375             CHANGE_WIFI_STATE
376     })
attach(@onNull AttachCallback attachCallback, @Nullable Handler handler)377     public void attach(@NonNull AttachCallback attachCallback, @Nullable Handler handler) {
378         attach(handler, null, attachCallback, null);
379     }
380 
381     /**
382      * Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
383      * create connections to peers. The device will attach to an existing cluster if it can find
384      * one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
385      * (e.g. successful attach to a cluster) are provided to the {@code attachCallback} object.
386      * An application <b>must</b> call {@link WifiAwareSession#close()} when done with the
387      * Wi-Fi Aware object.
388      * <p>
389      * Note: a Aware cluster is a shared resource - if the device is already attached to a cluster
390      * then this function will simply indicate success immediately using the same {@code
391      * attachCallback}.
392      * <p>
393      * This version of the API attaches a listener to receive the MAC address of the Aware interface
394      * on startup and whenever it is updated (it is randomized at regular intervals for privacy).
395      *
396      * If targeting {@link android.os.Build.VERSION_CODES#TIRAMISU} or later, the application must
397      * have {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} with
398      * android:usesPermissionFlags="neverForLocation". If the application does not declare
399      * android:usesPermissionFlags="neverForLocation", then it must also have
400      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
401      *
402      * If targeting an earlier release than {@link android.os.Build.VERSION_CODES#TIRAMISU}, the
403      * application must have {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
404      *
405      * Apps without {@link android.Manifest.permission#NEARBY_WIFI_DEVICES} or
406      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} can use the
407      * {@link #attach(AttachCallback, Handler)} version.
408      * Note that aside from permission requirements the {@link IdentityChangedListener} will wake up
409      * the host at regular intervals causing higher power consumption, do not use it unless the
410      * information is necessary (e.g. for out-of-band discovery).
411      *
412      * @param attachCallback A callback for attach events, extended from
413      * {@link AttachCallback}.
414      * @param identityChangedListener A listener for changed identity, extended from
415      * {@link IdentityChangedListener}.
416      * @param handler The Handler on whose thread to execute the callbacks of the {@code
417      * attachCallback} and {@code identityChangedListener} objects. If a null is provided then the
418      *                application's main thread will be used.
419      */
420     @RequiresPermission(allOf = {
421             ACCESS_WIFI_STATE,
422             CHANGE_WIFI_STATE,
423             ACCESS_FINE_LOCATION,
424             NEARBY_WIFI_DEVICES}, conditional = true)
attach(@onNull AttachCallback attachCallback, @NonNull IdentityChangedListener identityChangedListener, @Nullable Handler handler)425     public void attach(@NonNull AttachCallback attachCallback,
426             @NonNull IdentityChangedListener identityChangedListener,
427             @Nullable Handler handler) {
428         attach(handler, null, attachCallback, identityChangedListener);
429     }
430 
431     /** @hide */
attach(Handler handler, ConfigRequest configRequest, AttachCallback attachCallback, IdentityChangedListener identityChangedListener)432     public void attach(Handler handler, ConfigRequest configRequest,
433             AttachCallback attachCallback,
434             IdentityChangedListener identityChangedListener) {
435         if (VDBG) {
436             Log.v(TAG, "attach(): handler=" + handler + ", callback=" + attachCallback
437                     + ", configRequest=" + configRequest + ", identityChangedListener="
438                     + identityChangedListener);
439         }
440 
441         if (attachCallback == null) {
442             throw new IllegalArgumentException("Null callback provided");
443         }
444 
445         synchronized (mLock) {
446             Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper();
447 
448             try {
449                 Binder binder = new Binder();
450                 Bundle extras = new Bundle();
451                 if (SdkLevel.isAtLeastS()) {
452                     extras.putParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
453                             mContext.getAttributionSource());
454                 }
455                 mService.connect(binder, mContext.getOpPackageName(), mContext.getAttributionTag(),
456                         new WifiAwareEventCallbackProxy(this, looper, binder, attachCallback,
457                                 identityChangedListener), configRequest,
458                         identityChangedListener != null, extras);
459             } catch (RemoteException e) {
460                 throw e.rethrowFromSystemServer();
461             }
462         }
463     }
464 
465     /** @hide */
disconnect(int clientId, Binder binder)466     public void disconnect(int clientId, Binder binder) {
467         if (VDBG) Log.v(TAG, "disconnect()");
468 
469         try {
470             mService.disconnect(clientId, binder);
471         } catch (RemoteException e) {
472             throw e.rethrowFromSystemServer();
473         }
474     }
475 
476     /** @hide */
publish(int clientId, Looper looper, PublishConfig publishConfig, DiscoverySessionCallback callback)477     public void publish(int clientId, Looper looper, PublishConfig publishConfig,
478             DiscoverySessionCallback callback) {
479         if (VDBG) Log.v(TAG, "publish(): clientId=" + clientId + ", config=" + publishConfig);
480 
481         if (callback == null) {
482             throw new IllegalArgumentException("Null callback provided");
483         }
484 
485         try {
486             Bundle extras = new Bundle();
487             if (SdkLevel.isAtLeastS()) {
488                 extras.putParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
489                         mContext.getAttributionSource());
490             }
491             mService.publish(mContext.getOpPackageName(), mContext.getAttributionTag(), clientId,
492                     publishConfig,
493                     new WifiAwareDiscoverySessionCallbackProxy(this, looper, true, callback,
494                             clientId), extras);
495         } catch (RemoteException e) {
496             throw e.rethrowFromSystemServer();
497         }
498     }
499 
500     /** @hide */
updatePublish(int clientId, int sessionId, PublishConfig publishConfig)501     public void updatePublish(int clientId, int sessionId, PublishConfig publishConfig) {
502         if (VDBG) {
503             Log.v(TAG, "updatePublish(): clientId=" + clientId + ",sessionId=" + sessionId
504                     + ", config=" + publishConfig);
505         }
506 
507         try {
508             mService.updatePublish(clientId, sessionId, publishConfig);
509         } catch (RemoteException e) {
510             throw e.rethrowFromSystemServer();
511         }
512     }
513 
514     /** @hide */
subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig, DiscoverySessionCallback callback)515     public void subscribe(int clientId, Looper looper, SubscribeConfig subscribeConfig,
516             DiscoverySessionCallback callback) {
517         if (VDBG) {
518             if (VDBG) {
519                 Log.v(TAG,
520                         "subscribe(): clientId=" + clientId + ", config=" + subscribeConfig);
521             }
522         }
523 
524         if (callback == null) {
525             throw new IllegalArgumentException("Null callback provided");
526         }
527 
528         try {
529             Bundle extras = new Bundle();
530             if (SdkLevel.isAtLeastS()) {
531                 extras.putParcelable(WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE,
532                         mContext.getAttributionSource());
533             }
534             mService.subscribe(mContext.getOpPackageName(), mContext.getAttributionTag(), clientId,
535                     subscribeConfig,
536                     new WifiAwareDiscoverySessionCallbackProxy(this, looper, false, callback,
537                             clientId), extras);
538         } catch (RemoteException e) {
539             throw e.rethrowFromSystemServer();
540         }
541     }
542 
543     /** @hide */
updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig)544     public void updateSubscribe(int clientId, int sessionId, SubscribeConfig subscribeConfig) {
545         if (VDBG) {
546             Log.v(TAG, "updateSubscribe(): clientId=" + clientId + ",sessionId=" + sessionId
547                     + ", config=" + subscribeConfig);
548         }
549 
550         try {
551             mService.updateSubscribe(clientId, sessionId, subscribeConfig);
552         } catch (RemoteException e) {
553             throw e.rethrowFromSystemServer();
554         }
555     }
556 
557     /** @hide */
terminateSession(int clientId, int sessionId)558     public void terminateSession(int clientId, int sessionId) {
559         if (VDBG) {
560             Log.d(TAG,
561                     "terminateSession(): clientId=" + clientId + ", sessionId=" + sessionId);
562         }
563 
564         try {
565             mService.terminateSession(clientId, sessionId);
566         } catch (RemoteException e) {
567             throw e.rethrowFromSystemServer();
568         }
569     }
570 
571     /** @hide */
sendMessage(int clientId, int sessionId, PeerHandle peerHandle, byte[] message, int messageId, int retryCount)572     public void sendMessage(int clientId, int sessionId, PeerHandle peerHandle, byte[] message,
573             int messageId, int retryCount) {
574         if (peerHandle == null) {
575             throw new IllegalArgumentException(
576                     "sendMessage: invalid peerHandle - must be non-null");
577         }
578 
579         if (VDBG) {
580             Log.v(TAG, "sendMessage(): clientId=" + clientId + ", sessionId=" + sessionId
581                     + ", peerHandle=" + peerHandle.peerId + ", messageId="
582                     + messageId + ", retryCount=" + retryCount);
583         }
584 
585         try {
586             mService.sendMessage(clientId, sessionId, peerHandle.peerId, message, messageId,
587                     retryCount);
588         } catch (RemoteException e) {
589             throw e.rethrowFromSystemServer();
590         }
591     }
592 
593     /** @hide */
594     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
requestMacAddresses(int uid, int[] peerIds, IWifiAwareMacAddressProvider callback)595     public void requestMacAddresses(int uid, int[] peerIds,
596             IWifiAwareMacAddressProvider callback) {
597         try {
598             mService.requestMacAddresses(uid, peerIds, callback);
599         } catch (RemoteException e) {
600             throw e.rethrowFromSystemServer();
601         }
602     }
603 
604     /** @hide */
createNetworkSpecifier(int clientId, int role, int sessionId, @NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase)605     public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
606             @NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
607         if (VDBG) {
608             Log.v(TAG, "createNetworkSpecifier: role=" + role + ", sessionId=" + sessionId
609                     + ", peerHandle=" + ((peerHandle == null) ? peerHandle : peerHandle.peerId)
610                     + ", pmk=" + ((pmk == null) ? "null" : "non-null")
611                     + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
612         }
613 
614         if (!WifiAwareUtils.isLegacyVersion(mContext, Build.VERSION_CODES.Q)) {
615             throw new UnsupportedOperationException(
616                     "API deprecated - use WifiAwareNetworkSpecifier.Builder");
617         }
618 
619         if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
620                 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
621             throw new IllegalArgumentException(
622                     "createNetworkSpecifier: Invalid 'role' argument when creating a network "
623                             + "specifier");
624         }
625         if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR || !WifiAwareUtils.isLegacyVersion(mContext,
626                 Build.VERSION_CODES.P)) {
627             if (peerHandle == null) {
628                 throw new IllegalArgumentException(
629                         "createNetworkSpecifier: Invalid peer handle - cannot be null");
630             }
631         }
632 
633         return new WifiAwareNetworkSpecifier(
634                 (peerHandle == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB_ANY_PEER
635                         : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_IB,
636                 role,
637                 clientId,
638                 sessionId,
639                 peerHandle != null ? peerHandle.peerId : 0, // 0 is an invalid peer ID
640                 null, // peerMac (not used in this method)
641                 pmk,
642                 passphrase,
643                 0, // no port info for deprecated IB APIs
644                 -1); // no transport info for deprecated IB APIs
645     }
646 
647     /** @hide */
createNetworkSpecifier(int clientId, @DataPathRole int role, @NonNull byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase)648     public NetworkSpecifier createNetworkSpecifier(int clientId, @DataPathRole int role,
649             @NonNull byte[] peer, @Nullable byte[] pmk, @Nullable String passphrase) {
650         if (VDBG) {
651             Log.v(TAG, "createNetworkSpecifier: role=" + role
652                     + ", pmk=" + ((pmk == null) ? "null" : "non-null")
653                     + ", passphrase=" + ((passphrase == null) ? "null" : "non-null"));
654         }
655 
656         if (role != WIFI_AWARE_DATA_PATH_ROLE_INITIATOR
657                 && role != WIFI_AWARE_DATA_PATH_ROLE_RESPONDER) {
658             throw new IllegalArgumentException(
659                     "createNetworkSpecifier: Invalid 'role' argument when creating a network "
660                             + "specifier");
661         }
662         if (role == WIFI_AWARE_DATA_PATH_ROLE_INITIATOR || !WifiAwareUtils.isLegacyVersion(mContext,
663                 Build.VERSION_CODES.P)) {
664             if (peer == null) {
665                 throw new IllegalArgumentException(
666                         "createNetworkSpecifier: Invalid peer MAC - cannot be null");
667             }
668         }
669         if (peer != null && peer.length != 6) {
670             throw new IllegalArgumentException("createNetworkSpecifier: Invalid peer MAC address");
671         }
672 
673         return new WifiAwareNetworkSpecifier(
674                 (peer == null) ? WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB_ANY_PEER
675                         : WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
676                 role,
677                 clientId,
678                 0, // 0 is an invalid session ID
679                 0, // 0 is an invalid peer ID
680                 peer,
681                 pmk,
682                 passphrase,
683                 0, // no port info for OOB APIs
684                 -1); // no transport protocol info for OOB APIs
685     }
686 
687     private static class WifiAwareEventCallbackProxy extends IWifiAwareEventCallback.Stub {
688         private static final int CALLBACK_CONNECT_SUCCESS = 0;
689         private static final int CALLBACK_CONNECT_FAIL = 1;
690         private static final int CALLBACK_IDENTITY_CHANGED = 2;
691         private static final int CALLBACK_ATTACH_TERMINATE = 3;
692 
693         private final Handler mHandler;
694         private final WeakReference<WifiAwareManager> mAwareManager;
695         private final Binder mBinder;
696         private final Looper mLooper;
697 
698         /**
699          * Constructs a {@link AttachCallback} using the specified looper.
700          * All callbacks will delivered on the thread of the specified looper.
701          *
702          * @param looper The looper on which to execute the callbacks.
703          */
WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder, final AttachCallback attachCallback, final IdentityChangedListener identityChangedListener)704         WifiAwareEventCallbackProxy(WifiAwareManager mgr, Looper looper, Binder binder,
705                 final AttachCallback attachCallback,
706                 final IdentityChangedListener identityChangedListener) {
707             mAwareManager = new WeakReference<>(mgr);
708             mLooper = looper;
709             mBinder = binder;
710 
711             if (VDBG) Log.v(TAG, "WifiAwareEventCallbackProxy ctor: looper=" + looper);
712             mHandler = new Handler(looper) {
713                 @Override
714                 public void handleMessage(Message msg) {
715                     if (DBG) {
716                         Log.d(TAG, "WifiAwareEventCallbackProxy: What=" + msg.what + ", msg="
717                                 + msg);
718                     }
719 
720                     WifiAwareManager mgr = mAwareManager.get();
721                     if (mgr == null) {
722                         Log.w(TAG, "WifiAwareEventCallbackProxy: handleMessage post GC");
723                         return;
724                     }
725 
726                     switch (msg.what) {
727                         case CALLBACK_CONNECT_SUCCESS:
728                             attachCallback.onAttached(
729                                     new WifiAwareSession(mgr, mBinder, msg.arg1));
730                             break;
731                         case CALLBACK_CONNECT_FAIL:
732                             mAwareManager.clear();
733                             attachCallback.onAttachFailed();
734                             break;
735                         case CALLBACK_IDENTITY_CHANGED:
736                             if (identityChangedListener == null) {
737                                 Log.e(TAG, "CALLBACK_IDENTITY_CHANGED: null listener.");
738                             } else {
739                                 identityChangedListener.onIdentityChanged((byte[]) msg.obj);
740                             }
741                             break;
742                         case CALLBACK_ATTACH_TERMINATE:
743                             mAwareManager.clear();
744                             attachCallback.onAwareSessionTerminated();
745                     }
746                 }
747             };
748         }
749 
750         @Override
onConnectSuccess(int clientId)751         public void onConnectSuccess(int clientId) {
752             if (VDBG) Log.v(TAG, "onConnectSuccess");
753 
754             Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_SUCCESS);
755             msg.arg1 = clientId;
756             mHandler.sendMessage(msg);
757         }
758 
759         @Override
onConnectFail(int reason)760         public void onConnectFail(int reason) {
761             if (VDBG) Log.v(TAG, "onConnectFail: reason=" + reason);
762 
763             Message msg = mHandler.obtainMessage(CALLBACK_CONNECT_FAIL);
764             msg.arg1 = reason;
765             mHandler.sendMessage(msg);
766         }
767 
768         @Override
onIdentityChanged(byte[] mac)769         public void onIdentityChanged(byte[] mac) {
770             if (VDBG) Log.v(TAG, "onIdentityChanged: mac=" + new String(HexEncoding.encode(mac)));
771 
772             Message msg = mHandler.obtainMessage(CALLBACK_IDENTITY_CHANGED);
773             msg.obj = mac;
774             mHandler.sendMessage(msg);
775         }
776 
777         @Override
onAttachTerminate()778         public void onAttachTerminate() {
779             if (VDBG) Log.v(TAG, "onAwareSessionTerminated");
780 
781             Message msg = mHandler.obtainMessage(CALLBACK_ATTACH_TERMINATE);
782             mHandler.sendMessage(msg);
783         }
784     }
785 
786     private static class WifiAwareDiscoverySessionCallbackProxy extends
787             IWifiAwareDiscoverySessionCallback.Stub {
788         private static final int CALLBACK_SESSION_STARTED = 0;
789         private static final int CALLBACK_SESSION_CONFIG_SUCCESS = 1;
790         private static final int CALLBACK_SESSION_CONFIG_FAIL = 2;
791         private static final int CALLBACK_SESSION_TERMINATED = 3;
792         private static final int CALLBACK_MATCH = 4;
793         private static final int CALLBACK_MESSAGE_SEND_SUCCESS = 5;
794         private static final int CALLBACK_MESSAGE_SEND_FAIL = 6;
795         private static final int CALLBACK_MESSAGE_RECEIVED = 7;
796         private static final int CALLBACK_MATCH_WITH_DISTANCE = 8;
797         private static final int CALLBACK_MATCH_EXPIRED = 9;
798 
799         private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message";
800         private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2";
801         private static final String MESSAGE_BUNDLE_KEY_CIPHER_SUITE = "key_cipher_suite";
802         private static final String MESSAGE_BUNDLE_KEY_SCID = "key_scid";
803 
804         private final WeakReference<WifiAwareManager> mAwareManager;
805         private final boolean mIsPublish;
806         private final DiscoverySessionCallback mOriginalCallback;
807         private final int mClientId;
808 
809         private final Handler mHandler;
810         private DiscoverySession mSession;
811 
WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper, boolean isPublish, DiscoverySessionCallback originalCallback, int clientId)812         WifiAwareDiscoverySessionCallbackProxy(WifiAwareManager mgr, Looper looper,
813                 boolean isPublish, DiscoverySessionCallback originalCallback,
814                 int clientId) {
815             mAwareManager = new WeakReference<>(mgr);
816             mIsPublish = isPublish;
817             mOriginalCallback = originalCallback;
818             mClientId = clientId;
819 
820             if (VDBG) {
821                 Log.v(TAG, "WifiAwareDiscoverySessionCallbackProxy ctor: isPublish=" + isPublish);
822             }
823 
824             mHandler = new Handler(looper) {
825                 @Override
826                 public void handleMessage(Message msg) {
827                     if (DBG) Log.d(TAG, "What=" + msg.what + ", msg=" + msg);
828 
829                     if (mAwareManager.get() == null) {
830                         Log.w(TAG, "WifiAwareDiscoverySessionCallbackProxy: handleMessage post GC");
831                         return;
832                     }
833 
834                     switch (msg.what) {
835                         case CALLBACK_SESSION_STARTED:
836                             onProxySessionStarted(msg.arg1);
837                             break;
838                         case CALLBACK_SESSION_CONFIG_SUCCESS:
839                             mOriginalCallback.onSessionConfigUpdated();
840                             break;
841                         case CALLBACK_SESSION_CONFIG_FAIL:
842                             mOriginalCallback.onSessionConfigFailed();
843                             if (mSession == null) {
844                                 /*
845                                  * creation failed (as opposed to update
846                                  * failing)
847                                  */
848                                 mAwareManager.clear();
849                             }
850                             break;
851                         case CALLBACK_SESSION_TERMINATED:
852                             onProxySessionTerminated(msg.arg1);
853                             break;
854                         case CALLBACK_MATCH:
855                         case CALLBACK_MATCH_WITH_DISTANCE:
856                             List<byte[]> matchFilter = null;
857                             Bundle data = msg.getData();
858                             byte[] arg = data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2);
859                             try {
860                                 matchFilter = new TlvBufferUtils.TlvIterable(0, 1, arg).toList();
861                             } catch (BufferOverflowException e) {
862                                 matchFilter = Collections.emptyList();
863                                 Log.e(TAG, "onServiceDiscovered: invalid match filter byte array '"
864                                         + new String(HexEncoding.encode(arg))
865                                         + "' - cannot be parsed: e=" + e);
866                             }
867                             if (msg.what == CALLBACK_MATCH) {
868                                 mOriginalCallback.onServiceDiscovered(new PeerHandle(msg.arg1),
869                                         data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
870                                         matchFilter);
871                                 mOriginalCallback.onServiceDiscovered(
872                                         new ServiceDiscoveryInfo(
873                                                 new PeerHandle(msg.arg1),
874                                                 data.getInt(MESSAGE_BUNDLE_KEY_CIPHER_SUITE),
875                                                 data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
876                                                 matchFilter,
877                                                 data.getByteArray(MESSAGE_BUNDLE_KEY_SCID)));
878 
879                             } else {
880                                 mOriginalCallback.onServiceDiscoveredWithinRange(
881                                         new PeerHandle(msg.arg1),
882                                         msg.getData().getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
883                                         matchFilter, msg.arg2);
884                                 mOriginalCallback.onServiceDiscoveredWithinRange(
885                                         new ServiceDiscoveryInfo(
886                                                 new PeerHandle(msg.arg1),
887                                                 data.getInt(MESSAGE_BUNDLE_KEY_CIPHER_SUITE),
888                                                 data.getByteArray(MESSAGE_BUNDLE_KEY_MESSAGE),
889                                                 matchFilter,
890                                                 data.getByteArray(MESSAGE_BUNDLE_KEY_SCID)),
891                                         msg.arg2);
892                             }
893                             break;
894                         case CALLBACK_MESSAGE_SEND_SUCCESS:
895                             mOriginalCallback.onMessageSendSucceeded(msg.arg1);
896                             break;
897                         case CALLBACK_MESSAGE_SEND_FAIL:
898                             mOriginalCallback.onMessageSendFailed(msg.arg1);
899                             break;
900                         case CALLBACK_MESSAGE_RECEIVED:
901                             mOriginalCallback.onMessageReceived(new PeerHandle(msg.arg1),
902                                     (byte[]) msg.obj);
903                             break;
904                         case CALLBACK_MATCH_EXPIRED:
905                             mOriginalCallback
906                                     .onServiceLost(new PeerHandle(msg.arg1),
907                                             WIFI_AWARE_DISCOVERY_LOST_REASON_PEER_NOT_VISIBLE);
908                             break;
909                     }
910                 }
911             };
912         }
913 
914         @Override
onSessionStarted(int sessionId)915         public void onSessionStarted(int sessionId) {
916             if (VDBG) Log.v(TAG, "onSessionStarted: sessionId=" + sessionId);
917 
918             Message msg = mHandler.obtainMessage(CALLBACK_SESSION_STARTED);
919             msg.arg1 = sessionId;
920             mHandler.sendMessage(msg);
921         }
922 
923         @Override
onSessionConfigSuccess()924         public void onSessionConfigSuccess() {
925             if (VDBG) Log.v(TAG, "onSessionConfigSuccess");
926 
927             Message msg = mHandler.obtainMessage(CALLBACK_SESSION_CONFIG_SUCCESS);
928             mHandler.sendMessage(msg);
929         }
930 
931         @Override
onSessionConfigFail(int reason)932         public void onSessionConfigFail(int reason) {
933             if (VDBG) Log.v(TAG, "onSessionConfigFail: reason=" + reason);
934 
935             Message msg = mHandler.obtainMessage(CALLBACK_SESSION_CONFIG_FAIL);
936             msg.arg1 = reason;
937             mHandler.sendMessage(msg);
938         }
939 
940         @Override
onSessionTerminated(int reason)941         public void onSessionTerminated(int reason) {
942             if (VDBG) Log.v(TAG, "onSessionTerminated: reason=" + reason);
943 
944             Message msg = mHandler.obtainMessage(CALLBACK_SESSION_TERMINATED);
945             msg.arg1 = reason;
946             mHandler.sendMessage(msg);
947         }
948 
onMatchCommon(int messageType, int peerId, byte[] serviceSpecificInfo, byte[] matchFilter, int distanceMm, int peerCipherSuite, byte[] scid)949         private void onMatchCommon(int messageType, int peerId, byte[] serviceSpecificInfo,
950                 byte[] matchFilter, int distanceMm, int peerCipherSuite, byte[] scid) {
951             Bundle data = new Bundle();
952             data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE, serviceSpecificInfo);
953             data.putByteArray(MESSAGE_BUNDLE_KEY_MESSAGE2, matchFilter);
954             data.putInt(MESSAGE_BUNDLE_KEY_CIPHER_SUITE, peerCipherSuite);
955             data.putByteArray(MESSAGE_BUNDLE_KEY_SCID, scid);
956 
957             Message msg = mHandler.obtainMessage(messageType);
958             msg.arg1 = peerId;
959             msg.arg2 = distanceMm;
960             msg.setData(data);
961             mHandler.sendMessage(msg);
962         }
963 
964         @Override
onMatch(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter, int peerCipherSuite, byte[] scid)965         public void onMatch(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter,
966                 int peerCipherSuite, byte[] scid) {
967             if (VDBG) Log.v(TAG, "onMatch: peerId=" + peerId);
968 
969             onMatchCommon(CALLBACK_MATCH, peerId, serviceSpecificInfo, matchFilter, 0,
970                     peerCipherSuite, scid);
971         }
972 
973         @Override
onMatchWithDistance(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter, int distanceMm, int peerCipherSuite, byte[] scid)974         public void onMatchWithDistance(int peerId, byte[] serviceSpecificInfo, byte[] matchFilter,
975                 int distanceMm, int peerCipherSuite, byte[] scid) {
976             if (VDBG) {
977                 Log.v(TAG, "onMatchWithDistance: peerId=" + peerId + ", distanceMm=" + distanceMm);
978             }
979 
980             onMatchCommon(CALLBACK_MATCH_WITH_DISTANCE, peerId, serviceSpecificInfo, matchFilter,
981                     distanceMm, peerCipherSuite, scid);
982         }
983         @Override
onMatchExpired(int peerId)984         public void onMatchExpired(int peerId) {
985             if (VDBG) {
986                 Log.v(TAG, "onMatchExpired: peerId=" + peerId);
987             }
988             Message msg = mHandler.obtainMessage(CALLBACK_MATCH_EXPIRED);
989             msg.arg1 = peerId;
990             mHandler.sendMessage(msg);
991         }
992 
993         @Override
onMessageSendSuccess(int messageId)994         public void onMessageSendSuccess(int messageId) {
995             if (VDBG) Log.v(TAG, "onMessageSendSuccess");
996 
997             Message msg = mHandler.obtainMessage(CALLBACK_MESSAGE_SEND_SUCCESS);
998             msg.arg1 = messageId;
999             mHandler.sendMessage(msg);
1000         }
1001 
1002         @Override
onMessageSendFail(int messageId, int reason)1003         public void onMessageSendFail(int messageId, int reason) {
1004             if (VDBG) Log.v(TAG, "onMessageSendFail: reason=" + reason);
1005 
1006             Message msg = mHandler.obtainMessage(CALLBACK_MESSAGE_SEND_FAIL);
1007             msg.arg1 = messageId;
1008             msg.arg2 = reason;
1009             mHandler.sendMessage(msg);
1010         }
1011 
1012         @Override
onMessageReceived(int peerId, byte[] message)1013         public void onMessageReceived(int peerId, byte[] message) {
1014             if (VDBG) {
1015                 Log.v(TAG, "onMessageReceived: peerId=" + peerId);
1016             }
1017 
1018             Message msg = mHandler.obtainMessage(CALLBACK_MESSAGE_RECEIVED);
1019             msg.arg1 = peerId;
1020             msg.obj = message;
1021             mHandler.sendMessage(msg);
1022         }
1023 
1024         /*
1025          * Proxied methods
1026          */
onProxySessionStarted(int sessionId)1027         public void onProxySessionStarted(int sessionId) {
1028             if (VDBG) Log.v(TAG, "Proxy: onSessionStarted: sessionId=" + sessionId);
1029             if (mSession != null) {
1030                 Log.e(TAG,
1031                         "onSessionStarted: sessionId=" + sessionId + ": session already created!?");
1032                 throw new IllegalStateException(
1033                         "onSessionStarted: sessionId=" + sessionId + ": session already created!?");
1034             }
1035 
1036             WifiAwareManager mgr = mAwareManager.get();
1037             if (mgr == null) {
1038                 Log.w(TAG, "onProxySessionStarted: mgr GC'd");
1039                 return;
1040             }
1041 
1042             if (mIsPublish) {
1043                 PublishDiscoverySession session = new PublishDiscoverySession(mgr,
1044                         mClientId, sessionId);
1045                 mSession = session;
1046                 mOriginalCallback.onPublishStarted(session);
1047             } else {
1048                 SubscribeDiscoverySession
1049                         session = new SubscribeDiscoverySession(mgr, mClientId, sessionId);
1050                 mSession = session;
1051                 mOriginalCallback.onSubscribeStarted(session);
1052             }
1053         }
1054 
onProxySessionTerminated(int reason)1055         public void onProxySessionTerminated(int reason) {
1056             if (VDBG) Log.v(TAG, "Proxy: onSessionTerminated: reason=" + reason);
1057             if (mSession != null) {
1058                 mSession.setTerminated();
1059                 mSession = null;
1060             } else {
1061                 Log.w(TAG, "Proxy: onSessionTerminated called but mSession is null!?");
1062             }
1063             mAwareManager.clear();
1064             mOriginalCallback.onSessionTerminated();
1065         }
1066     }
1067 
1068     /**
1069      * Set Wi-Fi Aware protocol parameters.
1070      * @hide
1071      * @param params An object contain specified parameters. Use {@code null} to remove previously
1072      *               set configuration and restore default behavior.
1073      */
1074     @SystemApi
1075     @RequiresPermission(allOf = {OVERRIDE_WIFI_CONFIG,
1076             CHANGE_WIFI_STATE})
setAwareParams(@ullable AwareParams params)1077     public void setAwareParams(@Nullable AwareParams params) {
1078         try {
1079             mService.setAwareParams(params);
1080         } catch (RemoteException e) {
1081             throw e.rethrowFromSystemServer();
1082         }
1083     }
1084 }
1085