【Java精品源码栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了Java精品源码-【精品】Android启动过程分析 - 其它资料的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
Android 启动过程Key bootup componentsBootloader系统引导Bootloader 是 Android 系统加电运行的第一个程序,这只是 android 的外围程序,主要是在加载 linux 内核之前做些低级别的系统初始化工作。
在启动用户空间的应用程序之前,系统内核负责硬件、驱动和文件系统等一系列模块和组件的初始化工作。
The first program which runs on any Android system is the bootloader. Technically the bootloader isoutside the realm of Android itself and is used to do very low-level system initialization beforeloading the Linux kernel. The kernel then does the bulk of hardware driver and file systeminitialization before starting up the user-space programs and applications that make up Android.第一阶段的系统引导过程包括装载恢复镜像,或进行其他的系统恢复、更新和调试任务。
Often the first-stage bootloader will provide support for loading recovery images to the system flashor performing other recovery update or debugging tasks.The bootloader on the ADP1 detects certain keypresses which can be used to make it load arecovery image second instance of the kernel and system or put the phone into a mode where thedeveloper can perform development tasks fastboot mode such as re-writing flash images directlydownloading and executing an alternate kernel image etc.init初始化A key component of the Android bootup sequence is the program init which is a specializedprogram for initializing elements of the Android system. Unlike other Linux systems embedded orotherwise Android uses its own initialization program. Linux desktop systems have historicallyused some combination of /etc/inittab and sysV init levels - e.g. /etc/rc.d/init.d with symlinks in/etc/rc.d/rc.2345. Some embedded Linux systems use simplified forms of these -- such as the initprogram included in busybox which processes a limited form of /etc/inittab or a direct invocation ofa shell script or small program to do fixed initialization steps.The init program processes two files executing the commands it finds in them called init.rc andinit.ltmachine_namegt.rc where ltmachine_namegt is the name of the hardware that Android isrunning on. Usually this is a code word. The name of the HTC1 hardware for the ADP1 is trout andthe name of the emulator is goldfish.the init.rc file is intended to provide the generic initialization instructions while theinit.ltmachine_namegt.rc file is intended to provide the machine-specific initialization instructions.init resourcesThe syntax for these .rc files is documented in a readme file in the source tree. See the Android initlanguage referenceOr see also: http://www.kandroid.org/android_pdk/bring_up.htmlSee also http://www.androidenea.com/2009/08/init-process-and-initrc.htmlSequence of boot steps on ADP1firmwarefirst-stage bootloader runsit detects if a special key is held and can launch the recovery image or the fastboot bootloadereventually a kernel is loaded into RAM usually with an initrdnormally this will be the kernel from the kernel flash partition.kernelthe kernel bootscore kernel initializationmemory and I/O areas are initializedinterrupts are started and the process table is initializeddriver initializationkernel daemons threads are startedroot file system is mountedthe first user-space process is startedusually /init note that other Linux systems usually start /sbin/inituser spacethe kernel runs /init/init processes /init.rc and /init.ltmachine_namegt.rcdalvik VM is started zygote. See Android Zygote Startupseveral daemons are started:rild - radio interface link daemonvold - volume daemon media volumes as in file systems - nothing to do with audio volumethe system_server starts and initializes several core servicesSee http://www.androidenea.com/2009/07/system-server-in-android.htmlinitalization is done in 2 steps:1 a library is loaded to initialize interfaces to native services then2
java-based core services are initialized in ServerThread::run in SystemServer.javathe activity manager starts core applications which are themselves dalvik applicationscom.android.phone - phone applicationandroid.process.acore - home desktop and a few core apps.other processes are also started by /init somewhere in there:adbmediaserverdbus-daemonakmdTools for analyzing Android BootupBootchart - see Using Bootchart on AndroidNotes on the Android startup procedureOverviewSee quotAndroid Initialization Processquot at: http://blog.chinaunix.net/u2/85805/showart_1421736.htmlstracehttp://benno.id.au/blog/2007/11/18/android-runtime-straceInteraction of different processes on application initializationTalking about Android Process - http://blog.csdn.net/mawl2002/archive/2009/06/24/4295905.aspx文章分类:
Java 编程1. Boot 系统初始化, 具体过程参见systemcoreinitInit.c中的 main 函数,这时候,手机或者模拟器出现的画面是一个 console,显示“ANDROID”msg。
2. 初始化成功后,就开始 mounting 系统,具体参见systemcoremountdMountd.c 中的 main 函数。
3.接下来运行 androidRuntime,并开始启动
java 虚拟机 dalvikvm。
4.
Java 虚拟机启动成功后,开始系统初始化。
系统初始的第一步是用 JNI 方式实现的,对应
java 代码为frameworksbaseservicesjavacomandroidserverSystemServer.
java init1(Native)函数,对应的 JNI C代码为frameworksbasecorejniservercom_android_server_SystemServer.cpp,而实现的 C代码为frameworksbasecmdssystem_serverlibrary System_init.cpp 中的 system_init()函数。
5. system_init 调用 SurfaceFlinger,SurfaceFlinger 的 readyToRun函数用 BootAnimation 来实现开机动画,这时候手机或者模拟器显示是一副背景图加一个动态的小机器人。
6. 系统初始化的第二步,将启动 ServerThread 进程,参见 SystemServer.init2。
ServerThread 将启动各种系统服务,如 Power Manager、Activity Manager 等等,具体参见 ServerThread 的 run 函数,ServerThread 同在 SystemServer.
java 中。
7.这之后的事,应该就是进入系统了。
。
(这部分没有调查过)--------------------------------------------------------------------------------对于关注 Android 底层的朋友来说,其具体的启动过程应该是比较吸引我们的。
但是很多启动文件什么的,都得 adb push 到 host 上来看,挺不方便的,都怪 Android 自带的 Toolbox 太简略了。
所以在深入了解 Android 的启动流程之前,我们来把 Busybox 安装到 Android 上去,这样,就有很多工具供我们使用了。
首先去 busybox 主页 下载最新版本的源代码,然后用 arm 的交叉编译器编译出 busybox的可执行程序,编译的时候需要注意一些设置选项,例如 Build Options —gt Build BusyBox as a static binary no shared libs 这个要选上,因上这样子编译出来的 busyBox才是可以独立运行的。
│Do you want to build BusyBox with a Cross Compiler │ │ │ │/HOME/toolchains/gcc-4.0.2-glibc-2.3.5/arm-9tdmi-linux-gnu/bin/arm-9tdmi-linux-gnu│ 这是交叉编译器的路径,要根据具体的情况来设置。
Installation Options —gt Don’t use /usr 这样子编译出来的 busybox 才不会安装到你主机的/usr 目录下。
一定要选上。
busybox 的功能选项根据需要自选但是不要太贪心. OK,这里就不纠缠于编译 busybox 的东西了,网上资料无数。
接下来,我们把 busybox安装到模拟器上去。
先在模拟器上随便建一个 busybox 的文件夹,然后进入 busybox 可执行文件目录,使用命令 adb push busybox.asc /data/busybox/busybox 然后进入 adb shell,chmod 777 ./busybox,就可以直接使用了。
但现在还是不方便,总不能每用一个命令就输一次 busybox 吧所以,我们可以先用./busybox --install 将程序都安装到当前目录下,然后把当前目录添加到 PATH 变量中即可。
暂时使用 export 来添加吧,如果想永久添加,往下看。
好了,准备工作完成,开始研究的工作了。
既然是研究启动过程,那当然是先看看 init.rc文件。
去 etc 目录打开它,分析一下内容,首先是对 env 的定义,也就是全局环境变量的定义,接下来的建立和初始化里面的内容目前还不清楚什么意思, 紧接着就是系统启动时运行的初始进程信息, 这个比较有意思,包括了 usbd-config 和 qemu,qemu 自不用说, usbd-config 而作为初始启动的进程, 应该就是和上一篇文章猜的一样, 用来调试或者 usb 通信的。
往下看,是在初始启动进程完成之后开始启动的服务进程,这些进程如果因故退出,会自动重启。
这里面包括了 console 控制台,adbd 监护进程,usbd 监护进程,debuggerd 监护进程等.除去这些守护进程,能引起我们注意的,是 runtime 和 zygote。
这两个进程似乎掌管着其他进程以及应用程序的启动。
现在,来让我们做一个实验吧,将自动调用的启动过程变成手动,看看启动流程具体是什么样的。
想达到这个目的,首先就是要修改 init.rc 文件,当然不是在模拟器的 console 中改,一是不能改,二是你改了也没用,下次加载就会给你覆盖了。
所以,我们要从原始镜像ramdisk.img 入手了。
从 2.6 标准 Linux 内核开始,initrd.img 都采用 cpio 压缩,猜测 ramdisk.img也一样,需要使用 gunzip 解压缩,然后再使用 cpio 解包。
好,进入 tools/lib/images 目录下,先用 file 命令看看 ramdisk.img 的类型,没错,系统提示 ramdisk.img: gzip compressed data from Unix 很好,然后将 ramdisk.img 复制一份到任何其他目录下,将其名称改为 ramdisk.img.gz,并使用命令 gunzip ramdisk.img.gz 然后新建一个文件夹,叫 ramdisk 吧,进入,输入命令 cpio -i -F ../ramdisk.img 这下,你就能看见并操作 ramdisk 里面的内容了。
当然你也可以直接在外面进行操作,但是还是建议把 cpio 解压缩出来的内容全部集中在一个文件夹里面,因为一会我们还要将其压缩成新的 ramdisk.img。
OK,现在开始修改步骤吧。
用任何一款编辑器打开 init.rc,首先在 PATH 那里加上你的Busybox 安装路径,然后注释内容,我们要手工启动他们。
zygote exec /system/bin/app_process args 0 -Xzygote 1/system/bin 2 –zygote autostart 1 runtime exec/system/bin/runtime autostart 1 在这里需要注意,不要同时把两者都注释了,注释某一个,再试验手工启动它,如果两者同时注释我这里有问题,无法启动。
好,接下来,使用下列命令重新打包成镜像 cpio -i -t -F ../ramdisk.img gt list cpio -o -H newc -O lk.img lt list 当前目录下生成的 lk.img 就是我们的新镜像了。
使用自己的镜像启动 emulator emulator -console -ramdisk lk.img 如果我们注释的是 zygote,那么在后输入 app_process -Xzygote /system/bin –zygote 手工启动,命令行中输出的信息是 Prepping: /system/app/AlarmProvider.apk:/system/app/Browser.apk:/system/app/Calendar.apk:/system/app/Camera.apk:/system/app/Contacts.apk: /system/app/Development.apk:/system/app/GDataFeedsProvider.apk:/system/app/Gmail.apk:/system/app/GmailProvider.apk:/system/app/GoogleApps.apk: /system/app/GoogleAppsProvider.apk:/system/app/Home.apk:/system/app/ImProvider.apk:/system/app/Maps.apk:/system/app/MediaPickerActivity.apk: /system/app/MediaProvider.apk:/system/app/Phone.apk:/system/app/PimProvider.apk:/system/app/ApiDemos.apk:/system/app/SettingsProvider.apk: /system/app/Sms.apk:/system/app/SyncProvider.apk:/system/app/TelephonyProvider.apk:/system/app/XmppService.apk:/system/app/YouTube.apk File not found: /system/app/AlarmProvider.apk File not found: /system/app/Calendar.apk File not found: /system/app/Camera.apk File not found: /system/app/GDataFeedsProvider.apk File not found: /system/app/Gmail.apk File not found: /system/app/GmailProvider.apk File not found: /system/app/MediaPickerActivity.apk File not found: /system/app/PimProvider.apk File not found: /system/app/ApiDemos.apk File not found: /system/app/Sms.apk File not found: /system/app/SyncProvider.apk File not found: /system/app/YouTube.apk Prep complete 嘿嘿,从 File not found 的信息中可以看到一些 Google 可能会即将推出的应用,比如 Gmail什么的。
当然,这些都是
Java 框架的启动信息,我们以后还要借助其他工具来进行进一步探索。
如果我们注释的是 runtime,那么输出信息是: post-zygote 老实说,没有明白这是啥意思,呵呵,吃饭时间到了,懒得看了。
好了,今天就说到这,基本的方法就是这样,有兴趣的朋友可以进一步深入研究。
我们下一篇文章见。
Android 启动过程代码分析开机过程中无线模块的初始化过程如果 sim 卡锁开启,或者 pin 被锁住的时候,会要求输入pin 或者 puk,但是这个解锁动作必须在系统初始化完成以后才能进行。
图形系统都还没有初始化怎么输入密码阿当系统初始化完成以后会调用 wm.systemReady来通知大家。
这时候该做什么就做什么。
开机过程中无线模块的初始化过程: rild 调用参考实现 Reference-ril.c hardwarerilreference-ril 中的函数: const RIL_RadioFunctions RIL_Initconst struct RIL_Env env int argc char argv ret pthread_createamps_tid_mainloop ampattr mainLoop NULL static void mainLoopvoid param ret at_openfd onUnsolicited RIL_requestTimedCallbackinitializeCallback NULL ampTIMEVAL_0 在 initializeCallback 函数中对猫进行了初始化。
static void initializeCallbackvoid param ATResponse p_response NULLint errsetRadioState RADIO_STATE_OFFat_handshake/ note: we dont check errors here. Everything important willbe handled in onATTimeout and onATReaderClosed // atchannel is tolerant of echo but it must // have verbose result codes /at_send_commandquotATE0Q0V1quot NULL/ No auto-answer /at_send_commandquotATS00quot NULL/ Extended errors /at_send_commandquotATCMEE1quot NULL/ Network registration events /err at_send_commandquotATCREG2quot ampp_response/ some handsets -- in tethered mode -- dont support CREG2 /if err lt 0 p_response-gtsuccess 0 at_send_commandquotATCREG1quot NULLat_response_freep_response/ GPRS registration events /at_send_commandquotATCGREG1quot NULL/ Call Waiting notifications /at_send_commandquotATCCWA1quot NULL/ Alternating voice/data off /at_send_commandquotATCMOD0quot NULL/ Not muted /at_send_commandquotATCMUT0quot NULL/ CSSU unsolicited supp service notifications /at_send_commandquotATCSSN01quot NULL/ no connected line identification /at_send_commandquotATCOLP0quot NULL/ HEX character set /at_send_commandquotATCSCSquotHEXquotquot NULL/ USSD unsolicited /at_send_commandquotATCUSD1quot NULL/ Enable CGEV GPRS event notifications but dont buffer /at_send_commandquotATCGEREP10quot NULL/ SMS PDU mode /at_send_commandquotATCMGF0quot NULLifdef USE_TI_COMMANDSat_send_commandquotATCPI3quot NULL/ TI specific -- notifications when SMS is ready currently ignored /at_send_commandquotATCSTAT1quot NULLendif / USE_TI_COMMANDS // assume radio is off on error /if isRadioOn gt 0 setRadioState RADIO_STATE_SIM_NOT_READY默认状况下假设射频模块是好的,通过 setRadioState RADIO_STATE_SIM_NOT_READY 来触发对无线模块的初始化。
通过 static void onRadioPowerOn 对无线模块初始化。
首先通过 pollSIMStateNULL 轮询 sim 卡状态 。
static void pollSIMState void paramATResponse p_responseint retif sState RADIO_STATE_SIM_NOT_READY // no longer valid to pollreturnswitchgetSIMStatus case RIL_SIM_ABSENT:case RIL_SIM_PIN:case RIL_SIM_PUK: case RIL_SIM_NETWORK_PERSONALIZATION: default: setRadioStateRADIO_STATE_SIM_LOCKED_OR_ABSENT return case RIL_SIM_NOT_READY: RIL_requestTimedCallback pollSIMState NULL ampTIMEVAL_SIMPOLL return case RIL_SIM_READY: setRadioStateRADIO_STATE_SIM_READY return 读取 sim 卡状态的函数是:getSIMStatus err at_send_command_singlelinequotATCPINquot quotCPIN:quot ampp_response 它向猫发送了 at 命令 ATCPIN 来查询无线模块的状态,如果无线模块还没有就绪,那么他隔 1 秒钟继续调用 sim 卡状态轮询函数 pollSIMState,直到获得 sim 卡状态。
那么通过 setRadioStateRADIO_STATE_SIM_READY 设置变量 sState 当 sim 卡状态为就绪,为: RADIO_STATE_SIM_READY,这时候会调用函数 static void onSIMReady来进一步初始化无线模块。
发送的 at 命令有: at_send_command_singlelinequotATCSMS1quot quotCSMS:quot NULL at_send_commandquotATCNMI12211quot NULL 如果 sim 卡锁开启,或者 pin 被锁住的时候,会要求输入 pin 或者 puk,但是这个解锁动作必须在系统初始化完成以后才能 进行。
图形系统都还没有初始化怎么输入密码阿当系统初始化完成以后会调用wm.systemReady来通知大家。
这时候该做什么就做什么。
wm.systemReady的调用会触发解锁界面。
具体流程如下: 因为有: WindowManagerService wm null所以 wm.systemReady 调用的是 WindowManagerService 中的函数: public void systemReady mPolicy.systemReady WindowManagerService 中有: final WindowManagerPolicy mPolicy Polic.
上一篇:
第7章_工具类及常用算法
下一篇:
“群众路线”:内涵、逻辑与特质心得体会