Home | History | Annotate | Download | only in uicc
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.internal.telephony.uicc;
     18 
     19 import java.util.ArrayList;
     20 
     21 import android.os.AsyncResult;
     22 import android.os.Handler;
     23 import android.os.Looper;
     24 import android.os.Message;
     25 import android.telephony.Rlog;
     26 
     27 public class AdnRecordLoader extends Handler {
     28     final static String LOG_TAG = "AdnRecordLoader";
     29     final static boolean VDBG = false;
     30 
     31     //***** Instance Variables
     32 
     33     private IccFileHandler mFh;
     34     int mEf;
     35     int mExtensionEF;
     36     int mPendingExtLoads;
     37     Message mUserResponse;
     38     String mPin2;
     39 
     40     // For "load one"
     41     int mRecordNumber;
     42 
     43     // for "load all"
     44     ArrayList<AdnRecord> mAdns; // only valid after EVENT_ADN_LOAD_ALL_DONE
     45 
     46     // Either an AdnRecord or a reference to adns depending
     47     // if this is a load one or load all operation
     48     Object mResult;
     49 
     50     //***** Event Constants
     51 
     52     static final int EVENT_ADN_LOAD_DONE = 1;
     53     static final int EVENT_EXT_RECORD_LOAD_DONE = 2;
     54     static final int EVENT_ADN_LOAD_ALL_DONE = 3;
     55     static final int EVENT_EF_LINEAR_RECORD_SIZE_DONE = 4;
     56     static final int EVENT_UPDATE_RECORD_DONE = 5;
     57 
     58     //***** Constructor
     59 
     60     AdnRecordLoader(IccFileHandler fh) {
     61         // The telephony unit-test cases may create AdnRecords
     62         // in secondary threads
     63         super(Looper.getMainLooper());
     64         mFh = fh;
     65     }
     66 
     67     /**
     68      * Resulting AdnRecord is placed in response.obj.result
     69      * or response.obj.exception is set
     70      */
     71     public void
     72     loadFromEF(int ef, int extensionEF, int recordNumber,
     73                 Message response) {
     74         mEf = ef;
     75         mExtensionEF = extensionEF;
     76         mRecordNumber = recordNumber;
     77         mUserResponse = response;
     78 
     79         mFh.loadEFLinearFixed(
     80                     ef, recordNumber,
     81                     obtainMessage(EVENT_ADN_LOAD_DONE));
     82 
     83     }
     84 
     85 
     86     /**
     87      * Resulting ArrayList&lt;adnRecord> is placed in response.obj.result
     88      * or response.obj.exception is set
     89      */
     90     public void
     91     loadAllFromEF(int ef, int extensionEF,
     92                 Message response) {
     93         mEf = ef;
     94         mExtensionEF = extensionEF;
     95         mUserResponse = response;
     96 
     97         mFh.loadEFLinearFixedAll(
     98                     ef,
     99                     obtainMessage(EVENT_ADN_LOAD_ALL_DONE));
    100 
    101     }
    102 
    103     /**
    104      * Write adn to a EF SIM record
    105      * It will get the record size of EF record and compose hex adn array
    106      * then write the hex array to EF record
    107      *
    108      * @param adn is set with alphaTag and phone number
    109      * @param ef EF fileid
    110      * @param extensionEF extension EF fileid
    111      * @param recordNumber 1-based record index
    112      * @param pin2 for CHV2 operations, must be null if pin2 is not needed
    113      * @param response will be sent to its handler when completed
    114      */
    115     public void
    116     updateEF(AdnRecord adn, int ef, int extensionEF, int recordNumber,
    117             String pin2, Message response) {
    118         mEf = ef;
    119         mExtensionEF = extensionEF;
    120         mRecordNumber = recordNumber;
    121         mUserResponse = response;
    122         mPin2 = pin2;
    123 
    124         mFh.getEFLinearRecordSize( ef,
    125             obtainMessage(EVENT_EF_LINEAR_RECORD_SIZE_DONE, adn));
    126     }
    127 
    128     //***** Overridden from Handler
    129 
    130     @Override
    131     public void
    132     handleMessage(Message msg) {
    133         AsyncResult ar;
    134         byte data[];
    135         AdnRecord adn;
    136 
    137         try {
    138             switch (msg.what) {
    139                 case EVENT_EF_LINEAR_RECORD_SIZE_DONE:
    140                     ar = (AsyncResult)(msg.obj);
    141                     adn = (AdnRecord)(ar.userObj);
    142 
    143                     if (ar.exception != null) {
    144                         throw new RuntimeException("get EF record size failed",
    145                                 ar.exception);
    146                     }
    147 
    148                     int[] recordSize = (int[])ar.result;
    149                     // recordSize is int[3] array
    150                     // int[0]  is the record length
    151                     // int[1]  is the total length of the EF file
    152                     // int[2]  is the number of records in the EF file
    153                     // So int[0] * int[2] = int[1]
    154                    if (recordSize.length != 3 || mRecordNumber > recordSize[2]) {
    155                         throw new RuntimeException("get wrong EF record size format",
    156                                 ar.exception);
    157                     }
    158 
    159                     data = adn.buildAdnString(recordSize[0]);
    160 
    161                     if(data == null) {
    162                         throw new RuntimeException("wrong ADN format",
    163                                 ar.exception);
    164                     }
    165 
    166                     mFh.updateEFLinearFixed(mEf, mRecordNumber,
    167                             data, mPin2, obtainMessage(EVENT_UPDATE_RECORD_DONE));
    168 
    169                     mPendingExtLoads = 1;
    170 
    171                     break;
    172                 case EVENT_UPDATE_RECORD_DONE:
    173                     ar = (AsyncResult)(msg.obj);
    174                     if (ar.exception != null) {
    175                         throw new RuntimeException("update EF adn record failed",
    176                                 ar.exception);
    177                     }
    178                     mPendingExtLoads = 0;
    179                     mResult = null;
    180                     break;
    181                 case EVENT_ADN_LOAD_DONE:
    182                     ar = (AsyncResult)(msg.obj);
    183                     data = (byte[])(ar.result);
    184 
    185                     if (ar.exception != null) {
    186                         throw new RuntimeException("load failed", ar.exception);
    187                     }
    188 
    189                     if (VDBG) {
    190                         Rlog.d(LOG_TAG,"ADN EF: 0x"
    191                             + Integer.toHexString(mEf)
    192                             + ":" + mRecordNumber
    193                             + "\n" + IccUtils.bytesToHexString(data));
    194                     }
    195 
    196                     adn = new AdnRecord(mEf, mRecordNumber, data);
    197                     mResult = adn;
    198 
    199                     if (adn.hasExtendedRecord()) {
    200                         // If we have a valid value in the ext record field,
    201                         // we're not done yet: we need to read the corresponding
    202                         // ext record and append it
    203 
    204                         mPendingExtLoads = 1;
    205 
    206                         mFh.loadEFLinearFixed(
    207                             mExtensionEF, adn.mExtRecord,
    208                             obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
    209                     }
    210                 break;
    211 
    212                 case EVENT_EXT_RECORD_LOAD_DONE:
    213                     ar = (AsyncResult)(msg.obj);
    214                     data = (byte[])(ar.result);
    215                     adn = (AdnRecord)(ar.userObj);
    216 
    217                     if (ar.exception != null) {
    218                         throw new RuntimeException("load failed", ar.exception);
    219                     }
    220 
    221                     Rlog.d(LOG_TAG,"ADN extension EF: 0x"
    222                         + Integer.toHexString(mExtensionEF)
    223                         + ":" + adn.mExtRecord
    224                         + "\n" + IccUtils.bytesToHexString(data));
    225 
    226                     adn.appendExtRecord(data);
    227 
    228                     mPendingExtLoads--;
    229                     // result should have been set in
    230                     // EVENT_ADN_LOAD_DONE or EVENT_ADN_LOAD_ALL_DONE
    231                 break;
    232 
    233                 case EVENT_ADN_LOAD_ALL_DONE:
    234                     ar = (AsyncResult)(msg.obj);
    235                     ArrayList<byte[]> datas = (ArrayList<byte[]>)(ar.result);
    236 
    237                     if (ar.exception != null) {
    238                         throw new RuntimeException("load failed", ar.exception);
    239                     }
    240 
    241                     mAdns = new ArrayList<AdnRecord>(datas.size());
    242                     mResult = mAdns;
    243                     mPendingExtLoads = 0;
    244 
    245                     for(int i = 0, s = datas.size() ; i < s ; i++) {
    246                         adn = new AdnRecord(mEf, 1 + i, datas.get(i));
    247                         mAdns.add(adn);
    248 
    249                         if (adn.hasExtendedRecord()) {
    250                             // If we have a valid value in the ext record field,
    251                             // we're not done yet: we need to read the corresponding
    252                             // ext record and append it
    253 
    254                             mPendingExtLoads++;
    255 
    256                             mFh.loadEFLinearFixed(
    257                                 mExtensionEF, adn.mExtRecord,
    258                                 obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
    259                         }
    260                     }
    261                 break;
    262             }
    263         } catch (RuntimeException exc) {
    264             if (mUserResponse != null) {
    265                 AsyncResult.forMessage(mUserResponse)
    266                                 .exception = exc;
    267                 mUserResponse.sendToTarget();
    268                 // Loading is all or nothing--either every load succeeds
    269                 // or we fail the whole thing.
    270                 mUserResponse = null;
    271             }
    272             return;
    273         }
    274 
    275         if (mUserResponse != null && mPendingExtLoads == 0) {
    276             AsyncResult.forMessage(mUserResponse).result
    277                 = mResult;
    278 
    279             mUserResponse.sendToTarget();
    280             mUserResponse = null;
    281         }
    282     }
    283 
    284 
    285 }
    286