Uicc의 IccFileHandler(원본)

SIM카드의 본질은 파일 시스템이고 서로 다른 구역을 갖추고 있으며 IccFileHandler는 주로 SIM카드에서 해당 구역의 데이터를 읽는 데 사용된다.
1. IccFileHandler 기능
제공되는 Public 접근 방식을 살펴보겠습니다.
        public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) {}
        public void loadEFImgLinearFixed(int recordNum, Message onLoaded) {}
        public void loadEFLinearFixedAll(int fileid, Message onLoaded) {}
        public void loadEFTransparent(int fileid, Message onLoaded) {}
        public void loadEFTransparent(int fileid, int size, Message onLoaded) {}
        public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset, int length, Message onLoaded) {}
        public void getEFLinearRecordSize(int fileid, Message onLoaded) {}
        public void updateEFLinearFixed(int fileid, int recordNum, byte[] data, String pin2, Message onComplete) {}
        public void updateEFTransparent(int fileid, byte[] data, Message onComplete) {}

이러한 방법에서 알 수 있듯이 IccFileHandler의 주요 역할은SIM카드 파일 시스템의 읽기와 쓰기 조작을 제공하는 것이다. 이런 방법을 호출할 때 읽기와 쓰기가 필요한 파일 시스템 주소와 읽기가 끝난 후의 리셋 함수를 전달해야 한다. IccFileHandler는 데이터를 읽은 후에 호출자에게 알리고 리셋 값을 전달한다.
2. IccFileHandler의 생성 과정
       
서로 다른 유형의 SIM 카드 파티션 정보가 다르므로 UiccCardApplication에서는 현재 SIM 유형에 따라 다른 IccFileHandler 객체를 만듭니다.
        @UiccCardApplication.java
        private IccFileHandler createIccFileHandler(AppType type) {
            switch (type) {
                case APPTYPE_SIM:
                    return new SIMFileHandler(this, mAid, mCi);
                case APPTYPE_RUIM:
                    return new RuimFileHandler(this, mAid, mCi);
                case APPTYPE_USIM:
                    return new UsimFileHandler(this, mAid, mCi);
                case APPTYPE_CSIM:
                    return new CsimFileHandler(this, mAid, mCi);
                case APPTYPE_ISIM:
                    return new IsimFileHandler(this, mAid, mCi);
                default:
                    return null;
            }
        }
이 몇 가지 종류는 모두 IccFileHandler에서 계승되었다.서로 다른 SIM 카드는 단지 구역의 주소 정보에 차이가 있기 때문에 이런 몇 가지 종류는
유일한 차이점은 상위 클래스의 geteFPath () 방법을 다시 쓰는 것입니다. 예를 들어 SIMFileHandler:
        @SIMFileHandler.java
        protected String getEFPath(int efid) {
            switch(efid) {
                case EF_SMS:
                    return MF_SIM + DF_TELECOM;
                case EF_EXT6:
                case EF_MWIS:
                case EF_MBI:
                case EF_SPN:
                case EF_AD:
                case EF_MBDN:
                case EF_PNN:
                case EF_SPDI:
                case EF_SST:
                case EF_CFIS:
                case EF_GID1:
                    return MF_SIM + DF_GSM;
                case EF_MAILBOX_CPHS:
                case EF_VOICE_MAIL_INDICATOR_CPHS:
                case EF_CFF_CPHS:
                case EF_SPN_CPHS:
                case EF_SPN_SHORT_CPHS:
                case EF_INFO_CPHS:
                case EF_CSP_CPHS:
                    return MF_SIM + DF_GSM;
            }
            String path = getCommonIccEFPath(efid);
            if (path == null) {
                Rlog.e(LOG_TAG, "Error: EF Path being returned in null");
            }
            return path;
        } 
UsimFileHandler의 geteFPath()는 다음과 같다.
        @UsimFileHandler.java
        protected String getEFPath(int efid) {
            switch(efid) {
                case EF_SMS:
                case EF_EXT6:
                case EF_MWIS:
                case EF_MBI:
                case EF_SPN:
                case EF_AD:
                case EF_MBDN:
                case EF_PNN:
                case EF_OPL:
                case EF_SPDI:
                case EF_SST:
                case EF_CFIS:
                case EF_MAILBOX_CPHS:
                case EF_VOICE_MAIL_INDICATOR_CPHS:
                case EF_CFF_CPHS:
                case EF_SPN_CPHS:
                case EF_SPN_SHORT_CPHS:
                case EF_FDN:
                case EF_MSISDN:
                case EF_EXT2:
                case EF_INFO_CPHS:
                case EF_CSP_CPHS:
                case EF_GID1:
                    return MF_SIM + DF_ADF;

                case EF_PBR:
                    return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
            }
            String path = getCommonIccEFPath(efid);
            if (path == null) {
                return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
            }
            return path;
        }
에서 볼 수 있듯이 SIMFileHandler와 UsimFileHandler의 차이는 구역의 주소에 있다.
그런 다음 IccFileHandler의 구성 방법 프로세스를 살펴보십시오.
        @IccFileHandler.java
        protected IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
            mParentApp = app;
            mAid = aid;
            mCi = ci;
        }

IccFileHandler의 주요 역할은 수동적으로 SIM 구역 정보를 조회하는 것이기 때문에 구조 방법에서 중요한 상하문 정보를 사용하기 위해 저장할 뿐이다.
3. IccFileHandler가 파일을 읽는 절차
IccFileHandler의 주요 역할이 파일 정보를 읽는 것이기 때문에 그가 어떻게 정보를 읽는지 추적해 보겠습니다.
선형 고정 길이의 파일 정보를 읽을 때 가장 자주 사용하는 절차를 살펴보겠습니다.
        @IccFileHandler.java
        public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) {
            //    Record Size
            Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE, new LoadLinearFixedContext(fileid, recordNum, onLoaded));
            //  RILJ Modem  SIM        
            mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response);
        }
이 읽기 과정에서 해당 구역 내용을 직접 읽는 것이 아니라 현재 구역 기록의 길이를 먼저 읽고 길이를 받은 후에 현재 기록의 구체적인 내용을 읽는다.
        public void handleMessage(Message msg) {
            AsyncResult ar;
            IccIoResult result;
            Message response = null;
            String str;
            LoadLinearFixedContext lc;

            byte data[];
            int size;
            int fileid;
            int recordSize[];
            try {
                switch (msg.what) {
                    case EVENT_GET_RECORD_SIZE_IMG_DONE:
                    case EVENT_GET_RECORD_SIZE_DONE:
                        //   Modem       
                        ar = (AsyncResult)msg.obj;
                        lc = (LoadLinearFixedContext) ar.userObj;
                        result = (IccIoResult) ar.result;
                        response = lc.mOnLoaded;

                        if (processException(response, (AsyncResult) msg.obj)) {
                            break;
                        }

                        data = result.payload;
                        if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
                            throw new IccFileTypeMismatch();
                        }
                        if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
                            throw new IccFileTypeMismatch();
                        }

                        //         
                        lc.mRecordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;

                        size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8) + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);

                        lc.mCountRecords = size / lc.mRecordSize;
                        if (lc.mLoadAll) {
                            lc.results = new ArrayList<byte[]>(lc.mCountRecords);
                        }

                        //                
                        mCi.iccIOForApp(COMMAND_READ_RECORD, lc.mEfid, getEFPath(lc.mEfid),
                                lc.mRecordNum,
                                READ_RECORD_MODE_ABSOLUTE,
                                lc.mRecordSize, null, null, mAid,
                                obtainMessage(EVENT_READ_RECORD_DONE, lc));
                        break;


                }} catch (Exception exc) {
                }
        }
여기서 IccFileHandler가 기록의 길이를 받은 후,
iccIOForApp()를 통해 기록된 데이터를 다시 읽으면 진정으로 필요한 데이터를 얻을 수 있다.
        public void handleMessage(Message msg) {
            AsyncResult ar;
            IccIoResult result;
            Message response = null;
            String str;
            LoadLinearFixedContext lc;

            byte data[];
            int size;
            int fileid;
            int recordSize[];
            try {
                switch (msg.what) {
                    case EVENT_READ_IMG_DONE:
                    case EVENT_READ_RECORD_DONE:
                        ar = (AsyncResult)msg.obj;
                        lc = (LoadLinearFixedContext) ar.userObj;
                        result = (IccIoResult) ar.result;
                        response = lc.mOnLoaded;
                        if (processException(response, (AsyncResult) msg.obj)) {
                            break;
                        }

                        if (!lc.mLoadAll) {
                            sendResult(response, result.payload, null);
                        } else {
                            lc.results.add(result.payload);
                            lc.mRecordNum++;

                            //      
                            if (lc.mRecordNum > lc.mCountRecords) {
                                sendResult(response, lc.results, null);
                            } else {
                                mCi.iccIOForApp(COMMAND_READ_RECORD, lc.mEfid, getEFPath(lc.mEfid),
                                        lc.mRecordNum,
                                        READ_RECORD_MODE_ABSOLUTE,
                                        lc.mRecordSize, null, null, mAid,
                                        obtainMessage(EVENT_READ_RECORD_DONE, lc));
                            }
                        }

                        break;


                }} catch (Exception exc) {
                }
        }
기록을 읽는 과정에서 기록이 완전히 읽히고 (lc.mRecordNum > lc.mCountRecords) 기록이 끝날 때까지sendResult () 방법으로 기록 데이터를 당초 요청자에게 보내는 것을 보았다.
길이를 먼저 읽고 내용을 읽는 이런 방식은 loadEFLinearFixed(), loadEFImgLinearFixed(), loadEFTransparent() 등 세 가지 방법에도 적용된다.
이것이 IccFileHandler의 읽기 메커니즘입니다.
다음 장에서는 IccRecords 관련 프로세스에 대해 설명합니다.

좋은 웹페이지 즐겨찾기