第1章 PhoneSwitcher的处理流程
- 注意:PhoneSwitcher在PhoneFactory中初始化。PhoneSwitcher在初始时注册了广播接收器,监听数据卡的变化。
图1 PhoneSwitcher类,初始时注册了广播接收器
同时,TelephonyNetworkFactory初始时,注册成PhoneSwitcher的观察者,监听Phone数据能力的切换。
图2注册成PhoneSwitcher的观察者
2、当PhoneSwitcher收到数据卡变化的广播后,其handleMessage调用onEvaluate函数。
图3调用handleMessage进行消息处理,调用onEvaluate
onEvaluate函数判断出数据卡确实发生变化后,就会激活数据卡对应的Phone的拨号能力;
同时去激活非数据卡对应phone的拨号能力。
图4激活数据卡对应的phone拨号能力
PhoneSwitcher中定义了PhoneState类,专门用于处理激活和去激活Phone拨号能力的工作,
同时维护对应Phone的激活状态。
图5 PhoneState类处理和激活Phone拨号能力
在完成上述工作后,PhoneSwitcher就会通知TelephonyNetworkFactory发生了Active Phone Switch。
图6 PhoneSwitcher通知TelephonyNetworkFactory
3、TelephonyNetworkFactory收到通知后,就会调用onActivePhoneSwitch进行处理。
在onActivePhoneSwitch函数中,首先会调用PhoneSwitcher提供的isPhoneActive接口,
查询并更新TelephonyNetworkFactory的激活状态。
图7 调用PhoneSwitcher提供的isPhoneActive接口
此时,对于处于激活状态的TelephonyNetworkFactory来说,就可进入后续的拨号的流程;
对于非激活的TelephonyNetworkFactory而言,则会进入后续断开数据连接的流程。
图8
PhoneSwitcher的这部分流程实际上起到了一种承前启后的作用。
终端加载完APN、设置完数据卡后,必须在这一步激活数据卡对应Phone的拨号能力,
后续的数据拨号流程才能顺利完成。
4、PhoneSwitcher的 InformDdsRil()方法
4.1)在ConnectivityService构造的时候就创建了一个默认的defaultRequest,mDefauleRequest。网络工厂连接上以后,就请求网络连接。
4.2)在ConnectivityService的handleAsyncChannelHalfConnect里面,如果已经连接到网络工厂,就把网络请求CMD_REQUEST_NETWORK发到对应的网络工厂。
接着就是网络工厂处理请求CMD_REQUEST_NETWORK。
4.3)NetWorkFactory的handleAddRequest进行处理,调用evalRequest来判断是开启网络还是释放网络:
如果开启网络则调用needNetworkFor,如果是释放网络则调用releaseNetWorkFor;
现在先关注移动网络开启数据的,由于移动网络的网络工厂是TelephonyNetworkFactory,在dctController里面进行定义的。
4.4)TelepjonyNetworkFactory:needNetworkFor
检查sub id是否符合,还有apn是否支持,如果符合条件,则调用requestNetWork
4.5)DctController:request
把请求加入到队列mRequestInfo中,紧接着调用processRequests来处理队列中的请求。
4.6)QtiDctController:onProcessRequest
根据请求判断是否需要切DDs,需要的话调用handleDdsSwitch
4.7)qtiDctController:handleDdsSwitch
根据情况是要关闭当前的数据,还是开始建立连接,关闭调用doDisconnectAll,建立连接调用doConnect
4.8)qtiDctController:doConnect
调用informDdsToRil通知底层默认的dds,然后通过DcSwitchAsyncchannel的connect发送请求Request_Connect
状态条转如下:IdleState->AttachingState->AttachedState->DetachingState->IdleState
在AttachingState会调用setDataAllowed为true,DetachingState会setDataAllowed为falsesetDataAllowed会把某个phone的ps变为attached,从而触发建立data call。
扩展:在插卡之前也会创建PhoneSwitcher,未插卡的时候PhoneId都为0;插卡之后把subid赋值给PhoneId。
一)整体流程总结
- 每次插拔SIM卡都会将联系人数据库中关于SIM卡的联系人删除;
- SimStateReceiver 通过接收 RIL 上报的关于 SIM 卡状态变化的广播去启动 SimContactsService;
- SimContactsService 异步启动 IccProvider 去查询 SIM 卡联系人;
- 通过 IccPhoneBookInterfaceManager 一层层调用到 RIL 然后层层返回,最后构造MatrixCursor 插入数据库。
- 涉及的相关类的功能
- IccProvider:对外暴露的接口,我们通过它来查询SIM卡中的contacts信息;
- IccPhoneBookInterfaceManager: PhoneBook操作的服务;
- IccPhoneBookInterfaceManagerProxy:对外的PhoneBook操作服务, 上面类的代理;
- IccRecord:存储与卡相关的一些信息;
- AdnRecord:一条联系人信息读取后被封装的类型;
- AdnRecordCache:对SIM卡中联系人信息进行Cache;
- AdnRecordLoader:实际通过IccFileHandler去获取adn信息的类;
- IccFileHandler:向RIL发起请求,或者接受反馈;
- RIL:向底层发起请求,并接收反馈。
三)具体代码分析
- Phone进程通过AndroidManifest.xml启动之后,设备开机后在用户解锁前会进入一个DirectBootMode,这是系统会发送ACTION_LOCKED_BOOT_COMPLETED广播,等用户解锁后,系统才会发送ACTION_ BOOT_COMPLETED广播。
- SimStateReceiver 通过接收 RIL 上报的关于 SIM 卡状态变化的广播去启动 SimContactsService;
以下是对此的详细代码分析:
图2.1
插卡后,收到卡的状态变化的消息,或者收到phone启动后发送的广播消息ACTION_ BOOT_COMPLETED。
这里拿收到ACTION_ BOOT_COMPLETED来举例说明,收到该消息之后会执行sendPhoneBoot函数;在sendPhoneBoot函数中,会启动SimContactsService。
图2.2启动SimContentsService
- SimContactsService 异步启动 IccProvider 去查询 SIM 卡联系人;
- 通过 IccPhoneBookInterfaceManager 一层层调用到 RIL 然后层层返回,最后构造MatrixCursor 插入数据库。
1.前提介绍:该密码保存在/data/misc/keystore/user_0/.masterkey,可在adb shell后,ls –al /data/misc/keystore/user_0/.masterkey查看文件存在与否。
下面讲述的是,从设置点击 安全-屏幕锁定方式,设定pin-设置pin码,通知-完成,到pin如何进行加密和存储的。完成这个button是一个设置中通用的一个按键,不再通知界面的布局中。
2. 这个按键响应ChooseLockPassword.java的onClick方法,执行以下代码:
图3.1执行onclick()
进入handleNext()方法,当确认密码正确时,执行startSaveFinsh操作
图3.2执行startSaveAndFinsh()
看一下startSaveFinsh()函数的具体执行过程,在该过程中会调用SaveAndFinishWorker类的start方法。
图3.3在该过程中会调用ChooseLockPassword.java文件中的SaveAndFinishWorker的start()方法
3. 进入ChooseLockPassword.java文件中的SaveAndFinishWorker类里面执行start()方法,看一下start方法的详细内容。
SaveAndFinishWorker继承于SaveChosenLockWorkerBase类,在SaveAndFinishWorker的satrt方法的最后会执行staart(),这个start是SaveChosenLockWorkerBase类里面的方法。
图3.4 ChooseLockPassword.java文件的SaveAndFinishWorker类里执行start()
- 进入SaveChosenLockWorkerBase类查看具体的start方法。在该start方法中会调用ChooseLockPassword 类的saveAndVerifyInBackground()方法。
图3.5在该start方法中会结束ChooseLockPassword 的saveAndVerifyInBackground()
- ChooseLockPassword 类的saveAndVerifyInBackground(),在这个方法里面会调用LockPatternUtils.java文件的saveLockPassword()方法
图3.6调用LockPatternUtils.java文件的saveLockPassword()方法
- 看具体的LockPatternUtils.java文件的saveLockPassword()方法。进入该方法来保存密码。通过getLockSettings()间接调用LockSettingsS