Android教程之开机流程全面解析
本文详细讲述了Android的开机流程。分享给大家供大家参考,具体如下:
开机过程中无线模块的初始化过程;如果sim卡锁开启,或者pin被锁住的时候,会要求输入pin或者puk,但是这个解锁动作必须在系统初始化完成以后才能进行。(图形系统都还没有初始化怎么输入密码阿?)当系统初始化完成以后会调用wm.systemReady()来通知大家。这时候该做什么就做什么。
开机过程中无线模块的初始化过程:
rild调用参考实现Reference-ril.c(hardware\ril\reference-ril)中的函数:
constRIL_RadioFunctions*RIL_Init(conststructRIL_Env*env,intargc,char**argv) ret=pthread_create(&s_tid_mainloop,&attr,mainLoop,NULL); staticvoid*mainLoop(void*param) ret=at_open(fd,onUnsolicited); RIL_requestTimedCallback(initializeCallback,NULL,&TIMEVAL_0);
在initializeCallback函数中对猫进行了初始化。
staticvoidinitializeCallback(void*param)
{
ATResponse*p_response=NULL;
interr;
setRadioState(RADIO_STATE_OFF);
at_handshake();
/*note:wedon'tcheckerrorshere.Everythingimportantwill
behandledinonATTimeoutandonATReaderClosed*/
/*atchannelistolerantofechobutitmust*/
/*haveverboseresultcodes*/
at_send_command("ATE0Q0V1",NULL);
/*Noauto-answer*/
at_send_command("ATS0=0",NULL);
/*Extendederrors*/
at_send_command("AT+CMEE=1",NULL);
/*Networkregistrationevents*/
err=at_send_command("AT+CREG=2",&p_response);
/*somehandsets--intetheredmode--don'tsupportCREG=2*/
if(err<0||p_response->success==0){
at_send_command("AT+CREG=1",NULL);
}
at_response_free(p_response);
/*GPRSregistrationevents*/
at_send_command("AT+CGREG=1",NULL);
/*CallWaitingnotifications*/
at_send_command("AT+CCWA=1",NULL);
/*Alternatingvoice/dataoff*/
at_send_command("AT+CMOD=0",NULL);
/*Notmuted*/
at_send_command("AT+CMUT=0",NULL);
/*+CSSUunsolicitedsuppservicenotifications*/
at_send_command("AT+CSSN=0,1",NULL);
/*noconnectedlineidentification*/
at_send_command("AT+COLP=0",NULL);
/*HEXcharacterset*/
at_send_command("AT+CSCS=\"HEX\"",NULL);
/*USSDunsolicited*/
at_send_command("AT+CUSD=1",NULL);
/*Enable+CGEVGPRSeventnotifications,butdon'tbuffer*/
at_send_command("AT+CGEREP=1,0",NULL);
/*SMSPDUmode*/
at_send_command("AT+CMGF=0",NULL);
#ifdefUSE_TI_COMMANDS
at_send_command("AT%CPI=3",NULL);
/*TIspecific--notificationswhenSMSisready(currentlyignored)*/
at_send_command("AT%CSTAT=1",NULL);
#endif/*USE_TI_COMMANDS*/
/*assumeradioisoffonerror*/
if(isRadioOn()>0){
setRadioState(RADIO_STATE_SIM_NOT_READY);
}
}
默认状况下假设射频模块是好的,
通过setRadioState(RADIO_STATE_SIM_NOT_READY)来触发对无线模块的初始化。
通过staticvoidonRadioPowerOn()对无线模块初始化。
首先通过pollSIMState(NULL);轮询sim卡状态。
staticvoidpollSIMState(void*param)
{
ATResponse*p_response;
intret;
if(sState!=RADIO_STATE_SIM_NOT_READY){
//nolongervalidtopoll
return;
}
switch(getSIMStatus()){
caseRIL_SIM_ABSENT:
caseRIL_SIM_PIN:
caseRIL_SIM_PUK:
caseRIL_SIM_NETWORK_PERSONALIZATION:
default:
setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
return;
caseRIL_SIM_NOT_READY:
RIL_requestTimedCallback(pollSIMState,NULL,&TIMEVAL_SIMPOLL);
return;
caseRIL_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,这时候会调用函数staticvoidonSIMReady()来进一步初始化无线模块。
发送的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()的调用会触发解锁界面。具体流程如下:
因为有:WindowManagerServicewm=null;
所以wm.systemReady()
调用的是WindowManagerService中的函数:
publicvoidsystemReady(){
mPolicy.systemReady();
}
WindowManagerService中有:
finalWindowManagerPolicymPolicy=PolicyManager.makeNewWindowManager();
PolicyManager.makeNewWindowManager调用的是文件PolicyManager.java中的函数:
publicstaticWindowManagerPolicymakeNewWindowManager(){
returnsPolicy.makeNewWindowManager();
}
sPolicy.makeNewWindowManager调用的是文件Policy.java中的函数:
publicPhoneWindowManagermakeNewWindowManager(){
returnnewPhoneWindowManager();
}
因为PhoneWindowManager继承自WindowManagerPolicy
所以mPolicy.systemReady()最终调用的是文件PhoneWindowManager.java中的函数:
publicvoidsystemReady() mKeyguardMediator.onSystemReady(); doKeyguard(); showLocked(); Messagemsg=mHandler.obtainMessage(SHOW); mHandler.sendMessage(msg);
发送SHOW的消息。
文件KeyguardViewMediator.java中的消息处理函数:
publicvoidhandleMessage(Messagemsg)对SHOW消息进行了处理。
如果msg.what等于SHOW那么执行:
handleShow(); privatevoidhandleShow() ... mCallback.onKeyguardShow(); mKeyguardViewManager.show(); mShowing=true;
mKeyguardViewManager.show()调用的是文件KeyguardViewManager.java中的函数:
publicsynchronizedvoidshow() ... mKeyguardView=mKeyguardViewProperties.createKeyguardView(mContext,mUpdateMonitor,this); ...
mKeyguardViewProperties.createKeyguardView调用的是文件LockPatternKeyguardViewProperties.java中的函数:
publicKeyguardViewBasecreateKeyguardView(Contextcontext,
KeyguardUpdateMonitorupdateMonitor,
KeyguardWindowControllercontroller){
returnnewLockPatternKeyguardView(context,updateMonitor,
mLockPatternUtils,controller);
}
newLockPatternKeyguardView调用了类LockPatternKeyguardView的构造函数:
publicLockPatternKeyguardView( Contextcontext, KeyguardUpdateMonitorupdateMonitor, LockPatternUtilslockPatternUtils, KeyguardWindowControllercontroller) ... mLockScreen=createLockScreen(); addView(mLockScreen); finalUnlockModeunlockMode=getUnlockMode(); mUnlockScreen=createUnlockScreenFor(unlockMode); mUnlockScreenMode=unlockMode; addView(mUnlockScreen); updateScreen(mMode);
执行上面的程序然后弹出解锁界面,getUnlockMode获得锁类型,通常有三种:
enumUnlockMode{
Pattern,//图案锁
SimPin,//输入pin或者puk
Account//账号锁
}
通过上面的过程我们可以知道,在系统初始化阶段启动rild的时候,rild与猫进行了通信,并对猫进行初始化。保存了网络的一系列状态。
待机状态下,飞行模式切换流程分析:
飞行模式切换比较复杂,它状态改变时涉及到极大模块状态切换:
GSM模块,蓝牙模块,wifi模块。
飞行模式的enabler层会发送广播消息:ACTION_AIRPLANE_MODE_CHANGED
privatevoidsetAirplaneModeOn(booleanenabling){
mCheckBoxPref.setEnabled(false);
mCheckBoxPref.setSummary(enabling?R.string.airplane_mode_turning_on
:R.string.airplane_mode_turning_off);
//Changethesystemsetting
Settings.System.putInt(mContext.getContentResolver(),Settings.System.AIRPLANE_MODE_ON,
enabling?1:0);
//Posttheintent
Intentintent=newIntent(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中的的函数:
publicvoidsetRadioPower(booleanpower) mSST.setRadioPower(power);
因为有ServiceStateTrackermSST;
mSST.setRadioPower调用的是文件ServiceStateTracker.java中的函数:
publicvoidsetRadioPower(booleanpower) mDesiredPowerState=power; setPowerStateToDesired(); cm.setRadioPower(true,null);
或者
cm.setRadioPower(false,null);
因为有:
CommandsInterfacecm; publicfinalclassRILextendsBaseCommandsimplementsCommandsInterface
所以cm.setRadioPower调用的是文件RIL.java中的函数:
publicvoidsetRadioPower(booleanon,Messageresult) RILRequestrr=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中的函数:
publicsynchronizedbooleanenable(booleansaveSetting) setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON); mEnableThread=newEnableThread(saveSetting); mEnableThread.start(); ---- disable(false)
蓝牙关闭调用文件中的函数:
publicsynchronizedbooleandisable(booleansaveSetting) setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF);
wifi模块切换过程分析:
广播wifi状态改变的消息:WIFI_STATE_CHANGED_ACTION
setWifiEnabledState(enable?WIFI_STATE_ENABLING:WIFI_STATE_DISABLING,uid);
更新wifi状态:
privatevoidupdateWifiState()
如果需要使能开启wifi那么会发送:
sendEnableMessage(true,false,mLastEnableUid); sendStartMessage(strongestLockMode==WifiManager.WIFI_MODE_SCAN_ONLY); mWifiHandler.sendEmptyMessage(MESSAGE_STOP_WIFI);
消息循环中处理命令消息:
publicvoidhandleMessage(Messagemsg)
如果使能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>启动后退daemosupplicant:WifiNative.startSupplicant()
关闭过程步骤:
1>停止后退daemosupplicant:WifiNative.stopSupplicant()
2>卸载wifi驱动:WifiNative.unloadDriver()
如果wifi状态默认为开启那么WifiService服务的构造函数:
WifiService(Contextcontext,WifiStateTrackertracker) booleanwifiEnabled=getPersistedWifiEnabled(); setWifiEnabledBlocking(wifiEnabled,false,Process.myUid());
会开启wifi模块。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android数据库操作技巧总结》、《Android编程之activity操作技巧总结》、《Android文件操作技巧汇总》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》、《Android视图View技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。