一.BP测流程
1.若不支持热插拔,modem启动时通过sim卡轮询方式来查询,实质为发送STATUS指令,对应的apdu命令为
2. 通过NV70210来启用或者禁用热插拔
3.初始化流程
UIM driver的初始化:power_up ,atr, pps, card_inserted
MMGSDI的SIM 初始化:激活app,pin,simlock, nv 值, sim ready
NV4398 代表单双卡,false为双卡
4.热插拔防抖
1>硬件防抖
睡眠时钟
2>软件防抖
用NV值进行控制
二.AP侧流程
1.rild进程
执行ps -e |grep ril 可知对应的ril进程
qcrild对应的qcrild.rc定义如下
service vendor.qcrild /vendor/bin/hw/qcrild
class main
user radio
disabled
group radio cache inet misc audio log readproc wakelock oem_2901
capabilities BLOCK_SUSPEND NET_ADMIN NET_RAW
adb可使用start/stop vendor.qcrild 来启用停用,因此可在源码中搜索start vendor.qcrild来知道是谁启动的rild 进程
因为每个芯片平台的rild代码各不相同,这里不进行相关的源码分析
2.phone进程
1>phoneAPP启动
android:persistent=“true” 代表开机启动
packages\services\Telephony\AndroidManifest.xml:
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/phoneAppLabel"
android:icon="@mipmap/ic_launcher_phone"
android:allowBackup="false"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
为啥 android:persistent为true就代表开机启动,可参考源码AMS中的startPersistentApps
2>phone进程中各种对象的加载
3.Uicc中卡状态的处理
卡状态在IccCardConstants中定义有11种,如图所示
卡加载时通过UiccController→UiccCard→UiccProfile, 在UiccProfile中调用updateIccAvailability–>updateExternalState→setExternalState进行设置
最终保存在gsm.sim.state中
卡状态转化图如下
查看updateExternalState,涉及到的条件列举如下
1>mUiccCard.getCardState()
mCardState保存在UiccCard中,对应ril返回的SIM卡状态中的第一个
获取的状态为CARDSTATE_ERROR时,设置为CARD_IO_ERROR
获取的状态为CARDSTATE_RESTRICTED时,设置为CARD_RESTRICTED
2>mUiccCard instanceof EuiccCard && ((EuiccCard) mUiccCard).getEid() == null
im卡为eUicc且还未获取到eid,eid也可以在返回的卡状态中看到
该条件满足时直接返回 ,关键打印EID is not ready yet.
解析ATR时判断是否创建EUICC
3>mUiccApplication == null
mUiccApplication默认值为null,在updateIccAvailability中进行设置
该条件满足时设置为NOT_READY,关键打印setting state to NOT_READY because mUiccApplication is null
查看updateIccAvailability,重点关注newApp = getApplication(mCurrentAppType);
mCurrentAppType由UiccProfile构造方法→setCurrentAppType进行设置
//UiccProfile
f (phone != null) {
setCurrentAppType(phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM);
}
//setCurrentAppType
private void setCurrentAppType(boolean isGsm) {
if (isGsm) {
mCurrentAppType = UiccController.APP_FAM_3GPP;
} else {
//if CSIM application is not present, set current app to default app i.e 3GPP
UiccCardApplication newApp = null;
newApp = getApplication(UiccController.APP_FAM_3GPP2);
if (newApp != null) {
mCurrentAppType = UiccController.APP_FAM_3GPP2;
} else {
mCurrentAppType = UiccController.APP_FAM_3GPP;
}
}
}
}
//GsmCdmaPhone
//getPhoneType
public int getPhoneType() {
if (mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM) {
return PhoneConstants.PHONE_TYPE_GSM;
} else {
return PhoneConstants.PHONE_TYPE_CDMA;
}
}
//构造方法
mPrecisePhoneType = precisePhoneType;//来自创建时传进的参数
initRatSpecific(precisePhoneType);
//PhoneFactory中的makeDefaultPhone中创建
int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { GSM
else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) CDMA
//关键log Creating Phone with type = (1代表GSM,2代表CDMA)
elephonyManager.getPhoneType(networkModes[i]): //传进的是属性ro.telephony.default_network的值,在device/qcom/XXX/system.prop中定义
当值为7,8,21,11才可能为CdmaPhone,其它为GsmPhone
创建GsmPhone时mCurrentAppType为APP_FAM_3GPP
创建CdmaPhone时,若mCdmaSubscriptionAppIndex(对应返回的卡状态中的cdma_id)不为空,mCurrentAppType为APP_FAM_3GPP2,否则设置为APP_FAM_3GPP
总结:下面几种情况会返回空
创建的是GsmPhone且gsm_id=-1
创建的是CdmaPhone且cdma_id=-1
创建的是CdmaPhone且gsm_id=-1 ,中间逻辑出现错误导致错误设置
4>appState = mUiccApplication.getState
对应上面选择的gsm_id,cdma_id中的括号里的值
注:当UiccCardApplication收到EVENT_RADIO_UNAVAILABLE时,会将appState 设置为APPSTATE_UNKNOWN
appState为APPSTATE_PIN时,设置为PIN_REQUIRED
appState为APPSTATE_PUK时,设置为PUK_REQUIRED
appState为APPSTATE_SUBSCRIPTION_PERSO时,设置为NETWORK_LOCKED
appState为APPSTATE_UNKNOWN时,设置为NOT_READY
5>pin1State = mUiccApplication.getPin1State
当pin1State 为PINSTATE_ENABLED_PERM_BLOCKED(PUK解锁失败,永久锁定),卡文件未加载完全时设置为NOT_READY,全部加载完成设置为PERM_DISABLED
6>mUiccApplication.isPersoLocked()
网络锁判断条件mPersoSubState,同样来自返回的卡状态
7>mIccRecords != null && (mIccRecords.getLockedRecordsLoaded() || mIccRecords.getNetworkLockedRecordsLoaded())
卡文件加载完成