UiccのIccFileHandler(原)


SIMカードの本質はファイルシステムであり、異なるパーティションを備えているが、IccFileHandlerは主にSIMカードから対応するパーティションのデータを読み出すために使用される.
一、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はデータを読み出した後に呼び出し者に通知し、戻り値を伝達する.
二、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カードによってパーティションのアドレス情報が異なるだけなので、これらのクラスの
唯一の違いは、親のgeteEFPath()メソッドを書き換えることです.たとえば、SIM FileHandler:
        @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のgeteEFPath()は次のとおりです.
        @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;
        }
には、SIM FileHandlerとUsimFileHandlerの違いがパーティションのアドレスにあることがわかります.
しかし、IccFileHandlerの構造方法の流れを見てみましょう.
        @IccFileHandler.java
        protected IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
            mParentApp = app;
            mAid = aid;
            mCi = ci;
        }

IcccFileHandlerの主な役割は受動的にSIMパーティション情報を照会することであるため,構築方法では重要なコンテキスト情報を保存して使用に備えるだけである.
三、IccFileHandlerがファイルを読み取る流れ
IcccFileHandlerの主な役割がファイル情報の読み取りである以上、彼がどのように情報の読み取りを実現したのかを追跡します.
線形固定長のファイル情報を読み取る際の最も一般的な流れを見てみましょう.
        @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()の3つの方法を呼び出すのにも同様に適している.
これがIccFileHandlerの読み取りメカニズムです.
次の章では、IccRecordsに関する流れについて説明します.