文档库 最新最全的文档下载
当前位置:文档库 › Android软件流程之App&&Framework&&Ril

Android软件流程之App&&Framework&&Ril

Android软件流程之App&&Framework&&Ril
Android软件流程之App&&Framework&&Ril

Android软件流程之

App&&Framework&&Ril

(待续)

前言

本人主要负责Android的Phone模块的bug修改,经过几个月的学习,熟悉了Phone 模块ARM11(App、Framework与Ril)的整体框架。本文我将带领大家熟悉Android的App层与Framework层与Ril层如何进行交互,让大家了解具体代码流程,了解体系的整体框架。下面我将首先介绍App层、Framework层的详细流程,之后是Ril层。

在看本文之前希望读者能对一下知识有所了解,特别是Android的Handler机制,当然在文章中我也会对下面知识加以简单介绍。

面向对象编程思想

设计模式

Android的Handle ,Message ,Looper 机制

第一部分

Android软件流程之App&&Framework

一. 简述

1.Ril概述

RIL(Radio Interface Layer)工作在Android的Framework层之下,主要有c语言编写,

还有一部分c++,它主要负责数据的可靠传输、上层命令的发送以及response的解析。当然,

除了对网络的支持,RIL也支持SMS、Call等功能。当然这么说还是很抽象,下面我们就来看

看Ril和上层进行交互的所有“消息”。

2.Ril和上层进行交互的“信息”

这里我所谓的“消息”,其实可以概括为二种:

?Request:

上层,也就是App层和Framework层下发给Ril层的一些请求(如打电话

RIL_REQUEST_DIAL, 获取SIM卡的状态RIL_REQUEST_GET_SIM_STATUS等),最终由Ril层

把这些请求下发给ARM9侧。

?Response:

Response代表ARM9侧向ARM11侧上报的一些信息,它又可以分为两种

?UNSOL_RESPONSE:主动上报的一些信息,如来短信,

?SOL_RESPONSE:上层下发的一些请求,是需要有应答的,也可以说是响应的,

如我下发了RIL_REQUEST_GET_SIM_STATUS,需要Ril上报回来SIM_STATUS,我

们把这些上报信息称为命令的响应。

这些“消息”分别在framework层和ril层,都有定义,framework层定义在

com.android.internal.telephony包中的Rilcommands.java中,ril层在ril_commands.h中

定义,这两处的定义是完全一致的,每条“信息”都是一一对应的。

下面我把所有的这些“信息”,都汇总在下面,并进行的简单的描述,来让大家知道Ril

到底在和App和Framework进行哪些“交互”:

下面我将根据具体“消息”的讲述其功能、流程,以这些“消息”为出发点,开始我们

的“流程之旅”

二. 具体的流程

1、/*取得SIM卡的状态*/

?RIL_REQUEST_GET_SIM_STATUS

?RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED

Android手机中,上层(注:本文中所说的“上层”如不做特别说明,代表App层和Framework层)

不会主动下发RIL_REQUEST_GET_SIM_STATUS获取SIM卡请求,而会在Ril层主动上报

RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED后,才会发送RIL_REQUEST_GET_SIM_STATUS 下面让我们来看具体流程

1)Ril层主动上报RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED

在上层中最终与Ril层进行对话的最后一道门是Ril.java,这个文件的非常重要,以至于

你如果能把Ril.java中的类和方法全部搞懂,你就不用看这篇文章了,你已经了解了上层的基

本流程。

下面我先介绍下Ril.java这个文件,这个文件定义了两个类RILRequest类和Ril类,其

中Ril类有定义了两个内部类RILReceiver和RILSender,各个类的关系与作用见下图:在Ril构造函数中,我们会开启RILReceiver线程,

之后RILReceiver线程就开始监听Ril层是否有上报信息,具体的就是监听上层与Ril层的socket通道

Ril层上报的信息是以Parcel类型传上来的,通过监听Socket通道,一旦有信息上报,就进入了信息的处理函数processResponse (Parcel p):

在processResponse (Parcel p)中通过读取P的“第一位”信息,判断上报信息的类型,对主动上报和命令的响应两种信息分别处理,由于RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED是主动上报的所以进入processUnsolicited (Parcel p):

protected void processUnsolicited (Parcel p){

……

Response=p.readInt()

//读取P中的“第二位”信息,注意与第一次p.readInt()的值并不一样

……

……

……

……

上面的process函数通过读取Ril上报的p的“第二位”信息判断出来是上报的具体信息是RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,最后调用

setRadioStateFromRILInt(p.readInt())函数,并读取p中的“第三位”信息并作为参数.

通过p中打包的第三位数值。判断出来,具体的上报信息,并把这个具体的无线状态赋值给一个枚举类型newstate,并最后调用setRadioState(RadioState newState)。上面所说的newstate是了枚举类型,它定义在Basecomands中:

enum RadioState {

RADIO_OFF, /* Radio explictly powered off (eg CFUN=0) */ RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */ SIM_NOT_READY, /* Radio is on, but the SIM interface is not ready */ SIM_LOCKED_OR_ABSENT, /* SIM PIN locked, PUK required, network

personalization, or SIM absent */

SIM_READY, /* Radio is on and SIM interface is available */ RUIM_NOT_READY, /* Radio is on, but the RUIM interface is not ready */

RUIM_READY, /* Radio is on and the RUIM interface is available */ RUIM_LOCKED_OR_ABSENT, /* RUIM PIN locked, PUK required, network

personalization locked, or RUIM absent */ NV_NOT_READY, /* Radio is on, but the NV interface is not available */

NV_READY; /* Radio is on and the NV interface is available */ public boolean isOn() /* and available...*/ {

return this == SIM_NOT_READY

|| this == SIM_LOCKED_OR_ABSENT

|| this == SIM_READY

|| this == RUIM_NOT_READY

|| this == RUIM_READY

|| this == RUIM_LOCKED_OR_ABSENT

|| this == NV_NOT_READY

|| this == NV_READY;

}

public boolean isAvailable() {

return this != RADIO_UNAVAILABLE;

}

public boolean isSIMReady() {

return this == SIM_READY;

}

public boolean isRUIMReady() {

return this == RUIM_READY;

}

……

……

它其中不仅含有上报具体信息的定义,还提供了一些方法,如isNVReady(),这些方法都是通过上报的具体信息做的一些简单逻辑判断。

下面是setRadioState的定义:

com.android.internal.telephony - frameworks/base/telephony/java– BaseCommand.java

/**

*All Registers:

*CdmaDataConnectionTracker:调用虚函数onRadioAvailable()

*CDMAPhone:调用getBasebandVersion()发送RIL_REQUEST_BASEBAND_VERSIO

请求获取基带版本

getDeviceIdentity()发送RIL_REQUEST_DEVICE_IDENTITY请求

*CdmaServiceStateTracker:Do Nothing

*/

if (mState.isAvailable() && !oldState.isAvailable()) {

Log.d(LOG_TAG,"Notifying: radio available");

mAvailRegistrants.notifyRegistrants();

onRadioAvailable();

}

/**

*All Registers:

*CdmaCallTracker: 调用handleRadioNotAvailable()

* ->pollCallsWhenSafe()

* ->RIL_REQUEST_GET_CURRENT_CALLS请求

*/

if (!mState.isAvailable() && oldState.isAvailable()) {

Log.d(LOG_TAG,"Notifying: radio not available");

mNotAvailRegistrants.notifyRegistrants();

}

if (mState.isSIMReady() && !oldState.isSIMReady()) {

Log.d(LOG_TAG,"Notifying: SIM ready");

mSIMReadyRegistrants.notifyRegistrants();

}

if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {

Log.d(LOG_TAG,"Notifying: SIM locked or absent");

mSIMLockedRegistrants.notifyRegistrants();

}

/**

*All Registers:

* CdmaServiceStateTracker: 调用getCDMASubscription

* ->发送RIL_REQUEST_CDMA_SUBSCRIPTION请求

* RuimCard:调用getIccCardStatus

* ->发送RIL_REQUEST_GET_SIM_STATUS请求

* RuimRecords:调用onRuimReady()

* ->发送广播broadcastIccStateChangedIntent

* ->调用getIccCardStatus

* ->发送RIL_REQUEST_GET_SIM_STATUS请求

*/

if (mState.isRUIMReady() && !oldState.isRUIMReady()) {

Log.d(LOG_TAG,"Notifying: RUIM ready");

mRUIMReadyRegistrants.notifyRegistrants();

}

/**

*All Registers:

* RuimCard: 调用getIccCardStatus()

* ->发送RIL_REQUEST_GET_CURRENT_CALLS请求

*/

if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {

Log.d(LOG_TAG,"Notifying: RUIM locked or absent");

mRUIMLockedRegistrants.notifyRegistrants();

}

/**

*All Registers:

* CdmaDataConnectionTracker: 调用onNVReady()

* —>onTrySetupData

* CDMAPhone: 调用mNvLoadedRegistrants.notifyRegistrants() * ->通知它并的Registers

* CdmaServiceStateTracker:

* 调用cm.getCDMASubscription()

* ->发送RIL_REQUEST_CDMA_SUBSCRIPTION请求* pollState()

*/

if (mState.isNVReady() && !oldState.isNVReady()) {

Log.d(LOG_TAG,"Notifying: NV ready");

mNVReadyRegistrants.notifyRegistrants();

}

/**

*All Registers:

* SMSDispatcher: 调用reportSmsMemoryStatus

* —>RIL_REQUEST_REPORT_SMS_MEMORY_STATUS请求

* CdmaCallTracker: 调用handleRadioAvailable()

* -> pollCallsWhenSafe()

* ->发送RIL_REQUEST_GET_CURRENT_CALLS请求

* CdmaPhone: Do Nothing

*/

if (mState.isOn() && !oldState.isOn()) {

Log.d(LOG_TAG,"Notifying: Radio On");

mOnRegistrants.notifyRegistrants();

}

/**

*All Registers:

* CdmaDataConnectionTracker: 调用虚函数onRadioOffOrNotAvailable()

* RuimCard: 发送广播 broadcastIccStateChangedIntent * * RuimRecords: 调用RuimRecords中onRadioOffOrNotAvailable()

*/

if ((!mState.isOn() || !mState.isAvailable())

&& !((!oldState.isOn() || !oldState.isAvailable()))

) {

Log.d(LOG_TAG,"Notifying: radio off or not available");

mOffOrNotAvailRegistrants.notifyRegistrants();

}

if (mState.isGsm() && oldState.isCdma()) {

mRadioTechnologyChangedRegistrants.notifyRegistrants();

}

if (mState.isGsm() && !oldState.isOn() && (mPhoneType ==

Phone.PHONE_TYPE_CDMA)) {

mRadioTechnologyChangedRegistrants.notifyRegistrants();

}

/**

*All Registers:

* PhoneProxy: 根据上报信息,进行GSM和CDMA两者切换

*/

if (mState.isCdma() && oldState.isGsm()) {

mRadioTechnologyChangedRegistrants.notifyRegistrants();

}

/**

*All Registers:

* PhoneProxy: 根据上报信息,进行GSM和CDMA两者切换

*/

if (mState.isCdma() && !oldState.isOn() && (mPhoneType ==

Phone.PHONE_TYPE_GSM)) {

mRadioTechnologyChangedRegistrants.notifyRegistrants();

}

前面代码中我对每个上报信息的“注册者”,做了简单的介绍。这里所谓的注册者其实就是,Ril上报的信息,都会有哪些地方、哪些类响应此信息。比如,如果我们需要在某个类中响应

RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED信息,我们只需要在这个类中调用注册函数,

那么他就成为了这个信息的注册者也可以叫做监听者,注册者会被存储在Registantlist中,每个信息都对应一个Registantlist实例。当有上报信息时,它会通过调用notifyRegistrants函数,通知这个list中的所有注册者。

下面我们来选取一个具体的上报信息RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED-> RUIM_READY,跟踪一下它的具体流程,其它的上报信息走的流程大同小异。读者有兴趣的可以自己跟

一下。

上图是我对上报RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED-> RUIM_READY信息的函数,做了简单的介绍。下面我们来针对每个部分做已详细的介绍:

上图大概说明了如何成为一个注册者,如果我们需要监听某一个上报信息,只需要调用相应接口函数,本例中我们需要在RuimCard类中监听

RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED-> RUIM_READY信息,所以调用了CommandsInterface接口中的registerForRUIMReady注册函数,其具体定义是在实现CommandsInterface接口的BaseCommands类中。

上面的讲解大家肯定会很迷惑,下面我们就来进入上面那个注册函数的具体定义来加深对上

图的理解:

首先有必要先讲一下这个注册函数的参数

Handler:在注册者中定义,当有消息上报时,会在其中的handlemessage中响应。

(这里用到了Android的Handler机制,建议先阅读附录)

What:在注册中定义,当消息上报时,注册者会被通知的what这个信息。

下面是调用的注册函数的定义,在BaseCommands类中:

到此,我们把这个注册者加入到了mRUIMReadyRegistrants中,一旦上报

RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED-> RUIM_READY信息就会执行……

if (mState.isRUIMReady() && !oldState.isRUIMReady()) {

Log.d(LOG_TAG,"Notifying: RUIM ready");

mRUIMReadyRegistrants.notifyRegistrants();

……

通过mRUIMReadyRegistrants.notifyRegistrants()通知mRUIMReadyRegistrants中

的所有注册者。

现在我们假设Ril层上报给我们了RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED-> RUIM_READY消息,那么根据前面所讲,注册者会在注册时候传入的mHandler中响应到该消息,并做相应的处理,让我们来回到注册者,当然,现在他的身份其实是一个被通知者,

到此我们的ril上报信息、上层注册者的注册与响应的整个流程已经全部讲解完毕。

下面我们来讲一下上层下发请求的流程:

让我们回到刚才RuimCard这个注册者接收到RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED-> RUIM_READY信息的响应处理函数:

mPhone.mCM.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE))

其中obtainMessage(EVENT_GET_ICC_STATUS_DONE)函数很重要,函数作用是把RuimCard中定义的mHandler和EVENT_GET_ICC_STATUS_DONE存储在一个Message实例

里面,并返回这个Message实例。并把这个实例作为参数传进getIccCardStatus(Message result),下面我们来重点讲一下这个传下去Message实例的作用。

当我们发送一个请求后,我们会等待ril层给我们上报这个请求的响应(当然有的请求是不需要响应的,我们这里面谈论的是需要响应的请求),这个响应就是我最开始定义的

SOL_RESPONSE,前面对于主动上报的消息UNSOL_RESPONSE,已经做了详细的介绍是通过注册-通知机制完成的,那么这个SOL_RESPONSE也就是请求的响应消息,是如何上报的呢?上报给谁的呢?这其实完全决定于下发请求时候,传下来的这个Message实例,以getIccCardStatus为例,它传下去的Message实例(通过obtainMessage函数获得)里面包含RuimCard中定义的mHandler,那么当请求的响应到来的时候这个mHandler中的handleMessage会响应到,并调用相应的处理函数。

上面的响应函数调用的是mCM接口中的getIccCardStatus函数,其具体实现是在

Ril.java中:

在getIccCardStatus中把具体的请求号和上层传下来的Message实例构造成为一个RILRequest类型实例rr,其中上层传下来的Message实例被赋值给rr.mResult,,并最后

调用send函数:

下面就让我们来进入mSender中的handleMessage中看看它到底最后做了什么,

上图中mRequestsList就是一个ArrayList类型的链表,里面存储的“元素”是RILRequest,每个RILRequest实例rr以serial进行索引。其中add方法就是向mRequestsList链表中添加成员。其具体定义如下:

ArrayList mRequestsList = new ArrayList();

synchronized (mRequestsList) {

mRequestsList.add(rr);

}

到此为止,我们主动下发请求的流程我们也跟了一遍。终于可以歇口气了,发送完请求后轮

到ril和ARM9去做具体的动作了,我们要做的就是开始等待这个请求的SOL_RESPONSE了。

前面详细介绍的下发命令时候传下来的那个message也要派上用场了。

至于RILReceiver线程就监听Ril层上报信息,一旦有信息上报,就会调用processResponse (Parcel p),这一部分和ril主动上报信息UNSOL_RESPONSE的流程是一

样的,前面我们已经介绍过了,这里就不做介绍。和主动上报不同的是我们根据p中存取的“第

一位”信息判断这个上报的消息是UNSOL_RESPONSE后,调用的是processSolicited

(Parcel p):

上面最后调用rr.mResult.sendToTarget(),函数后,就会进入到下发请求时候传下来

那个Message中的Handler,在其中的handleMessage进行处理,由以上分析我们知道其实

rr.mResult就是这个传下来的Message,只不过在其中我们通过调用forMessage把上报的

一些信息添加到了这个Message中的obj成员变量中。

下面让我们回到发送请求的IccCard中的mHandler:

在getIccCardStatusDone中handleIccCardStatus((IccCardStatus) ar.result),最终根据电话卡的不同状态信息分发给“想要知道它们的地方”:

通过这个例子我们了解到,如何收到广播,也可以说如何收到下层上报的消息。

android系统开机启动流程分析

一,系统引导bootloader 加电,cpu执行bootloader程序,正常启动系统,加载boot.img【其中包含内核。还有ramdisk】 二,内核kernel bootloader加载kernel,kernel自解压,初始化,载入built-in驱动程序,完成启动。 内核启动后会创建若干内核线程,在后装入并执行程序/sbin/init/,载入init process,切换至用户空间(user-space) 内核zImage解压缩 head.S【这是ARM-Linux运行的第一个文件,这些代码是一个比较独立的代码包裹器。其作用就是解压Linux内核,并将PC指针跳到内核(vmlinux)的第一条指令】首先初始化自解压相关环境(内存等),调用decompress_kernel进行解压,解压后调用start_kernel启动内核【start_kernel是任何版本linux内核的通用初始化函数,它会初始化很多东西,输出linux版本信息,设置体系结构相关的环境,页表结构初始化,设置系 统自陷入口,初始化系统IRQ,初始化核心调度器等等】,最后调用rest_init【rest_init 会调用kernel_init启动init进程(缺省是/init)。然后执行schedule开始任务调度。这个init是由android的./system/core/init下的代码编译出来的,由此进入了android的代码】。 三,Init进程启动 【init是kernel启动的第一个进程,init启动以后,整个android系统就起来了】 init进程启动后,根据init.rc 和init. .rc脚本文件建立几个基本 服务(servicemanager zygote),然后担当property service 的功能 打开.rc文件,解析文件内容。【system/core/init/init.c】将service信息放置到service.list中【system/core/init/init_parser.c】。 建立service进程。【service_start(…) execve(…)】 在init.c中,完成以下工作 1、初始化log系统【解析/init.rc和init.%hardware%.rc文件,在两个 文件解析步骤2时执行“early-init”行动】 2、初始化设备【在/dev下创建所有设备节点,下载firmwares】 3、初始化属性服务器【在两个文件解析步骤2时执行“init”行动】

分析Android 开机启动慢的原因

开机启动花了40多秒,正常开机只需要28秒就能开机起来。 内核的启动我没有去分析,另一个同事分析的。我主要是分析从SystemServer启来到开机动画结束显示解锁界面的这段时间,也就是开机动画的第三个动画开始到结束这段时间,这是个比较耗时阶段,一般都在17秒左右(见过牛B的手机,只需5秒)。 SystemServer分两步执行:init1和init2。init1主要是初始化native的服务,代码在sy stem_init.cpp的system_init,初始化了SurfaceFlinger和SensorService这两个native的服务。init2启动的是java的服务,比如ActivityManagerService、WindowManagerService、PackageManagerService等,在这个过程中PackageManagerService用的时间最长,因为PackageManagerService会去扫描特定目录下的jar包和apk文件。 在开机时间需要40多秒的时,从Log上可以看到,从SurfaceFlinger初始化到动画结束,要27秒左右的时间,即从SurfaceFlinger::init的LOGI("SurfaceFlinger is starting")这句Log到void SurfaceFlinger::bootFinished()的LOGI("Boot is finished (%ld ms)", long(ns 2ms(duration)) ),需要27秒左右的时间,这显然是太长了,但到底是慢在哪了呢?应该在个中间的点,二分一下,于是想到了以启动服务前后作为分隔:是服务启动慢了,还是在服务启动后的这段时间慢?以ActivityManagerService的Slog.i(TAG, "System now ready")的这句Log为分割点,对比了一下,在从SurfaceFlinger is starting到System now read y多了7秒左右的时间,这说明SystemServer在init1和init2过程中启动慢了,通过排查,发现在init1启动的时候,花了7秒多的时间,也就是system_init的LOGI("Entered system _init()")到LOGI("System server: starting Android runtime.\n")这段时间用了7秒多,而正常情况是400毫秒便可以初始化完,通过添加Log看到,在SensorService启动时,用了比较长的时间。 不断的添加Log发现,在启动SensorService时候,关闭设备文件变慢了,每次关闭一个/dev/input/下的设备文件需要100ms左右,而SensorService有60~70次的关闭文件,大概有7s左右的时间。 调用流程是: frameworks/base/cmds/system_server/library/system_init.cpp: system_init->SensorServi ce::instantiate frameworks/native/services/sensorservice/SensorService.cpp: void SensorService::onFi rstRef()->SensorDevice& dev(SensorDevice::getInstance()) hardware/libsensors/SensorDevice.cpp: SensorDevice::SensorDevice()->sensors_open hardware/libsensors/sensors.cpp: open_sensors->sensors_poll_context_t sensors_poll_context_t执行打开每个传感器设备时,遍历/dev/input/目录下的设备文件,以匹配当前需要打开的设备,遍历文件是在 hardware/libsensors/SensorBase.cpp的openInput下实现,如果打开的设备文件不是正在打开的设备文件,会执行下面语句的else部分: if (!strcmp(name, inputName)) { strcpy(input_name, filename); break;

Android 开机启动流程

Android的开机流程 1. 系统引导bootloader 1) 源码:bootable/bootloader/* 2) 说明:加电后,CPU将先执行bootloader程序,此处有三种选择 a) 开机按Camera+Power启动到fastboot,即命令或SD卡烧写模式,不加载内核及文件系统,此处可以进行工厂模式的烧写 b) 开机按Home+Power启动到recovery模式,加载recovery.img,recovery.i mg包含内核,基本的文件系统,用于工程模式的烧写 c) 开机按Power,正常启动系统,加载boot.img,boot.img包含内核,基本文件系统,用于正常启动手机(以下只分析正常启动的情况) 2. 内核kernel 1) 源码:kernel/* 2) 说明:kernel由bootloader加载 3. 文件系统及应用init 1) 源码:system/core/init/* 2) 配置文件:system/rootdir/init.rc, 3) 说明:init是一个由内核启动的用户级进程,它按照init.rc中的设置执行:启动服务(这里的服务指linux底层服务,如adbd提供adb支持,vold提供SD卡挂载等),执行命令和按其中的配置语句执行相应功能 4. 重要的后台程序zygote 1)源码:frameworks/base/cmds/app_main.cpp等 2) 说明:zygote是一个在init.rc中被指定启动的服务,该服务对应的命令是/system/bin/app_process a)建立Java Runtime,建立虚拟机 b) 建立Socket接收ActivityManangerService的请求,用于Fork应用程序 c) 启动System Server 5. 系统服务system server 1)源码:frameworks/base/services/java/com/android/server/SystemServer.jav a 2) 说明:被zygote启动,通过SystemManager管理android的服务(这里的服务指frameworks/base/services下的服务,如卫星定位服务,剪切板服务等) 6. 桌面launcher 1)源码:ActivityManagerService.java为入口,packages/apps/launcher*实现 2) 说明:系统启动成功后SystemServer使用xxx.systemReady()通知各个服务,系统已经就绪,桌面程序Home就是在ActivityManagerService.systemReady()通知的过程中建立的,最终调用()启launcher 7. 解锁 1) 源码: frameworks/policies/base/phone/com/android/internal/policy/impl/*lock* 2) 说明:系统启动成功后SystemServer调用wm.systemReady()通知WindowManagerService,进而调用PhoneWindowManager,最终通过LockPatternKeyguardView显示解锁界面,跟踪代码可以看到解锁界面并不是一个Activity,这是只是向特定层上绘图,其代码了存放在特殊的位置

基于MT6752的 android 系统启动流程分析报告

基于MT6752的Android系统启动流程分析报告 1、Bootloader引导 (2) 2、Linux内核启动 (23) 3、Android系统启动 (23) 报告人: 日期:2016.09.03

对于Android整个启动过程来说,基本可以划分成三个阶段:Bootloader引导、Linux kernel启动、Android启动。但根据芯片架构和平台的不同,在启动的Bootloader阶段会有所差异。 本文以MTK的MT6752平台为例,分析一下基于该平台的Android系统启动流程。 1、Bootloader引导 1.1、Bootloader基本介绍 BootLoader是在操作系统运行之前运行的一段程序,它可以将系统的软硬件环境带到一个合适状态,为运行操作系统做好准备,目的就是引导linux操作系统及Android框架(framework)。 它的主要功能包括设置处理器和内存的频率、调试信息端口、可引导的存储设备等等。在可执行环境创建好之后,接下来把software装载到内存并执行。除了装载software,一个外部工具也能和bootloader握手(handshake),可指示设备进入不同的操作模式,比如USB下载模式和META模式。就算没有外部工具的握手,通过外部任何组合或是客户自定义按键,bootloader也能够进入这些模式。 由于不同处理器芯片厂商对arm core的封装差异比较大,所以不同的arm处理器,对于上电引导都是由特定处理器芯片厂商自己开发的程序,这个上电引导程序通常比较简单,会初始化硬件,提供下载模式等,然后才会加载通常的bootloader。 下面是几个arm平台的bootloader方案: marvell(pxa935) : bootROM + OBM + BLOB informax(im9815) : bootROM + barbox + U-boot mediatek(mt6517) : bootROM + pre-loader + U-boot broadcom(bcm2157) : bootROM + boot1/boot2 + U-boot 而对MT6752平台,MTK对bootloader引导方案又进行了调整,它将bootloader分为以下两个部分: (1) 第1部分bootloader,是MTK内部(in-house)的pre-loader,这部分依赖平台。 (2) 第2部分bootloader,是LK(little kernel的缩写,作用同常见的u-boot差不多),这部分依赖操作系统,负责引导linux操作系统和Android框架。 1.2、bootloader的工作流程 1.2.1 bootloader正常的启动流程 先来看启动流程图:

linux内核启动 Android系统启动过程详解

linux内核启动+Android系统启动过程详解 第一部分:汇编部分 Linux启动之 linux-rk3288-tchip/kernel/arch/arm/boot/compressed/ head.S分析这段代码是linux boot后执行的第一个程序,完成的主要工作是解压内核,然后跳转到相关执行地址。这部分代码在做驱动开发时不需要改动,但分析其执行流程对是理解android的第一步 开头有一段宏定义这是gnu arm汇编的宏定义。关于GUN 的汇编和其他编译器,在指令语法上有很大差别,具体可查询相关GUN汇编语法了解 另外此段代码必须不能包括重定位部分。因为这时一开始必须要立即运行的。所谓重定位,比如当编译时某个文件用到外部符号是用动态链接库的方式,那么该文件生成的目标文件将包含重定位信息,在加载时需要重定位该符号,否则执行时将因找不到地址而出错 #ifdef DEBUG//开始是调试用,主要是一些打印输出函数,不用关心 #if defined(CONFIG_DEBUG_ICEDCC)

……具体代码略 #endif 宏定义结束之后定义了一个段, .section ".start", #alloc, #execinstr 这个段的段名是 .start,#alloc表示Section contains allocated data, #execinstr表示Section contains executable instructions. 生成最终映像时,这段代码会放在最开头 .align start: .type start,#function /*.type指定start这个符号是函数类型*/ .rept 8 mov r0, r0 //将此命令重复8次,相当于nop,这里是为中断向量保存空间 .endr b 1f .word 0x016f2818 @ Magic numbers to help the loader

Android开机启动流程样本

Android的开机流程 1. 系统引导bootloader 1) 源码: bootable/bootloader/* 2) 说明: 加电后, CPU将先执行bootloader程序, 此处有三种选择 a) 开机按Camera+Power启动到fastboot, 即命令或SD卡烧写模式, 不加载内核及文件系统, 此处能够进行工厂模式的烧写 b) 开机按Home+Power启动到recovery模式, 加载recovery.img, recovery.img包含内核, 基本的文件系统, 用于工程模式的烧写 c) 开机按Power, 正常启动系统, 加载boot.img, boot.img包含内核, 基本文件系统, 用于正常启动手机( 以下只分析正常启动的情况) 2. 内核kernel 1) 源码: kernel/* 2) 说明: kernel由bootloader加载 3. 文件系统及应用init 1) 源码: system/core/init/* 2) 配置文件: system/rootdir/init.rc, 3) 说明: init是一个由内核启动的用户级进程, 它按照init.rc中的设置执行: 启动服务( 这里的服务指linux底层服务, 如adbd提供adb支持, vold提供SD卡挂载等) , 执行命令和按其中的配置语句执行相应功能 4. 重要的后台程序zygote 1) 源码: frameworks/base/cmds/app_main.cpp等 2) 说明: zygote是一个在init.rc中被指定启动的服务, 该服务对应的命令是/system/bin/app_process

Android系统启动过程详解

Android系统启动过程详解 Android系统启动过程 首先Android框架架构图:(来自网上,我觉得这张图看起来很清晰) Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。 启动的过程如下图所示:(图片来自网上,后面有地址)

下面将从Android4.0源码中,和网络达人对此的总结中,对此过程加以学习了解和总结, 以下学习过程中代码片段中均有省略不完整,请参照源码。

一Init进程的启动 init进程,它是一个由内核启动的用户级进程。内核自行启动(已经被载入内存,开始运行, 并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。init始终是第一个进程。 启动过程就是代码init.c中main函数执行过程:system\core\init\init. c 在函数中执行了:文件夹建立,挂载,rc文件解析,属性设置,启动服务,执行动作,socket监听…… 下面看两个重要的过程:rc文件解析和服务启动。 1 rc文件解析 .rc文件是Android使用的初始化脚本文件(System/Core/Init/readm e.txt中有描述: four broad classes of statements which are Actions, Commands, Services, and Options.) 其中Command 就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是linux 命令, 还有一些是android 添加的,如:class_start :启动服务,class_stop :关闭服务,等等。 其中Options是针对Service 的选项的。 系统初始化要触发的动作和要启动的服务及其各自属性都在rc脚本文件中定义。具体看一下启动脚本:\system\core\rootdir\init.rc 在解析rc脚本文件时,将相应的类型放入各自的List中: \system\core\init\Init_parser.c :init_parse_config_file( )存入到 action_queue、action_list、service_list中,解析过程可以看一下parse_config函数,类似状态机形式挺有意思。 这其中包含了服务:adbd、servicemanager、vold、ril-daemon、deb uggerd、surfaceflinger、zygote、media…… 2 服务启动 文件解析完成之后将service放入到service_list中。 文件解析完成之后将service放入到service_list中。 \system\core\init\builtins.c

RK系统启动流程

RK29机型之Android系统启动流程 分类:瑞芯微RK 2012-02-12 14:50 4439人阅读评论(0) 收藏举报/******************************************************************************************** * author:conowen@大钟 * E-mail:conowen@https://www.wendangku.net/doc/359690631.html, * https://www.wendangku.net/doc/359690631.html,/conowen * 注:本文为原创,仅作为学习交流使用,转载请标明作者及出处。 ********************************************************************************************/ 第一步:系统引导bootloader,即RK29xxLoaderXXX.bin文件 加电后,CPU将先执行 bootloader程序,然后bootloader首先会读寄存器地址base + APP_DATA1的内容,根据这个地址的值决定是否进入recovery模式或者其它模式。bootloader还会读取MISC分区第一块的内容,决定进入recovery模式还是升级基带Baseband Processor(BP)或做其它事情 而上述寄存器与分区的值是有按键触发或者软件触发的。 a) 开机按reset+返回键,系统进入recovery模式,加载recovery.img,recovery.img 包含内核,基本的文件系统,用于工程模式的烧写 b) 开机按Power,正常启动系统,加载boot.img,boot.img包含内核,基本文件系统,用于正常启动机器(以下只分析正常启动的情况) 第二步:启动内核kernel 1) 源码:kernel/* 2) 说明:kernel由bootloader加载 第三步:文件系统(rootfs)及应用初始化(init) 1) 源码:system/core/init/* 2) 配置文件:system/rootdir/init.rc, 3) 说明:init是一个由内核启动的用户级进程,它按照init.rc中的设置执行:启动服务(这里的服务指linux底层服务,如adbd提供adb支持,vold提供SD卡挂载等),执行 命令和按其中的配置语句执行相应功能 第四步:重要的后台程序zygote 1) 源码:frameworks/base/cmds/app_main.cpp等 2) 说明:zygote是一个在init.rc中被指定启动的服务,该服务对应的命令是 /system/bin/app_process a) 建立Java Runtime,建立虚拟机

Android SystemBar启动流程分析

Android SystemBar启动流程分析 SystemBars的服务被start时,最终会调用该类的onNoService()方法。 @Override public void start() { if (DEBUG) Log.d(TAG, "start"); ServiceMonitor mServiceMonitor = new ServiceMonitor(TAG, DEBUG, mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); mServiceMonitor.start(); // will call onNoService if no remote service is found } @Override public void onNoService() { if (DEBUG) Log.d(TAG, "onNoService"); createStatusBarFromConfig(); // fallback to using an in-process implementation } private void createStatusBarFromConfig() { … mStatusBar = (BaseStatusBar) cls.newInstance(); … mStatusBar.start(); } BaseStatusBar是一个抽象类,故调用其子类的PhoneStatusBar的start 函数。 @Override public void start() { … super.start(); … } 子类的start又调用了父类的start public void start() { … createAndAddWindows(); … }

AndroidL系统启动及加载流程分析

Android L系统启动及加载流程分析 1、概述 Android L的启动可以分为几个步骤:Linux内核启动、init进程启动、native系统服务及java系统服务启动、Home启动,主要过程如下图: 图1 整个启动流程跟4.4及之前的版本相差不多,只是有个别不同之处,本文我们主要分析Linux内核启动之后的过程。

2、启动过程分析 2.1 init进程启动 当系统内核加载完成之后,会启动init守护进程,它是内核启动的第一个用户级进程,是Android的一个进程,进程号为1,init进程启动后执行入口函数main(),主要操作为: 图2 AndroidL上将selinux的安全等级提高了,设为了enforcing模式,4.4上是permissive模式。 解析rc脚本文件,即init.rc脚本,该文件是Android初始化脚本,定义了一系列的动作和执行这些动作的时间阶段e aryl-init、init、early-boot、boot、post-fs等阶段。init进程main 函数中会根据这些阶段进行解析执行。AndroidL上为了流程更清晰,增加了charger(充电开机)、ffbm(工厂模式)、以及late-init阶段,实际上这些阶段是对其他阶段的组合执行,比如late-init:

2.2 ServiceManager的启动 servicemanager的启动就是init进程通过init.rc脚本启动的: 源码在frameworks/native/cmds/servicemanager/service_manager.c中,servicemanager是服务管理器,它本身也是一个服务(handle=0),通过binder调用,为native和Java系统服务提供注册和查询服务的,即某个服务启动后,需要将自己注册到servicemanager中,供其他服务或者应用查询使用。AndroidL上servicemanger中在处理注册和查询动作之前添加了selinux安全检测相关的处理。 2.3 SurfaceFinger、MediaServer进程启动 Android4.4以前,surfacefinger的启动根据属性system_init.startsurfaceflinger,决定是通过init.rc启动还是systemserver进程启动,之后的版本包括AndoridL都是通过init.rc启动的: 启动后会向servicemanager进程注册服务中,该服务启动时主要功能是初始化整个显

BOOTCHART ANDROID文档(开机慢)

BootChart在Android中的应用 1简介 Bootchart是一个能对GNU/Linux boot过程进行性能分析并把结果直观化的工具。它在boot过程中搜集资源利用情况及进程信息然后以PNG,SVG或EPS格式来显示结果。BootChart包含数据收集工具和图像产生工具,数据收集工具在原始的BootChart中是独立的shell程序,但在Android中,数据收集工具被集成到了init程序中。 2BootChart使用步骤概述 ?在主机上安装BootChart ?建立有BootChart支持的init文件 ?安装init到系统镜像 ?使能启动时的BootChart功能 ?收集系统产生的数据 ?根据产生的数据生成图表 ?结果分析 以下部分将对这些步骤进行详细描述(环境:Ubuntu9.04,Android1.6)。 3详细说明 ?在主机上安装BootChart $sudo apt-get install bootchart 注:由于BootChart是用Java语言实现,所以要求其所运行的主机安装Java包。 ?创建支持BootChart功能的‘init’文件 Andoid系统中运行的第一个程序是'init',其所在的目录为Andoid文件系统的根目录下(即/)。'init'是一个由内核启动的用户级进程,主要是对系统进行初始化和根据init.rc与init.xxx.rc文件建立几个基本的服务。 创建'init'时对BootChart的数据收集功能是可选的,默认的'init'是不支持BootChart 的数据收集功能的。要想在Andoid中应用BootChart,必须创建支持BootChart数据收集功能的'init'。 $cd~/myandroid $export INIT_BOOTCHART=true #vim system/core/init/Android.mk 20ifeq($(strip$(INIT_BOOTCHART)),true) 21LOCAL_SRC_FILES+=bootchart.c

android开机启动流程简单分析

android开机启动流程简单分析 android启动 当引导程序启动Linux内核后,会加载各种驱动和数据结构,当有了驱动以后,开始启动Android系统同时会加载用户级别的第一个进程init(system\core\init\init.cpp)代码如下: int main(int argc, char** argv) { ..... //创建文件夹,挂载 // Get the basic filesystem setup we need put together in the initramdisk // on / and then we'll let the rc file figure out the rest. if (is_first_stage) { mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); #define MAKE_STR(x) __STRING(x) mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)); mount("sysfs", "/sys", "sysfs", 0, NULL); } ..... //打印日志,设置log的级别 klog_init(); klog_set_level(KLOG_NOTICE_LEVEL); ..... Parser& parser = Parser::GetInstance(); parser.AddSectionParser("service",std::make_unique()); parser.AddSectionParser("on", std::make_unique()); parser.AddSectionParser("import", std::make_unique()); // 加载init.rc配置文件 parser.ParseConfig("/init.rc"); } 加载init.rc文件,会启动一个Zygote进程,此进程是Android系统的一个母进程,用来启动Android的其他服务进程,代码: 从Android L开始,在/system/core/rootdir 目录中有4 个zygote 相关的启动脚本如下图:

Android ninja 编译启动过程分析

Android ninja编译启动过程分析 ---make是如何转换到到ninja编译的 1.首先你的得对make的工作机制有个大概的了解: 运行的命令在要编译的目录下运行make,或者make target_name a.分析处理保存阶段(没有实际编译动作):它首先对当前目录下的Makefile文件的做一次扫描,语法分析,还有处理,主要是变量的保存,目标依赖列表生成,目标下的action列表的生成,然后记住 b.然后按记住的目标执行action列表动作(有实际编译动作). 编译启动的入口方式还是运行make: 2开始make-jxxx方式进入.....(xxx是本机cpu的数量) make开始做进行第一次扫描.... 目前USE_NINJA还是没有定义,估计以后很久很久才能启用的了! BUILDING_WITH_NINJA开始也是没定义的 看make扫描入口文件: Makefile: include build/core/main.mk 在build/core/main.mk: 在ninia之前都有include help.mk和config.mk 97include$(BUILD_SYSTEM)/help.mk 98 99#Set up various standard variables based on configuration 100#and host information. 101include$(BUILD_SYSTEM)/config.mk 说明make help//显示make帮助make config//当前显示配置 103relaunch_with_ninja:= 104ifneq($(USE_NINJA),false) 105ifndef BUILDING_WITH_NINJA<==第二次扫描不会到这里了 106relaunch_with_ninja:=true 107endif 108endif 116ifeq($(relaunch_with_ninja),true)<===第一次扫描入这里了 117#Mark this is a ninja build. 118$(shell mkdir-p$(OUT_DIR)&&touch$(OUT_DIR)/ninja_build) 119include build/core/ninja.mk//---进入ninja.mk 第一次扫描到此为止就结束掉了,因为在当前ifeq else endif后面没有代码了 120else#///!relaunch_with_ninja<===第二次扫描入这里了

Android Service如何开机自启动以及自启动失败原因

Android Service如何开机自启动以及自启动失败原因 本文主要介绍Android Service如何开机自启动、自启动失败的原因、adb命令发送 BOOT_COMPLETED。 应用程序是否可以在安装后自启动,没有ui的纯service应用如何启动? 1、Android应用如何开机自启动 (1)、在AndroidManifest.xml中注册 AndroidManifest.xml中注册BOOT_COMPLETED Action注意不仅要添加 android.intent.action.BOOT_COMPLETED对应的action,还需要添加对应的uses-permission (2)、Receiver接收广播进行处理 public class BootBroadcastReceiver extends BroadcastReceiver { public static final String TAG = "BootBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction().toString(); if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { // u can start your service here Toast.makeText(context, "boot completed action has got", Toast.LENGTH_LONG).show(); return; } } } 2、自启动失败的原因 接收不到BOOT_COMPLETED广播可能的原因 (1)、BOOT_COMPLETED对应的action和uses-permission没有一起添加 (2)、应用安装到了sd卡内,安装在sd卡内的应用是收不到BOOT_COMPLETED广播的 (3)、系统开启了Fast Boot模式,这种模式下系统启动并不会发送BOOT_COMPLETED广播 (4)、应用程序安装后重来没有启动过,这种情况下应用程序接收不到任何广播,包括 BOOT_COMPLETED、ACTION_PACKAGE_ADDED、CONNECTIVITY_ACTION等等。 Android3.1之后,系统为了加强了安全性控制,应用程序安装后或是(设置)应用管理中被强制关闭后处于stopped状态,在这种状态下接收不到任何广播,除非广播带有 FLAG_INCLUDE_STOPPED_PACKAGES标志,而默认所有系统广播都是 FLAG_EXCLUDE_STOPPED_PACKAGES的,所以就没法通过系统广播自启动了。所以Android3.1之后 (1)、应用程序无法在安装后自己启动 (2)、没有ui的程序必须通过其他应用激活才能启动,如它的Activity、Service、Content Provider被其他应用调用。 存在一种例外,就是应用程序被adb push you.apk /system/app/下是会自动启动的,不处于stopped状态。

android开机过程

一、Android开机启动流程简介 1、OS-level: 由bootloader载入linux kernel后kernel开始初始化, 并载入built-in 的驱动程序。Kernel完成开机后,载入init process,切换至user-space。 Init进程是第一个在user-space启动的进程。 2、Android-level: 由init process读取init.rc,Native 服务启动,并启动重要的外部程序,例如:servicemanager、Zygote以及System Server等。 由 init process 根据硬件类型读取init.xxx.rc。由init.xxx.rc加载init.xxx.sh。 由 init.xxx.sh 加载特定的硬件驱动。如hi_tuner.ko、hi_demux.ko等。 3、Zygote-Mode: Zygote 启动完SystemServer 后,进入Zygote Mode,在Socket 等候命令。 随后,使用者将看到一个桌面环境(Home Screen)。桌面环境由一个名为[Launcher]的应用程序负责提供。 本文档重点研究Android-level中的启动流程。 启动流程如下图所示:

二、init process流程分析 init进程简介 init进程是第一个在user-space启动的进程。由内核启动参数[init]传递给内核,如果该项没有设置,内核会按 /etc/init,/bin/init,/sbin/init,/bin/sh的顺序进行尝试,如果都有的都没找到,内核会抛出 kernel panic:的错误。

Android系统启动升级流程

A n d r o i d系统启动升级 流程 TTA standardization office【TTA 5AB- TTAK 08- TTA 2C】

摘要 本文首先介绍了Android系统更新要用到的一些概念:硬件、三种模式及相互之间的通信。然后介绍了Android系统的启动和升级流程。 概述 通常,Android系统的升级包名称为update.zip。Android系统内部自带了烧写升级包的工具,我们可以手动烧写,也可以通过某些机制自动更新系统。同时,我们可以手动修改和制作升级包。本文主要阐述在Android系统升级中用到的一些概念,本文只是作为索引,并不涉及到具体的烧写工作。本文基于Android系统的版本:4.0.4。 硬件 Android系统的烧写,是非常贴近硬件的。一是,烧写是在实实在在的硬件上操作的。二则,有时在翻阅源码的时候,需要知道硬件的类型,以便找到和硬件相对应的源码。 烧写相关的硬件主要有三部分:CPU、内存和nand flash。当然,只是相对本文而言。CPU用来执行程序中的指令。内存只是在运行中,将需要运行的程序加载其中并运行,关机后即消失。nandflash用来存储程序的数据,它会一直存在。系统启动时,会将nand flash上的操作系统加载到内存,然后运行在CPU 中,对于非系统程序,按需加载到内存中运行。了解这些,有助于了解整个烧写的过程。 在板子上,可以通过下面的命令,查看CPU的信息: [plain] cat /proc/cpuinfo 通过如下命令查看内存的信息: [plain] cat /proc/meminfo nand flash是需要分区的,每个分区中对应了Android系统烧写包中不同的image,比如:boot、system分区等。可以通过如下命令来查看nand flash 的分区情况: [plain] cat /proc/mtd # 查看分区状况 通常,nand flash包含了以下分区: 开机动画:用于在开机或者升级过程中显示在屏幕上的内容。 boot:用于Android系统的正常启动 recovery:用于Android系统进入recovery模式下,参见本文后续介绍。 misc:用于保存BCB的内容,参见本文后续介绍。

Android应用程序内部启动Activity过程(startActivity)的源代码分析

上文介绍了Android应用程序的启动过程,即应用程序默认Activity的启动过程,一般来说,这种默认Activity是在新的进程和任务中启动的;本文将继续分析在应用程序内部启动非默认Activity的过程的源代码,这种非默认Activity一般是在原来的进程和任务中启动的。 这里,我们像上一篇文章Android应用程序启动过程源代码分析一样,采用再上一篇文章Android 应用程序的Activity启动过程简要介绍和学习计划所举的例子来分析在应用程序内部启动非默认Activity的过程。 在应用程序内部启动非默认Activity的过程与在应用程序启动器Launcher中启动另外一个应用程序的默认Activity的过程大体上一致的,因此,这里不会像上文Android应用程序启动过程源代码分析一样详细分析每一个步骤,我们着重关注有差别的地方。 回忆一下Android应用程序的Activity启动过程简要介绍和学习计划一文所用的应用程序Activity,它包含两个Activity,分别是MainActivity和SubActivity,前者是应用程序的默认Activity,后者是非默认Activity。MainActivity启动起来,通过点击它界面上的按钮,便可以在应用程序内部启动SubActivity。 我们先来看一下应用程序的配置文件AndroidManifest.xml,看看这两个Activity是如何配置的:view plain 1. 2. 6. 7. 9. 10. 11. 12. 13. 14. 16. 17. 18. 19. 20. 21. 22.

相关文档
相关文档 最新文档