Android 無線啟動流程

时间:2021-06-03 15:13:20

 

开机流程中无线模块的原始化流程 ;假如 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) {

  mCheckBoxp ref.setEnabled(false);

  mCheckBoxp ref.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模块。