Android教程之開機(jī)流程全面解析
本文詳細(xì)講述了Android的開機(jī)流程。分享給大家供大家參考,具體如下:
開機(jī)過(guò)程中無(wú)線模塊的初始化過(guò)程;如果sim卡鎖開啟,或者pin被鎖住的時(shí)候,會(huì)要求輸入pin或者puk,但是這個(gè)解鎖動(dòng)作必須在系統(tǒng)初始化完成以后才能進(jìn)行。(圖形系統(tǒng)都還沒(méi)有初始化怎么輸入密碼阿?)當(dāng)系統(tǒng)初始化完成以后會(huì)調(diào)用 wm.systemReady()來(lái)通知大家。這時(shí)候該做什么就做什么。
開機(jī)過(guò)程中無(wú)線模塊的初始化過(guò)程:
rild 調(diào)用參考實(shí)現(xiàn) Reference-ril.c (hardware\ril\reference-ril) 中的函數(shù):
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 函數(shù)中對(duì)貓進(jìn)行了初始化。
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); } }
默認(rèn)狀況下假設(shè)射頻模塊是好的,
通過(guò) setRadioState (RADIO_STATE_SIM_NOT_READY) 來(lái)觸發(fā)對(duì)無(wú)線模塊的初始化。
通過(guò) static void onRadioPowerOn() 對(duì)無(wú)線模塊初始化。
首先通過(guò) pollSIMState(NULL); 輪詢 sim卡狀態(tài) 。
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卡狀態(tài)的函數(shù)是:getSIMStatus()
err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);
它向貓發(fā)送了at命令 AT+CPIN? 來(lái)查詢無(wú)線模塊的狀態(tài),如果無(wú)線模塊還沒(méi)有就緒,那么他隔1秒鐘繼續(xù)調(diào)用
sim卡狀態(tài)輪詢函數(shù) pollSIMState,直到獲得sim卡狀態(tài)。
當(dāng)sim卡狀態(tài)為就緒,那么通過(guò) setRadioState(RADIO_STATE_SIM_READY) 設(shè)置變量 sState 為:
RADIO_STATE_SIM_READY,這時(shí)候會(huì)調(diào)用函數(shù) static void onSIMReady()來(lái)進(jìn)一步初始化無(wú)線模塊。
發(fā)送的at命令有:
at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL); at_send_command("AT+CNMI=1,2,2,1,1", NULL);
如果sim卡鎖開啟,或者pin被鎖住的時(shí)候,會(huì)要求輸入pin或者puk,但是這個(gè)解鎖動(dòng)作必須在系統(tǒng)初始化完成以后才能進(jìn)行。(圖形系統(tǒng)都還沒(méi)有初始化怎么輸入密碼阿?)當(dāng)系統(tǒng)初始化完成以后會(huì)調(diào)用 wm.systemReady()來(lái)通知大家。這時(shí)候該做什么就做什么。
wm.systemReady()的調(diào)用會(huì)觸發(fā)解鎖界面。具體流程如下:
因?yàn)橛校?WindowManagerService wm = null;
所以 wm.systemReady()
調(diào)用的是 WindowManagerService 中的函數(shù):
public void systemReady() { mPolicy.systemReady(); }
WindowManagerService 中有:
PolicyManager.makeNewWindowManager 調(diào)用的是文件 PolicyManager.java 中的函數(shù):
public static WindowManagerPolicy makeNewWindowManager() { return sPolicy.makeNewWindowManager(); }
sPolicy.makeNewWindowManager 調(diào)用的是文件 Policy.java 中的函數(shù):
public PhoneWindowManager makeNewWindowManager() { return new PhoneWindowManager(); }
因?yàn)?PhoneWindowManager 繼承自 WindowManagerPolicy
所以 mPolicy.systemReady() 最終調(diào)用的是文件 PhoneWindowManager.java 中的函數(shù):
public void systemReady() mKeyguardMediator.onSystemReady(); doKeyguard(); showLocked(); Message msg = mHandler.obtainMessage(SHOW); mHandler.sendMessage(msg);
發(fā)送 SHOW 的消息。
文件 KeyguardViewMediator.java 中的消息處理函數(shù):
public void handleMessage(Message msg) 對(duì) SHOW 消息進(jìn)行了處理。
如果 msg.what 等于 SHOW 那么執(zhí)行:
handleShow(); private void handleShow() ... mCallback.onKeyguardShow(); mKeyguardViewManager.show(); mShowing = true;
mKeyguardViewManager.show() 調(diào)用的是文件 KeyguardViewManager.java 中的函數(shù):
public synchronized void show() ... mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this); ...
mKeyguardViewProperties.createKeyguardView 調(diào)用的是文件 LockPatternKeyguardViewProperties.java中的函數(shù):
public KeyguardViewBase createKeyguardView(Context context, KeyguardUpdateMonitor updateMonitor, KeyguardWindowController controller) { return new LockPatternKeyguardView(context, updateMonitor, mLockPatternUtils, controller); }
new LockPatternKeyguardView 調(diào)用了類 LockPatternKeyguardView 的構(gòu)造函數(shù):
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);
執(zhí)行上面的程序然后彈出解鎖界面,getUnlockMode 獲得鎖類型,通常有三種:
enum UnlockMode { Pattern, //圖案鎖 SimPin, //輸入pin或者puk Account //賬號(hào)鎖 }
通過(guò)上面的過(guò)程我們可以知道,在系統(tǒng)初始化階段啟動(dòng)rild的時(shí)候,rild與貓進(jìn)行了通信,并對(duì)貓進(jìn)行初始化。保存了網(wǎng)絡(luò)的一系列狀態(tài)。
待機(jī)狀態(tài)下,飛行模式切換流程分析:
飛行模式切換比較復(fù)雜,它狀態(tài)改變時(shí)涉及到極大模塊狀態(tài)切換:
GSM模塊,藍(lán)牙模塊,wifi模塊。
飛行模式的enabler層會(huì)發(fā)送廣播消息: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); }
因?yàn)镚SM ,藍(lán)牙,wifi模塊分別注冊(cè)了對(duì) ACTION_AIRPLANE_MODE_CHANGED 消息的監(jiān)測(cè),所以收到該消息后,模塊會(huì)進(jìn)行切換。
BluetoothDeviceService.java
開啟藍(lán)牙:enable(false);
關(guān)閉藍(lán)牙:disable(false);
PhoneApp.java (packages\apps\phone\src\com\android\phone)
設(shè)置GSM模塊狀態(tài) phone.setRadioPower(enabled);
WifiService.java
設(shè)置 wifi 狀態(tài) setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());
GSM模塊切換過(guò)程分析:
phone.setRadioPower(enabled)調(diào)用的是:
文件 GSMPhone.java 中的的函數(shù):
public void setRadioPower(boolean power) mSST.setRadioPower(power);
因?yàn)橛?ServiceStateTracker mSST;
mSST.setRadioPower 調(diào)用的是文件 ServiceStateTracker.java 中的函數(shù):
public void setRadioPower(boolean power) mDesiredPowerState = power; setPowerStateToDesired(); cm.setRadioPower(true, null);
或者
cm.setRadioPower(false, null);
因?yàn)橛校?/p>
CommandsInterface cm; public final class RIL extends BaseCommands implements CommandsInterface
所以 cm.setRadioPower 調(diào)用的是文件 RIL.java 中的函數(shù):
public void setRadioPower(boolean on, Message result) RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result); rr.mp.writeInt(1); ... send(rr)
通過(guò) send 向 rild 發(fā)送 RIL_REQUEST_RADIO_POWER 請(qǐng)求來(lái)開啟或者關(guān)閉GSM模塊。
rild 數(shù)據(jù)接收流程:
收到 RIL_REQUEST_RADIO_POWER 執(zhí)行:
requestRadioPower(data, datalen, t);
然后根據(jù)條件往無(wú)線模塊發(fā)送模塊開啟和關(guān)閉請(qǐng)求
主要的at命令有:
err = at_send_command("AT+CFUN=0", &p_response); err = at_send_command("AT+CFUN=1", &p_response);
藍(lán)牙模塊切換過(guò)程分析:
enable(false);
藍(lán)牙開啟調(diào)用文件 BluetoothDeviceService.java 中的函數(shù):
public synchronized boolean enable(boolean saveSetting) setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON); mEnableThread = new EnableThread(saveSetting); mEnableThread.start(); ---- disable(false)
藍(lán)牙關(guān)閉調(diào)用文件 中的函數(shù):
public synchronized boolean disable(boolean saveSetting) setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF);
wifi模塊切換過(guò)程分析:
廣播 wifi 狀態(tài)改變的消息:WIFI_STATE_CHANGED_ACTION
更新 wifi 狀態(tài):
private void updateWifiState()
如果需要使能開啟 wifi 那么會(huì)發(fā)送:
sendEnableMessage(true, false, mLastEnableUid); sendStartMessage(strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY); mWifiHandler.sendEmptyMessage(MESSAGE_STOP_WIFI);
消息循環(huán)中處理命令消息:
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();
開啟過(guò)程步驟:
1> 裝載 wifi 驅(qū)動(dòng): WifiNative.loadDriver()
2> 啟動(dòng)后退 daemo supplicant: WifiNative.startSupplicant()
關(guān)閉過(guò)程步驟:
1> 停止后退 daemo supplicant:WifiNative.stopSupplicant()
2> 卸載 wifi 驅(qū)動(dòng): WifiNative.unloadDriver()
如果 wifi 狀態(tài)默認(rèn)為開啟那么 WifiService 服務(wù)的構(gòu)造函數(shù):
WifiService(Context context, WifiStateTracker tracker) boolean wifiEnabled = getPersistedWifiEnabled(); setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());
會(huì)開啟wifi模塊。
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android數(shù)據(jù)庫(kù)操作技巧總結(jié)》、《Android編程之a(chǎn)ctivity操作技巧總結(jié)》、《Android文件操作技巧匯總》、《Android編程開發(fā)之SD卡操作方法匯總》、《Android開發(fā)入門與進(jìn)階教程》、《Android資源操作技巧匯總》、《Android視圖View技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android APP啟動(dòng)方式、啟動(dòng)流程及啟動(dòng)優(yōu)化分析
- 分析Android中應(yīng)用的啟動(dòng)流程
- 從源碼分析Android的Glide庫(kù)的圖片加載流程及特點(diǎn)
- Android系統(tǒng)關(guān)機(jī)的全流程解析
- Android Bluetooth藍(lán)牙技術(shù)使用流程詳解
- Android Mms之:短信發(fā)送流程(圖文詳解)
- Android Mms之:接收信息流程(圖文詳解)
- Android中打電話的數(shù)據(jù)流程分析
- Android 2.3 撥號(hào)上網(wǎng)流程從源碼角度進(jìn)行分析
- Android編程輸入事件流程詳解
相關(guān)文章
Android 自定義彈出菜單和對(duì)話框功能實(shí)例代碼
Android 開發(fā)當(dāng)中,可能會(huì)存在許多自定義布局的需求,比如自定義彈出菜單(popupWindow),以及自定義對(duì)話框(Dialog)。下面通過(guò)本文給大家介紹Android 自定義彈出菜單和對(duì)話框功能實(shí)例代碼,感興趣的朋友一起看看吧2017-08-08為Android應(yīng)用增加渠道信息 自動(dòng)化不同渠道的打包過(guò)程的使用詳解
為了統(tǒng)計(jì)渠道信息,就不得不在程序的某個(gè)地方加入渠道的信息,然后針對(duì)不同的渠道打不同的包。一般可以在Manifest文件中加入渠道編號(hào),而不直接寫在代碼中。這樣做的好處是,可以針對(duì)不同渠道,自動(dòng)化去修改Manifest文件中的渠道編號(hào),然后自動(dòng)為該渠道打包2013-05-05Android studio 實(shí)現(xiàn)手機(jī)掃描二維碼功能
這篇文章主要介紹了Android studio 實(shí)現(xiàn)手機(jī)掃描二維碼功能,需要的朋友可以參考下2019-10-10Android GridView實(shí)現(xiàn)滾動(dòng)到指定位置的方法
這篇文章主要介紹了Android GridView實(shí)現(xiàn)滾動(dòng)到指定位置的方法,本文介紹了4個(gè)相關(guān)的方法,分別對(duì)它們做了講解,需要的朋友可以參考下2015-06-06android?scrollview頂部漸漸消失實(shí)現(xiàn)實(shí)例詳解
這篇文章主要為大家介紹了android?scrollview頂部漸漸消失實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11Android基于widget組件實(shí)現(xiàn)物體移動(dòng)/控件拖動(dòng)功能示例
這篇文章主要介紹了Android基于widget組件實(shí)現(xiàn)物體移動(dòng)/控件拖動(dòng)功能,結(jié)合實(shí)例形式分析了widget組件在桌面應(yīng)用中的事件響應(yīng)與屬性動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-10-10Android仿QQ分組實(shí)現(xiàn)二級(jí)菜單展示
這篇文章主要為大家詳細(xì)介紹了Android仿QQ分組實(shí)現(xiàn)二級(jí)菜單展示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Android手勢(shì)ImageView三部曲 第二部
這篇文章主要為大家詳細(xì)介紹了Android手勢(shì)ImageView三部曲的第二部,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03