Files
CamSwapper/docs/testing-tutorial.md
T
2026-05-08 11:45:15 +02:00

6.9 KiB

CamSwapper System-Wide HAL Hook Testing Tutorial

This guide walks you through testing the system-wide camera HAL hook feature on a rooted Pixel 9a. This mode injects virtual camera feeds into all camera apps simultaneously via LD_PRELOAD, with no per-app Xposed scoping required.

Prerequisites

  • Rooted Pixel 9a (Magisk or KernelSU installed)
  • ADB (Android Debug Bridge) set up on your computer
  • camswapper-hal-hook-v1.zip — the flashable module ZIP (pre-built, in the repo)
  • A test video file (MP4, H.264/H.265/VP9) or RTSP stream URL

Step 1: Prepare the Device

  1. Connect your Pixel 9a via USB

  2. Enable USB debugging in Developer Options

  3. Authorize the ADB connection on your device

  4. Verify ADB connection:

    adb devices
    

    You should see your device serial with "device" status.

  5. Verify root access:

    adb shell su -c id
    

    Should return uid=0(root) gid=0(root) groups=0(root).

Step 2: Install the Module (ZIP Flash)

The module is packaged as a standard ZIP file that can be flashed directly in Magisk or KernelSU.

Option A: Flash via Magisk App

  1. Transfer camswapper-hal-hook-v1.zip to your device
  2. Open Magisk app → Modules tab → "Install from storage"
  3. Select camswapper-hal-hook-v1.zip
  4. Wait for installation to complete
  5. Tap "Reboot"

Option B: Flash via KernelSU Manager

  1. Transfer camswapper-hal-hook-v1.zip to your device
  2. Open KernelSU app → Modules tab → "+" button
  3. Select camswapper-hal-hook-v1.zip
  4. Wait for installation to complete
  5. Tap "Reboot"

Option C: Flash via Custom Recovery (TWRP)

  1. Push the ZIP to your device: adb push camswapper-hal-hook-v1.zip /sdcard/
  2. Boot into recovery
  3. Flash the ZIP
  4. Reboot system

Verify Installation

After reboot, check the module is recognized:

adb shell su -c "ls -la /data/adb/modules/camera-hook/"

You should see module.prop, post-fs-data.sh, service.sh, libcamera_hook.so, system.prop, sepolicy.rule, and customize.sh.

Step 3: Verify Module Installation

After the device reboots, run the included integration test script or verify manually.

Option A: Run Integration Test Script

./test_hal_wrapper.sh

This script checks prerequisites, module installation, wrap property, config file, and hook loading status.

Option B: Manual Verification

  1. Check the wrap property is set correctly:

    adb shell getprop wrap.android.hardware.camera.provider@2.7-service-google
    

    Expected output: LD_PRELOAD=/data/adb/modules/camera-hook/libcamera_hook.so

  2. Check the camera provider process is running:

    adb shell pidof android.hardware.camera.provider@2.7-service-google
    

    Should return a PID number.

  3. Verify libcamera_hook.so is loaded in the provider process:

    adb shell su -c "cat /proc/\$(pidof android.hardware.camera.provider@2.7-service-google)/maps | grep libcamera_hook"
    

    Should show the path to libcamera_hook.so.

  4. Check hook initialization logs:

    adb logcat -d -s CameraHook
    

    Should show hook initialization messages.

  5. Check for SELinux denials:

    adb shell su -c "dmesg | grep \"avc: denied\" | grep camera"
    

    Should return empty if no denials are present.

Step 4: Configure Video Source

The HAL hook reads configuration from /data/local/camera_magic/config.txt. You can configure it via the CamSwapper app or manually.

Option A: Use CamSwapper App

  1. Install the CamSwapper app on your device
  2. Open the app and navigate to HAL Mode settings
  3. Toggle "Enable HAL Mode"
  4. Select source mode: File or RTSP
  5. For File mode: select your video file (place it in /data/local/camera_magic/video.mp4 or update config manually)
  6. For RTSP mode: enter your RTSP stream URL

Option B: Manual Config File

Create or edit the config file directly via adb:

adb shell su -c "mkdir -p /data/local/camera_magic"
adb shell su -c "echo 'enabled=1' > /data/local/camera_magic/config.txt"
adb shell su -c "echo 'source_mode=file' >> /data/local/camera_magic/config.txt"
adb shell su -c "echo 'video_path=/data/local/camera_magic/test_video.mp4' >> /data/local/camera_magic/config.txt"
adb shell su -c "echo 'rtsp_url=' >> /data/local/camera_magic/config.txt"
adb shell su -c "chmod 644 /data/local/camera_magic/config.txt"

Config File Format

enabled=1          # 0=off, 1=on
source_mode=file   # file or rtsp
video_path=/data/local/camera_magic/video.mp4
rtsp_url=rtsp://192.168.1.100:554/stream

Step 5: Test the Virtual Camera

  1. Push your test video file to the device:

    adb push test_video.mp4 /data/local/camera_magic/video.mp4
    adb shell su -c "chmod 644 /data/local/camera_magic/video.mp4"
    
  2. Open any camera app (Google Camera, Instagram, Telegram, etc.)

  3. The camera preview should display your virtual video instead of the real camera feed.

  4. Check hook logs for frame injection:

    adb logcat -s CameraHook
    

    Should show FPS counts and frame injection messages.

Step 6: Test RTSP Stream (Optional)

  1. Update config to RTSP mode:

    adb shell su -c "sed -i 's/source_mode=file/source_mode=rtsp/' /data/local/camera_magic/config.txt"
    adb shell su -c "sed -i 's|video_path=.*|rtsp_url=rtsp://YOUR_RTSP_URL|' /data/local/camera_magic/config.txt"
    
  2. Restart the camera provider process to reload config:

    adb shell su -c "killall android.hardware.camera.provider@2.7-service-google"
    

    The process will restart automatically and load the new config.

  3. Open a camera app to view the RTSP stream.

Troubleshooting

Hook Not Loading

  • Verify module is in /data/adb/modules/camera-hook/
  • Check wrap property is set correctly
  • Reboot the device
  • Check adb shell dmesg | grep CameraHook for error messages

No Virtual Feed Showing

  • Verify enabled=1 in config file
  • Check video file path is correct and accessible
  • Test RTSP URL with VLC first to ensure it's reachable
  • View hook logs: adb logcat -s CameraHook
  • Verify libcamera_hook.so is loaded in the provider process

SELinux Denials

  • Check adb shell dmesg | grep "avc: denied"
  • Ensure sepolicy.rule is present in the module directory
  • Temporary test: set SELinux to Permissive with adb shell su -c setenforce 0

Camera App Crashes

  • Check logcat for crashes: adb logcat -d | grep -i crash
  • Verify video format is supported (H.264/H.265/VP9)
  • Try a lower resolution/bitrate video file

Uninstall/Disable HAL Hook

Temporary Disable

Set enabled=0 in config file:

adb shell su -c "sed -i 's/enabled=1/enabled=0/' /data/local/camera_magic/config.txt"

Restart camera provider: adb shell su -c "killall android.hardware.camera.provider@2.7-service-google"

Permanent Uninstall

adb shell su -c "rm -rf /data/adb/modules/camera-hook"
adb shell su -c "setprop wrap.android.hardware.camera.provider@2.7-service-google ''"
adb shell su -c "rm -rf /data/local/camera_magic"
adb reboot