root-pixel7a

star 2

Magisk root setup and persistence for Pixel 7a (lynx). Use this skill when rooting the device, troubleshooting root/su access, managing rootd, or recovering from boot issues. Runs on macOS and Linux.

Trac-Systems By Trac-Systems schedule Updated 2/24/2026

name: root-pixel7a description: Magisk root setup and persistence for Pixel 7a (lynx). Use this skill when rooting the device, troubleshooting root/su access, managing rootd, or recovering from boot issues. Runs on macOS and Linux.

ROOT-PIXEL7A-SKILL

Purpose

Canonical runbook for Pixel 7a (lynx) root setup and persistence.

Scope boundary

  • This file is root-only.
  • Voice/call bridge runtime is documented separately in skills/voice-bridge/SKILL.md.
  • Pixel 10 Pro (blazer) is intentionally separate and remains APatch-first (skills/root-pixel10pro/SKILL.md).

Current known-good state (2026-02-23)

  • Root method: Magisk patch on init_boot.
  • Native Magisk su path: /debug_ramdisk/su.
  • Required compatibility entrypoint for this project: /data/adb/ap/bin/su.
  • Runtime helper daemon for app integrations: rootd on 127.0.0.1:48733.
  • Validated build: BP4A.260205.001 (Android 16).

Device + build scope

OTA updates WILL break root

WARNING: Do NOT accept over-the-air (OTA) system updates on a rooted device. Any OTA update will overwrite the patched init_boot partition with a stock image, removing Magisk root entirely. The su binary, rootd daemon, and all root-dependent functionality (call audio capture, ALSA routing, default dialer override) will stop working immediately after the update reboots the device.

If an OTA update has already been applied: re-root from scratch using this runbook with a factory image matching the new build ID. The old patched image will not work — you must patch the init_boot.img from the new build's factory package.

To prevent accidental updates: Settings → System → Software updates → disable auto-download/auto-install. On a voice-only SIM with no data plan and no Wi-Fi, OTA updates cannot download, but the setting should still be disabled as a safeguard.

Non-negotiable runtime requirements

  • No screen lock: lock screen must be None or Swipe.
  • App permissions: After installing the Clawfinger APK, the human must grant these permissions on the device (Settings → Apps → Clawfinger → Permissions):
    • Microphone (record audio)
    • Phone (manage phone calls)
    • Notifications (if prompted)
  • Default dialer: Clawfinger must be default dialer. This does NOT persist across reboots — Android resets the DIALER role to the stock dialer on every reboot. Must be re-set after every reboot.
    # Set via role manager (no root needed):
    adb shell cmd role add-role-holder android.app.role.DIALER com.tracsystems.phonebridge 1
    # Or via telecom (needs root):
    adb shell '/data/adb/ap/bin/su -c "telecom set-default-dialer com.tracsystems.phonebridge"'
    # Verify:
    adb shell '/data/adb/ap/bin/su -c "telecom get-default-dialer"'
    # Must output: com.tracsystems.phonebridge
    
    Symptom if not set: Phone rings normally through Google Dialer, PhoneBridge BridgeInCallService is never bound, calls are not picked up or handled by the assistant.
  • Keep Clawfinger battery mode on Unrestricted.
  • rootd must be running: rootd does NOT auto-start after reboot. Must be manually started after every reboot.
  • Keep compatibility su path file valid:
    • /data/adb/ap/su_path must contain /data/adb/ap/bin/su.

Post-reboot recovery (REQUIRED after every reboot)

After every reboot, three things break and must be fixed manually:

  1. DIALER role resets — Android resets android.app.role.DIALER to the stock dialer.
  2. rootd is not running — The rootd daemon does not auto-start. Without it, RootShellRuntime cannot execute any root commands (tinyplay, tinymix, tinycap all fail).
  3. /data/adb/ is inaccessible — Magisk enforces /data/adb/ as drwx------ (700, root only). The app cannot directly access /data/adb/ap/bin/su or /data/adb/service.d/phonebridge-tiny*. Only rootd (running as root) or /data/local/tmp/su (symlink to /debug_ramdisk/su) can bootstrap root access.

Symptom if rootd is not running: Logs show root shell unavailable: no_root_shell:rootd:code=126:error=ConnectException...ECONNREFUSED | /data/adb/ap/bin/su:code=126:error=IOException...Permission denied. No greeting is played, no audio capture, no tinymix routing — the call is completely silent.

Fix all three after every reboot:

adb wait-for-device
# 1) Re-set default dialer
adb shell cmd role add-role-holder android.app.role.DIALER com.tracsystems.phonebridge 1
# 2) Start rootd (must use /debug_ramdisk/su since /data/adb/ is inaccessible)
adb shell '/debug_ramdisk/su -c "nohup /system/bin/sh /data/adb/service.d/phonebridge-rootd.sh > /dev/null 2>&1 &"'
# 3) Verify
adb shell '/debug_ramdisk/su -c "telecom get-default-dialer"'
# Must output: com.tracsystems.phonebridge
echo "CMD_B64:aWQ=" | adb shell "nc 127.0.0.1 48733"
# Must output: uid=0(root) ... __PB_EXIT__:0

Root provisioning (Magisk) deterministic runbook

0) Create temporary local workspace

mkdir -p root-work rootd

1) Preflight gate (must pass before flashing)

adb wait-for-device
adb devices
adb shell getprop ro.product.device
adb shell getprop ro.build.id
adb shell getprop ro.boot.slot_suffix
adb reboot bootloader
fastboot getvar unlocked 2>&1
fastboot getvar current-slot 2>&1

Pass criteria:

  • ro.product.device is lynx
  • build is expected (BP4A.260205.001 for this runbook)
  • unlocked: yes
  • current slot is reported (a or b)

2) Prepare exact matching factory package

HUMAN ACTION REQUIRED: Download matching factory zip from https://developers.google.com/android/images to root-work/.

cd root-work
unzip -o lynx-*.zip
unzip -o lynx-*/image-*.zip -d image
ls -l image/boot.img image/init_boot.img image/vbmeta.img image/vendor_boot.img image/vendor_kernel_boot.img

Pass criteria:

  • all listed images exist in root-work/image/.

3) Patch stock init_boot.img with Magisk (scripted)

Primary path:

skills/root-pixel7a/bin/magisk_patch_init_boot.sh \
  --init-boot-img root-work/image/init_boot.img \
  --out-img root-work/patched-init-boot-magisk.img \
  --apk root-work/magisk/Magisk-v30.6.apk

Notes:

  • If --apk is omitted, the script downloads latest release and prefers Magisk-v*.apk (not app-debug.apk).
  • Output image is always root-work/patched-init-boot-magisk.img.

4) Flash patched init_boot with guard auto-recovery

skills/root-pixel7a/bin/magisk_flash_init_boot_guarded.sh \
  --patched-img root-work/patched-init-boot-magisk.img \
  --stock-init-boot root-work/image/init_boot.img

If instability is detected, the guard script restores stock init_boot_a and init_boot_b automatically.

5) Install full Magisk app (manager)

adb install -r root-work/magisk/Magisk-v30.6.apk

Validation:

adb shell 'dumpsys package com.topjohnwu.magisk | grep -E "versionName=|versionCode="'
# Expect versionCode around 30600 for v30.6; not versionCode=1 stub package

6) Create required /data/adb/ap/bin/su compatibility path (link + wrapper)

Project runtime expects /data/adb/ap/bin/su, while Magisk native path is /debug_ramdisk/su.

Apply compatibility chain:

# 1) Link `/data/local/tmp/su` -> `/debug_ramdisk/su`
adb shell 'ln -sfn /debug_ramdisk/su /data/local/tmp/su'

# 2) Wrapper at `/data/adb/ap/bin/su` to preserve CLI args (`-c`, etc.)
cat > root-work/su-wrapper.sh <<'SH'
#!/system/bin/sh
exec /data/local/tmp/su "$@"
SH
adb push root-work/su-wrapper.sh /data/local/tmp/phonebridge-su-wrapper.sh

# 3) Install wrapper and su_path using native Magisk su
adb shell '/debug_ramdisk/su -c "mkdir -p /data/adb/ap/bin /data/adb/ap"'
adb shell '/debug_ramdisk/su -c "cp /data/local/tmp/phonebridge-su-wrapper.sh /data/adb/ap/bin/su && chmod 755 /data/adb/ap/bin/su"'
adb shell '/debug_ramdisk/su -c "echo /data/adb/ap/bin/su > /data/adb/ap/su_path && chmod 644 /data/adb/ap/su_path"'

Validation:

adb shell '/data/adb/ap/bin/su -c id'
adb shell '/data/adb/ap/bin/su -v'
adb shell '/debug_ramdisk/su -c id'

Pass criteria:

  • all three return success.

Root runtime architecture (required)

Why rootd is required

  • App sandbox cannot directly run su in all contexts.
  • RootShellRuntime must use rootd first, then fallback paths.

rootd install locations

  • /data/adb/service.d/phonebridge-root-handler.sh
  • /data/adb/service.d/phonebridge-rootd.sh

rootd local staging (temporary)

  • Create temporary rootd/ during setup.
  • If scripts already exist on device, pull them first (source of truth).
  • If scripts are missing, create bootstrap templates:

rootd/phonebridge-root-handler.sh

#!/system/bin/sh
line="$(cat)"
case "$line" in
  CMD_B64:*) cmd_b64="${line#CMD_B64:}" ;;
  *) echo "invalid_request"; echo "__PB_EXIT__:2"; exit 0 ;;
esac

cmd="$(echo "$cmd_b64" | base64 -d 2>/dev/null)"
if [ -z "$cmd" ]; then
  cmd="$(echo "$cmd_b64" | toybox base64 -d 2>/dev/null)"
fi
[ -z "$cmd" ] && { echo "decode_failed"; echo "__PB_EXIT__:3"; exit 0; }

case "$cmd" in
  id|echo*|pm\ grant*|appops\ set*|cmd\ appops*|settings*|getprop*|setprop*|dumpsys*|ls*|cat*|rm*|mount*|ps*|kill*|pkill*|chmod*|chown*|chcon*|cp*|mv*|mkdir*|touch*|/data/adb/service.d/phonebridge-tinycap*|/data/adb/service.d/phonebridge-tinyplay*|/data/adb/service.d/phonebridge-tinymix*|/data/adb/service.d/phonebridge-tinypcminfo*|am\ *)
    output="$(/system/bin/sh -c "$cmd" 2>&1)"; code=$? ;;
  *)
    output="blocked_command"; code=126 ;;
esac

printf '%s\n' "$output"
printf '__PB_EXIT__:%d\n' "$code"

rootd/phonebridge-rootd.sh

#!/system/bin/sh
PORT=48733
HANDLER=/data/adb/service.d/phonebridge-root-handler.sh
[ ! -x "$HANDLER" ] && exit 1
exec /system/bin/nc -L -s 127.0.0.1 -p "$PORT" /system/bin/sh "$HANDLER"

Push scripts:

adb push rootd/phonebridge-root-handler.sh /data/local/tmp/
adb push rootd/phonebridge-rootd.sh /data/local/tmp/
adb shell '/data/adb/ap/bin/su -c "cp /data/local/tmp/phonebridge-root-handler.sh /data/adb/service.d/ && cp /data/local/tmp/phonebridge-rootd.sh /data/adb/service.d/ && chmod 755 /data/adb/service.d/phonebridge-root-handler.sh /data/adb/service.d/phonebridge-rootd.sh"'

rootd health checks

adb shell '/data/adb/ap/bin/su -c id'
adb shell 'cat /data/adb/ap/su_path'
adb shell '/data/adb/ap/bin/su -c "ps -A | grep -E \"phonebridge-rootd|[n]c -L -s 127.0.0.1 -p 48733\""'
echo "CMD_B64:$(echo -n id | base64)" | adb shell "nc 127.0.0.1 48733"

Pass criteria:

  • root identity returned.
  • rootd endpoint returns __PB_EXIT__:0.

Tinytools installation (mandatory)

for f in tinymix tinycap tinyplay tinypcminfo; do
  adb push skills/root-pixel7a/bin/$f /data/local/tmp/phonebridge-$f
  adb shell "chmod +x /data/local/tmp/phonebridge-$f"
done
adb shell '/data/adb/ap/bin/su -c "for f in tinymix tinycap tinyplay tinypcminfo; do cp /data/local/tmp/phonebridge-\$f /data/adb/service.d/phonebridge-\$f && chmod 755 /data/adb/service.d/phonebridge-\$f; done"'

Verify:

adb shell '/data/adb/ap/bin/su -c "/data/adb/service.d/phonebridge-tinymix -D 0 controls"' | head -5

Post-root deterministic verification gate

adb reboot
adb wait-for-device
adb shell '/data/adb/ap/bin/su -c id'
adb shell 'cat /data/adb/ap/su_path'
adb shell '/data/adb/ap/bin/su -c "test -x /data/adb/service.d/phonebridge-root-handler.sh && echo handler_ok || echo handler_missing"'
adb shell '/data/adb/ap/bin/su -c "test -x /data/adb/service.d/phonebridge-rootd.sh && echo rootd_ok || echo rootd_missing"'
adb shell '/data/adb/ap/bin/su -c "ps -A | grep -E \"phonebridge-rootd|[n]c -L -s 127.0.0.1 -p 48733\""'
adb shell '/data/adb/ap/bin/su -c "test -x /data/adb/service.d/phonebridge-tinymix && echo tinymix_ok || echo tinymix_missing"'
adb shell '/data/adb/ap/bin/su -c "/data/adb/service.d/phonebridge-tinymix -D 0 controls | head -1"'
# Re-set default dialer (resets on every reboot):
adb shell cmd role add-role-holder android.app.role.DIALER com.tracsystems.phonebridge 1
adb shell '/data/adb/ap/bin/su -c "telecom get-default-dialer"'
# Must output: com.tracsystems.phonebridge

Persistence requirements

  • Magisk root must survive reboot.
  • /data/adb/ap/bin/su compatibility wrapper must survive reboot.
  • /data/local/tmp/su -> /debug_ramdisk/su link must be valid after reboot.
  • rootd scripts in /data/adb/service.d/ must survive reboot.
  • Tinytools in /data/adb/service.d/phonebridge-tiny* must persist.
  • Local temporary folders (root-work/, rootd/) must not be kept.

Recovery path (if boot issues return)

Reflash matching stock partitions from same factory image:

  • boot_[ab], init_boot_[ab], vbmeta_[ab], vendor_boot_[ab], vendor_kernel_boot_[ab]

Recovery commands:

cd root-work/image
fastboot flash boot_a boot.img
fastboot flash boot_b boot.img
fastboot flash init_boot_a init_boot.img
fastboot flash init_boot_b init_boot.img
fastboot flash vbmeta_a vbmeta.img
fastboot flash vbmeta_b vbmeta.img
fastboot flash vendor_boot_a vendor_boot.img
fastboot flash vendor_boot_b vendor_boot.img
fastboot flash vendor_kernel_boot_a vendor_kernel_boot.img
fastboot flash vendor_kernel_boot_b vendor_kernel_boot.img
fastboot reboot
adb wait-for-device
adb shell getprop sys.boot_completed

Cleanup (mandatory)

After successful deployment and verification:

rm -rf root-work rootd
Install via CLI
npx skills add https://github.com/Trac-Systems/clawfinger-app --skill root-pixel7a
Repository Details
star Stars 2
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator
Trac-Systems
Trac-Systems Explore all skills →