UiccController.java revision e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2
1/* 2 * Copyright (C) 2011 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 com.android.internal.telephony.CommandsInterface; 20import com.android.internal.telephony.IccCard; 21import com.android.internal.telephony.IccCardStatus; 22import com.android.internal.telephony.IccCardStatus.CardState; 23import com.android.internal.telephony.PhoneBase; 24 25import android.os.AsyncResult; 26import android.os.Handler; 27import android.os.Message; 28import android.os.Registrant; 29import android.os.RegistrantList; 30import android.util.Log; 31 32/* This class is responsible for keeping all knowledge about 33 * ICCs in the system. It is also used as API to get appropriate 34 * applications to pass them to phone and service trackers. 35 */ 36public class UiccController extends Handler { 37 private static final boolean DBG = true; 38 private static final String LOG_TAG = "RIL_UiccController"; 39 40 private static final int EVENT_ICC_STATUS_CHANGED = 1; 41 private static final int EVENT_GET_ICC_STATUS_DONE = 2; 42 43 private static UiccController mInstance; 44 45 private PhoneBase mCurrentPhone; 46 private CommandsInterface mCi; 47 private IccCard mIccCard; 48 private boolean mRegisteredWithCi = false; 49 50 private RegistrantList mIccChangedRegistrants = new RegistrantList(); 51 52 public static synchronized UiccController getInstance(PhoneBase phone) { 53 if (mInstance == null) { 54 mInstance = new UiccController(phone); 55 } else if (phone != null) { 56 mInstance.setNewPhone(phone); 57 } 58 return mInstance; 59 } 60 61 // This method is not synchronized as getInstance(PhoneBase) is. 62 public static UiccController getInstance() { 63 return getInstance(null); 64 } 65 66 public synchronized IccCard getIccCard() { 67 return mIccCard; 68 } 69 70 //Notifies when card status changes 71 public void registerForIccChanged(Handler h, int what, Object obj) { 72 Registrant r = new Registrant (h, what, obj); 73 mIccChangedRegistrants.add(r); 74 //Notify registrant right after registering, so that it will get the latest ICC status, 75 //otherwise which may not happen until there is an actual change in ICC status. 76 r.notifyRegistrant(); 77 } 78 public void unregisterForIccChanged(Handler h) { 79 mIccChangedRegistrants.remove(h); 80 } 81 82 @Override 83 public void handleMessage (Message msg) { 84 switch (msg.what) { 85 case EVENT_ICC_STATUS_CHANGED: 86 if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); 87 mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); 88 break; 89 case EVENT_GET_ICC_STATUS_DONE: 90 if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); 91 AsyncResult ar = (AsyncResult)msg.obj; 92 onGetIccCardStatusDone(ar); 93 break; 94 default: 95 Log.e(LOG_TAG, " Unknown Event " + msg.what); 96 } 97 } 98 99 private UiccController(PhoneBase phone) { 100 if (DBG) log("Creating UiccController"); 101 setNewPhone(phone); 102 } 103 104 private synchronized void onGetIccCardStatusDone(AsyncResult ar) { 105 if (ar.exception != null) { 106 Log.e(LOG_TAG,"Error getting ICC status. " 107 + "RIL_REQUEST_GET_ICC_STATUS should " 108 + "never return an error", ar.exception); 109 return; 110 } 111 112 IccCardStatus status = (IccCardStatus)ar.result; 113 114 //Update already existing card 115 if (mIccCard != null && status.getCardState() == CardState.CARDSTATE_PRESENT) { 116 mIccCard.update(mCurrentPhone, status); 117 } 118 119 //Dispose of removed card 120 if (mIccCard != null && status.getCardState() != CardState.CARDSTATE_PRESENT) { 121 mIccCard.dispose(); 122 mIccCard = null; 123 } 124 125 //Create new card 126 if (mIccCard == null && status.getCardState() == CardState.CARDSTATE_PRESENT) { 127 mIccCard = new IccCard(mCurrentPhone, status, mCurrentPhone.getPhoneName(), true); 128 } 129 130 if (DBG) log("Notifying IccChangedRegistrants"); 131 mIccChangedRegistrants.notifyRegistrants(); 132 } 133 134 private void setNewPhone(PhoneBase phone) { 135 if (phone == null) { 136 throw new RuntimeException("Phone can't be null in UiccController"); 137 //return; 138 } 139 140 if (DBG) log("setNewPhone"); 141 if (mCurrentPhone != phone) { 142 if (mIccCard != null) { 143 // Refresh card if phone changed 144 // TODO: Remove once card is simplified 145 if (DBG) log("Disposing card since phone object changed"); 146 mIccCard.dispose(); 147 mIccCard = null; 148 } 149 sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED)); 150 mCurrentPhone = phone; 151 152 if (!mRegisteredWithCi) { 153 // This needs to be done only once after we have valid phone object 154 mCi = mCurrentPhone.mCM; 155 mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); 156 // TODO remove this once modem correctly notifies the unsols 157 mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null); 158 mRegisteredWithCi = true; 159 } 160 } 161 } 162 163 private void log(String string) { 164 Log.d(LOG_TAG, string); 165 } 166} 167