UiccController.java revision f92aefb45aa708772779a1ea10622b38f965fab5
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) { 116 mIccCard.update(mCurrentPhone, status); 117 } 118 119 //Create new card 120 if (mIccCard == null) { 121 mIccCard = new IccCard(mCurrentPhone, status, mCurrentPhone.getPhoneName(), true); 122 } 123 124 if (DBG) log("Notifying IccChangedRegistrants"); 125 mIccChangedRegistrants.notifyRegistrants(); 126 } 127 128 private void setNewPhone(PhoneBase phone) { 129 if (phone == null) { 130 throw new RuntimeException("Phone can't be null in UiccController"); 131 //return; 132 } 133 134 if (DBG) log("setNewPhone"); 135 if (mCurrentPhone != phone) { 136 if (mIccCard != null) { 137 // Refresh card if phone changed 138 // TODO: Remove once card is simplified 139 if (DBG) log("Disposing card since phone object changed"); 140 mIccCard.dispose(); 141 mIccCard = null; 142 } 143 sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED)); 144 mCurrentPhone = phone; 145 146 if (!mRegisteredWithCi) { 147 // This needs to be done only once after we have valid phone object 148 mCi = mCurrentPhone.mCM; 149 mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); 150 // TODO remove this once modem correctly notifies the unsols 151 mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null); 152 mRegisteredWithCi = true; 153 } 154 } 155 } 156 157 private void log(String string) { 158 Log.d(LOG_TAG, string); 159 } 160} 161