Android教程之开机流程全面解析_Android

本文详细讲述了Android的开机流程。分享给大家供大家参考,具体如下:

开机过程中无线模块的初始化过程;如果sim卡锁开启,或者pin被锁住的时候,会要求输入pin或者puk,但是这个解锁动作必须在系统初始化完成以后才能进行。(图形系统都还没有初始化怎么输入密码阿?)当系统初始化完成以后会调用 wm.systemReady()来通知大家。这时候该做什么就做什么。

开机过程中无线模块的初始化过程:

rild 调用参考实现 Reference-ril.c (hardware\ril\reference-ril) 中的函数:

const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
static void *mainLoop(void *param)
ret = at_open(fd, onUnsolicited);
RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);

在 initializeCallback 函数中对猫进行了初始化。

static void initializeCallback(void *param)
{
ATResponse *p_response = NULL;
int err;
setRadioState (RADIO_STATE_OFF);
at_handshake();
/* note: we don't check errors here. Everything important will
be handled in onATTimeout and onATReaderClosed */
/* atchannel is tolerant of echo but it must */
/* have verbose result codes */
at_send_command("ATE0Q0V1", NULL);
/* No auto-answer */
at_send_command("ATS0=0", NULL);
/* Extended errors */
at_send_command("AT+CMEE=1", NULL);
/* Network registration events */
err = at_send_command("AT+CREG=2", &p_response);
/* some handsets -- in tethered mode -- don't support CREG=2 */
if (err < 0 || p_response->success == 0) {
at_send_command("AT+CREG=1", NULL);
}
at_response_free(p_response);
/* GPRS registration events */
at_send_command("AT+CGREG=1", NULL);
/* Call Waiting notifications */
at_send_command("AT+CCWA=1", NULL);
/* Alternating voice/data off */
at_send_command("AT+CMOD=0", NULL);
/* Not muted */
at_send_command("AT+CMUT=0", NULL);
/* +CSSU unsolicited supp service notifications */
at_send_command("AT+CSSN=0,1", NULL);
/* no connected line identification */
at_send_command("AT+COLP=0", NULL);
/* HEX character set */
at_send_command("AT+CSCS=\"HEX\"", NULL);
/* USSD unsolicited */
at_send_command("AT+CUSD=1", NULL);
/* Enable +CGEV GPRS event notifications, but don't buffer */
at_send_command("AT+CGEREP=1,0", NULL);
/* SMS PDU mode */
at_send_command("AT+CMGF=0", NULL);
#ifdef USE_TI_COMMANDS
at_send_command("AT%CPI=3", NULL);
/* TI specific -- notifications when SMS is ready (currently ignored) */
at_send_command("AT%CSTAT=1", NULL);
#endif /* USE_TI_COMMANDS */
/* assume radio is off on error */
if (isRadioOn() > 0) {
setRadioState (RADIO_STATE_SIM_NOT_READY);
}
}

默认状况下假设射频模块是好的,
通过 setRadioState (RADIO_STATE_SIM_NOT_READY) 来触发对无线模块的初始化。

通过 static void onRadioPowerOn() 对无线模块初始化。

首先通过 pollSIMState(NULL); 轮询 sim卡状态 。

static void pollSIMState (void *param)
{
ATResponse *p_response;
int ret;
if (sState != RADIO_STATE_SIM_NOT_READY) {
// no longer valid to poll
return;
}
switch(getSIMStatus()) {
case RIL_SIM_ABSENT:
case RIL_SIM_PIN:
case RIL_SIM_PUK:
case RIL_SIM_NETWORK_PERSONALIZATION:
default:
setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
return;
case RIL_SIM_NOT_READY:
RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
return;
case RIL_SIM_READY:
setRadioState(RADIO_STATE_SIM_READY);
return;
}
}

读取sim卡状态的函数是:getSIMStatus()

err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);

它向猫发送了at命令 AT+CPIN? 来查询无线模块的状态,如果无线模块还没有就绪,那么他隔1秒钟继续调用

sim卡状态轮询函数 pollSIMState,直到获得sim卡状态。

当sim卡状态为就绪,那么通过 setRadioState(RADIO_STATE_SIM_READY) 设置变量 sState 为:

RADIO_STATE_SIM_READY,这时候会调用函数 static void onSIMReady()来进一步初始化无线模块。

发送的at命令有:

at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
at_send_command("AT+CNMI=1,2,2,1,1", NULL);

如果sim卡锁开启,或者pin被锁住的时候,会要求输入pin或者puk,但是这个解锁动作必须在系统初始化完成以后才能进行。(图形系统都还没有初始化怎么输入密码阿?)当系统初始化完成以后会调用 wm.systemReady()来通知大家。这时候该做什么就做什么。

wm.systemReady()的调用会触发解锁界面。具体流程如下:

因为有: WindowManagerService wm = null;
所以 wm.systemReady()
调用的是 WindowManagerService 中的函数:

public void systemReady() {
mPolicy.systemReady();
}

WindowManagerService 中有:

复制代码 代码如下:

final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();

PolicyManager.makeNewWindowManager 调用的是文件 PolicyManager.java 中的函数:

public static WindowManagerPolicy makeNewWindowManager() {
return sPolicy.makeNewWindowManager();
}

sPolicy.makeNewWindowManager 调用的是文件 Policy.java 中的函数:

public PhoneWindowManager makeNewWindowManager() {
return new PhoneWindowManager();
}

因为 PhoneWindowManager 继承自 WindowManagerPolicy
所以 mPolicy.systemReady() 最终调用的是文件 PhoneWindowManager.java 中的函数:

public void systemReady()
mKeyguardMediator.onSystemReady();
doKeyguard();
showLocked();
Message msg = mHandler.obtainMessage(SHOW);
mHandler.sendMessage(msg);

发送 SHOW 的消息。

文件 KeyguardViewMediator.java 中的消息处理函数:

public void handleMessage(Message msg) 对 SHOW 消息进行了处理。
如果 msg.what 等于 SHOW 那么执行:

handleShow();
private void handleShow()
...
mCallback.onKeyguardShow();
mKeyguardViewManager.show();
mShowing = true;

mKeyguardViewManager.show() 调用的是文件 KeyguardViewManager.java 中的函数:

public synchronized void show()
...
mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
...

mKeyguardViewProperties.createKeyguardView 调用的是文件 LockPatternKeyguardViewProperties.java中的函数:

public KeyguardViewBase createKeyguardView(Context context,
KeyguardUpdateMonitor updateMonitor,
KeyguardWindowController controller) {
return new LockPatternKeyguardView(context, updateMonitor,
mLockPatternUtils, controller);
}

new LockPatternKeyguardView 调用了类 LockPatternKeyguardView 的构造函数:

public LockPatternKeyguardView(
Context context,
KeyguardUpdateMonitor updateMonitor,
LockPatternUtils lockPatternUtils,
KeyguardWindowController controller)
...
mLockScreen = createLockScreen();
addView(mLockScreen);
final UnlockMode unlockMode = getUnlockMode();
mUnlockScreen = createUnlockScreenFor(unlockMode);
mUnlockScreenMode = unlockMode;
addView(mUnlockScreen);
updateScreen(mMode);

执行上面的程序然后弹出解锁界面,getUnlockMode 获得锁类型,通常有三种:

enum UnlockMode {
Pattern, //图案锁
SimPin, //输入pin或者puk
Account //账号锁
}

通过上面的过程我们可以知道,在系统初始化阶段启动rild的时候,rild与猫进行了通信,并对猫进行初始化。保存了网络的一系列状态。

待机状态下,飞行模式切换流程分析:

飞行模式切换比较复杂,它状态改变时涉及到极大模块状态切换:

GSM模块,蓝牙模块,wifi模块。

飞行模式的enabler层会发送广播消息:ACTION_AIRPLANE_MODE_CHANGED

private void setAirplaneModeOn(boolean enabling) {
mCheckBoxPref.setEnabled(false);
mCheckBoxPref.setSummary(enabling ? R.string.airplane_mode_turning_on
: R.string.airplane_mode_turning_off);
// Change the system setting
Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
enabling ? 1 : 0);
// Post the intent
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", enabling);
mContext.sendBroadcast(intent);
}

因为GSM ,蓝牙,wifi模块分别注册了对 ACTION_AIRPLANE_MODE_CHANGED 消息的监测,所以收到该消息后,模块会进行切换。

BluetoothDeviceService.java

开启蓝牙:enable(false);
关闭蓝牙:disable(false);
PhoneApp.java (packages\apps\phone\src\com\android\phone)
设置GSM模块状态 phone.setRadioPower(enabled);
WifiService.java
设置 wifi 状态 setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());

GSM模块切换过程分析:

phone.setRadioPower(enabled)调用的是:

文件 GSMPhone.java 中的的函数:

public void setRadioPower(boolean power)
mSST.setRadioPower(power);

因为有 ServiceStateTracker mSST;

mSST.setRadioPower 调用的是文件 ServiceStateTracker.java 中的函数:

public void setRadioPower(boolean power)
mDesiredPowerState = power;
setPowerStateToDesired();
cm.setRadioPower(true, null);

或者

cm.setRadioPower(false, null);

因为有:

CommandsInterface cm;
public final class RIL extends BaseCommands implements CommandsInterface

所以 cm.setRadioPower 调用的是文件 RIL.java 中的函数:

public void setRadioPower(boolean on, Message result)
RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
rr.mp.writeInt(1);
...
send(rr)

通过 send 向 rild 发送 RIL_REQUEST_RADIO_POWER 请求来开启或者关闭GSM模块。

rild 数据接收流程:

收到 RIL_REQUEST_RADIO_POWER 执行:

requestRadioPower(data, datalen, t);

然后根据条件往无线模块发送模块开启和关闭请求

主要的at命令有:

err = at_send_command("AT+CFUN=0", &p_response);
err = at_send_command("AT+CFUN=1", &p_response);

蓝牙模块切换过程分析:

enable(false);

蓝牙开启调用文件 BluetoothDeviceService.java 中的函数:

public synchronized boolean enable(boolean saveSetting)
setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON);
mEnableThread = new EnableThread(saveSetting);
mEnableThread.start();
----
disable(false)

蓝牙关闭调用文件 中的函数:

public synchronized boolean disable(boolean saveSetting)
setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF);

wifi模块切换过程分析:

广播 wifi 状态改变的消息:WIFI_STATE_CHANGED_ACTION

复制代码 代码如下:

setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);

更新 wifi 状态:

private void updateWifiState()

如果需要使能开启 wifi 那么会发送:

sendEnableMessage(true, false, mLastEnableUid);
sendStartMessage(strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY);
mWifiHandler.sendEmptyMessage(MESSAGE_STOP_WIFI);

消息循环中处理命令消息:

public void handleMessage(Message msg)

如果使能wifi:setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);

开启wifi:

mWifiStateTracker.setScanOnlyMode(msg.arg1 != 0);
setWifiEnabledBlocking(false, msg.arg1 == 1, msg.arg2);

断开

mWifiStateTracker.disconnectAndStop();

开启过程步骤:

1> 装载 wifi 驱动: WifiNative.loadDriver()
2> 启动后退 daemo supplicant: WifiNative.startSupplicant()
关闭过程步骤:
1> 停止后退 daemo supplicant:WifiNative.stopSupplicant()
2> 卸载 wifi 驱动: WifiNative.unloadDriver()

如果 wifi 状态默认为开启那么 WifiService 服务的构造函数:

WifiService(Context context, WifiStateTracker tracker)
boolean wifiEnabled = getPersistedWifiEnabled();
setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());

会开启wifi模块。

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android数据库操作技巧总结》、《Android编程之activity操作技巧总结》、《Android文件操作技巧汇总》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》、《Android视图View技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
开机流程
android开机流程、android 开机流程详解、android 开机启动流程、android 开机向导流程、android手机开机流程,以便于您获取更多的相关知识。

时间: 2024-11-10 00:05:23

Android教程之开机流程全面解析_Android的相关文章

Android教程之开机流程全面解析

本文详细讲述了Android的开机流程.分享给大家供大家参考,具体如下: 开机过程中无线模块的初始化过程;如果sim卡锁开启,或者pin被锁住的时候,会要求输入pin或者puk,但是这个解锁动作必须在系统初始化完成以后才能进行.(图形系统都还没有初始化怎么输入密码阿?)当系统初始化完成以后会调用 wm.systemReady()来通知大家.这时候该做什么就做什么. 开机过程中无线模块的初始化过程: rild 调用参考实现 Reference-ril.c (hardware\ril\referen

Android编程输入事件流程详解_Android

本文实例讲述了Android编程输入事件流程.分享给大家供大家参考,具体如下: EventHub对输入设备进行了封装.输入设备驱动程序对用户空间应用程序提供一些设备文件,这些设备文件放在/dev/input里面. EventHub扫描/dev/input下所有设备文件,并打开它们. bool EventHub::openPlatformInput(void) { ... mFDCount = 1; mFDs = (pollfd *)calloc(1, sizeof(mFDs[0])); mDev

Android入门之Gallery用法实例解析_Android

本文实例介绍的Android的Gallery控件是个很不错的看图控件,可以大大减轻开发者对于看图功能的开发,并且效果也很美观.本文实例中的Gallery的用法,主要实现用反射机制来动态读取资源中的图片. 该实例代码运行的效果图如下:   main.xml源码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.andro

Android中Java instanceof关键字全面解析_Android

instanceof关键字用于判断一个引用类型变量所指向的对象是否是一个类(或接口.抽象类.父类)的实例. instanceof是Java的一个二元操作符,和==,>,<是同一类东东.由于它是由字母组成的,所以也是Java的保留关键字.它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据.举个例子: String s = "I AM an Object!"; boolean isObject = s instanceof Object; 我们声明了

Android提高之Service用法实例解析_Android

前面文章介绍了Activity以及Intent的使用,本文就来介绍Service.如果把Activity比喻为前台程序,那么Service就是后台程序,Service的整个生命周期都只会在后台执行.Service跟Activity一样也由Intent调用.在工程里想要添加一个Service,先新建继承Service的类,然后到AndroidManifest.xml -> Application ->Application Nodes中的Service标签中添加.  Service要由Activ

Android入门之PopupWindow用法实例解析_Android

本文实例介绍一下PopupWindow对话框.PopupWindow是阻塞对话框,只有在外部线程 或者 PopupWindow本身做退出操作才可以执行.PopupWindow完全依赖Layout做外观,在常见的开发中,PopupWindow应该会与AlertDialog常混用. 先贴出本例中运行的结果图: main.xml的源码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln

使用Docker来加速构建Android应用的基本部署思路解析_Android

意义 极大的缩短安卓开发到测试到产品到渠道的距离. 给安卓程序员减轻负担. Google做的环境已经特别到位了,放到docker里面明显不会有多大的坑(误,逃).Dockerfile https://github.com/lijianying10/FixLinux/blob/master/dockerfiles/androidautobuild/Dockerfile 团队协作的故事 在敏捷开发的站立会议上,我作为一个后端程序员发现安卓程序员发布的时间大概是半个小时左右的时间,我觉得时间太长了应该

ubuntu 12.10 上 android 编译环境搭建的深入解析_Android

1. 安装所有的套件sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev:i386 g++-multilib mingw32 openjdk-6-jdk tofrodos python-mar

Android Bluetooth蓝牙技术使用流程详解_Android

在上篇文章给大家介绍了Android Bluetooth蓝牙技术初体验相关内容,感兴趣的朋友可以点击了解详情. 一:蓝牙设备之间的通信主要包括了四个步骤 设置蓝牙设备 寻找局域网内可能或者匹配的设备 连接设备 设备之间的数据传输 二:具体编程实现 1. 启动蓝牙功能 首先通过调用静态方法getDefaultAdapter()获取蓝牙适配器BluetoothAdapter,如果返回为空,则无法继续执行了.例如: BluetoothAdapter mBluetoothAdapter = Blueto