UiccController.java revision d720945f2be5ea5fe0faf67e67d9ea0e184eba67
1/* 2 * Copyright (C) 2011-2012 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 17package com.android.internal.telephony.uicc; 18 19import android.content.Context; 20import android.os.AsyncResult; 21import android.os.Handler; 22import android.os.Message; 23import android.os.Registrant; 24import android.os.RegistrantList; 25import android.telephony.Rlog; 26 27import com.android.internal.telephony.CommandsInterface; 28 29/** 30 * This class is responsible for keeping all knowledge about 31 * Universal Integrated Circuit Card (UICC), also know as SIM's, 32 * in the system. It is also used as API to get appropriate 33 * applications to pass them to phone and service trackers. 34 * 35 * UiccController is created with the call to make() function. 36 * UiccController is a singleton and make() must only be called once 37 * and throws an exception if called multiple times. 38 * 39 * Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed" 40 * notifications. When such notification arrives UiccController will call 41 * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS 42 * request appropriate tree of uicc objects will be created. 43 * 44 * Following is class diagram for uicc classes: 45 * 46 * UiccController 47 * # 48 * | 49 * UiccCard 50 * # # 51 * | ------------------ 52 * UiccCardApplication CatService 53 * # # 54 * | | 55 * IccRecords IccFileHandler 56 * ^ ^ ^ ^ ^ ^ ^ ^ 57 * SIMRecords---- | | | | | | ---SIMFileHandler 58 * RuimRecords----- | | | | ----RuimFileHandler 59 * IsimUiccRecords--- | | -----UsimFileHandler 60 * | ------CsimFileHandler 61 * ----IsimFileHandler 62 * 63 * Legend: # stands for Composition 64 * ^ stands for Generalization 65 * 66 * See also {@link com.android.internal.telephony.IccCard} 67 * and {@link com.android.internal.telephony.IccCardProxy} 68 */ 69public class UiccController extends Handler { 70 private static final boolean DBG = true; 71 private static final String LOG_TAG = "RIL_UiccController"; 72 73 public static final int APP_FAM_3GPP = 1; 74 public static final int APP_FAM_3GPP2 = 2; 75 public static final int APP_FAM_IMS = 3; 76 77 private static final int EVENT_ICC_STATUS_CHANGED = 1; 78 private static final int EVENT_GET_ICC_STATUS_DONE = 2; 79 80 private static final Object mLock = new Object(); 81 private static UiccController mInstance; 82 83 private Context mContext; 84 private CommandsInterface mCi; 85 private UiccCard mUiccCard; 86 87 private RegistrantList mIccChangedRegistrants = new RegistrantList(); 88 89 public static UiccController make(Context c, CommandsInterface ci) { 90 synchronized (mLock) { 91 if (mInstance != null) { 92 throw new RuntimeException("UiccController.make() should only be called once"); 93 } 94 mInstance = new UiccController(c, ci); 95 return mInstance; 96 } 97 } 98 99 public static UiccController getInstance() { 100 synchronized (mLock) { 101 if (mInstance == null) { 102 throw new RuntimeException( 103 "UiccController.getInstance can't be called before make()"); 104 } 105 return mInstance; 106 } 107 } 108 109 public UiccCard getUiccCard() { 110 synchronized (mLock) { 111 return mUiccCard; 112 } 113 } 114 115 // Easy to use API 116 public UiccCardApplication getUiccCardApplication(int family) { 117 synchronized (mLock) { 118 if (mUiccCard != null) { 119 return mUiccCard.getApplication(family); 120 } 121 return null; 122 } 123 } 124 125 // Easy to use API 126 public IccRecords getIccRecords(int family) { 127 synchronized (mLock) { 128 if (mUiccCard != null) { 129 UiccCardApplication app = mUiccCard.getApplication(family); 130 if (app != null) { 131 return app.getIccRecords(); 132 } 133 } 134 return null; 135 } 136 } 137 138 // Easy to use API 139 public IccFileHandler getIccFileHandler(int family) { 140 synchronized (mLock) { 141 if (mUiccCard != null) { 142 UiccCardApplication app = mUiccCard.getApplication(family); 143 if (app != null) { 144 return app.getIccFileHandler(); 145 } 146 } 147 return null; 148 } 149 } 150 151 //Notifies when card status changes 152 public void registerForIccChanged(Handler h, int what, Object obj) { 153 synchronized (mLock) { 154 Registrant r = new Registrant (h, what, obj); 155 mIccChangedRegistrants.add(r); 156 //Notify registrant right after registering, so that it will get the latest ICC status, 157 //otherwise which may not happen until there is an actual change in ICC status. 158 r.notifyRegistrant(); 159 } 160 } 161 162 public void unregisterForIccChanged(Handler h) { 163 synchronized (mLock) { 164 mIccChangedRegistrants.remove(h); 165 } 166 } 167 168 @Override 169 public void handleMessage (Message msg) { 170 synchronized (mLock) { 171 switch (msg.what) { 172 case EVENT_ICC_STATUS_CHANGED: 173 if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); 174 mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); 175 break; 176 case EVENT_GET_ICC_STATUS_DONE: 177 if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); 178 AsyncResult ar = (AsyncResult)msg.obj; 179 onGetIccCardStatusDone(ar); 180 break; 181 default: 182 Rlog.e(LOG_TAG, " Unknown Event " + msg.what); 183 } 184 } 185 } 186 187 private UiccController(Context c, CommandsInterface ci) { 188 if (DBG) log("Creating UiccController"); 189 mContext = c; 190 mCi = ci; 191 mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); 192 // TODO remove this once modem correctly notifies the unsols 193 mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null); 194 } 195 196 private synchronized void onGetIccCardStatusDone(AsyncResult ar) { 197 if (ar.exception != null) { 198 Rlog.e(LOG_TAG,"Error getting ICC status. " 199 + "RIL_REQUEST_GET_ICC_STATUS should " 200 + "never return an error", ar.exception); 201 return; 202 } 203 204 IccCardStatus status = (IccCardStatus)ar.result; 205 206 if (mUiccCard == null) { 207 //Create new card 208 mUiccCard = new UiccCard(mContext, mCi, status); 209 } else { 210 //Update already existing card 211 mUiccCard.update(mContext, mCi , status); 212 } 213 214 if (DBG) log("Notifying IccChangedRegistrants"); 215 mIccChangedRegistrants.notifyRegistrants(); 216 } 217 218 private void log(String string) { 219 Rlog.d(LOG_TAG, string); 220 } 221} 222