1# Better Together Connectivity Quality (BeToCQ) Test Suite
2
3Better Together Connectivity Quality (BeToCQ) is a new test tool built by
4Android to test the cross-device connectivity performance that isn't covered
5by the existing Android tests.
6
7This tool is built on the top of the Nearby Connections API. Under Nearby
8Connections, it has Android connectivity stack including Bluetooth, Wi-Fi, NFC,
9and UWB technologies.
10
11BeToCQ is designed to catch connectivity software and hardware performance
12issues by measuring detailed quality signals including the discovery, connection
13latency, transfer speed, and overall success rate.
14
15Depending on the device capabilities, the test takes two to six hours to
16complete.
17
18## Test types {:#test-types}
19
20BeToCQ consists of three parts:
21
22- Function test
23
24  The function test ensures hardware and software readiness for each radio
25  technology.
26
27- Directed test
28
29  The directed test measures performance of each wireless medium against
30  expectations. To discover the radio concurrency issue, sometimes multiple
31  mediums are enabled at the same time during the test.
32
33  The function and direct tests are the foundational tests running with
34  fixed wireless mediums. This helps isolate the issue to an individual medium
35  and makes the debugging process more straightforward.
36
37- Critical user journey (CUJ) test
38
39  The CUJ test tests the real use case. Different from function and
40  directed test, the CUJ test can use multiple radios in a more dynamic way. So the
41  debugging is typically more difficult in CUJ tests. That's why CUJ tests run as
42  the last step when the other tests have already passed.
43
44  CUJ test are implemented as the test cases defined in the `compound_test`
45  directory, and are dynamically configured based on the CUJ requirements. The
46  term `compound_test` refers to the fact that it uses multiple radios in a
47  dynamic way.
48
49  The test suite currently supports three CUJs: Quick Start, Quick Share, and eSIM
50  transfer. We plan to add more CUJs in later releases.
51
52## Device capabilities {:#device-capabilities}
53
54The exact connectivity performance depends on the device capability.
55For example, the low-cost 2 GHz-only Wi-Fi device achieves a lower speed
56than the dual-band Wi-Fi device. On the other hand, the dual-band-simultaneous
57(DBS) capable device can support a 2G infrastructure-STA connection and 5G
58device-to-device connection in parallel and thus can support higher
59device-to-device transfer speed.
60
61As a result, this test suite uses the wireless capabilities of test devices as
62inputs to customize the test case and set the right performance expectations.
63
64## Test cases {:#test-cases}
65
66In the directed and CUJ tests, depending on the device capabilities,
67test cases are defined to cover:
68
69- Different Wi-Fi concurrencies: single-channel concurrency (SCC) versus
70  multi-channel concurrency (MCC)
71- Different wireless channels: 2G, 5G, 5G DFS, and 5G indoor
72
73The test cases uses the following naming convention:
74
75```
76 ConcurrencyMode_MediumBand_MediumName_StaBand_sta_test
77```
78
79For example, `scc_indoor_5g_wfd_sta_test` means:
80
81- WLAN and Wi-Fi Direct (WFD) concurrency mode operates in the same channel.
82- Transfer medium is WFD.
83- Both STA and WFD are connected to 5G indoor channel (for example, 5180 in JP).
84
85Similarly, `mcc_5g_all_wifi_non_dbs_2g_sta_test` means:
86outmod betocq_test_suite
87
88- Transfer medium can be any 5G Wi-Fi medium.
89- STA is connected to the 2G band and the transfer medium is connected to the 5G band.
90- Device isn't capable of DBS and so it operates in MCC mode.
91
92Note that some test cases are skipped if they aren't supported by the device
93capabilities. For example:
94
95- `scc_indoor_5g_wfd_sta_test` is skipped if the device doesn't
96 support WFD group owner (GO) at the 5G indoor channel.
97
98- `mcc_5g_all_wifi_non_dbs_2g_sta_test` is skipped for DBS capable devices.
99
100Each test case runs multiple iterations to collect the following stats:
101
102- Success rate
103- Failure reason for each failed iteration
104- Discovery latency stats
105- Connection latency stats
106- Wi-Fi upgrade latency stats
107- Transfer speed stats
108
109MCC test cases run more iterations than SCC test cases.
1105G test cases transfer larger files than 2G test cases.
111
112The test cases execution depends on the device capability, so it's
113important to fill in the device capabilities section correctly in the test
114configuration file. We'll discuss this in more detail in the following sections.
115
116## Actionable test results {:#actional-test-results}
117
118Running the test is straightforward, but it can be difficult to get insights out
119of the test results and determine further action to take.
120
121BetoCQ takes three steps to address this issue:
122
123- Simplifies the test report review with the visualized test summary.
124
125- Sets the proper performance expectations based
126  on devices capabilities.  The test results are compared against the expectations
127  so that there are clear pass/failure signals.
128
129- Makes debugging job more straightforward, with the test isolating each failure
130  to a single component. The tool also provides the most likely failure
131  reasons and suggest next steps for debugging and appropriate component owner.
132
133## Prerequisites {:#test-prerequisites}
134
135*   **Environment.**
136
137    We recommend an RF shielding box or room to run the test.
138
139*   **Wi-Fi Access Point (AP) and network.**
140
141    The test AP must be a dual-band capable Wi-Fi AP with two SSIDs (one at
142    2 GHz and one at 5 GHz) with support for DFS channels. Example of
143    routers that meet the testing requirements include NETGEAR RAX50 AX5400,
144    NETGEAR RAX120 AX6000, and NETGEAR R8000b AC3200. It's ideal to use two APs
145    to support all test cases. The test AP must have the access to
146    google.com. Note that in China, this test requires an office VPN network or
147    installing a VPN app in devices.
148
149*   **Target device.**
150
151    The target device must run a userdebug image of the latest Android version,
152    for example, Android 14. **This is the device that is being validated.**
153
154*   **Source device.**
155
156    Run the suite and pass the quality bar with one source device
157    running a userdebug image of the latest Android version. We recommend a
158    model with known good connectivity performance. Some options are:
159    - A model that already passed the automated test suite as a target.
160    - A flagship model with no known major Bluetooth and Wi-Fi issues.
161    - A Google Pixel 8
162
163*   **Prepare devices.**
164
165    Before you run the automated test, prepare all devices by completing the
166    device setup processes. After the new devices are set up, connect them to
167    the internet for at least one hour to ensure each is properly configured.
168
169    Follow the instructions listed in [Google Play Protect]
170    (https://support.google.com/googleplay/answer/2812853)
171    to turn off Google Play Protect so that the test APK can run properly.
172
173    Keep the device awake while charging so that the operating system doesn't
174    suspend the test snippet process.
175
176    To avoid the strong signal issue, keep two devices at least 10 cm away. This
177    is especially important for 2G test as the 2G signal is typically stronger
178    than 5G or 6G signal.
179
180
181## Test steps {:#test-steps}
182
183Follow these steps to prepare and execute tests and review test results.
184
185### Prepare the test {:#test-prep}
186
187Prepare the following materials to be used for the tests.
188
189#### Get the test codes, tools, and configure build {:#test-codes}
190
1911.  Download the release test binary files (see release instructions) and save them
192in a local directory:
193  - `betocq_test_suite` (Linux and macOS)
194  - `betocq_test_suite_windows.zip` (Windows only)
195  - `local_mobly_runner.py`
196  - `cuj_and_test_config.yml`
197
1982. Make these two files executable (Linux and macOS only):
199
200  ```
201  chmod +x betocq_test_suite
202  chmod +x local_mobly_runner.py
203  ```
204
2053.  Check and install Python version 3.11 or later:
206    -   Check your Python 3 version number:
207
208      ```
209      python3 --version
210      ```
211
212    -   If your version is lower than Python 3.11, install Python 3.11 or later:
213
214      ```
215      sudo apt install python3
216      ```
217      Or install the latest version from
218      [python.org](https://www.python.org/downloads/windows) for Windows.
219
2204. Windows only: Download [adb](https://developer.android.com/tools/releases/platform-tools)
221   and add its path to the [`Path` environment variable](https://stackoverflow.com/questions/44272416/how-to-add-a-folder-to-path-environment-variable-in-windows-10-with-screensho).
222
223#### Configure Wi-Fi AP and test {:#config}
224
2251. Configure Wi-Fi AP channel frequency:
226
227  -   There are three Wi-Fi channels to be tested: 2437, 5180, and 5260.
228      5260 is a [DFS channel]
229        (https://en.wikipedia.org/wiki/List_of_WLAN_channels).
230
231  -   If there are two dual-band APs, all three Wi-Fi channels can be supported.
232
233
2342. Modify the test config file `cuj_and_test_config.yml` as follows:
235    -  Find device serial numbers:
236
237        ```
238        adb devices -l
239        List of devices attached
240          17011FDEE0002N  device usb:1-1 product:raven model:Pixel_6_Pro
241          R3CN90YNAR      device usb:1-2 product:p3sksx model:SM_G998N
242        ```
243
244        In this example, the source device is 17011FDEE0002N and the target
245        device is R3CN90YNAR.
246
247    -  Specify the target and source device serial numbers:
248
249        ```
250        - serial: "17011FDEE0002N"
251          role: "source_device"
252        ```
253
254        ```
255        - serial: "R3CN90YNAR"
256          role: "target_device"
257        ```
258
259    -  Specify `wifi_ssid` and `wifi_password` for each Wi-Fi channel:
260
261        ```
262          wifi_2g_ssid: "NETGEAR62-2G"
263          wifi_2g_password: "yourpassword"
264          wifi_5g_ssid: "NETGEAR62-5G-1"
265          wifi_5g_password: "yourpassword"
266          wifi_dfs_5g_ssid: "ASUS_5G"
267          wifi_dfs_5g_password: "yourpassword"
268        ```
269
270        Where `wifi_2g_ssid` is for the channel of 2437, `wifi_2g_ssid` is for
271        the channel of 5180 and `wifi_dfs_5g_ssid` is for the channel of 5260.
272
273        Leave `wifi_password` as an empty string `""` if it's an open network.
274
275    - Split the test into two runs if the required channels can't be supported
276      at the same time:
277
278      1. In the first run, define 2G and 5G SSID but leave the 5G DFS SSID to an empty
279         string `""` so that the 5G DFS test cases are skipped.
280      2. In the second run, define the 5G DFS SSID but leave the 2G and 5G SSID as empty
281         strings to cover the 5G DFS test case.
282
2833. Configure device capabilities for both source and target devices.
284
285      For example, the following configuration means the device uses Wi-Fi
286      chipset WCN6710, and supports two spatial streams with the maximum PHY rate of
287      2402 Mbps (2x2, 11AX, 160 MHz) at 5G and 287 Mbps (2x2, 11AX,
288      20 MHz) at 2G. This device doesn't support STA + WFD concurrency in DBS mode.
289      It doesn't support starting WFD group owner mode at an STA-associated DFS or
290      indoor channel.
291
292      ```
293        wifi_chipset: "wcn6710"
294        # The max number of spatial streams
295        max_num_streams: 2
296        # The max PHY rate at 5G, in Mbps
297        max_phy_rate_5g_mbps: 2402
298        # The max PHY rate at 2G, in Mbps
299        max_phy_rate_2g_mbps: 287
300        # if the device supports 5G Wi-Fi
301        supports_5g: True
302        # if the device supports DBS in STA and Wi-Fi Direct concurrency mode
303        supports_dbs_sta_wfd: False
304        # The max number of spatial streams in DBS mode.
305        max_num_streams_dbs: 1
306        # if the device supports to start WFD group owner at a STA-associated DFS channel
307        enable_sta_dfs_channel_for_peer_network: False
308        # if the device supports to start WFD group owner at a STA-associated indoor channel
309        enable_sta_indoor_channel_for_peer_network: False
310      ```
311
312      For the last two parameters, review `config_wifiEnableStaDfsChannelForPeerNetwork`
313      and `config_wifiEnableStaIndoorChannelForPeerNetwork` in the Wi-Fi device
314      overlay file [`config.xml`] (https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Wifi/service/ServiceWifiResources/res/values/config.xml).
315
316      Check with the Wi-Fi engineering team about device capabilities details.
317
318
319### Run the test {:#run-test}
320To run the test on Linux directly from AOSP repo:
321
322  - Refer to release instructions below to set up the build environment.
323
324    ```
325    source build/envsetup.sh
326    lunch aosp_arm-trunk_staging-eng
327    ```
328
329  - Run the test with atest:
330
331    ```
332    atest -v betocq_test_suite -- --config <local_testbed_directory>/cuj_and_test_config.yml --testbed Quickstart
333    ```
334
335To run the test on Linux and macOS with test binary, run the following commands from the local
336directory:
337
338  ```
339  python3 local_mobly_runner.py -p ./betocq_test_suite -tb Quickstart -i --novenv -c cuj_and_test_config.yml
340  ```
341
342Note that `Quickstart` is the CUJ test name and there are
343a few other supported CUJ tests listed in `cuj_and_test_config.yml`.
344
345If there are more than two devices connected to USB ports, specify the device
346serial number explicitly:
347
348  ```
349  python3 local_mobly_runner.py -p ./betocq_test_suite -tb Quickstart -i --novenv -s <serial1>,<serial2> -c cuj_and_test_config.yml
350  ```
351
352Note that no space is allowed between
353two device serial numbers in the above commafnd.
354
355To run the test on Windows:
356
357  ```
358  python3 local_mobly_runner.py -p ./betocq_test_suite_windows.zip -tb Quickstart -i -c cuj_and_test_config.yml
359  ```
360
361### Check the test result and debug failure {:#check-result}
362
3631.  Verify that these lines appear at the end of the test console output:
364
365  ```
366  Artifacts are saved in <TestResultDirectory>
367  Test summary saved in <TestResultDirectory>/test_summary.yaml
368  ```
369
370    Where `<TestResultDirectory>` is something like
371    `/tmp/logs/mobly/<CujTestName>/<TestDateTime>`.
372
3732.  Use Result Uploader to upload the artifact folder to Google's result storage
374  service so that the test results are visualized. The latest version of the tool
375  and instructions are provided in the
376 [results_uploader](https://cs.android.com/android/platform/superproject/main/+/main:tools/test/mobly_extensions/tools/results_uploader/).
377    -   If this is your first time using the tool, file an issue with Google to
378        get onboarded.
379    -   Once you upload the artifacts, a link is displayed in the console
380        output. Click the link, then click **betocq_test_suite** to display
381        a dashboard view of your test results.
382
3833.  Click **MoblyTest** to display the overall test results.
384    -   Review the source and target device capability summary.
385    -   Review the completed function test result summary.
386    -   Review the completed directed and CUJ result summary.
387
3884. If the test passes, no further action is required.
389
3905.  Click each test case (for example, `test_scc_5g_wfd_sta`) to display the
391   status of each iteration under **Repeats**.
392    -   Green squares indicate passed tests, red squares indicate failed tests.
393
3946. If the test fails, follow the following steps to triage the results:
395   1. For each failed test case:
396
397      - Review the test case details including the transfer medium, concurrency
398        mode, the channel bands of STA, and the transfer medium.
399
400      - Check if the device capabilities are configured correctly.
401
402      - Review the failed iterations and reasons. Follow the debugging tips to
403        triage and work with the internal engineering team.
404
405   2. Click the failed (red) iterations to see the timestamp and detailed
406     failure signatures. Here is the list of failure signatures:
407      - Wi-Fi STA connection failure signature:
408
409          ```
410          Failed to connect to SSID
411          ```
412          or
413
414          ```
415          Failed to remove networks
416          ```
417      - Discovery failure signature:
418
419          ```
420          Timed out after waiting 30.0s for event "onEndpointFound" triggered by startDiscovery
421          ```
422      - BT connection failure signature:
423
424          ```
425          com.google.android.gms.common.api.ApiException: 8007: STATUS_RADIO_ERROR
426          at com.google.android.nearby.mobly.snippet.connection.ConnectionsClientSnippet.requestConnection(
427          ```
428      - Wi-Fi medium upgrade failure signature:
429
430          ```
431          Timed out after waiting 25.0s for event "onBandwidthChanged" triggered by requestConnection
432          ```
433      - Transfer failure signature:
434
435          ```
436          Timed out after 110.0s waiting for an "onPayloadTransferUpdate" event
437          ```
438
439      - Failure signature due to the GMS updates, which repeats a few times before the test exits:
440
441          ```
442          test_log.INFO:
443          In send_rpc_request
444          No response from server. Check the device logcat for crashes.
445          ```
446
447          ```
448          logcat and bug report:
449          stop com.google.android.gms due to installPackage
450          ```
451   3. Review the logcat and bug report of each failing iteration on both
452    source and target sides. You can find them as boxed links under the test
453    name.
454
455   4. Search the following keywords for the related logs in the bug report:
456    `WifiP2pService`, `wpa_supplicant`, `NearbyConnections`, and `NearbyMediums`.
457
458   5. Review the Wi-Fi Direct logs in the bug report if the `WIFI_DIRECT` medium is used.
459    Check if it's a group owner or client side error when bandwidth upgrade
460    fails.
461
462      ```
463      DUMP OF SERVICE wifip2p:
464      WifiP2pMetrics:
465      mConnectionEvents:
466      connectionType=FAST, groupRole=CLIENT, freq=5745, sta freq=2437, connectivityLevelFailureCode=NONE
467      ```
468
469   6. Check the above STA frequency and P2P frequency values. If both have valid
470    values but the values are different, the device likely operates in multiple
471    channel concurrency (MCC) mode unless it supports 2G + 5G concurrency.
472    In MCC mode, firmware could have the bugs resulting in bandwidth
473    upgrade failure or transfer issues. Check with the Wi-Fi chip vendor if there
474    are any known bug fixes for MCC mode.
475
4767. To rule out the test setup issue or device issue, repeat the test with a pair
477  of known good devices (or a pair of new devices).
478    - If the failure persists, check the test setup because it likely has the
479  issue. If possible, move the test to a clean environment to rule out the
480  interference issue.
481    - If the failure disappears, DUT likely has the issue. Work with the Wi-Fi/BT
482    engineering team to resolve the device issue. This might require getting
483    help from the Wi-Fi/BT chip vendor.
484
4858. If the issue can't be resolved by the internal engineering team and there is
486  strong evidence that there might be an issue on the Google side, create an issue
487  for Google. Be sure to include all test artifacts.
488
489## Linux and Windows release instructions {:#test-codes}
490
491Skip this unless you want to release the test binary from AOSP.
492
493- Get AOSP codes from
494  [AOSP](https://cs.android.com/android/platform/superproject/+/master:platform_testing/tests/bettertogether/betocq/;l=1).
495
496- Build the test binary for Linux and macOS:
497
498  ```
499  source build/envsetup.sh
500  lunch aosp_arm-trunk_staging-eng
501  make betocq_test_suite
502  outmod betocq_test_suite
503  ```
504
505- Upload these files to a shared drive:
506
507  ```
508  tools/test/mobly_extensions/scripts/local_mobly_runner.py
509  out/host/linux-x86/nativetest64/betocq_test_suite/betocq_test_suite
510  out/host/linux-x86/nativetest64/betocq_test_suite/cuj_and_test_config.yml
511  ```
512
513- Generate the zip file for Windows execution:
514
515  ```
516  mkdir ~/betocq_windows
517  cp platform_testing/tests/bettertogether/betocq/betocq_test_suite.py ~/betocq_windows/__main__.py
518  echo mobly > ~/betocq_windows/requirements.txt
519  cp -r platform_testing/tests/bettertogether/betocq ~/betocq_windows
520  cp out/host/linux-x86/nativetest64/betocq_test_suite/*.apk ~/betocq_windows
521  cd ~/betocq_windows
522  zip -r ~/betocq_test_suite_windows.zip ./
523  ```
524
525- Upload these files to a shared drive:
526
527  ```
528  tools/test/mobly_extensions/scripts/local_mobly_runner.py
529  out/host/linux-x86/nativetest64/betocq_test_suite/cuj_and_test_config.yml
530  ~/betocq_test_suite_windows.zip
531  ```
532