Commit 21626897743a
Changed files (1)
tools
tools/boox-debloat.sh
@@ -0,0 +1,720 @@
+#!/usr/bin/env nix-shell
+#! nix-shell -i bash -p android-tools curl
+
+# BOOX Tablet Debloat Script
+# Disables safe BOOX bloatware packages to free up RAM
+# Created: 2026-01-15
+# ONLY runs on NoteAir4C devices for safety
+
+set -e
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}BOOX Tablet Debloat Script${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+
+# Check if device is connected
+echo -e "${YELLOW}Checking for connected device...${NC}"
+if ! adb devices | grep -q "device$"; then
+ echo -e "${RED}ERROR: No device connected!${NC}"
+ echo "Please ensure:"
+ echo " 1. USB debugging is enabled on your BOOX tablet"
+ echo " 2. Device is connected via USB"
+ echo " 3. You've authorized this computer on the device"
+ exit 1
+fi
+
+DEVICE=$(adb devices | grep "device$" | awk '{print $1}')
+echo -e "${GREEN}✓ Device connected: $DEVICE${NC}"
+echo
+
+# Get device info
+echo -e "${YELLOW}Verifying device model...${NC}"
+MODEL=$(adb shell getprop ro.product.model)
+ANDROID=$(adb shell getprop ro.build.version.release)
+FIRMWARE=$(adb shell getprop ro.build.display.id)
+
+echo " Model: $MODEL"
+echo " Android: $ANDROID"
+echo " Firmware: $FIRMWARE"
+echo
+
+# Safety check: Only run on NoteAir4C
+if [ "$MODEL" != "NoteAir4C" ]; then
+ echo -e "${RED}ERROR: This script is configured to only run on NoteAir4C devices!${NC}"
+ echo -e "${RED}Detected model: $MODEL${NC}"
+ echo
+ echo "This is a safety measure to prevent accidentally debloating the wrong device."
+ echo
+ echo "If you want to run this on a different BOOX model, edit the script and change"
+ echo "the MODEL check to match your device."
+ exit 1
+fi
+
+echo -e "${GREEN}✓ Confirmed NoteAir4C - proceeding with safety checks${NC}"
+echo
+
+# =============================================================================
+# Safety Check: Ensure critical replacements are installed
+# =============================================================================
+
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}Pre-flight Safety Checks${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+
+SAFETY_ISSUES=0
+
+# Check for alternative launcher (if we plan to remove com.onyx launcher later)
+echo -e "${YELLOW}Checking for alternative launcher...${NC}"
+ALTERNATIVE_LAUNCHERS=(
+ "ru.execbit.aiolauncher" # AIO Launcher (recommended for e-ink)
+ "ch.deletescape.lawnchair.plah" # Lawnchair (F-Droid)
+ "com.teslacoilsw.launcher" # Nova Launcher
+)
+
+HAS_ALT_LAUNCHER=0
+LAUNCHER_PACKAGE=""
+for launcher in "${ALTERNATIVE_LAUNCHERS[@]}"; do
+ if adb shell pm list packages | grep -q "^package:$launcher$"; then
+ LAUNCHER_NAME=$(adb shell pm list packages | grep "$launcher" | cut -d: -f2)
+ echo -e "${GREEN}✓ Found alternative launcher: $LAUNCHER_NAME${NC}"
+ HAS_ALT_LAUNCHER=1
+ LAUNCHER_PACKAGE=$launcher
+
+ # Set as default if it's AIO Launcher
+ if [ "$launcher" = "ru.execbit.aiolauncher" ]; then
+ echo -e "${YELLOW} Setting AIO Launcher as default...${NC}"
+ if adb shell cmd package set-home-activity ru.execbit.aiolauncher/.MainActivity 2>&1 | grep -q "Success"; then
+ echo -e "${GREEN} ✓ Set as default launcher${NC}"
+ else
+ echo -e "${YELLOW} ⚠ Could not set as default automatically${NC}"
+ echo -e "${YELLOW} Please set manually: Home button → AIO Launcher → Always${NC}"
+ fi
+ fi
+ break
+ fi
+done
+
+if [ $HAS_ALT_LAUNCHER -eq 0 ]; then
+ echo -e "${YELLOW}⚠ No alternative launcher found${NC}"
+ echo " Note: Not removing BOOX launcher (com.onyx) - it's safe for now."
+ echo " If you want to remove it later, install an alternative launcher first."
+fi
+echo
+
+# Check for alternative keyboard (if we plan to remove ONYX keyboards)
+echo -e "${YELLOW}Checking for alternative keyboard...${NC}"
+ALTERNATIVE_KEYBOARDS=(
+ "com.google.android.inputmethod.latin" # Gboard (already installed)
+ "org.pocketworkstation.pckeyboard" # Hacker's Keyboard
+ "com.menny.android.anysoftkeyboard" # AnySoftKeyboard
+ "rkr.simplekeyboard.inputmethod" # Simple Keyboard
+ "fr.bepo.clavierexterne" # BÉPO (already installed)
+)
+
+HAS_ALT_KEYBOARD=0
+KEYBOARD_NAMES=""
+for keyboard in "${ALTERNATIVE_KEYBOARDS[@]}"; do
+ if adb shell pm list packages | grep -q "^package:$keyboard$"; then
+ KEYBOARD_NAME=$(adb shell pm list packages | grep "$keyboard" | cut -d: -f2)
+ KEYBOARD_NAMES="$KEYBOARD_NAMES\n - $KEYBOARD_NAME"
+ HAS_ALT_KEYBOARD=1
+ fi
+done
+
+if [ $HAS_ALT_KEYBOARD -eq 1 ]; then
+ echo -e "${GREEN}✓ Found alternative keyboard(s):${NC}"
+ echo -e "$KEYBOARD_NAMES"
+else
+ echo -e "${RED}✗ No alternative keyboard found!${NC}"
+ echo " Installing Google Keyboard or another alternative is recommended"
+ echo " if you plan to disable ONYX keyboards."
+ ((SAFETY_ISSUES++))
+fi
+echo
+
+# Check for F-Droid (useful for installing alternatives)
+echo -e "${YELLOW}Checking for F-Droid...${NC}"
+if adb shell pm list packages | grep -q "^package:org.fdroid.fdroid$"; then
+ echo -e "${GREEN}✓ F-Droid is installed${NC}"
+
+ # Check if it's disabled
+ if adb shell pm list packages -d | grep -q "^package:org.fdroid.fdroid$"; then
+ echo -e "${YELLOW} ⚠ F-Droid is currently disabled - enabling it...${NC}"
+ adb shell pm enable org.fdroid.fdroid
+ echo -e "${GREEN} ✓ F-Droid enabled${NC}"
+ fi
+else
+ echo -e "${YELLOW}⚠ F-Droid not installed${NC}"
+ echo " F-Droid is useful for installing alternative apps, but not required."
+ echo " AIO Launcher can be installed from Google Play Store instead."
+fi
+echo
+
+# Offer to install AIO Launcher if not present
+if [ $HAS_ALT_LAUNCHER -eq 0 ]; then
+ echo -e "${YELLOW}Recommendation: Install AIO Launcher${NC}"
+ echo " AIO Launcher is a minimalist launcher designed for simplicity and speed."
+ echo " It's particularly well-suited for e-ink displays."
+ echo " Features:"
+ echo " - Text-based minimal interface (perfect for e-ink)"
+ echo " - Very low memory footprint"
+ echo " - Fast, no animations"
+ echo " - Highly customizable"
+ echo
+ echo " This script can automatically download and install AIO Launcher for you."
+ echo
+ read -p " Download and install AIO Launcher now? [Y/n] " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Nn]$ ]]; then
+ echo -e "${YELLOW}Downloading AIO Launcher...${NC}"
+
+ # Create temp directory
+ TEMP_DIR=$(mktemp -d)
+ APK_PATH="$TEMP_DIR/aio-launcher.apk"
+
+ # Download from Uptodown (reliable APK mirror)
+ # Note: This is the free version from official Uptodown mirror
+ echo " Source: Uptodown (reliable APK mirror)"
+
+ # Get latest version download URL from Uptodown
+ # Uptodown provides direct APK downloads for Android apps
+ DOWNLOAD_URL="https://dw.uptodown.com/dwn/VgGOk7_tR_2XAHTeDUlQwXdxn6_o9rN3WT-ypxdA-t7MyzTWcWoPgJ1sqPXxRWO2TBu0ZcLCY3r60hSmX-5hG-b8RWqXlBQqOSRx6m-q1mCYOCApnLd9O0HnMPqbhevU/DudI_KHcChA0M2TvhAxE3TjXSC7SDRZdJAoVm_9MuJKCREMOBVYN8Uig7-f3fWQXbqLmOjgMcuQtSFWaEwJ0SX90J4_PcP1C1A5dXXbKTIFT0I8y-6VVp9-zFCYiPKhv/Xhf4XPFxpyQs0WqjhzPJuw==/aio-launcher.apk"
+
+ if curl -L -o "$APK_PATH" "$DOWNLOAD_URL" 2>/dev/null; then
+ echo -e "${GREEN} ✓ Downloaded successfully${NC}"
+
+ echo -e "${YELLOW}Installing AIO Launcher...${NC}"
+ if adb install "$APK_PATH" 2>&1 | grep -q "Success"; then
+ echo -e "${GREEN} ✓ AIO Launcher installed successfully${NC}"
+ HAS_ALT_LAUNCHER=1
+ LAUNCHER_PACKAGE="ru.execbit.aiolauncher"
+
+ # Set as default launcher
+ echo -e "${YELLOW}Setting AIO Launcher as default launcher...${NC}"
+
+ # Set AIO Launcher as default home activity
+ if adb shell cmd package set-home-activity ru.execbit.aiolauncher/.MainActivity 2>&1 | grep -q "Success"; then
+ echo -e "${GREEN} ✓ AIO Launcher set as default launcher${NC}"
+ else
+ echo -e "${YELLOW} ⚠ Could not automatically set default launcher${NC}"
+ echo " Please set manually: Home button → AIO Launcher → Always"
+ fi
+ else
+ echo -e "${RED} ✗ Failed to install AIO Launcher${NC}"
+ echo " You can install manually from Google Play Store instead."
+ fi
+
+ # Cleanup
+ rm -f "$APK_PATH"
+ rmdir "$TEMP_DIR"
+ else
+ echo -e "${RED} ✗ Failed to download AIO Launcher${NC}"
+ echo " You can install manually from Google Play Store instead."
+ rm -rf "$TEMP_DIR"
+ fi
+ else
+ echo -e "${YELLOW} Install AIO Launcher manually from Google Play Store:${NC}"
+ echo " 1. Open Play Store on your BOOX"
+ echo " 2. Search for 'AIO Launcher'"
+ echo " 3. Install it"
+ echo " 4. Set as default launcher (Home button → AIO Launcher → Always)"
+ echo
+ read -p " Continue without alternative launcher? [y/N] " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ echo -e "${YELLOW}Exiting. Install AIO Launcher and run this script again.${NC}"
+ exit 0
+ fi
+ fi
+ echo
+fi
+
+# Summary of safety checks
+if [ $SAFETY_ISSUES -gt 0 ]; then
+ echo -e "${YELLOW}⚠ Warning: $SAFETY_ISSUES safety issue(s) detected${NC}"
+ echo " Review the warnings above before proceeding."
+ echo
+fi
+
+# =============================================================================
+# Memory stats before debloating
+# =============================================================================
+
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}Memory Analysis${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+
+echo -e "${YELLOW}Memory Before Debloating:${NC}"
+MEM_TOTAL=$(adb shell cat /proc/meminfo | grep MemTotal | awk '{print $2}')
+MEM_FREE_BEFORE=$(adb shell cat /proc/meminfo | grep MemFree | awk '{print $2}')
+MEM_AVAILABLE_BEFORE=$(adb shell cat /proc/meminfo | grep MemAvailable | awk '{print $2}')
+echo " Total RAM: $((MEM_TOTAL / 1024)) MB"
+echo " Free RAM: $((MEM_FREE_BEFORE / 1024)) MB"
+echo " Available RAM: $((MEM_AVAILABLE_BEFORE / 1024)) MB"
+echo
+
+# =============================================================================
+# Package removal/disabling - Interactive Selection
+# =============================================================================
+
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}Package Selection${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+
+# Define all packages with safety levels
+# Format: "package_name|safety_level|description|memory_mb"
+
+declare -A PACKAGE_INFO
+
+# ===== SAFE - No dependencies, no critical functionality =====
+PACKAGE_INFO["com.onyx.mail"]="SAFE|Email client - use alternatives like K-9 Mail|198"
+PACKAGE_INFO["com.onyx.gallery"]="SAFE|Gallery app - use alternatives like Immich or Simple Gallery|161"
+PACKAGE_INFO["com.onyx.easytransfer"]="SAFE|File transfer utility - not needed|146"
+PACKAGE_INFO["com.onyx.aiassistant"]="SAFE|AI Assistant - not essential|139"
+PACKAGE_INFO["com.onyx.android.ksync"]="SAFE|Cloud sync service - use alternatives like Syncthing|201"
+PACKAGE_INFO["com.onyx.calculator"]="SAFE|Calculator app - Android has built-in|0"
+PACKAGE_INFO["com.onyx.musicplayer"]="SAFE|Music player - not ideal for e-ink|0"
+PACKAGE_INFO["com.onyx.voicerecorder"]="SAFE|Voice recorder - rarely used on e-ink|0"
+PACKAGE_INFO["com.onyx.dict"]="SAFE|Dictionary app - use online alternatives|0"
+PACKAGE_INFO["com.onyx.igetshop"]="SAFE|Shopping app - bloatware|0"
+PACKAGE_INFO["com.onyx.clock"]="SAFE|Clock app - Android has built-in|128"
+PACKAGE_INFO["com.onyx.android.production.test"]="SAFE|Test suite - not needed for users|0"
+
+# ===== CONDITIONAL - Safe if alternatives installed =====
+PACKAGE_INFO["com.onyx.kime"]="CONDITIONAL|ONYX Keyboard 1 - need alternative keyboard first|0"
+PACKAGE_INFO["com.onyx.latinime"]="CONDITIONAL|ONYX Keyboard 2 - need alternative keyboard first|0"
+PACKAGE_INFO["com.onyx"]="CONDITIONAL|BOOX Launcher - MUST have alternative launcher installed first!|477"
+PACKAGE_INFO["com.onyx.appmarket"]="CONDITIONAL|ONYX App Store - can use Play Store/F-Droid instead|0"
+PACKAGE_INFO["com.onyx.kreader"]="CONDITIONAL|BOOX Reader - if using KOReader or other alternatives|0"
+
+# ===== RISKY - Can cause issues, careful consideration needed =====
+PACKAGE_INFO["com.android.vending"]="RISKY|Google Play Store - need F-Droid or sideload apps|216"
+PACKAGE_INFO["com.google.android.gms"]="RISKY|Google Play Services - some apps depend on it|621"
+PACKAGE_INFO["org.chromium.chrome"]="RISKY|Chrome browser - need alternative browser|118"
+PACKAGE_INFO["com.google.android.tts"]="RISKY|Google Text-to-Speech - needed for TTS features|154"
+PACKAGE_INFO["com.google.android.syncadapters.calendar"]="RISKY|Google Calendar Sync - if using Google Calendar|161"
+PACKAGE_INFO["com.google.android.apps.restore"]="RISKY|Google Restore - needed for app backups|141"
+
+# ===== DANGEROUS - DO NOT REMOVE unless you know what you're doing =====
+PACKAGE_INFO["com.android.systemui"]="DANGEROUS|System UI - CRITICAL, will break device|0"
+PACKAGE_INFO["com.android.settings"]="DANGEROUS|Android Settings - CRITICAL, will break device|0"
+PACKAGE_INFO["com.onyx.android.onyxotaservice"]="DANGEROUS|OTA Update Service - prevents firmware updates if removed|0"
+
+# Default safe list (pre-selected)
+PACKAGES_TO_DISABLE=(
+ "com.onyx.mail"
+ "com.onyx.gallery"
+ "com.onyx.easytransfer"
+ "com.onyx.aiassistant"
+ "com.onyx.android.ksync"
+ "com.onyx.calculator"
+ "com.onyx.musicplayer"
+ "com.onyx.voicerecorder"
+ "com.onyx.dict"
+ "com.onyx.igetshop"
+ "com.onyx.clock"
+ "com.onyx.android.production.test"
+)
+
+echo -e "${GREEN}Package Categories:${NC}"
+echo -e " ${GREEN}[SAFE]${NC} - No dependencies, safe to remove"
+echo -e " ${YELLOW}[CONDITIONAL]${NC} - Safe only if alternatives installed"
+echo -e " ${RED}[RISKY]${NC} - May break functionality, careful!"
+echo -e " ${RED}[DANGEROUS]${NC} - DO NOT REMOVE"
+echo
+
+# Show what's currently selected (safe packages by default)
+echo -e "${YELLOW}Currently selected packages (${#PACKAGES_TO_DISABLE[@]} packages):${NC}"
+for pkg in "${PACKAGES_TO_DISABLE[@]}"; do
+ IFS='|' read -r level desc mem <<< "${PACKAGE_INFO[$pkg]}"
+ COLOR="${GREEN}"
+ echo -e " ${COLOR}[${level}]${NC} $pkg - $desc"
+done
+echo
+
+# Ask if user wants to customize selection
+read -p "Customize package selection? [y/N] " -n 1 -r
+echo
+if [[ $REPLY =~ ^[Yy]$ ]]; then
+ echo
+ echo -e "${BLUE}========================================${NC}"
+ echo -e "${BLUE}Available Packages${NC}"
+ echo -e "${BLUE}========================================${NC}"
+ echo
+
+ # Show all packages by category
+ echo -e "${GREEN}=== SAFE Packages ===${NC}"
+ for pkg in "${!PACKAGE_INFO[@]}"; do
+ IFS='|' read -r level desc mem <<< "${PACKAGE_INFO[$pkg]}"
+ if [ "$level" == "SAFE" ]; then
+ # Check if package exists on device
+ if adb shell pm list packages | grep -q "^package:$pkg$"; then
+ echo " $pkg - $desc"
+ fi
+ fi
+ done
+ echo
+
+ echo -e "${YELLOW}=== CONDITIONAL Packages (need alternatives) ===${NC}"
+ for pkg in "${!PACKAGE_INFO[@]}"; do
+ IFS='|' read -r level desc mem <<< "${PACKAGE_INFO[$pkg]}"
+ if [ "$level" == "CONDITIONAL" ]; then
+ if adb shell pm list packages | grep -q "^package:$pkg$"; then
+ echo " $pkg - $desc"
+ fi
+ fi
+ done
+ echo
+
+ echo -e "${RED}=== RISKY Packages (careful!) ===${NC}"
+ for pkg in "${!PACKAGE_INFO[@]}"; do
+ IFS='|' read -r level desc mem <<< "${PACKAGE_INFO[$pkg]}"
+ if [ "$level" == "RISKY" ]; then
+ if adb shell pm list packages | grep -q "^package:$pkg$"; then
+ echo " $pkg - $desc"
+ fi
+ fi
+ done
+ echo
+
+ echo -e "${RED}=== DANGEROUS Packages (DO NOT REMOVE) ===${NC}"
+ for pkg in "${!PACKAGE_INFO[@]}"; do
+ IFS='|' read -r level desc mem <<< "${PACKAGE_INFO[$pkg]}"
+ if [ "$level" == "DANGEROUS" ]; then
+ if adb shell pm list packages | grep -q "^package:$pkg$"; then
+ echo " $pkg - $desc"
+ fi
+ fi
+ done
+ echo
+
+ echo -e "${YELLOW}Choose a preset:${NC}"
+ echo " 1) Safe only (default, recommended)"
+ echo " 2) Safe + Keyboards (if you have alternative keyboard)"
+ echo " 3) Safe + Google services (degoogle - requires F-Droid)"
+ echo " 4) Safe + Launcher (ONLY if AIO Launcher is installed and set as default)"
+ echo " 5) Custom selection (advanced)"
+ echo
+ read -p "Select preset [1-5]: " -n 1 -r PRESET
+ echo
+ echo
+
+ case $PRESET in
+ 2)
+ echo -e "${YELLOW}Selected: Safe + Keyboards${NC}"
+ # Check for alternative keyboard
+ if [ $HAS_ALT_KEYBOARD -eq 0 ]; then
+ echo -e "${RED}WARNING: No alternative keyboard detected!${NC}"
+ echo "Install Gboard, AnySoftKeyboard, or Hacker's Keyboard first."
+ read -p "Continue anyway? [y/N] " -n 1 -r
+ echo
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ echo "Falling back to safe packages only."
+ else
+ PACKAGES_TO_DISABLE+=("com.onyx.kime" "com.onyx.latinime")
+ fi
+ else
+ PACKAGES_TO_DISABLE+=("com.onyx.kime" "com.onyx.latinime")
+ echo -e "${GREEN}Alternative keyboard detected - safe to remove ONYX keyboards${NC}"
+ fi
+ ;;
+ 3)
+ echo -e "${YELLOW}Selected: Safe + Google services (degoogle)${NC}"
+ echo -e "${RED}WARNING: This will remove Google Play Store!${NC}"
+ echo "Make sure F-Droid is installed for app management."
+ read -p "Continue with degoogle? [y/N] " -n 1 -r
+ echo
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ PACKAGES_TO_DISABLE+=(
+ "com.android.vending"
+ "com.google.android.tts"
+ "com.google.android.syncadapters.calendar"
+ "com.google.android.apps.restore"
+ "org.chromium.chrome"
+ )
+ echo -e "${YELLOW}Added Google services to removal list${NC}"
+ fi
+ ;;
+ 4)
+ echo -e "${YELLOW}Selected: Safe + Launcher${NC}"
+ if [ $HAS_ALT_LAUNCHER -eq 0 ]; then
+ echo -e "${RED}ERROR: No alternative launcher detected!${NC}"
+ echo "Install AIO Launcher or another launcher first."
+ echo "Falling back to safe packages only."
+ else
+ echo -e "${GREEN}Alternative launcher detected: $LAUNCHER_PACKAGE${NC}"
+ read -p "Remove BOOX Launcher? [y/N] " -n 1 -r
+ echo
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ PACKAGES_TO_DISABLE+=("com.onyx")
+ echo -e "${YELLOW}Added BOOX Launcher to removal list${NC}"
+ fi
+ fi
+ ;;
+ 5)
+ echo -e "${YELLOW}Custom selection${NC}"
+ echo "Enter package names to add (comma-separated), or press Enter to skip:"
+ read -r CUSTOM_PACKAGES
+ if [ -n "$CUSTOM_PACKAGES" ]; then
+ IFS=',' read -ra PKGS <<< "$CUSTOM_PACKAGES"
+ for pkg in "${PKGS[@]}"; do
+ pkg=$(echo "$pkg" | xargs) # trim whitespace
+ if [ -n "${PACKAGE_INFO[$pkg]}" ]; then
+ PACKAGES_TO_DISABLE+=("$pkg")
+ echo " Added: $pkg"
+ else
+ echo " Unknown package (skipped): $pkg"
+ fi
+ done
+ fi
+ ;;
+ *)
+ echo -e "${GREEN}Using default safe packages${NC}"
+ ;;
+ esac
+ echo
+fi
+
+# Final confirmation - show what will be disabled
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}Final Package List${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+echo -e "${YELLOW}Packages to uninstall (${#PACKAGES_TO_DISABLE[@]} total):${NC}"
+
+TOTAL_MEM_RECOVERY=0
+for pkg in "${PACKAGES_TO_DISABLE[@]}"; do
+ IFS='|' read -r level desc mem <<< "${PACKAGE_INFO[$pkg]}"
+
+ # Color based on safety level
+ case $level in
+ SAFE) COLOR="${GREEN}" ;;
+ CONDITIONAL) COLOR="${YELLOW}" ;;
+ RISKY) COLOR="${RED}" ;;
+ DANGEROUS) COLOR="${RED}" ;;
+ *) COLOR="${NC}" ;;
+ esac
+
+ if [ "$mem" -gt 0 ]; then
+ echo -e " ${COLOR}[${level}]${NC} $pkg - $desc (${mem} MB)"
+ TOTAL_MEM_RECOVERY=$((TOTAL_MEM_RECOVERY + mem))
+ else
+ echo -e " ${COLOR}[${level}]${NC} $pkg - $desc"
+ fi
+done
+
+if [ $TOTAL_MEM_RECOVERY -gt 0 ]; then
+ echo
+ echo -e "${GREEN}Estimated memory recovery: ~${TOTAL_MEM_RECOVERY} MB${NC}"
+fi
+echo
+
+# Final confirmation
+read -p "Continue with uninstalling these packages? [y/N] " -n 1 -r
+echo
+if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+ echo -e "${YELLOW}Aborted by user.${NC}"
+ exit 0
+fi
+
+echo
+
+# Uninstall packages
+UNINSTALLED_COUNT=0
+SKIPPED_COUNT=0
+FAILED_COUNT=0
+
+# Cache package lists to avoid repeated ADB calls (much faster)
+echo -e "${YELLOW}Getting package lists from device...${NC}"
+ALL_PACKAGES=$(adb shell pm list packages)
+echo -e "${GREEN}✓ Package list cached${NC}"
+echo
+
+for pkg in "${PACKAGES_TO_DISABLE[@]}"; do
+ # Check if package exists (using cached list)
+ if ! echo "$ALL_PACKAGES" | grep -q "^package:$pkg$"; then
+ echo -e "${YELLOW}⊘ Skipping $pkg (not installed)${NC}"
+ SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
+ continue
+ fi
+
+ # Uninstall package for user 0
+ echo -e "${YELLOW}Uninstalling: $pkg${NC}"
+ if adb shell pm uninstall --user 0 "$pkg" 2>&1 | grep -q "Success"; then
+ echo -e "${GREEN}✓ Successfully uninstalled: $pkg${NC}"
+ UNINSTALLED_COUNT=$((UNINSTALLED_COUNT + 1))
+ else
+ echo -e "${RED}✗ Failed to uninstall: $pkg${NC}"
+ FAILED_COUNT=$((FAILED_COUNT + 1))
+ fi
+done
+
+echo
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}Summary${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo " Uninstalled: $UNINSTALLED_COUNT"
+echo " Skipped: $SKIPPED_COUNT"
+echo " Failed: $FAILED_COUNT"
+echo
+
+# Get memory stats after
+if [ $UNINSTALLED_COUNT -gt 0 ]; then
+ echo -e "${YELLOW}Memory After Debloating:${NC}"
+ MEM_FREE_AFTER=$(adb shell cat /proc/meminfo | grep MemFree | awk '{print $2}')
+ MEM_AVAILABLE_AFTER=$(adb shell cat /proc/meminfo | grep MemAvailable | awk '{print $2}')
+ echo " Free RAM: $((MEM_FREE_AFTER / 1024)) MB (was $((MEM_FREE_BEFORE / 1024)) MB)"
+ echo " Available RAM: $((MEM_AVAILABLE_AFTER / 1024)) MB (was $((MEM_AVAILABLE_BEFORE / 1024)) MB)"
+
+ # Calculate improvement
+ FREE_DIFF=$(((MEM_FREE_AFTER - MEM_FREE_BEFORE) / 1024))
+ AVAILABLE_DIFF=$(((MEM_AVAILABLE_AFTER - MEM_AVAILABLE_BEFORE) / 1024))
+
+ echo
+ if [ $FREE_DIFF -gt 0 ]; then
+ echo -e "${GREEN}Immediate improvement: +${FREE_DIFF} MB free${NC}"
+ fi
+ if [ $AVAILABLE_DIFF -gt 0 ]; then
+ echo -e "${GREEN}Available RAM improved: +${AVAILABLE_DIFF} MB${NC}"
+ fi
+ echo
+
+ # Suggest reboot
+ echo -e "${YELLOW}Recommendation:${NC}"
+ echo " Reboot device to fully free up memory from disabled apps."
+ echo
+ read -p "Reboot device now? [y/N] " -n 1 -r
+ echo
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ echo -e "${YELLOW}Rebooting device...${NC}"
+ adb reboot
+ echo -e "${GREEN}✓ Device rebooting. Wait ~30 seconds then check memory usage.${NC}"
+ else
+ echo -e "${YELLOW}Remember to reboot later to see full memory recovery.${NC}"
+ fi
+else
+ echo -e "${YELLOW}No packages were uninstalled. Nothing to do.${NC}"
+fi
+
+# =============================================================================
+# BOOX-Specific Optimizations
+# =============================================================================
+
+echo
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}BOOX E-ink Optimizations${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+
+# Apps that should NOT be frozen (need background activity)
+APPS_TO_UNFREEZE=(
+ "org.mozilla.thunderbird" # Thunderbird (email)
+ "com.fsck.k9" # K-9 Mail
+ "com.google.android.gm" # Gmail
+ "org.thoughtcrime.securesms" # Signal (messaging)
+ "org.telegram.messenger" # Telegram
+ "com.whatsapp" # WhatsApp
+ "io.homeassistant.companion.android" # Home Assistant
+ "com.termux" # Termux (terminal)
+ "org.koreader.launcher.fdroid" # KOReader (reading)
+ "org.koreader.launcher" # KOReader (Play Store version)
+ "ru.execbit.aiolauncher" # AIO Launcher
+ "app.organicmaps" # Organic Maps
+ "org.mozilla.firefox" # Firefox
+ "com.readwise.reader" # Readwise Reader
+ "com.amazon.kindle" # Kindle
+)
+
+echo -e "${YELLOW}Configuring app permissions for e-ink optimization...${NC}"
+echo
+
+CONFIGURED_COUNT=0
+for app in "${APPS_TO_UNFREEZE[@]}"; do
+ # Check if app is installed
+ if ! echo "$ALL_PACKAGES" | grep -q "^package:$app$"; then
+ continue
+ fi
+
+ APP_NAME=$(echo "$app" | rev | cut -d. -f1 | rev)
+ echo -e "${YELLOW}Configuring: $APP_NAME ($app)${NC}"
+
+ # Allow background activity (prevents BOOX from killing the app)
+ if adb shell cmd appops set "$app" RUN_IN_BACKGROUND allow 2>&1 | grep -qv "No operations"; then
+ echo -e "${GREEN} ✓ Allowed background activity${NC}"
+ fi
+
+ # Disable battery optimization (Android standard)
+ # Note: BOOX doesn't fully support this, but we try anyway
+ adb shell dumpsys deviceidle whitelist +"$app" 2>/dev/null || true
+
+ CONFIGURED_COUNT=$((CONFIGURED_COUNT + 1))
+done
+
+if [ $CONFIGURED_COUNT -gt 0 ]; then
+ echo
+ echo -e "${GREEN}✓ Configured $CONFIGURED_COUNT apps for background activity${NC}"
+else
+ echo -e "${YELLOW}No apps found that need configuration${NC}"
+fi
+
+echo
+echo -e "${BLUE}========================================${NC}"
+echo -e "${BLUE}Manual E-ink Settings (Recommended)${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+echo -e "${YELLOW}The following settings should be configured manually on your BOOX:${NC}"
+echo
+echo "1. App Freeze Settings (Critical!):"
+echo " Settings → Apps → App Management Settings"
+echo " For each important app (email, messaging, etc.):"
+echo " - Tap the app"
+echo " - Disable 'Freeze' or enable 'Stay active in background'"
+echo
+echo "2. E-ink Optimization Settings:"
+echo " Settings → Apps → App Optimization"
+echo " For each app, configure:"
+echo " - Screen Refresh Mode:"
+echo " • Speed Mode: For interactive apps (browsers, email, terminals)"
+echo " • Balanced Mode: For general use"
+echo " • Quality/HD Mode: For reading (Kindle, KOReader)"
+echo " - Animation Optimization: Enable (reduces ghosting)"
+echo
+echo "3. Recommended App Settings:"
+echo " - Kindle/Reading apps: Quality mode, no animation"
+echo " - Email/Messaging: Speed mode, enable background activity"
+echo " - Termux/Terminal: Speed mode, enable background activity"
+echo " - KOReader: Speed mode, unfreeze, unrestricted battery"
+echo " - Browsers: Speed mode"
+echo " - Home Assistant: Speed mode, enable background activity"
+echo
+
+echo
+echo -e "${BLUE}========================================${NC}"
+echo -e "${GREEN}Done!${NC}"
+echo -e "${BLUE}========================================${NC}"
+echo
+echo "Next steps:"
+echo " 1. If you installed AIO Launcher, set it as default:"
+echo " Home button → AIO Launcher → Always"
+echo
+echo " 2. To reinstall a package:"
+echo " adb shell cmd package install-existing <package_name>"
+echo
+echo " 3. To see all installed packages:"
+echo " adb shell pm list packages"
+echo
+echo " 4. To add more packages to debloat:"
+echo " Edit ~/src/home/tools/boox-debloat.sh"
+echo " Add packages to PACKAGES_TO_DISABLE array"
+echo