安卓系统Fallback的结束到桌面启动

📅 2026/7/31 17:22:51 👁️ 阅读次数 📝 编程学习
安卓系统Fallback的结束到桌面启动

主线

支线

HomeActivity和fallbackHome的联系

结合Android系统HomeActivity启动流程相关内容,二者的核心联系如下:

层级与定位关系‌
FallbackHome是Android系统在Direct Boot(设备未解锁)阶段的‌临时HomeActivity‌,而常规的HomeActivity就是用户日常使用的桌面Launcher主Activity。在设备加密未解锁时,系统无法启动普通Launcher,FallbackHome就作为临时的HomeActivity占位。
启动时序关联‌
系统开机时,在用户完成设备解锁前,系统通过resolveHomeActivity优先解析到FallbackHome启动;用户解锁后,FallbackHome会自动退出,系统重新解析Home Intent,启动真正的桌面HomeActivity完成接管。
优先级与调度逻辑‌
FallbackHome的intent-filter优先级被设为-1000,远低于常规Launcher的HomeActivity优先级,解锁后系统会自动将Home入口切换为正式的桌面HomeActivity,避免临时界面长期占用前台。


2launch是否也可以作为未解锁状态替换fallbackHome(未解锁)

launch包含第三方应用,如果是加密状态第三方应用也不该展示,那显而易见就是无法控制第三方应用,就设置一个fallbackHome什么都不展示,但他可以在加密的状态下运行起来,

它是也是一种解密的状态,可以在未解锁之前呢呃,理论上就是说你要是真正想做这件事啊。也许是可以的,但是你要想一个问题啊,就是说如果你只是桌面的话啊,你要是不跟其他的。应用有任何耦合的情况下,那是可以的啊,但是朗取的话啊,他明显就可能跟其他第三方应用有较大的耦合,对吧?比如说我们桌面的那些小部件什么的,对吧啊?你这个时候可能是要第三方的那种应用啊,或者要访问第三方的一些文件或者什么东西,对吧?那这个时候的话。你要是说。人家加密的这种状态的话,你是不是也要求其他第三方应用,他也跟你一样,这样的一种状态,那这肯定就不现实了,对吧?你肯定无法控制第三方应用

3FallbackHome‌ 切换到正式 ‌HomeActivity (Launcher)‌ 的关键源码调用链路 ‌,并补充核心节点的逻辑注释。

这一过程主要发生在系统启动后期(systemReady)以及用户解锁设备时。核心逻辑位于 ActivityTaskManagerService (ATMS) 和 RootWindowContainer 中。

1. 核心启动入口:SystemServer -> AMS

系统服务准备就绪后,AMS 会触发 Home 的启动流程。

java
// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
// ... 其他服务启动
mActivityManagerService.systemReady(() -> {
// systemReady 回调中,启动 Home Activity
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
}, t);
}

2. ATMS 调度层:解析与路由

startHomeOnAllDisplays 最终委托给 RootWindowContainer 处理。这是决定“启动哪个 Home”的关键决策点。

java
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

boolean startHomeOnDisplay(int userId, String reason, int displayId,
boolean allowInstrumenting, boolean fromHomeKey) {
// 1. 构建标准的 Home Intent (Action: MAIN, Category: HOME)
Intent homeIntent = mService.getHomeIntent();

// 2. 【关键节点】解析具体的 ActivityInfo
// 这里会根据当前系统状态(是否加密、是否解锁)来决定返回 FallbackHome 还是 Launcher
ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent);

if (aInfo == null || homeIntent == null) {
return false;
}

// 3. 检查是否允许启动
if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) {
return false;
}

// 4. 设置组件并启动
homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);

// 5. 执行真正的 Activity 启动流程
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, reason, displayId);
return true;
}

3. 核心决策逻辑:resolveHomeActivity

这是理解二者联系的最核心方法。它决定了在当前时刻,谁才是真正的“Home”。

java
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

private ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
// 获取 PackageManagerService
final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);

// 【关键逻辑】判断当前用户是否处于“解锁”状态
// 如果设备加密且未解锁 (Locked),或者用户尚未完成首次设置
if (!mService.mUserController.isCurrentUserUnlockingOrUnlocked(userId)) {
// 场景 A:设备未解锁 / Direct Boot 模式
// 优先查找标记了 directBootAware=true 的 Home Activity
// FallbackHome (在 Settings 中) 通常配置了 android:directBootAware="true"
// 而普通 Launcher 通常没有这个属性,因此在未解锁时不可见
return pmi.resolveHomeActivityForDirectBoot(userId, homeIntent);
} else {
// 场景 B:设备已解锁
// 正常解析所有带有 CATEGORY_HOME 的 Activity
// 此时会根据 priority (优先级) 选择。
// FallbackHome 的 priority 通常设为 -1000 (极低),而 Launcher 为 0 或更高
// 因此,系统会选择正式的 Launcher 作为 HomeActivity
return pmi.resolveHomeActivity(userId, homeIntent);
}
}


注意‌:不同 Android 版本中,resolveHomeActivity 的具体实现可能略有差异(例如 Android 11+ 引入了 TaskDisplayArea 的概念),但核心判断逻辑依然是:‌检查用户解锁状态‌ 和 ‌Intent 解析优先级‌。

4. FallbackHome 的自我终结与切换

FallbackHome 启动后,并不是永远驻留。它内部有一个机制来检测何时该“退场”。

java
// packages/apps/Settings/src/com/android/settings/FallbackHome.java

public class FallbackHome extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fallback_home);

// 注册一个广播接收器或监听器,监控用户解锁状态
// 当用户输入密码/指纹解锁成功后,系统会发送 ACTION_USER_UNLOCKED
}

@Override
protected void onResume() {
super.onResume();
// 检查用户是否已经解锁
if (isUserUnlocked()) {
// 如果已解锁,说明正式的 Launcher 现在可以启动了
// 启动真正的 Home Intent (此时 resolveHomeActivity 会返回 Launcher)
startActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
// 结束自己
finish();
} else {
// 如果未解锁,保持显示,等待解锁
// 可能会显示一个进度条或 "Android is starting..." 提示
}
}

private boolean isUserUnlocked() {
UserManager um = getSystemService(UserManager.class);
return um.isUserUnlocked();
}
}

5. 总结:切换流程图
mermaid
生成失败,请稍后重试~
关键点注释说明

android:directBootAware="true"‌:

这是 FallbackHome 能在开机未解锁时启动的根本原因。普通 Launcher 如果没有声明此属性,在设备加密未解锁阶段对系统是不可见的(PackageManager 不会解析到它)。

Intent Filter Priority‌:

FallbackHome 的 <intent-filter> 中通常设置 android:priority="-1000"。
正式 Launcher 的 priority 通常为 0 或更高。
当用户解锁后,resolveHomeActivity 会重新查询所有 Home Activity,由于优先级差异,系统会自动选择正式 Launcher,从而实现“无感切换”。

startHomeActivity 的幂等性‌:

系统可能会多次调用 startHomeOnDisplay。如果当前前台已经是 Home Activity(无论是 Fallback 还是正式),系统会根据情况决定是否需要重新启动或只是 bring to front。

ANR 保护‌:

FallbackHome 作为一个轻量级 Activity,其启动速度极快,避免了因 Launcher 加载缓慢(如资源多、插件化初始化等)导致的长时间黑屏或 ANR(Application Not Responding)。它充当了一个“占位符”,确保窗口管理器(WMS)始终有一个合法的 Home Task 存在。

通过这套机制,Android 保证了从开机到用户可交互界面的平滑过渡,同时解决了加密设备在未解锁状态下的 UI 展示问题。

4