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程序设计有所帮助。