#!/usr/bin/env bash # CamSwapper HAL Hook - Integration Testing Script # Tests the system-wide camera HAL hook installation and functionality # Usage: ./test_hal_wrapper.sh [DEVICE_SERIAL] # # Prerequisites: # - adb installed and in PATH # - Device connected via USB (or specify serial with argument) # - Device rooted with Magisk or KernelSU # - Root module installed (root-module/ pushed to /data/adb/modules/camera2magic/) # - Device rebooted after module installation set -euo pipefail # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Test results PASS_COUNT=0 FAIL_COUNT=0 RESULTS_LOG="test_results.log" # ADB setup ADB="adb" if [ -n "${1:-}" ]; then ADB="adb -s $1" fi log() { echo -e "$*" echo -e "$*" >> "$RESULTS_LOG" } pass() { log "${GREEN}[PASS]${NC} $*" ((PASS_COUNT++)) } fail() { log "${RED}[FAIL]${NC} $*" ((FAIL_COUNT++)) } warn() { log "${YELLOW}[WARN]${NC} $*" } # Initialize results log echo "CamSwapper HAL Hook - Integration Test Results" > "$RESULTS_LOG" echo "Date: $(date)" >> "$RESULTS_LOG" echo "=========================================" >> "$RESULTS_LOG" log "=========================================" log "CamSwapper HAL Hook - Integration Test" log "=========================================" log "" # Test 0: Device connectivity log "--- Test 0: Device Connectivity ---" if $ADB shell "echo connected" >/dev/null 2>&1; then pass "Device connected via adb" else fail "Device not connected. Check USB connection and adb authorization." log "Cannot continue without device connection." exit 1 fi # Test 1: Root access log "" log "--- Test 1: Root Access ---" ROOT_CHECK=$($ADB shell "su -c id" 2>/dev/null || true) if echo "$ROOT_CHECK" | grep -q "uid=0"; then pass "Root access available" else fail "Root access not available. Device must be rooted with Magisk or KernelSU." log "Cannot continue without root." exit 1 fi # Test 2: Module installed log "" log "--- Test 2: Root Module Installation ---" MODULE_DIR=$($ADB shell "su -c 'ls -d /data/adb/modules/camera2magic 2>/dev/null || ls -d /data/adb/modules/*camera* 2>/dev/null'" 2>/dev/null | tr -d '\r' || true) if [ -n "$MODULE_DIR" ]; then pass "Module directory found: $MODULE_DIR" # Check hook library HOOK_LIB=$($ADB shell "su -c 'ls $MODULE_DIR/libcamera_hook.so 2>/dev/null'" 2>/dev/null | tr -d '\r' || true) if [ -n "$HOOK_LIB" ]; then pass "libcamera_hook.so present in module" else fail "libcamera_hook.so NOT found in module directory" fi # Check sepolicy.rule SEPOLICY=$($ADB shell "su -c 'ls $MODULE_DIR/sepolicy.rule 2>/dev/null'" 2>/dev/null | tr -d '\r' || true) if [ -n "$SEPOLICY" ]; then pass "sepolicy.rule present in module" else warn "sepolicy.rule not found (may not be required on all devices)" fi else fail "Module directory not found in /data/adb/modules/" warn "Install the module: adb push root-module/ /data/adb/modules/camera2magic/" fi # Test 3: Wrap property set log "" log "--- Test 3: Wrap Property Configuration ---" WRAP_PROP=$($ADB shell "getprop wrap.android.hardware.camera.provider@2.7-service-google" 2>/dev/null | tr -d '\r' || true) if echo "$WRAP_PROP" | grep -q "LD_PRELOAD"; then pass "Wrap property set: $WRAP_PROP" else fail "Wrap property NOT set or empty" warn "Expected: LD_PRELOAD=/data/adb/modules/.../libcamera_hook.so" warn "Try: adb shell setprop wrap.android.hardware.camera.provider@2.7-service-google 'LD_PRELOAD=/data/adb/modules/camera2magic/libcamera_hook.so'" fi # Test 4: Config file log "" log "--- Test 4: Configuration File ---" CONFIG=$($ADB shell "su -c 'cat /data/local/camera_magic/config.txt 2>/dev/null'" 2>/dev/null | tr -d '\r' || true) if [ -n "$CONFIG" ]; then pass "Config file exists" log " Contents: $CONFIG" else warn "Config file not found at /data/local/camera_magic/config.txt" warn "Creating default config..." $ADB shell "su -c 'mkdir -p /data/local/camera_magic && echo \"enabled=0\" > /data/local/camera_magic/config.txt && chmod 644 /data/local/camera_magic/config.txt'" 2>/dev/null || true pass "Default config created" fi # Test 5: Camera provider process detection log "" log "--- Test 5: Camera Provider Process ---" PROVIDER_PID=$($ADB shell "pidof android.hardware.camera.provider@2.7-service-google" 2>/dev/null | tr -d '\r' || true) if [ -n "$PROVIDER_PID" ]; then pass "Camera provider process running (PID: $PROVIDER_PID)" # Check if hook library is loaded LOADED_LIBS=$($ADB shell "su -c 'cat /proc/$PROVIDER_PID/maps 2>/dev/null | grep libcamera_hook'" 2>/dev/null | tr -d '\r' || true) if [ -n "$LOADED_LIBS" ]; then pass "libcamera_hook.so loaded in camera provider process" else warn "libcamera_hook.so NOT detected in camera provider process maps" warn "This may be normal if the provider hasn't been restarted since module install" warn "Try rebooting the device or restarting the camera provider" fi else warn "Camera provider process not found (may not be running yet)" warn "The provider starts on-demand when a camera app is opened" fi # Test 6: SELinux status log "" log "--- Test 6: SELinux Status ---" SELINUX_STATUS=$($ADB shell "getenforce" 2>/dev/null | tr -d '\r' || true) if [ "$SELINUX_STATUS" = "Enforcing" ]; then pass "SELinux is Enforcing (policy rules are active)" elif [ "$SELINUX_STATUS" = "Permissive" ]; then warn "SELinux is Permissive (policy rules not enforced, but hook should still work)" else warn "SELinux status unknown: $SELINUX_STATUS" fi # Test 7: AVC denials check log "" log "--- Test 7: SELinux AVC Denials ---" AVC_DENIALS=$($ADB shell "su -c 'dmesg | grep \"avc: denied\" | grep -i camera | tail -5'" 2>/dev/null | tr -d '\r' || true) if [ -z "$AVC_DENIALS" ]; then pass "No camera-related AVC denials found" else warn "AVC denials detected (may need additional SELinux rules):" log "$AVC_DENIALS" fi # Test 8: Logcat hook initialization log "" log "--- Test 8: Hook Initialization Logs ---" HOOK_LOGS=$($ADB logcat -d -s CameraHook 2>/dev/null | grep -i "hook\|init\|loaded\|CameraHook" | tail -5 || true) if [ -n "$HOOK_LOGS" ]; then pass "Hook initialization logs found" log "$HOOK_LOGS" else warn "No hook initialization logs found" warn "This may be normal if the camera provider hasn't been restarted" fi # Summary log "" log "=========================================" log "Test Summary" log "=========================================" log "${GREEN}Passed: $PASS_COUNT${NC}" log "${RED}Failed: $FAIL_COUNT${NC}" log "" if [ "$FAIL_COUNT" -eq 0 ]; then log "${GREEN}All tests passed!${NC}" log "" log "Next steps:" log "1. Enable HAL mode in CamSwapper app" log "2. Set video path or RTSP URL in config" log "3. Open any camera app to verify virtual feed" log "4. Check: adb logcat -s CameraHook for frame injection logs" else log "${RED}Some tests failed. Review the output above.${NC}" log "" log "Common fixes:" log "- Reboot device after module installation" log "- Verify module is in /data/adb/modules/camera2magic/" log "- Check wrap property is set correctly" log "- Ensure SELinux policy rules are loaded" fi log "" log "Full results saved to: $RESULTS_LOG" exit "$FAIL_COUNT"