1c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville/* 2e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Copyright (C) 2011-2012 The Android Open Source Project 3c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 4c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 5c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * you may not use this file except in compliance with the License. 6c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * You may obtain a copy of the License at 7c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 8c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * http://www.apache.org/licenses/LICENSE-2.0 9c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * 10c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * Unless required by applicable law or agreed to in writing, software 11c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * distributed under the License is distributed on an "AS IS" BASIS, 12c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * See the License for the specific language governing permissions and 14c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * limitations under the License. 15c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 16c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 17c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Savillepackage com.android.internal.telephony.uicc; 18c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 19e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport android.content.Context; 20bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.AsyncResult; 21bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Handler; 22bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Message; 23bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.Registrant; 24bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkaimport android.os.RegistrantList; 25390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajanimport android.os.SystemProperties; 267695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajanimport android.os.storage.StorageManager; 27a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport android.telephony.TelephonyManager; 28ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog; 294cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawalimport android.text.format.Time; 30c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 31e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenkaimport com.android.internal.telephony.CommandsInterface; 32a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.PhoneConstants; 33a8467dd0c524787104b1ccdddc5e8af10ba729edWink Savilleimport com.android.internal.telephony.SubscriptionController; 34e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka 3505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.FileDescriptor; 3605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenkaimport java.io.PrintWriter; 374cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawalimport java.util.LinkedList; 3805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka 39e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka/** 40e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * This class is responsible for keeping all knowledge about 41e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Universal Integrated Circuit Card (UICC), also know as SIM's, 42e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * in the system. It is also used as API to get appropriate 43c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville * applications to pass them to phone and service trackers. 44e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * 45e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * UiccController is created with the call to make() function. 46e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * UiccController is a singleton and make() must only be called once 47e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * and throws an exception if called multiple times. 48e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * 49e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed" 50e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * notifications. When such notification arrives UiccController will call 51e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS 52e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * request appropriate tree of uicc objects will be created. 53e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * 54e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Following is class diagram for uicc classes: 55e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * 56e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * UiccController 57e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * # 58e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * | 59e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * UiccCard 60e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * # # 61e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * | ------------------ 62e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * UiccCardApplication CatService 63e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * # # 64e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * | | 65e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * IccRecords IccFileHandler 66e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * ^ ^ ^ ^ ^ ^ ^ ^ 67e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * SIMRecords---- | | | | | | ---SIMFileHandler 68e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * RuimRecords----- | | | | ----RuimFileHandler 69e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * IsimUiccRecords--- | | -----UsimFileHandler 70e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * | ------CsimFileHandler 71e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * ----IsimFileHandler 72e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * 73e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * Legend: # stands for Composition 74e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * ^ stands for Generalization 75e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * 76e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka * See also {@link com.android.internal.telephony.IccCard} 77cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville * and {@link com.android.internal.telephony.uicc.IccCardProxy} 78c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville */ 79bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenkapublic class UiccController extends Handler { 80c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static final boolean DBG = true; 81cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville private static final String LOG_TAG = "UiccController"; 82c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 83e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka public static final int APP_FAM_3GPP = 1; 84e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka public static final int APP_FAM_3GPP2 = 2; 85e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka public static final int APP_FAM_IMS = 3; 86e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka 87bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka private static final int EVENT_ICC_STATUS_CHANGED = 1; 88bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka private static final int EVENT_GET_ICC_STATUS_DONE = 2; 895d8e4457b03d166aa249989916b66a85df898516Steven Liu private static final int EVENT_RADIO_UNAVAILABLE = 3; 9062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal private static final int EVENT_SIM_REFRESH = 4; 91bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 92390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan private static final String DECRYPT_STATE = "trigger_restart_framework"; 93390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan 94a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private CommandsInterface[] mCis; 95a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private UiccCard[] mUiccCards = new UiccCard[TelephonyManager.getDefault().getPhoneCount()]; 96a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 97e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka private static final Object mLock = new Object(); 98c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private static UiccController mInstance; 99c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 100e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka private Context mContext; 101bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 102a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville protected RegistrantList mIccChangedRegistrants = new RegistrantList(); 103c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 1044cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal // Logging for dumpsys. Useful in cases when the cards run into errors. 1054cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal private static final int MAX_PROACTIVE_COMMANDS_TO_LOG = 20; 1064cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal private LinkedList<String> mCardLogs = new LinkedList<String>(); 1074cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal 108a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville public static UiccController make(Context c, CommandsInterface[] ci) { 109a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (mInstance != null) { 111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville throw new RuntimeException("MSimUiccController.make() should only be called once"); 112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mInstance = new UiccController(c, ci); 114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return (UiccController)mInstance; 115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private UiccController(Context c, CommandsInterface []ci) { 119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (DBG) log("Creating UiccController"); 120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mContext = c; 121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mCis = ci; 122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville for (int i = 0; i < mCis.length; i++) { 123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Integer index = new Integer(i); 124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index); 125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // TODO remove this once modem correctly notifies the unsols 1267695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // If the device has been decrypted or FBE is supported, read SIM when radio state is 1277695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // available. 1287695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // Else wait for radio to be on. This is needed for the scenario when SIM is locked -- 1297695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // to avoid overlap of CryptKeeper and SIM unlock screen. 1307695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan if (DECRYPT_STATE.equals(SystemProperties.get("vold.decrypt")) || 1317695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan StorageManager.isFileEncryptedNativeOrEmulated()) { 132390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index); 133390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan } else { 134390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan mCis[i].registerForOn(this, EVENT_ICC_STATUS_CHANGED, index); 135390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan } 1365d8e4457b03d166aa249989916b66a85df898516Steven Liu mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index); 13762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index); 138a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 139a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 140c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 141bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public static UiccController getInstance() { 142e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 143e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka if (mInstance == null) { 144e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka throw new RuntimeException( 145e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka "UiccController.getInstance can't be called before make()"); 146e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 147e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka return mInstance; 148e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 149e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 150e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka 151062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public UiccCard getUiccCard(int phoneId) { 152e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 153062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal if (isValidCardIndex(phoneId)) { 154062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal return mUiccCards[phoneId]; 155e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 156e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka return null; 157e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 158bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 159bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 160a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville public UiccCard[] getUiccCards() { 161a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Return cloned array since we don't want to give out reference 162a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // to internal data structure. 163a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return mUiccCards.clone(); 165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Easy to use API 169062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public IccRecords getIccRecords(int phoneId, int family) { 170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 171062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCardApplication app = getUiccCardApplication(phoneId, family); 172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (app != null) { 173a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return app.getIccRecords(); 174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 175a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return null; 176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Easy to use API 180062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public IccFileHandler getIccFileHandler(int phoneId, int family) { 181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 182062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCardApplication app = getUiccCardApplication(phoneId, family); 183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (app != null) { 184a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return app.getIccFileHandler(); 185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 186a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return null; 187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 190c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 191bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka //Notifies when card status changes 192bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public void registerForIccChanged(Handler h, int what, Object obj) { 193e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 194e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka Registrant r = new Registrant (h, what, obj); 195e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka mIccChangedRegistrants.add(r); 196e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //Notify registrant right after registering, so that it will get the latest ICC status, 197e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //otherwise which may not happen until there is an actual change in ICC status. 198e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka r.notifyRegistrant(); 199e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 200bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 201e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka 202bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public void unregisterForIccChanged(Handler h) { 203e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 204e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka mIccChangedRegistrants.remove(h); 205e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 206bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 207bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 208bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka @Override 209bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public void handleMessage (Message msg) { 210e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 211a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Integer index = getCiIndex(msg); 212a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 213a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (index < 0 || index >= mCis.length) { 214a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Rlog.e(LOG_TAG, "Invalid index : " + index + " received with event " + msg.what); 215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return; 216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 21862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal AsyncResult ar = (AsyncResult)msg.obj; 219e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka switch (msg.what) { 220e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka case EVENT_ICC_STATUS_CHANGED: 221e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); 222a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); 223e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka break; 224e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka case EVENT_GET_ICC_STATUS_DONE: 225e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); 226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville onGetIccCardStatusDone(ar, index); 227e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka break; 2285d8e4457b03d166aa249989916b66a85df898516Steven Liu case EVENT_RADIO_UNAVAILABLE: 2295d8e4457b03d166aa249989916b66a85df898516Steven Liu if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card"); 2305d8e4457b03d166aa249989916b66a85df898516Steven Liu if (mUiccCards[index] != null) { 2315d8e4457b03d166aa249989916b66a85df898516Steven Liu mUiccCards[index].dispose(); 2325d8e4457b03d166aa249989916b66a85df898516Steven Liu } 2335d8e4457b03d166aa249989916b66a85df898516Steven Liu mUiccCards[index] = null; 2345d8e4457b03d166aa249989916b66a85df898516Steven Liu mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 2355d8e4457b03d166aa249989916b66a85df898516Steven Liu break; 23662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal case EVENT_SIM_REFRESH: 23762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (DBG) log("Received EVENT_SIM_REFRESH"); 23862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal onSimRefresh(ar, index); 23962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal break; 240e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka default: 241ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, " Unknown Event " + msg.what); 242e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 243bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 244bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 245bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 246a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private Integer getCiIndex(Message msg) { 247a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville AsyncResult ar; 248a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Integer index = new Integer(PhoneConstants.DEFAULT_CARD_INDEX); 249a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville /* 251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * The events can be come in two ways. By explicitly sending it using 252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * sendMessage, in this case the user object passed is msg.obj and from 253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * the CommandsInterface, in this case the user object is msg.obj.userObj 254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */ 255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (msg != null) { 256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (msg.obj != null && msg.obj instanceof Integer) { 257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville index = (Integer)msg.obj; 258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } else if(msg.obj != null && msg.obj instanceof AsyncResult) { 259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville ar = (AsyncResult)msg.obj; 260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (ar.userObj != null && ar.userObj instanceof Integer) { 261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville index = (Integer)ar.userObj; 262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return index; 266a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 268a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Easy to use API 269062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public UiccCardApplication getUiccCardApplication(int phoneId, int family) { 270a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 271062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal if (isValidCardIndex(phoneId)) { 272062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCard c = mUiccCards[phoneId]; 273a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (c != null) { 274062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal return mUiccCards[phoneId].getApplication(family); 275a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 276a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return null; 278a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) { 282bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka if (ar.exception != null) { 283ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG,"Error getting ICC status. " 284bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka + "RIL_REQUEST_GET_ICC_STATUS should " 285bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka + "never return an error", ar.exception); 286bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka return; 287c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 288a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (!isValidCardIndex(index)) { 289a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Rlog.e(LOG_TAG,"onGetIccCardStatusDone: invalid index : " + index); 290a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return; 291a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 292c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 293bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka IccCardStatus status = (IccCardStatus)ar.result; 294bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (mUiccCards[index] == null) { 296e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //Create new card 297a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mUiccCards[index] = new UiccCard(mContext, mCis[index], status, index); 298e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } else { 299e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //Update already existing card 300a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mUiccCards[index].update(mContext, mCis[index] , status); 301bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 302bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 303bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka if (DBG) log("Notifying IccChangedRegistrants"); 304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 305a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 306a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 307a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 30862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal private void onSimRefresh(AsyncResult ar, Integer index) { 30962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (ar.exception != null) { 31062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.e(LOG_TAG, "Sim REFRESH with exception: " + ar.exception); 31162648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal return; 31262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 31362648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 31462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (!isValidCardIndex(index)) { 31562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.e(LOG_TAG,"onSimRefresh: invalid index : " + index); 31662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal return; 31762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 31862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 31962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal IccRefreshResponse resp = (IccRefreshResponse) ar.result; 32062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.d(LOG_TAG, "onSimRefresh: " + resp); 32162648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 32262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (mUiccCards[index] == null) { 32362648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.e(LOG_TAG,"onSimRefresh: refresh on null card : " + index); 32462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal return; 32562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 32662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 327626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal if (resp.refreshResult != IccRefreshResponse.REFRESH_RESULT_RESET) { 328626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal Rlog.d(LOG_TAG, "Ignoring non reset refresh: " + resp); 329626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal return; 33062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 33162648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 332626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal Rlog.d(LOG_TAG, "Handling refresh reset: " + resp); 333626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal 33462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal boolean changed = mUiccCards[index].resetAppWithAid(resp.aid); 33562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (changed) { 33662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal boolean requirePowerOffOnSimRefreshReset = mContext.getResources().getBoolean( 33762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal com.android.internal.R.bool.config_requireRadioPowerOffOnSimRefreshReset); 33862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (requirePowerOffOnSimRefreshReset) { 33962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mCis[index].setRadioPower(false, null); 34062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } else { 34162648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); 34262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 34362648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 34462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 34562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 34662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 347a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private boolean isValidCardIndex(int index) { 348a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return (index >= 0 && index < mUiccCards.length); 349bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 350bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 351c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private void log(String string) { 352ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, string); 353c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 35405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka 3554cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal // TODO: This is hacky. We need a better way of saving the logs. 3564cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal public void addCardLog(String data) { 3574cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal Time t = new Time(); 3584cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal t.setToNow(); 3594cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal mCardLogs.addLast(t.format("%m-%d %H:%M:%S") + " " + data); 3604cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal if (mCardLogs.size() > MAX_PROACTIVE_COMMANDS_TO_LOG) { 3614cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal mCardLogs.removeFirst(); 3624cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal } 3634cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal } 364a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 36505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 36605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println("UiccController: " + this); 36705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mContext=" + mContext); 36805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mInstance=" + mInstance); 36905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mIccChangedRegistrants: size=" + mIccChangedRegistrants.size()); 37005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka for (int i = 0; i < mIccChangedRegistrants.size(); i++) { 37105ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mIccChangedRegistrants[" + i + "]=" 37205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka + ((Registrant)mIccChangedRegistrants.get(i)).getHandler()); 37305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka } 37405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(); 37505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.flush(); 37638aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal pw.println(" mUiccCards: size=" + mUiccCards.length); 37738aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal for (int i = 0; i < mUiccCards.length; i++) { 37838aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal if (mUiccCards[i] == null) { 37938aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal pw.println(" mUiccCards[" + i + "]=null"); 38038aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal } else { 38138aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal pw.println(" mUiccCards[" + i + "]=" + mUiccCards[i]); 38238aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal mUiccCards[i].dump(fd, pw, args); 38338aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal } 38438aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal } 3854cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal pw.println("mCardLogs: "); 3864cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal for (int i = 0; i < mCardLogs.size(); ++i) { 3874cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal pw.println(" " + mCardLogs.get(i)); 3884cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal } 38905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka } 390bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka} 391