官方示意图
* Following is class diagram for uicc classes:
*
* UiccController
* #
* |
* UiccSlot[]
* #
* |
* UiccCard
* #
* |
* UiccProfile
* # #
* | ------------------
* UiccCardApplication CatService
* # #
* | |
* IccRecords IccFileHandler
* ^ ^ ^ ^ ^ ^ ^ ^
* SIMRecords---- | | | | | | ---SIMFileHandler
* RuimRecords----- | | | | ----RuimFileHandler
* IsimUiccRecords--- | | -----UsimFileHandler
* | ------CsimFileHandler
* ----IsimFileHandler
*
* Legend: # stands for Composition
* ^ stands for Generalization
frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneFactory.java
创建UiccController
public static void makeDefaultPhone(Context context) {
...
sCommandsInterfaces = new RIL[numPhones];
sUiccController = UiccController.make(context, sCommandsInterfaces);
...
}
public static UiccController make(Context c, CommandsInterface[] ci) {
synchronized (mLock) {
if (mInstance != null) {
throw new RuntimeException("UiccController.make() should only be called once");
}
mInstance = new UiccController(c, ci);
return mInstance;
}
}
这里RIL是封装了radio hal的接口
/** Returns a {@link IRadio} instance or null if the service is not available. */
@VisibleForTesting
public synchronized IRadio getRadioProxy(Message result) {
...
if (mRadioProxy != null) {
return mRadioProxy;
}
// 不同的hal版本接口
if (mRadioProxy == null) {
try {
mRadioProxy = android.hardware.radio.V1_3.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
mRadioVersion = RADIO_HAL_VERSION_1_3;
} catch (NoSuchElementException e) {
}
}
if (mRadioProxy == null) {
try {
mRadioProxy = android.hardware.radio.V1_2.IRadio.getService(
HIDL_SERVICE_NAME[mPhoneId], true);
mRadioVersion = RADIO_HAL_VERSION_1_2;
} catch (NoSuchElementException e) {
}
}
...
//添加RadioResponse
mRadioProxy.setResponseFunctions(mRadioResponse, mRadioIndication);
}
hal中通过RadioResponse与JAVA层交互
UiccController初始化的时候会触发EVENT_RADIO_AVAILABLE
或者EVENT_RADIO_AVAILABLE
事件
private UiccController(Context c, CommandsInterface []ci) {
if (!StorageManager.inCryptKeeperBounce()) {
mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i);
} else {
mCis[i].registerForOn(this, EVENT_RADIO_ON, i);
}
}
JAVA层对应的处理逻辑 ,获取IccCardStatus完毕后,立马触发EVENT_GET_SLOT_STATUS_DONE事件
//UiccController.java
case EVENT_RADIO_AVAILABLE:
case EVENT_RADIO_ON:
mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE,
phoneId));
// slot status should be the same on all RILs; request it only for phoneId 0
if (phoneId == 0) {
//获取IccCardStatus完毕后,立马触发EVENT_GET_SLOT_STATUS_DONE事件
mRadioConfig.getSimSlotsStatus(obtainMessage(EVENT_GET_SLOT_STATUS_DONE,
phoneId));
}
break;
获取IccCardStatus,实际通过RIL调用hal接口
@Override
public void getIccCardStatus(Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
RILRequest rr = obtainRequest(RIL_REQUEST_GET_SIM_STATUS, result,
mRILDefaultWorkSource);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
try {
radioProxy.getIccCardStatus(rr.mSerial);
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "getIccCardStatus", e);
}
}
}
hal中对应的接口
// hardware/ril/libril/ril_service.cpp
Return<void> RadioImpl::getIccCardStatus(int32_t serial) {
#if VDBG
RLOGD("getIccCardStatus: serial %d", serial);
#endif
dispatchVoid(serial, mSlotId, RIL_REQUEST_GET_SIM_STATUS);
return Void();
}
所有的交互事件都会经过此流程 onRequest --> RIL_onRequestComplete
// hardware/ril/reference-ril/reference-ril.c
static void
onRequest (int request, void *data, size_t datalen, RIL_Token t)
{
...
switch (request) {
case RIL_REQUEST_GET_SIM_STATUS: {
RIL_CardStatus_v6 *p_card_status;
char *p_buffer;
int buffer_size;
int result = getCardStatus(&p_card_status);
if (result == RIL_E_SUCCESS) {
p_buffer = (char *)p_card_status;
buffer_size = sizeof(*p_card_status);
} else {
p_buffer = NULL;
buffer_size = 0;
}
RIL_onRequestComplete(t, result, p_buffer, buffer_size);
freeCardStatus(p_card_status);
break;
}
...
}
中间调用部分略过封装了Sokcket, 最终会调用到 getIccCardStatusResponse
int radio::getIccCardStatusResponse(int slotId,
int responseType, int serial, RIL_Errno e,
void *response, size_t responseLen) {
if (radioService[slotId]->mRadioResponse != NULL) {
RadioResponseInfo responseInfo = {};
populateResponseInfo(responseInfo, serial, responseType, e);
CardStatus cardStatus = {CardState::ABSENT, PinState::UNKNOWN, -1, -1, -1, {}};
RIL_CardStatus_v6 *p_cur = ((RIL_CardStatus_v6 *) response);
if (response == NULL || responseLen != sizeof(RIL_CardStatus_v6)
|| p_cur->gsm_umts_subscription_app_index >= p_cur->num_applications
|| p_cur->cdma_subscription_app_index >= p_cur->num_applications
|| p_cur->ims_subscription_app_index >= p_cur->num_applications) {
RLOGE("getIccCardStatusResponse: Invalid response");
if (e == RIL_E_SUCCESS) responseInfo.error = RadioError::INVALID_RESPONSE;
} else {
// CardStatus 赋值
cardStatus.cardState = (CardState) p_cur->card_state;
cardStatus.universalPinState = (PinState) p_cur->universal_pin_state;
cardStatus.gsmUmtsSubscriptionAppIndex = p_cur->gsm_umts_subscription_app_index;
cardStatus.cdmaSubscriptionAppIndex = p_cur->cdma_subscription_app_index;
cardStatus.imsSubscriptionAppIndex = p_cur->ims_subscription_app_index;
RIL_AppStatus *rilAppStatus = p_cur->applications;
cardStatus.applications.resize(p_cur->num_applications);
AppStatus *appStatus = cardStatus.applications.data();
#if VDBG
RLOGD("getIccCardStatusResponse: num_applications %d", p_cur->num_applications);
#endif
for (int i = 0; i < p_cur->num_applications; i++) {
appStatus[i].appType = (AppType) rilAppStatus[i].app_type;
appStatus[i].appState = (AppState) rilAppStatus[i].app_state;
appStatus[i].persoSubstate = (PersoSubstate) rilAppStatus[i].perso_substate;
appStatus[i].aidPtr = convertCharPtrToHidlString(rilAppStatus[i].aid_ptr);
appStatus[i].appLabelPtr = convertCharPtrToHidlString(
rilAppStatus[i].app_label_ptr);
appStatus[i].pin1Replaced = rilAppStatus[i].pin1_replaced;
appStatus[i].pin1 = (PinState) rilAppStatus[i].pin1;
appStatus[i].pin2 = (PinState) rilAppStatus[i].pin2;
}
}
// 调用java代码 RadioResponse.getIccCardStatusResponse
Return<void> retStatus = radioService[slotId]->mRadioResponse->
getIccCardStatusResponse(responseInfo, cardStatus);
radioService[slotId]->checkReturnStatus(retStatus);
} else {
RLOGE("getIccCardStatusResponse: radioService[%d]->mRadioResponse == NULL", slotId);
}
return 0;
}
java中会将CardStatus转换成ICardStatus
// frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioResponse.java
public void getIccCardStatusResponse(RadioResponseInfo responseInfo, CardStatus cardStatus) {
responseIccCardStatus(responseInfo, cardStatus);
}
public void getIccCardStatusResponse_1_2(RadioResponseInfo responseInfo,
android.hardware.radio.V1_2.CardStatus cardStatus) {
responseIccCardStatus_1_2(responseInfo, cardStatus);
}
private void responseIccCardStatus(RadioResponseInfo responseInfo, CardStatus cardStatus) {
RILRequest rr = mRil.processResponse(responseInfo);
if (rr != null) {
// 转换成 IccCardStatus
IccCardStatus iccCardStatus = convertHalCardStatus(cardStatus);
mRil.riljLog("responseIccCardStatus: from HIDL: " + iccCardStatus);
if (responseInfo.error == RadioError.NONE) {
sendMessageResponse(rr.mResult, iccCardStatus);
}
mRil.processResponseDone(rr, responseInfo, iccCardStatus);
}
}
到此RIL已经拿到了IccCardStatus ,接着触发EVENT_GET_SLOT_STATUS_DONE
事件调用onGetIccCardStatusDone创建了UiccSlot
case EVENT_GET_ICC_STATUS_DONE:
onGetIccCardStatusDone(ar, phoneId); //这一步中会创建UiccSlot
//创建UiccCard
private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) {
IccCardStatus status = (IccCardStatus)ar.result;
if (mUiccSlots[slotId] == null) {
mUiccSlots[slotId] = new UiccSlot(mContext, true);
}
//更新status
mUiccSlots[slotId].update(mCis[index], status, index, slotId);
}
UiccSlot.update函数会创建UiccCard, UiccCard中的信息就来自IccCardStatus
以电话号码为例:
public String getLine1NumberForDisplay(int subId, String callingPackage) {
String iccId = getIccId(subId);
if (iccId != null) {
String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
return mTelephonySharedPreferences.getString(numberPrefKey, null);
}
return null;
}
// 获取UiccCard中的mIccid
private String getIccId(int subId) {
final Phone phone = getPhone(subId);
UiccCard card = phone == null ? null : phone.getUiccCard();
String iccId = card.getIccId();
return iccId;
}
获取UiccCard中的mIccid
// frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/UiccCard.java
public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
synchronized (mLock) {
mCardState = ics.mCardState;
mContext = c;
mCi = ci;
mIccid = ics.iccid; //电话号码
updateCardId();
...
}
}
标签:md,cur,cardStatus,RIL,EVENT,UiccCard,null,流程,responseInfo
From: https://www.cnblogs.com/tangshunhui/p/18670863