首页 > 其他分享 >UiccCard流程.md

UiccCard流程.md

时间:2025-01-14 15:34:06浏览次数:1  
标签:md cur cardStatus RIL EVENT UiccCard null 流程 responseInfo

官方示意图

 * 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

相关文章

  • Oracle自定义函数:生成汉字首字母拼音码的函数、MD5
    1 生成汉字拼音码的函数使用方法:select用户名.函数名(需要获取首字母拼音码的字段名)from用户名.表名;selectoracle_user1.fgetpy(t.name)fromoracle_user1.studentt;函数定义:createorreplacefunctionfgetpy(v_strvarchar2)returnvarchar2asv_strleni......
  • O2O模式实战手册:利用板栗看板优化项目管理流程
    O2O(OnlineToOffline)模式,又称离线商务模式,是指线上营销线上购买或预订(预约)带动线下经营和线下消费。以下是对O2O模式的详细解析:一、模式概念O2O这个概念是2011年由AlexRampell提出来的,即将线下商务的机会与互联网结合在了一起,让互联网成为线下交易的前台。这样线下服务就可以......
  • pbootcms数据库sqlite转mysql操作流程
    操作并不复杂,如果没有基础,操作之前一定要备份,避免数据损坏第一步:用SQLiteStudio打开db数据库,并导出sql文件第二步:使用专用工具,将导出的sql文件进行处理。第三步:将文件通过数据库管理工具导入第四步:修改数据库配置文件,根据自己IDE数据库信息调整就行。第五步:登录网站......
  • 【 ATU NXP-MCX_A系列 】马达调适技巧与流程 ( 上 )
    1.   概述此文章简介说明马达调适的技巧与流程,基于NXPMCX_A系列MCU硬体搭配Freemaster界面来实际操作说明,简易说明BLDC马达FOC控制架构,让使用者快速了解马达控制架构,搭配调适流程,加快学习马达调适技巧,针对不同马达进行调适,马上知道问题点进行参数的调整,而非盲目......
  • Java流程控制
    用户交互Scannerimportjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){System.out.println("Helloworld!");//从键盘接收数据Scannerscanner=newScanner(System.in);//判断用户有......
  • 【黑灰产】杀猪盘作案流程讲解
    作案步骤何谓杀猪盘,指的是诈骗分子利用网络交友,获取受害人充分信任后,诱导受害人投资赌博的一种电信诈骗方式。“杀猪盘”是“从业者们”(诈骗团伙)自己起的名字,是指放长线“养猪”诈骗,养得越久,诈骗得越狠。整个杀猪盘作案流程可以分为三个步骤:找猪、养猪、杀猪。作案流程整......
  • 医学图像分析工具08:BrainSuite || 用 BrainSuite 处理 MRI 数据的完整流程 模块化、图
    BrainSuite:强大的神经影像分析工具BrainSuite是另一个广受神经科学研究人员喜爱的神经影像学分析工具。与FreeSurfer类似,BrainSuite的设计目标是通过高效的算法和简洁的界面帮助用户处理和分析MRI数据,但它更注重提供模块化、直观的操作体验。接下来,我们将详细探讨Br......
  • AMD发布科研Agent,论文自动化评分趋近顶会NeurIPS水平~
    科学发现漫长且成本高昂,为了加速科学发现,降低研究成本,并提高研究质量,芯片厂商AMD推出了AgentLaboratory,这是一个基于自主大型语言模型(LLM)的框架,能够完成整个研究流程。AgentLaboratory接受人类研究想法和一组笔记作为输入,将其提供给一系列由LLM驱动的专门Agent组成的流程线,......
  • DevOps 企业级 CI/CD 实战 —— 整合 GitLab+Jenkins+Harbor+Docker 实现代码全自动化
    前言随着AI人工智能、云计算、Docker、K8S等容器技术等的发展,DevOps得到了广泛的应用和推广,CI/CD(持续集成/持续部署)等概念不断深化和完善。CI/CD是现代软件开发中的重要实践,CI(ContinuousIntegration,持续集成)强调开发人员频繁地将代码集成到共享仓库,并且每次集成都......
  • 万字图文:SaaS业务架构、价值流、业务能力、业务流程、业务对象、组织架构
    大家好,我是汤师爷~本文为读者提供一个SaaS业务架构的系统性框架,探讨业务架构分析的核心要素,帮助SaaS企业深入剖析目标客户的业务模式,全面理解他们的业务架构。无论你是SaaS创业者、产品经理还是架构师,本文内容都将为你的系统设计和决策提供帮助。1目标与步骤SaaS业务架构需要......