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