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