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
-
Connect your Pixel 9a via USB
-
Enable USB debugging in Developer Options
-
Authorize the ADB connection on your device
-
Verify ADB connection:
adb devicesYou should see your device serial with "device" status.
-
Verify root access:
adb shell su -c idShould 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
- Transfer
camswapper-hal-hook-v1.zipto your device - Open Magisk app → Modules tab → "Install from storage"
- Select
camswapper-hal-hook-v1.zip - Wait for installation to complete
- Tap "Reboot"
Option B: Flash via KernelSU Manager
- Transfer
camswapper-hal-hook-v1.zipto your device - Open KernelSU app → Modules tab → "+" button
- Select
camswapper-hal-hook-v1.zip - Wait for installation to complete
- Tap "Reboot"
Option C: Flash via Custom Recovery (TWRP)
- Push the ZIP to your device:
adb push camswapper-hal-hook-v1.zip /sdcard/ - Boot into recovery
- Flash the ZIP
- 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
-
Check the wrap property is set correctly:
adb shell getprop wrap.android.hardware.camera.provider@2.7-service-googleExpected output:
LD_PRELOAD=/data/adb/modules/camera-hook/libcamera_hook.so -
Check the camera provider process is running:
adb shell pidof android.hardware.camera.provider@2.7-service-googleShould return a PID number.
-
Verify
libcamera_hook.sois 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. -
Check hook initialization logs:
adb logcat -d -s CameraHookShould show hook initialization messages.
-
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
- Install the CamSwapper app on your device
- Open the app and navigate to HAL Mode settings
- Toggle "Enable HAL Mode"
- Select source mode: File or RTSP
- For File mode: select your video file (place it in
/data/local/camera_magic/video.mp4or update config manually) - 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
-
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" -
Open any camera app (Google Camera, Instagram, Telegram, etc.)
-
The camera preview should display your virtual video instead of the real camera feed.
-
Check hook logs for frame injection:
adb logcat -s CameraHookShould show FPS counts and frame injection messages.
Step 6: Test RTSP Stream (Optional)
-
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" -
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.
-
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 CameraHookfor error messages
No Virtual Feed Showing
- Verify
enabled=1in 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.sois loaded in the provider process
SELinux Denials
- Check
adb shell dmesg | grep "avc: denied" - Ensure
sepolicy.ruleis 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