1 /* 2 * Copyright (C) 2012 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.cts; 18 19 import static android.content.Context.RECEIVER_NOT_EXPORTED; 20 import static android.net.wifi.p2p.WifiP2pConfig.GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL; 21 import static android.os.Process.myUid; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertNotEquals; 28 import static org.junit.Assert.assertNotNull; 29 import static org.junit.Assert.assertNull; 30 import static org.junit.Assert.assertTrue; 31 import static org.junit.Assert.fail; 32 import static org.junit.Assume.assumeTrue; 33 34 import android.app.UiAutomation; 35 import android.content.BroadcastReceiver; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.content.pm.PackageManager; 40 import android.net.ConnectivityManager; 41 import android.net.MacAddress; 42 import android.net.Network; 43 import android.net.NetworkCapabilities; 44 import android.net.NetworkInfo; 45 import android.net.NetworkRequest; 46 import android.net.wifi.OuiKeyedData; 47 import android.net.wifi.ScanResult; 48 import android.net.wifi.WifiManager; 49 import android.net.wifi.WpsInfo; 50 import android.net.wifi.p2p.WifiP2pConfig; 51 import android.net.wifi.p2p.WifiP2pDevice; 52 import android.net.wifi.p2p.WifiP2pDeviceList; 53 import android.net.wifi.p2p.WifiP2pDiscoveryConfig; 54 import android.net.wifi.p2p.WifiP2pExtListenParams; 55 import android.net.wifi.p2p.WifiP2pGroup; 56 import android.net.wifi.p2p.WifiP2pGroupList; 57 import android.net.wifi.p2p.WifiP2pInfo; 58 import android.net.wifi.p2p.WifiP2pManager; 59 import android.net.wifi.p2p.WifiP2pManager.ExternalApproverRequestListener; 60 import android.net.wifi.p2p.WifiP2pWfdInfo; 61 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo; 62 import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo; 63 import android.os.Build; 64 import android.os.Handler; 65 import android.os.HandlerExecutor; 66 import android.os.HandlerThread; 67 import android.os.PersistableBundle; 68 import android.os.WorkSource; 69 import android.platform.test.annotations.AppModeFull; 70 import android.platform.test.annotations.RequiresFlagsEnabled; 71 import android.util.Log; 72 73 import androidx.annotation.NonNull; 74 import androidx.annotation.Nullable; 75 import androidx.test.ext.junit.runners.AndroidJUnit4; 76 import androidx.test.filters.SdkSuppress; 77 import androidx.test.platform.app.InstrumentationRegistry; 78 79 import com.android.compatibility.common.util.ApiLevelUtil; 80 import com.android.compatibility.common.util.ApiTest; 81 import com.android.compatibility.common.util.PollingCheck; 82 import com.android.compatibility.common.util.ShellIdentityUtils; 83 import com.android.wifi.flags.Flags; 84 85 import org.junit.After; 86 import org.junit.AfterClass; 87 import org.junit.Before; 88 import org.junit.BeforeClass; 89 import org.junit.Test; 90 import org.junit.runner.RunWith; 91 92 import java.util.ArrayList; 93 import java.util.Arrays; 94 import java.util.BitSet; 95 import java.util.LinkedList; 96 import java.util.List; 97 import java.util.concurrent.CountDownLatch; 98 import java.util.concurrent.Executor; 99 import java.util.concurrent.TimeUnit; 100 import java.util.function.Consumer; 101 import java.util.stream.Collectors; 102 103 @RunWith(AndroidJUnit4.class) 104 @AppModeFull(reason = "Cannot get WifiManager in instant app mode") 105 public class ConcurrencyTest extends WifiJUnit4TestBase { 106 private static Context sContext; 107 private static boolean sShouldRunTest; 108 109 private static class MySync { 110 static final int P2P_STATE = 1; 111 static final int DISCOVERY_STATE = 2; 112 static final int NETWORK_INFO = 3; 113 static final int LISTEN_STATE = 4; 114 115 public BitSet pendingSync = new BitSet(); 116 117 public int expectedP2pState = WifiP2pManager.WIFI_P2P_STATE_DISABLED; 118 public int expectedDiscoveryState; 119 public NetworkInfo expectedNetworkInfo; 120 public int expectedListenState; 121 } 122 123 private static class MyResponse { 124 public boolean valid = false; 125 126 public boolean success; 127 public int failureReason; 128 public int p2pState; 129 public int discoveryState; 130 public int listenState; 131 public NetworkInfo networkInfo; 132 public WifiP2pInfo p2pInfo; 133 public String deviceName; 134 public WifiP2pGroupList persistentGroups; 135 public WifiP2pGroup group = new WifiP2pGroup(); 136 137 // External approver 138 public boolean isAttached; 139 public boolean isDetached; 140 public int detachReason; 141 public MacAddress targetPeer; 142 reset()143 public void reset() { 144 valid = false; 145 146 networkInfo = null; 147 p2pInfo = null; 148 deviceName = null; 149 persistentGroups = null; 150 group = null; 151 152 isAttached = false; 153 isDetached = false; 154 targetPeer = null; 155 } 156 } 157 158 private static WifiManager sWifiManager; 159 private static WifiP2pManager sWifiP2pManager; 160 private static WifiP2pManager.Channel sWifiP2pChannel; 161 private static final MySync MY_SYNC = new MySync(); 162 private static final MyResponse MY_RESPONSE = new MyResponse(); 163 private static boolean sWasVerboseLoggingEnabled; 164 private WifiP2pConfig mTestWifiP2pPeerConfig; 165 private static boolean sWasWifiEnabled; 166 private static boolean sWasScanThrottleEnabled; 167 private final Object mLock = new Object(); 168 169 private static final String TAG = "ConcurrencyTest"; 170 private static final int TIMEOUT_MS = 15000; 171 private static final int WAIT_MS = 100; 172 private static final int DURATION = 5000; 173 private static final int TEST_OUI = 0x00C82ADD; // Google OUI 174 private static final BroadcastReceiver RECEIVER = new BroadcastReceiver() { 175 @Override 176 public void onReceive(Context context, Intent intent) { 177 final String action = intent.getAction(); 178 if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) { 179 synchronized (MY_SYNC) { 180 MY_SYNC.pendingSync.set(MySync.P2P_STATE); 181 MY_SYNC.expectedP2pState = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 182 WifiP2pManager.WIFI_P2P_STATE_DISABLED); 183 Log.d(TAG, "Get WIFI_P2P_STATE_CHANGED_ACTION: " 184 + MY_SYNC.expectedP2pState); 185 MY_SYNC.notify(); 186 } 187 } else if (action.equals(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION)) { 188 synchronized (MY_SYNC) { 189 MY_SYNC.pendingSync.set(MySync.DISCOVERY_STATE); 190 MY_SYNC.expectedDiscoveryState = intent.getIntExtra( 191 WifiP2pManager.EXTRA_DISCOVERY_STATE, 192 WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED); 193 Log.d(TAG, "Get WIFI_P2P_STATE_CHANGED_ACTION: " 194 + MY_SYNC.expectedDiscoveryState); 195 MY_SYNC.notify(); 196 } 197 } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { 198 synchronized (MY_SYNC) { 199 MY_SYNC.pendingSync.set(MySync.NETWORK_INFO); 200 MY_SYNC.expectedNetworkInfo = (NetworkInfo) intent.getExtra( 201 WifiP2pManager.EXTRA_NETWORK_INFO, null); 202 Log.d(TAG, "Get WIFI_P2P_CONNECTION_CHANGED_ACTION: " 203 + MY_SYNC.expectedNetworkInfo); 204 MY_SYNC.notify(); 205 } 206 } else if (action.equals(WifiP2pManager.ACTION_WIFI_P2P_LISTEN_STATE_CHANGED)) { 207 synchronized (MY_SYNC) { 208 MY_SYNC.pendingSync.set(MySync.LISTEN_STATE); 209 MY_SYNC.expectedListenState = intent.getIntExtra( 210 WifiP2pManager.EXTRA_LISTEN_STATE, 211 WifiP2pManager.WIFI_P2P_LISTEN_STOPPED); 212 MY_SYNC.notify(); 213 } 214 } 215 } 216 }; 217 218 private static WifiP2pManager.ActionListener sActionListener = 219 new WifiP2pManager.ActionListener() { 220 @Override 221 public void onSuccess() { 222 synchronized (MY_RESPONSE) { 223 MY_RESPONSE.valid = true; 224 MY_RESPONSE.success = true; 225 MY_RESPONSE.notify(); 226 } 227 } 228 229 @Override 230 public void onFailure(int reason) { 231 synchronized (MY_RESPONSE) { 232 Log.d(TAG, "failure reason: " + reason); 233 MY_RESPONSE.valid = true; 234 MY_RESPONSE.success = false; 235 MY_RESPONSE.failureReason = reason; 236 MY_RESPONSE.notify(); 237 } 238 } 239 }; 240 241 private final HandlerThread mHandlerThread = new HandlerThread("WifiP2pConcurrencyTest"); 242 protected final Executor mExecutor; 243 { mHandlerThread.start()244 mHandlerThread.start(); 245 mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper())); 246 } 247 248 @BeforeClass setUpClass()249 public static void setUpClass() throws Exception { 250 sContext = InstrumentationRegistry.getInstrumentation().getContext(); 251 if (!WifiFeature.isWifiSupported(sContext) 252 && !WifiFeature.isP2pSupported(sContext)) { 253 // skip the test if WiFi && p2p are not supported 254 return; 255 } 256 if (!WifiFeature.isWifiSupported(sContext)) { 257 assertThat(WifiFeature.isP2pSupported(sContext)).isFalse(); 258 } 259 if (!WifiFeature.isP2pSupported(sContext)) { 260 return; 261 } 262 if (!hasLocationFeature()) { 263 Log.d(TAG, "Skipping test as location is not supported"); 264 return; 265 } 266 sShouldRunTest = true; 267 sWifiManager = (WifiManager) sContext.getSystemService(Context.WIFI_SERVICE); 268 assertThat(sWifiManager).isNotNull(); 269 270 // turn on verbose logging for tests 271 sWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions( 272 () -> sWifiManager.isVerboseLoggingEnabled()); 273 ShellIdentityUtils.invokeWithShellPermissions( 274 () -> sWifiManager.setVerboseLoggingEnabled(true)); 275 sWasScanThrottleEnabled = ShellIdentityUtils.invokeWithShellPermissions( 276 () -> sWifiManager.isScanThrottleEnabled()); 277 ShellIdentityUtils.invokeWithShellPermissions( 278 () -> sWifiManager.setScanThrottleEnabled(false)); 279 sWasWifiEnabled = sWifiManager.isWifiEnabled(); 280 281 IntentFilter intentFilter = new IntentFilter(); 282 intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 283 intentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION); 284 intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 285 intentFilter.addAction(WifiP2pManager.ACTION_WIFI_P2P_LISTEN_STATE_CHANGED); 286 intentFilter.setPriority(999); 287 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)) { 288 sContext.registerReceiver(RECEIVER, intentFilter, RECEIVER_NOT_EXPORTED); 289 } else { 290 sContext.registerReceiver(RECEIVER, intentFilter); 291 } 292 if (sWasWifiEnabled) { 293 // Clean the possible P2P enabled broadcast from other test case. 294 waitForBroadcasts(MySync.P2P_STATE); 295 ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false)); 296 PollingCheck.check("Wifi not disabled", DURATION, () -> !sWifiManager.isWifiEnabled()); 297 // Make sure WifiP2P is disabled 298 waitForBroadcasts(MySync.P2P_STATE); 299 assertThat(WifiP2pManager.WIFI_P2P_STATE_DISABLED).isEqualTo(MY_SYNC.expectedP2pState); 300 } 301 synchronized (MY_SYNC) { 302 MY_SYNC.expectedP2pState = WifiP2pManager.WIFI_P2P_STATE_DISABLED; 303 MY_SYNC.expectedDiscoveryState = WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED; 304 MY_SYNC.expectedNetworkInfo = null; 305 MY_SYNC.expectedListenState = WifiP2pManager.WIFI_P2P_LISTEN_STOPPED; 306 MY_SYNC.pendingSync.clear(); 307 resetResponse(MY_RESPONSE); 308 } 309 setupWifiP2p(); 310 } 311 312 @AfterClass tearDownClass()313 public static void tearDownClass() throws Exception { 314 if (!sShouldRunTest) { 315 return; 316 } 317 sContext.unregisterReceiver(RECEIVER); 318 ShellIdentityUtils.invokeWithShellPermissions( 319 () -> sWifiManager.setVerboseLoggingEnabled(sWasVerboseLoggingEnabled)); 320 ShellIdentityUtils.invokeWithShellPermissions( 321 () -> sWifiManager.setScanThrottleEnabled(sWasScanThrottleEnabled)); 322 if (sWasWifiEnabled) { 323 enableWifi(); 324 } 325 } 326 327 328 @Before setUp()329 public void setUp() throws Exception { 330 assumeTrue(sShouldRunTest); 331 332 // Clean all the state 333 synchronized (MY_SYNC) { 334 MY_SYNC.expectedP2pState = WifiP2pManager.WIFI_P2P_STATE_DISABLED; 335 MY_SYNC.expectedDiscoveryState = WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED; 336 MY_SYNC.expectedNetworkInfo = null; 337 MY_SYNC.expectedListenState = WifiP2pManager.WIFI_P2P_LISTEN_STOPPED; 338 MY_SYNC.pendingSync.clear(); 339 resetResponse(MY_RESPONSE); 340 } 341 342 // for general connect command 343 mTestWifiP2pPeerConfig = new WifiP2pConfig(); 344 mTestWifiP2pPeerConfig.deviceAddress = "aa:bb:cc:dd:ee:ff"; 345 } 346 347 @After tearDown()348 public void tearDown() throws Exception { 349 if (!sShouldRunTest) { 350 return; 351 } 352 removeAllPersistentGroups(); 353 resetResponse(MY_RESPONSE); 354 sWifiP2pManager.cancelConnect(sWifiP2pChannel, sActionListener); 355 assertTrue(waitForServiceResponse(MY_RESPONSE)); 356 resetResponse(MY_RESPONSE); 357 sWifiP2pManager.removeGroup(sWifiP2pChannel, sActionListener); 358 assertTrue(waitForServiceResponse(MY_RESPONSE)); 359 } 360 waitForBroadcasts(List<Integer> waitSyncList)361 private static boolean waitForBroadcasts(List<Integer> waitSyncList) { 362 synchronized (MY_SYNC) { 363 long timeout = System.currentTimeMillis() + TIMEOUT_MS; 364 while (System.currentTimeMillis() < timeout) { 365 List<Integer> handledSyncList = waitSyncList.stream() 366 .filter(w -> MY_SYNC.pendingSync.get(w)) 367 .collect(Collectors.toList()); 368 handledSyncList.forEach(w -> MY_SYNC.pendingSync.clear(w)); 369 waitSyncList.removeAll(handledSyncList); 370 if (waitSyncList.isEmpty()) { 371 break; 372 } 373 try { 374 MY_SYNC.wait(WAIT_MS); 375 } catch (InterruptedException e) { } 376 } 377 if (!waitSyncList.isEmpty()) { 378 Log.i(TAG, "Missing broadcast: " + waitSyncList); 379 } 380 return waitSyncList.isEmpty(); 381 } 382 } 383 waitForBroadcasts(int waitSingleSync)384 private static boolean waitForBroadcasts(int waitSingleSync) { 385 return waitForBroadcasts( 386 new LinkedList<Integer>(Arrays.asList(waitSingleSync))); 387 } 388 waitForNextNetworkState()389 private NetworkInfo.DetailedState waitForNextNetworkState() { 390 waitForBroadcasts(MySync.NETWORK_INFO); 391 assertThat(MY_SYNC.expectedNetworkInfo).isNotNull(); 392 return MY_SYNC.expectedNetworkInfo.getDetailedState(); 393 } 394 waitForConnectedNetworkState()395 private boolean waitForConnectedNetworkState() { 396 // The possible orders of network states are: 397 // * IDLE > CONNECTING > CONNECTED for lazy initialization 398 // * DISCONNECTED > CONNECTING > CONNECTED for previous group removal 399 // * CONNECTING > CONNECTED 400 NetworkInfo.DetailedState state = waitForNextNetworkState(); 401 if (state == NetworkInfo.DetailedState.IDLE 402 || state == NetworkInfo.DetailedState.DISCONNECTED) { 403 state = waitForNextNetworkState(); 404 } 405 if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU) 406 && state == NetworkInfo.DetailedState.CONNECTING) { 407 state = waitForNextNetworkState(); 408 } 409 return state == NetworkInfo.DetailedState.CONNECTED; 410 } 411 waitForServiceResponse(MyResponse waitResponse)412 private static boolean waitForServiceResponse(MyResponse waitResponse) { 413 synchronized (waitResponse) { 414 long timeout = System.currentTimeMillis() + TIMEOUT_MS; 415 while (System.currentTimeMillis() < timeout) { 416 try { 417 waitResponse.wait(WAIT_MS); 418 } catch (InterruptedException e) { } 419 420 if (waitResponse.valid) { 421 return true; 422 } 423 } 424 return false; 425 } 426 } 427 428 429 // Returns true if the device has location feature. hasLocationFeature()430 private static boolean hasLocationFeature() { 431 return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION); 432 } 433 resetResponse(MyResponse responseObj)434 private static void resetResponse(MyResponse responseObj) { 435 synchronized (responseObj) { 436 responseObj.reset(); 437 } 438 } 439 440 /* 441 * Enables Wifi and block until connection is established. 442 */ enableWifi()443 private static void enableWifi() throws Exception { 444 if (!sWifiManager.isWifiEnabled()) { 445 ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(true)); 446 PollingCheck.check("Wifi not enabled", DURATION, () -> sWifiManager.isWifiEnabled()); 447 ShellIdentityUtils.invokeWithShellPermissions( 448 () -> sWifiManager.startScan(new WorkSource(myUid()))); 449 ConnectivityManager cm = 450 (ConnectivityManager) sContext.getSystemService(Context.CONNECTIVITY_SERVICE); 451 NetworkRequest request = new NetworkRequest.Builder() 452 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) 453 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 454 .build(); 455 final CountDownLatch latch = new CountDownLatch(1); 456 ConnectivityManager.NetworkCallback networkCallback = 457 new ConnectivityManager.NetworkCallback() { 458 @Override 459 public void onAvailable(Network network) { 460 latch.countDown(); 461 } 462 }; 463 cm.registerNetworkCallback(request, networkCallback); 464 assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 465 cm.unregisterNetworkCallback(networkCallback); 466 Thread.sleep(15_000); 467 } 468 } 469 removeAllPersistentGroups()470 private static void removeAllPersistentGroups() { 471 WifiP2pGroupList persistentGroups = getPersistentGroups(); 472 assertNotNull(persistentGroups); 473 for (WifiP2pGroup group: persistentGroups.getGroupList()) { 474 resetResponse(MY_RESPONSE); 475 ShellIdentityUtils.invokeWithShellPermissions(() -> { 476 sWifiP2pManager.deletePersistentGroup(sWifiP2pChannel, 477 group.getNetworkId(), 478 sActionListener); 479 assertTrue(waitForServiceResponse(MY_RESPONSE)); 480 assertTrue(MY_RESPONSE.success); 481 }); 482 } 483 persistentGroups = getPersistentGroups(); 484 assertNotNull(persistentGroups); 485 assertEquals(0, persistentGroups.getGroupList().size()); 486 } 487 setupWifiP2p()488 private static void setupWifiP2p() { 489 try { 490 enableWifi(); 491 } catch (Exception e) { 492 Log.d(TAG, "Enable Wifi got exception:" + e.getMessage()); 493 } 494 495 assertThat(sWifiManager.isWifiEnabled()).isTrue(); 496 497 sWifiP2pManager = (WifiP2pManager) sContext.getSystemService(Context.WIFI_P2P_SERVICE); 498 sWifiP2pChannel = sWifiP2pManager.initialize( 499 sContext, sContext.getMainLooper(), null); 500 501 assertThat(sWifiP2pManager).isNotNull(); 502 assertThat(sWifiP2pChannel).isNotNull(); 503 504 assertThat(waitForBroadcasts(MySync.P2P_STATE)).isTrue(); 505 506 assertThat(WifiP2pManager.WIFI_P2P_STATE_ENABLED).isEqualTo(MY_SYNC.expectedP2pState); 507 removeAllPersistentGroups(); 508 } 509 510 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#requestP2pState"}) 511 @Test testConcurrency()512 public void testConcurrency() { 513 sWifiP2pManager.requestP2pState(sWifiP2pChannel, new WifiP2pManager.P2pStateListener() { 514 @Override 515 public void onP2pStateAvailable(int state) { 516 synchronized (MY_RESPONSE) { 517 MY_RESPONSE.valid = true; 518 MY_RESPONSE.p2pState = state; 519 MY_RESPONSE.notify(); 520 } 521 } 522 }); 523 assertTrue(waitForServiceResponse(MY_RESPONSE)); 524 assertEquals(WifiP2pManager.WIFI_P2P_STATE_ENABLED, MY_RESPONSE.p2pState); 525 } 526 527 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#requestDiscoveryState", 528 "android.net.wifi.p2p.WifiP2pManager#discoverPeers", 529 "android.net.wifi.p2p.WifiP2pManager#stopPeerDiscovery"}) 530 @Test testRequestDiscoveryState()531 public void testRequestDiscoveryState() { 532 sWifiP2pManager.requestDiscoveryState( 533 sWifiP2pChannel, new WifiP2pManager.DiscoveryStateListener() { 534 @Override 535 public void onDiscoveryStateAvailable(int state) { 536 synchronized (MY_RESPONSE) { 537 MY_RESPONSE.valid = true; 538 MY_RESPONSE.discoveryState = state; 539 MY_RESPONSE.notify(); 540 } 541 } 542 }); 543 assertTrue(waitForServiceResponse(MY_RESPONSE)); 544 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED, MY_RESPONSE.discoveryState); 545 546 // If there is any saved network and this device is connecting to this saved network, 547 // p2p discovery might be blocked during DHCP provision. 548 int retryCount = 3; 549 while (retryCount > 0) { 550 resetResponse(MY_RESPONSE); 551 sWifiP2pManager.discoverPeers(sWifiP2pChannel, sActionListener); 552 assertTrue(waitForServiceResponse(MY_RESPONSE)); 553 if (MY_RESPONSE.success 554 || MY_RESPONSE.failureReason != WifiP2pManager.BUSY) { 555 break; 556 } 557 Log.w(TAG, "Discovery is blocked, try again!"); 558 try { 559 Thread.sleep(500); 560 } catch (InterruptedException ex) {} 561 retryCount--; 562 } 563 assertTrue(MY_RESPONSE.success); 564 assertTrue(waitForBroadcasts(MySync.DISCOVERY_STATE)); 565 566 resetResponse(MY_RESPONSE); 567 sWifiP2pManager.requestDiscoveryState(sWifiP2pChannel, 568 new WifiP2pManager.DiscoveryStateListener() { 569 @Override 570 public void onDiscoveryStateAvailable(int state) { 571 synchronized (MY_RESPONSE) { 572 MY_RESPONSE.valid = true; 573 MY_RESPONSE.discoveryState = state; 574 MY_RESPONSE.notify(); 575 } 576 } 577 }); 578 assertTrue(waitForServiceResponse(MY_RESPONSE)); 579 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED, MY_RESPONSE.discoveryState); 580 581 sWifiP2pManager.stopPeerDiscovery(sWifiP2pChannel, null); 582 } 583 584 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#requestNetworkInfo", 585 "android.net.wifi.p2p.WifiP2pManager#createGroup", 586 "android.net.wifi.p2p.WifiP2pManager#removeGroup"}) 587 @Test testRequestNetworkInfo()588 public void testRequestNetworkInfo() { 589 sWifiP2pManager.requestNetworkInfo(sWifiP2pChannel, 590 new WifiP2pManager.NetworkInfoListener() { 591 @Override 592 public void onNetworkInfoAvailable(NetworkInfo info) { 593 synchronized (MY_RESPONSE) { 594 MY_RESPONSE.valid = true; 595 MY_RESPONSE.networkInfo = info; 596 MY_RESPONSE.notify(); 597 } 598 } 599 }); 600 assertTrue(waitForServiceResponse(MY_RESPONSE)); 601 assertNotNull(MY_RESPONSE.networkInfo); 602 603 resetResponse(MY_RESPONSE); 604 sWifiP2pManager.createGroup(sWifiP2pChannel, sActionListener); 605 assertTrue(waitForServiceResponse(MY_RESPONSE)); 606 assertTrue(MY_RESPONSE.success); 607 608 assertTrue(waitForConnectedNetworkState()); 609 610 resetResponse(MY_RESPONSE); 611 sWifiP2pManager.requestNetworkInfo(sWifiP2pChannel, 612 new WifiP2pManager.NetworkInfoListener() { 613 @Override 614 public void onNetworkInfoAvailable(NetworkInfo info) { 615 synchronized (MY_RESPONSE) { 616 MY_RESPONSE.valid = true; 617 MY_RESPONSE.networkInfo = info; 618 MY_RESPONSE.notify(); 619 } 620 } 621 }); 622 assertTrue(waitForServiceResponse(MY_RESPONSE)); 623 assertNotNull(MY_RESPONSE.networkInfo); 624 assertEquals(NetworkInfo.DetailedState.CONNECTED, 625 MY_RESPONSE.networkInfo.getDetailedState()); 626 627 resetResponse(MY_RESPONSE); 628 sWifiP2pManager.requestConnectionInfo(sWifiP2pChannel, 629 new WifiP2pManager.ConnectionInfoListener() { 630 @Override 631 public void onConnectionInfoAvailable(WifiP2pInfo info) { 632 synchronized (MY_RESPONSE) { 633 MY_RESPONSE.valid = true; 634 MY_RESPONSE.p2pInfo = new WifiP2pInfo(info); 635 MY_RESPONSE.notify(); 636 } 637 } 638 }); 639 assertTrue(waitForServiceResponse(MY_RESPONSE)); 640 assertNotNull(MY_RESPONSE.p2pInfo); 641 assertTrue(MY_RESPONSE.p2pInfo.groupFormed); 642 assertTrue(MY_RESPONSE.p2pInfo.isGroupOwner); 643 644 resetResponse(MY_RESPONSE); 645 sWifiP2pManager.requestGroupInfo(sWifiP2pChannel, 646 new WifiP2pManager.GroupInfoListener() { 647 @Override 648 public void onGroupInfoAvailable(WifiP2pGroup group) { 649 synchronized (MY_RESPONSE) { 650 MY_RESPONSE.group = new WifiP2pGroup(group); 651 MY_RESPONSE.valid = true; 652 MY_RESPONSE.notify(); 653 } 654 } 655 }); 656 assertTrue(waitForServiceResponse(MY_RESPONSE)); 657 assertNotNull(MY_RESPONSE.group); 658 assertNotEquals(0, MY_RESPONSE.group.getFrequency()); 659 assertTrue(MY_RESPONSE.group.getNetworkId() >= 0); 660 661 resetResponse(MY_RESPONSE); 662 sWifiP2pManager.removeGroup(sWifiP2pChannel, sActionListener); 663 assertTrue(waitForServiceResponse(MY_RESPONSE)); 664 assertTrue(MY_RESPONSE.success); 665 assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); 666 assertNotNull(MY_SYNC.expectedNetworkInfo); 667 assertEquals(NetworkInfo.DetailedState.DISCONNECTED, 668 MY_SYNC.expectedNetworkInfo.getDetailedState()); 669 } 670 getDeviceName()671 private String getDeviceName() { 672 resetResponse(MY_RESPONSE); 673 sWifiP2pManager.requestDeviceInfo(sWifiP2pChannel, 674 new WifiP2pManager.DeviceInfoListener() { 675 @Override 676 public void onDeviceInfoAvailable(WifiP2pDevice wifiP2pDevice) { 677 synchronized (MY_RESPONSE) { 678 MY_RESPONSE.deviceName = wifiP2pDevice.deviceName; 679 MY_RESPONSE.valid = true; 680 MY_RESPONSE.notify(); 681 } 682 } 683 }); 684 assertTrue(waitForServiceResponse(MY_RESPONSE)); 685 return MY_RESPONSE.deviceName; 686 } 687 688 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pGroup#setVendorData"}) 689 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 690 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 691 codeName = "VanillaIceCream") 692 @Test testWifiP2pGroupSetAndGetVendorData()693 public void testWifiP2pGroupSetAndGetVendorData() { 694 List<OuiKeyedData> vendorData = createTestOuiKeyedDataList(5); 695 WifiP2pGroup group = new WifiP2pGroup(); 696 group.setVendorData(vendorData); 697 assertTrue(vendorData.equals(group.getVendorData())); 698 } 699 700 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#setDeviceName"}) 701 @Test testSetDeviceName()702 public void testSetDeviceName() { 703 String testDeviceName = "test"; 704 String originalDeviceName = getDeviceName(); 705 assertNotNull(originalDeviceName); 706 707 ShellIdentityUtils.invokeWithShellPermissions(() -> { 708 sWifiP2pManager.setDeviceName( 709 sWifiP2pChannel, testDeviceName, sActionListener); 710 assertTrue(waitForServiceResponse(MY_RESPONSE)); 711 assertTrue(MY_RESPONSE.success); 712 }); 713 714 String currentDeviceName = getDeviceName(); 715 assertEquals(testDeviceName, currentDeviceName); 716 717 // restore the device name at the end 718 resetResponse(MY_RESPONSE); 719 ShellIdentityUtils.invokeWithShellPermissions(() -> { 720 sWifiP2pManager.setDeviceName( 721 sWifiP2pChannel, originalDeviceName, sActionListener); 722 assertTrue(waitForServiceResponse(MY_RESPONSE)); 723 assertTrue(MY_RESPONSE.success); 724 }); 725 } 726 getPersistentGroups()727 private static WifiP2pGroupList getPersistentGroups() { 728 resetResponse(MY_RESPONSE); 729 ShellIdentityUtils.invokeWithShellPermissions(() -> { 730 sWifiP2pManager.requestPersistentGroupInfo(sWifiP2pChannel, 731 new WifiP2pManager.PersistentGroupInfoListener() { 732 @Override 733 public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) { 734 synchronized (MY_RESPONSE) { 735 MY_RESPONSE.persistentGroups = groups; 736 MY_RESPONSE.valid = true; 737 MY_RESPONSE.notify(); 738 } 739 } 740 }); 741 assertTrue(waitForServiceResponse(MY_RESPONSE)); 742 }); 743 return MY_RESPONSE.persistentGroups; 744 } 745 746 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#requestPersistentGroupInfo", 747 "android.net.wifi.p2p.WifiP2pManager#factoryReset"}) 748 @Test testPersistentGroupOperation()749 public void testPersistentGroupOperation() { 750 sWifiP2pManager.createGroup(sWifiP2pChannel, sActionListener); 751 assertTrue(waitForServiceResponse(MY_RESPONSE)); 752 assertTrue(MY_RESPONSE.success); 753 754 assertTrue(waitForConnectedNetworkState()); 755 756 resetResponse(MY_RESPONSE); 757 sWifiP2pManager.removeGroup(sWifiP2pChannel, sActionListener); 758 assertTrue(waitForServiceResponse(MY_RESPONSE)); 759 assertTrue(MY_RESPONSE.success); 760 assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); 761 assertNotNull(MY_SYNC.expectedNetworkInfo); 762 assertEquals(NetworkInfo.DetailedState.DISCONNECTED, 763 MY_SYNC.expectedNetworkInfo.getDetailedState()); 764 765 WifiP2pGroupList persistentGroups = getPersistentGroups(); 766 assertNotNull(persistentGroups); 767 assertEquals(1, persistentGroups.getGroupList().size()); 768 769 resetResponse(MY_RESPONSE); 770 final int firstNetworkId = persistentGroups.getGroupList().get(0).getNetworkId(); 771 ShellIdentityUtils.invokeWithShellPermissions(() -> { 772 sWifiP2pManager.deletePersistentGroup(sWifiP2pChannel, 773 firstNetworkId, 774 sActionListener); 775 assertTrue(waitForServiceResponse(MY_RESPONSE)); 776 assertTrue(MY_RESPONSE.success); 777 }); 778 779 persistentGroups = getPersistentGroups(); 780 assertNotNull(persistentGroups); 781 assertEquals(0, persistentGroups.getGroupList().size()); 782 783 resetResponse(MY_RESPONSE); 784 sWifiP2pManager.createGroup(sWifiP2pChannel, sActionListener); 785 assertTrue(waitForServiceResponse(MY_RESPONSE)); 786 assertTrue(MY_RESPONSE.success); 787 assertTrue(waitForConnectedNetworkState()); 788 789 resetResponse(MY_RESPONSE); 790 sWifiP2pManager.removeGroup(sWifiP2pChannel, sActionListener); 791 assertTrue(waitForServiceResponse(MY_RESPONSE)); 792 assertTrue(MY_RESPONSE.success); 793 assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); 794 assertNotNull(MY_SYNC.expectedNetworkInfo); 795 assertEquals(NetworkInfo.DetailedState.DISCONNECTED, 796 MY_SYNC.expectedNetworkInfo.getDetailedState()); 797 798 resetResponse(MY_RESPONSE); 799 ShellIdentityUtils.invokeWithShellPermissions(() -> { 800 sWifiP2pManager.factoryReset(sWifiP2pChannel, sActionListener); 801 assertTrue(waitForServiceResponse(MY_RESPONSE)); 802 assertTrue(MY_RESPONSE.success); 803 }); 804 805 persistentGroups = getPersistentGroups(); 806 assertNotNull(persistentGroups); 807 assertEquals(0, persistentGroups.getGroupList().size()); 808 } 809 810 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#setWifiP2pChannels", 811 "android.net.wifi.p2p.WifiP2pManager#startListening", 812 "android.net.wifi.p2p.WifiP2pManager#stopListening"}) 813 @Test testP2pListening()814 public void testP2pListening() { 815 ShellIdentityUtils.invokeWithShellPermissions(() -> { 816 sWifiP2pManager.setWifiP2pChannels(sWifiP2pChannel, 6, 11, sActionListener); 817 assertTrue(waitForServiceResponse(MY_RESPONSE)); 818 assertTrue(MY_RESPONSE.success); 819 }); 820 821 resetResponse(MY_RESPONSE); 822 ShellIdentityUtils.invokeWithShellPermissions(() -> { 823 sWifiP2pManager.startListening(sWifiP2pChannel, sActionListener); 824 assertTrue(waitForServiceResponse(MY_RESPONSE)); 825 assertTrue(MY_RESPONSE.success); 826 }); 827 828 resetResponse(MY_RESPONSE); 829 sWifiP2pManager.stopListening(sWifiP2pChannel, sActionListener); 830 assertTrue(waitForServiceResponse(MY_RESPONSE)); 831 assertTrue(MY_RESPONSE.success); 832 } 833 834 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#setWifiP2pChannels", 835 "android.net.wifi.p2p.WifiP2pManager#startListening", 836 "android.net.wifi.p2p.WifiP2pManager#stopListening"}) 837 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 838 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 839 codeName = "VanillaIceCream") 840 @Test testP2pListeningWithParameters()841 public void testP2pListeningWithParameters() { 842 ShellIdentityUtils.invokeWithShellPermissions(() -> { 843 sWifiP2pManager.setWifiP2pChannels(sWifiP2pChannel, 6, 11, sActionListener); 844 assertTrue(waitForServiceResponse(MY_RESPONSE)); 845 assertTrue(MY_RESPONSE.success); 846 }); 847 848 List<OuiKeyedData> vendorData = createTestOuiKeyedDataList(5); 849 WifiP2pExtListenParams extListenParams = 850 new WifiP2pExtListenParams.Builder().setVendorData(vendorData).build(); 851 assertTrue(vendorData.equals(extListenParams.getVendorData())); 852 853 resetResponse(MY_RESPONSE); 854 ShellIdentityUtils.invokeWithShellPermissions(() -> { 855 sWifiP2pManager.startListening(sWifiP2pChannel, extListenParams, sActionListener); 856 assertTrue(waitForServiceResponse(MY_RESPONSE)); 857 assertTrue(MY_RESPONSE.success); 858 }); 859 860 resetResponse(MY_RESPONSE); 861 sWifiP2pManager.stopListening(sWifiP2pChannel, sActionListener); 862 assertTrue(waitForServiceResponse(MY_RESPONSE)); 863 assertTrue(MY_RESPONSE.success); 864 } 865 866 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#setServiceResponseListener", 867 "android.net.wifi.p2p.WifiP2pManager#addLocalService", 868 "android.net.wifi.p2p.WifiP2pManager#clearLocalServices", 869 "android.net.wifi.p2p.WifiP2pManager#removeLocalService"}) 870 @Test testP2pService()871 public void testP2pService() { 872 // This only store the listener to the WifiP2pManager internal variable, nothing to fail. 873 sWifiP2pManager.setServiceResponseListener(sWifiP2pChannel, 874 new WifiP2pManager.ServiceResponseListener() { 875 @Override 876 public void onServiceAvailable( 877 int protocolType, byte[] responseData, WifiP2pDevice srcDevice) { 878 } 879 }); 880 881 List<String> services = new ArrayList<String>(); 882 services.add("urn:schemas-upnp-org:service:AVTransport:1"); 883 services.add("urn:schemas-upnp-org:service:ConnectionManager:1"); 884 WifiP2pServiceInfo rendererService = WifiP2pUpnpServiceInfo.newInstance( 885 "6859dede-8574-59ab-9332-123456789011", 886 "urn:schemas-upnp-org:device:MediaRenderer:1", 887 services); 888 sWifiP2pManager.addLocalService(sWifiP2pChannel, 889 rendererService, 890 sActionListener); 891 assertTrue(waitForServiceResponse(MY_RESPONSE)); 892 assertTrue(MY_RESPONSE.success); 893 894 resetResponse(MY_RESPONSE); 895 sWifiP2pManager.removeLocalService(sWifiP2pChannel, 896 rendererService, 897 sActionListener); 898 assertTrue(waitForServiceResponse(MY_RESPONSE)); 899 assertTrue(MY_RESPONSE.success); 900 901 resetResponse(MY_RESPONSE); 902 sWifiP2pManager.clearLocalServices(sWifiP2pChannel, 903 sActionListener); 904 assertTrue(waitForServiceResponse(MY_RESPONSE)); 905 assertTrue(MY_RESPONSE.success); 906 } 907 908 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#removeClient"}) 909 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 910 @Test testRemoveClient()911 public void testRemoveClient() { 912 913 if (!sWifiP2pManager.isGroupClientRemovalSupported()) return; 914 915 sWifiP2pManager.createGroup(sWifiP2pChannel, sActionListener); 916 assertTrue(waitForServiceResponse(MY_RESPONSE)); 917 assertTrue(MY_RESPONSE.success); 918 919 assertTrue(waitForConnectedNetworkState()); 920 921 resetResponse(MY_RESPONSE); 922 MacAddress peerMacAddress = MacAddress.fromString(mTestWifiP2pPeerConfig.deviceAddress); 923 sWifiP2pManager.removeClient( 924 sWifiP2pChannel, peerMacAddress, sActionListener); 925 assertTrue(waitForServiceResponse(MY_RESPONSE)); 926 assertTrue(MY_RESPONSE.success); 927 } 928 929 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#discoverPeers"}) 930 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 931 @Test testDiscoverPeersOnSpecificFreq()932 public void testDiscoverPeersOnSpecificFreq() { 933 if (!sWifiP2pManager.isChannelConstrainedDiscoverySupported()) return; 934 935 resetResponse(MY_RESPONSE); 936 sWifiP2pManager.requestDiscoveryState( 937 sWifiP2pChannel, new WifiP2pManager.DiscoveryStateListener() { 938 @Override 939 public void onDiscoveryStateAvailable(int state) { 940 synchronized (MY_RESPONSE) { 941 MY_RESPONSE.valid = true; 942 MY_RESPONSE.discoveryState = state; 943 MY_RESPONSE.notify(); 944 } 945 } 946 }); 947 assertTrue(waitForServiceResponse(MY_RESPONSE)); 948 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED, MY_RESPONSE.discoveryState); 949 950 // If there is any saved network and this device is connecting to this saved network, 951 // p2p discovery might be blocked during DHCP provision. 952 int retryCount = 3; 953 while (retryCount > 0) { 954 resetResponse(MY_RESPONSE); 955 sWifiP2pManager.discoverPeersOnSpecificFrequency(sWifiP2pChannel, 956 2412, sActionListener); 957 assertTrue(waitForServiceResponse(MY_RESPONSE)); 958 if (MY_RESPONSE.success 959 || MY_RESPONSE.failureReason != WifiP2pManager.BUSY) { 960 break; 961 } 962 Log.w(TAG, "Discovery is blocked, try again!"); 963 try { 964 Thread.sleep(500); 965 } catch (InterruptedException ex) { } 966 retryCount--; 967 } 968 assertTrue(MY_RESPONSE.success); 969 assertTrue(waitForBroadcasts(MySync.DISCOVERY_STATE)); 970 971 resetResponse(MY_RESPONSE); 972 sWifiP2pManager.requestDiscoveryState(sWifiP2pChannel, 973 new WifiP2pManager.DiscoveryStateListener() { 974 @Override 975 public void onDiscoveryStateAvailable(int state) { 976 synchronized (MY_RESPONSE) { 977 MY_RESPONSE.valid = true; 978 MY_RESPONSE.discoveryState = state; 979 MY_RESPONSE.notify(); 980 } 981 } 982 }); 983 assertTrue(waitForServiceResponse(MY_RESPONSE)); 984 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED, MY_RESPONSE.discoveryState); 985 986 sWifiP2pManager.stopPeerDiscovery(sWifiP2pChannel, null); 987 } 988 989 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#discoverPeersOnSocialChannels"}) 990 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 991 @Test testDiscoverPeersOnSocialChannelsOnly()992 public void testDiscoverPeersOnSocialChannelsOnly() { 993 994 if (!sWifiP2pManager.isChannelConstrainedDiscoverySupported()) return; 995 996 resetResponse(MY_RESPONSE); 997 sWifiP2pManager.requestDiscoveryState( 998 sWifiP2pChannel, new WifiP2pManager.DiscoveryStateListener() { 999 @Override 1000 public void onDiscoveryStateAvailable(int state) { 1001 synchronized (MY_RESPONSE) { 1002 MY_RESPONSE.valid = true; 1003 MY_RESPONSE.discoveryState = state; 1004 MY_RESPONSE.notify(); 1005 } 1006 } 1007 }); 1008 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1009 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED, MY_RESPONSE.discoveryState); 1010 1011 // If there is any saved network and this device is connecting to this saved network, 1012 // p2p discovery might be blocked during DHCP provision. 1013 int retryCount = 3; 1014 while (retryCount > 0) { 1015 resetResponse(MY_RESPONSE); 1016 sWifiP2pManager.discoverPeersOnSocialChannels(sWifiP2pChannel, sActionListener); 1017 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1018 if (MY_RESPONSE.success 1019 || MY_RESPONSE.failureReason != WifiP2pManager.BUSY) { 1020 break; 1021 } 1022 Log.w(TAG, "Discovery is blocked, try again!"); 1023 try { 1024 Thread.sleep(500); 1025 } catch (InterruptedException ex) { } 1026 retryCount--; 1027 } 1028 assertTrue(MY_RESPONSE.success); 1029 assertTrue(waitForBroadcasts(MySync.DISCOVERY_STATE)); 1030 1031 resetResponse(MY_RESPONSE); 1032 sWifiP2pManager.requestDiscoveryState(sWifiP2pChannel, 1033 new WifiP2pManager.DiscoveryStateListener() { 1034 @Override 1035 public void onDiscoveryStateAvailable(int state) { 1036 synchronized (MY_RESPONSE) { 1037 MY_RESPONSE.valid = true; 1038 MY_RESPONSE.discoveryState = state; 1039 MY_RESPONSE.notify(); 1040 } 1041 } 1042 }); 1043 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1044 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED, MY_RESPONSE.discoveryState); 1045 1046 sWifiP2pManager.stopPeerDiscovery(sWifiP2pChannel, null); 1047 } 1048 createTestOuiKeyedData(int oui)1049 private static OuiKeyedData createTestOuiKeyedData(int oui) { 1050 PersistableBundle bundle = new PersistableBundle(); 1051 bundle.putString("stringFieldKey", "stringData"); 1052 bundle.putInt("intFieldKey", 789); 1053 return new OuiKeyedData.Builder(oui, bundle).build(); 1054 } 1055 createTestOuiKeyedDataList(int size)1056 private static List<OuiKeyedData> createTestOuiKeyedDataList(int size) { 1057 List<OuiKeyedData> ouiKeyedDataList = new ArrayList<>(); 1058 for (int i = 0; i < size; i++) { 1059 ouiKeyedDataList.add(createTestOuiKeyedData(TEST_OUI)); 1060 } 1061 return ouiKeyedDataList; 1062 } 1063 1064 /** 1065 * Test that we can trigger a P2P scan using 1066 * {@link WifiP2pManager#startPeerDiscovery( 1067 * WifiP2pManager.Channel, WifiP2pDiscoveryConfig, WifiP2pManager.ActionListener)} 1068 */ 1069 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#startPeerDiscovery"}) 1070 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1071 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 1072 codeName = "VanillaIceCream") 1073 @Test testStartPeerDiscovery()1074 public void testStartPeerDiscovery() { 1075 if (!sWifiP2pManager.isChannelConstrainedDiscoverySupported()) return; 1076 1077 resetResponse(MY_RESPONSE); 1078 sWifiP2pManager.requestDiscoveryState( 1079 sWifiP2pChannel, new WifiP2pManager.DiscoveryStateListener() { 1080 @Override 1081 public void onDiscoveryStateAvailable(int state) { 1082 synchronized (MY_RESPONSE) { 1083 MY_RESPONSE.valid = true; 1084 MY_RESPONSE.discoveryState = state; 1085 MY_RESPONSE.notify(); 1086 } 1087 } 1088 }); 1089 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1090 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED, MY_RESPONSE.discoveryState); 1091 1092 WifiP2pDiscoveryConfig discoveryConfig = new WifiP2pDiscoveryConfig.Builder( 1093 WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ) 1094 .setFrequencyMhz(2412) 1095 .setVendorData(createTestOuiKeyedDataList(5)) 1096 .build(); 1097 1098 // If there is any saved network and this device is connecting to this saved network, 1099 // p2p discovery might be blocked during DHCP provision. 1100 int retryCount = 3; 1101 while (retryCount > 0) { 1102 resetResponse(MY_RESPONSE); 1103 sWifiP2pManager.startPeerDiscovery(sWifiP2pChannel, 1104 discoveryConfig, sActionListener); 1105 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1106 if (MY_RESPONSE.success 1107 || MY_RESPONSE.failureReason != WifiP2pManager.BUSY) { 1108 break; 1109 } 1110 Log.w(TAG, "Discovery is blocked, try again!"); 1111 try { 1112 Thread.sleep(500); 1113 } catch (InterruptedException ex) { } 1114 retryCount--; 1115 } 1116 assertTrue(MY_RESPONSE.success); 1117 assertTrue(waitForBroadcasts(MySync.DISCOVERY_STATE)); 1118 1119 resetResponse(MY_RESPONSE); 1120 sWifiP2pManager.requestDiscoveryState(sWifiP2pChannel, 1121 new WifiP2pManager.DiscoveryStateListener() { 1122 @Override 1123 public void onDiscoveryStateAvailable(int state) { 1124 synchronized (MY_RESPONSE) { 1125 MY_RESPONSE.valid = true; 1126 MY_RESPONSE.discoveryState = state; 1127 MY_RESPONSE.notify(); 1128 } 1129 } 1130 }); 1131 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1132 assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED, MY_RESPONSE.discoveryState); 1133 1134 sWifiP2pManager.stopPeerDiscovery(sWifiP2pChannel, null); 1135 } 1136 1137 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pConfig.Builder#setGroupClientIpProvisioningMode"}) 1138 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1139 @Test testP2pConnectDoesNotThrowExceptionWhenGroupOwnerIpv6IsNotProvided()1140 public void testP2pConnectDoesNotThrowExceptionWhenGroupOwnerIpv6IsNotProvided() { 1141 1142 if (sWifiP2pManager.isGroupOwnerIPv6LinkLocalAddressProvided()) { 1143 return; 1144 } 1145 WifiP2pConfig config = new WifiP2pConfig.Builder() 1146 .setDeviceAddress(MacAddress.fromString("aa:bb:cc:dd:ee:ff")) 1147 .setGroupClientIpProvisioningMode( 1148 GROUP_CLIENT_IP_PROVISIONING_MODE_IPV6_LINK_LOCAL) 1149 .build(); 1150 sWifiP2pManager.connect(sWifiP2pChannel, config, sActionListener); 1151 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1152 assertFalse(MY_RESPONSE.success); 1153 } 1154 1155 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pConfig.Builder#setVendorData"}) 1156 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1157 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 1158 codeName = "VanillaIceCream") 1159 @Test testP2pConnectDoesNotThrowExceptionWithVendorData()1160 public void testP2pConnectDoesNotThrowExceptionWithVendorData() { 1161 OuiKeyedData vendorDataElement = 1162 new OuiKeyedData.Builder(TEST_OUI, new PersistableBundle()).build(); 1163 List<OuiKeyedData> vendorData = Arrays.asList(vendorDataElement); 1164 WifiP2pConfig config = new WifiP2pConfig.Builder() 1165 .setDeviceAddress(MacAddress.fromString("aa:bb:cc:dd:ee:ff")) 1166 .build(); 1167 config.setVendorData(vendorData); 1168 sWifiP2pManager.connect(sWifiP2pChannel, config, sActionListener); 1169 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1170 assertFalse(MY_RESPONSE.success); 1171 } 1172 1173 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#setVendorElements"}) 1174 @Test testP2pSetVendorElements()1175 public void testP2pSetVendorElements() { 1176 1177 if (!sWifiP2pManager.isSetVendorElementsSupported()) return; 1178 1179 // Vendor-Specific EID is 221. 1180 List<ScanResult.InformationElement> ies = new ArrayList<>(Arrays.asList( 1181 new ScanResult.InformationElement(221, 0, 1182 new byte[]{(byte) 1, (byte) 2, (byte) 3, (byte) 4}))); 1183 ShellIdentityUtils.invokeWithShellPermissions(() -> { 1184 sWifiP2pManager.setVendorElements(sWifiP2pChannel, ies, sActionListener); 1185 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1186 assertTrue(MY_RESPONSE.success); 1187 }); 1188 1189 resetResponse(MY_RESPONSE); 1190 sWifiP2pManager.discoverPeers(sWifiP2pChannel, sActionListener); 1191 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1192 } 1193 1194 /** Test IEs whose size is greater than the maximum allowed size. */ 1195 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager" 1196 + "#getP2pMaxAllowedVendorElementsLengthBytes"}) 1197 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1198 @Test testP2pSetVendorElementsOverMaximumAllowedSize()1199 public void testP2pSetVendorElementsOverMaximumAllowedSize() { 1200 1201 if (!sWifiP2pManager.isSetVendorElementsSupported()) return; 1202 1203 List<ScanResult.InformationElement> ies = new ArrayList<>(); 1204 ies.add(new ScanResult.InformationElement(221, 0, 1205 new byte[WifiP2pManager.getP2pMaxAllowedVendorElementsLengthBytes() + 1])); 1206 ShellIdentityUtils.invokeWithShellPermissions(() -> { 1207 try { 1208 sWifiP2pManager.setVendorElements(sWifiP2pChannel, ies, sActionListener); 1209 fail("Should raise IllegalArgumentException"); 1210 } catch (IllegalArgumentException ex) { 1211 // expected 1212 return; 1213 } 1214 }); 1215 } 1216 1217 /** Test that external approver APIs. */ 1218 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#addExternalApprover", 1219 "android.net.wifi.p2p.WifiP2pManager#setConnectionRequestResult", 1220 "android.net.wifi.p2p.WifiP2pManager#removeExternalApprover"}) 1221 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1222 @Test testP2pExternalApprover()1223 public void testP2pExternalApprover() { 1224 final MacAddress peer = MacAddress.fromString("11:22:33:44:55:66"); 1225 ExternalApproverRequestListener listener = 1226 new ExternalApproverRequestListener() { 1227 @Override 1228 public void onAttached(MacAddress deviceAddress) { 1229 synchronized (MY_RESPONSE) { 1230 MY_RESPONSE.targetPeer = deviceAddress; 1231 MY_RESPONSE.valid = true; 1232 MY_RESPONSE.isAttached = true; 1233 MY_RESPONSE.notify(); 1234 } 1235 } 1236 @Override 1237 public void onDetached(MacAddress deviceAddress, int reason) { 1238 synchronized (MY_RESPONSE) { 1239 MY_RESPONSE.targetPeer = deviceAddress; 1240 MY_RESPONSE.detachReason = reason; 1241 MY_RESPONSE.valid = true; 1242 MY_RESPONSE.isDetached = true; 1243 MY_RESPONSE.notify(); 1244 } 1245 } 1246 @Override 1247 public void onConnectionRequested(int requestType, WifiP2pConfig config, 1248 WifiP2pDevice device) { 1249 } 1250 @Override 1251 public void onPinGenerated(MacAddress deviceAddress, String pin) { 1252 } 1253 }; 1254 1255 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1256 try { 1257 uiAutomation.adoptShellPermissionIdentity(); 1258 sWifiP2pManager.addExternalApprover(sWifiP2pChannel, peer, listener); 1259 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1260 assertTrue(MY_RESPONSE.isAttached); 1261 assertFalse(MY_RESPONSE.isDetached); 1262 assertEquals(peer, MY_RESPONSE.targetPeer); 1263 1264 // Just ignore the result as there is no real incoming request. 1265 sWifiP2pManager.setConnectionRequestResult(sWifiP2pChannel, peer, 1266 WifiP2pManager.CONNECTION_REQUEST_ACCEPT, null); 1267 sWifiP2pManager.setConnectionRequestResult(sWifiP2pChannel, peer, 1268 WifiP2pManager.CONNECTION_REQUEST_ACCEPT, "12345678", null); 1269 1270 resetResponse(MY_RESPONSE); 1271 sWifiP2pManager.removeExternalApprover(sWifiP2pChannel, peer, null); 1272 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1273 assertTrue(MY_RESPONSE.isDetached); 1274 assertFalse(MY_RESPONSE.isAttached); 1275 assertEquals(peer, MY_RESPONSE.targetPeer); 1276 assertEquals(ExternalApproverRequestListener.APPROVER_DETACH_REASON_REMOVE, 1277 MY_RESPONSE.detachReason); 1278 } finally { 1279 uiAutomation.dropShellPermissionIdentity(); 1280 } 1281 1282 } 1283 1284 /** Test setWfdInfo() API. */ 1285 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#setWfdInfo"}) 1286 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE) 1287 @Test testP2pSetWfdInfo()1288 public void testP2pSetWfdInfo() { 1289 WifiP2pWfdInfo info = new WifiP2pWfdInfo(); 1290 info.setEnabled(true); 1291 info.setDeviceType(WifiP2pWfdInfo.DEVICE_TYPE_WFD_SOURCE); 1292 info.setSessionAvailable(true); 1293 ShellIdentityUtils.invokeWithShellPermissions(() -> { 1294 sWifiP2pManager.setWfdInfo(sWifiP2pChannel, info, sActionListener); 1295 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1296 assertTrue(MY_RESPONSE.success); 1297 }); 1298 } 1299 1300 /** 1301 * Tests {@link WifiP2pManager#getListenState(WifiP2pManager.Channel, Executor, Consumer)} 1302 */ 1303 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#getListenState"}) 1304 @Test testGetListenState()1305 public void testGetListenState() { 1306 Consumer<Integer> testListenStateListener = new Consumer<Integer>() { 1307 @Override 1308 public void accept(Integer state) { 1309 synchronized (MY_RESPONSE) { 1310 MY_RESPONSE.valid = true; 1311 MY_RESPONSE.listenState = state.intValue(); 1312 MY_RESPONSE.notify(); 1313 } 1314 } 1315 }; 1316 1317 sWifiP2pManager.getListenState(sWifiP2pChannel, mExecutor, testListenStateListener); 1318 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1319 assertEquals(WifiP2pManager.WIFI_P2P_LISTEN_STOPPED, MY_RESPONSE.listenState); 1320 1321 resetResponse(MY_RESPONSE); 1322 sWifiP2pManager.startListening(sWifiP2pChannel, sActionListener); 1323 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1324 assertTrue(waitForBroadcasts(MySync.LISTEN_STATE)); 1325 1326 resetResponse(MY_RESPONSE); 1327 sWifiP2pManager.getListenState(sWifiP2pChannel, mExecutor, testListenStateListener); 1328 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1329 assertEquals(WifiP2pManager.WIFI_P2P_LISTEN_STARTED, MY_RESPONSE.listenState); 1330 1331 resetResponse(MY_RESPONSE); 1332 sWifiP2pManager.stopListening(sWifiP2pChannel, sActionListener); 1333 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1334 assertTrue(waitForBroadcasts(MySync.LISTEN_STATE)); 1335 1336 resetResponse(MY_RESPONSE); 1337 sWifiP2pManager.getListenState(sWifiP2pChannel, mExecutor, testListenStateListener); 1338 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1339 assertEquals(WifiP2pManager.WIFI_P2P_LISTEN_STOPPED, MY_RESPONSE.listenState); 1340 } 1341 1342 @ApiTest(apis = {"android.net.wifi.WifiP2pManager#getListenState"}) 1343 @Test testWpsInfo()1344 public void testWpsInfo() { 1345 WpsInfo info = new WpsInfo(); 1346 assertEquals(WpsInfo.INVALID, info.setup); 1347 assertNull(info.BSSID); 1348 assertNull(info.pin); 1349 WpsInfo infoCopy = new WpsInfo(info); 1350 assertEquals(WpsInfo.INVALID, infoCopy.setup); 1351 assertNull(infoCopy.BSSID); 1352 assertNull(infoCopy.pin); 1353 } 1354 1355 /** 1356 * Tests that we can properly get/set fields in {@link WifiP2pDiscoveryConfig}. 1357 */ 1358 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1359 @Test testWifiP2pDiscoveryConfig()1360 public void testWifiP2pDiscoveryConfig() { 1361 int scanType = WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ; 1362 int frequencyMhz = 2600; 1363 WifiP2pDiscoveryConfig config = new WifiP2pDiscoveryConfig.Builder(scanType) 1364 .setFrequencyMhz(frequencyMhz) 1365 .build(); 1366 assertEquals(scanType, config.getScanType()); 1367 assertEquals(frequencyMhz, config.getFrequencyMhz()); 1368 } 1369 1370 /** 1371 * Tests that we can properly get/set fields in {@link WifiP2pDiscoveryConfig}, 1372 * including the Vendor Data. 1373 */ 1374 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1375 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 1376 codeName = "VanillaIceCream") 1377 @Test testWifiP2pDiscoveryConfigWithVendorData()1378 public void testWifiP2pDiscoveryConfigWithVendorData() { 1379 int scanType = WifiP2pManager.WIFI_P2P_SCAN_SINGLE_FREQ; 1380 int frequencyMhz = 2600; 1381 List<OuiKeyedData> vendorData = createTestOuiKeyedDataList(5); 1382 WifiP2pDiscoveryConfig config = new WifiP2pDiscoveryConfig.Builder(scanType) 1383 .setFrequencyMhz(frequencyMhz) 1384 .setVendorData(vendorData) 1385 .build(); 1386 assertEquals(scanType, config.getScanType()); 1387 assertEquals(frequencyMhz, config.getFrequencyMhz()); 1388 assertTrue(vendorData.equals(config.getVendorData())); 1389 } 1390 1391 /** 1392 * Tests that we can properly set/get vendor data in {@link WifiP2pDevice}. 1393 */ 1394 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1395 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM, 1396 codeName = "VanillaIceCream") 1397 @Test testWifiP2pDeviceWithVendorData()1398 public void testWifiP2pDeviceWithVendorData() { 1399 WifiP2pDevice device = new WifiP2pDevice(); 1400 List<OuiKeyedData> vendorData = createTestOuiKeyedDataList(5); 1401 device.setVendorData(vendorData); 1402 assertEquals(vendorData, device.getVendorData()); 1403 } 1404 1405 private static class TestWifiP2pListener implements WifiP2pManager.WifiP2pListener { 1406 public static final int ON_P2P_STATE_CHANGED = 0; 1407 public static final int ON_DISCOVERY_STATE_CHANGED = 1; 1408 public static final int ON_LISTEN_STATE_CHANGED = 2; 1409 public static final int ON_DEVICE_CONFIGURATION_CHANGED = 3; 1410 public static final int ON_PEER_LIST_CHANGED = 4; 1411 public static final int ON_PERSISTENT_GROUPS_CHANGED = 5; 1412 public static final int ON_GROUP_CREATING = 6; 1413 public static final int ON_GROUP_NEGOTIATION_REJECTED_BY_USER = 7; 1414 public static final int ON_GROUP_CREATION_FAILED = 8; 1415 public static final int ON_GROUP_CREATED = 9; 1416 public static final int ON_PEER_CLIENT_JOINED = 10; 1417 public static final int ON_PEER_CLIENT_DISCONNECTED = 11; 1418 public static final int ON_FREQUENCY_CHANGED = 12; 1419 public static final int ON_GROUP_REMOVED = 13; 1420 final Object mP2pListenerLock; 1421 int mCalledCallbacks = 0; 1422 int mP2pState = -1; 1423 int mDiscoveryState = -1; 1424 int mListenState = -1; 1425 WifiP2pDevice mP2pDevice = null; 1426 WifiP2pDeviceList mP2pDeviceList = null; 1427 WifiP2pGroupList mP2pGroupList = null; 1428 WifiP2pInfo mP2pInfo = null; 1429 WifiP2pGroup mP2pGroup = null; 1430 int mP2pGroupCreationFailureReason = -1; 1431 TestWifiP2pListener(Object lock)1432 TestWifiP2pListener(Object lock) { 1433 mP2pListenerLock = lock; 1434 } 1435 getP2pState()1436 public int getP2pState() { 1437 synchronized (mP2pListenerLock) { 1438 return mP2pState; 1439 } 1440 } 1441 getDiscoveryState()1442 public int getDiscoveryState() { 1443 synchronized (mP2pListenerLock) { 1444 return mDiscoveryState; 1445 } 1446 } 1447 getListenState()1448 public int getListenState() { 1449 synchronized (mP2pListenerLock) { 1450 return mListenState; 1451 } 1452 } 1453 getP2pDevice()1454 public WifiP2pDevice getP2pDevice() { 1455 synchronized (mP2pListenerLock) { 1456 return mP2pDevice; 1457 } 1458 } 1459 getP2pDeviceList()1460 public WifiP2pDeviceList getP2pDeviceList() { 1461 synchronized (mP2pListenerLock) { 1462 return mP2pDeviceList; 1463 } 1464 } 1465 getP2pGroupList()1466 public WifiP2pGroupList getP2pGroupList() { 1467 synchronized (mP2pListenerLock) { 1468 return mP2pGroupList; 1469 } 1470 } 1471 getP2pGroupCreationFailureReason()1472 public int getP2pGroupCreationFailureReason() { 1473 synchronized (mP2pListenerLock) { 1474 return mP2pGroupCreationFailureReason; 1475 } 1476 } 1477 getP2pInfo()1478 public WifiP2pInfo getP2pInfo() { 1479 synchronized (mP2pListenerLock) { 1480 return mP2pInfo; 1481 } 1482 } 1483 getP2pGroup()1484 public WifiP2pGroup getP2pGroup() { 1485 synchronized (mP2pListenerLock) { 1486 return mP2pGroup; 1487 } 1488 } 1489 reset()1490 public void reset() { 1491 mCalledCallbacks = 0; 1492 mP2pState = -1; 1493 mDiscoveryState = -1; 1494 mListenState = -1; 1495 mP2pDevice = null; 1496 mP2pDeviceList = null; 1497 mP2pGroupList = null; 1498 mP2pInfo = null; 1499 mP2pGroup = null; 1500 mP2pGroupCreationFailureReason = -1; 1501 } 1502 1503 @Override onP2pStateChanged(int state)1504 public void onP2pStateChanged(int state) { 1505 synchronized (mP2pListenerLock) { 1506 mP2pState = state; 1507 mCalledCallbacks |= 1 << ON_P2P_STATE_CHANGED; 1508 mP2pListenerLock.notify(); 1509 } 1510 } 1511 1512 @Override onDiscoveryStateChanged(int state)1513 public void onDiscoveryStateChanged(int state) { 1514 synchronized (mP2pListenerLock) { 1515 mDiscoveryState = state; 1516 mCalledCallbacks |= 1 << ON_DISCOVERY_STATE_CHANGED; 1517 mP2pListenerLock.notify(); 1518 } 1519 } 1520 1521 @Override onListenStateChanged(int state)1522 public void onListenStateChanged(int state) { 1523 synchronized (mP2pListenerLock) { 1524 mListenState = state; 1525 mCalledCallbacks |= 1 << ON_LISTEN_STATE_CHANGED; 1526 mP2pListenerLock.notify(); 1527 } 1528 } 1529 1530 @Override onDeviceConfigurationChanged(@ullable WifiP2pDevice p2pDevice)1531 public void onDeviceConfigurationChanged(@Nullable WifiP2pDevice p2pDevice) { 1532 synchronized (mP2pListenerLock) { 1533 mP2pDevice = p2pDevice; 1534 mCalledCallbacks |= 1 << ON_DEVICE_CONFIGURATION_CHANGED; 1535 mP2pListenerLock.notify(); 1536 } 1537 } 1538 1539 @Override onPeerListChanged(@onNull WifiP2pDeviceList p2pDeviceList)1540 public void onPeerListChanged(@NonNull WifiP2pDeviceList p2pDeviceList) { 1541 synchronized (mP2pListenerLock) { 1542 mP2pDeviceList = p2pDeviceList; 1543 mCalledCallbacks |= 1 << ON_PEER_LIST_CHANGED; 1544 mP2pListenerLock.notify(); 1545 } 1546 } 1547 1548 @Override onPersistentGroupsChanged(@onNull WifiP2pGroupList p2pGroupList)1549 public void onPersistentGroupsChanged(@NonNull WifiP2pGroupList p2pGroupList) { 1550 synchronized (mP2pListenerLock) { 1551 mP2pGroupList = p2pGroupList; 1552 mCalledCallbacks |= 1 << ON_PERSISTENT_GROUPS_CHANGED; 1553 mP2pListenerLock.notify(); 1554 } 1555 } 1556 1557 @Override onGroupCreating()1558 public void onGroupCreating() { 1559 synchronized (mP2pListenerLock) { 1560 mCalledCallbacks |= 1 << ON_GROUP_CREATING; 1561 // do not notify lock till group created 1562 } 1563 } 1564 1565 @Override onGroupNegotiationRejectedByUser()1566 public void onGroupNegotiationRejectedByUser() { 1567 synchronized (mP2pListenerLock) { 1568 mCalledCallbacks |= 1 << ON_GROUP_NEGOTIATION_REJECTED_BY_USER; 1569 mP2pListenerLock.notify(); 1570 } 1571 } 1572 1573 @Override onGroupCreationFailed(int reason)1574 public void onGroupCreationFailed(int reason) { 1575 synchronized (mP2pListenerLock) { 1576 mP2pGroupCreationFailureReason = reason; 1577 mCalledCallbacks |= 1 << ON_GROUP_CREATION_FAILED; 1578 mP2pListenerLock.notify(); 1579 } 1580 } 1581 1582 @Override onGroupCreated(@onNull WifiP2pInfo wifiP2pInfo, @NonNull WifiP2pGroup wifiP2pGroup)1583 public void onGroupCreated(@NonNull WifiP2pInfo wifiP2pInfo, 1584 @NonNull WifiP2pGroup wifiP2pGroup) { 1585 synchronized (mP2pListenerLock) { 1586 mP2pInfo = wifiP2pInfo; 1587 mP2pGroup = wifiP2pGroup; 1588 mCalledCallbacks |= 1 << ON_GROUP_CREATED; 1589 mP2pListenerLock.notify(); 1590 } 1591 } 1592 1593 @Override onPeerClientJoined(@onNull WifiP2pInfo wifiP2pInfo, @NonNull WifiP2pGroup wifiP2pGroup)1594 public void onPeerClientJoined(@NonNull WifiP2pInfo wifiP2pInfo, 1595 @NonNull WifiP2pGroup wifiP2pGroup) { 1596 synchronized (mP2pListenerLock) { 1597 mP2pInfo = wifiP2pInfo; 1598 mP2pGroup = wifiP2pGroup; 1599 mCalledCallbacks |= 1 << ON_PEER_CLIENT_JOINED; 1600 mP2pListenerLock.notify(); 1601 } 1602 } 1603 1604 @Override onPeerClientDisconnected(@onNull WifiP2pInfo wifiP2pInfo, @NonNull WifiP2pGroup wifiP2pGroup)1605 public void onPeerClientDisconnected(@NonNull WifiP2pInfo wifiP2pInfo, 1606 @NonNull WifiP2pGroup wifiP2pGroup) { 1607 synchronized (mP2pListenerLock) { 1608 mP2pInfo = wifiP2pInfo; 1609 mP2pGroup = wifiP2pGroup; 1610 mCalledCallbacks |= 1 << ON_PEER_CLIENT_DISCONNECTED; 1611 mP2pListenerLock.notify(); 1612 } 1613 } 1614 1615 @Override onFrequencyChanged(@onNull WifiP2pInfo wifiP2pInfo, @NonNull WifiP2pGroup wifiP2pGroup)1616 public void onFrequencyChanged(@NonNull WifiP2pInfo wifiP2pInfo, 1617 @NonNull WifiP2pGroup wifiP2pGroup) { 1618 synchronized (mP2pListenerLock) { 1619 mP2pInfo = wifiP2pInfo; 1620 mP2pGroup = wifiP2pGroup; 1621 mCalledCallbacks |= 1 << ON_FREQUENCY_CHANGED; 1622 mP2pListenerLock.notify(); 1623 } 1624 } 1625 1626 @Override onGroupRemoved()1627 public void onGroupRemoved() { 1628 synchronized (mP2pListenerLock) { 1629 mCalledCallbacks |= 1 << ON_GROUP_REMOVED; 1630 mP2pListenerLock.notify(); 1631 } 1632 } 1633 } 1634 waitForP2pListenerCallbackCalled(TestWifiP2pListener p2pListener, int calledCallbackOffset, int waitTimeoutMs)1635 private boolean waitForP2pListenerCallbackCalled(TestWifiP2pListener p2pListener, 1636 int calledCallbackOffset, int waitTimeoutMs) { 1637 synchronized (p2pListener.mP2pListenerLock) { 1638 long timeout = System.currentTimeMillis() + waitTimeoutMs; 1639 while (System.currentTimeMillis() < timeout) { 1640 try { 1641 p2pListener.mP2pListenerLock.wait(WAIT_MS); 1642 } catch (InterruptedException e) { 1643 } 1644 if ((p2pListener.mCalledCallbacks & (1 << calledCallbackOffset)) > 0) { 1645 return true; 1646 } 1647 } 1648 return false; 1649 } 1650 } 1651 1652 @ApiTest(apis = {"android.net.wifi.p2p.WifiP2pManager#registerWifiP2pListener", 1653 "android.net.wifi.p2p.WifiP2pManager#unregisterWifiP2pListener"}) 1654 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1655 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1656 @Test testWifiP2pListener()1657 public void testWifiP2pListener() { 1658 int lockWaitTimeoutMs = 5000; 1659 TestWifiP2pListener p2pListener = new TestWifiP2pListener(mLock); 1660 synchronized (mLock) { 1661 sWifiP2pManager.registerWifiP2pListener(mExecutor, p2pListener); 1662 1663 resetResponse(MY_RESPONSE); 1664 sWifiP2pManager.startListening(sWifiP2pChannel, sActionListener); 1665 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1666 assertTrue(waitForP2pListenerCallbackCalled(p2pListener, 1667 p2pListener.ON_LISTEN_STATE_CHANGED, lockWaitTimeoutMs)); 1668 assertEquals(WifiP2pManager.WIFI_P2P_LISTEN_STARTED, p2pListener.getListenState()); 1669 resetResponse(MY_RESPONSE); 1670 p2pListener.reset(); 1671 sWifiP2pManager.stopListening(sWifiP2pChannel, sActionListener); 1672 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1673 assertTrue(waitForP2pListenerCallbackCalled(p2pListener, 1674 p2pListener.ON_LISTEN_STATE_CHANGED, lockWaitTimeoutMs)); 1675 assertEquals(WifiP2pManager.WIFI_P2P_LISTEN_STOPPED, p2pListener.getListenState()); 1676 1677 resetResponse(MY_RESPONSE); 1678 p2pListener.reset(); 1679 String testDeviceName = "Android_Test"; 1680 String originalDeviceName = getDeviceName(); 1681 assertNotNull(originalDeviceName); 1682 ShellIdentityUtils.invokeWithShellPermissions(() -> { 1683 sWifiP2pManager.setDeviceName( 1684 sWifiP2pChannel, testDeviceName, sActionListener); 1685 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1686 assertTrue(waitForP2pListenerCallbackCalled(p2pListener, 1687 p2pListener.ON_DEVICE_CONFIGURATION_CHANGED, lockWaitTimeoutMs)); 1688 assertEquals(testDeviceName, p2pListener.getP2pDevice().deviceName); 1689 }); 1690 resetResponse(MY_RESPONSE); 1691 p2pListener.reset(); 1692 ShellIdentityUtils.invokeWithShellPermissions(() -> { 1693 sWifiP2pManager.setDeviceName( 1694 sWifiP2pChannel, originalDeviceName, sActionListener); 1695 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1696 assertTrue(waitForP2pListenerCallbackCalled(p2pListener, 1697 p2pListener.ON_DEVICE_CONFIGURATION_CHANGED, lockWaitTimeoutMs)); 1698 assertEquals(originalDeviceName, p2pListener.getP2pDevice().deviceName); 1699 }); 1700 1701 resetResponse(MY_RESPONSE); 1702 p2pListener.reset(); 1703 sWifiP2pManager.createGroup(sWifiP2pChannel, sActionListener); 1704 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1705 assertTrue(MY_RESPONSE.success); 1706 assertTrue(waitForP2pListenerCallbackCalled(p2pListener, p2pListener.ON_GROUP_CREATED, 1707 lockWaitTimeoutMs)); 1708 assertTrue(p2pListener.getP2pInfo().groupFormed); 1709 assertNotNull(p2pListener.getP2pGroup()); 1710 1711 resetResponse(MY_RESPONSE); 1712 p2pListener.reset(); 1713 sWifiP2pManager.removeGroup(sWifiP2pChannel, sActionListener); 1714 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1715 assertTrue(waitForP2pListenerCallbackCalled(p2pListener, p2pListener.ON_GROUP_REMOVED, 1716 lockWaitTimeoutMs)); 1717 1718 WifiP2pGroupList persistentGroups = getPersistentGroups(); 1719 assertNotNull(persistentGroups); 1720 assertEquals(1, persistentGroups.getGroupList().size()); 1721 resetResponse(MY_RESPONSE); 1722 p2pListener.reset(); 1723 final int firstNetworkId = persistentGroups.getGroupList().get(0).getNetworkId(); 1724 ShellIdentityUtils.invokeWithShellPermissions(() -> { 1725 sWifiP2pManager.deletePersistentGroup(sWifiP2pChannel, 1726 firstNetworkId, 1727 sActionListener); 1728 assertTrue(waitForServiceResponse(MY_RESPONSE)); 1729 assertTrue(waitForP2pListenerCallbackCalled(p2pListener, 1730 p2pListener.ON_PERSISTENT_GROUPS_CHANGED, lockWaitTimeoutMs)); 1731 }); 1732 1733 sWifiP2pManager.unregisterWifiP2pListener(p2pListener); 1734 } 1735 } 1736 1737 @RequiresFlagsEnabled(Flags.FLAG_ANDROID_V_WIFI_API) 1738 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) 1739 @Test testP2pWhenInfraStaDisabled()1740 public void testP2pWhenInfraStaDisabled() throws Exception { 1741 if (!sWifiManager.isD2dSupportedWhenInfraStaDisabled()) { 1742 // skip the test if feature is not supported. 1743 return; 1744 } 1745 UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 1746 WifiManagerTest.Mutable<Boolean> isQuerySucceeded = 1747 new WifiManagerTest.Mutable<Boolean>(false); 1748 boolean currentD2dAllowed = false; 1749 boolean isRestoreRequired = false; 1750 long now, deadline; 1751 try { 1752 uiAutomation.adoptShellPermissionIdentity(); 1753 WifiManagerTest.Mutable<Boolean> isD2dAllowed = 1754 new WifiManagerTest.Mutable<Boolean>(false); 1755 sWifiManager.queryD2dAllowedWhenInfraStaDisabled(mExecutor, 1756 new Consumer<Boolean>() { 1757 @Override 1758 public void accept(Boolean value) { 1759 synchronized (mLock) { 1760 isD2dAllowed.value = value; 1761 isQuerySucceeded.value = true; 1762 mLock.notify(); 1763 } 1764 } 1765 }); 1766 synchronized (mLock) { 1767 now = System.currentTimeMillis(); 1768 deadline = now + DURATION; 1769 while (!isQuerySucceeded.value && now < deadline) { 1770 mLock.wait(deadline - now); 1771 now = System.currentTimeMillis(); 1772 } 1773 } 1774 assertTrue("d2d allowed query fail", isQuerySucceeded.value); 1775 currentD2dAllowed = isD2dAllowed.value; 1776 isRestoreRequired = true; 1777 // Now force wifi off and d2d is on 1778 sWifiManager.setWifiEnabled(false); 1779 sWifiManager.setD2dAllowedWhenInfraStaDisabled(true); 1780 // Run a test to make sure p2p can be used. 1781 testRequestDiscoveryState(); 1782 // Set d2d to false and check 1783 sWifiManager.setD2dAllowedWhenInfraStaDisabled(false); 1784 // Make sure WifiP2P is disabled 1785 waitForBroadcasts(MySync.P2P_STATE); 1786 assertThat(WifiP2pManager.WIFI_P2P_STATE_DISABLED).isEqualTo(MY_SYNC.expectedP2pState); 1787 } finally { 1788 if (isRestoreRequired) { 1789 sWifiManager.setD2dAllowedWhenInfraStaDisabled(currentD2dAllowed); 1790 } 1791 uiAutomation.dropShellPermissionIdentity(); 1792 } 1793 } 1794 } 1795