14de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan/* 24de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * Copyright 2017 The Android Open Source Project 34de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * 44de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * Licensed under the Apache License, Version 2.0 (the "License"); 54de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * you may not use this file except in compliance with the License. 64de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * You may obtain a copy of the License at 74de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * 84de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * http://www.apache.org/licenses/LICENSE-2.0 94de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * 104de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * Unless required by applicable law or agreed to in writing, software 114de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * distributed under the License is distributed on an "AS IS" BASIS, 124de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * See the License for the specific language governing permissions and 144de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * limitations under the License. 154de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan */ 164de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 174de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanpackage com.android.internal.telephony.uicc; 184de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 194de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.app.AlertDialog; 204de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.content.ActivityNotFoundException; 214de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.content.ComponentName; 224de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.content.Context; 234de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.content.DialogInterface; 244de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.content.Intent; 254de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.content.res.Resources; 264de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.os.Handler; 274de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.os.Message; 284de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.os.PowerManager; 294de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.telephony.Rlog; 304de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport android.view.WindowManager; 314de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 324de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport com.android.internal.R; 334de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport com.android.internal.telephony.CommandsInterface; 344de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport com.android.internal.telephony.CommandsInterface.RadioState; 3506c1f46c4f7d32f1a9832121f7e4cfe67f6660bcAmit Mahajanimport com.android.internal.telephony.IccCardConstants; 364de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport com.android.internal.telephony.uicc.IccCardStatus.CardState; 372e7e5ab2b4a80d3df4df40157b1cfd5c72e6e4b8Holly Jiuyu Sunimport com.android.internal.telephony.uicc.euicc.EuiccCard; 384de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 394de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport java.io.FileDescriptor; 404de8effafa19167eb55efb666fa275fe419cc615Amit Mahajanimport java.io.PrintWriter; 414de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 424de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan/** 434de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * This class represents a physical slot on the device. 444de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan */ 453caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajanpublic class UiccSlot extends Handler { 464de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private static final String TAG = "UiccSlot"; 474de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private static final boolean DBG = true; 484de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 494de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan public static final String EXTRA_ICC_CARD_ADDED = 504de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan "com.android.internal.telephony.uicc.ICC_CARD_ADDED"; 51184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li public static final int INVALID_PHONE_ID = -1; 524de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 534de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private final Object mLock = new Object(); 544de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private boolean mActive; 5596170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu private boolean mStateIsUnknown = true; 564de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private CardState mCardState; 574de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private Context mContext; 584de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private CommandsInterface mCi; 594de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private UiccCard mUiccCard; 604de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private RadioState mLastRadioState = RadioState.RADIO_UNAVAILABLE; 61ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan private boolean mIsEuicc; 62ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan private String mIccId; 6328dcffcfdf04b4f5fa16f78219278987febc68e3yinxu private AnswerToReset mAtr; 64184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li private int mPhoneId = INVALID_PHONE_ID; 654de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 664de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private static final int EVENT_CARD_REMOVED = 13; 674de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private static final int EVENT_CARD_ADDED = 14; 684de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 693caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan public UiccSlot(Context c, boolean isActive) { 704de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (DBG) log("Creating"); 713caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan mContext = c; 724de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan mActive = isActive; 73a3d5188fe326da174471025db03f5a3e4594be20Malcolm Chen mCardState = null; 744de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 754de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 764de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan /** 774de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * Update slot. The main trigger for this is a change in the ICC Card status. 784de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan */ 79ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan public void update(CommandsInterface ci, IccCardStatus ics, int phoneId) { 80de72f77373b6b38cd650133c89f6cf72c55ac06byinxu if (DBG) log("cardStatus update: " + ics.toString()); 814de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan synchronized (mLock) { 824de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan CardState oldState = mCardState; 834de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan mCardState = ics.mCardState; 84de72f77373b6b38cd650133c89f6cf72c55ac06byinxu mIccId = ics.iccid; 8506c1f46c4f7d32f1a9832121f7e4cfe67f6660bcAmit Mahajan mPhoneId = phoneId; 86ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan parseAtr(ics.atr); 874de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan mCi = ci; 884de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 894de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan RadioState radioState = mCi.getRadioState(); 904de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (DBG) { 914de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan log("update: radioState=" + radioState + " mLastRadioState=" + mLastRadioState); 924de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 934de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 94a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen if (absentStateUpdateNeeded(oldState)) { 95a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen updateCardStateAbsent(); 96de72f77373b6b38cd650133c89f6cf72c55ac06byinxu // Because mUiccCard may be updated in both IccCardStatus and IccSlotStatus, we need to 97de72f77373b6b38cd650133c89f6cf72c55ac06byinxu // create a new UiccCard instance in two scenarios: 98de72f77373b6b38cd650133c89f6cf72c55ac06byinxu // 1. mCardState is changing from ABSENT to non ABSENT. 99de72f77373b6b38cd650133c89f6cf72c55ac06byinxu // 2. The latest mCardState is not ABSENT, but there is no UiccCard instance. 100de72f77373b6b38cd650133c89f6cf72c55ac06byinxu } else if ((oldState == null || oldState == CardState.CARDSTATE_ABSENT 101de72f77373b6b38cd650133c89f6cf72c55ac06byinxu || mUiccCard == null) && mCardState != CardState.CARDSTATE_ABSENT) { 1024de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // No notifications while radio is off or we just powering up 1034de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) { 1044de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (DBG) log("update: notify card added"); 1053caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan sendMessage(obtainMessage(EVENT_CARD_ADDED, null)); 1064de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 1074de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 1084de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // card is present in the slot now; create new mUiccCard 1094de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (mUiccCard != null) { 1104de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan loge("update: mUiccCard != null when card was present; disposing it now"); 1114de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan mUiccCard.dispose(); 1124de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 1134de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 114ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan if (!mIsEuicc) { 11598a7a2b7cd8e0c4ea787e434ed9c6c6d5ddf8d5fAmit Mahajan mUiccCard = new UiccCard(mContext, mCi, ics, mPhoneId, mLock); 116ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } else { 11798a7a2b7cd8e0c4ea787e434ed9c6c6d5ddf8d5fAmit Mahajan mUiccCard = new EuiccCard(mContext, mCi, ics, phoneId, mLock); 118ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 1193caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } else { 1203caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan if (mUiccCard != null) { 1213caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan mUiccCard.update(mContext, mCi, ics); 1223caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } 1234de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 1244de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan mLastRadioState = radioState; 1254de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 1264de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 1274de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 128ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan /** 129ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan * Update slot based on IccSlotStatus. 130ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan */ 131ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan public void update(CommandsInterface ci, IccSlotStatus iss) { 132de72f77373b6b38cd650133c89f6cf72c55ac06byinxu if (DBG) log("slotStatus update: " + iss.toString()); 133ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan synchronized (mLock) { 134a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen CardState oldState = mCardState; 135ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan mCi = ci; 136909b9acc801116e577b3856d153a8a65b691409ayinxu parseAtr(iss.atr); 137909b9acc801116e577b3856d153a8a65b691409ayinxu mCardState = iss.cardState; 138909b9acc801116e577b3856d153a8a65b691409ayinxu mIccId = iss.iccid; 139ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan if (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_INACTIVE) { 140a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen // TODO: (b/79432584) evaluate whether should broadcast card state change 141a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen // even if it's inactive. 142ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan if (mActive) { 143ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan mActive = false; 14428eb337c9a4d6a9b7b032ff35e0b348ea514bdb7Amit Mahajan mLastRadioState = RadioState.RADIO_UNAVAILABLE; 145184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li mPhoneId = INVALID_PHONE_ID; 14628eb337c9a4d6a9b7b032ff35e0b348ea514bdb7Amit Mahajan if (mUiccCard != null) mUiccCard.dispose(); 14796170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu nullifyUiccCard(true /* sim state is unknown */); 148ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 149a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen } else { 150ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan mActive = true; 151a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen mPhoneId = iss.logicalSlotIndex; 152a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen if (absentStateUpdateNeeded(oldState)) { 153a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen updateCardStateAbsent(); 154a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen } 155a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen // TODO: (b/79432584) Create UiccCard or EuiccCard object here. 156a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen // Right now It's OK not creating it because Card status update will do it. 157a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen // But we should really make them symmetric. 158ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 159ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 160ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 161ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan 162a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen private boolean absentStateUpdateNeeded(CardState oldState) { 163a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen return (oldState != CardState.CARDSTATE_ABSENT || mUiccCard != null) 164a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen && mCardState == CardState.CARDSTATE_ABSENT; 165a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen } 166a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen 167a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen private void updateCardStateAbsent() { 168a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen RadioState radioState = 169a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen (mCi == null) ? RadioState.RADIO_UNAVAILABLE : mCi.getRadioState(); 170a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen // No notifications while radio is off or we just powering up 171a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) { 172a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen if (DBG) log("update: notify card removed"); 173a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen sendMessage(obtainMessage(EVENT_CARD_REMOVED, null)); 174a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen } 175a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen 176a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen UiccController.updateInternalIccState( 177a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, mPhoneId); 178a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen 179a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen // no card present in the slot now; dispose card and make mUiccCard null 180a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen if (mUiccCard != null) { 181a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen mUiccCard.dispose(); 182a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen } 183a12e3dabbddce9fb8669dfb06627b38f01c5efd4Malcolm Chen nullifyUiccCard(false /* sim state is not unknown */); 184a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen mLastRadioState = radioState; 185a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen } 186a1d802eb4b862a9a796a36072e9b2c805360d834Malcolm Chen 18796170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu // whenever we set mUiccCard to null, we lose the ability to differentiate between absent and 18896170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu // unknown states. To mitigate this, we will us mStateIsUnknown to keep track. The sim is only 18996170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu // unknown if we haven't heard from the radio or if the radio has become unavailable. 19096170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu private void nullifyUiccCard(boolean stateUnknown) { 19196170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu mStateIsUnknown = stateUnknown; 19296170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu mUiccCard = null; 19396170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu } 19496170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu 19596170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu public boolean isStateUnknown() { 196a12e3dabbddce9fb8669dfb06627b38f01c5efd4Malcolm Chen return (mCardState == null || mCardState == CardState.CARDSTATE_ABSENT) && mStateIsUnknown; 19796170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu } 19896170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu 19928dcffcfdf04b4f5fa16f78219278987febc68e3yinxu private void checkIsEuiccSupported() { 20028dcffcfdf04b4f5fa16f78219278987febc68e3yinxu if (mAtr != null && mAtr.isEuiccSupported()) { 20128dcffcfdf04b4f5fa16f78219278987febc68e3yinxu mIsEuicc = true; 20228dcffcfdf04b4f5fa16f78219278987febc68e3yinxu } else { 20328dcffcfdf04b4f5fa16f78219278987febc68e3yinxu mIsEuicc = false; 20428dcffcfdf04b4f5fa16f78219278987febc68e3yinxu } 20528dcffcfdf04b4f5fa16f78219278987febc68e3yinxu } 20628dcffcfdf04b4f5fa16f78219278987febc68e3yinxu 207ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan private void parseAtr(String atr) { 20828dcffcfdf04b4f5fa16f78219278987febc68e3yinxu mAtr = AnswerToReset.parseAtr(atr); 20928dcffcfdf04b4f5fa16f78219278987febc68e3yinxu if (mAtr == null) { 21028dcffcfdf04b4f5fa16f78219278987febc68e3yinxu return; 21128dcffcfdf04b4f5fa16f78219278987febc68e3yinxu } 21228dcffcfdf04b4f5fa16f78219278987febc68e3yinxu checkIsEuiccSupported(); 213ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 214ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan 215ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan public boolean isEuicc() { 216ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan return mIsEuicc; 217ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 218ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan 219ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan public boolean isActive() { 220ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan return mActive; 221ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 222ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan 223184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li public int getPhoneId() { 224184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li return mPhoneId; 225184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li } 226184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li 227ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan public String getIccId() { 2281acc4c72ae6e1b7c38e36b96f65330c52b7fd58eAmit Mahajan if (mIccId != null) { 2291acc4c72ae6e1b7c38e36b96f65330c52b7fd58eAmit Mahajan return mIccId; 2301acc4c72ae6e1b7c38e36b96f65330c52b7fd58eAmit Mahajan } else if (mUiccCard != null) { 2311acc4c72ae6e1b7c38e36b96f65330c52b7fd58eAmit Mahajan return mUiccCard.getIccId(); 2321acc4c72ae6e1b7c38e36b96f65330c52b7fd58eAmit Mahajan } else { 2331acc4c72ae6e1b7c38e36b96f65330c52b7fd58eAmit Mahajan return null; 2341acc4c72ae6e1b7c38e36b96f65330c52b7fd58eAmit Mahajan } 235ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan } 236ce32bfe78ca1e8e30f30c04457ce8c700086f769Amit Mahajan 237258ed5bd03c1c2c59749bbaaa59c173f3eec0fb9Qingxi Li public boolean isExtendedApduSupported() { 238258ed5bd03c1c2c59749bbaaa59c173f3eec0fb9Qingxi Li return (mAtr != null && mAtr.isExtendedApduSupported()); 239258ed5bd03c1c2c59749bbaaa59c173f3eec0fb9Qingxi Li } 240258ed5bd03c1c2c59749bbaaa59c173f3eec0fb9Qingxi Li 2414de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan @Override 2424de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan protected void finalize() { 2434de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (DBG) log("UiccSlot finalized"); 2444de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2454de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2464de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private void onIccSwap(boolean isAdded) { 2474de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2484de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan boolean isHotSwapSupported = mContext.getResources().getBoolean( 2494de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan R.bool.config_hotswapCapable); 2504de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2514de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (isHotSwapSupported) { 2524de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan log("onIccSwap: isHotSwapSupported is true, don't prompt for rebooting"); 2534de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan return; 2544de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2554de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan log("onIccSwap: isHotSwapSupported is false, prompt for rebooting"); 2564de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2574de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan promptForRestart(isAdded); 2584de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2594de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2604de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private void promptForRestart(boolean isAdded) { 2614de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan synchronized (mLock) { 2624de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan final Resources res = mContext.getResources(); 2634de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan final String dialogComponent = res.getString( 2644de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan R.string.config_iccHotswapPromptForRestartDialogComponent); 2654de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (dialogComponent != null) { 2664de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan Intent intent = new Intent().setComponent(ComponentName.unflattenFromString( 2674de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan dialogComponent)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 2684de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan .putExtra(EXTRA_ICC_CARD_ADDED, isAdded); 2694de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan try { 2704de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan mContext.startActivity(intent); 2714de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan return; 2724de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } catch (ActivityNotFoundException e) { 2734de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan loge("Unable to find ICC hotswap prompt for restart activity: " + e); 2744de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2754de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2764de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2774de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // TODO: Here we assume the device can't handle SIM hot-swap 2784de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // and has to reboot. We may want to add a property, 2794de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support 2804de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // hot-swap. 2814de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan DialogInterface.OnClickListener listener = null; 2824de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2834de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 2844de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // TODO: SimRecords is not reset while SIM ABSENT (only reset while 2854de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // Radio_off_or_not_available). Have to reset in both both 2864de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan // added or removed situation. 2874de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan listener = new DialogInterface.OnClickListener() { 2884de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan @Override 2894de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan public void onClick(DialogInterface dialog, int which) { 2904de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan synchronized (mLock) { 2914de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (which == DialogInterface.BUTTON_POSITIVE) { 2924de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan if (DBG) log("Reboot due to SIM swap"); 2934de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan PowerManager pm = (PowerManager) mContext 2944de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan .getSystemService(Context.POWER_SERVICE); 2954de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pm.reboot("SIM is added."); 2964de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2974de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2984de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 2994de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3004de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan }; 3014de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3024de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan Resources r = Resources.getSystem(); 3034de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3044de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan String title = (isAdded) ? r.getString(R.string.sim_added_title) : 3054de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan r.getString(R.string.sim_removed_title); 3064de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan String message = (isAdded) ? r.getString(R.string.sim_added_message) : 3074de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan r.getString(R.string.sim_removed_message); 3084de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan String buttonTxt = r.getString(R.string.sim_restart_button); 3094de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3104de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan AlertDialog dialog = new AlertDialog.Builder(mContext) 3114de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan .setTitle(title) 3124de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan .setMessage(message) 3134de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan .setPositiveButton(buttonTxt, listener) 3144de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan .create(); 3154de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); 3164de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan dialog.show(); 3174de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 3184de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 3194de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3203caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan @Override 3213caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan public void handleMessage(Message msg) { 3223caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan switch (msg.what) { 3233caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan case EVENT_CARD_REMOVED: 3243caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan onIccSwap(false); 3253caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan break; 3263caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan case EVENT_CARD_ADDED: 3273caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan onIccSwap(true); 3283caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan break; 3293caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan default: 3303caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan loge("Unknown Event " + msg.what); 3314de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 3323caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } 3334de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3344de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan /** 3354de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * Returns the state of the UiccCard in the slot. 3364de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * @return 3374de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan */ 3384de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan public CardState getCardState() { 3394de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan synchronized (mLock) { 340a3d5188fe326da174471025db03f5a3e4594be20Malcolm Chen if (mCardState == null) { 341a3d5188fe326da174471025db03f5a3e4594be20Malcolm Chen return CardState.CARDSTATE_ABSENT; 342a3d5188fe326da174471025db03f5a3e4594be20Malcolm Chen } else { 343a3d5188fe326da174471025db03f5a3e4594be20Malcolm Chen return mCardState; 344a3d5188fe326da174471025db03f5a3e4594be20Malcolm Chen } 3454de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 3464de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 3474de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3483caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan /** 3493caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan * Returns the UiccCard in the slot. 3503caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan */ 3513caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan public UiccCard getUiccCard() { 3523caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan synchronized (mLock) { 3533caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan return mUiccCard; 3543caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } 3553caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } 3563caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan 3573caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan /** 3583caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan * Processes radio state unavailable event 3593caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan */ 3603caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan public void onRadioStateUnavailable() { 3613caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan if (mUiccCard != null) { 3623caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan mUiccCard.dispose(); 3633caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } 36496170b8afa17db4832f5f0e7fab0f64dc2428a64Jordan Liu nullifyUiccCard(true /* sim state is unknown */); 3654a7b0a1de1c07c26eefda1fe5d2609cd54c2ecbdAmit Mahajan 366184357ae34f91869f31c259af5b53a852c03f8a6Qingxi Li if (mPhoneId != INVALID_PHONE_ID) { 3672a63f28dd26512f45b706ddab00c18c4f91bc7e4Malcolm Chen UiccController.updateInternalIccState( 36806c1f46c4f7d32f1a9832121f7e4cfe67f6660bcAmit Mahajan IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null, mPhoneId); 36906c1f46c4f7d32f1a9832121f7e4cfe67f6660bcAmit Mahajan } 3704a7b0a1de1c07c26eefda1fe5d2609cd54c2ecbdAmit Mahajan 3713caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan mCardState = CardState.CARDSTATE_ABSENT; 3723caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan mLastRadioState = RadioState.RADIO_UNAVAILABLE; 3733caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } 3743caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan 3754de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private void log(String msg) { 3764de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan Rlog.d(TAG, msg); 3774de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 3784de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3794de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan private void loge(String msg) { 3804de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan Rlog.e(TAG, msg); 3814de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 3824de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan 3834de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan /** 3844de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan * Dump 3854de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan */ 3864de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3874de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.println("UiccSlot:"); 3884de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.println(" mCi=" + mCi); 3894de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.println(" mActive=" + mActive); 3904de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.println(" mLastRadioState=" + mLastRadioState); 3914de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.println(" mCardState=" + mCardState); 3923caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan if (mUiccCard != null) { 3933caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan pw.println(" mUiccCard=" + mUiccCard); 3943caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan mUiccCard.dump(fd, pw, args); 3953caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } else { 3963caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan pw.println(" mUiccCard=null"); 3973caa000d2f0643c50bf74d85a3e6672e484e25e1Amit Mahajan } 3984de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.println(); 3994de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.flush(); 4004de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan pw.flush(); 4014de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan } 4024de8effafa19167eb55efb666fa275fe419cc615Amit Mahajan} 403