guide #041

APK v2: Escape Hatches (Post-Brick Fix)

Problem
APK v1 was a brick trap: fullscreen hid ADB auth popup, back disabled, no escape to Settings.

Solution
5 protections: visible status bar, triple-tap Settings, double-back chooser, emergency button, ADB kill switch.

Context

The first PocketClaw launcher (Hack #39) was a fullscreen WebView with no escape route. This created a brick trap: if the battery dies, Android invalidates ADB RSA keys. On reboot, the ADB authorization dialog appears — but it renders BEHIND the fullscreen launcher, invisible and untouchable. Without ADB, there's no way to install a different launcher or access settings. Factory reset becomes the only option.

This scenario actually happened and nearly bricked the phone. The fix was to add 5 layers of escape hatches to ensure the user can always reach Settings or a launcher chooser.

Implementation

Five protections were added to the launcher:

// 1. Status bar visible (not truly fullscreen)
// Use Theme.NoTitleBar instead of Theme.NoTitleBar.Fullscreen
// in AndroidManifest.xml:
// android:theme="@android:style/Theme.NoTitleBar"
// This keeps the status bar visible, including ADB auth notifications

// 2. Triple-tap title opens Settings
private int tapCount = 0;
private long lastTap = 0;
titleView.setOnClickListener(v -> {
    long now = System.currentTimeMillis();
    if (now - lastTap > 1000) tapCount = 0;
    tapCount++;
    lastTap = now;
    if (tapCount >= 3) {
        startActivity(new Intent(Settings.ACTION_SETTINGS));
        tapCount = 0;
    }
});

// 3. Double-back shows launcher chooser
private long lastBack = 0;
public void onBackPressed() {
    long now = System.currentTimeMillis();
    if (now - lastBack < 500) {
        // Show launcher chooser
        Intent i = new Intent(Intent.ACTION_MAIN);
        i.addCategory(Intent.CATEGORY_HOME);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(Intent.createChooser(i, "Choose launcher"));
    }
    lastBack = now;
}

// 4. Emergency Settings button after 5 min without gateway
// If HTTP fetch to localhost:9000 fails for 5 minutes,
// show a red "OPEN SETTINGS" button on screen

// 5. ADB broadcast kill switch
// Registered in manifest:
// <receiver android:name=".ExitReceiver">
//   <intent-filter>
//     <action android:name="com.pocketclaw.EXIT" />
//   </intent-filter>
// </receiver>

The ADB kill switch works from any ADB connection:

# Kill the launcher from ADB:
adb shell am broadcast -a com.pocketclaw.EXIT
# Launcher exits, falls back to system launcher chooser

Verification

# Test triple-tap (on device):
# Tap "POCKETCLAW" title 3 times quickly -> Settings opens

# Test double-back (on device):
# Press Back twice quickly -> launcher chooser appears

# Test ADB kill switch:
adb shell am broadcast -a com.pocketclaw.EXIT
# Expected: launcher exits, chooser appears

# Test emergency button (disconnect gateway):
# Wait 5 minutes with gateway stopped
# Red "OPEN SETTINGS" button should appear on screen

Gotchas

  • Theme.NoTitleBar (not Fullscreen) is critical. The status bar must remain visible so ADB authorization dialogs and notifications are accessible
  • The triple-tap timeout (1 second) prevents accidental triggers but is short enough for intentional use
  • The emergency button timer (5 minutes) is deliberately long to avoid false positives during gateway restarts
  • On the native APK (Hack #40), these same 5 protections were re-implemented in Java

Result

MetricBeforeAfter
Escape routes05
Brick riskHigh (near-brick happened)Minimal
ADB auth recoveryFactory resetKill switch broadcast
Settings accessImpossibleTriple-tap or emergency
Continue reading
guide
Pocket AI complete guide
Running self-hosted AI on portable hardware
guide
Edge AI hardware buyer's guide 2026
Pi 5 vs Mini PC vs Mac Mini
report
Self-hosted AI landscape 2026
Quarterly state of the ecosystem
section
Pocket AI hardware hub
All portable hosts reviewed
section
Agent tracker
Live stats on every agent
newsletter
Thursday digest
Weekly summary in your inbox