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