Skip to content

[Android][斐讯N1] 卡开机动画恢复:launcher 替换误删 directBootAware HOME #56

Description

@nzcv

[Android][斐讯N1] 卡开机动画恢复:launcher 替换误删 directBootAware HOME

斐讯 N1 / p230(Amlogic S905D,Android 7.1.2,已 root,SuperSU)。用一个「替换桌面」的脚本把系统 launcher 换成爱家桌面后,设备一直卡在开机动画。adb 仍能连上(网络 adb),但永远进不了桌面。本文记录完整排查与恢复方法。

现象

  • 一直停在开机动画,进不了系统。
  • adb 能连(状态 device),说明 adbd 起来了,问题在 framework / 开机后期,不是底层 kernel 挂掉。

关键判断命令:

adb shell getprop sys.boot_completed     # 空 = 没启动完成
adb shell getprop init.svc.bootanim      # running = 卡在开机动画
adb shell dumpsys user | grep -i "Started users state"   # {0=0}=BOOTING {0=3}=UNLOCKED
adb shell "cmd package query-activities -a android.intent.action.MAIN -c android.intent.category.HOME"
adb logcat -d | grep -a "No home screen found" | tail -n1

确认特征:bootanim=running、user 状态 {0=0}、HOME 查询为空、日志反复 ActivityManager: No home screen found

根本原因

替换脚本做了三件事,组合起来导致死锁:

  1. 安装 爱家桌面 com.aijia.launcher(为 Android 14 / targetSdk 34 打包,与 Android 7.1.2 不兼容)并 set-home-activity 设为持久 HOME。
  2. pm disablecom.android.provision/.bluetooth.BluetoothActivity —— 它是本机唯一的 directBootAware、priority=1 的 SETUP_WIZARD HOME,在开机「锁定阶段」充当 HOME。
  3. /system/app/AijiaLauncher 推了个坏包(split 解析失败的残留)。

机制:开机锁定阶段普通 launcher 不是 directBootAware,会被 PMS 过滤掉;provision 的兜底 HOME 又被禁用 → 锁定阶段没有任何可用 HOME → user 0 永远停在 STATE_BOOTING 无法解锁 → system_serverNo home screen found → 卡开机动画。

易踩的坑:am start/query-activities 对这些桌面返回「does not exist / No activities found」,并不是组件被删,而是 user 锁定时 PMS 过滤了非 directBootAware 组件。直接重启会复现死锁,不能解决问题。

恢复步骤

1. 打破死锁(让本次开机先完成、解锁 user 0)

adb shell "am start -n com.android.tv.settings/.MainSettings"
adb shell "input keyevent 224"   # 唤醒
adb shell "input keyevent 82"    # 消掉 keyguard
adb shell dumpsys user | grep -i "Started users state"   # 期望 {0=3}
adb shell getprop sys.boot_completed                      # 期望 1

{0=3} 后,普通 launcher 组件才可解析。

2. 拿 root(SuperSU,人工授权)

SuperSU 默认对 shell 静默拒绝。让用户盯着投屏点 授予/Grant(选「记住」),重试到 uid=0

adb shell 'su -c "id" 2>&1; echo RC=$?'   # 期望 uid=0(root)

若秒拒不弹窗,打开 SuperSU 让用户把「默认访问」设为提示/允许,或给 (shell) 授权:

adb shell "monkey -p eu.chainfire.supersu -c android.intent.category.LAUNCHER 1"
adb exec-out screencap -p > /tmp/supersu.png   # 截图引导点按

3–4. SELinux 临时 permissive + 重新启用兜底 HOME

root 的 su 上下文是 u:r:toolbox:s0,enforcing 时连不上 package 服务(Can't find service: package),需临时放开:

adb shell 'su -c "setenforce 0"'
adb shell 'su -c "pm enable com.android.provision/com.android.provision.bluetooth.BluetoothActivity"'

该组件 directBootAware=true、priority=1,是保证以后每次都能正常过锁定阶段的关键。设备已激活(settings get global device_provisioned == 1),向导会直接放行。

5. 设定目标桌面为 HOME

# 启蒙桌面 asyt2
adb shell "cmd package set-home-activity com.asyt2.linearlauncher/.MainActivity"
# 或 原厂 Phicomm 桌面
# adb shell "cmd package set-home-activity com.phicomm.launcherush.debug/com.phicomm.launcherush.activities.ApplicationList"

adb shell "input keyevent 3"   # HOME
adb shell "dumpsys window windows" | grep -i mCurrentFocus

cmd package resolve-activity -c HOME 仍会显示 provision(优先级高),这是正常的——AMS 实际启动 HOME 时会遵循 set-home-activity 设的首选。

6. 卸载爱家桌面 + 清理 /system 残留

adb uninstall com.aijia.launcher
adb shell 'su -c "mount -o rw,remount /system"'
adb shell 'su -c "rm -rf /system/app/AijiaLauncher"'
adb shell 'su -c "mount -o ro,remount /system"'

7. 恢复 SELinux、重启、验证无人值守开机

adb shell 'su -c "setenforce 1"'
adb reboot
# 网络 adb 重连:sleep 60; adb connect <ip>:5555
adb shell getprop sys.boot_completed        # 1
adb shell getprop init.svc.bootanim         # stopped
adb shell dumpsys user | grep -i "Started users state"   # {0=3}
adb shell "dumpsys window windows" | grep -i mCurrentFocus  # 目标桌面

成功标志:自动开机直达目标桌面,无需手动消 keyguard

关键坑位小结

  • 别只重启:纯重启会复现死锁;持久修复在于第 4 步重新启用 provision 的 directBootAware 兜底 HOME。
  • su 上下文 u:r:toolbox:s0 enforcing 时调不了 pm/cmd package → 先 setenforce 0,做完 setenforce 1
  • 改系统组件 pm enable / set-home-activity 必须走 su(shell 会 SecurityException);shell 只能做 adb uninstall 和查询。
  • /system 里的 APK 用 adb exec-out cat <path> > out.apkadb pull 可能报 does not exist)。
  • 查 APK 真实入口:aapt dump badging$ANDROID_HOME/build-tools/*/aapt)。
  • am start does not exist / HOME 查询为空」往往是 user 锁定期的 PMS 过滤,不代表组件丢失。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions