Develop

Use Meta Quest Scriptable Testing Services to Enable E2E Testing

Updated: Oct 6, 2026
On-device automated end-to-end (E2E) testing can be challenging because device features can interfere with tests. For example, a modal system dialog can prevent a test from launching. A device can also enter auto-sleep during a long performance test.
Meta Quest Scriptable Testing services let you disable these features so that tests run reliably. They can reduce or eliminate the manual steps needed to configure a device and reset it between runs. This streamlines hardware setup and helps developers test efficiently at scale.

Use Cases

You can use simple ADB commands to perform the following actions without putting on the headset:
  • Set and get properties:
    • Enable or disable certain modal (blocking) system dialogs, including the Allow USB Debugging and Allow connected device to access files dialogs.
    • Enable or disable the boundary.
    • Enable or disable auto-sleep.
  • Reset a device:
    • Factory reset the device.
    • Configure Wi-Fi.
    • Log in with a test user.
DEVELOPER USE ONLY
Use of these features by non-developers, or for purposes other than development of Meta Quest software, is not supported, and attempting to do so could degrade the lifetime of the headset.

Prerequisites

  • Install ADB and fastboot on your development workstation. If they are not already installed, install the appropriate Android SDK Platform Tools⁠ package.
  • Create a test user if you do not already have one. Record the test user’s email, password, and PIN.
  • Set up your device with a single test user. Multi-user flows, and non-test user developer accounts, are not recommended for use with E2E testing. Devices can be setup by one of the following methods:

Usage

Use the following ADB commands on a computer connected to your device. This approach works well for running automated tests locally or managing a device lab at scale.
The testing services provide two main sets of commands:
  • GET_PROPERTY and SET_PROPERTY: Control services that can interfere with automated testing.
  • WIPE_DEVICE and SETUP_FOR_TEST: Reset the device to a known state so that sequential tests do not interfere with one another.
The following sections describe how to use each set of commands.

Controlling services that interfere with automation (SET/GET_PROPERTY)

The SET_PROPERTY and GET_PROPERTY commands execute synchronously. SET_PROPERTY reports whether the command succeeded and includes an error message if it failed. GET_PROPERTY returns a bundle that contains the current values of all supported properties.
// Disable three system features that would otherwise interfere with an E2E test.
// The Store PIN associated with the logged in account is required.
> adb shell content call --uri content://com.oculus.rc --method SET_PROPERTY \
   --extra 'disable_guardian:b:true'  \
   --extra 'disable_dialogs:b:true'   \
   --extra 'disable_autosleep:b:true' \
   --extra 'PIN:s:1234'
Result: Bundle[{Success=true}]

// Query the currently set property values.
> adb shell content call --uri content://com.oculus.rc --method GET_PROPERTY
Result: Bundle[{disable_guardian=true, disable_dialogs=true, disable_autosleep=true}]

// Simulate putting on the headset by triggering the proximity sensor.
> adb shell am broadcast -a com.oculus.vrpowermanager.prox_close

// Install your APK and run your test. For example:
> adb install /path/to/my_app.apk
> adb shell am start -S com.my.app.packagename/.MainTestActivity

// Re-enable the system features.
> adb shell content call --uri content://com.oculus.rc --method SET_PROPERTY \
   --extra 'disable_guardian:b:false'  \
   --extra 'disable_dialogs:b:false'   \
   --extra 'disable_autosleep:b:false' \
   --extra 'PIN:s:1234'

// Simulate taking the headset off by triggering the proximity sensor.
> adb shell am broadcast -a com.oculus.vrpowermanager.prox_far
Re-enable any disabled properties after your test to avoid side effects such as screen burn-in and rapid battery drain. A factory reset restores these properties to their default values, but a reboot does not.

Wiping the device to prepare for testing (WIPE_DEVICE/SETUP_FOR_TEST)

For repeatable E2E tests, wipe the device before a test run so that the test starts from a known state. This prevents state from a previous run from affecting the next one. The following example chains WIPE_DEVICE and SETUP_FOR_TEST:
// Factory reset the device. The Store PIN associated with the logged in account
// is required.
> adb shell content call --uri content://com.oculus.rc --method WIPE_DEVICE \
    --extra 'PIN:s:1234'
Result: Bundle[{Message=WIPE_DATA Pending, Success=true}]

// Wait for the device to restart.

// Log in with a test user and connect to the local Wi-Fi network.
> adb shell content call --uri content://com.oculus.rc --method SETUP_FOR_TEST \
    --extra 'WIFI_SSID:s:my_wifi_ssid' \
    --extra 'WIFI_PWD:s:my_wifi_password' \
    --extra 'WIFI_AUTH:s:WPA' \
    --extra 'EMAIL:s:my_test_user@tfbnw.net' \
    --extra 'PWD:s:my_test_user_password'

// Wait for the device to restart.

// Optional: Disable auto-sleep. As part of the SETUP_FOR_TEST call above,
// disable_guardian and disable_dialogs are already true.
> adb shell content call --uri content://com.oculus.rc --method SET_PROPERTY \
   --extra 'disable_autosleep:b:true' \
   --extra 'PIN:s:1234'
Result: Bundle[{Success=true}]

// Install your APK and run your test. For example:
> adb install /path/to/my_app.apk
> adb shell am start -S com.my.app.packagename/.MainTestActivity

// Repeat the process for your next test, starting with WIPE_DEVICE.

Python Helper Script for Device Wipe and Setup

The following Python helper script combines the ADB commands from the previous flow into one method call. Call setupDeviceForTest() with the appropriate parameters to complete these steps:
  1. Call WIPE_DEVICE.
  2. Wait for the device to reboot.
  3. Call SETUP_FOR_TEST.
  4. Wait for the device to reboot.
After the method returns, the device is ready for you to install your APK and run your test.
import subprocess
import time

# Prepare the connected device for testing by factory resetting it, connecting it
# to Wi-Fi, and logging in with a test user.
#
# testUserEmail and testUserPassword: Credentials for an existing Meta test user
#   (https://developers.meta.com/vr/resources/test-users/). The device logs in
#   with this user after the reset. These email addresses usually use the @tfbnw.net
#   domain.
#
# testUserPin: If the device has a logged-in user, provide that user's Store PIN.
#   The method ignores this parameter when the device is logged out.
#   Note this is the currently logged-in user, which can differ from the test user #   specified above.
#
# wifiSSID and wifiPassword: Valid credentials for an in-range Wi-Fi network.
#
# deviceId: The device serial number. Required only when multiple headsets are
#   connected to the host machine.
def setupDeviceForTest(
    testUserEmail,
    testUserPassword,
    testUserPin,
    wifiSSID,
    wifiPassword,
    deviceId=None,
):
    # Factory reset the device to create a clean test environment. This reset is
    # required before SETUP_FOR_TEST. WIPE_DEVICE preserves ADB access after the reboot.
    result = __runAdbShell(
        f"content call --uri content://com.oculus.rc --method WIPE_DEVICE "
        f"--extra 'PIN:s:{testUserPin}'",
        deviceId,
    )
    if result.returncode == 0 and "Success=true" in result.stdout:
        __runAdbCommand("wait-for-disconnect", deviceId)
        __waitForDeviceBootCompleted(40, deviceId)
    else:
        print(
            f"WIPE_DEVICE call failed: returncode={result.returncode}; {result.stdout}; {result.stderr};"
        )
        return -1

    # Connect to Wi-Fi and log in with the test user.
    result = __runAdbShell(
        f"content call --uri content://com.oculus.rc --method SETUP_FOR_TEST "
        f"--extra 'WIFI_SSID:s:{wifiSSID}' --extra 'WIFI_PWD:s:{wifiPassword}' --extra 'WIFI_AUTH:s:WPA' "
        f"--extra 'EMAIL:s:{testUserEmail}' --extra 'PWD:s:{testUserPassword}'",
        deviceId,
    )
    if result.returncode == 0 and "Success=true" in result.stdout:
        __runAdbCommand("wait-for-disconnect", deviceId)
        __waitForDeviceBootCompleted(40, deviceId)
        __waitForDumpSys("Horizon logged in: true", 25, deviceId)
    else:
        print(
            f"SETUP_FOR_TEST call failed: returncode={result.returncode}; {result.stdout}; {result.stderr};"
        )
        return -1


# Install the specified APK and launch the app.
def installAndStartApp(apkPath, packageName, activityName, deviceId=None):
    __runAdbCommand(f"install {apkPath}", deviceId)
    __runAdbShell(f"am start -S {packageName}/{activityName}", deviceId)


def sleepHeadset(deviceId=None):
    __runAdbShell("input keyevent POWER", deviceId)


def __runShellCommand(command):
    print(f"SHELL: {command}")
    split = command.split()
    result = subprocess.run(split, capture_output=True, text=True)
    return result


def __getDeviceArg(deviceId):
    if deviceId is None:
        return " "
    else:
        return f" -s {deviceId} "


def __runAdbShell(command, deviceId):
    return __runShellCommand("adb" + __getDeviceArg(deviceId) + "shell " + command)


def __runAdbCommand(command, deviceId):
    return __runShellCommand("adb" + __getDeviceArg(deviceId) + command)


def __waitForProperty(property, maxSeconds, deviceId):
    print(f"Waiting for {property} to turn true")
    start = time.time()
    while "1" not in __runAdbShell(f"getprop {property}", deviceId).stdout:
        if time.time() - start > maxSeconds:
            raise RuntimeError(f"timed out while waiting for {property} to turn true")
        __sleep(2)
    print(f"{property} is true")


def __waitForDeviceBootCompleted(maxSeconds, deviceId):
    __runAdbCommand("wait-for-device", deviceId)
    __waitForProperty("sys.boot_completed", maxSeconds, deviceId)
    __sleep(2)


def __waitForCommand(command, targetString, maxSeconds):
    print(f"Waiting for command '{command}' to return '{targetString}'")
    start = time.time()
    while True:
        result = __runShellCommand(command)
        # Stop when the target string appears in stdout or stderr.
        if (
            result.stderr.find(targetString) >= 0
            or result.stdout.find(targetString) >= 0
        ):
            break
        # Raise an exception if the target does not appear before the timeout.
        if time.time() - start > maxSeconds:
            raise RuntimeError(
                f"timed out while waiting for command '{command}' to return '{targetString}'. \n"
                + f"STDOUT: {result.stdout} \n"
                + f"STDERR: {result.stderr} \n"
            )
        __sleep(2)
    print("Found return string: " + targetString)


def __waitForDumpSys(targetString, maxSeconds, deviceId):
    __waitForCommand(
        "adb" + __getDeviceArg(deviceId) + "shell dumpsys CompanionService",
        targetString,
        maxSeconds,
    )


def __sleep(seconds):
    print(f"SLEEP {seconds}s")
    time.sleep(seconds)

Frequently Asked Questions

Only if a dialog blocks you from launching your test with adb install and adb shell am start. These services are designed to eliminate only blocking dialogs. Other non-blocking dialogs might still appear.
If SETUP_FOR_TEST returns {Message=Login/Wifi Pending, Success=true} but the device does not restart, check the Wi-Fi and test-user login credentials. Search the device’s logcat for Skip NUX to identify the cause. For example, you might see one of these messages:
  • [Skip NUX] Failed to connect to WiFi.
  • [Skip NUX] Failed to login.
If the Wi-Fi SSID contains spaces, escape each space with a backslash.
If you use the same test user to log in dozens or hundreds of times per day, the authentication service might throttle that user. Create additional test users and rotate through them to avoid this limit.
No. The device must be provisioned.
Yes. Use the -s parameter with each ADB command to specify the target device’s serial number. Run adb devices to list the serial numbers of all connected devices.
As described in Prerequisites, enable developer mode by logging in to the device through a standard setup flow. This allows ADB to recognize the connected device. A traditional factory reset, such as fastboot erase userdata, removes this access. You must then log in again. To preserve access, reset the device with WIPE_DEVICE and immediately follow it with a valid SETUP_FOR_TEST call.

Additional Testing Resources

Quest Scriptable Testing services prepare your device for an E2E test, but they do not run or validate the test. Use a test driver or testing framework, such as one of the following options:

See Also