android 無線模組的開機啟動

來源:互聯網
上載者:User

http://tech.sina.com.cn/s/2010-01-14/19281215405.shtml

開機過程中無線模組的初始化過程;如果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模組。

wordend 相關閱讀:
Android教程-解決WiFi串連不穩定
從零開始建立一個Android主畫面Widget
Android 妙招解決App Widget使用者互動

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.