OSDN Git Service

Separate SIM states from Radio states
authorNaveen Kalla <nkalla@quicinc.com>
Thu, 29 Dec 2011 23:07:41 +0000 (15:07 -0800)
committerWink Saville <wink@google.com>
Thu, 29 Dec 2011 23:08:20 +0000 (15:08 -0800)
Radio state reflects the state of the modem. SIM_READY, RUIM_READY,
NV_READY are subscription states and it is possible that the new cards
have multiple subscriptions. Remove the SIM states from Radio State and
introduce a new VOICE_RADIO_TECH message to identify the exact voice
technology. SIM states will continue to be identified from the
SIM_STATUS messages.

Change-Id: Ia67d54f43b6c3340d9cf5c27fcb6f7ef49ef4d40

30 files changed:
packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
telephony/java/android/telephony/ServiceState.java
telephony/java/com/android/internal/telephony/BaseCommands.java
telephony/java/com/android/internal/telephony/CommandsInterface.java
telephony/java/com/android/internal/telephony/DataConnectionTracker.java
telephony/java/com/android/internal/telephony/IccCard.java
telephony/java/com/android/internal/telephony/Phone.java
telephony/java/com/android/internal/telephony/PhoneBase.java
telephony/java/com/android/internal/telephony/PhoneFactory.java
telephony/java/com/android/internal/telephony/PhoneProxy.java
telephony/java/com/android/internal/telephony/RIL.java
telephony/java/com/android/internal/telephony/RILConstants.java
telephony/java/com/android/internal/telephony/ServiceStateTracker.java
telephony/java/com/android/internal/telephony/cat/CatService.java
telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
telephony/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java [new file with mode: 0644]
telephony/java/com/android/internal/telephony/cdma/RuimCard.java
telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
telephony/java/com/android/internal/telephony/gsm/SimCard.java
telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java

index 5a927c6..6e9ea52 100644 (file)
@@ -1515,10 +1515,6 @@ public class DatabaseHelper extends SQLiteOpenHelper {
             loadSetting(stmt, Settings.Secure.CDMA_CELL_BROADCAST_SMS,
                     RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
     
-            // Set the preferred cdma subscription to 0 = Subscription from RUIM, when available
-            loadSetting(stmt, Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION,
-                    RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
-    
             // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
             // persistent system property instead.
             //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
index 2f010e5..32a6975 100644 (file)
@@ -97,6 +97,11 @@ public class ServiceState implements Parcelable {
     public static final int RADIO_TECHNOLOGY_LTE = 14;
     /** @hide */
     public static final int RADIO_TECHNOLOGY_HSPAP = 15;
+    /**
+     * GSM radio technology only supports voice. It does not support data.
+     * @hide
+     */
+    public static final int RADIO_TECHNOLOGY_GSM = 16;
 
     /**
      * Available registration states for GSM, UMTS and CDMA.
@@ -447,6 +452,9 @@ public class ServiceState implements Parcelable {
             case 15:
                 rtString = "HSPAP";
                 break;
+            case 16:
+                rtString = "GSM";
+                break;
             default:
                 rtString = "Unexpected";
                 Log.w(LOG_TAG, "Unexpected radioTechnology=" + rt);
@@ -654,4 +662,28 @@ public class ServiceState implements Parcelable {
     public int getSystemId() {
         return this.mSystemId;
     }
+
+    /** @hide */
+    public static boolean isGsm(int radioTechnology) {
+        return radioTechnology == RADIO_TECHNOLOGY_GPRS
+                || radioTechnology == RADIO_TECHNOLOGY_EDGE
+                || radioTechnology == RADIO_TECHNOLOGY_UMTS
+                || radioTechnology == RADIO_TECHNOLOGY_HSDPA
+                || radioTechnology == RADIO_TECHNOLOGY_HSUPA
+                || radioTechnology == RADIO_TECHNOLOGY_HSPA
+                || radioTechnology == RADIO_TECHNOLOGY_LTE
+                || radioTechnology == RADIO_TECHNOLOGY_HSPAP
+                || radioTechnology == RADIO_TECHNOLOGY_GSM;
+    }
+
+    /** @hide */
+    public static boolean isCdma(int radioTechnology) {
+        return radioTechnology == RADIO_TECHNOLOGY_IS95A
+                || radioTechnology == RADIO_TECHNOLOGY_IS95B
+                || radioTechnology == RADIO_TECHNOLOGY_1xRTT
+                || radioTechnology == RADIO_TECHNOLOGY_EVDO_0
+                || radioTechnology == RADIO_TECHNOLOGY_EVDO_A
+                || radioTechnology == RADIO_TECHNOLOGY_EVDO_B
+                || radioTechnology == RADIO_TECHNOLOGY_EHRPD;
+    }
 }
index 07b6183..893d7a8 100644 (file)
@@ -39,9 +39,6 @@ public abstract class BaseCommands implements CommandsInterface {
     //***** Instance Variables
     protected Context mContext;
     protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
-    protected RadioState mSimState = RadioState.RADIO_UNAVAILABLE;
-    protected RadioState mRuimState = RadioState.RADIO_UNAVAILABLE;
-    protected RadioState mNvState = RadioState.RADIO_UNAVAILABLE;
     protected Object mStateMonitor = new Object();
 
     protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
@@ -49,15 +46,10 @@ public abstract class BaseCommands implements CommandsInterface {
     protected RegistrantList mAvailRegistrants = new RegistrantList();
     protected RegistrantList mOffOrNotAvailRegistrants = new RegistrantList();
     protected RegistrantList mNotAvailRegistrants = new RegistrantList();
-    protected RegistrantList mSIMReadyRegistrants = new RegistrantList();
-    protected RegistrantList mSIMLockedRegistrants = new RegistrantList();
-    protected RegistrantList mRUIMReadyRegistrants = new RegistrantList();
-    protected RegistrantList mRUIMLockedRegistrants = new RegistrantList();
-    protected RegistrantList mNVReadyRegistrants = new RegistrantList();
     protected RegistrantList mCallStateRegistrants = new RegistrantList();
     protected RegistrantList mVoiceNetworkStateRegistrants = new RegistrantList();
     protected RegistrantList mDataNetworkStateRegistrants = new RegistrantList();
-    protected RegistrantList mRadioTechnologyChangedRegistrants = new RegistrantList();
+    protected RegistrantList mVoiceRadioTechChangedRegistrants = new RegistrantList();
     protected RegistrantList mIccStatusChangedRegistrants = new RegistrantList();
     protected RegistrantList mVoicePrivacyOnRegistrants = new RegistrantList();
     protected RegistrantList mVoicePrivacyOffRegistrants = new RegistrantList();
@@ -118,19 +110,6 @@ public abstract class BaseCommands implements CommandsInterface {
         return mState;
     }
 
-    public RadioState getSimState() {
-        return mSimState;
-    }
-
-    public RadioState getRuimState() {
-        return mRuimState;
-    }
-
-    public RadioState getNvState() {
-        return mNvState;
-    }
-
-
     public void registerForRadioStateChanged(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
@@ -217,100 +196,6 @@ public abstract class BaseCommands implements CommandsInterface {
         }
     }
 
-
-    /** Any transition into SIM_READY */
-    public void registerForSIMReady(Handler h, int what, Object obj) {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mSIMReadyRegistrants.add(r);
-
-            if (mSimState.isSIMReady()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void unregisterForSIMReady(Handler h) {
-        synchronized (mStateMonitor) {
-            mSIMReadyRegistrants.remove(h);
-        }
-    }
-
-    /** Any transition into RUIM_READY */
-    public void registerForRUIMReady(Handler h, int what, Object obj) {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mRUIMReadyRegistrants.add(r);
-
-            if (mRuimState.isRUIMReady()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void unregisterForRUIMReady(Handler h) {
-        synchronized(mStateMonitor) {
-            mRUIMReadyRegistrants.remove(h);
-        }
-    }
-
-    /** Any transition into NV_READY */
-    public void registerForNVReady(Handler h, int what, Object obj) {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mNVReadyRegistrants.add(r);
-
-            if (mNvState.isNVReady()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void unregisterForNVReady(Handler h) {
-        synchronized (mStateMonitor) {
-            mNVReadyRegistrants.remove(h);
-        }
-    }
-
-    public void registerForSIMLockedOrAbsent(Handler h, int what, Object obj) {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mSIMLockedRegistrants.add(r);
-
-            if (mSimState == RadioState.SIM_LOCKED_OR_ABSENT) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void unregisterForSIMLockedOrAbsent(Handler h) {
-        synchronized (mStateMonitor) {
-            mSIMLockedRegistrants.remove(h);
-        }
-    }
-
-    public void registerForRUIMLockedOrAbsent(Handler h, int what, Object obj) {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mRUIMLockedRegistrants.add(r);
-
-            if (mRuimState == RadioState.RUIM_LOCKED_OR_ABSENT) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void unregisterForRUIMLockedOrAbsent(Handler h) {
-        synchronized (mStateMonitor) {
-            mRUIMLockedRegistrants.remove(h);
-        }
-    }
-
     public void registerForCallStateChanged(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
@@ -341,13 +226,13 @@ public abstract class BaseCommands implements CommandsInterface {
         mDataNetworkStateRegistrants.remove(h);
     }
 
-    public void registerForRadioTechnologyChanged(Handler h, int what, Object obj) {
+    public void registerForVoiceRadioTechChanged(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
-        mRadioTechnologyChangedRegistrants.add(r);
+        mVoiceRadioTechChangedRegistrants.add(r);
     }
 
-    public void unregisterForRadioTechnologyChanged(Handler h) {
-        mRadioTechnologyChangedRegistrants.remove(h);
+    public void unregisterForVoiceRadioTechChanged(Handler h) {
+        mVoiceRadioTechChangedRegistrants.remove(h);
     }
 
     public void registerForIccStatusChanged(Handler h, int what, Object obj) {
@@ -697,8 +582,7 @@ public abstract class BaseCommands implements CommandsInterface {
      * This function is called only by RIL.java when receiving unsolicited
      * RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
      *
-     * RadioState has 5 values : RADIO_OFF, RADIO_UNAVAILABLE, SIM_NOT_READY,
-     * SIM_LOCKED_OR_ABSENT, and SIM_READY.
+     * RadioState has 3 values : RADIO_OFF, RADIO_UNAVAILABLE, RADIO_ON.
      *
      * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
      */
@@ -719,22 +603,6 @@ public abstract class BaseCommands implements CommandsInterface {
                 return;
             }
 
-            // FIXME: Use Constants or Enums
-            if(mState.getType() == 0) {
-                mSimState = mState;
-                mRuimState = mState;
-                mNvState = mState;
-            }
-            else if (mState.getType() == 1) {
-                mSimState = mState;
-            }
-            else if (mState.getType() == 2) {
-                mRuimState = mState;
-            }
-            else if (mState.getType() == 3) {
-                mNvState = mState;
-            }
-
             mRadioStateChangedRegistrants.notifyRegistrants();
 
             if (mState.isAvailable() && !oldState.isAvailable()) {
@@ -748,30 +616,6 @@ public abstract class BaseCommands implements CommandsInterface {
                 mNotAvailRegistrants.notifyRegistrants();
             }
 
-            if (mState.isSIMReady() && !oldState.isSIMReady()) {
-                Log.d(LOG_TAG,"Notifying: SIM ready");
-                mSIMReadyRegistrants.notifyRegistrants();
-            }
-
-            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
-                Log.d(LOG_TAG,"Notifying: SIM locked or absent");
-                mSIMLockedRegistrants.notifyRegistrants();
-            }
-
-            if (mState.isRUIMReady() && !oldState.isRUIMReady()) {
-                Log.d(LOG_TAG,"Notifying: RUIM ready");
-                mRUIMReadyRegistrants.notifyRegistrants();
-            }
-
-            if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
-                Log.d(LOG_TAG,"Notifying: RUIM locked or absent");
-                mRUIMLockedRegistrants.notifyRegistrants();
-            }
-            if (mState.isNVReady() && !oldState.isNVReady()) {
-                Log.d(LOG_TAG,"Notifying: NV ready");
-                mNVReadyRegistrants.notifyRegistrants();
-            }
-
             if (mState.isOn() && !oldState.isOn()) {
                 Log.d(LOG_TAG,"Notifying: Radio On");
                 mOnRegistrants.notifyRegistrants();
@@ -783,33 +627,6 @@ public abstract class BaseCommands implements CommandsInterface {
                 Log.d(LOG_TAG,"Notifying: radio off or not available");
                 mOffOrNotAvailRegistrants.notifyRegistrants();
             }
-
-            /* Radio Technology Change events
-             * NOTE: isGsm and isCdma have no common states in RADIO_OFF or RADIO_UNAVAILABLE; the
-             *   current phone is determined by mPhoneType
-             * NOTE: at startup no phone have been created and the RIL determines the mPhoneType
-             *   looking based on the networkMode set by the PhoneFactory in the constructor
-             */
-
-            if (mState.isGsm() && oldState.isCdma()) {
-                Log.d(LOG_TAG,"Notifying: radio technology change CDMA to GSM");
-                mRadioTechnologyChangedRegistrants.notifyRegistrants();
-            }
-
-            if (mState.isGsm() && !oldState.isOn() && (mPhoneType == Phone.PHONE_TYPE_CDMA)) {
-                Log.d(LOG_TAG,"Notifying: radio technology change CDMA OFF to GSM");
-                mRadioTechnologyChangedRegistrants.notifyRegistrants();
-            }
-
-            if (mState.isCdma() && oldState.isGsm()) {
-                Log.d(LOG_TAG,"Notifying: radio technology change GSM to CDMA");
-                mRadioTechnologyChangedRegistrants.notifyRegistrants();
-            }
-
-            if (mState.isCdma() && !oldState.isOn() && (mPhoneType == Phone.PHONE_TYPE_GSM)) {
-                Log.d(LOG_TAG,"Notifying: radio technology change GSM OFF to CDMA");
-                mRadioTechnologyChangedRegistrants.notifyRegistrants();
-            }
         }
     }
 
index d6e6ae0..ee39850 100644 (file)
@@ -20,81 +20,24 @@ import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 
 import android.os.Message;
 import android.os.Handler;
+import android.util.Log;
 
 /**
  * {@hide}
  */
 public interface CommandsInterface {
     enum RadioState {
-        RADIO_OFF(0),         /* Radio explictly powered off (eg CFUN=0) */
-        RADIO_UNAVAILABLE(0), /* Radio unavailable (eg, resetting or not booted) */
-        SIM_NOT_READY(1),     /* Radio is on, but the SIM interface is not ready */
-        SIM_LOCKED_OR_ABSENT(1),  /* SIM PIN locked, PUK required, network
-                                     personalization, or SIM absent */
-        SIM_READY(1),         /* Radio is on and SIM interface is available */
-        RUIM_NOT_READY(2),    /* Radio is on, but the RUIM interface is not ready */
-        RUIM_READY(2),        /* Radio is on and the RUIM interface is available */
-        RUIM_LOCKED_OR_ABSENT(2), /* RUIM PIN locked, PUK required, network
-                                     personalization locked, or RUIM absent */
-        NV_NOT_READY(3),      /* Radio is on, but the NV interface is not available */
-        NV_READY(3);          /* Radio is on and the NV interface is available */
+        RADIO_OFF,         /* Radio explicitly powered off (eg CFUN=0) */
+        RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */
+        RADIO_ON;          /* Radio is on */
 
         public boolean isOn() /* and available...*/ {
-            return this == SIM_NOT_READY
-                    || this == SIM_LOCKED_OR_ABSENT
-                    || this == SIM_READY
-                    || this == RUIM_NOT_READY
-                    || this == RUIM_READY
-                    || this == RUIM_LOCKED_OR_ABSENT
-                    || this == NV_NOT_READY
-                    || this == NV_READY;
-        }
-        private int stateType;
-        private RadioState (int type) {
-            stateType = type;
-        }
-
-        public int getType() {
-            return stateType;
+            return this == RADIO_ON;
         }
 
         public boolean isAvailable() {
             return this != RADIO_UNAVAILABLE;
         }
-
-        public boolean isSIMReady() {
-            return this == SIM_READY;
-        }
-
-        public boolean isRUIMReady() {
-            return this == RUIM_READY;
-        }
-
-        public boolean isNVReady() {
-            return this == NV_READY;
-        }
-
-        public boolean isGsm() {
-            if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
-                return false;
-            } else {
-                return this == SIM_NOT_READY
-                        || this == SIM_LOCKED_OR_ABSENT
-                        || this == SIM_READY;
-            }
-        }
-
-        public boolean isCdma() {
-            if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
-                return true;
-            } else {
-                return this ==  RUIM_NOT_READY
-                        || this == RUIM_READY
-                        || this == RUIM_LOCKED_OR_ABSENT
-                        || this == NV_NOT_READY
-                        || this == NV_READY;
-            }
-        }
     }
 
     //***** Constants
@@ -168,11 +111,9 @@ public interface CommandsInterface {
     static final int CDMA_SMS_FAIL_CAUSE_ENCODING_PROBLEM           = 96;
 
     //***** Methods
-
     RadioState getRadioState();
-    RadioState getSimState();
-    RadioState getRuimState();
-    RadioState getNvState();
+
+    void getVoiceRadioTechnology(Message result);
 
     /**
      * Fires on any RadioState transition
@@ -185,6 +126,9 @@ public interface CommandsInterface {
     void registerForRadioStateChanged(Handler h, int what, Object obj);
     void unregisterForRadioStateChanged(Handler h);
 
+    void registerForVoiceRadioTechChanged(Handler h, int what, Object obj);
+    void unregisterForVoiceRadioTechChanged(Handler h);
+
     /**
      * Fires on any transition into RadioState.isOn()
      * Fires immediately if currently in that state
@@ -222,18 +166,8 @@ public interface CommandsInterface {
     void unregisterForOffOrNotAvailable(Handler h);
 
     /**
-     * Fires on any transition into SIM_READY
-     * Fires immediately if if currently in that state
-     * In general, actions should be idempotent. State may change
-     * before event is received.
+     * Fires on any change in ICC status
      */
-    void registerForSIMReady(Handler h, int what, Object obj);
-    void unregisterForSIMReady(Handler h);
-
-    /** Any transition into SIM_LOCKED_OR_ABSENT */
-    void registerForSIMLockedOrAbsent(Handler h, int what, Object obj);
-    void unregisterForSIMLockedOrAbsent(Handler h);
-
     void registerForIccStatusChanged(Handler h, int what, Object obj);
     void unregisterForIccStatusChanged(Handler h);
 
@@ -244,13 +178,6 @@ public interface CommandsInterface {
     void registerForDataNetworkStateChanged(Handler h, int what, Object obj);
     void unregisterForDataNetworkStateChanged(Handler h);
 
-    void registerForRadioTechnologyChanged(Handler h, int what, Object obj);
-    void unregisterForRadioTechnologyChanged(Handler h);
-    void registerForNVReady(Handler h, int what, Object obj);
-    void unregisterForNVReady(Handler h);
-    void registerForRUIMLockedOrAbsent(Handler h, int what, Object obj);
-    void unregisterForRUIMLockedOrAbsent(Handler h);
-
     /** InCall voice privacy notifications */
     void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj);
     void unregisterForInCallVoicePrivacyOn(Handler h);
@@ -258,15 +185,6 @@ public interface CommandsInterface {
     void unregisterForInCallVoicePrivacyOff(Handler h);
 
     /**
-     * Fires on any transition into RUIM_READY
-     * Fires immediately if if currently in that state
-     * In general, actions should be idempotent. State may change
-     * before event is received.
-     */
-    void registerForRUIMReady(Handler h, int what, Object obj);
-    void unregisterForRUIMReady(Handler h);
-
-    /**
      * unlike the register* methods, there's only one new 3GPP format SMS handler.
      * if you need to unregister, you should also tell the radio to stop
      * sending SMS's to you (via AT+CNMI)
index 6d9a2c2..0c2e17c 100644 (file)
@@ -121,7 +121,7 @@ public abstract class DataConnectionTracker extends Handler {
     protected static final int EVENT_DO_RECOVERY = BASE + 18;
     protected static final int EVENT_APN_CHANGED = BASE + 19;
     protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
-    protected static final int EVENT_NV_READY = BASE + 21;
+    protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = BASE + 21;
     protected static final int EVENT_PS_RESTRICT_ENABLED = BASE + 22;
     protected static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
     public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
index 955849d..f4308a0 100644 (file)
@@ -36,7 +36,7 @@ import android.view.WindowManager;
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.CommandsInterface.RadioState;
 import com.android.internal.telephony.gsm.SIMRecords;
-
+import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
 import android.os.SystemProperties;
 
 import com.android.internal.R;
@@ -50,10 +50,17 @@ public abstract class IccCard {
 
     private IccCardStatus mIccCardStatus = null;
     protected State mState = null;
+    private final Object mStateMonitor = new Object();
+
+    protected boolean is3gpp = true;
+    protected boolean isSubscriptionFromIccCard = true;
+    protected CdmaSubscriptionSourceManager mCdmaSSM = null;
     protected PhoneBase mPhone;
     private RegistrantList mAbsentRegistrants = new RegistrantList();
     private RegistrantList mPinLockedRegistrants = new RegistrantList();
     private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
+    protected RegistrantList mReadyRegistrants = new RegistrantList();
+    protected RegistrantList mRuimReadyRegistrants = new RegistrantList();
 
     private boolean mDesiredPinLocked;
     private boolean mDesiredFdnEnabled;
@@ -88,7 +95,7 @@ public abstract class IccCard {
     static public final String INTENT_VALUE_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED";
 
 
-    protected static final int EVENT_ICC_LOCKED_OR_ABSENT = 1;
+    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;
@@ -102,6 +109,8 @@ public abstract class IccCard {
     private static final int EVENT_ICC_STATUS_CHANGED = 12;
     private static final int EVENT_CARD_REMOVED = 13;
     private static final int EVENT_CARD_ADDED = 14;
+    protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 15;
+    protected static final int EVENT_RADIO_ON = 16;
 
     /*
       UNKNOWN is a transient state, for example, after uesr inputs ICC pin under
@@ -138,30 +147,25 @@ public abstract class IccCard {
                  */
                 case RADIO_OFF:
                 case RADIO_UNAVAILABLE:
-                case SIM_NOT_READY:
-                case RUIM_NOT_READY:
                     return State.UNKNOWN;
-                case SIM_LOCKED_OR_ABSENT:
-                case RUIM_LOCKED_OR_ABSENT:
-                    //this should be transient-only
-                    return State.UNKNOWN;
-                case SIM_READY:
-                case RUIM_READY:
-                case NV_READY:
-                    return State.READY;
-                case NV_NOT_READY:
-                    return State.ABSENT;
+                default:
+                    if (!is3gpp && !isSubscriptionFromIccCard) {
+                        // CDMA can get subscription from NV. In that case,
+                        // subscription is ready as soon as Radio is ON.
+                        return State.READY;
+                    }
             }
         } else {
             return mState;
         }
 
-        Log.e(mLogTag, "IccCard.getState(): case should never be reached");
         return State.UNKNOWN;
     }
 
     public IccCard(PhoneBase phone, String logTag, Boolean dbg) {
         mPhone = phone;
+        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);
         mLogTag = logTag;
         mDbg = dbg;
@@ -169,6 +173,8 @@ public abstract class IccCard {
 
     public void dispose() {
         mPhone.mCM.unregisterForIccStatusChanged(mHandler);
+        mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
+        mPhone.mCM.unregisterForOn(mHandler);
     }
 
     protected void finalize() {
@@ -226,6 +232,49 @@ public abstract class IccCard {
         mPinLockedRegistrants.remove(h);
     }
 
+    public void registerForReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mReadyRegistrants.add(r);
+
+            if (getState() == State.READY) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForReady(Handler h) {
+        synchronized (mStateMonitor) {
+            mReadyRegistrants.remove(h);
+        }
+    }
+
+    public State getRuimState() {
+        if(mIccCardStatus != null) {
+            return getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
+        } else {
+            return State.UNKNOWN;
+        }
+    }
+
+    public void registerForRuimReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mRuimReadyRegistrants.add(r);
+
+            if (getState() == State.READY && getRuimState() == State.READY ) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForRuimReady(Handler h) {
+        synchronized (mStateMonitor) {
+            mRuimReadyRegistrants.remove(h);
+        }
+    }
 
     /**
      * Supply the ICC PIN to the ICC
@@ -423,13 +472,25 @@ public abstract class IccCard {
         boolean isIccCardAdded;
 
         State oldState, newState;
+        State oldRuimState = getRuimState();
 
         oldState = mState;
         mIccCardStatus = newCardStatus;
         newState = getIccCardState();
-        mState = newState;
 
-        updateStateProperty();
+        synchronized (mStateMonitor) {
+            mState = newState;
+            updateStateProperty();
+            if (oldState != State.READY && newState == State.READY) {
+                mHandler.sendMessage(mHandler.obtainMessage(EVENT_ICC_READY));
+                mReadyRegistrants.notifyRegistrants();
+            } else if (newState.isPinLocked()) {
+                mHandler.sendMessage(mHandler.obtainMessage(EVENT_ICC_LOCKED));
+            }
+            if (oldRuimState != State.READY && getRuimState() == State.READY) {
+                mRuimReadyRegistrants.notifyRegistrants();
+            }
+        }
 
         transitionedIntoPinLocked = (
                  (oldState != State.PIN_REQUIRED && newState == State.PIN_REQUIRED)
@@ -584,22 +645,30 @@ public abstract class IccCard {
                     updateStateProperty();
                     broadcastIccStateChangedIntent(INTENT_VALUE_ICC_NOT_READY, null);
                     break;
-                case EVENT_ICC_READY:
-                    //TODO: put facility read in SIM_READY now, maybe in REG_NW
+                case EVENT_RADIO_ON:
+                    if (!is3gpp) {
+                        handleCdmaSubscriptionSource();
+                    }
                     mPhone.mCM.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
-                    mPhone.mCM.queryFacilityLock (
-                            CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
-                            obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
-                    mPhone.mCM.queryFacilityLock (
-                            CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX,
-                            obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
                     break;
-                case EVENT_ICC_LOCKED_OR_ABSENT:
-                    mPhone.mCM.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
-                    mPhone.mCM.queryFacilityLock (
-                            CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
-                            obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
+                case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
+                    handleCdmaSubscriptionSource();
+                    break;
+                case EVENT_ICC_READY:
+                    if(isSubscriptionFromIccCard) {
+                        mPhone.mCM.queryFacilityLock (
+                                CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
+                                obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
+                        mPhone.mCM.queryFacilityLock (
+                                CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX,
+                                obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
+                    }
                     break;
+                case EVENT_ICC_LOCKED:
+                    mPhone.mCM.queryFacilityLock (
+                             CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
+                             obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
+                     break;
                 case EVENT_GET_ICC_STATUS_DONE:
                     ar = (AsyncResult)msg.obj;
 
@@ -689,7 +758,30 @@ public abstract class IccCard {
         }
     };
 
+    private void handleCdmaSubscriptionSource() {
+        if(mCdmaSSM != null)  {
+            int newSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource();
+
+            Log.d(mLogTag, "Received Cdma subscription source: " + newSubscriptionSource);
+
+            boolean isNewSubFromRuim =
+                (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
+
+            if (isNewSubFromRuim != isSubscriptionFromIccCard) {
+                isSubscriptionFromIccCard = isNewSubFromRuim;
+                // Parse the Stored IccCardStatus Message to set mState correctly.
+                handleIccCardStatus(mIccCardStatus);
+            }
+        }
+    }
+
     public State getIccCardState() {
+        if(!is3gpp && !isSubscriptionFromIccCard) {
+            // CDMA can get subscription from NV. In that case,
+            // subscription is ready as soon as Radio is ON.
+            return State.READY;
+        }
+
         if (mIccCardStatus == null) {
             Log.e(mLogTag, "[IccCard] IccCardStatus is null");
             return IccCard.State.ABSENT;
@@ -703,19 +795,11 @@ public abstract class IccCard {
         RadioState currentRadioState = mPhone.mCM.getRadioState();
         // check radio technology
         if( currentRadioState == RadioState.RADIO_OFF         ||
-            currentRadioState == RadioState.RADIO_UNAVAILABLE ||
-            currentRadioState == RadioState.SIM_NOT_READY     ||
-            currentRadioState == RadioState.RUIM_NOT_READY    ||
-            currentRadioState == RadioState.NV_NOT_READY      ||
-            currentRadioState == RadioState.NV_READY) {
+            currentRadioState == RadioState.RADIO_UNAVAILABLE) {
             return IccCard.State.NOT_READY;
         }
 
-        if( currentRadioState == RadioState.SIM_LOCKED_OR_ABSENT  ||
-            currentRadioState == RadioState.SIM_READY             ||
-            currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
-            currentRadioState == RadioState.RUIM_READY) {
-
+        if( currentRadioState == RadioState.RADIO_ON ) {
             State csimState =
                 getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
             State usimState =
@@ -730,8 +814,7 @@ public abstract class IccCard {
             }
 
             // check for CDMA radio technology
-            if (currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
-                currentRadioState == RadioState.RUIM_READY) {
+            if (!is3gpp) {
                 return csimState;
             }
             return usimState;
index 9d189c1..d41ce4d 100644 (file)
@@ -1772,4 +1772,15 @@ public interface Phone {
      * @return an interface to the UsimServiceTable record, or null if not available
      */
     UsimServiceTable getUsimServiceTable();
+
+    /**
+     * Unregister from all events it registered for and dispose objects
+     * created by this object.
+     */
+    void dispose();
+
+    /**
+     * Remove references to external object stored in this object.
+     */
+    void removeReferences();
 }
index 94f7a13..49f64c9 100644 (file)
@@ -103,6 +103,7 @@ public abstract class PhoneBase extends Handler implements Phone {
     protected static final int EVENT_SET_ENHANCED_VP                = 24;
     protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
     protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
+    protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 27;
 
     // Key used to read/write current CLIR setting
     public static final String CLIR_KEY = "clir_key";
@@ -262,6 +263,10 @@ public abstract class PhoneBase extends Handler implements Phone {
     public void removeReferences() {
         mSmsStorageMonitor = null;
         mSmsUsageMonitor = null;
+        mSMS = null;
+        mIccRecords = null;
+        mIccCard = null;
+        mDataConnectionTracker = null;
     }
 
     /**
index 74bae44..f495d7e 100644 (file)
@@ -25,6 +25,7 @@ import android.os.SystemProperties;
 
 import com.android.internal.telephony.cdma.CDMAPhone;
 import com.android.internal.telephony.cdma.CDMALTEPhone;
+import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
 import com.android.internal.telephony.gsm.GSMPhone;
 import com.android.internal.telephony.sip.SipPhone;
 import com.android.internal.telephony.sip.SipPhoneFactory;
@@ -47,7 +48,8 @@ public class PhoneFactory {
     static private Looper sLooper;
     static private Context sContext;
 
-    static final int preferredCdmaSubscription = RILConstants.PREFERRED_CDMA_SUBSCRIPTION;
+    static final int preferredCdmaSubscription =
+                         CdmaSubscriptionSourceManager.PREFERRED_CDMA_SUBSCRIPTION;
 
     //***** Class Methods
 
@@ -114,11 +116,11 @@ public class PhoneFactory {
                 int lteOnCdma = BaseCommands.getLteOnCdmaModeStatic();
                 switch (lteOnCdma) {
                     case Phone.LTE_ON_CDMA_FALSE:
-                        cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_NV;
+                        cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV;
                         Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV");
                         break;
                     case Phone.LTE_ON_CDMA_TRUE:
-                        cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_RUIM;
+                        cdmaSubscription = CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM;
                         Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM");
                         break;
                     case Phone.LTE_ON_CDMA_UNKNOWN:
index 60f364e..2931a02 100644 (file)
@@ -22,6 +22,7 @@ import android.content.Context;
 import android.content.Intent;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
+import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemProperties;
@@ -35,6 +36,7 @@ import com.android.internal.telephony.gsm.GSMPhone;
 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.CallManager;
 
 import java.util.List;
 
@@ -42,7 +44,6 @@ public class PhoneProxy extends Handler implements Phone {
     public final static Object lockForRadioTechnologyChange = new Object();
 
     private Phone mActivePhone;
-    private String mOutgoingPhone;
     private CommandsInterface mCommandsInterface;
     private IccSmsInterfaceManagerProxy mIccSmsInterfaceManagerProxy;
     private IccPhoneBookInterfaceManagerProxy mIccPhoneBookInterfaceManagerProxy;
@@ -50,7 +51,13 @@ public class PhoneProxy extends Handler implements Phone {
 
     private boolean mResetModemOnRadioTechnologyChange = false;
 
-    private static final int EVENT_RADIO_TECHNOLOGY_CHANGED = 1;
+    private int mRilVersion;
+
+    private static final int EVENT_VOICE_RADIO_TECH_CHANGED = 1;
+    private static final int EVENT_RADIO_ON = 2;
+    private static final int EVENT_REQUEST_VOICE_RADIO_TECH_DONE = 3;
+    private static final int EVENT_RIL_CONNECTED = 4;
+
     private static final String LOG_TAG = "PHONE";
 
     //***** Class Methods
@@ -64,89 +71,181 @@ public class PhoneProxy extends Handler implements Phone {
                 phone.getIccPhoneBookInterfaceManager());
         mPhoneSubInfoProxy = new PhoneSubInfoProxy(phone.getPhoneSubInfo());
         mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
-        mCommandsInterface.registerForRadioTechnologyChanged(
-                this, EVENT_RADIO_TECHNOLOGY_CHANGED, null);
+
+        mCommandsInterface.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
+        mCommandsInterface.registerForOn(this, EVENT_RADIO_ON, null);
+        mCommandsInterface.registerForVoiceRadioTechChanged(
+                             this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
     }
 
     @Override
     public void handleMessage(Message msg) {
+        AsyncResult ar = (AsyncResult) msg.obj;
         switch(msg.what) {
-        case EVENT_RADIO_TECHNOLOGY_CHANGED:
-            //switch Phone from CDMA to GSM or vice versa
-            mOutgoingPhone = mActivePhone.getPhoneName();
-            logd("Switching phone from " + mOutgoingPhone + "Phone to " +
-                    (mOutgoingPhone.equals("GSM") ? "CDMAPhone" : "GSMPhone") );
-            boolean oldPowerState = false; // old power state to off
-            if (mResetModemOnRadioTechnologyChange) {
-                if (mCommandsInterface.getRadioState().isOn()) {
-                    oldPowerState = true;
-                    logd("Setting Radio Power to Off");
-                    mCommandsInterface.setRadioPower(false, null);
-                }
+        case EVENT_RADIO_ON:
+            /* Proactively query voice radio technologies */
+            mCommandsInterface.getVoiceRadioTechnology(
+                    this.obtainMessage(EVENT_REQUEST_VOICE_RADIO_TECH_DONE));
+            break;
+
+        case EVENT_RIL_CONNECTED:
+            if (ar.exception == null && ar.result != null) {
+                mRilVersion = (Integer) ar.result;
+            } else {
+                logd("Unexpected exception on EVENT_RIL_CONNECTED");
+                mRilVersion = -1;
             }
+            break;
 
-            if(mOutgoingPhone.equals("GSM")) {
-                logd("Make a new CDMAPhone and destroy the old GSMPhone.");
+        case EVENT_VOICE_RADIO_TECH_CHANGED:
+        case EVENT_REQUEST_VOICE_RADIO_TECH_DONE:
 
-                ((GSMPhone)mActivePhone).dispose();
-                Phone oldPhone = mActivePhone;
+            if (ar.exception == null) {
+                if ((ar.result != null) && (((int[]) ar.result).length != 0)) {
+                    int newVoiceTech = ((int[]) ar.result)[0];
+                    updatePhoneObject(newVoiceTech);
+                } else {
+                    loge("Voice Radio Technology event " + msg.what + " has no tech!");
+                }
+            } else {
+                loge("Voice Radio Technology event " + msg.what + " exception!" + ar.exception);
+            }
+            break;
 
-                //Give the garbage collector a hint to start the garbage collection asap
-                // NOTE this has been disabled since radio technology change could happen during
-                //   e.g. a multimedia playing and could slow the system. Tests needs to be done
-                //   to see the effects of the GC call here when system is busy.
-                //System.gc();
+        default:
+            loge("Error! This handler was not registered for this message type. Message: "
+                    + msg.what);
+            break;
+        }
+        super.handleMessage(msg);
+    }
 
-                mActivePhone = PhoneFactory.getCdmaPhone();
-                ((GSMPhone)oldPhone).removeReferences();
-                oldPhone = null;
-            } else {
-                logd("Make a new GSMPhone and destroy the old CDMAPhone.");
+    private static void logd(String msg) {
+        Log.d(LOG_TAG, "[PhoneProxy] " + msg);
+    }
 
-                ((CDMAPhone)mActivePhone).dispose();
-                //mActivePhone = null;
-                Phone oldPhone = mActivePhone;
+    private void logw(String msg) {
+        Log.w(LOG_TAG, "[PhoneProxy] " + msg);
+    }
 
-                // Give the GC a hint to start the garbage collection asap
-                // NOTE this has been disabled since radio technology change could happen during
-                //   e.g. a multimedia playing and could slow the system. Tests needs to be done
-                //   to see the effects of the GC call here when system is busy.
-                //System.gc();
+    private void loge(String msg) {
+        Log.e(LOG_TAG, "[PhoneProxy] " + msg);
+    }
 
-                mActivePhone = PhoneFactory.getGsmPhone();
-                ((CDMAPhone)oldPhone).removeReferences();
-                oldPhone = null;
+    private void updatePhoneObject(int newVoiceRadioTech) {
+
+        if (mActivePhone != null) {
+            if(mRilVersion == 6 && getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+                /*
+                 * On v6 RIL, when LTE_ON_CDMA is TRUE, always create CDMALTEPhone
+                 * irrespective of the voice radio tech reported.
+                 */
+                if (mActivePhone.getPhoneType() == PHONE_TYPE_CDMA) {
+                    logd("LTE ON CDMA property is set. Use CDMA Phone" +
+                            " newVoiceRadioTech = " + newVoiceRadioTech +
+                            " Active Phone = " + mActivePhone.getPhoneName());
+                    return;
+                } else {
+                    logd("LTE ON CDMA property is set. Switch to CDMALTEPhone" +
+                            " newVoiceRadioTech = " + newVoiceRadioTech +
+                            " Active Phone = " + mActivePhone.getPhoneName());
+                    newVoiceRadioTech = ServiceState.RADIO_TECHNOLOGY_1xRTT;
+                }
+            } else {
+                if ((ServiceState.isCdma(newVoiceRadioTech) &&
+                        mActivePhone.getPhoneType() == PHONE_TYPE_CDMA) ||
+                        (ServiceState.isGsm(newVoiceRadioTech) &&
+                                mActivePhone.getPhoneType() == PHONE_TYPE_GSM)) {
+                    // Nothing changed. Keep phone as it is.
+                    logd("Ignoring voice radio technology changed message." +
+                            " newVoiceRadioTech = " + newVoiceRadioTech +
+                            " Active Phone = " + mActivePhone.getPhoneName());
+                    return;
+                }
             }
+        }
+
+        if (newVoiceRadioTech == ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
+            // We need some voice phone object to be active always, so never
+            // delete the phone without anything to replace it with!
+            logd("Ignoring voice radio technology changed message. newVoiceRadioTech = Unknown."
+                    + " Active Phone = " + mActivePhone.getPhoneName());
+            return;
+        }
 
-            if (mResetModemOnRadioTechnologyChange) {
-                logd("Resetting Radio");
-                mCommandsInterface.setRadioPower(oldPowerState, null);
+        boolean oldPowerState = false; // old power state to off
+        if (mResetModemOnRadioTechnologyChange) {
+            if (mCommandsInterface.getRadioState().isOn()) {
+                oldPowerState = true;
+                logd("Setting Radio Power to Off");
+                mCommandsInterface.setRadioPower(false, null);
             }
+        }
 
-            //Set the new interfaces in the proxy's
-            mIccSmsInterfaceManagerProxy.setmIccSmsInterfaceManager(
-                    mActivePhone.getIccSmsInterfaceManager());
-            mIccPhoneBookInterfaceManagerProxy.setmIccPhoneBookInterfaceManager(
-                    mActivePhone.getIccPhoneBookInterfaceManager());
-            mPhoneSubInfoProxy.setmPhoneSubInfo(this.mActivePhone.getPhoneSubInfo());
-            mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
-
-            //Send an Intent to the PhoneApp that we had a radio technology change
-            Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
-            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-            intent.putExtra(Phone.PHONE_NAME_KEY, mActivePhone.getPhoneName());
-            ActivityManagerNative.broadcastStickyIntent(intent, null);
-            break;
-        default:
-            Log.e(LOG_TAG,"Error! This handler was not registered for this message type. Message: "
-                    + msg.what);
-        break;
+        deleteAndCreatePhone(newVoiceRadioTech);
+
+        if (mResetModemOnRadioTechnologyChange && oldPowerState) { // restore power state
+            logd("Resetting Radio");
+            mCommandsInterface.setRadioPower(oldPowerState, null);
         }
-        super.handleMessage(msg);
+
+        // Set the new interfaces in the proxy's
+        mIccSmsInterfaceManagerProxy.setmIccSmsInterfaceManager(
+                mActivePhone.getIccSmsInterfaceManager());
+        mIccPhoneBookInterfaceManagerProxy.setmIccPhoneBookInterfaceManager(mActivePhone
+                .getIccPhoneBookInterfaceManager());
+        mPhoneSubInfoProxy.setmPhoneSubInfo(this.mActivePhone.getPhoneSubInfo());
+
+        mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
+
+        // Send an Intent to the PhoneApp that we had a radio technology change
+        Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        intent.putExtra(Phone.PHONE_NAME_KEY, mActivePhone.getPhoneName());
+        ActivityManagerNative.broadcastStickyIntent(intent, null);
+
     }
 
-    private static void logd(String msg) {
-        Log.d(LOG_TAG, "[PhoneProxy] " + msg);
+    private void deleteAndCreatePhone(int newVoiceRadioTech) {
+
+        String outgoingPhoneName = "Unknown";
+        Phone oldPhone = mActivePhone;
+
+        if (oldPhone != null) {
+            outgoingPhoneName = ((PhoneBase) oldPhone).getPhoneName();
+        }
+
+        logd("Switching Voice Phone : " + outgoingPhoneName + " >>> "
+                + (ServiceState.isGsm(newVoiceRadioTech) ? "GSM" : "CDMA"));
+
+        if (oldPhone != null) {
+            CallManager.getInstance().unregisterPhone(oldPhone);
+            logd("Disposing old phone..");
+            oldPhone.dispose();
+        }
+
+        // Give the garbage collector a hint to start the garbage collection
+        // asap NOTE this has been disabled since radio technology change could
+        // happen during e.g. a multimedia playing and could slow the system.
+        // Tests needs to be done to see the effects of the GC call here when
+        // system is busy.
+        // System.gc();
+
+        if (ServiceState.isCdma(newVoiceRadioTech)) {
+            mActivePhone = PhoneFactory.getCdmaPhone();
+        } else if (ServiceState.isGsm(newVoiceRadioTech)) {
+            mActivePhone = PhoneFactory.getGsmPhone();
+        }
+
+        if (oldPhone != null) {
+            oldPhone.removeReferences();
+        }
+
+        if(mActivePhone != null) {
+            CallManager.getInstance().registerPhone(mActivePhone);
+        }
+
+        oldPhone = null;
     }
 
     public ServiceState getServiceState() {
@@ -859,4 +958,15 @@ public class PhoneProxy extends Handler implements Phone {
     public UsimServiceTable getUsimServiceTable() {
         return mActivePhone.getUsimServiceTable();
     }
+
+    public void dispose() {
+        mCommandsInterface.unregisterForOn(this);
+        mCommandsInterface.unregisterForVoiceRadioTechChanged(this);
+        mCommandsInterface.unregisterForRilConnected(this);
+    }
+
+    public void removeReferences() {
+        mActivePhone = null;
+        mCommandsInterface = null;
+    }
 }
index f2e7f45..718a4fd 100644 (file)
@@ -644,6 +644,15 @@ public final class RIL extends BaseCommands implements CommandsInterface {
 
     //***** CommandsInterface implementation
 
+    public void getVoiceRadioTechnology(Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_VOICE_RADIO_TECH, result);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+
     @Override public void
     setOnNITZTime(Handler h, int what, Object obj) {
         super.setOnNITZTime(h, what, obj);
@@ -2020,14 +2029,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
         switch(stateInt) {
             case 0: state = RadioState.RADIO_OFF; break;
             case 1: state = RadioState.RADIO_UNAVAILABLE; break;
-            case 2: state = RadioState.SIM_NOT_READY; break;
-            case 3: state = RadioState.SIM_LOCKED_OR_ABSENT; break;
-            case 4: state = RadioState.SIM_READY; break;
-            case 5: state = RadioState.RUIM_NOT_READY; break;
-            case 6: state = RadioState.RUIM_READY; break;
-            case 7: state = RadioState.RUIM_LOCKED_OR_ABSENT; break;
-            case 8: state = RadioState.NV_NOT_READY; break;
-            case 9: state = RadioState.NV_READY; break;
+            case 10: state = RadioState.RADIO_ON; break;
 
             default:
                 throw new RuntimeException(
@@ -2286,6 +2288,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_REQUEST_ISIM_AUTHENTICATION: ret =  responseString(p); break;
             case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU: ret = responseVoid(p); break;
             case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: ret = responseICC_IO(p); break;
+            case RIL_REQUEST_VOICE_RADIO_TECH: ret = responseInts(p); break;
             default:
                 throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
             //break;
@@ -2434,6 +2437,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_UNSOl_CDMA_PRL_CHANGED: ret = responseInts(p); break;
             case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
             case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;
+            case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: ret =  responseInts(p); break;
 
             default:
                 throw new RuntimeException("Unrecognized unsol response: " + response);
@@ -2738,6 +2742,15 @@ public final class RIL extends BaseCommands implements CommandsInterface {
                 }
                 break;
 
+            case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED:
+                if (RILJ_LOGD) unsljLogRet(response, ret);
+
+                if (mVoiceRadioTechChangedRegistrants != null) {
+                    mVoiceRadioTechChangedRegistrants.notifyRegistrants(
+                            new AsyncResult(null, ret, null));
+                }
+                break;
+
             case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
                 if (RILJ_LOGD) unsljLogRet(response, ret);
 
@@ -3495,6 +3508,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_REQUEST_ISIM_AUTHENTICATION: return "RIL_REQUEST_ISIM_AUTHENTICATION";
             case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU: return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU";
             case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS";
+            case RIL_REQUEST_VOICE_RADIO_TECH: return "RIL_REQUEST_VOICE_RADIO_TECH";
             default: return "<unknown request>";
         }
     }
@@ -3543,6 +3557,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
             case RIL_UNSOl_CDMA_PRL_CHANGED: return "UNSOL_CDMA_PRL_CHANGED";
             case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
             case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED";
+            case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: return "UNSOL_VOICE_RADIO_TECH_CHANGED";
             default: return "<unknown reponse>";
         }
     }
index ba9d07a..f501b21 100644 (file)
@@ -75,11 +75,6 @@ public interface RILConstants {
 
     int PREFERRED_NETWORK_MODE      = NETWORK_MODE_WCDMA_PREF;
 
-    /* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
-    int SUBSCRIPTION_FROM_RUIM      = 0; /* CDMA subscription from RUIM when available */
-    int SUBSCRIPTION_FROM_NV        = 1; /* CDMA subscription from NV */
-    int PREFERRED_CDMA_SUBSCRIPTION = SUBSCRIPTION_FROM_NV;
-
     int CDMA_CELL_BROADCAST_SMS_DISABLED = 1;
     int CDMA_CELL_BROADCAST_SMS_ENABLED  = 0;
 
@@ -264,6 +259,7 @@ cat include/telephony/ril.h | \
     int RIL_REQUEST_ISIM_AUTHENTICATION = 105;
     int RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU = 106;
     int RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS = 107;
+    int RIL_REQUEST_VOICE_RADIO_TECH = 108;
     int RIL_UNSOL_RESPONSE_BASE = 1000;
     int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
     int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
@@ -300,4 +296,5 @@ cat include/telephony/ril.h | \
     int RIL_UNSOl_CDMA_PRL_CHANGED = 1032;
     int RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE = 1033;
     int RIL_UNSOL_RIL_CONNECTED = 1034;
+    int RIL_UNSOL_VOICE_RADIO_TECH_CHANGED = 1035;
 }
index 1b3ee1e..9c80de7 100644 (file)
@@ -124,6 +124,10 @@ public abstract class ServiceStateTracker extends Handler {
     protected static final int EVENT_ERI_FILE_LOADED                   = 36;
     protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE       = 37;
     protected static final int EVENT_SET_RADIO_POWER_OFF               = 38;
+    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 String TIMEZONE_PROPERTY = "persist.sys.timezone";
 
index 5a994f3..000bfac 100644 (file)
@@ -120,9 +120,7 @@ public class CatService extends Handler implements AppInterface {
         mIccRecords = ir;
 
         // Register for SIM ready event.
-        mCmdIf.registerForSIMReady(this, MSG_ID_SIM_READY, null);
-        mCmdIf.registerForRUIMReady(this, MSG_ID_SIM_READY, null);
-        mCmdIf.registerForNVReady(this, MSG_ID_SIM_READY, null);
+        ic.registerForReady(this, MSG_ID_SIM_READY, null);
         mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
 
         CatLog.d(this, "Is running");
index 8534810..54e651a 100644 (file)
@@ -79,10 +79,12 @@ public class CDMALTEPhone extends CDMAPhone {
 
     @Override
     protected void initSstIcc() {
-        mSST = new CdmaLteServiceStateTracker(this);
-        mIccRecords = new CdmaLteUiccRecords(this);
         mIccCard = new SimCard(this, LOG_TAG, DBG);
+        mIccRecords = new CdmaLteUiccRecords(this);
         mIccFileHandler = new CdmaLteUiccFileHandler(this);
+        // CdmaLteServiceStateTracker registers with IccCard to know
+        // when the card is ready. So create mIccCard before the ServiceStateTracker
+        mSST = new CdmaLteServiceStateTracker(this);
     }
 
     @Override
index 58e3e5f..d25291d 100755 (executable)
@@ -93,17 +93,16 @@ public class CDMAPhone extends PhoneBase {
     // Instance Variables
     CdmaCallTracker mCT;
     CdmaServiceStateTracker mSST;
+    CdmaSubscriptionSourceManager mCdmaSSM;
     ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>();
     RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
     RuimSmsInterfaceManager mRuimSmsInterfaceManager;
+    int mCdmaSubscriptionSource = CdmaSubscriptionSourceManager.SUBSCRIPTION_SOURCE_UNKNOWN;
     PhoneSubInfo mSubInfo;
     EriManager mEriManager;
     WakeLock mWakeLock;
     CatService mCcatService;
 
-    // mNvLoadedRegistrants are informed after the EVENT_NV_READY
-    private final RegistrantList mNvLoadedRegistrants = new RegistrantList();
-
     // mEriFileLoadedRegistrants are informed after the ERI text has been loaded
     private final RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
 
@@ -149,15 +148,19 @@ public class CDMAPhone extends PhoneBase {
     }
 
     protected void initSstIcc() {
-        mSST = new CdmaServiceStateTracker(this);
-        mIccRecords = new RuimRecords(this);
         mIccCard = new RuimCard(this, LOG_TAG, DBG);
+        mIccRecords = new RuimRecords(this);
         mIccFileHandler = new RuimFileHandler(this);
+        // CdmaServiceStateTracker registers with IccCard to know
+        // when the Ruim card is ready. So create mIccCard before the ServiceStateTracker
+        mSST = new CdmaServiceStateTracker(this);
     }
 
     protected void init(Context context, PhoneNotifier notifier) {
         mCM.setPhoneType(Phone.PHONE_TYPE_CDMA);
         mCT = new CdmaCallTracker(this);
+        mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, mCM, this,
+                EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
         mSMS = new CdmaSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);
         mDataConnectionTracker = new CdmaDataConnectionTracker (this);
         mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
@@ -173,7 +176,6 @@ public class CDMAPhone extends PhoneBase {
         mCM.registerForOn(this, EVENT_RADIO_ON, null);
         mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
         mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
-        mCM.registerForNVReady(this, EVENT_NV_READY, null);
         mCM.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
 
         PowerManager pm
@@ -225,7 +227,6 @@ public class CDMAPhone extends PhoneBase {
             mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
             mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
             mCM.unregisterForOn(this); //EVENT_RADIO_ON
-            mCM.unregisterForNVReady(this); //EVENT_NV_READY
             mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
             mCM.unSetOnSuppServiceNotification(this);
             removeCallbacks(mExitEcmRunnable);
@@ -236,6 +237,7 @@ public class CDMAPhone extends PhoneBase {
             mCT.dispose();
             mDataConnectionTracker.dispose();
             mSST.dispose();
+            mCdmaSSM.dispose(this);
             mSMS.dispose();
             mIccFileHandler.dispose(); // instance of RuimFileHandler
             mIccRecords.dispose();
@@ -254,12 +256,8 @@ public class CDMAPhone extends PhoneBase {
         super.removeReferences();
         mRuimPhoneBookInterfaceManager = null;
         mRuimSmsInterfaceManager = null;
-        mSMS = null;
         mSubInfo = null;
-        mIccRecords = null;
         mIccFileHandler = null;
-        mIccCard = null;
-        mDataConnectionTracker = null;
         mCT = null;
         mSST = null;
         mEriManager = null;
@@ -1018,6 +1016,13 @@ public class CDMAPhone extends PhoneBase {
 
             case EVENT_RADIO_ON:{
                 Log.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
+                handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
+            }
+            break;
+
+            case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:{
+                Log.d(LOG_TAG, "EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED");
+                handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
             }
             break;
 
@@ -1033,8 +1038,6 @@ public class CDMAPhone extends PhoneBase {
 
             case EVENT_NV_READY:{
                 Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
-                //Inform the Service State Tracker
-                mNvLoadedRegistrants.notifyRegistrants();
                 prepareEri();
             }
             break;
@@ -1060,6 +1063,21 @@ public class CDMAPhone extends PhoneBase {
     }
 
     /**
+     * Handles the call to get the subscription source
+     *
+     * @param holds the new CDMA subscription source value
+     */
+    private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
+        if (newSubscriptionSource != mCdmaSubscriptionSource) {
+             mCdmaSubscriptionSource = newSubscriptionSource;
+             if (newSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
+                 // NV is ready when subscription source is NV
+                 sendMessage(obtainMessage(EVENT_NV_READY));
+             }
+        }
+    }
+
+    /**
      * Retrieves the PhoneSubInfo of the CDMAPhone
      */
     public PhoneSubInfo getPhoneSubInfo() {
@@ -1080,15 +1098,6 @@ public class CDMAPhone extends PhoneBase {
         return mRuimPhoneBookInterfaceManager;
     }
 
-    public void registerForNvLoaded(Handler h, int what, Object obj) {
-        Registrant r = new Registrant (h, what, obj);
-        mNvLoadedRegistrants.add(r);
-    }
-
-    public void unregisterForNvLoaded(Handler h) {
-        mNvLoadedRegistrants.remove(h);
-    }
-
     public void registerForEriFileLoaded(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
         mEriFileLoadedRegistrants.add(r);
index 8fb136e..40825f8 100755 (executable)
@@ -32,6 +32,7 @@ import android.text.TextUtils;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.RILConstants;
 
 /**
  * {@hide}
@@ -429,8 +430,9 @@ public class CdmaConnection extends Connection {
                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
                         || serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
                     return DisconnectCause.OUT_OF_SERVICE;
-                } else if (phone.mCM.getNvState() != CommandsInterface.RadioState.NV_READY
-                        && phone.getIccCard().getState() != RuimCard.State.READY) {
+                } else if (phone.mCdmaSubscriptionSource ==
+                               CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM
+                           && phone.getIccCard().getState() != RuimCard.State.READY) {
                     return DisconnectCause.ICC_ERROR;
                 } else if (causeCode==CallFailCause.NORMAL_CLEARING) {
                     return DisconnectCause.NORMAL;
index 5889372..06860d8 100644 (file)
@@ -43,6 +43,7 @@ import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.RetryManager;
 import com.android.internal.telephony.Phone;
 import com.android.internal.util.AsyncChannel;
+import com.android.internal.telephony.RILConstants;
 
 import java.util.ArrayList;
 
@@ -53,6 +54,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
     protected final String LOG_TAG = "CDMA";
 
     private CDMAPhone mCdmaPhone;
+    private CdmaSubscriptionSourceManager mCdmaSSM;
 
     /** The DataConnection being setup */
     private CdmaDataConnection mPendingDataConnection;
@@ -103,7 +105,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
         p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
         p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         p.mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
-        p.mCM.registerForNVReady(this, EVENT_NV_READY, null);
         p.mCM.registerForDataNetworkStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
         p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
         p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
@@ -112,6 +113,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
         p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
         p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
         p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
+        mCdmaSSM = CdmaSubscriptionSourceManager.getInstance (p.getContext(), p.mCM, this,
+                EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
 
         mDataConnectionTracker = this;
 
@@ -129,7 +132,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
         mPhone.mCM.unregisterForAvailable(this);
         mPhone.mCM.unregisterForOffOrNotAvailable(this);
         mCdmaPhone.mIccRecords.unregisterForRecordsLoaded(this);
-        mPhone.mCM.unregisterForNVReady(this);
         mPhone.mCM.unregisterForDataNetworkStateChanged(this);
         mCdmaPhone.mCT.unregisterForVoiceCallEnded(this);
         mCdmaPhone.mCT.unregisterForVoiceCallStarted(this);
@@ -137,6 +139,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
         mCdmaPhone.mSST.unregisterForDataConnectionDetached(this);
         mCdmaPhone.mSST.unregisterForRoamingOn(this);
         mCdmaPhone.mSST.unregisterForRoamingOff(this);
+        mCdmaSSM.dispose(this);
         mPhone.mCM.unregisterForCdmaOtaProvision(this);
 
         destroyAllDataConnectionList();
@@ -192,11 +195,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
         int psState = mCdmaPhone.mSST.getCurrentDataConnectionState();
         boolean roaming = (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled());
         boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
+        boolean subscriptionFromNv = (mCdmaSSM.getCdmaSubscriptionSource()
+                                       == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV);
 
         boolean allowed =
                     (psState == ServiceState.STATE_IN_SERVICE ||
                             mAutoAttachOnCreation) &&
-                    (mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
+                    (subscriptionFromNv ||
                             mCdmaPhone.mIccRecords.getRecordsLoaded()) &&
                     (mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
                             mPhone.getState() == Phone.State.IDLE) &&
@@ -210,9 +215,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
             if (!((psState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
                 reason += " - psState= " + psState;
             }
-            if (!(mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
-                    mCdmaPhone.mIccRecords.getRecordsLoaded())) {
-                reason += " - radioState= " + mPhone.mCM.getNvState() + " - RUIM not loaded";
+            if (!subscriptionFromNv &&
+                    !mCdmaPhone.mIccRecords.getRecordsLoaded()) {
+                reason += " - RUIM not loaded";
             }
             if (!(mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
                     mPhone.getState() == Phone.State.IDLE)) {
@@ -926,8 +931,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
                 onRecordsLoaded();
                 break;
 
-            case EVENT_NV_READY:
-                onNVReady();
+            case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
+                if(mCdmaSSM.getCdmaSubscriptionSource() ==
+                       CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_NV) {
+                    onNVReady();
+                }
                 break;
 
             case EVENT_CDMA_DATA_DETACHED:
index 3486190..6b73cc5 100644 (file)
@@ -20,6 +20,7 @@ import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.IccCard;
 
 import android.content.Intent;
 import android.telephony.SignalStrength;
@@ -39,11 +40,9 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
     CDMALTEPhone mCdmaLtePhone;
 
     private ServiceState  mLteSS;  // The last LTE state from Voice Registration
-    private boolean mNeedToRegForSimLoaded = true;
 
     public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
         super(phone);
-        cm.registerForSIMReady(this, EVENT_SIM_READY, null);
         mCdmaLtePhone = phone;
 
         mLteSS = new ServiceState();
@@ -51,12 +50,6 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
     }
 
     @Override
-    public void dispose() {
-        cm.unregisterForSIMReady(this);
-        super.dispose();
-    }
-
-    @Override
     public void handleMessage(Message msg) {
         AsyncResult ar;
         int[] ints;
@@ -67,23 +60,7 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
             ar = (AsyncResult)msg.obj;
             handlePollStateResult(msg.what, ar);
             break;
-        case EVENT_SIM_READY:
-            if (DBG) log("handleMessage EVENT_SIM_READY");
-            isSubscriptionFromRuim = false;
-            // Register SIM_RECORDS_LOADED dynamically.
-            // This is to avoid confilct with RUIM_READY scenario)
-            if (mNeedToRegForSimLoaded) {
-                phone.mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
-                mNeedToRegForSimLoaded = false;
-            }
-            pollState();
-            // Signal strength polling stops when radio is off.
-            queueNextSignalStrengthPoll();
-
-            // load ERI file
-            phone.prepareEri();
-            break;
-        case EVENT_SIM_RECORDS_LOADED:
+        case EVENT_RUIM_RECORDS_LOADED:
             CdmaLteUiccRecords sim = (CdmaLteUiccRecords)phone.mIccRecords;
             if ((sim != null) && sim.isProvisioned()) {
                 mMdn = sim.getMdn();
@@ -367,9 +344,9 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
                 ss.setOperatorAlphaLong(eriText);
             }
 
-            if (cm.getSimState().isSIMReady()) {
-                // 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.
+            if (phone.mIccCard.getState() == IccCard.State.READY) {
+                // 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();
                 int iconIndex = ss.getCdmaEriIconIndex();
index d939e98..5115d76 100755 (executable)
@@ -22,10 +22,12 @@ import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.CommandsInterface.RadioState;
 
 import android.app.AlarmManager;
 import android.content.ContentResolver;
@@ -41,6 +43,7 @@ import android.os.RegistrantList;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.provider.Settings.Secure;
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Telephony.Intents;
 import android.telephony.ServiceState;
@@ -138,6 +141,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
 
     private boolean isEriTextLoaded = false;
     protected boolean isSubscriptionFromRuim = false;
+    private CdmaSubscriptionSourceManager mCdmaSSM;
 
     /* Used only for debugging purposes. */
     private String mRegistrationDeniedReason;
@@ -173,20 +177,22 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
         newCellLoc = new CdmaCellLocation();
         mSignalStrength = new SignalStrength();
 
+        mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(phone.getContext(), cm, this,
+                EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
+        isSubscriptionFromRuim = (mCdmaSSM.getCdmaSubscriptionSource() ==
+                          CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
+
         PowerManager powerManager =
                 (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
 
-        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
 
         cm.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED_CDMA, null);
         cm.setOnNITZTime(this, EVENT_NITZ_TIME, null);
         cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
 
-        cm.registerForRUIMReady(this, EVENT_RUIM_READY, null);
-
-        cm.registerForNVReady(this, EVENT_NV_READY, null);
+        cm.registerForCdmaPrlChanged(this, EVENT_CDMA_PRL_VERSION_CHANGED, null);
         phone.registerForEriFileLoaded(this, EVENT_ERI_FILE_LOADED, null);
         cm.registerForCdmaOtaProvision(this,EVENT_OTA_PROVISION_STATUS_CHANGE, null);
 
@@ -207,11 +213,10 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
 
     public void dispose() {
         // Unregister for all events.
-        cm.unregisterForAvailable(this);
         cm.unregisterForRadioStateChanged(this);
         cm.unregisterForVoiceNetworkStateChanged(this);
-        cm.unregisterForRUIMReady(this);
-        cm.unregisterForNVReady(this);
+        phone.mIccCard.unregisterForReady(this);
+
         cm.unregisterForCdmaOtaProvision(this);
         phone.unregisterForEriFileLoaded(this);
         phone.mIccRecords.unregisterForRecordsLoaded(this);
@@ -219,6 +224,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
         cm.unSetOnNITZTime(this);
         cr.unregisterContentObserver(mAutoTimeObserver);
         cr.unregisterContentObserver(mAutoTimeZoneObserver);
+        mCdmaSSM.dispose(this);
+        cm.unregisterForCdmaPrlChanged(this);
     }
 
     @Override
@@ -245,15 +252,39 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
         cdmaForSubscriptionInfoReadyRegistrants.remove(h);
     }
 
+    /**
+     * Save current source of cdma subscription
+     * @param source - 1 for NV, 0 for RUIM
+     */
+    private void saveCdmaSubscriptionSource(int source) {
+        log("Storing cdma subscription source: " + source);
+        Secure.putInt(phone.getContext().getContentResolver(),
+                Secure.CDMA_SUBSCRIPTION_MODE,
+                source );
+    }
+
+    private void getSubscriptionInfoAndStartPollingThreads() {
+        cm.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
+
+        // Get Registration Information
+        pollState();
+    }
+
     @Override
     public void handleMessage (Message msg) {
         AsyncResult ar;
         int[] ints;
         String[] strings;
 
+        if (!phone.mIsTheCurrentActivePhone) {
+            loge("Received message " + msg + "[" + msg.what + "]" +
+                    " while being destroyed. Ignoring.");
+            return;
+        }
+
         switch (msg.what) {
-        case EVENT_RADIO_AVAILABLE:
-            if (DBG) log("handleMessage: EVENT_RADIO_AVAILABLE");
+        case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
+            handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
             break;
 
         case EVENT_RUIM_READY:
@@ -262,39 +293,30 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
 
             // The RUIM is now ready i.e if it was locked it has been
             // unlocked. At this stage, the radio is already powered on.
-            isSubscriptionFromRuim = true;
             if (mNeedToRegForRuimLoaded) {
                 phone.mIccRecords.registerForRecordsLoaded(this,
                         EVENT_RUIM_RECORDS_LOADED, null);
                 mNeedToRegForRuimLoaded = false;
             }
-
-            cm.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
-            if (DBG) log("handleMessage: EVENT_RUIM_READY, Send Request getCDMASubscription.");
-
-            // Restore the previous network selection.
-            pollState();
-
-            // Signal strength polling stops when radio is off.
-            queueNextSignalStrengthPoll();
+            if (DBG) log("Receive EVENT_RUIM_READY and Send Request getCDMASubscription.");
+            getSubscriptionInfoAndStartPollingThreads();
+            phone.prepareEri();
             break;
 
         case EVENT_NV_READY:
-            // TODO: Consider calling setCurrentPreferredNetworkType as we do in GsmSST.
-            // cm.setCurrentPreferredNetworkType();
-
-            isSubscriptionFromRuim = false;
             // For Non-RUIM phones, the subscription information is stored in
             // Non Volatile. Here when Non-Volatile is ready, we can poll the CDMA
             // subscription info.
-            if (DBG) log("handleMessage: EVENT_NV_READY, Send Request getCDMASubscription.");
-            cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
-            pollState();
-            // Signal strength polling stops when radio is off.
-            queueNextSignalStrengthPoll();
+            getSubscriptionInfoAndStartPollingThreads();
             break;
 
         case EVENT_RADIO_STATE_CHANGED:
+            if(cm.getRadioState() == RadioState.RADIO_ON) {
+                handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
+
+                // Signal strength polling stops when radio is off.
+                queueNextSignalStrengthPoll();
+            }
             // This will do nothing in the 'radio not available' case.
             setPowerStateToDesired();
             pollState();
@@ -308,7 +330,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
             // This callback is called when signal strength is polled
             // all by itself.
 
-            if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isGsm())) {
+            if (!(cm.getRadioState().isOn())) {
                 // Polling will continue when radio turns back on.
                 return;
             }
@@ -457,6 +479,14 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
             }
             break;
 
+        case EVENT_CDMA_PRL_VERSION_CHANGED:
+            ar = (AsyncResult)msg.obj;
+            if (ar.exception == null) {
+                ints = (int[]) ar.result;
+                mPrlVersion = Integer.toString(ints[0]);
+            }
+            break;
+
         default:
             super.handleMessage(msg);
         break;
@@ -465,6 +495,19 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
 
     //***** Private Instance Methods
 
+    private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
+        log("Subscription Source : " + newSubscriptionSource);
+        isSubscriptionFromRuim =
+            (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
+        saveCdmaSubscriptionSource(newSubscriptionSource);
+        if (!isSubscriptionFromRuim) {
+            // NV is ready when subscription source is NV
+            sendMessage(obtainMessage(EVENT_NV_READY));
+        } else {
+            phone.mIccCard.registerForReady(this, EVENT_RUIM_READY, null);
+        }
+    }
+
     @Override
     protected void setPowerStateToDesired() {
         // If we want it on and it's off, turn it on
@@ -481,13 +524,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
 
     @Override
     protected void updateSpnDisplay() {
-        // TODO RUIM SPN is not implemented, EF_SPN has to be read and Display Condition
-        //   Character Encoding, Language Indicator and SPN has to be set, something like below:
-        // if (cm.getRadioState().isRUIMReady()) {
-        //     rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric());
-        //     spn = phone.mSIMRecords.getServiceProvideName();
-        // }
-
         // mOperatorAlphaLong contains the ERI text
         String plmn = ss.getOperatorAlphaLong();
         if (!TextUtils.equals(plmn, mCurPlmn)) {
@@ -653,7 +689,8 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
                                 "'= " + opNames[2]);
                     }
                 }
-                if (cm.getNvState().isNVReady()) {
+
+                if (!isSubscriptionFromRuim) {
                     // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
                     // ERI text, so here it is ignored what is coming from the modem.
                     newSS.setOperatorName(null, opNames[1], opNames[2]);
@@ -810,18 +847,6 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
             pollStateDone();
             break;
 
-        case SIM_NOT_READY:
-        case SIM_LOCKED_OR_ABSENT:
-        case SIM_READY:
-            if (DBG) log("Radio Technology Change ongoing, setting SS to off");
-            newSS.setStateOff();
-            newCellLoc.setStateInvalid();
-            setSignalStrengthDefaultValues();
-            mGotCountryCode = false;
-
-            // NOTE: pollStateDone() is not needed in this case
-            break;
-
         default:
             // Issue all poll-related commands at once, then count
             // down the responses which are allowed to arrive
@@ -946,7 +971,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
         }
 
         if (hasChanged) {
-            if (cm.getRadioState().isNVReady()) {
+            if ((cm.getRadioState().isOn()) && (!isSubscriptionFromRuim)) {
                 String eriText;
                 // Now the CDMAPhone sees the new ServiceState so it can get the new ERI text
                 if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
@@ -1061,9 +1086,9 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
      * This code should probably be hoisted to the base class so
      * the fix, when added, works for both.
      */
-    protected void
+    private void
     queueNextSignalStrengthPoll() {
-        if (dontPollSignalStrength || (cm.getRadioState().isGsm())) {
+        if (dontPollSignalStrength) {
             // The radio is telling us about signal strength changes
             // we don't have to ask it
             return;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSubscriptionSourceManager.java
new file mode 100644 (file)
index 0000000..80af9d4
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.cdma;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.RILConstants;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * Class that handles the CDMA subscription source changed events from RIL
+ */
+public class CdmaSubscriptionSourceManager extends Handler {
+    static final String LOG_TAG = "CDMA";
+    private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1;
+    private static final int EVENT_GET_CDMA_SUBSCRIPTION_SOURCE     = 2;
+    private static final int EVENT_RADIO_ON                         = 3;
+
+    public static final int SUBSCRIPTION_SOURCE_UNKNOWN = -1;
+    public static final int SUBSCRIPTION_FROM_RUIM      = 0; /* CDMA subscription from RUIM */
+    public static final int SUBSCRIPTION_FROM_NV        = 1; /* CDMA subscription from NV */
+    public static final int PREFERRED_CDMA_SUBSCRIPTION = SUBSCRIPTION_FROM_NV;
+
+    private static CdmaSubscriptionSourceManager sInstance;
+    private static final Object sReferenceCountMonitor = new Object();
+    private static int sReferenceCount = 0;
+
+    // ***** Instance Variables
+    private CommandsInterface mCM;
+    private Context mContext;
+    private RegistrantList mCdmaSubscriptionSourceChangedRegistrants = new RegistrantList();
+
+    // Type of CDMA subscription source
+    private AtomicInteger mCdmaSubscriptionSource = new AtomicInteger(SUBSCRIPTION_FROM_NV);
+
+    // Constructor
+    private CdmaSubscriptionSourceManager(Context context, CommandsInterface ci) {
+        mContext = context;
+        mCM = ci;
+        mCM.registerForCdmaSubscriptionChanged(this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
+        mCM.registerForOn(this, EVENT_RADIO_ON, null);
+        int subscriptionSource = getDefaultCdmaSubscriptionSource();
+        mCdmaSubscriptionSource.set(subscriptionSource);
+    }
+
+    /**
+     * This function creates a single instance of this class
+     *
+     * @return object of type CdmaSubscriptionSourceManager
+     */
+    public static CdmaSubscriptionSourceManager getInstance(Context context,
+            CommandsInterface ci, Handler h, int what, Object obj) {
+        synchronized (sReferenceCountMonitor) {
+            if (null == sInstance) {
+                sInstance = new CdmaSubscriptionSourceManager(context, ci);
+            }
+            sInstance.sReferenceCount++;
+        }
+        sInstance.registerForCdmaSubscriptionSourceChanged(h, what, obj);
+        return sInstance;
+    }
+
+    /**
+     * Unregisters for the registered event with RIL
+     */
+    public void dispose(Handler h) {
+        mCdmaSubscriptionSourceChangedRegistrants.remove(h);
+        synchronized (sReferenceCountMonitor) {
+            sReferenceCount--;
+            if (sReferenceCount <= 0) {
+                mCM.unregisterForCdmaSubscriptionChanged(this);
+                mCM.unregisterForOn(this);
+                sInstance = null;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see android.os.Handler#handleMessage(android.os.Message)
+     */
+    @Override
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+        switch (msg.what) {
+            case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
+            case EVENT_GET_CDMA_SUBSCRIPTION_SOURCE:
+            {
+                log("CDMA_SUBSCRIPTION_SOURCE event = " + msg.what);
+                ar = (AsyncResult) msg.obj;
+                handleGetCdmaSubscriptionSource(ar);
+            }
+            break;
+            case EVENT_RADIO_ON: {
+                mCM.getCdmaSubscriptionSource(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_SOURCE));
+            }
+            break;
+            default:
+                super.handleMessage(msg);
+        }
+    }
+
+    /**
+     * Returns the current CDMA subscription source value
+     * @return CDMA subscription source value
+     */
+    public int getCdmaSubscriptionSource() {
+        return mCdmaSubscriptionSource.get();
+    }
+
+    /**
+     * Gets the default CDMA subscription source
+     *
+     * @return Default CDMA subscription source from Settings DB if present.
+     */
+    private int getDefaultCdmaSubscriptionSource() {
+        // Get the default value from the Settings
+        int subscriptionSource = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.CDMA_SUBSCRIPTION_MODE, PREFERRED_CDMA_SUBSCRIPTION);
+        return subscriptionSource;
+    }
+
+    /**
+     * Clients automatically register for CDMA subscription source changed event
+     * when they get an instance of this object.
+     */
+    private void registerForCdmaSubscriptionSourceChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mCdmaSubscriptionSourceChangedRegistrants.add(r);
+    }
+
+    /**
+     * Handles the call to get the subscription source
+     *
+     * @param ar AsyncResult object that contains the result of get CDMA
+     *            subscription source call
+     */
+    private void handleGetCdmaSubscriptionSource(AsyncResult ar) {
+        if ((ar.exception == null) && (ar.result != null)) {
+            int newSubscriptionSource = ((int[]) ar.result)[0];
+
+            if (newSubscriptionSource != mCdmaSubscriptionSource.get()) {
+                log("Subscription Source Changed : " + mCdmaSubscriptionSource + " >> "
+                        + newSubscriptionSource);
+                mCdmaSubscriptionSource.set(newSubscriptionSource);
+
+                // Notify registrants of the new CDMA subscription source
+                mCdmaSubscriptionSourceChangedRegistrants.notifyRegistrants(new AsyncResult(null,
+                        null, null));
+            }
+        } else {
+            // GET_CDMA_SUBSCRIPTION is returning Failure. Probably
+            // because modem created GSM Phone. If modem created
+            // GSMPhone, then PhoneProxy will trigger a change in
+            // Phone objects and this object will be destroyed.
+            logw("Unable to get CDMA Subscription Source, Exception: " + ar.exception
+                    + ", result: " + ar.result);
+        }
+    }
+
+    private void log(String s) {
+        Log.d(LOG_TAG, "[CdmaSSM] " + s);
+    }
+
+    private void loge(String s) {
+        Log.e(LOG_TAG, "[CdmaSSM] " + s);
+    }
+
+    private void logw(String s) {
+        Log.w(LOG_TAG, "[CdmaSSM] " + s);
+    }
+
+}
index 11f44d4..02eb86d 100644 (file)
@@ -27,19 +27,17 @@ public final class RuimCard extends IccCard {
 
     RuimCard(CDMAPhone phone, String LOG_TAG, boolean dbg) {
         super(phone, LOG_TAG, dbg);
-        mPhone.mCM.registerForRUIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
-        mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
-        mPhone.mCM.registerForRUIMReady(mHandler, EVENT_ICC_READY, null);
+        is3gpp = false;
+        mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(),
+                       mPhone.mCM, mHandler, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
+
         updateStateProperty();
     }
 
     @Override
     public void dispose() {
         super.dispose();
-        //Unregister for all events
-        mPhone.mCM.unregisterForRUIMLockedOrAbsent(mHandler);
-        mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
-        mPhone.mCM.unregisterForRUIMReady(mHandler);
+        mCdmaSSM.dispose(mHandler);
     }
 
     @Override
index 9850b9f..b057e46 100755 (executable)
@@ -88,7 +88,7 @@ public final class RuimRecords extends IccRecords {
         recordsToLoad = 0;
 
 
-        p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
+        p.mIccCard.registerForRuimReady(this, EVENT_RUIM_READY, null);
         p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         // NOTE the EVENT_SMS_ON_RUIM is not registered
         p.mCM.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
@@ -101,14 +101,14 @@ public final class RuimRecords extends IccRecords {
     @Override
     public void dispose() {
         //Unregister for all events
-        phone.mCM.unregisterForRUIMReady(this);
+        phone.mIccCard.unregisterForRuimReady(this);
         phone.mCM.unregisterForOffOrNotAvailable( this);
         phone.mCM.unregisterForIccRefresh(this);
     }
 
     @Override
     protected void finalize() {
-        if(DBG) Log.d(LOG_TAG, "RuimRecords finalized");
+        if(DBG) log("RuimRecords finalized");
     }
 
     @Override
@@ -150,7 +150,7 @@ public final class RuimRecords extends IccRecords {
         AsyncResult.forMessage((onComplete)).exception =
                 new IccException("setVoiceMailNumber not implemented");
         onComplete.sendToTarget();
-        Log.e(LOG_TAG, "method setVoiceMailNumber is not implemented");
+        loge("method setVoiceMailNumber is not implemented");
     }
 
     /**
@@ -198,6 +198,12 @@ public final class RuimRecords extends IccRecords {
 
         boolean isRecordLoadResponse = false;
 
+        if (!phone.mIsTheCurrentActivePhone) {
+            loge("Received message " + msg +
+                    "[" + msg.what + "] while being destroyed. Ignoring.");
+            return;
+        }
+
         try { switch (msg.what) {
             case EVENT_RUIM_READY:
                 onRuimReady();
@@ -208,7 +214,7 @@ public final class RuimRecords extends IccRecords {
             break;
 
             case EVENT_GET_DEVICE_IDENTITY_DONE:
-                Log.d(LOG_TAG, "Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
+                log("Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
             break;
 
             /* IO events */
@@ -217,7 +223,7 @@ public final class RuimRecords extends IccRecords {
 
                 ar = (AsyncResult)msg.obj;
                 if (ar.exception != null) {
-                    Log.e(LOG_TAG, "Exception querying IMSI, Exception:" + ar.exception);
+                    loge("Exception querying IMSI, Exception:" + ar.exception);
                     break;
                 }
 
@@ -226,11 +232,11 @@ public final class RuimRecords extends IccRecords {
                 // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
                 // than 15 (and usually 15).
                 if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) {
-                    Log.e(LOG_TAG, "invalid IMSI " + mImsi);
+                    loge("invalid IMSI " + mImsi);
                     mImsi = null;
                 }
 
-                Log.d(LOG_TAG, "IMSI: " + mImsi.substring(0, 6) + "xxxxxxxxx");
+                log("IMSI: " + mImsi.substring(0, 6) + "xxxxxxxxx");
 
                 String operatorNumeric = getRUIMOperatorNumeric();
                 if (operatorNumeric != null) {
@@ -251,7 +257,7 @@ public final class RuimRecords extends IccRecords {
                 mMin2Min1 = localTemp[3];
                 mPrlVersion = localTemp[4];
 
-                Log.d(LOG_TAG, "MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
+                log("MDN: " + mMyMobileNumber + " MIN: " + mMin2Min1);
 
             break;
 
@@ -267,7 +273,7 @@ public final class RuimRecords extends IccRecords {
 
                 iccid = IccUtils.bcdToString(data, 0, data.length);
 
-                Log.d(LOG_TAG, "iccid: " + iccid);
+                log("iccid: " + iccid);
 
             break;
 
@@ -287,7 +293,7 @@ public final class RuimRecords extends IccRecords {
 
             // TODO: probably EF_CST should be read instead
             case EVENT_GET_SST_DONE:
-                Log.d(LOG_TAG, "Event EVENT_GET_SST_DONE Received");
+                log("Event EVENT_GET_SST_DONE Received");
             break;
 
             case EVENT_RUIM_REFRESH:
@@ -318,14 +324,14 @@ public final class RuimRecords extends IccRecords {
         if (recordsToLoad == 0 && recordsRequested == true) {
             onAllRecordsLoaded();
         } else if (recordsToLoad < 0) {
-            Log.e(LOG_TAG, "RuimRecords: recordsToLoad <0, programmer error suspected");
+            loge("RuimRecords: recordsToLoad <0, programmer error suspected");
             recordsToLoad = 0;
         }
     }
 
     @Override
     protected void onAllRecordsLoaded() {
-        Log.d(LOG_TAG, "RuimRecords: record load complete");
+        log("RuimRecords: record load complete");
 
         // Further records that can be inserted are Operator/OEM dependent
 
index e1f4c4b..af7c78c 100644 (file)
@@ -135,13 +135,13 @@ public class GSMPhone extends PhoneBase {
         }
 
         mCM.setPhoneType(Phone.PHONE_TYPE_GSM);
+        mIccCard = new SimCard(this, LOG_TAG, true);
         mCT = new GsmCallTracker(this);
         mSST = new GsmServiceStateTracker (this);
         mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);
         mIccFileHandler = new SIMFileHandler(this);
         mIccRecords = new SIMRecords(this);
         mDataConnectionTracker = new GsmDataConnectionTracker (this);
-        mIccCard = new SimCard(this);
         if (!unitTestMode) {
             mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
             mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
@@ -234,12 +234,8 @@ public class GSMPhone extends PhoneBase {
         mStkService = null;
         mSimPhoneBookIntManager = null;
         mSimSmsIntManager = null;
-        mSMS = null;
         mSubInfo = null;
-        mIccRecords = null;
         mIccFileHandler = null;
-        mIccCard = null;
-        mDataConnectionTracker = null;
         mCT = null;
         mSST = null;
     }
index 84127cf..92e16ce 100644 (file)
@@ -205,7 +205,7 @@ 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);
-        cm.registerForSIMReady(this, EVENT_SIM_READY, null);
+        phone.mIccCard.registerForReady(this, EVENT_SIM_READY, null);
 
         // system setting property AIRPLANE_MODE_ON is set in Settings.
         int airplaneMode = Settings.System.getInt(
@@ -238,8 +238,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
         cm.unregisterForAvailable(this);
         cm.unregisterForRadioStateChanged(this);
         cm.unregisterForVoiceNetworkStateChanged(this);
-        cm.unregisterForSIMReady(this);
-
+        phone.mIccCard.unregisterForReady(this);
         phone.mIccRecords.unregisterForRecordsLoaded(this);
         cm.unSetOnSignalStrengthUpdate(this);
         cm.unSetOnRestrictedStateChanged(this);
@@ -263,6 +262,11 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
         String[] strings;
         Message message;
 
+        if (!phone.mIsTheCurrentActivePhone) {
+            Log.e(LOG_TAG, "Received message " + msg +
+                    "[" + msg.what + "] while being destroyed. Ignoring.");
+            return;
+        }
         switch (msg.what) {
             case EVENT_RADIO_AVAILABLE:
                 //this is unnecessary
@@ -309,8 +313,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
                 // This callback is called when signal strength is polled
                 // all by itself
 
-                if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isCdma())) {
-                    // Polling will continue when radio turns back on and not CDMA
+                if (!(cm.getRadioState().isOn())) {
+                    // Polling will continue when radio turns back on
                     return;
                 }
                 ar = (AsyncResult) msg.obj;
@@ -703,20 +707,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
                 pollStateDone();
             break;
 
-            case RUIM_NOT_READY:
-            case RUIM_READY:
-            case RUIM_LOCKED_OR_ABSENT:
-            case NV_NOT_READY:
-            case NV_READY:
-                if (DBG) log("Radio Technology Change ongoing, setting SS to off");
-                newSS.setStateOff();
-                newCellLoc.setStateInvalid();
-                setSignalStrengthDefaultValues();
-                mGotCountryCode = false;
-
-                //NOTE: pollStateDone() is not needed in this case
-                break;
-
             default:
                 // Issue all poll-related commands at once
                 // then count down the responses, which
@@ -996,7 +986,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
     }
 
     private void queueNextSignalStrengthPoll() {
-        if (dontPollSignalStrength || (cm.getRadioState().isCdma())) {
+        if (dontPollSignalStrength) {
             // The radio is telling us about signal strength changes
             // we don't have to ask it
             return;
index 495b5bc..7c423c7 100755 (executable)
@@ -184,7 +184,7 @@ public class SIMRecords extends IccRecords {
         // recordsToLoad is set to 0 because no requests are made yet
         recordsToLoad = 0;
 
-        p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+        p.mIccCard.registerForReady(this, EVENT_SIM_READY, null);
         p.mCM.registerForOffOrNotAvailable(
                         this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
@@ -198,13 +198,13 @@ public class SIMRecords extends IccRecords {
     @Override
     public void dispose() {
         //Unregister for all events
-        phone.mCM.unregisterForSIMReady(this);
+        phone.mIccCard.unregisterForReady(this);
         phone.mCM.unregisterForOffOrNotAvailable( this);
         phone.mCM.unregisterForIccRefresh(this);
     }
 
     protected void finalize() {
-        if(DBG) Log.d(LOG_TAG, "SIMRecords finalized");
+        if(DBG) log("finalized");
     }
 
     protected void onRadioOffOrNotAvailable() {
@@ -412,8 +412,7 @@ public class SIMRecords extends IccRecords {
                     obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS));
             }
         } catch (ArrayIndexOutOfBoundsException ex) {
-            Log.w(LOG_TAG,
-                "Error saving voice mail state to SIM. Probably malformed SIM record", ex);
+            logw("Error saving voice mail state to SIM. Probably malformed SIM record", ex);
         }
     }
 
@@ -468,8 +467,7 @@ public class SIMRecords extends IccRecords {
                         obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS));
             }
         } catch (ArrayIndexOutOfBoundsException ex) {
-            Log.w(LOG_TAG,
-                    "Error saving call fowarding flag to SIM. "
+            logw("Error saving call fowarding flag to SIM. "
                             + "Probably malformed SIM record", ex);
 
         }
@@ -495,11 +493,11 @@ public class SIMRecords extends IccRecords {
     @Override
     public String getOperatorNumeric() {
         if (imsi == null) {
-            Log.d(LOG_TAG, "getOperatorNumeric: IMSI == null");
+            log("getOperatorNumeric: IMSI == null");
             return null;
         }
         if (mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
-            Log.d(LOG_TAG, "getSIMOperatorNumeric: bad mncLength");
+            log("getSIMOperatorNumeric: bad mncLength");
             return null;
         }
 
@@ -517,6 +515,12 @@ public class SIMRecords extends IccRecords {
 
         boolean isRecordLoadResponse = false;
 
+        if (!phone.mIsTheCurrentActivePhone) {
+            loge("Received message " + msg + "[" + msg.what + "] " +
+                    " while being destroyed. Ignoring.");
+            return;
+        }
+
         try { switch (msg.what) {
             case EVENT_SIM_READY:
                 onSimReady();
@@ -533,7 +537,7 @@ public class SIMRecords extends IccRecords {
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception != null) {
-                    Log.e(LOG_TAG, "Exception querying IMSI, Exception:" + ar.exception);
+                    loge("Exception querying IMSI, Exception:" + ar.exception);
                     break;
                 }
 
@@ -542,11 +546,11 @@ public class SIMRecords extends IccRecords {
                 // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
                 // than 15 (and usually 15).
                 if (imsi != null && (imsi.length() < 6 || imsi.length() > 15)) {
-                    Log.e(LOG_TAG, "invalid IMSI " + imsi);
+                    loge("invalid IMSI " + imsi);
                     imsi = null;
                 }
 
-                Log.d(LOG_TAG, "IMSI: " + /* imsi.substring(0, 6) +*/ "xxxxxxx");
+                log("IMSI: " + /* imsi.substring(0, 6) +*/ "xxxxxxx");
 
                 if (((mncLength == UNKNOWN) || (mncLength == 2)) &&
                         ((imsi != null) && (imsi.length() >= 6))) {
@@ -567,7 +571,7 @@ public class SIMRecords extends IccRecords {
                         mncLength = MccTable.smallestDigitsMccForMnc(mcc);
                     } catch (NumberFormatException e) {
                         mncLength = UNKNOWN;
-                        Log.e(LOG_TAG, "SIMRecords: Corrupt IMSI!");
+                        loge("Corrupt IMSI!");
                     }
                 }
 
@@ -589,15 +593,14 @@ public class SIMRecords extends IccRecords {
                 isValidMbdn = false;
                 if (ar.exception == null) {
                     // Refer TS 51.011 Section 10.3.44 for content details
-                    Log.d(LOG_TAG, "EF_MBI: " +
-                            IccUtils.bytesToHexString(data));
+                    log("EF_MBI: " + IccUtils.bytesToHexString(data));
 
                     // Voice mail record number stored first
                     mailboxIndex = (int)data[0] & 0xff;
 
                     // check if dailing numbe id valid
                     if (mailboxIndex != 0 && mailboxIndex != 0xff) {
-                        Log.d(LOG_TAG, "Got valid mailbox number for MBDN");
+                        log("Got valid mailbox number for MBDN");
                         isValidMbdn = true;
                     }
                 }
@@ -633,7 +636,7 @@ public class SIMRecords extends IccRecords {
 
                 if (ar.exception != null) {
 
-                    Log.d(LOG_TAG, "Invalid or missing EF"
+                    log("Invalid or missing EF"
                         + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? "[MAILBOX]" : "[MBDN]"));
 
                     // Bug #645770 fall back to CPHS
@@ -653,7 +656,7 @@ public class SIMRecords extends IccRecords {
 
                 adn = (AdnRecord)ar.result;
 
-                Log.d(LOG_TAG, "VM: " + adn +
+                log("VM: " + adn +
                         ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? " EF[MAILBOX]" : " EF[MBDN]"));
 
                 if (adn.isEmpty() && msg.what == EVENT_GET_MBDN_DONE) {
@@ -678,7 +681,7 @@ public class SIMRecords extends IccRecords {
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception != null) {
-                    Log.d(LOG_TAG, "Invalid or missing EF[MSISDN]");
+                    log("Invalid or missing EF[MSISDN]");
                     break;
                 }
 
@@ -687,7 +690,7 @@ public class SIMRecords extends IccRecords {
                 msisdn = adn.getNumber();
                 msisdnTag = adn.getAlphaTag();
 
-                Log.d(LOG_TAG, "MSISDN: " + /*msisdn*/ "xxxxxxx");
+                log("MSISDN: " + /*msisdn*/ "xxxxxxx");
             break;
 
             case EVENT_SET_MSISDN_DONE:
@@ -711,13 +714,12 @@ public class SIMRecords extends IccRecords {
                     break;
                 }
 
-                Log.d(LOG_TAG, "EF_MWIS: " +
-                   IccUtils.bytesToHexString(data));
+                log("EF_MWIS: " + IccUtils.bytesToHexString(data));
 
                 efMWIS = data;
 
                 if ((data[0] & 0xff) == 0xff) {
-                    Log.d(LOG_TAG, "SIMRecords: Uninitialized record MWIS");
+                    log("Uninitialized record MWIS");
                     break;
                 }
 
@@ -775,7 +777,7 @@ public class SIMRecords extends IccRecords {
 
                 iccid = IccUtils.bcdToString(data, 0, data.length);
 
-                Log.d(LOG_TAG, "iccid: " + iccid);
+                log("iccid: " + iccid);
 
             break;
 
@@ -791,16 +793,15 @@ public class SIMRecords extends IccRecords {
                         break;
                     }
 
-                    Log.d(LOG_TAG, "EF_AD: " +
-                            IccUtils.bytesToHexString(data));
+                    log("EF_AD: " + IccUtils.bytesToHexString(data));
 
                     if (data.length < 3) {
-                        Log.d(LOG_TAG, "SIMRecords: Corrupt AD data on SIM");
+                        log("Corrupt AD data on SIM");
                         break;
                     }
 
                     if (data.length == 3) {
-                        Log.d(LOG_TAG, "SIMRecords: MNC length not present in EF_AD");
+                        log("MNC length not present in EF_AD");
                         break;
                     }
 
@@ -829,13 +830,13 @@ public class SIMRecords extends IccRecords {
                                 mncLength = MccTable.smallestDigitsMccForMnc(mcc);
                             } catch (NumberFormatException e) {
                                 mncLength = UNKNOWN;
-                                Log.e(LOG_TAG, "SIMRecords: Corrupt IMSI!");
+                                loge("Corrupt IMSI!");
                             }
                         } else {
                             // Indicate we got this info, but it didn't contain the length.
                             mncLength = UNKNOWN;
 
-                            Log.d(LOG_TAG, "SIMRecords: MNC length not present in EF_AD");
+                            log("MNC length not present in EF_AD");
                         }
                     }
                     if (imsi != null && mncLength != UNKNOWN) {
@@ -862,8 +863,7 @@ public class SIMRecords extends IccRecords {
                     break;
                 }
 
-                Log.d(LOG_TAG, "EF_CFF_CPHS: " +
-                        IccUtils.bytesToHexString(data));
+                log("EF_CFF_CPHS: " + IccUtils.bytesToHexString(data));
                 mEfCff = data;
 
                 if (mEfCfis == null) {
@@ -890,7 +890,7 @@ public class SIMRecords extends IccRecords {
             case EVENT_UPDATE_DONE:
                 ar = (AsyncResult)msg.obj;
                 if (ar.exception != null) {
-                    Log.i(LOG_TAG, "SIMRecords update failed", ar.exception);
+                    logw("update failed. ", ar.exception);
                 }
             break;
 
@@ -939,10 +939,10 @@ public class SIMRecords extends IccRecords {
                 int[] index = (int[])ar.result;
 
                 if (ar.exception != null || index.length != 1) {
-                    Log.e(LOG_TAG, "[SIMRecords] Error on SMS_ON_SIM with exp "
+                    loge("Error on SMS_ON_SIM with exp "
                             + ar.exception + " length " + index.length);
                 } else {
-                    Log.d(LOG_TAG, "READ EF_SMS RECORD index=" + index[0]);
+                    log("READ EF_SMS RECORD index=" + index[0]);
                     phone.getIccFileHandler().loadEFLinearFixed(EF_SMS,index[0],
                             obtainMessage(EVENT_GET_SMS_DONE));
                 }
@@ -954,8 +954,7 @@ public class SIMRecords extends IccRecords {
                 if (ar.exception == null) {
                     handleSms((byte[])ar.result);
                 } else {
-                    Log.e(LOG_TAG, "[SIMRecords] Error on GET_SMS with exp "
-                            + ar.exception);
+                    loge("Error on GET_SMS with exp " + ar.exception);
                 }
                 break;
             case EVENT_GET_SST_DONE:
@@ -1048,7 +1047,7 @@ public class SIMRecords extends IccRecords {
             case EVENT_SIM_REFRESH:
                 isRecordLoadResponse = false;
                 ar = (AsyncResult)msg.obj;
-               if (DBG) log("Sim REFRESH with exception: " + ar.exception);
+                if (DBG) log("Sim REFRESH with exception: " + ar.exception);
                 if (ar.exception == null) {
                     handleSimRefresh((int[])(ar.result));
                 }
@@ -1063,8 +1062,7 @@ public class SIMRecords extends IccRecords {
                     break;
                 }
 
-                Log.d(LOG_TAG, "EF_CFIS: " +
-                   IccUtils.bytesToHexString(data));
+                log("EF_CFIS: " + IccUtils.bytesToHexString(data));
 
                 mEfCfis = data;
 
@@ -1080,13 +1078,13 @@ public class SIMRecords extends IccRecords {
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception != null) {
-                    Log.e(LOG_TAG,"Exception in fetching EF_CSP data " + ar.exception);
+                    loge("Exception in fetching EF_CSP data " + ar.exception);
                     break;
                 }
 
                 data = (byte[])ar.result;
 
-                Log.i(LOG_TAG,"EF_CSP: " + IccUtils.bytesToHexString(data));
+                log("EF_CSP: " + IccUtils.bytesToHexString(data));
                 handleEfCspData(data);
                 break;
 
@@ -1095,7 +1093,7 @@ public class SIMRecords extends IccRecords {
 
         }}catch (RuntimeException exc) {
             // I don't want these exceptions to be fatal
-            Log.w(LOG_TAG, "Exception parsing SIM record", exc);
+            logw("Exception parsing SIM record", exc);
         } finally {
             // Count up record load responses even if they are fails
             if (isRecordLoadResponse) {
@@ -1118,7 +1116,7 @@ public class SIMRecords extends IccRecords {
                 break;
             case EF_CSP_CPHS:
                 recordsToLoad++;
-                Log.i(LOG_TAG, "[CSP] SIM Refresh for EF_CSP_CPHS");
+                log("[CSP] SIM Refresh for EF_CSP_CPHS");
                 phone.getIccFileHandler().loadEFTransparent(EF_CSP_CPHS,
                         obtainMessage(EVENT_GET_CSP_CPHS_DONE));
                 break;
@@ -1242,13 +1240,13 @@ public class SIMRecords extends IccRecords {
         if (recordsToLoad == 0 && recordsRequested == true) {
             onAllRecordsLoaded();
         } else if (recordsToLoad < 0) {
-            Log.e(LOG_TAG, "SIMRecords: recordsToLoad <0, programmer error suspected");
+            loge("recordsToLoad <0, programmer error suspected");
             recordsToLoad = 0;
         }
     }
 
     protected void onAllRecordsLoaded() {
-        Log.d(LOG_TAG, "SIMRecords: record load complete");
+        log("record load complete");
 
         String operator = getOperatorNumeric();
 
@@ -1261,7 +1259,7 @@ public class SIMRecords extends IccRecords {
                     MccTable.countryCodeForMcc(Integer.parseInt(imsi.substring(0,3))));
         }
         else {
-            Log.e("SIM", "[SIMRecords] onAllRecordsLoaded: imsi is NULL!");
+            loge("onAllRecordsLoaded: imsi is NULL!");
         }
 
         setVoiceMailByCountry(operator);
@@ -1304,7 +1302,7 @@ public class SIMRecords extends IccRecords {
         recordsRequested = true;
         IccFileHandler iccFh = phone.getIccFileHandler();
 
-        Log.v(LOG_TAG, "SIMRecords:fetchSimRecords " + recordsToLoad);
+        logv("fetchSimRecords " + recordsToLoad);
 
         phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE));
         recordsToLoad++;
@@ -1590,6 +1588,14 @@ public class SIMRecords extends IccRecords {
         Log.e(LOG_TAG, "[SIMRecords] " + s);
     }
 
+    protected void logw(String s, Throwable tr) {
+        Log.w(LOG_TAG, "[SIMRecords] " + s, tr);
+    }
+
+    protected void logv(String s) {
+        Log.v(LOG_TAG, "[SIMRecords] " + s);
+    }
+
     /**
      * Return true if "Restriction of menu options for manual PLMN selection"
      * bit is set or EF_CSP data is unavailable, return false otherwise.
@@ -1619,8 +1625,7 @@ public class SIMRecords extends IccRecords {
         mCspPlmnEnabled = true;
         for (int i = 0; i < usedCspGroups; i++) {
              if (data[2 * i] == valueAddedServicesGroup) {
-                 Log.i(LOG_TAG, "[CSP] found ValueAddedServicesGroup, value "
-                       + data[(2 * i) + 1]);
+                 log("[CSP] found ValueAddedServicesGroup, value " + data[(2 * i) + 1]);
                  if ((data[(2 * i) + 1] & 0x80) == 0x80) {
                      // Bit 8 is for
                      // "Restriction of menu options for manual PLMN selection".
@@ -1630,13 +1635,13 @@ public class SIMRecords extends IccRecords {
                      mCspPlmnEnabled = false;
                      // Operator Selection menu should be disabled.
                      // Operator Selection Mode should be set to Automatic.
-                     Log.i(LOG_TAG,"[CSP] Set Automatic Network Selection");
+                     log("[CSP] Set Automatic Network Selection");
                      phone.setNetworkSelectionModeAutomatic(null);
                  }
                  return;
              }
         }
 
-        Log.w(LOG_TAG, "[CSP] Value Added Service Group (0xC0), not found!");
+        log("[CSP] Value Added Service Group (0xC0), not found!");
     }
 }
index 1fa278a..e34e10a 100644 (file)
@@ -29,41 +29,9 @@ import android.os.SystemProperties;
  */
 public final class SimCard extends IccCard {
 
-    SimCard(GSMPhone phone) {
-        super(phone, "GSM", true);
-
-        mPhone.mCM.registerForSIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
-        mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
-        mPhone.mCM.registerForSIMReady(mHandler, EVENT_ICC_READY, null);
-        updateStateProperty();
-    }
-
-    /**
-    * We have the Sim card for LTE on CDMA phone
-    */
     public SimCard(PhoneBase phone, String logTag, Boolean dbg) {
         super(phone, logTag, dbg);
-        mPhone.mCM.registerForSIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
-        mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
-        mPhone.mCM.registerForSIMReady(mHandler, EVENT_ICC_READY, null);
         updateStateProperty();
-
-        if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
-            mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
-        }
-    }
-
-    @Override
-    public void dispose() {
-        super.dispose();
-        //Unregister for all events
-        mPhone.mCM.unregisterForSIMLockedOrAbsent(mHandler);
-        mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
-        mPhone.mCM.unregisterForSIMReady(mHandler);
-
-        if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
-            mPhone.mCM.unregisterForIccStatusChanged(mHandler);
-        }
     }
 
     @Override
index ab01012..9201984 100644 (file)
@@ -412,4 +412,7 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface {
 
     public void requestIsimAuthentication(String nonce, Message response) {
     }
+
+    public void getVoiceRadioTechnology(Message result) {
+    }
 }
index a0c7d5d..60d9d24 100644 (file)
@@ -120,9 +120,9 @@ public final class SimulatedCommands extends BaseCommands
 
         if (pin != null && pin.equals(mPinCode)) {
             Log.i(LOG_TAG, "[SimCmd] supplyIccPin: success!");
-            setRadioState(RadioState.SIM_READY);
             mPinUnlockAttempts = 0;
             mSimLockedState = SimLockState.NONE;
+            mIccStatusChangedRegistrants.notifyRegistrants();
 
             if (result != null) {
                 AsyncResult.forMessage(result, null, null);
@@ -162,9 +162,9 @@ public final class SimulatedCommands extends BaseCommands
 
         if (puk != null && puk.equals(SIM_PUK_CODE)) {
             Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!");
-            setRadioState(RadioState.SIM_READY);
             mSimLockedState = SimLockState.NONE;
             mPukUnlockAttempts = 0;
+            mIccStatusChangedRegistrants.notifyRegistrants();
 
             if (result != null) {
                 AsyncResult.forMessage(result, null, null);
@@ -441,11 +441,11 @@ public final class SimulatedCommands extends BaseCommands
      *      The ar.result List is sorted by DriverCall.index
      */
     public void getCurrentCalls (Message result) {
-        if (mState == RadioState.SIM_READY) {
+        if ((mState == RadioState.RADIO_ON) && !isSimLocked()) {
             //Log.i("GSM", "[SimCmds] getCurrentCalls");
             resultSuccess(result, simulatedCallState.getDriverCalls());
         } else {
-            //Log.i("GSM", "[SimCmds] getCurrentCalls: SIM not ready!");
+            //Log.i("GSM", "[SimCmds] getCurrentCalls: RADIO_OFF or SIM not ready!");
             resultFail(result,
                 new CommandException(
                     CommandException.Error.RADIO_NOT_AVAILABLE));
@@ -1022,14 +1022,7 @@ public final class SimulatedCommands extends BaseCommands
 
     public void setRadioPower(boolean on, Message result) {
         if(on) {
-            if (isSimLocked()) {
-                Log.i("SIM", "[SimCmd] setRadioPower: SIM locked! state=" +
-                        mSimLockedState);
-                setRadioState(RadioState.SIM_LOCKED_OR_ABSENT);
-            }
-            else {
-                setRadioState(RadioState.SIM_READY);
-            }
+            setRadioState(RadioState.RADIO_ON);
         } else {
             setRadioState(RadioState.RADIO_OFF);
         }
@@ -1517,4 +1510,8 @@ public final class SimulatedCommands extends BaseCommands
     public void requestIsimAuthentication(String nonce, Message response) {
         unimplemented(response);
     }
+
+    public void getVoiceRadioTechnology(Message response) {
+        unimplemented(response);
+    }
 }
index 7e0d3c4..b385cee 100644 (file)
@@ -608,4 +608,8 @@ class UsimDataDownloadCommands extends BaseCommands {
     @Override
     public void requestIsimAuthentication(String nonce, Message response) {
     }
+
+    @Override
+    public void getVoiceRadioTechnology(Message response) {
+    }
 }