diff options
author | Alex Yakavenka <ayakav@codeaurora.org> | 2012-07-26 15:34:10 -0700 |
---|---|---|
committer | Wink Saville <wink@google.com> | 2012-08-08 20:48:20 -0700 |
commit | e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2 (patch) | |
tree | 4eed1415126fb7bb5caf178a3d1c119e09ae13f3 | |
parent | f7c060b9ded0613109c1cec05c537c4e846fecd4 (diff) | |
download | frameworks_opt_telephony-e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2.zip frameworks_opt_telephony-e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2.tar.gz frameworks_opt_telephony-e0e2ebb5a50e580cbe6957dcafb3495a2d0a27f2.tar.bz2 |
Telephony: Dynamically instantiate IccCard
Instantiate when get_sim_status request returns
Change-Id: I9c9333d23f1e0b23256731b245577d1a25721647
21 files changed, 643 insertions, 278 deletions
diff --git a/src/java/com/android/internal/telephony/DataConnectionTracker.java b/src/java/com/android/internal/telephony/DataConnectionTracker.java index ef50b91..fdaf0a3 100644 --- a/src/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/src/java/com/android/internal/telephony/DataConnectionTracker.java @@ -47,6 +47,7 @@ import android.util.Log; import com.android.internal.R; import com.android.internal.telephony.DataConnection.FailCause; import com.android.internal.telephony.DctConstants; +import com.android.internal.telephony.uicc.UiccController; import com.android.internal.util.AsyncChannel; import java.io.FileDescriptor; @@ -57,6 +58,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; /** * {@hide} @@ -166,11 +168,12 @@ public abstract class DataConnectionTracker extends Handler { // member variables protected PhoneBase mPhone; + protected UiccController mUiccController; + protected AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>(); protected DctConstants.Activity mActivity = DctConstants.Activity.NONE; protected DctConstants.State mState = DctConstants.State.IDLE; protected Handler mDataConnectionTracker = null; - protected long mTxPkts; protected long mRxPkts; protected int mNetStatPollPeriod; @@ -419,6 +422,8 @@ public abstract class DataConnectionTracker extends Handler { super(); if (DBG) log("DCT.constructor"); mPhone = phone; + mUiccController = UiccController.getInstance(); + mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null); IntentFilter filter = new IntentFilter(); filter.addAction(getActionIntentReconnectAlarm()); @@ -461,6 +466,7 @@ public abstract class DataConnectionTracker extends Handler { mIsDisposed = true; mPhone.getContext().unregisterReceiver(this.mIntentReceiver); mDataRoamingSettingObserver.unregister(mPhone.getContext()); + mUiccController.unregisterForIccChanged(this); } protected void broadcastMessenger() { @@ -583,6 +589,7 @@ public abstract class DataConnectionTracker extends Handler { protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason); protected abstract void onCleanUpAllConnections(String cause); protected abstract boolean isDataPossible(String apnType); + protected abstract void onUpdateIcc(); protected void onDataStallAlarm(int tag) { loge("onDataStallAlarm: not impleted tag=" + tag); @@ -693,6 +700,10 @@ public abstract class DataConnectionTracker extends Handler { onSetPolicyDataEnabled(enabled); break; } + case DctConstants.EVENT_ICC_CHANGED: + onUpdateIcc(); + break; + default: Log.e("DATA", "Unidentified event msg=" + msg); break; diff --git a/src/java/com/android/internal/telephony/IccCard.java b/src/java/com/android/internal/telephony/IccCard.java index 740292c..b093ef7 100644 --- a/src/java/com/android/internal/telephony/IccCard.java +++ b/src/java/com/android/internal/telephony/IccCard.java @@ -34,10 +34,13 @@ import android.view.WindowManager; import com.android.internal.telephony.PhoneBase; import com.android.internal.telephony.CommandsInterface.RadioState; +import com.android.internal.telephony.gsm.GSMPhone; import com.android.internal.telephony.gsm.SIMFileHandler; import com.android.internal.telephony.gsm.SIMRecords; +import com.android.internal.telephony.sip.SipPhone; import com.android.internal.telephony.cat.CatService; import com.android.internal.telephony.cdma.CDMALTEPhone; +import com.android.internal.telephony.cdma.CDMAPhone; import com.android.internal.telephony.cdma.CdmaLteUiccFileHandler; import com.android.internal.telephony.cdma.CdmaLteUiccRecords; import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; @@ -84,8 +87,6 @@ public class IccCard { protected static final int EVENT_ICC_LOCKED = 1; private static final int EVENT_GET_ICC_STATUS_DONE = 2; protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 3; - private static final int EVENT_PINPUK_DONE = 4; - private static final int EVENT_REPOLL_STATUS_DONE = 5; protected static final int EVENT_ICC_READY = 6; private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 7; private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 8; @@ -122,34 +123,19 @@ public class IccCard { return IccCardConstants.State.UNKNOWN; } - public IccCard(PhoneBase phone, String logTag, Boolean is3gpp, Boolean dbg) { + public IccCard(PhoneBase phone, IccCardStatus ics, String logTag, boolean dbg) { mLogTag = logTag; mDbg = dbg; - if (mDbg) log("[IccCard] Creating card type " + (is3gpp ? "3gpp" : "3gpp2")); - mPhone = phone; - this.is3gpp = is3gpp; + if (mDbg) log("Creating"); + update(phone, ics); mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(), mPhone.mCM, mHandler, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); - if (phone.mCM.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE - && phone instanceof CDMALTEPhone) { - mIccFileHandler = new CdmaLteUiccFileHandler(this, "", mPhone.mCM); - mIccRecords = new CdmaLteUiccRecords(this, mPhone.mContext, mPhone.mCM); - } else { - // Correct aid will be set later (when GET_SIM_STATUS returns) - mIccFileHandler = is3gpp ? new SIMFileHandler(this, "", mPhone.mCM) : - new RuimFileHandler(this, "", mPhone.mCM); - mIccRecords = is3gpp ? new SIMRecords(this, mPhone.mContext, mPhone.mCM) : - new RuimRecords(this, mPhone.mContext, mPhone.mCM); - } - mCatService = CatService.getInstance(mPhone.mCM, mIccRecords, - mPhone.mContext, mIccFileHandler, this); mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); mPhone.mCM.registerForOn(mHandler, EVENT_RADIO_ON, null); - mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_STATUS_CHANGED, null); } public void dispose() { - if (mDbg) log("[IccCard] Disposing card type " + (is3gpp ? "3gpp" : "3gpp2")); + if (mDbg) log("Disposing card type " + (is3gpp ? "3gpp" : "3gpp2")); mPhone.mCM.unregisterForIccStatusChanged(mHandler); mPhone.mCM.unregisterForOffOrNotAvailable(mHandler); mPhone.mCM.unregisterForOn(mHandler); @@ -159,6 +145,42 @@ public class IccCard { mIccFileHandler.dispose(); } + public void update(PhoneBase phone, IccCardStatus ics) { + if (phone != mPhone) { + PhoneBase oldPhone = mPhone; + mPhone = phone; + log("Update"); + if (phone instanceof GSMPhone) { + is3gpp = true; + } else if (phone instanceof CDMALTEPhone){ + is3gpp = true; + } else if (phone instanceof CDMAPhone){ + is3gpp = false; + } else if (phone instanceof SipPhone){ + is3gpp = true; + } else { + throw new RuntimeException("Update: Unhandled phone type. Critical error!" + + phone.getPhoneName()); + } + + + if (phone.mCM.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE + && phone instanceof CDMALTEPhone) { + mIccFileHandler = new CdmaLteUiccFileHandler(this, "", mPhone.mCM); + mIccRecords = new CdmaLteUiccRecords(this, mPhone.mContext, mPhone.mCM); + } else { + // Correct aid will be set later (when GET_SIM_STATUS returns) + mIccFileHandler = is3gpp ? new SIMFileHandler(this, "", mPhone.mCM) : + new RuimFileHandler(this, "", mPhone.mCM); + mIccRecords = is3gpp ? new SIMRecords(this, mPhone.mContext, mPhone.mCM) : + new RuimRecords(this, mPhone.mContext, mPhone.mCM); + } + mCatService = CatService.getInstance(mPhone.mCM, mIccRecords, mPhone.mContext, + mIccFileHandler, this); + } + mHandler.sendMessage(mHandler.obtainMessage(EVENT_GET_ICC_STATUS_DONE, ics)); + } + protected void finalize() { if (mDbg) log("[IccCard] Finalized card type " + (is3gpp ? "3gpp" : "3gpp2")); } @@ -289,27 +311,23 @@ public class IccCard { */ public void supplyPin (String pin, Message onComplete) { - mPhone.mCM.supplyIccPin(pin, mHandler.obtainMessage(EVENT_PINPUK_DONE, onComplete)); + mPhone.mCM.supplyIccPin(pin, onComplete); } public void supplyPuk (String puk, String newPin, Message onComplete) { - mPhone.mCM.supplyIccPuk(puk, newPin, - mHandler.obtainMessage(EVENT_PINPUK_DONE, onComplete)); + mPhone.mCM.supplyIccPuk(puk, newPin, onComplete); } public void supplyPin2 (String pin2, Message onComplete) { - mPhone.mCM.supplyIccPin2(pin2, - mHandler.obtainMessage(EVENT_PINPUK_DONE, onComplete)); + mPhone.mCM.supplyIccPin2(pin2, onComplete); } public void supplyPuk2 (String puk2, String newPin2, Message onComplete) { - mPhone.mCM.supplyIccPuk2(puk2, newPin2, - mHandler.obtainMessage(EVENT_PINPUK_DONE, onComplete)); + mPhone.mCM.supplyIccPuk2(puk2, newPin2, onComplete); } public void supplyNetworkDepersonalization (String pin, Message onComplete) { - mPhone.mCM.supplyNetworkDepersonalization(pin, - mHandler.obtainMessage(EVENT_PINPUK_DONE, onComplete)); + mPhone.mCM.supplyNetworkDepersonalization(pin, onComplete); } /** @@ -439,21 +457,15 @@ public class IccCard { * */ public String getServiceProviderName () { - return mPhone.mIccRecords.getServiceProviderName(); + return mIccRecords.getServiceProviderName(); } protected void updateStateProperty() { mPhone.setSystemProperty(TelephonyProperties.PROPERTY_SIM_STATE, getState().toString()); } - private void getIccCardStatusDone(AsyncResult ar) { - if (ar.exception != null) { - Log.e(mLogTag,"Error getting ICC status. " - + "RIL_REQUEST_GET_ICC_STATUS should " - + "never return an error", ar.exception); - return; - } - handleIccCardStatus((IccCardStatus) ar.result); + private void getIccCardStatusDone(IccCardStatus ics) { + handleIccCardStatus(ics); } private void handleIccCardStatus(IccCardStatus newCardStatus) { @@ -534,11 +546,8 @@ public class IccCard { // Call onReady Record(s) on the IccCard becomes ready (not NV) if (oldState != IccCardConstants.State.READY && newState == IccCardConstants.State.READY && (is3gpp || isSubscriptionFromIccCard)) { - if (!(mIccFileHandler instanceof CdmaLteUiccFileHandler)) { - // CdmaLteUicc File Handler deals with both USIM and CSIM. - // Do not lock onto one AID for now. - mIccFileHandler.setAid(getAid()); - } + mIccFileHandler.setAid(getAid()); + broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_READY, null); mIccRecords.onReady(); } } @@ -660,7 +669,6 @@ public class IccCard { if (!is3gpp) { handleCdmaSubscriptionSource(); } - mPhone.mCM.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); break; case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED: handleCdmaSubscriptionSource(); @@ -681,30 +689,9 @@ public class IccCard { obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE)); break; case EVENT_GET_ICC_STATUS_DONE: - ar = (AsyncResult)msg.obj; - - getIccCardStatusDone(ar); - break; - case EVENT_PINPUK_DONE: - // a PIN/PUK/PIN2/PUK2/Network Personalization - // request has completed. ar.userObj is the response Message - // Repoll before returning - ar = (AsyncResult)msg.obj; - // TODO should abstract these exceptions - AsyncResult.forMessage(((Message)ar.userObj)).exception - = ar.exception; - mPhone.mCM.getIccCardStatus( - obtainMessage(EVENT_REPOLL_STATUS_DONE, ar.userObj)); - break; - case EVENT_REPOLL_STATUS_DONE: - // Finished repolling status after PIN operation - // ar.userObj is the response messaeg - // ar.userObj.obj is already an AsyncResult with an - // appropriate exception filled in if applicable + IccCardStatus cs = (IccCardStatus)msg.obj; - ar = (AsyncResult)msg.obj; - getIccCardStatusDone(ar); - ((Message)ar.userObj).sendToTarget(); + getIccCardStatusDone(cs); break; case EVENT_QUERY_FACILITY_LOCK_DONE: ar = (AsyncResult)msg.obj; @@ -753,10 +740,6 @@ public class IccCard { = ar.exception; ((Message)ar.userObj).sendToTarget(); break; - case EVENT_ICC_STATUS_CHANGED: - Log.d(mLogTag, "Received Event EVENT_ICC_STATUS_CHANGED"); - mPhone.mCM.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); - break; case EVENT_CARD_REMOVED: onIccSwap(false); break; @@ -926,6 +909,10 @@ public class IccCard { Log.d(mLogTag, "[IccCard] " + msg); } + private void loge(String msg) { + Log.e(mLogTag, "[IccCard] " + msg); + } + protected int getCurrentApplicationIndex() { if (is3gpp) { return mIccCardStatus.getGsmUmtsSubscriptionAppIndex(); diff --git a/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java index 45562ca..0e5f2da 100644 --- a/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java +++ b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java @@ -103,11 +103,23 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub { public IccPhoneBookInterfaceManager(PhoneBase phone) { this.phone = phone; + IccRecords r = phone.mIccRecords.get(); + if (r != null) { + adnCache = r.getAdnCache(); + } } public void dispose() { } + public void updateIccRecords(IccRecords iccRecords) { + if (iccRecords != null) { + adnCache = iccRecords.getAdnCache(); + } else { + adnCache = null; + } + } + protected void publish() { //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy ServiceManager.addService("simphonebook", this); diff --git a/src/java/com/android/internal/telephony/IccRecords.java b/src/java/com/android/internal/telephony/IccRecords.java index 41c9d5a..3c90647 100644 --- a/src/java/com/android/internal/telephony/IccRecords.java +++ b/src/java/com/android/internal/telephony/IccRecords.java @@ -26,6 +26,8 @@ import android.os.RegistrantList; import com.android.internal.telephony.gsm.UsimServiceTable; import com.android.internal.telephony.ims.IsimRecords; +import java.util.concurrent.atomic.AtomicBoolean; + /** * {@hide} */ @@ -33,7 +35,7 @@ public abstract class IccRecords extends Handler implements IccConstants { protected static final boolean DBG = true; // ***** Instance Variables - protected boolean mDestroyed = false; // set to true once this object needs to be disposed of + protected AtomicBoolean mDestroyed = new AtomicBoolean(false); protected Context mContext; protected CommandsInterface mCi; protected IccFileHandler mFh; @@ -79,9 +81,9 @@ public abstract class IccRecords extends Handler implements IccConstants { // ***** Event Constants protected static final int EVENT_SET_MSISDN_DONE = 30; - public static final int EVENT_MWI = 0; - public static final int EVENT_CFI = 1; - public static final int EVENT_SPN = 2; + public static final int EVENT_MWI = 0; // Message Waiting indication + public static final int EVENT_CFI = 1; // Call Forwarding indication + public static final int EVENT_SPN = 2; // Service Provider Name public static final int EVENT_GET_ICC_RECORD_DONE = 100; @@ -113,7 +115,7 @@ public abstract class IccRecords extends Handler implements IccConstants { * Call when the IccRecords object is no longer going to be used. */ public void dispose() { - mDestroyed = true; + mDestroyed.set(true); mParentCard = null; mFh = null; mCi = null; @@ -128,12 +130,8 @@ public abstract class IccRecords extends Handler implements IccConstants { return adnCache; } - public IccCard getIccCard() { - return mParentCard; - } - public void registerForRecordsLoaded(Handler h, int what, Object obj) { - if (mDestroyed) { + if (mDestroyed.get()) { return; } diff --git a/src/java/com/android/internal/telephony/PhoneBase.java b/src/java/com/android/internal/telephony/PhoneBase.java index b55240a..866628b 100644 --- a/src/java/com/android/internal/telephony/PhoneBase.java +++ b/src/java/com/android/internal/telephony/PhoneBase.java @@ -40,6 +40,7 @@ import com.android.internal.R; import com.android.internal.telephony.gsm.UsimServiceTable; import com.android.internal.telephony.ims.IsimRecords; import com.android.internal.telephony.test.SimulatedRadioControl; +import com.android.internal.telephony.uicc.UiccController; import com.android.internal.telephony.gsm.SIMRecords; import java.io.FileDescriptor; @@ -110,6 +111,7 @@ public abstract class PhoneBase extends Handler implements Phone { protected static final int EVENT_SET_NETWORK_AUTOMATIC = 28; protected static final int EVENT_NEW_ICC_SMS = 29; protected static final int EVENT_ICC_RECORD_EVENTS = 30; + protected static final int EVENT_ICC_CHANGED = 31; // Key used to read/write current CLIR setting public static final String CLIR_KEY = "clir_key"; @@ -126,7 +128,8 @@ public abstract class PhoneBase extends Handler implements Phone { int mCallRingDelay; public boolean mIsTheCurrentActivePhone = true; boolean mIsVoiceCapable = true; - public IccRecords mIccRecords; + protected UiccController mUiccController = null; + public AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>(); protected AtomicReference<IccCard> mIccCard = new AtomicReference<IccCard>(); public SmsStorageMonitor mSmsStorageMonitor; public SmsUsageMonitor mSmsUsageMonitor; @@ -251,6 +254,8 @@ public abstract class PhoneBase extends Handler implements Phone { // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers. mSmsStorageMonitor = new SmsStorageMonitor(this); mSmsUsageMonitor = new SmsUsageMonitor(context); + mUiccController = UiccController.getInstance(this); + mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null); } public void dispose() { @@ -262,6 +267,7 @@ public abstract class PhoneBase extends Handler implements Phone { // Dispose the SMS usage and storage monitors mSmsStorageMonitor.dispose(); mSmsUsageMonitor.dispose(); + mUiccController.unregisterForIccChanged(this); } } @@ -269,9 +275,10 @@ public abstract class PhoneBase extends Handler implements Phone { mSmsStorageMonitor = null; mSmsUsageMonitor = null; mSMS = null; - mIccRecords = null; + mIccRecords.set(null); mIccCard.set(null); mDataConnectionTracker = null; + mUiccController = null; } /** @@ -309,6 +316,10 @@ public abstract class PhoneBase extends Handler implements Phone { } break; + case EVENT_ICC_CHANGED: + onUpdateIccAvailability(); + break; + default: throw new RuntimeException("unexpected event not handled"); } @@ -319,6 +330,9 @@ public abstract class PhoneBase extends Handler implements Phone { return mContext; } + // Will be called when icc changed + protected abstract void onUpdateIccAvailability(); + /** * Disables the DNS check (i.e., allows "0.0.0.0"). * Useful for lab testing environment. @@ -667,22 +681,26 @@ public abstract class PhoneBase extends Handler implements Phone { @Override public String getIccSerialNumber() { - return mIccRecords.iccid; + IccRecords r = mIccRecords.get(); + return (r != null) ? r.iccid : ""; } @Override public boolean getIccRecordsLoaded() { - return mIccRecords.getRecordsLoaded(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getRecordsLoaded() : false; } @Override public boolean getMessageWaitingIndicator() { - return mIccRecords.getVoiceMessageWaiting(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getVoiceMessageWaiting() : false; } @Override public boolean getCallForwardingIndicator() { - return mIccRecords.getVoiceCallForwardingFlag(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getVoiceCallForwardingFlag() : false; } /** @@ -1136,7 +1154,10 @@ public abstract class PhoneBase extends Handler implements Phone { */ @Override public void setVoiceMessageWaiting(int line, int countWaiting) { - mIccRecords.setVoiceMessageWaiting(line, countWaiting); + IccRecords r = mIccRecords.get(); + if (r != null) { + r.setVoiceMessageWaiting(line, countWaiting); + } } /** @@ -1145,7 +1166,8 @@ public abstract class PhoneBase extends Handler implements Phone { */ @Override public UsimServiceTable getUsimServiceTable() { - return mIccRecords.getUsimServiceTable(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getUsimServiceTable() : null; } public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -1158,7 +1180,7 @@ public abstract class PhoneBase extends Handler implements Phone { pw.println(" mCallRingDelay=" + mCallRingDelay); pw.println(" mIsTheCurrentActivePhone=" + mIsTheCurrentActivePhone); pw.println(" mIsVoiceCapable=" + mIsVoiceCapable); - pw.println(" mIccRecords=" + mIccRecords); + pw.println(" mIccRecords=" + mIccRecords.get()); pw.println(" mIccCard=" + mIccCard.get()); pw.println(" mSmsStorageMonitor=" + mSmsStorageMonitor); pw.println(" mSmsUsageMonitor=" + mSmsUsageMonitor); diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java index e4cfb23..178addd 100644 --- a/src/java/com/android/internal/telephony/ServiceStateTracker.java +++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java @@ -18,6 +18,7 @@ package com.android.internal.telephony; import android.os.AsyncResult; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.os.Registrant; import android.os.RegistrantList; @@ -28,12 +29,17 @@ import android.util.TimeUtils; import java.io.FileDescriptor; import java.io.PrintWriter; +import com.android.internal.telephony.uicc.UiccController; + /** * {@hide} */ public abstract class ServiceStateTracker extends Handler { protected CommandsInterface cm; + protected UiccController mUiccController = null; + protected IccCard mIccCard = null; + protected IccRecords mIccRecords = null; public ServiceState ss; protected ServiceState newSS; @@ -131,7 +137,7 @@ public abstract class ServiceStateTracker extends Handler { protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 39; protected static final int EVENT_CDMA_PRL_VERSION_CHANGED = 40; protected static final int EVENT_RADIO_ON = 41; - + protected static final int EVENT_ICC_CHANGED = 42; protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; @@ -168,7 +174,10 @@ public abstract class ServiceStateTracker extends Handler { protected static final String REGISTRATION_DENIED_GEN = "General"; protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure"; - public ServiceStateTracker() { + public ServiceStateTracker(PhoneBase p, CommandsInterface ci) { + cm = ci; + mUiccController = UiccController.getInstance(); + mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null); } public boolean getDesiredPowerState() { @@ -295,6 +304,10 @@ public abstract class ServiceStateTracker extends Handler { } break; + case EVENT_ICC_CHANGED: + onUpdateIccAvailability(); + break; + default: log("Unhandled message with number: " + msg.what); break; @@ -305,6 +318,7 @@ public abstract class ServiceStateTracker extends Handler { protected abstract void handlePollStateResult(int what, AsyncResult ar); protected abstract void updateSpnDisplay(); protected abstract void setPowerStateToDesired(); + protected abstract void onUpdateIccAvailability(); protected abstract void log(String s); protected abstract void loge(String s); @@ -535,4 +549,19 @@ public abstract class ServiceStateTracker extends Handler { pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff); pw.println(" mPendingRadioPowerOffAfterDataOffTag=" + mPendingRadioPowerOffAfterDataOffTag); } + + /** + * Verifies the current thread is the same as the thread originally + * used in the initialization of this instance. Throws RuntimeException + * if not. + * + * @exception RuntimeException if the current thread is not + * the thread that originally obtained this PhoneBase instance. + */ + protected void checkCorrectThread() { + if (Thread.currentThread() != getLooper().getThread()) { + throw new RuntimeException( + "ServiceStateTracker must be used from within one thread"); + } + } } diff --git a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java index df42515..f125484 100644 --- a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java +++ b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java @@ -29,6 +29,7 @@ import android.util.Log; import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.IccRecords; import com.android.internal.telephony.OperatorInfo; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; @@ -67,7 +68,6 @@ public class CDMALTEPhone extends CDMAPhone { public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) { super(context, ci, notifier, false); m3gppSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor); - mIccRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null); } @Override @@ -89,10 +89,6 @@ public class CDMALTEPhone extends CDMAPhone { @Override protected void initSstIcc() { - mIccCard.set(UiccController.getInstance(this).getIccCard()); - mIccRecords = mIccCard.get().getIccRecords(); - // CdmaLteServiceStateTracker registers with IccCard to know - // when the card is ready. So create mIccCard before the ServiceStateTracker mSST = new CdmaLteServiceStateTracker(this); } @@ -101,7 +97,6 @@ public class CDMALTEPhone extends CDMAPhone { synchronized(PhoneProxy.lockForRadioTechnologyChange) { super.dispose(); m3gppSMS.dispose(); - mIccRecords.unregisterForNewSms(this); } } @@ -205,11 +200,12 @@ public class CDMALTEPhone extends CDMAPhone { @Override public boolean updateCurrentCarrierInProvider() { - if (mIccRecords != null) { + IccRecords r = mIccRecords.get(); + if (r != null) { try { Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); ContentValues map = new ContentValues(); - String operatorNumeric = mIccRecords.getOperatorNumeric(); + String operatorNumeric = r.getOperatorNumeric(); map.put(Telephony.Carriers.NUMERIC, operatorNumeric); if (DBG) log("updateCurrentCarrierInProvider from UICC: numeric=" + operatorNumeric); @@ -227,7 +223,8 @@ public class CDMALTEPhone extends CDMAPhone { // return IMSI from USIM as subscriber ID. @Override public String getSubscriberId() { - return mIccRecords.getIMSI(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getIMSI() : ""; } @Override @@ -242,12 +239,14 @@ public class CDMALTEPhone extends CDMAPhone { @Override public IsimRecords getIsimRecords() { - return mIccRecords.getIsimRecords(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getIsimRecords() : null; } @Override public String getMsisdn() { - return mIccRecords.getMsisdnNumber(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getMsisdnNumber() : null; } @Override @@ -261,6 +260,26 @@ public class CDMALTEPhone extends CDMAPhone { } @Override + protected void registerForRuimRecordEvents() { + IccRecords r = mIccRecords.get(); + if (r == null) { + return; + } + r.registerForNewSms(this, EVENT_NEW_ICC_SMS, null); + super.registerForRuimRecordEvents(); + } + + @Override + protected void unregisterForRuimRecordEvents() { + IccRecords r = mIccRecords.get(); + if (r == null) { + return; + } + r.unregisterForNewSms(this); + super.unregisterForRuimRecordEvents(); + } + + @Override protected void log(String s) { Log.d(LOG_TAG, "[CDMALTEPhone] " + s); } diff --git a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java index 26ef9dc..f88fa9c 100755 --- a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java +++ b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java @@ -50,6 +50,7 @@ import com.android.internal.telephony.IccCard; import com.android.internal.telephony.IccException; import com.android.internal.telephony.IccFileHandler; import com.android.internal.telephony.IccPhoneBookInterfaceManager; +import com.android.internal.telephony.IccRecords; import com.android.internal.telephony.IccSmsInterfaceManager; import com.android.internal.telephony.MccTable; import com.android.internal.telephony.MmiCode; @@ -153,10 +154,6 @@ public class CDMAPhone extends PhoneBase { } protected void initSstIcc() { - mIccCard.set(UiccController.getInstance(this).getIccCard()); - mIccRecords = mIccCard.get().getIccRecords(); - // CdmaServiceStateTracker registers with IccCard to know - // when the Ruim card is ready. So create mIccCard before the ServiceStateTracker mSST = new CdmaServiceStateTracker(this); } @@ -173,7 +170,6 @@ public class CDMAPhone extends PhoneBase { mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML); mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); - registerForRuimRecordEvents(); mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); mCM.registerForOn(this, EVENT_RADIO_ON, null); mCM.setOnSuppServiceNotification(this, EVENT_SSN, null); @@ -728,7 +724,10 @@ public class CDMAPhone extends PhoneBase { Message resp; mVmNumber = voiceMailNumber; resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); - mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp); + IccRecords r = mIccRecords.get(); + if (r != null) { + r.setVoiceMailNumber(alphaTag, mVmNumber, resp); + } } public String getVoiceMailNumber() { @@ -750,7 +749,8 @@ public class CDMAPhone extends PhoneBase { * @hide */ public int getVoiceMessageCount() { - int voicemailCount = mIccRecords.getVoiceMessageCount(); + IccRecords r = mIccRecords.get(); + int voicemailCount = (r != null) ? r.getVoiceMessageCount() : 0; // If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility // that phone was power cycled and would have lost the voicemail count. // So get the count from preferences. @@ -1065,6 +1065,39 @@ public class CDMAPhone extends PhoneBase { } } + @Override + protected void onUpdateIccAvailability() { + if (mUiccController == null ) { + return; + } + + IccCard newIccCard = mUiccController.getIccCard(); + + IccCard c = mIccCard.get(); + if (c != newIccCard) { + if (c != null) { + log("Removing stale icc objects."); + if (mIccRecords.get() != null) { + unregisterForRuimRecordEvents(); + if (mRuimPhoneBookInterfaceManager != null) { + mRuimPhoneBookInterfaceManager.updateIccRecords(null); + } + } + mIccRecords.set(null); + mIccCard.set(null); + } + if (newIccCard != null) { + log("New card found"); + mIccCard.set(newIccCard); + mIccRecords.set(newIccCard.getIccRecords()); + registerForRuimRecordEvents(); + if (mRuimPhoneBookInterfaceManager != null) { + mRuimPhoneBookInterfaceManager.updateIccRecords(mIccRecords.get()); + } + } + } + } + private void processIccRecordEvents(int eventCode) { switch (eventCode) { case RuimRecords.EVENT_MWI: @@ -1463,14 +1496,22 @@ public class CDMAPhone extends PhoneBase { return mEriManager.isEriFileLoaded(); } - private void registerForRuimRecordEvents() { - mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); - mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); + protected void registerForRuimRecordEvents() { + IccRecords r = mIccRecords.get(); + if (r == null) { + return; + } + r.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); + r.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); } - private void unregisterForRuimRecordEvents() { - mIccRecords.unregisterForRecordsEvents(this); - mIccRecords.unregisterForRecordsLoaded(this); + protected void unregisterForRuimRecordEvents() { + IccRecords r = mIccRecords.get(); + if (r == null) { + return; + } + r.unregisterForRecordsEvents(this); + r.unregisterForRecordsLoaded(this); } protected void log(String s) { diff --git a/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index 20f1d08..51b4a4c 100644 --- a/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -42,6 +42,8 @@ import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.EventLogTags; import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.IccRecords; import com.android.internal.telephony.RetryManager; import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.Phone; @@ -104,7 +106,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { p.mCM.registerForAvailable (this, DctConstants.EVENT_RADIO_AVAILABLE, null); p.mCM.registerForOffOrNotAvailable(this, DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); - p.mIccRecords.registerForRecordsLoaded(this, DctConstants.EVENT_RECORDS_LOADED, null); p.mCM.registerForDataNetworkStateChanged (this, DctConstants.EVENT_DATA_STATE_CHANGED, null); p.mCT.registerForVoiceCallEnded (this, DctConstants.EVENT_VOICE_CALL_ENDED, null); p.mCT.registerForVoiceCallStarted (this, DctConstants.EVENT_VOICE_CALL_STARTED, null); @@ -146,7 +147,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { // Unregister from all events mPhone.mCM.unregisterForAvailable(this); mPhone.mCM.unregisterForOffOrNotAvailable(this); - mCdmaPhone.mIccRecords.unregisterForRecordsLoaded(this); + IccRecords r = mIccRecords.get(); + if (r != null) { r.unregisterForRecordsLoaded(this);} mPhone.mCM.unregisterForDataNetworkStateChanged(this); mCdmaPhone.mCT.unregisterForVoiceCallEnded(this); mCdmaPhone.mCT.unregisterForVoiceCallStarted(this); @@ -216,11 +218,12 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { boolean subscriptionFromNv = (mCdmaSSM.getCdmaSubscriptionSource() == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV); + IccRecords r = mIccRecords.get(); boolean allowed = (psState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) && (subscriptionFromNv || - mCdmaPhone.mIccRecords.getRecordsLoaded()) && + (r != null && r.getRecordsLoaded())) && (mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() || mPhone.getState() ==PhoneConstants.State.IDLE) && !roaming && @@ -235,7 +238,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { reason += " - psState= " + psState; } if (!subscriptionFromNv && - !mCdmaPhone.mIccRecords.getRecordsLoaded()) { + !(r != null && r.getRecordsLoaded())) { reason += " - RUIM not loaded"; } if (!(mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() || @@ -1007,6 +1010,34 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { } @Override + protected void onUpdateIcc() { + if (mUiccController == null ) { + return; + } + + IccCard newIccCard = mUiccController.getIccCard(); + IccRecords newIccRecords = null; + if (newIccCard != null) { + newIccRecords = newIccCard.getIccRecords(); + } + + IccRecords r = mIccRecords.get(); + if (r != newIccRecords) { + if (r != null) { + log("Removing stale icc objects."); + r.unregisterForRecordsLoaded(this); + mIccRecords.set(null); + } + if (newIccRecords != null) { + log("New card found"); + mIccRecords.set(newIccRecords); + newIccRecords.registerForRecordsLoaded( + this, DctConstants.EVENT_RECORDS_LOADED, null); + } + } + } + + @Override public boolean isDisconnected() { return ((mState == DctConstants.State.IDLE) || (mState == DctConstants.State.FAILED)); } diff --git a/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java index 0c5c342..43db046 100644 --- a/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java +++ b/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java @@ -65,7 +65,7 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { handlePollStateResult(msg.what, ar); break; case EVENT_RUIM_RECORDS_LOADED: - CdmaLteUiccRecords sim = (CdmaLteUiccRecords)phone.mIccRecords; + CdmaLteUiccRecords sim = (CdmaLteUiccRecords)mIccRecords; if ((sim != null) && sim.isProvisioned()) { mMdn = sim.getMdn(); mMin = sim.getMin(); @@ -344,7 +344,7 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { if (ss.getState() == ServiceState.STATE_IN_SERVICE) { eriText = phone.getCdmaEriText(); } else if (ss.getState() == ServiceState.STATE_POWER_OFF) { - eriText = phone.mIccRecords.getServiceProviderName(); + eriText = (mIccRecords != null) ? mIccRecords.getServiceProviderName() : null; if (TextUtils.isEmpty(eriText)) { // Sets operator alpha property by retrieving from // build-time system property @@ -359,16 +359,18 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker { ss.setOperatorAlphaLong(eriText); } - if (phone.getIccCard().getState() == IccCardConstants.State.READY) { + if (mIccCard != null && mIccCard.getState() == IccCardConstants.State.READY && + mIccRecords != null) { // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches // one configfured in SIM, use operator name from CSIM record. boolean showSpn = - ((CdmaLteUiccRecords)phone.mIccRecords).getCsimSpnDisplayCondition(); + ((CdmaLteUiccRecords)mIccRecords).getCsimSpnDisplayCondition(); int iconIndex = ss.getCdmaEriIconIndex(); if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) && - isInHomeSidNid(ss.getSystemId(), ss.getNetworkId())) { - ss.setOperatorAlphaLong(phone.mIccRecords.getServiceProviderName()); + isInHomeSidNid(ss.getSystemId(), ss.getNetworkId()) && + mIccRecords != null) { + ss.setOperatorAlphaLong(mIccRecords.getServiceProviderName()); } } diff --git a/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java index 5a4af7a..8247d54 100755 --- a/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java +++ b/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java @@ -116,12 +116,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { long mSavedTime; long mSavedAtTime; - /** - * We can't register for SIM_RECORDS_LOADED immediately because the - * SIMRecords object may not be instantiated yet. - */ - private boolean mNeedToRegForRuimLoaded = false; - /** Wake lock used while setting time of day. */ private PowerManager.WakeLock mWakeLock; private static final String WAKELOCK_TAG = "ServiceStateTracker"; @@ -163,11 +157,10 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { }; public CdmaServiceStateTracker(CDMAPhone phone) { - super(); + super(phone, phone.mCM); this.phone = phone; cr = phone.getContext().getContentResolver(); - cm = phone.mCM; ss = new ServiceState(); newSS = new ServiceState(); cellLoc = new CdmaCellLocation(); @@ -204,18 +197,17 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { Settings.System.getUriFor(Settings.System.AUTO_TIME_ZONE), true, mAutoTimeZoneObserver); setSignalStrengthDefaultValues(); - - mNeedToRegForRuimLoaded = true; } public void dispose() { + checkCorrectThread(); // Unregister for all events. cm.unregisterForRadioStateChanged(this); cm.unregisterForVoiceNetworkStateChanged(this); - phone.getIccCard().unregisterForReady(this); cm.unregisterForCdmaOtaProvision(this); phone.unregisterForEriFileLoaded(this); - phone.mIccRecords.unregisterForRecordsLoaded(this); + if (mIccCard != null) {mIccCard.unregisterForReady(this);} + if (mIccRecords != null) {mIccRecords.unregisterForRecordsLoaded(this);} cm.unSetOnSignalStrengthUpdate(this); cm.unSetOnNITZTime(this); cr.unregisterContentObserver(mAutoTimeObserver); @@ -287,14 +279,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { // TODO: Consider calling setCurrentPreferredNetworkType as we do in GsmSST. // cm.setCurrentPreferredNetworkType(); - // The RUIM is now ready i.e if it was locked it has been - // unlocked. At this stage, the radio is already powered on. - if (mNeedToRegForRuimLoaded) { - phone.mIccRecords.registerForRecordsLoaded(this, - EVENT_RUIM_RECORDS_LOADED, null); - mNeedToRegForRuimLoaded = false; - } - if (phone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) { // Subscription will be read from SIM I/O if (DBG) log("Receive EVENT_RUIM_READY"); @@ -413,8 +397,19 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { mIsMinInfoReady = true; updateOtaspState(); - phone.getIccCard().broadcastIccStateChangedIntent( - IccCardConstants.INTENT_VALUE_ICC_IMSI, null); + if (mIccCard != null) { + if (DBG) { + log("GET_CDMA_SUBSCRIPTION broadcast Icc state changed"); + } + mIccCard.broadcastIccStateChangedIntent( + IccCardConstants.INTENT_VALUE_ICC_IMSI, + null); + } else { + if (DBG) { + log("GET_CDMA_SUBSCRIPTION mIccCard is null (probably NV type device)" + + " can't broadcast Icc state changed"); + } + } } else { if (DBG) { log("GET_CDMA_SUBSCRIPTION: error parsing cdmaSubscription params num=" @@ -506,8 +501,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { if (!isSubscriptionFromRuim) { // NV is ready when subscription source is NV sendMessage(obtainMessage(EVENT_NV_READY)); - } else { - phone.getIccCard().registerForReady(this, EVENT_RUIM_READY, null); } } @@ -1702,6 +1695,38 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { } @Override + protected void onUpdateIccAvailability() { + if (mUiccController == null ) { + return; + } + + IccCard newIccCard = mUiccController.getIccCard(); + + if (mIccCard != newIccCard) { + if (mIccCard != null) { + log("Removing stale icc objects."); + mIccCard.unregisterForReady(this); + if (mIccRecords != null) { + mIccRecords.unregisterForRecordsLoaded(this); + } + mIccRecords = null; + mIccCard = null; + } + if (newIccCard != null) { + log("New card found"); + mIccCard = newIccCard; + mIccRecords = mIccCard.getIccRecords(); + if (isSubscriptionFromRuim) { + mIccCard.registerForReady(this, EVENT_RUIM_READY, null); + if (mIccRecords != null) { + mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); + } + } + } + } + } + + @Override protected void log(String s) { Log.d(LOG_TAG, "[CdmaSST] " + s); } @@ -1734,7 +1759,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker { pw.println(" mSavedTimeZone=" + mSavedTimeZone); pw.println(" mSavedTime=" + mSavedTime); pw.println(" mSavedAtTime=" + mSavedAtTime); - pw.println(" mNeedToRegForRuimLoaded=" + mNeedToRegForRuimLoaded); pw.println(" mWakeLock=" + mWakeLock); pw.println(" mCurPlmn=" + mCurPlmn); pw.println(" mMdn=" + mMdn); diff --git a/src/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java b/src/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java index 04ee2dd..e919245 100644 --- a/src/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java +++ b/src/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java @@ -21,6 +21,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import android.os.Message; import android.util.Log; +import com.android.internal.telephony.IccFileHandler; import com.android.internal.telephony.IccPhoneBookInterfaceManager; /** @@ -34,7 +35,6 @@ public class RuimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager public RuimPhoneBookInterfaceManager(CDMAPhone phone) { super(phone); - adnCache = phone.mIccRecords.getAdnCache(); //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy } @@ -61,8 +61,12 @@ public class RuimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager AtomicBoolean status = new AtomicBoolean(false); Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE, status); - phone.getIccFileHandler().getEFLinearRecordSize(efid, response); - waitForResult(status); + IccFileHandler fh = phone.getIccFileHandler(); + //IccFileHandler can be null if there is no icc card present. + if (fh != null) { + fh.getEFLinearRecordSize(efid, response); + waitForResult(status); + } } return recordSize; diff --git a/src/java/com/android/internal/telephony/cdma/RuimRecords.java b/src/java/com/android/internal/telephony/cdma/RuimRecords.java index e257fb6..d3e04bd 100755 --- a/src/java/com/android/internal/telephony/cdma/RuimRecords.java +++ b/src/java/com/android/internal/telephony/cdma/RuimRecords.java @@ -200,7 +200,7 @@ public final class RuimRecords extends IccRecords { boolean isRecordLoadResponse = false; - if (mDestroyed) { + if (mDestroyed.get()) { loge("Received message " + msg + "[" + msg.what + "] while being destroyed. Ignoring."); return; @@ -318,18 +318,20 @@ public final class RuimRecords extends IccRecords { // One record loaded successfully or failed, In either case // we need to update the recordsToLoad count recordsToLoad -= 1; - if (DBG) log("RuimRecords:onRecordLoaded " + recordsToLoad + " requested: " + recordsRequested); + if (DBG) log("onRecordLoaded " + recordsToLoad + " requested: " + recordsRequested); if (recordsToLoad == 0 && recordsRequested == true) { onAllRecordsLoaded(); } else if (recordsToLoad < 0) { - loge("RuimRecords: recordsToLoad <0, programmer error suspected"); + loge("recordsToLoad <0, programmer error suspected"); recordsToLoad = 0; } } @Override protected void onAllRecordsLoaded() { + if (DBG) log("record load complete"); + // Further records that can be inserted are Operator/OEM dependent String operator = getRUIMOperatorNumeric(); @@ -349,13 +351,6 @@ public final class RuimRecords extends IccRecords { @Override public void onReady() { - /* broadcast intent ICC_READY here so that we can make sure - READY is sent before IMSI ready - */ - - mParentCard.broadcastIccStateChangedIntent( - IccCardConstants.INTENT_VALUE_ICC_READY, null); - fetchRuimRecords(); mCi.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE)); @@ -365,7 +360,7 @@ public final class RuimRecords extends IccRecords { private void fetchRuimRecords() { recordsRequested = true; - Log.v(LOG_TAG, "RuimRecords:fetchRuimRecords " + recordsToLoad); + if (DBG) log("fetchRuimRecords " + recordsToLoad); mCi.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE)); recordsToLoad++; @@ -374,7 +369,7 @@ public final class RuimRecords extends IccRecords { obtainMessage(EVENT_GET_ICCID_DONE)); recordsToLoad++; - log("RuimRecords:fetchRuimRecords " + recordsToLoad + " requested: " + recordsRequested); + if (DBG) log("fetchRuimRecords " + recordsToLoad + " requested: " + recordsRequested); // Further records that can be inserted are Operator/OEM dependent } diff --git a/src/java/com/android/internal/telephony/gsm/GSMPhone.java b/src/java/com/android/internal/telephony/gsm/GSMPhone.java index 34ee647..bc8aa0f 100644 --- a/src/java/com/android/internal/telephony/gsm/GSMPhone.java +++ b/src/java/com/android/internal/telephony/gsm/GSMPhone.java @@ -59,6 +59,7 @@ import com.android.internal.telephony.Connection; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.IccFileHandler; import com.android.internal.telephony.IccPhoneBookInterfaceManager; +import com.android.internal.telephony.IccRecords; import com.android.internal.telephony.IccSmsInterfaceManager; import com.android.internal.telephony.MmiCode; import com.android.internal.telephony.OperatorInfo; @@ -140,11 +141,10 @@ public class GSMPhone extends PhoneBase { } mCM.setPhoneType(PhoneConstants.PHONE_TYPE_GSM); - mIccCard.set(UiccController.getInstance(this).getIccCard()); - mIccRecords = mIccCard.get().getIccRecords(); mCT = new GsmCallTracker(this); mSST = new GsmServiceStateTracker (this); mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor); + mDataConnectionTracker = new GsmDataConnectionTracker (this); if (!unitTestMode) { mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this); @@ -153,7 +153,6 @@ public class GSMPhone extends PhoneBase { } mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); - registerForSimRecordEvents(); mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); mCM.registerForOn(this, EVENT_RADIO_ON, null); mCM.setOnUSSD(this, EVENT_USSD, null); @@ -801,7 +800,8 @@ public class GSMPhone extends PhoneBase { public String getVoiceMailNumber() { // Read from the SIM. If its null, try reading from the shared preference area. - String number = mIccRecords.getVoiceMailNumber(); + IccRecords r = mIccRecords.get(); + String number = (r != null) ? r.getVoiceMailNumber() : ""; if (TextUtils.isEmpty(number)) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); number = sp.getString(VM_NUMBER, null); @@ -823,8 +823,9 @@ public class GSMPhone extends PhoneBase { public String getVoiceMailAlphaTag() { String ret; + IccRecords r = mIccRecords.get(); - ret = mIccRecords.getVoiceMailAlphaTag(); + ret = (r != null) ? r.getVoiceMailAlphaTag() : ""; if (ret == null || ret.length() == 0) { return mContext.getText( @@ -857,24 +858,31 @@ public class GSMPhone extends PhoneBase { } public String getSubscriberId() { - return mIccRecords.getIMSI(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getIMSI() : ""; } public String getLine1Number() { - return mIccRecords.getMsisdnNumber(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getMsisdnNumber() : ""; } @Override public String getMsisdn() { - return mIccRecords.getMsisdnNumber(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getMsisdnNumber() : ""; } public String getLine1AlphaTag() { - return mIccRecords.getMsisdnAlphaTag(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.getMsisdnAlphaTag() : ""; } public void setLine1Number(String alphaTag, String number, Message onComplete) { - mIccRecords.setMsisdnNumber(alphaTag, number, onComplete); + IccRecords r = mIccRecords.get(); + if (r != null) { + r.setMsisdnNumber(alphaTag, number, onComplete); + } } public void setVoiceMailNumber(String alphaTag, @@ -884,7 +892,10 @@ public class GSMPhone extends PhoneBase { Message resp; mVmNumber = voiceMailNumber; resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); - mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp); + IccRecords r = mIccRecords.get(); + if (r != null) { + r.setVoiceMailNumber(alphaTag, mVmNumber, resp); + } } private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) { @@ -1252,8 +1263,9 @@ public class GSMPhone extends PhoneBase { case EVENT_SET_CALL_FORWARD_DONE: ar = (AsyncResult)msg.obj; - if (ar.exception == null) { - mIccRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1); + IccRecords r = mIccRecords.get(); + if (ar.exception == null && r != null) { + r.setVoiceCallForwardingFlag(1, msg.arg1 == 1); } onComplete = (Message) ar.userObj; if (onComplete != null) { @@ -1326,12 +1338,41 @@ public class GSMPhone extends PhoneBase { } } + @Override + protected void onUpdateIccAvailability() { + if (mUiccController == null ) { + return; + } + + IccCard newIccCard = mUiccController.getIccCard(); + + IccCard c = mIccCard.get(); + if (c != newIccCard) { + if (c != null) { + if (LOCAL_DEBUG) log("Removing stale icc objects."); + if (mIccRecords.get() != null) { + unregisterForSimRecordEvents(); + mSimPhoneBookIntManager.updateIccRecords(null); + } + mIccRecords.set(null); + mIccCard.set(null); + } + if (newIccCard != null) { + if (LOCAL_DEBUG) log("New card found"); + mIccCard.set(newIccCard); + mIccRecords.set(newIccCard.getIccRecords()); + registerForSimRecordEvents(); + mSimPhoneBookIntManager.updateIccRecords(mIccRecords.get()); + } + } + } + private void processIccRecordEvents(int eventCode) { switch (eventCode) { - case SIMRecords.EVENT_CFI: + case IccRecords.EVENT_CFI: notifyCallForwardingIndicator(); break; - case SIMRecords.EVENT_MWI: + case IccRecords.EVENT_MWI: notifyMessageWaitingIndicator(); break; } @@ -1343,11 +1384,12 @@ public class GSMPhone extends PhoneBase { * @return true for success; false otherwise. */ boolean updateCurrentCarrierInProvider() { - if (mIccRecords != null) { + IccRecords r = mIccRecords.get(); + if (r != null) { try { Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); ContentValues map = new ContentValues(); - map.put(Telephony.Carriers.NUMERIC, mIccRecords.getOperatorNumeric()); + map.put(Telephony.Carriers.NUMERIC, r.getOperatorNumeric()); mContext.getContentResolver().insert(uri, map); return true; } catch (SQLException e) { @@ -1409,16 +1451,19 @@ public class GSMPhone extends PhoneBase { } private void handleCfuQueryResult(CallForwardInfo[] infos) { - if (infos == null || infos.length == 0) { - // Assume the default is not active - // Set unconditional CFF in SIM to false - mIccRecords.setVoiceCallForwardingFlag(1, false); - } else { - for (int i = 0, s = infos.length; i < s; i++) { - if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) { - mIccRecords.setVoiceCallForwardingFlag(1, (infos[i].status == 1)); - // should only have the one - break; + IccRecords r = mIccRecords.get(); + if (r != null) { + if (infos == null || infos.length == 0) { + // Assume the default is not active + // Set unconditional CFF in SIM to false + r.setVoiceCallForwardingFlag(1, false); + } else { + for (int i = 0, s = infos.length; i < s; i++) { + if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) { + r.setVoiceCallForwardingFlag(1, (infos[i].status == 1)); + // should only have the one + break; + } } } } @@ -1477,22 +1522,31 @@ public class GSMPhone extends PhoneBase { } public boolean isCspPlmnEnabled() { - return mIccRecords.isCspPlmnEnabled(); + IccRecords r = mIccRecords.get(); + return (r != null) ? r.isCspPlmnEnabled() : false; } private void registerForSimRecordEvents() { - mIccRecords.registerForNetworkSelectionModeAutomatic( + IccRecords r = mIccRecords.get(); + if (r == null) { + return; + } + r.registerForNetworkSelectionModeAutomatic( this, EVENT_SET_NETWORK_AUTOMATIC, null); - mIccRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null); - mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); - mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); + r.registerForNewSms(this, EVENT_NEW_ICC_SMS, null); + r.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); + r.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); } private void unregisterForSimRecordEvents() { - mIccRecords.unregisterForNetworkSelectionModeAutomatic(this); - mIccRecords.unregisterForNewSms(this); - mIccRecords.unregisterForRecordsEvents(this); - mIccRecords.unregisterForRecordsLoaded(this); + IccRecords r = mIccRecords.get(); + if (r == null) { + return; + } + r.unregisterForNetworkSelectionModeAutomatic(this); + r.unregisterForNewSms(this); + r.unregisterForRecordsEvents(this); + r.unregisterForRecordsLoaded(this); } @Override @@ -1509,4 +1563,8 @@ public class GSMPhone extends PhoneBase { if (VDBG) pw.println(" mImeiSv=" + mImeiSv); pw.println(" mVmNumber=" + mVmNumber); } + + protected void log(String s) { + Log.d(LOG_TAG, "[GSMPhone] " + s); + } } diff --git a/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 324841e..bcc2908 100644 --- a/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -60,6 +60,8 @@ import com.android.internal.telephony.DataConnectionAc; import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.EventLogTags; +import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.IccRecords; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneBase; import com.android.internal.telephony.PhoneConstants; @@ -190,7 +192,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { p.mCM.registerForAvailable (this, DctConstants.EVENT_RADIO_AVAILABLE, null); p.mCM.registerForOffOrNotAvailable(this, DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); - p.mIccRecords.registerForRecordsLoaded(this, DctConstants.EVENT_RECORDS_LOADED, null); p.mCM.registerForDataNetworkStateChanged (this, DctConstants.EVENT_DATA_STATE_CHANGED, null); p.getCallTracker().registerForVoiceCallEnded (this, DctConstants.EVENT_VOICE_CALL_ENDED, @@ -235,7 +236,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { //Unregister for all events mPhone.mCM.unregisterForAvailable(this); mPhone.mCM.unregisterForOffOrNotAvailable(this); - mPhone.mIccRecords.unregisterForRecordsLoaded(this); + IccRecords r = mIccRecords.get(); + if (r != null) { r.unregisterForRecordsLoaded(this);} mPhone.mCM.unregisterForDataNetworkStateChanged(this); mPhone.getCallTracker().unregisterForVoiceCallEnded(this); mPhone.getCallTracker().unregisterForVoiceCallStarted(this); @@ -637,10 +639,12 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { int gprsState = mPhone.getServiceStateTracker().getCurrentDataConnectionState(); boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState(); + IccRecords r = mIccRecords.get(); + boolean recordsLoaded = (r != null) ? r.getRecordsLoaded() : false; boolean allowed = (gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) && - mPhone.mIccRecords.getRecordsLoaded() && + recordsLoaded && (mPhone.getState() == PhoneConstants.State.IDLE || mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) && internalDataEnabled && @@ -652,7 +656,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) { reason += " - gprs= " + gprsState; } - if (!mPhone.mIccRecords.getRecordsLoaded()) reason += " - SIM not loaded"; + if (!recordsLoaded) reason += " - SIM not loaded"; if (mPhone.getState() != PhoneConstants.State.IDLE && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) { reason += " - PhoneState= " + mPhone.getState(); @@ -2000,7 +2004,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { log("onRadioAvailable: We're on the simulator; assuming data is connected"); } - if (mPhone.mIccRecords.getRecordsLoaded()) { + IccRecords r = mIccRecords.get(); + if (r != null && r.getRecordsLoaded()) { notifyOffApnsOfAvailability(null); } @@ -2296,7 +2301,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { */ private void createAllApnList() { mAllApns = new ArrayList<ApnSetting>(); - String operator = mPhone.mIccRecords.getOperatorNumeric(); + IccRecords r = mIccRecords.get(); + String operator = (r != null) ? r.getOperatorNumeric() : ""; if (operator != null) { String selection = "numeric = '" + operator + "'"; // query only enabled apn. @@ -2412,7 +2418,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } } - String operator = mPhone.mIccRecords.getOperatorNumeric(); + IccRecords r = mIccRecords.get(); + String operator = (r != null) ? r.getOperatorNumeric() : ""; int radioTech = mPhone.getServiceState().getRilRadioTechnology(); if (canSetPreferApn && mPreferredApn != null && @@ -2648,6 +2655,34 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { } @Override + protected void onUpdateIcc() { + if (mUiccController == null ) { + return; + } + + IccCard newIccCard = mUiccController.getIccCard(); + IccRecords newIccRecords = null; + if (newIccCard != null) { + newIccRecords = newIccCard.getIccRecords(); + } + + IccRecords r = mIccRecords.get(); + if (r != newIccRecords) { + if (r != null) { + log("Removing stale icc objects."); + r.unregisterForRecordsLoaded(this); + mIccRecords.set(null); + } + if (newIccRecords != null) { + log("New card found"); + mIccRecords.set(newIccRecords); + newIccRecords.registerForRecordsLoaded( + this, DctConstants.EVENT_RECORDS_LOADED, null); + } + } + } + + @Override protected void log(String s) { Log.d(LOG_TAG, "[GsmDCT] "+ s); } diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java index 15e6a22..1f7836e 100644 --- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java +++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java @@ -885,7 +885,10 @@ public final class GsmMmiCode extends Handler implements MmiCode { */ if ((ar.exception == null) && (msg.arg1 == 1)) { boolean cffEnabled = (msg.arg2 == 1); - phone.mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled); + IccRecords r = phone.mIccRecords.get(); + if (r != null) { + r.setVoiceCallForwardingFlag(1, cffEnabled); + } } onSetComplete(ar); @@ -1203,7 +1206,10 @@ public final class GsmMmiCode extends Handler implements MmiCode { (info.serviceClass & serviceClassMask) == CommandsInterface.SERVICE_CLASS_VOICE) { boolean cffEnabled = (info.status == 1); - phone.mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled); + IccRecords r = phone.mIccRecords.get(); + if (r != null) { + r.setVoiceCallForwardingFlag(1, cffEnabled); + } } return TextUtils.replace(template, sources, destinations); @@ -1228,7 +1234,10 @@ public final class GsmMmiCode extends Handler implements MmiCode { sb.append(context.getText(com.android.internal.R.string.serviceDisabled)); // Set unconditional CFF in SIM to false - phone.mIccRecords.setVoiceCallForwardingFlag(1, false); + IccRecords r = phone.mIccRecords.get(); + if (r != null) { + r.setVoiceCallForwardingFlag(1, false); + } } else { SpannableStringBuilder tb = new SpannableStringBuilder(); diff --git a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java index 808ec2b..046d220 100644 --- a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java +++ b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java @@ -125,12 +125,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker { long mSavedTime; long mSavedAtTime; - /** - * We can't register for SIM_RECORDS_LOADED immediately because the - * SIMRecords object may not be instantiated yet. - */ - private boolean mNeedToRegForSimLoaded; - /** Started the recheck process after finding gprs should registered but not. */ private boolean mStartedGprsRegCheck = false; @@ -193,10 +187,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker { }; public GsmServiceStateTracker(GSMPhone phone) { - super(); + super(phone, phone.mCM); this.phone = phone; - cm = phone.mCM; ss = new ServiceState(); newSS = new ServiceState(); cellLoc = new GsmCellLocation(); @@ -214,7 +207,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker { cm.setOnNITZTime(this, EVENT_NITZ_TIME, null); cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null); cm.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null); - phone.getIccCard().registerForReady(this, EVENT_SIM_READY, null); // system setting property AIRPLANE_MODE_ON is set in Settings. int airplaneMode = Settings.System.getInt( @@ -231,7 +223,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker { mAutoTimeZoneObserver); setSignalStrengthDefaultValues(); - mNeedToRegForSimLoaded = true; // Monitor locale change IntentFilter filter = new IntentFilter(); @@ -243,12 +234,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } public void dispose() { + checkCorrectThread(); // Unregister for all events. cm.unregisterForAvailable(this); cm.unregisterForRadioStateChanged(this); cm.unregisterForVoiceNetworkStateChanged(this); - phone.getIccCard().unregisterForReady(this); - phone.mIccRecords.unregisterForRecordsLoaded(this); + if (mIccCard != null) {mIccCard.unregisterForReady(this);} + if (mIccRecords != null) {mIccRecords.unregisterForRecordsLoaded(this);} cm.unSetOnSignalStrengthUpdate(this); cm.unSetOnRestrictedStateChanged(this); cm.unSetOnNITZTime(this); @@ -286,15 +278,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker { // Set the network type, in case the radio does not restore it. cm.setCurrentPreferredNetworkType(); - // The SIM is now ready i.e if it was locked - // it has been unlocked. At this stage, the radio is already - // powered on. - if (mNeedToRegForSimLoaded) { - phone.mIccRecords.registerForRecordsLoaded(this, - EVENT_SIM_RECORDS_LOADED, null); - mNeedToRegForSimLoaded = false; - } - boolean skipRestoringSelection = phone.getContext().getResources().getBoolean( com.android.internal.R.bool.skip_restoring_network_selection); @@ -496,8 +479,11 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } protected void updateSpnDisplay() { - int rule = phone.mIccRecords.getDisplayRule(ss.getOperatorNumeric()); - String spn = phone.mIccRecords.getServiceProviderName(); + if (mIccRecords == null) { + return; + } + int rule = mIccRecords.getDisplayRule(ss.getOperatorNumeric()); + String spn = mIccRecords.getServiceProviderName(); String plmn = ss.getOperatorAlphaLong(); // For emergency calls only, pass the EmergencyCallsOnly string via EXTRA_PLMN @@ -1150,7 +1136,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker { ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) || ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); //ignore the normal call and data restricted state before SIM READY - if (phone.getIccCard().getState() == IccCardConstants.State.READY) { + if (mIccCard.getState() == IccCardConstants.State.READY) { newRs.setCsNormalRestricted( ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) || ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); @@ -1677,6 +1663,35 @@ final class GsmServiceStateTracker extends ServiceStateTracker { } @Override + protected void onUpdateIccAvailability() { + if (mUiccController == null ) { + return; + } + + IccCard newIccCard = mUiccController.getIccCard(); + + if (mIccCard != newIccCard) { + if (mIccCard != null) { + log("Removing stale icc objects."); + mIccCard.unregisterForReady(this); + if (mIccRecords != null) { + mIccRecords.unregisterForRecordsLoaded(this); + } + mIccRecords = null; + mIccCard = null; + } + if (newIccCard != null) { + log("New card found"); + mIccCard = newIccCard; + mIccRecords = mIccCard.getIccRecords(); + mIccCard.registerForReady(this, EVENT_SIM_READY, null); + if (mIccRecords != null) { + mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); + } + } + } + } + @Override protected void log(String s) { Log.d(LOG_TAG, "[GsmSST] " + s); } @@ -1716,7 +1731,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker { pw.println(" mSavedTimeZone=" + mSavedTimeZone); pw.println(" mSavedTime=" + mSavedTime); pw.println(" mSavedAtTime=" + mSavedAtTime); - pw.println(" mNeedToRegForSimLoaded=" + mNeedToRegForSimLoaded); pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck); pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg); pw.println(" mNotification=" + mNotification); diff --git a/src/java/com/android/internal/telephony/gsm/SIMRecords.java b/src/java/com/android/internal/telephony/gsm/SIMRecords.java index 1ec3ea7..d5099f7 100755 --- a/src/java/com/android/internal/telephony/gsm/SIMRecords.java +++ b/src/java/com/android/internal/telephony/gsm/SIMRecords.java @@ -522,7 +522,7 @@ public class SIMRecords extends IccRecords { boolean isRecordLoadResponse = false; - if (mDestroyed) { + if (mDestroyed.get()) { loge("Received message " + msg + "[" + msg.what + "] " + " while being destroyed. Ignoring."); return; @@ -1300,12 +1300,6 @@ public class SIMRecords extends IccRecords { @Override public void onReady() { - /* broadcast intent SIM_READY here so that we can make sure - READY is sent before IMSI ready - */ - mParentCard.broadcastIccStateChangedIntent( - IccCardConstants.INTENT_VALUE_ICC_READY, null); - fetchSimRecords(); } diff --git a/src/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java b/src/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java index 35ba0d1..37f9a4f 100644 --- a/src/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java +++ b/src/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java @@ -21,6 +21,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import android.os.Message; import android.util.Log; +import com.android.internal.telephony.IccFileHandler; import com.android.internal.telephony.IccPhoneBookInterfaceManager; /** @@ -34,7 +35,6 @@ public class SimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager { public SimPhoneBookInterfaceManager(GSMPhone phone) { super(phone); - adnCache = phone.mIccRecords.getAdnCache(); //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy } @@ -61,8 +61,11 @@ public class SimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager { AtomicBoolean status = new AtomicBoolean(false); Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE, status); - phone.getIccFileHandler().getEFLinearRecordSize(efid, response); - waitForResult(status); + IccFileHandler fh = phone.getIccFileHandler(); + if (fh != null) { + fh.getEFLinearRecordSize(efid, response); + waitForResult(status); + } } return recordSize; diff --git a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java index ff64486..b0a6080 100755 --- a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java +++ b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java @@ -462,4 +462,8 @@ abstract class SipPhoneBase extends PhoneBase { notifyPhoneStateChanged(); } } + + @Override + protected void onUpdateIccAvailability() { + } } diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java index 5961efd..ab7d561 100644 --- a/src/java/com/android/internal/telephony/uicc/UiccController.java +++ b/src/java/com/android/internal/telephony/uicc/UiccController.java @@ -16,78 +16,151 @@ package com.android.internal.telephony.uicc; +import com.android.internal.telephony.CommandsInterface; import com.android.internal.telephony.IccCard; +import com.android.internal.telephony.IccCardStatus; +import com.android.internal.telephony.IccCardStatus.CardState; import com.android.internal.telephony.PhoneBase; -import com.android.internal.telephony.cdma.CDMALTEPhone; -import com.android.internal.telephony.cdma.CDMAPhone; -import com.android.internal.telephony.gsm.GSMPhone; +import android.os.AsyncResult; +import android.os.Handler; +import android.os.Message; +import android.os.Registrant; +import android.os.RegistrantList; import android.util.Log; /* This class is responsible for keeping all knowledge about * ICCs in the system. It is also used as API to get appropriate * applications to pass them to phone and service trackers. */ -public class UiccController { +public class UiccController extends Handler { private static final boolean DBG = true; private static final String LOG_TAG = "RIL_UiccController"; + private static final int EVENT_ICC_STATUS_CHANGED = 1; + private static final int EVENT_GET_ICC_STATUS_DONE = 2; + private static UiccController mInstance; private PhoneBase mCurrentPhone; - private boolean mIsCurrentCard3gpp; + private CommandsInterface mCi; private IccCard mIccCard; + private boolean mRegisteredWithCi = false; + + private RegistrantList mIccChangedRegistrants = new RegistrantList(); public static synchronized UiccController getInstance(PhoneBase phone) { if (mInstance == null) { mInstance = new UiccController(phone); - } else { + } else if (phone != null) { mInstance.setNewPhone(phone); } return mInstance; } - public IccCard getIccCard() { + // This method is not synchronized as getInstance(PhoneBase) is. + public static UiccController getInstance() { + return getInstance(null); + } + + public synchronized IccCard getIccCard() { return mIccCard; } + //Notifies when card status changes + public void registerForIccChanged(Handler h, int what, Object obj) { + Registrant r = new Registrant (h, what, obj); + mIccChangedRegistrants.add(r); + //Notify registrant right after registering, so that it will get the latest ICC status, + //otherwise which may not happen until there is an actual change in ICC status. + r.notifyRegistrant(); + } + public void unregisterForIccChanged(Handler h) { + mIccChangedRegistrants.remove(h); + } + + @Override + public void handleMessage (Message msg) { + switch (msg.what) { + case EVENT_ICC_STATUS_CHANGED: + if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); + mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); + break; + case EVENT_GET_ICC_STATUS_DONE: + if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); + AsyncResult ar = (AsyncResult)msg.obj; + onGetIccCardStatusDone(ar); + break; + default: + Log.e(LOG_TAG, " Unknown Event " + msg.what); + } + } + private UiccController(PhoneBase phone) { if (DBG) log("Creating UiccController"); setNewPhone(phone); } - private void setNewPhone(PhoneBase phone) { - mCurrentPhone = phone; - if (phone instanceof GSMPhone) { - if (DBG) log("New phone is GSMPhone"); - updateCurrentCard(IccCard.CARD_IS_3GPP); - } else if (phone instanceof CDMALTEPhone){ - if (DBG) log("New phone type is CDMALTEPhone"); - updateCurrentCard(IccCard.CARD_IS_3GPP); - } else if (phone instanceof CDMAPhone){ - if (DBG) log("New phone type is CDMAPhone"); - updateCurrentCard(IccCard.CARD_IS_NOT_3GPP); - } else { - Log.e(LOG_TAG, "Unhandled phone type. Critical error!"); + private synchronized void onGetIccCardStatusDone(AsyncResult ar) { + if (ar.exception != null) { + Log.e(LOG_TAG,"Error getting ICC status. " + + "RIL_REQUEST_GET_ICC_STATUS should " + + "never return an error", ar.exception); + return; } - } - private void updateCurrentCard(boolean isNewCard3gpp) { - if (mIsCurrentCard3gpp == isNewCard3gpp && mIccCard != null) { - return; + IccCardStatus status = (IccCardStatus)ar.result; + + //Update already existing card + if (mIccCard != null && status.getCardState() == CardState.CARDSTATE_PRESENT) { + mIccCard.update(mCurrentPhone, status); } - if (mIccCard != null) { + //Dispose of removed card + if (mIccCard != null && status.getCardState() != CardState.CARDSTATE_PRESENT) { mIccCard.dispose(); mIccCard = null; } - mIsCurrentCard3gpp = isNewCard3gpp; - mIccCard = new IccCard(mCurrentPhone, mCurrentPhone.getPhoneName(), - isNewCard3gpp, DBG); + //Create new card + if (mIccCard == null && status.getCardState() == CardState.CARDSTATE_PRESENT) { + mIccCard = new IccCard(mCurrentPhone, status, mCurrentPhone.getPhoneName(), true); + } + + if (DBG) log("Notifying IccChangedRegistrants"); + mIccChangedRegistrants.notifyRegistrants(); + } + + private void setNewPhone(PhoneBase phone) { + if (phone == null) { + throw new RuntimeException("Phone can't be null in UiccController"); + //return; + } + + if (DBG) log("setNewPhone"); + if (mCurrentPhone != phone) { + if (mIccCard != null) { + // Refresh card if phone changed + // TODO: Remove once card is simplified + if (DBG) log("Disposing card since phone object changed"); + mIccCard.dispose(); + mIccCard = null; + } + sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED)); + mCurrentPhone = phone; + + if (!mRegisteredWithCi) { + // This needs to be done only once after we have valid phone object + mCi = mCurrentPhone.mCM; + mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); + // TODO remove this once modem correctly notifies the unsols + mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null); + mRegisteredWithCi = true; + } + } } private void log(String string) { Log.d(LOG_TAG, string); } -}
\ No newline at end of file +} |