Home | History | Annotate | Download | only in telephony
      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;
     18 
     19 import java.util.ArrayList;
     20 
     21 import android.os.AsyncResult;
     22 import android.os.Handler;
     23 import android.os.Message;
     24 import android.util.Log;
     25 
     26 
     27 public class AdnRecordLoader extends Handler {
     28     static String LOG_TAG;
     29 
     30     //***** Instance Variables
     31 
     32     PhoneBase phone;
     33     int ef;
     34     int extensionEF;
     35     int pendingExtLoads;
     36     Message userResponse;
     37     String pin2;
     38 
     39     // For "load one"
     40     int recordNumber;
     41 
     42     // for "load all"
     43     ArrayList<AdnRecord> adns; // only valid after EVENT_ADN_LOAD_ALL_DONE
     44 
     45     // Either an AdnRecord or a reference to adns depending
     46     // if this is a load one or load all operation
     47     Object result;
     48 
     49     //***** Event Constants
     50 
     51     static final int EVENT_ADN_LOAD_DONE = 1;
     52     static final int EVENT_EXT_RECORD_LOAD_DONE = 2;
     53     static final int EVENT_ADN_LOAD_ALL_DONE = 3;
     54     static final int EVENT_EF_LINEAR_RECORD_SIZE_DONE = 4;
     55     static final int EVENT_UPDATE_RECORD_DONE = 5;
     56 
     57     //***** Constructor
     58 
     59     public AdnRecordLoader(PhoneBase phone) {
     60         // The telephony unit-test cases may create AdnRecords
     61         // in secondary threads
     62         super(phone.getHandler().getLooper());
     63 
     64         this.phone = phone;
     65         LOG_TAG = phone.getPhoneName();
     66     }
     67 
     68     /**
     69      * Resulting AdnRecord is placed in response.obj.result
     70      * or response.obj.exception is set
     71      */
     72     public void
     73     loadFromEF(int ef, int extensionEF, int recordNumber,
     74                 Message response) {
     75         this.ef = ef;
     76         this.extensionEF = extensionEF;
     77         this.recordNumber = recordNumber;
     78         this.userResponse = response;
     79 
     80         phone.mIccFileHandler.loadEFLinearFixed(
     81                     ef, recordNumber,
     82                     obtainMessage(EVENT_ADN_LOAD_DONE));
     83 
     84     }
     85 
     86 
     87     /**
     88      * Resulting ArrayList&lt;adnRecord> is placed in response.obj.result
     89      * or response.obj.exception is set
     90      */
     91     public void
     92     loadAllFromEF(int ef, int extensionEF,
     93                 Message response) {
     94         this.ef = ef;
     95         this.extensionEF = extensionEF;
     96         this.userResponse = response;
     97 
     98         phone.mIccFileHandler.loadEFLinearFixedAll(
     99                     ef,
    100                     obtainMessage(EVENT_ADN_LOAD_ALL_DONE));
    101 
    102     }
    103 
    104     /**
    105      * Write adn to a EF SIM record
    106      * It will get the record size of EF record and compose hex adn array
    107      * then write the hex array to EF record
    108      *
    109      * @param adn is set with alphaTag and phone number
    110      * @param ef EF fileid
    111      * @param extensionEF extension EF fileid
    112      * @param recordNumber 1-based record index
    113      * @param pin2 for CHV2 operations, must be null if pin2 is not needed
    114      * @param response will be sent to its handler when completed
    115      */
    116     public void
    117     updateEF(AdnRecord adn, int ef, int extensionEF, int recordNumber,
    118             String pin2, Message response) {
    119         this.ef = ef;
    120         this.extensionEF = extensionEF;
    121         this.recordNumber = recordNumber;
    122         this.userResponse = response;
    123         this.pin2 = pin2;
    124 
    125         phone.mIccFileHandler.getEFLinearRecordSize( ef,
    126             obtainMessage(EVENT_EF_LINEAR_RECORD_SIZE_DONE, adn));
    127     }
    128 
    129     //***** Overridden from Handler
    130 
    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 || recordNumber > 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                     phone.mIccFileHandler.updateEFLinearFixed(ef, recordNumber,
    167                             data, pin2, obtainMessage(EVENT_UPDATE_RECORD_DONE));
    168 
    169                     pendingExtLoads = 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                     pendingExtLoads = 0;
    179                     result = 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 (false) {
    190                         Log.d(LOG_TAG,"ADN EF: 0x"
    191                             + Integer.toHexString(ef)
    192                             + ":" + recordNumber
    193                             + "\n" + IccUtils.bytesToHexString(data));
    194                     }
    195 
    196                     adn = new AdnRecord(ef, recordNumber, data);
    197                     result = 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                         pendingExtLoads = 1;
    205 
    206                         phone.mIccFileHandler.loadEFLinearFixed(
    207                             extensionEF, adn.extRecord,
    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                     Log.d(LOG_TAG,"ADN extension EF: 0x"
    222                         + Integer.toHexString(extensionEF)
    223                         + ":" + adn.extRecord
    224                         + "\n" + IccUtils.bytesToHexString(data));
    225 
    226                     adn.appendExtRecord(data);
    227 
    228                     pendingExtLoads--;
    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                     adns = new ArrayList<AdnRecord>(datas.size());
    242                     result = adns;
    243                     pendingExtLoads = 0;
    244 
    245                     for(int i = 0, s = datas.size() ; i < s ; i++) {
    246                         adn = new AdnRecord(ef, 1 + i, datas.get(i));
    247                         adns.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                             pendingExtLoads++;
    255 
    256                             phone.mIccFileHandler.loadEFLinearFixed(
    257                                 extensionEF, adn.extRecord,
    258                                 obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
    259                         }
    260                     }
    261                 break;
    262             }
    263         } catch (RuntimeException exc) {
    264             if (userResponse != null) {
    265                 AsyncResult.forMessage(userResponse)
    266                                 .exception = exc;
    267                 userResponse.sendToTarget();
    268                 // Loading is all or nothing--either every load succeeds
    269                 // or we fail the whole thing.
    270                 userResponse = null;
    271             }
    272             return;
    273         }
    274 
    275         if (userResponse != null && pendingExtLoads == 0) {
    276             AsyncResult.forMessage(userResponse).result
    277                 = result;
    278 
    279             userResponse.sendToTarget();
    280             userResponse = null;
    281         }
    282     }
    283 
    284 
    285 }
    286