Chinaunix首页 | 论坛 | 博客
  • 博客访问: 836319
  • 博文数量: 244
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 2420
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-29 09:07
文章分类

全部博文(244)

文章存档

2011年(4)

2010年(3)

2009年(72)

2008年(119)

2007年(46)

我的朋友

分类: LINUX

2009-05-22 10:50:57

开机过程中无线模块的初始化过程:
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模块。
 
阅读(1102) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~