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 104c556e9a3149b6cbd4517fe02aae11689ec5a4e03Polina Bondarenko private UiccStateChangedLauncher mLauncher; 105c556e9a3149b6cbd4517fe02aae11689ec5a4e03Polina Bondarenko 1064cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal // Logging for dumpsys. Useful in cases when the cards run into errors. 1074cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal private static final int MAX_PROACTIVE_COMMANDS_TO_LOG = 20; 1084cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal private LinkedList<String> mCardLogs = new LinkedList<String>(); 1094cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal 110a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville public static UiccController make(Context c, CommandsInterface[] ci) { 111a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 112a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (mInstance != null) { 113a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville throw new RuntimeException("MSimUiccController.make() should only be called once"); 114a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 115a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mInstance = new UiccController(c, ci); 116a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return (UiccController)mInstance; 117a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 118a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 119a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 120a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private UiccController(Context c, CommandsInterface []ci) { 121a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (DBG) log("Creating UiccController"); 122a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mContext = c; 123a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mCis = ci; 124a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville for (int i = 0; i < mCis.length; i++) { 125a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Integer index = new Integer(i); 126a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index); 127a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // TODO remove this once modem correctly notifies the unsols 1287695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // If the device has been decrypted or FBE is supported, read SIM when radio state is 1297695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // available. 1307695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // Else wait for radio to be on. This is needed for the scenario when SIM is locked -- 1317695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan // to avoid overlap of CryptKeeper and SIM unlock screen. 1327695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan if (DECRYPT_STATE.equals(SystemProperties.get("vold.decrypt")) || 1337695051bf2bb6562ad6a9b5fa7616cd1002f245aAmit Mahajan StorageManager.isFileEncryptedNativeOrEmulated()) { 134390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index); 135390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan } else { 136390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan mCis[i].registerForOn(this, EVENT_ICC_STATUS_CHANGED, index); 137390c357ab9e1300f03d7477bf9d86bf67a3c8413Amit Mahajan } 1385d8e4457b03d166aa249989916b66a85df898516Steven Liu mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index); 13962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index); 140a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 141c556e9a3149b6cbd4517fe02aae11689ec5a4e03Polina Bondarenko 142c556e9a3149b6cbd4517fe02aae11689ec5a4e03Polina Bondarenko mLauncher = new UiccStateChangedLauncher(c, this); 143a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 144c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 145bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public static UiccController getInstance() { 146e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 147e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka if (mInstance == null) { 148e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka throw new RuntimeException( 149e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka "UiccController.getInstance can't be called before make()"); 150e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 151e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka return mInstance; 152e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 153e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 154e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka 155062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public UiccCard getUiccCard(int phoneId) { 156e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 157062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal if (isValidCardIndex(phoneId)) { 158062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal return mUiccCards[phoneId]; 159e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 160e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka return null; 161e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 162bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 163bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 164a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville public UiccCard[] getUiccCards() { 165a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Return cloned array since we don't want to give out reference 166a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // to internal data structure. 167a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 168a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return mUiccCards.clone(); 169a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 170a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 171a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 172a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Easy to use API 173062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public IccRecords getIccRecords(int phoneId, int family) { 174a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 175062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCardApplication app = getUiccCardApplication(phoneId, family); 176a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (app != null) { 177a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return app.getIccRecords(); 178a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 179a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return null; 180a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 181a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 182a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 183a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Easy to use API 184062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public IccFileHandler getIccFileHandler(int phoneId, int family) { 185a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 186062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCardApplication app = getUiccCardApplication(phoneId, family); 187a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (app != null) { 188a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return app.getIccFileHandler(); 189a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 190a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return null; 191a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 192a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 193a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 194c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 195bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka //Notifies when card status changes 196bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public void registerForIccChanged(Handler h, int what, Object obj) { 197e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 198e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka Registrant r = new Registrant (h, what, obj); 199e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka mIccChangedRegistrants.add(r); 200e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //Notify registrant right after registering, so that it will get the latest ICC status, 201e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //otherwise which may not happen until there is an actual change in ICC status. 202e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka r.notifyRegistrant(); 203e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 204bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 205e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka 206bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public void unregisterForIccChanged(Handler h) { 207e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 208e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka mIccChangedRegistrants.remove(h); 209e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 210bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 211bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 212bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka @Override 213bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka public void handleMessage (Message msg) { 214e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka synchronized (mLock) { 215a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Integer index = getCiIndex(msg); 216a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 217a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (index < 0 || index >= mCis.length) { 218a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Rlog.e(LOG_TAG, "Invalid index : " + index + " received with event " + msg.what); 219a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return; 220a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 221a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 22262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal AsyncResult ar = (AsyncResult)msg.obj; 223e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka switch (msg.what) { 224e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka case EVENT_ICC_STATUS_CHANGED: 225e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); 226a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); 227e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka break; 228e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka case EVENT_GET_ICC_STATUS_DONE: 229e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); 230a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville onGetIccCardStatusDone(ar, index); 231e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka break; 2325d8e4457b03d166aa249989916b66a85df898516Steven Liu case EVENT_RADIO_UNAVAILABLE: 2335d8e4457b03d166aa249989916b66a85df898516Steven Liu if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card"); 2345d8e4457b03d166aa249989916b66a85df898516Steven Liu if (mUiccCards[index] != null) { 2355d8e4457b03d166aa249989916b66a85df898516Steven Liu mUiccCards[index].dispose(); 2365d8e4457b03d166aa249989916b66a85df898516Steven Liu } 2375d8e4457b03d166aa249989916b66a85df898516Steven Liu mUiccCards[index] = null; 2385d8e4457b03d166aa249989916b66a85df898516Steven Liu mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 2395d8e4457b03d166aa249989916b66a85df898516Steven Liu break; 24062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal case EVENT_SIM_REFRESH: 24162648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (DBG) log("Received EVENT_SIM_REFRESH"); 24262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal onSimRefresh(ar, index); 24362648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal break; 244e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka default: 245ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, " Unknown Event " + msg.what); 246e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } 247bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 248bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 249bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 250a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private Integer getCiIndex(Message msg) { 251a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville AsyncResult ar; 252a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Integer index = new Integer(PhoneConstants.DEFAULT_CARD_INDEX); 253a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 254a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville /* 255a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * The events can be come in two ways. By explicitly sending it using 256a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * sendMessage, in this case the user object passed is msg.obj and from 257a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville * the CommandsInterface, in this case the user object is msg.obj.userObj 258a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville */ 259a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (msg != null) { 260a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (msg.obj != null && msg.obj instanceof Integer) { 261a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville index = (Integer)msg.obj; 262a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } else if(msg.obj != null && msg.obj instanceof AsyncResult) { 263a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville ar = (AsyncResult)msg.obj; 264a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (ar.userObj != null && ar.userObj instanceof Integer) { 265a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville index = (Integer)ar.userObj; 266a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 267a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 268a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 269a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return index; 270a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 271a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 272a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville // Easy to use API 273062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal public UiccCardApplication getUiccCardApplication(int phoneId, int family) { 274a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville synchronized (mLock) { 275062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal if (isValidCardIndex(phoneId)) { 276062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal UiccCard c = mUiccCards[phoneId]; 277a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (c != null) { 278062a2a3838c8d8adf16f4d9fbde8d52450da0336Shishir Agrawal return mUiccCards[phoneId].getApplication(family); 279a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 280a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 281a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return null; 282a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 283a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 284a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 285a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) { 286bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka if (ar.exception != null) { 287ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG,"Error getting ICC status. " 288bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka + "RIL_REQUEST_GET_ICC_STATUS should " 289bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka + "never return an error", ar.exception); 290bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka return; 291c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 292a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (!isValidCardIndex(index)) { 293a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville Rlog.e(LOG_TAG,"onGetIccCardStatusDone: invalid index : " + index); 294a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return; 295a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 296c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville 297bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka IccCardStatus status = (IccCardStatus)ar.result; 298bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 299a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville if (mUiccCards[index] == null) { 300e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //Create new card 301a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mUiccCards[index] = new UiccCard(mContext, mCis[index], status, index); 302e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka } else { 303e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka //Update already existing card 304a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mUiccCards[index].update(mContext, mCis[index] , status); 305bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 306bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 307bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka if (DBG) log("Notifying IccChangedRegistrants"); 308a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 309a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 310a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville } 311a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 31262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal private void onSimRefresh(AsyncResult ar, Integer index) { 31362648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (ar.exception != null) { 31462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.e(LOG_TAG, "Sim REFRESH with exception: " + ar.exception); 31562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal return; 31662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 31762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 31862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (!isValidCardIndex(index)) { 31962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.e(LOG_TAG,"onSimRefresh: invalid index : " + index); 32062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal return; 32162648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 32262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 32362648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal IccRefreshResponse resp = (IccRefreshResponse) ar.result; 32462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.d(LOG_TAG, "onSimRefresh: " + resp); 32562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 32662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (mUiccCards[index] == null) { 32762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal Rlog.e(LOG_TAG,"onSimRefresh: refresh on null card : " + index); 32862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal return; 32962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 33062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 331626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal if (resp.refreshResult != IccRefreshResponse.REFRESH_RESULT_RESET) { 332626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal Rlog.d(LOG_TAG, "Ignoring non reset refresh: " + resp); 333626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal return; 33462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 33562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 336626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal Rlog.d(LOG_TAG, "Handling refresh reset: " + resp); 337626e120359bef26ef72c710c0d2d1c7b7d76722bShishir Agrawal 33862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal boolean changed = mUiccCards[index].resetAppWithAid(resp.aid); 33962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (changed) { 34062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal boolean requirePowerOffOnSimRefreshReset = mContext.getResources().getBoolean( 34162648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal com.android.internal.R.bool.config_requireRadioPowerOffOnSimRefreshReset); 34262648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal if (requirePowerOffOnSimRefreshReset) { 34362648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mCis[index].setRadioPower(false, null); 34462648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } else { 34562648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); 34662648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 34762648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 34862648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 34962648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal } 35062648296ee1514d871d7d779d6f33da5e55babcaShishir Agrawal 351a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville private boolean isValidCardIndex(int index) { 352a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville return (index >= 0 && index < mUiccCards.length); 353bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka } 354bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka 355c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville private void log(String string) { 356ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.d(LOG_TAG, string); 357c38bb60d867c5d61d90b7179a9ed2b2d1848124fWink Saville } 35805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka 3594cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal // TODO: This is hacky. We need a better way of saving the logs. 3604cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal public void addCardLog(String data) { 3614cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal Time t = new Time(); 3624cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal t.setToNow(); 3634cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal mCardLogs.addLast(t.format("%m-%d %H:%M:%S") + " " + data); 3644cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal if (mCardLogs.size() > MAX_PROACTIVE_COMMANDS_TO_LOG) { 3654cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal mCardLogs.removeFirst(); 3664cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal } 3674cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal } 368a8467dd0c524787104b1ccdddc5e8af10ba729edWink Saville 36905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 37005ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println("UiccController: " + this); 37105ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mContext=" + mContext); 37205ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mInstance=" + mInstance); 37305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mIccChangedRegistrants: size=" + mIccChangedRegistrants.size()); 37405ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka for (int i = 0; i < mIccChangedRegistrants.size(); i++) { 37505ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(" mIccChangedRegistrants[" + i + "]=" 37605ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka + ((Registrant)mIccChangedRegistrants.get(i)).getHandler()); 37705ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka } 37805ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.println(); 37905ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka pw.flush(); 38038aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal pw.println(" mUiccCards: size=" + mUiccCards.length); 38138aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal for (int i = 0; i < mUiccCards.length; i++) { 38238aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal if (mUiccCards[i] == null) { 38338aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal pw.println(" mUiccCards[" + i + "]=null"); 38438aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal } else { 38538aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal pw.println(" mUiccCards[" + i + "]=" + mUiccCards[i]); 38638aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal mUiccCards[i].dump(fd, pw, args); 38738aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal } 38838aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal } 3894cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal pw.println("mCardLogs: "); 3904cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal for (int i = 0; i < mCardLogs.size(); ++i) { 3914cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal pw.println(" " + mCardLogs.get(i)); 3924cdf0a453fa3df6015032ec5cbb8d3253b6f81daShishir Agrawal } 39305ef3b65972826780859b9acbd1fa9580d099832Alex Yakavenka } 394bb36adde615d3d85fa0fc23935197c6bc6a799edAlex Yakavenka} 395