Use a device as a webcam

For devices running Android 14-QPR1 or higher, Android supports using the device as a USB webcam. Android devices supporting this feature are advertise as a UVC device, which lets a wide range of USB hosts with different operating systems (for example, Linux, macOS, Windows, and ChromeOS) use the device's camera as a webcam. The DeviceAsWebcam service supports this feature to use the device as a webcam.

DeviceAsWebcam service

The DeviceAsWebcam service in AOSP includes a preview activity (DeviceAsWebcamPreview.java) that lets users frame the scene. The preview activity lets the user do the following:

  • Preview how the webcam feed will look on the host machine before streaming starts.

  • Customize the webcam feed sent to the host in the following ways:

    • Selecting the camera to stream, front or back.
    • Selecting the zoom level using a slider or buttons.
    • Tapping a particular region of the preview to focus or remove the focus on a region.

The preview activity works with general accessibility features on Android such as TalkBack, Switch Access, and Voice Access.

webcam feed streamed to host

Figure 1. Webcam feed being streamed to a host with preview controlling the feed.

Architecture

The architecture to support using a device as a webcam is illustrated in Figure 2. The following describes the interaction flow of the DeviceAsWebcam service with the rest of the Android framework:

  1. The user selects the USB webcam option in the Settings app.
  2. The Settings app sends a binder call to system_server through the UsbManager class informing it that FUNCTION_UVC is selected.
  3. The system server does the following:
    1. Informs the USB gadget HAL to retrieve the UVC gadget function through a setUsbFunctions HAL interface call.
    2. Informs the USB gadget HAL to configure the UVC gadget driver using ConfigFs.
  4. Upon receiving a callback from the gadget HAL, system_server sends a broadcast to the framework to be picked up by the DeviceAsWebcam service.
  5. The USB gadget driver starts the webcam stream upon receiving configuration commands from the host through V4L2 nodes at /dev/video*.

device as webcam architecture

Figure 2. DeviceAsWebcam architecture.

Implementation

This section describes how to support using an Android device as a webcam.

Kernel support

For Android 14 or higher, the Generic Kernel Image (GKI) enables the UVC gadget driver by default (see details in AOSP patch).

Support UVC in Gadget HAL

Starting with Android 14, the UVC function is included in the GadgetFunction.aidl HAL interface. For the Gadget HAL, the UVC gadget is mounted to ConfigFS in the same way as other ConfigFS functions such as MTP or ADB.

To implement the Gadget HAL, make modifications to mount the UVC function to ConfigFS. The following is an example snippet of a Gadget HAL implementation supporting the UVC function:

UsbGadget::setCurrentUsbFunctions(long functions) {
   ...
   // Existing functions
   if ((functions & GadgetFunction::MTP) != 0) {
       ...
       linkFunction("ffs.mtp"); // Mount to ConfigFS
       ...
   }
   ...
   // UVC function follows the same pattern!
   if ((functions & GadgetFunction::UVC) != 0) {
       ...
       linkFunction("uvc.0"); // Mount to ConfigFS
       ...
   }
   ...
}

When the device is acting as a webcam, ensure the USB gadget HAL is advertising the proper VID/PID combinations.

Because all UVC logic is in either vendor init or in the DeviceAsWebcam service, no UVC specific logic, other than symlinking the UVC function to ConfigFS, is required in the Gadget HAL.

For further guidance on implementation, see the following sample code in AOSP:

Set up ConfigFS with UVC configurations

To inform the UVC gadget driver which formats, sizes, and frame rates are supported by the Android webcam, set up ConfigFS with UVC configurations. For more information, see the upstream Linux documentation on the ConfigFS UVC gadget ABI.

The following is an example of how vendor init can set up the UVC gadget driver (code snippet in AOSP):

# uvc function
   mkdir /configfs_path/functions/uvc.0
   write /configfs_path/functions/uvc.0/function_name "Android Webcam"
   write /configfs_path/functions/uvc.0/streaming_maxpacket 3072
   # setup control params
   mkdir /configfs_path/functions/uvc.0/control/header/h
   symlink /configfs_path/functions/uvc.0/control/header/h \
                /configfs_path/functions/uvc.0/control/class/fs/h
   symlink /configfs_path/functions/uvc.0/control/header/h \
                /configfs_path/functions/uvc.0/control/class/ss/h
   # advertise 1080p resolution for webcam encoded as mjpeg
   mkdir /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/wHeight 1080
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/wWidth 1920
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwMaxVideoFrameBufferSize 4147200
   # advertise 30 fps support for 1080p.
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwDefaultFrameInterval 333333
   write /configfs_path/functions/uvc.0/streaming/mjpeg/m/1080p/dwFrameInterval "333333"
   # setup streaming params
   mkdir /configfs_path/functions/uvc.0/streaming/header/h
   symlink /configfs_path/functions/uvc.0/streaming/mjpeg/m \
                /configfs_path/functions/uvc.0/streaming/header/h/m
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /configfs_path/functions/uvc.0/streaming/class/fs/h
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /configfs_path/functions/uvc.0/streaming/class/hs/h
   symlink /configfs_path/functions/uvc.0/streaming/header/h \
                /config/usb_gadget/g1/functions/uvc.0/streaming/class/ss/h
   # ...

This snippet sets up the UVC gadget driver to advertise a 1080p MJPEG stream at 30 fps. These capabilities are communicated to the USB host when it queries supported resolutions and frame rates.

The following are general guidelines for selecting the configurations the webcam advertises:

  • The two stream formats supported by the DeviceAsWebcam service are MJPEG and uncompressed YUYV.
  • USB 2.0 supports 480 Mbps (60 MBps) transfer of data. This means that at 30 fps, each frame must have a maximum size of 2 MB; and at 60 fps, a maximum size of 1 MB.
    • Uncompressed streams (YUYV): At 30 fps, the maximum supported frame size is 720p because YUYV is 2 bytes per pixel.
    • Compressed MJPEG streams: Assuming a 1:10 compression ratio from YUV, USB 2.0 can support 4K (1.18 MB per frame).
  • Primary front and back camera devices must support all the frame sizes that are advertised. This is because the user can switch between camera IDs using the preview UI. For MJPEG streams, we recommend vendors advertise 480p (640 x 480), 720p (1280 x 820) and 1080p (1920 x 1080) frame sizes because these are sizes commonly used by host apps.
  • Primary front and back camera devices must support all frame rates that are advertised. We strongly recommend vendors support 30 fps.

For an example of adding webcam stream configurations (ConfigFS), see AOSP sample patch.

Enable webcam in the build

To enable the DeviceAsWebcam service, you must set the ro.usb.uvc.enabled system property to true in the device.mk file.

# Enable UVC support
PRODUCT_VENDOR_PROPERTIES += \
    ro.usb.uvc.enabled=true

When this system property is enabled, a Webcam option appears in the Settings app under USB preferences as shown in Figure 3. When the option is selected, the Android device appears as a USB webcam to the host device.

Figure 3. USB preferences in Settings app.

You can also set the device to the USB webcam function through ADB using this command:

adb shell svc usb setFunctions uvc

Consider power and thermal concerns

Webcam operations means that a device's camera might be on for multiple hours a day, so we recommend taking measures to ensure that the power consumption and thermal of the device remains under certain limits. The following are recommended solutions to keep power consumption under limits:

  • For better power performance from the camera HAL, enable STREAM_USE_CASE_VIDEO_CALL in the DeviceAsWebcam service.
  • If power is a concern even with STREAM_USE_CASE_VIDEO_CALL enabled, the DeviceAsWebcam service provides an option to further decrease power consumption by using physical streams. You can use runtime resource overlays (RROs) to specify which physical camera to use. Physical streams significantly drop the video quality and lead to a confusing UX, so use this solution only as a last resort. Optimizing STREAM_USE_CASE_VIDEO_CALL is the preferred solution to power concerns. For more information on RROs supported by the DeviceAsWebcam service, see readme.md.

    The following is an example of an RRO set up to use physical camera ID 3 instead of logical camera ID 0. For an example in AOSP, see DeviceAsWebcamRaven.

    // For logical camera id 0 - use physical camera id 3
    {"0": {"3" : "UW"}}
    

Verification

To test your implementation of the DeviceAsWebcam service on your device, use the following tests:

  • CTS verifier test webcam: Test that formats, sizes, and frame rates are supported by the device.
  • Manual tests: Test that the webcam feature works with a variety of host apps on a variety of host operating systems.

Known issues

The following are known issues for the DeviceAsWebcam service: