# 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:
   ```bash
   adb devices
   ```
   You should see your device serial with "device" status.

5. Verify root access:
   ```bash
   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:
```bash
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
```bash
./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:
   ```bash
   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:
   ```bash
   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:
   ```bash
   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:
   ```bash
   adb logcat -d -s CameraHook
   ```
   Should show hook initialization messages.

5. Check for SELinux denials:
   ```bash
   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:

```bash
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:
   ```bash
   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:
   ```bash
   adb logcat -s CameraHook
   ```
   Should show FPS counts and frame injection messages.

## Step 6: Test RTSP Stream (Optional)

1. Update config to RTSP mode:
   ```bash
   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:
   ```bash
   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:
```bash
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
```bash
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
```

---
