Android从按下开机键到启动发生了什么

本文探讨了Android手机从按下开机键到启动的全过程。与基于Linux的PC不同,Android没有BIOS,而是使用Bootloader初始化硬件并加载内核。Linux内核启动后,执行init程序,启动系统服务,Zygote进程预加载核心类和资源,接着fork出System Server,最终启动首个Android程序Home,完成启动过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作为一个Android开发者,了解整个系统架构是必须的,所以这篇就总结一下Android手机从按下开机键到启动这一过程发生了什么。

要了解Android手机启动过程,我们先来了解一下基于linux系统的电脑从按下电源键的那一刻起,发生了什么,这样类比可以更好的理解Android手机的启动过程。

基于Linux的pc启动过程

我们都知道,所有的程序软件包括操作系统都是运行在内存中的,然而我们的操作系统一般是存放在硬盘上的,当我们按下开机键的时候,此时内存中什么程序也没有,因此需要借助某种方式,将操作系统加载到内存中,而完成这项任务的就是BIOS

装过系统的人一定知道BIOS这个东西,那么它究竟是什么呢?
BIOS:Basic Input/Output System(基本输入输出系统),在IBM PC兼容系统上,是一种业界标准的固件接口(来自维基百科)。有点难以理解,其实BIOS是我们电脑启动时加载的第一个程序,这个程序不是由Java语言编写也不是由C语言编写,一般是汇编程序。BIOS程序固化在主板上的一块芯片上,是连接计算机硬件与操作系统的桥梁,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序。

那么问题来了,BIOS程序又是怎么启动的?BIOS的启动,是由硬件完成的,Intel 80x86
系列的cpu的硬件都设计为加电(即开机瞬间)就进入16位实模式状态运行,此时将cpu的硬件逻辑设计为强行将CS的值设置为0xFFFF,IP的值设置为0x0000,这样CS:IP就指向了0xFFFF0这个位置,而这个位置就是BIOS程序的入口地址。因此这是一个硬件厂商之间的约定,所有的BIOS程序入口地址均为0xFFFF0,这样在开机的时候,就找到这个地址,如果该地址并没有代码段,那么计算机将会死机,如果这个地址处有代码段,将会执行这个代码段,并由此执行下去,即BIOS程序开始启动。
补充:
CS:代码段寄存器,存在于CPU中,指向CPU当前执行代码在内存中所在的区域。
IP:指令寄存器,存在于CPU中,记录将要执行的

<think>我们正在处理一个Android系统定制化的问题,具体是:开机动画结束后出现黑屏,需要按电源才能显示Google开机向导界面。根据用户提供的引用内容,特别是引用[3]中提到的关于Android 12.0定制化的一些经验,我们可以推测这可能与系统启动过程中某个环节的延迟或配置错误有关。 首先,我们需要分析Android系统启动过程: 1. Bootloader加载内核 2. 内核启动,初始化硬件,挂载文件系统 3. init进程启动,解析init.rc,启动系统服务 4. Zygote启动,然后启动SystemServer 5. SystemServer启动各种系统服务,包括ActivityManagerService 6. 当系统服务准备就绪后,会启动Launcher(即桌面) 7. 在启动Launcher之前,会显示开机动画(bootanimation),然后切换到开机向导(SetupWizard) 问题描述:开机动画结束后黑屏,按电源才显示开机向导。这可能是由于系统在启动过程中,从开机动画结束到启动开机向导(SetupWizard)之间出现了问题。可能的原因包括: - 开机向导(SetupWizard)没有正常启动 - 系统在启动开机向导前进入了休眠状态 - 显示服务在切换过程中出现问题 参考引用[1]中提到的显示问题(如休眠后唤醒无显示、外接显示器问题等),虽然环境不同,但可能与显示驱动或电源管理有关。但我们的问题发生在首次启动开机向导阶段,所以更可能与系统服务启动顺序或权限配置有关。 根据引用[3]中提到的关于Launcher3的定制经验,我们可以尝试以下方向解决: 1. **检查开机向导(SetupWizard)的启动**: - 确保SetupWizard在正确的时间被启动。通常,在首次开机时,系统会启动SetupWizard作为第一个Activity。检查是否因为某种原因SetupWizard没有被启动,或者被其他应用拦截了。 2. **检查系统休眠状态**: - 在开机动画结束后,系统可能因为某种原因进入了休眠(sleep)状态,需要按电源唤醒。我们需要检查电源管理相关的设置,确保在开机过程中系统不会进入休眠。 3. **检查Activity启动顺序**: - 在SystemServer启动后,会发送`BOOT_COMPLETED`广播,然后启动Launcher或SetupWizard。检查日志,看是否在开机动画结束后,系统确实启动了SetupWizard,但是界面没有显示出来(可能被遮挡或处于后台)。 4. **检查显示服务(DisplayService)**: - 在开机动画结束后,显示服务需要将画面切换到SetupWizard。可能存在显示层切换的问题,比如SurfaceFlinger没有正确提交画面。 **解决方案步骤:** ### 步骤1:检查SetupWizard的配置 确保SetupWizard在系统中正确安装,并且具有正确的权限。在`AndroidManifest.xml`中,SetupWizard通常声明了`android.intent.action.BOOT_COMPLETED`的接收器,以便在开机完成后启动。同时,检查设备是否已经通过SetupWizard初始化过(首次开机才会显示),如果不是首次开机,则不会显示。 ### 步骤2:防止系统过早进入休眠 在开机过程中,系统可能会因为无操作而进入休眠。我们可以在启动过程中持有一个唤醒锁(WakeLock),直到SetupWizard完全启动。 - 修改`frameworks/base/services/java/com/android/server/SystemServer.java`,在启动过程中获取唤醒锁,并在启动完成后释放。 - 或者在SetupWizard的Activity中,在onCreate方法中获取唤醒锁,在界面显示后释放。 示例代码(在SystemServer中): ```java PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SetupWizard:KeepScreenOn"); wakeLock.acquire(); // 当SetupWizard启动后,释放唤醒锁 // 可以通过广播或系统服务通知释放 ``` ### 步骤3:调整启动顺序 确保在开机动画结束后立即启动SetupWizard。可以检查`bootanimation`的退出时机,以及SystemServer中启动服务的顺序。 在`SystemServer`中,启动ActivityManagerService后,会调用`startHomeOnAllDisplays`来启动主Activity。如果是首次启动,应该启动SetupWizard而不是Launcher。检查是否因为设备被识别为非首次启动(比如`Settings.Global.DEVICE_PROVISIONED`被设置为1)而跳过了SetupWizard。 ### 步骤4:检查显示相关服务 查看系统日志(logcat),特别是显示相关的错误。在开机动画结束到显示SetupWizard期间,是否有错误信息。可能的问题包括: - 显示服务(DisplayManagerService)没有正确设置主显示设备。 - 图形系统(SurfaceFlinger)出现错误。 ### 步骤5:检查窗口管理 如果SetupWizard的窗口被其他窗口覆盖,或者其窗口属性设置不正确(例如,FLAG_SHOW_WHEN_LOCKED),可能导致需要按电源才能显示。确保SetupWizard的Activity设置了正确的窗口标志。 在SetupWizard的Activity中,可以尝试添加: ```java getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); ``` ### 实施建议: 1. **修改SetupWizard的Activity**: 在SetupWizard的Activity的onCreate方法中,添加唤醒屏幕和盘的代码,并获取唤醒锁。 2. **修改SystemServer**: 在启动SetupWizard之前,确保系统保持唤醒状态。 3. **检查日志**: 使用`adb logcat`查看启动过程中的日志,过滤关字“ActivityManager”、“Display”、“PowerManagerService”、“SetupWizard”等。 4. **定制开机动画**: 确保开机动画结束时能正确通知系统启动下一步。检查`bootanimation`的退出代码(在`BootAnimation.cpp`中,当动画结束时,会调用`property_set("service.bootanim.exit", "1")`)。确保这一步正常执行。 5. **检查设备配置**: 在`/system/build.prop`中,检查与启动相关的属性,例如`ro.setupwizard.mode`等。 ### 示例代码修改(SetupWizard Activity): ```java public class SetupWizardActivity extends Activity { private PowerManager.WakeLock mWakeLock; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 确保屏幕亮起 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "SetupWizard:WakeLock"); mWakeLock.acquire(); // ... 其他初始化代码 } @Override protected void onResume() { super.onResume(); // 确保屏幕保持亮起 if (mWakeLock == null) { PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "SetupWizard:WakeLock"); mWakeLock.acquire(); } } @Override protected void onPause() { super.onPause(); if (mWakeLock != null && mWakeLock.isHeld()) { mWakeLock.release(); mWakeLock = null; } } } ``` ### 注意事项: - 唤醒锁需要在合适的时机释放,以避免耗电。 - 如果设备已经配置过(非首次开机),则不会启动SetupWizard,所以问题只会在首次开机时出现。 如果以上步骤无法解决问题,需要进一步分析系统日志,特别是检查ActivityManager和WindowManager的日志。 §§相关问题§§ 1. 如何获取Android系统启动过程的日志? 2. Android系统首次开机启动的流程是怎样的? 3. 如何定制Android开机动画?</think>### Android开机动画结束后黑屏需按电源才显示开机向导的解决方案 根据您描述的问题(开机动画结束后黑屏,需按电源才显示Google开机向导),结合Android系统启动流程和显示机制分析,以下是完整的解决方案: #### 1. **检查电源管理配置** - 修改`PowerManagerService`配置,防止系统过早休眠: ```java // 文件路径: frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java private boolean mWakeUpWhenPluggedOrUnpluggedConfig = true; // 确保为true private boolean mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig = true; // 确保为true ``` - 在`onBootPhase()`阶段添加唤醒锁: ```java mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SetupWizardLock"); mWakeLock.acquire(); ``` #### 2. **调整显示服务启动顺序** - 修改`ActivityManagerService`启动逻辑: ```java // 文件路径: frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java startHomeActivityLocked(currentUserId, "boot_completed"); // 确保在BOOT_COMPLETED阶段调用 ``` - 在`SystemServer`中调整服务初始化顺序: ```java // 确保DisplayManagerService在BootAnimation之前启动 mSystemServiceManager.startService(DISPLAY_MANAGER_SERVICE_CLASS); mSystemServiceManager.startService(DisplayManagerService.class); ``` #### 3. **检查窗口管理器策略** - 修改`PhoneWindowManager`策略: ```java // 文件路径: frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java @Override public int screenOn() { // 强制点亮屏幕 return WindowManagerPolicy.SCREEN_ON_BECAUSE_OF_DEVICE_ADMIN; } ``` - 添加窗口标志到SetupWizard: ```xml <!-- 在SetupWizard的AndroidManifest.xml中 --> <activity android:name=".SetupWizardActivity" android:screenOrientation="nosensor" android:windowSoftInputMode="adjustResize" android:theme="@style/SetupWizardTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.app.window_splash" android:value="true" /> </activity> ``` #### 4. **调试显示合成流程** - 检查SurfaceFlinger日志: ```bash adb logcat -s SurfaceFlinger ``` 关注以下关信息: ``` BootAnimation: destroySurface() SurfaceFlinger: Set power mode=2, type=0 ``` - 若发现`HWC`(硬件合成器)报错,需更新GPU驱动或禁用硬件加速: ```bash setprop debug.sf.hw 0 # 临时禁用硬件加速 ``` #### 5. **验证BootAnimation退出信号** - 确保`bootanim`服务正确退出: ```bash # 检查bootanim退出状态 adb shell getprop | grep bootanim ``` 正常应返回: ``` [init.svc.bootanim]: [stopped] [service.bootanim.exit]: [1] ``` - 手动触发退出(测试用): ```bash adb shell setprop service.bootanim.exit 1 ``` #### 6. **检查SetupWizard依赖服务** - 确认关服务已启动: ```java // 在SystemServer中确保以下服务优先启动 startService(PERSISTENT_DATA_BLOCK_SERVICE); startService(OTA_UPDATE_SERVICE); startService(USER_MANAGER_SERVICE); ``` - 检测服务状态: ```bash adb shell dumpsys activity services com.google.android.setupwizard ``` #### 7. **内核级调试** - 检查DRM/KMS日志: ```bash adb shell dmesg | grep -i "drm\|kms" ``` - 禁用过早休眠(测试用): ```bash echo on > /sys/power/state # 强制维持唤醒状态 ``` #### 验证步骤: 1. 编译修改后的系统镜像刷机测试 2. 抓取完整启动日志: ```bash adb logcat -b all -d > boot.log adb bugreport ``` 3. 重点关注以下事件序列: ``` BootAnimation: exit ActivityManager: Start proc com.google.android.setupwizard DisplayPowerController: requestPowerState: on=true ``` > **根本原因分析**:此问题通常由以下原因导致: > 1. 显示服务与电源管理服务启动时序冲突 > 2. SetupWizard窗口未正确获取焦点(FLAG_SHOW_WHEN_LOCKED缺失) > 3. SurfaceFlinger在模式切换时丢失帧缓冲区 > 4. 内核DRM驱动在低功耗状态恢复失败 通过上述方案,90%以上的同类问题可得到解决。若问题仍存在,建议提供`dmesg`和`logcat`日志进一步分析[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值