summaryrefslogtreecommitdiffstats
path: root/src/java
diff options
context:
space:
mode:
authorAlex Yakavenka <ayakav@codeaurora.org>2012-07-10 00:48:53 -0700
committerAlex Yakavenka <ayakav@codeaurora.org>2012-09-07 10:09:59 -0700
commite287feac673ff68565b766e0e463d105fa9cef9d (patch)
tree7ee79096f25919ee91fa8114eabb202a3e7925b9 /src/java
parent7ac8d8026b997141d106762574478eb9daaf3f38 (diff)
downloadframeworks_opt_telephony-e287feac673ff68565b766e0e463d105fa9cef9d.zip
frameworks_opt_telephony-e287feac673ff68565b766e0e463d105fa9cef9d.tar.gz
frameworks_opt_telephony-e287feac673ff68565b766e0e463d105fa9cef9d.tar.bz2
Telephony: Remove CdmaLteUicc objects
-Pass IccCard object to GsmMmiCode -Create IccCardProxy -Make IccCard an interface and pass instance of IccCardProxy to external applications (PhoneApp). IccCardProxy will use internal UiccCard to map Icc requests to current active application on UiccCard to maintain backwards compatibility for external applications -Add documentation to UiccController The primary advantage of UiccController is that we can work with multiple uicc applications at the same time. And that is a requirement for modes like Cdma/Lte. The existing code supports Cdma/Lte only partially and with guessing on modem side. However, some things modem can guess, while others - it can't. For instance, when a user tries to edit the fdn list the current code will pass ef_id for fdn (0x6F3B). But the modem will have no clue which fdn list the user wants to edit (csim or usim, both have path 7FFF), and it's impossible for modem to guess correctly all the time. All the modem can do is try to be consistent and hope another device is doing same things. Imagine you bring your card from another Cdma/Lte device to your new Cdma/Lte device: if this modem uses different fdn file, it won't work as all existing entries won't be there. Another example is when the modem's guess is wrong for files like csim/ef_li (7FFF 6F3A) versus usim/ef_adn (7FFF 6F3A). They have same ef_ids so Android really should pass aid of the app it wants to access. Without aids there is no way modem can know for sure which file Android wants to read! However, in the current code even Android doesn't know which aid it wants to read file from since CdmaLteRecords has only 1 aid. All of these problems cause more and more hacks, both in the modem and in Android side. UiccController cleans up current code and provides framework to work with multiple Uicc applications at the same time. Change-Id: I60216887b14140bdf833a8ed579ba16cad932bdc
Diffstat (limited to 'src/java')
-rw-r--r--src/java/com/android/internal/telephony/CsimFileHandler.java71
-rw-r--r--src/java/com/android/internal/telephony/IccCard.java848
-rw-r--r--src/java/com/android/internal/telephony/IccCardApplicationStatus.java (renamed from src/java/com/android/internal/telephony/IccCardApplication.java)2
-rw-r--r--src/java/com/android/internal/telephony/IccCardProxy.java690
-rw-r--r--src/java/com/android/internal/telephony/IccCardStatus.java79
-rw-r--r--src/java/com/android/internal/telephony/IccConstants.java5
-rw-r--r--src/java/com/android/internal/telephony/IccFileHandler.java32
-rw-r--r--src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java4
-rw-r--r--src/java/com/android/internal/telephony/IccRecords.java38
-rwxr-xr-xsrc/java/com/android/internal/telephony/PhoneBase.java19
-rw-r--r--src/java/com/android/internal/telephony/PhoneFactory.java4
-rw-r--r--src/java/com/android/internal/telephony/PhoneProxy.java15
-rwxr-xr-xsrc/java/com/android/internal/telephony/RIL.java44
-rwxr-xr-xsrc/java/com/android/internal/telephony/ServiceStateTracker.java14
-rw-r--r--src/java/com/android/internal/telephony/UiccCard.java358
-rw-r--r--src/java/com/android/internal/telephony/UiccCardApplication.java699
-rw-r--r--src/java/com/android/internal/telephony/UsimFileHandler.java87
-rw-r--r--src/java/com/android/internal/telephony/cat/CatService.java48
-rw-r--r--src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java69
-rwxr-xr-xsrc/java/com/android/internal/telephony/cdma/CDMAPhone.java30
-rwxr-xr-xsrc/java/com/android/internal/telephony/cdma/CdmaConnection.java11
-rw-r--r--src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java14
-rwxr-xr-xsrc/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java17
-rw-r--r--src/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java79
-rwxr-xr-xsrc/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java452
-rwxr-xr-xsrc/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java39
-rw-r--r--src/java/com/android/internal/telephony/cdma/RuimFileHandler.java31
-rwxr-xr-xsrc/java/com/android/internal/telephony/cdma/RuimRecords.java390
-rw-r--r--src/java/com/android/internal/telephony/gsm/GSMPhone.java33
-rw-r--r--src/java/com/android/internal/telephony/gsm/GsmConnection.java9
-rw-r--r--src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java10
-rw-r--r--src/java/com/android/internal/telephony/gsm/GsmMmiCode.java47
-rwxr-xr-xsrc/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java29
-rw-r--r--src/java/com/android/internal/telephony/gsm/SIMFileHandler.java29
-rwxr-xr-xsrc/java/com/android/internal/telephony/gsm/SIMRecords.java79
-rw-r--r--src/java/com/android/internal/telephony/ims/IsimFileHandler.java58
-rw-r--r--src/java/com/android/internal/telephony/ims/IsimUiccRecords.java157
-rw-r--r--src/java/com/android/internal/telephony/uicc/README1
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccController.java232
39 files changed, 3080 insertions, 1793 deletions
diff --git a/src/java/com/android/internal/telephony/CsimFileHandler.java b/src/java/com/android/internal/telephony/CsimFileHandler.java
new file mode 100644
index 0000000..979d1d2
--- /dev/null
+++ b/src/java/com/android/internal/telephony/CsimFileHandler.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006, 2012 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;
+
+import android.util.Log;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.UiccCardApplication;
+
+/**
+ * {@hide}
+ * This class should be used to access files in CSIM ADF
+ */
+public final class CsimFileHandler extends IccFileHandler implements IccConstants {
+ static final String LOG_TAG = "RIL_CsimFH";
+
+ public CsimFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
+ super(app, aid, ci);
+ }
+
+ @Override
+ protected String getEFPath(int efid) {
+ switch(efid) {
+ case EF_SMS:
+ case EF_CST:
+ case EF_FDN:
+ case EF_MSISDN:
+ case EF_RUIM_SPN:
+ case EF_CSIM_LI:
+ case EF_CSIM_MDN:
+ case EF_CSIM_IMSIM:
+ case EF_CSIM_CDMAHOME:
+ case EF_CSIM_EPRL:
+ return MF_SIM + DF_ADF;
+ }
+ String path = getCommonIccEFPath(efid);
+ if (path == null) {
+ // The EFids in UICC phone book entries are decided by the card manufacturer.
+ // So if we don't match any of the cases above and if its a UICC return
+ // the global 3g phone book path.
+ return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
+ }
+ return path;
+ }
+
+ @Override
+ protected void logd(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+
+ @Override
+ protected void loge(String msg) {
+ Log.e(LOG_TAG, msg);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/IccCard.java b/src/java/com/android/internal/telephony/IccCard.java
index 648b73e..f1ac581 100644
--- a/src/java/com/android/internal/telephony/IccCard.java
+++ b/src/java/com/android/internal/telephony/IccCard.java
@@ -16,277 +16,58 @@
package com.android.internal.telephony;
-import static android.Manifest.permission.READ_PHONE_STATE;
-import android.app.ActivityManagerNative;
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
-import android.os.PowerManager;
-import android.os.Registrant;
-import android.os.RegistrantList;
-import android.util.Log;
-import android.view.WindowManager;
-import com.android.internal.telephony.PhoneBase;
-import com.android.internal.telephony.CommandsInterface.RadioState;
-import com.android.internal.telephony.gsm.GSMPhone;
-import com.android.internal.telephony.gsm.SIMFileHandler;
-import com.android.internal.telephony.gsm.SIMRecords;
-import com.android.internal.telephony.sip.SipPhone;
-import com.android.internal.telephony.cat.CatService;
-import com.android.internal.telephony.cdma.CDMALTEPhone;
-import com.android.internal.telephony.cdma.CDMAPhone;
-import com.android.internal.telephony.cdma.CdmaLteUiccFileHandler;
-import com.android.internal.telephony.cdma.CdmaLteUiccRecords;
-import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
-import com.android.internal.telephony.cdma.RuimFileHandler;
-import com.android.internal.telephony.cdma.RuimRecords;
-
-import com.android.internal.R;
+import com.android.internal.telephony.IccCardConstants.State;
/**
* {@hide}
+ * @Deprecated use UiccController.getUiccCard instead.
+ *
+ * Integrated Circuit Card (ICC) interface
+ * An object of a class implementing this interface is used by external
+ * apps (specifically PhoneApp) to perform icc card related functionality.
+ *
+ * Apps (those that have access to Phone object) can retrieve this object
+ * by calling phone.getIccCard()
+ *
+ * This interface is implemented by IccCardProxy and the object PhoneApp
+ * gets when it calls getIccCard is IccCardProxy.
*/
-public class IccCard {
- protected String mLogTag;
- protected boolean mDbg;
-
- protected IccCardStatus mIccCardStatus = null;
- protected IccCardConstants.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 IccRecords mIccRecords;
- private IccFileHandler mIccFileHandler;
- private CatService mCatService;
-
- 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;
- private boolean mIccPinLocked = true; // Default to locked
- private boolean mIccFdnEnabled = false; // Default to disabled.
- // Will be updated when SIM_READY.
-
- /* Parameter is3gpp's values to be passed to constructor */
- public final static boolean CARD_IS_3GPP = true;
- public final static boolean CARD_IS_NOT_3GPP = false;
-
- 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;
- protected static final int EVENT_ICC_READY = 6;
- private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 7;
- private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 8;
- private static final int EVENT_CHANGE_ICC_PASSWORD_DONE = 9;
- private static final int EVENT_QUERY_FACILITY_FDN_DONE = 10;
- private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 11;
- 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;
-
- public IccCardConstants.State getState() {
- if (mState == null) {
- switch(mPhone.mCM.getRadioState()) {
- /* This switch block must not return anything in
- * IccCardConstants.State.isLocked() or IccCardConstants.State.ABSENT.
- * If it does, handleSimStatus() may break
- */
- case RADIO_OFF:
- case RADIO_UNAVAILABLE:
- return IccCardConstants.State.UNKNOWN;
- default:
- if (!is3gpp && !isSubscriptionFromIccCard) {
- // CDMA can get subscription from NV. In that case,
- // subscription is ready as soon as Radio is ON.
- return IccCardConstants.State.READY;
- }
- }
- } else {
- return mState;
- }
-
- return IccCardConstants.State.UNKNOWN;
- }
-
- public IccCard(PhoneBase phone, IccCardStatus ics, String logTag, boolean dbg) {
- mLogTag = logTag;
- mDbg = dbg;
- if (mDbg) log("Creating");
- update(phone, ics);
- mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(),
- mPhone.mCM, mHandler, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
- mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
- mPhone.mCM.registerForOn(mHandler, EVENT_RADIO_ON, null);
- }
-
- public void dispose() {
- if (mDbg) log("Disposing card type " + (is3gpp ? "3gpp" : "3gpp2"));
- mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
- mPhone.mCM.unregisterForOn(mHandler);
- mCatService.dispose();
- mCdmaSSM.dispose(mHandler);
- mIccRecords.dispose();
- mIccFileHandler.dispose();
- }
-
- public void update(PhoneBase phone, IccCardStatus ics) {
- if (phone != mPhone) {
- PhoneBase oldPhone = mPhone;
- mPhone = phone;
- log("Update");
- if (phone instanceof GSMPhone) {
- is3gpp = true;
- } else if (phone instanceof CDMALTEPhone){
- is3gpp = true;
- } else if (phone instanceof CDMAPhone){
- is3gpp = false;
- } else if (phone instanceof SipPhone){
- is3gpp = true;
- } else {
- throw new RuntimeException("Update: Unhandled phone type. Critical error!" +
- phone.getPhoneName());
- }
-
-
- if (phone.mCM.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE
- && phone instanceof CDMALTEPhone) {
- mIccFileHandler = new CdmaLteUiccFileHandler(this, "", mPhone.mCM);
- mIccRecords = new CdmaLteUiccRecords(this, mPhone.mContext, mPhone.mCM);
- } else {
- // Correct aid will be set later (when GET_SIM_STATUS returns)
- mIccFileHandler = is3gpp ? new SIMFileHandler(this, "", mPhone.mCM) :
- new RuimFileHandler(this, "", mPhone.mCM);
- mIccRecords = is3gpp ? new SIMRecords(this, mPhone.mContext, mPhone.mCM) :
- new RuimRecords(this, mPhone.mContext, mPhone.mCM);
- }
- mCatService = CatService.getInstance(mPhone.mCM, mIccRecords, mPhone.mContext,
- mIccFileHandler, this);
- }
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_GET_ICC_STATUS_DONE, ics));
- }
-
- protected void finalize() {
- if (mDbg) log("[IccCard] Finalized card type " + (is3gpp ? "3gpp" : "3gpp2"));
- }
+public interface IccCard {
+ /**
+ * @return combined Card and current App state
+ */
+ public State getState();
- public IccRecords getIccRecords() {
- return mIccRecords;
- }
+ /**
+ * @return IccRecords object belonging to current UiccCardApplication
+ */
+ public IccRecords getIccRecords();
- public IccFileHandler getIccFileHandler() {
- return mIccFileHandler;
- }
+ /**
+ * @return IccFileHandler object belonging to current UiccCardApplication
+ */
+ public IccFileHandler getIccFileHandler();
/**
* Notifies handler of any transition into IccCardConstants.State.ABSENT
*/
- public void registerForAbsent(Handler h, int what, Object obj) {
- Registrant r = new Registrant (h, what, obj);
-
- mAbsentRegistrants.add(r);
-
- if (getState() == IccCardConstants.State.ABSENT) {
- r.notifyRegistrant();
- }
- }
-
- public void unregisterForAbsent(Handler h) {
- mAbsentRegistrants.remove(h);
- }
+ public void registerForAbsent(Handler h, int what, Object obj);
+ public void unregisterForAbsent(Handler h);
/**
* Notifies handler of any transition into IccCardConstants.State.NETWORK_LOCKED
*/
- public void registerForNetworkLocked(Handler h, int what, Object obj) {
- Registrant r = new Registrant (h, what, obj);
-
- mNetworkLockedRegistrants.add(r);
-
- if (getState() == IccCardConstants.State.NETWORK_LOCKED) {
- r.notifyRegistrant();
- }
- }
-
- public void unregisterForNetworkLocked(Handler h) {
- mNetworkLockedRegistrants.remove(h);
- }
+ public void registerForNetworkLocked(Handler h, int what, Object obj);
+ public void unregisterForNetworkLocked(Handler h);
/**
* Notifies handler of any transition into IccCardConstants.State.isPinLocked()
*/
- public void registerForLocked(Handler h, int what, Object obj) {
- Registrant r = new Registrant (h, what, obj);
-
- mPinLockedRegistrants.add(r);
-
- if (getState().isPinLocked()) {
- r.notifyRegistrant();
- }
- }
-
- public void unregisterForLocked(Handler h) {
- 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() == IccCardConstants.State.READY) {
- r.notifyRegistrant(new AsyncResult(null, null, null));
- }
- }
- }
-
- public void unregisterForReady(Handler h) {
- synchronized (mStateMonitor) {
- mReadyRegistrants.remove(h);
- }
- }
-
- public IccCardConstants.State getRuimState() {
- if(mIccCardStatus != null) {
- return getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
- } else {
- return IccCardConstants.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() == IccCardConstants.State.READY &&
- getRuimState() == IccCardConstants.State.READY ) {
- r.notifyRegistrant(new AsyncResult(null, null, null));
- }
- }
- }
-
- public void unregisterForRuimReady(Handler h) {
- synchronized (mStateMonitor) {
- mRuimReadyRegistrants.remove(h);
- }
- }
+ public void registerForLocked(Handler h, int what, Object obj);
+ public void unregisterForLocked(Handler h);
/**
* Supply the ICC PIN to the ICC
@@ -305,29 +86,28 @@ public class IccCard {
* instanceof com.android.internal.telephony.gsm.CommandException)
* && ((CommandException)(((AsyncResult)onComplete.obj).exception))
* .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
- *
- *
*/
+ public void supplyPin (String pin, Message onComplete);
- public void supplyPin (String pin, Message onComplete) {
- mPhone.mCM.supplyIccPin(pin, onComplete);
- }
-
- public void supplyPuk (String puk, String newPin, Message onComplete) {
- mPhone.mCM.supplyIccPuk(puk, newPin, onComplete);
- }
+ /**
+ * Supply the ICC PUK to the ICC
+ */
+ public void supplyPuk (String puk, String newPin, Message onComplete);
- public void supplyPin2 (String pin2, Message onComplete) {
- mPhone.mCM.supplyIccPin2(pin2, onComplete);
- }
+ /**
+ * Supply the ICC PIN2 to the ICC
+ */
+ public void supplyPin2 (String pin2, Message onComplete);
- public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
- mPhone.mCM.supplyIccPuk2(puk2, newPin2, onComplete);
- }
+ /**
+ * Supply the ICC PUK2 to the ICC
+ */
+ public void supplyPuk2 (String puk2, String newPin2, Message onComplete);
- public void supplyNetworkDepersonalization (String pin, Message onComplete) {
- mPhone.mCM.supplyNetworkDepersonalization(pin, onComplete);
- }
+ /**
+ * Supply Network depersonalization code to the RIL
+ */
+ public void supplyNetworkDepersonalization (String pin, Message onComplete);
/**
* Check whether ICC pin lock is enabled
@@ -336,9 +116,7 @@ public class IccCard {
* @return true for ICC locked enabled
* false for ICC locked disabled
*/
- public boolean getIccLockEnabled() {
- return mIccPinLocked;
- }
+ public boolean getIccLockEnabled();
/**
* Check whether ICC fdn (fixed dialing number) is enabled
@@ -347,9 +125,7 @@ public class IccCard {
* @return true for ICC fdn enabled
* false for ICC fdn disabled
*/
- public boolean getIccFdnEnabled() {
- return mIccFdnEnabled;
- }
+ public boolean getIccFdnEnabled();
/**
* Set the ICC pin lock enabled or disabled
@@ -363,18 +139,7 @@ public class IccCard {
* ((AsyncResult)onComplete.obj).exception != null on fail
*/
public void setIccLockEnabled (boolean enabled,
- String password, Message onComplete) {
- int serviceClassX;
- serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
- CommandsInterface.SERVICE_CLASS_DATA +
- CommandsInterface.SERVICE_CLASS_FAX;
-
- mDesiredPinLocked = enabled;
-
- mPhone.mCM.setFacilityLock(CommandsInterface.CB_FACILITY_BA_SIM,
- enabled, password, serviceClassX,
- mHandler.obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
- }
+ String password, Message onComplete);
/**
* Set the ICC fdn enabled or disabled
@@ -388,19 +153,7 @@ public class IccCard {
* ((AsyncResult)onComplete.obj).exception != null on fail
*/
public void setIccFdnEnabled (boolean enabled,
- String password, Message onComplete) {
- int serviceClassX;
- serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
- CommandsInterface.SERVICE_CLASS_DATA +
- CommandsInterface.SERVICE_CLASS_FAX +
- CommandsInterface.SERVICE_CLASS_SMS;
-
- mDesiredFdnEnabled = enabled;
-
- mPhone.mCM.setFacilityLock(CommandsInterface.CB_FACILITY_BA_FD,
- enabled, password, serviceClassX,
- mHandler.obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
- }
+ String password, Message onComplete);
/**
* Change the ICC password used in ICC pin lock
@@ -414,11 +167,7 @@ public class IccCard {
* ((AsyncResult)onComplete.obj).exception != null on fail
*/
public void changeIccLockPassword(String oldPassword, String newPassword,
- Message onComplete) {
- mPhone.mCM.changeIccPin(oldPassword, newPassword,
- mHandler.obtainMessage(EVENT_CHANGE_ICC_PASSWORD_DONE, onComplete));
-
- }
+ Message onComplete);
/**
* Change the ICC password used in ICC fdn enable
@@ -432,12 +181,7 @@ public class IccCard {
* ((AsyncResult)onComplete.obj).exception != null on fail
*/
public void changeIccFdnPassword(String oldPassword, String newPassword,
- Message onComplete) {
- mPhone.mCM.changeIccPin2(oldPassword, newPassword,
- mHandler.obtainMessage(EVENT_CHANGE_ICC_PASSWORD_DONE, onComplete));
-
- }
-
+ Message onComplete);
/**
* Returns service provider name stored in ICC card.
@@ -455,490 +199,16 @@ public class IccCard {
* yet available
*
*/
- public String getServiceProviderName () {
- return mIccRecords.getServiceProviderName();
- }
-
- protected void updateStateProperty() {
- mPhone.setSystemProperty(TelephonyProperties.PROPERTY_SIM_STATE, getState().toString());
- }
-
- private void getIccCardStatusDone(IccCardStatus ics) {
- handleIccCardStatus(ics);
- }
-
- private void handleIccCardStatus(IccCardStatus newCardStatus) {
- boolean transitionedIntoPinLocked;
- boolean transitionedIntoAbsent;
- boolean transitionedIntoNetworkLocked;
- boolean transitionedIntoPermBlocked;
- boolean isIccCardRemoved;
- boolean isIccCardAdded;
-
- IccCardConstants.State oldState, newState;
- IccCardConstants.State oldRuimState = getRuimState();
-
- oldState = mState;
- mIccCardStatus = newCardStatus;
- newState = getIccCardState();
-
- synchronized (mStateMonitor) {
- mState = newState;
- updateStateProperty();
- if (oldState != IccCardConstants.State.READY &&
- newState == IccCardConstants.State.READY) {
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_ICC_READY));
- mReadyRegistrants.notifyRegistrants();
- } else if (newState.isPinLocked()) {
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_ICC_LOCKED));
- }
- if (oldRuimState != IccCardConstants.State.READY &&
- getRuimState() == IccCardConstants.State.READY) {
- mRuimReadyRegistrants.notifyRegistrants();
- }
- }
-
- transitionedIntoPinLocked = (
- (oldState != IccCardConstants.State.PIN_REQUIRED &&
- newState == IccCardConstants.State.PIN_REQUIRED)
- || (oldState != IccCardConstants.State.PUK_REQUIRED &&
- newState == IccCardConstants.State.PUK_REQUIRED));
- transitionedIntoAbsent = (oldState != IccCardConstants.State.ABSENT &&
- newState == IccCardConstants.State.ABSENT);
- transitionedIntoNetworkLocked = (oldState != IccCardConstants.State.NETWORK_LOCKED
- && newState == IccCardConstants.State.NETWORK_LOCKED);
- transitionedIntoPermBlocked = (oldState != IccCardConstants.State.PERM_DISABLED
- && newState == IccCardConstants.State.PERM_DISABLED);
- isIccCardRemoved = (oldState != null && oldState.iccCardExist() &&
- newState == IccCardConstants.State.ABSENT);
- isIccCardAdded = (oldState == IccCardConstants.State.ABSENT &&
- newState != null && newState.iccCardExist());
-
- if (transitionedIntoPinLocked) {
- if (mDbg) log("Notify SIM pin or puk locked.");
- mPinLockedRegistrants.notifyRegistrants();
- broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOCKED,
- (newState == IccCardConstants.State.PIN_REQUIRED) ?
- IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN :
- IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK);
- } else if (transitionedIntoAbsent) {
- if (mDbg) log("Notify SIM missing.");
- mAbsentRegistrants.notifyRegistrants();
- broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_ABSENT, null);
- } else if (transitionedIntoNetworkLocked) {
- if (mDbg) log("Notify SIM network locked.");
- mNetworkLockedRegistrants.notifyRegistrants();
- broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOCKED,
- IccCardConstants.INTENT_VALUE_LOCKED_NETWORK);
- } else if (transitionedIntoPermBlocked) {
- if (mDbg) log("Notify SIM permanently disabled.");
- broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_ABSENT,
- IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED);
- }
-
- if (isIccCardRemoved) {
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
- } else if (isIccCardAdded) {
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
- }
-
- // Call onReady Record(s) on the IccCard becomes ready (not NV)
- if (oldState != IccCardConstants.State.READY && newState == IccCardConstants.State.READY &&
- (is3gpp || isSubscriptionFromIccCard)) {
- mIccFileHandler.setAid(getAid());
- broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_READY, null);
- mIccRecords.onReady();
- }
- }
-
- private void onIccSwap(boolean isAdded) {
- // TODO: Here we assume the device can't handle SIM hot-swap
- // and has to reboot. We may want to add a property,
- // e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support
- // hot-swap.
- DialogInterface.OnClickListener listener = null;
-
-
- // TODO: SimRecords is not reset while SIM ABSENT (only reset while
- // Radio_off_or_not_available). Have to reset in both both
- // added or removed situation.
- listener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- if (mDbg) log("Reboot due to SIM swap");
- PowerManager pm = (PowerManager) mPhone.getContext()
- .getSystemService(Context.POWER_SERVICE);
- pm.reboot("SIM is added.");
- }
- }
-
- };
-
- Resources r = Resources.getSystem();
-
- String title = (isAdded) ? r.getString(R.string.sim_added_title) :
- r.getString(R.string.sim_removed_title);
- String message = (isAdded) ? r.getString(R.string.sim_added_message) :
- r.getString(R.string.sim_removed_message);
- String buttonTxt = r.getString(R.string.sim_restart_button);
-
- AlertDialog dialog = new AlertDialog.Builder(mPhone.getContext())
- .setTitle(title)
- .setMessage(message)
- .setPositiveButton(buttonTxt, listener)
- .create();
- dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
- dialog.show();
- }
+ public String getServiceProviderName ();
/**
- * Interperate EVENT_QUERY_FACILITY_LOCK_DONE
- * @param ar is asyncResult of Query_Facility_Locked
+ * Checks if an Application of specified type present on the card
+ * @param type is AppType to look for
*/
- private void onQueryFdnEnabled(AsyncResult ar) {
- if(ar.exception != null) {
- if(mDbg) log("Error in querying facility lock:" + ar.exception);
- return;
- }
-
- int[] ints = (int[])ar.result;
- if(ints.length != 0) {
- mIccFdnEnabled = (0!=ints[0]);
- if(mDbg) log("Query facility lock : " + mIccFdnEnabled);
- } else {
- Log.e(mLogTag, "[IccCard] Bogus facility lock response");
- }
- }
-
- /**
- * Interperate EVENT_QUERY_FACILITY_LOCK_DONE
- * @param ar is asyncResult of Query_Facility_Locked
- */
- private void onQueryFacilityLock(AsyncResult ar) {
- if(ar.exception != null) {
- if (mDbg) log("Error in querying facility lock:" + ar.exception);
- return;
- }
-
- int[] ints = (int[])ar.result;
- if(ints.length != 0) {
- mIccPinLocked = (0!=ints[0]);
- if(mDbg) log("Query facility lock : " + mIccPinLocked);
- } else {
- Log.e(mLogTag, "[IccCard] Bogus facility lock response");
- }
- }
-
- public void broadcastIccStateChangedIntent(String value, String reason) {
- Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- intent.putExtra(PhoneConstants.PHONE_NAME_KEY, mPhone.getPhoneName());
- intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
- intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
- if(mDbg) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " + value
- + " reason " + reason);
- ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE);
- }
-
- protected Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg){
- AsyncResult ar;
- int serviceClassX;
-
- serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
- CommandsInterface.SERVICE_CLASS_DATA +
- CommandsInterface.SERVICE_CLASS_FAX;
-
- if (!mPhone.mIsTheCurrentActivePhone) {
- Log.e(mLogTag, "Received message " + msg + "[" + msg.what
- + "] while being destroyed. Ignoring.");
- return;
- }
-
- switch (msg.what) {
- case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
- mState = null;
- updateStateProperty();
- broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_NOT_READY,
- null);
- break;
- case EVENT_RADIO_ON:
- if (!is3gpp) {
- handleCdmaSubscriptionSource();
- }
- break;
- 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:
- IccCardStatus cs = (IccCardStatus)msg.obj;
-
- getIccCardStatusDone(cs);
- break;
- case EVENT_QUERY_FACILITY_LOCK_DONE:
- ar = (AsyncResult)msg.obj;
- onQueryFacilityLock(ar);
- break;
- case EVENT_QUERY_FACILITY_FDN_DONE:
- ar = (AsyncResult)msg.obj;
- onQueryFdnEnabled(ar);
- break;
- case EVENT_CHANGE_FACILITY_LOCK_DONE:
- ar = (AsyncResult)msg.obj;
- if (ar.exception == null) {
- mIccPinLocked = mDesiredPinLocked;
- if (mDbg) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: " +
- "mIccPinLocked= " + mIccPinLocked);
- } else {
- Log.e(mLogTag, "Error change facility lock with exception "
- + ar.exception);
- }
- AsyncResult.forMessage(((Message)ar.userObj)).exception
- = ar.exception;
- ((Message)ar.userObj).sendToTarget();
- break;
- case EVENT_CHANGE_FACILITY_FDN_DONE:
- ar = (AsyncResult)msg.obj;
-
- if (ar.exception == null) {
- mIccFdnEnabled = mDesiredFdnEnabled;
- if (mDbg) log("EVENT_CHANGE_FACILITY_FDN_DONE: " +
- "mIccFdnEnabled=" + mIccFdnEnabled);
- } else {
- Log.e(mLogTag, "Error change facility fdn with exception "
- + ar.exception);
- }
- AsyncResult.forMessage(((Message)ar.userObj)).exception
- = ar.exception;
- ((Message)ar.userObj).sendToTarget();
- break;
- case EVENT_CHANGE_ICC_PASSWORD_DONE:
- ar = (AsyncResult)msg.obj;
- if(ar.exception != null) {
- Log.e(mLogTag, "Error in change sim password with exception"
- + ar.exception);
- }
- AsyncResult.forMessage(((Message)ar.userObj)).exception
- = ar.exception;
- ((Message)ar.userObj).sendToTarget();
- break;
- case EVENT_CARD_REMOVED:
- onIccSwap(false);
- break;
- case EVENT_CARD_ADDED:
- onIccSwap(true);
- break;
- default:
- Log.e(mLogTag, "[IccCard] Unknown Event " + msg.what);
- }
- }
- };
-
- 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 IccCardConstants.State getIccCardState() {
- if(!is3gpp && !isSubscriptionFromIccCard) {
- // CDMA can get subscription from NV. In that case,
- // subscription is ready as soon as Radio is ON.
- return IccCardConstants.State.READY;
- }
-
- if (mIccCardStatus == null) {
- Log.e(mLogTag, "[IccCard] IccCardStatus is null");
- return IccCardConstants.State.ABSENT;
- }
-
- // this is common for all radio technologies
- if (!mIccCardStatus.getCardState().isCardPresent()) {
- return IccCardConstants.State.ABSENT;
- }
-
- RadioState currentRadioState = mPhone.mCM.getRadioState();
- // check radio technology
- if( currentRadioState == RadioState.RADIO_OFF ||
- currentRadioState == RadioState.RADIO_UNAVAILABLE) {
- return IccCardConstants.State.NOT_READY;
- }
-
- if( currentRadioState == RadioState.RADIO_ON ) {
- IccCardConstants.State csimState =
- getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
- IccCardConstants.State usimState =
- getAppState(mIccCardStatus.getGsmUmtsSubscriptionAppIndex());
-
- if(mDbg) log("USIM=" + usimState + " CSIM=" + csimState);
-
- if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
- // UICC card contains both USIM and CSIM
- // Return consolidated status
- return getConsolidatedState(csimState, usimState, csimState);
- }
-
- // check for CDMA radio technology
- if (!is3gpp) {
- return csimState;
- }
- return usimState;
- }
-
- return IccCardConstants.State.ABSENT;
- }
-
- private IccCardConstants.State getAppState(int appIndex) {
- IccCardApplication app;
- if (appIndex >= 0 && appIndex < IccCardStatus.CARD_MAX_APPS) {
- app = mIccCardStatus.getApplication(appIndex);
- } else {
- Log.e(mLogTag, "[IccCard] Invalid Subscription Application index:" + appIndex);
- return IccCardConstants.State.ABSENT;
- }
-
- if (app == null) {
- Log.e(mLogTag, "[IccCard] Subscription Application in not present");
- return IccCardConstants.State.ABSENT;
- }
-
- // check if PIN required
- if (app.pin1.isPermBlocked()) {
- return IccCardConstants.State.PERM_DISABLED;
- }
- if (app.app_state.isPinRequired()) {
- return IccCardConstants.State.PIN_REQUIRED;
- }
- if (app.app_state.isPukRequired()) {
- return IccCardConstants.State.PUK_REQUIRED;
- }
- if (app.app_state.isSubscriptionPersoEnabled()) {
- return IccCardConstants.State.NETWORK_LOCKED;
- }
- if (app.app_state.isAppReady()) {
- return IccCardConstants.State.READY;
- }
- if (app.app_state.isAppNotReady()) {
- return IccCardConstants.State.NOT_READY;
- }
- return IccCardConstants.State.NOT_READY;
- }
-
- private IccCardConstants.State getConsolidatedState(IccCardConstants.State left,
- IccCardConstants.State right, IccCardConstants.State preferredState) {
- // Check if either is absent.
- if (right == IccCardConstants.State.ABSENT) return left;
- if (left == IccCardConstants.State.ABSENT) return right;
-
- // Only if both are ready, return ready
- if ((left == IccCardConstants.State.READY) && (right == IccCardConstants.State.READY)) {
- return IccCardConstants.State.READY;
- }
-
- // Case one is ready, but the other is not.
- if (((right == IccCardConstants.State.NOT_READY) &&
- (left == IccCardConstants.State.READY)) ||
- ((left == IccCardConstants.State.NOT_READY) &&
- (right == IccCardConstants.State.READY))) {
- return IccCardConstants.State.NOT_READY;
- }
-
- // At this point, the other state is assumed to be one of locked state
- if (right == IccCardConstants.State.NOT_READY) return left;
- if (left == IccCardConstants.State.NOT_READY) return right;
-
- // At this point, FW currently just assumes the status will be
- // consistent across the applications...
- return preferredState;
- }
-
- public boolean isApplicationOnIcc(IccCardApplication.AppType type) {
- if (mIccCardStatus == null) return false;
-
- for (int i = 0 ; i < mIccCardStatus.getNumApplications(); i++) {
- IccCardApplication app = mIccCardStatus.getApplication(i);
- if (app != null && app.app_type == type) {
- return true;
- }
- }
- return false;
- }
+ public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type);
/**
* @return true if a ICC card is present
*/
- public boolean hasIccCard() {
- if (mIccCardStatus == null) {
- return false;
- } else {
- // Returns ICC card status for both GSM and CDMA mode
- return mIccCardStatus.getCardState().isCardPresent();
- }
- }
-
- private void log(String msg) {
- Log.d(mLogTag, "[IccCard] " + msg);
- }
-
- private void loge(String msg) {
- Log.e(mLogTag, "[IccCard] " + msg);
- }
-
- protected int getCurrentApplicationIndex() {
- if (is3gpp) {
- return mIccCardStatus.getGsmUmtsSubscriptionAppIndex();
- } else {
- return mIccCardStatus.getCdmaSubscriptionAppIndex();
- }
- }
-
- public String getAid() {
- String aid = "";
- if (mIccCardStatus == null) {
- return aid;
- }
-
- int appIndex = getCurrentApplicationIndex();
-
- if (appIndex >= 0 && appIndex < IccCardStatus.CARD_MAX_APPS) {
- IccCardApplication app = mIccCardStatus.getApplication(appIndex);
- if (app != null) {
- aid = app.aid;
- } else {
- Log.e(mLogTag, "[IccCard] getAid: no current application index=" + appIndex);
- }
- } else {
- Log.e(mLogTag, "[IccCard] getAid: Invalid Subscription Application index=" + appIndex);
- }
-
- return aid;
- }
+ public boolean hasIccCard();
}
diff --git a/src/java/com/android/internal/telephony/IccCardApplication.java b/src/java/com/android/internal/telephony/IccCardApplicationStatus.java
index abb740e..f3f22ea 100644
--- a/src/java/com/android/internal/telephony/IccCardApplication.java
+++ b/src/java/com/android/internal/telephony/IccCardApplicationStatus.java
@@ -24,7 +24,7 @@ import com.android.internal.telephony.IccCardStatus.PinState;
*
* {@hide}
*/
-public class IccCardApplication {
+public class IccCardApplicationStatus {
public enum AppType{
APPTYPE_UNKNOWN,
APPTYPE_SIM,
diff --git a/src/java/com/android/internal/telephony/IccCardProxy.java b/src/java/com/android/internal/telephony/IccCardProxy.java
new file mode 100644
index 0000000..eef0c6f
--- /dev/null
+++ b/src/java/com/android/internal/telephony/IccCardProxy.java
@@ -0,0 +1,690 @@
+/*
+ * Copyright (C) 2012 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;
+
+import static android.Manifest.permission.READ_PHONE_STATE;
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
+import android.util.Log;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
+import com.android.internal.telephony.IccCardApplicationStatus.PersoSubState;
+import com.android.internal.telephony.IccCardStatus.CardState;
+import com.android.internal.telephony.IccCardStatus.PinState;
+import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
+import com.android.internal.telephony.uicc.UiccController;
+
+import static com.android.internal.telephony.Phone.CDMA_SUBSCRIPTION_NV;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_STATE;
+
+/**
+ * @Deprecated use {@link UiccController}.getUiccCard instead.
+ *
+ * The Phone App assumes that there is only one icc card, and one icc application
+ * available at a time. Moreover, it assumes such object (represented with IccCard)
+ * is available all the time (whether {@link RILConstants.RIL_REQUEST_GET_SIM_STATUS} returned
+ * or not, whether card has desired application or not, whether there really is a card in the
+ * slot or not).
+ *
+ * UiccController, however, can handle multiple instances of icc objects (multiple
+ * {@link UiccCardApplication}, multiple {@link IccFileHandler}, multiple {@link IccRecords})
+ * created and destroyed dynamically during phone operation.
+ *
+ * This class implements the IccCard interface that is always available (right after default
+ * phone object is constructed) to expose the current (based on voice radio technology)
+ * application on the uicc card, so that external apps won't break.
+ */
+
+public class IccCardProxy extends Handler implements IccCard {
+ private static final boolean DBG = true;
+ private static final String LOG_TAG = "RIL_IccCardProxy";
+
+ private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 1;
+ private static final int EVENT_RADIO_ON = 2;
+ private static final int EVENT_ICC_CHANGED = 3;
+ private static final int EVENT_ICC_ABSENT = 4;
+ private static final int EVENT_ICC_LOCKED = 5;
+ private static final int EVENT_APP_READY = 6;
+ private static final int EVENT_RECORDS_LOADED = 7;
+ private static final int EVENT_IMSI_READY = 8;
+ private static final int EVENT_NETWORK_LOCKED = 9;
+ private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 11;
+
+ private final Object mLock = new Object();
+ private Context mContext;
+ private CommandsInterface mCi;
+
+ private RegistrantList mAbsentRegistrants = new RegistrantList();
+ private RegistrantList mPinLockedRegistrants = new RegistrantList();
+ private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
+
+ private int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp?
+ private UiccController mUiccController = null;
+ private UiccCard mUiccCard = null;
+ private UiccCardApplication mUiccApplication = null;
+ private IccRecords mIccRecords = null;
+ private CdmaSubscriptionSourceManager mCdmaSSM = null;
+ private boolean mRadioOn = false;
+ private boolean mCdmaSubscriptionFromNv = false;
+ private boolean mIsMultimodeCdmaPhone =
+ SystemProperties.getBoolean("ro.config.multimode_cdma", false);
+ private boolean mQuietMode = false; // when set to true IccCardProxy will not broadcast
+ // ACTION_SIM_STATE_CHANGED intents
+ private boolean mInitialized = false;
+ private State mExternalState = State.UNKNOWN;
+
+ public IccCardProxy(Context context, CommandsInterface ci) {
+ log("Creating");
+ this.mContext = context;
+ this.mCi = ci;
+ mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context,
+ ci, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
+ mUiccController = UiccController.getInstance();
+ mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
+ ci.registerForOn(this,EVENT_RADIO_ON, null);
+ ci.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
+ setExternalState(State.NOT_READY);
+ }
+
+ public void dispose() {
+ synchronized (mLock) {
+ log("Disposing");
+ //Cleanup icc references
+ mUiccController.unregisterForIccChanged(this);
+ mUiccController = null;
+ mCi.unregisterForOn(this);
+ mCi.unregisterForOffOrNotAvailable(this);
+ mCdmaSSM.dispose(this);
+ }
+ }
+
+ /*
+ * The card application that the external world sees will be based on the
+ * voice radio technology only!
+ */
+ public void setVoiceRadioTech(int radioTech) {
+ synchronized (mLock) {
+ if (DBG) {
+ log("Setting radio tech " + ServiceState.rilRadioTechnologyToString(radioTech));
+ }
+ if (ServiceState.isGsm(radioTech)) {
+ mCurrentAppType = UiccController.APP_FAM_3GPP;
+ } else {
+ mCurrentAppType = UiccController.APP_FAM_3GPP2;
+ }
+ updateQuietMode();
+ }
+ }
+
+ /**
+ * In case of 3gpp2 we need to find out if subscription used is coming from
+ * NV in which case we shouldn't broadcast any sim states changes if at the
+ * same time ro.config.multimode_cdma property set to false.
+ */
+ private void updateQuietMode() {
+ synchronized (mLock) {
+ if (DBG) log("Updating quiet mode");
+ boolean oldQuietMode = mQuietMode;
+ boolean newQuietMode;
+ if (mCurrentAppType == UiccController.APP_FAM_3GPP) {
+ newQuietMode = false;
+ if (DBG) log("3GPP subscription -> QuietMode: " + newQuietMode);
+ } else {
+ int newSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource();
+ mCdmaSubscriptionFromNv = newSubscriptionSource == CDMA_SUBSCRIPTION_NV;
+ if (mCdmaSubscriptionFromNv && mIsMultimodeCdmaPhone) {
+ log("Cdma multimode phone detected. Forcing IccCardProxy into 3gpp mode");
+ mCurrentAppType = UiccController.APP_FAM_3GPP;
+ }
+ newQuietMode = mCdmaSubscriptionFromNv
+ && (mCurrentAppType == UiccController.APP_FAM_3GPP2)
+ && !mIsMultimodeCdmaPhone;
+ }
+
+ if (mQuietMode == false && newQuietMode == true) {
+ // Last thing to do before switching to quiet mode is
+ // broadcast ICC_READY
+ log("Switching to QuietMode.");
+ setExternalState(State.READY);
+ mQuietMode = newQuietMode;
+ } else if (mQuietMode == true && newQuietMode == false) {
+ if (DBG) log("Switching out from QuietMode. Force broadcast of current state:"
+ + mExternalState);
+ mQuietMode = newQuietMode;
+ setExternalState(mExternalState, true);
+ }
+ if (DBG) log("QuietMode is " + mQuietMode + " (app_type: " + mCurrentAppType + " nv: "
+ + mCdmaSubscriptionFromNv + " multimode: " + mIsMultimodeCdmaPhone + ")");
+ mInitialized = true;
+ sendMessage(obtainMessage(EVENT_ICC_CHANGED));
+ }
+ }
+
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_RADIO_OFF_OR_UNAVAILABLE:
+ mRadioOn = false;
+ break;
+ case EVENT_RADIO_ON:
+ mRadioOn = true;
+ if (!mInitialized) {
+ updateQuietMode();
+ }
+ break;
+ case EVENT_ICC_CHANGED:
+ if (mInitialized) {
+ updateIccAvailability();
+ }
+ break;
+ case EVENT_ICC_ABSENT:
+ mAbsentRegistrants.notifyRegistrants();
+ setExternalState(State.ABSENT);
+ break;
+ case EVENT_ICC_LOCKED:
+ processLockedState();
+ break;
+ case EVENT_APP_READY:
+ setExternalState(State.READY);
+ break;
+ case EVENT_RECORDS_LOADED:
+ broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
+ break;
+ case EVENT_IMSI_READY:
+ broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_IMSI, null);
+ break;
+ case EVENT_NETWORK_LOCKED:
+ mNetworkLockedRegistrants.notifyRegistrants();
+ setExternalState(State.NETWORK_LOCKED);
+ break;
+ case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
+ updateQuietMode();
+ break;
+ default:
+ loge("Unhandled message with number: " + msg.what);
+ break;
+ }
+ }
+
+ private void updateIccAvailability() {
+ synchronized (mLock) {
+ UiccCard newCard = mUiccController.getUiccCard();
+ CardState state = CardState.CARDSTATE_ABSENT;
+ UiccCardApplication newApp = null;
+ IccRecords newRecords = null;
+ if (newCard != null) {
+ state = newCard.getCardState();
+ newApp = newCard.getApplication(mCurrentAppType);
+ if (newApp != null) {
+ newRecords = newApp.getIccRecords();
+ }
+ }
+
+ if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) {
+ if (DBG) log("Icc changed. Reregestering.");
+ unregisterUiccCardEvents();
+ mUiccCard = newCard;
+ mUiccApplication = newApp;
+ mIccRecords = newRecords;
+ registerUiccCardEvents();
+ }
+
+ updateExternalState();
+ }
+ }
+
+ private void updateExternalState() {
+ if (mUiccCard == null || mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) {
+ if (mRadioOn) {
+ setExternalState(State.ABSENT);
+ } else {
+ setExternalState(State.NOT_READY);
+ }
+ return;
+ }
+
+ if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR ||
+ mUiccApplication == null) {
+ setExternalState(State.UNKNOWN);
+ return;
+ }
+
+ switch (mUiccApplication.getState()) {
+ case APPSTATE_UNKNOWN:
+ case APPSTATE_DETECTED:
+ setExternalState(State.UNKNOWN);
+ break;
+ case APPSTATE_PIN:
+ setExternalState(State.PIN_REQUIRED);
+ break;
+ case APPSTATE_PUK:
+ setExternalState(State.PUK_REQUIRED);
+ break;
+ case APPSTATE_SUBSCRIPTION_PERSO:
+ if (mUiccApplication.getPersoSubState() == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
+ setExternalState(State.NETWORK_LOCKED);
+ } else {
+ setExternalState(State.UNKNOWN);
+ }
+ break;
+ case APPSTATE_READY:
+ setExternalState(State.READY);
+ break;
+ }
+ }
+
+ private void registerUiccCardEvents() {
+ if (mUiccCard != null) mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null);
+ if (mUiccApplication != null) {
+ mUiccApplication.registerForReady(this, EVENT_APP_READY, null);
+ mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null);
+ mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null);
+ }
+ if (mIccRecords != null) {
+ mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null);
+ mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+ }
+ }
+
+ private void unregisterUiccCardEvents() {
+ if (mUiccCard != null) mUiccCard.unregisterForAbsent(this);
+ if (mUiccApplication != null) mUiccApplication.unregisterForReady(this);
+ if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this);
+ if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this);
+ if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this);
+ if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this);
+ }
+
+ private void broadcastIccStateChangedIntent(String value, String reason) {
+ synchronized (mLock) {
+ if (mQuietMode) {
+ log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " + value
+ + " reason " + reason);
+ return;
+ }
+
+ Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
+ intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
+ intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
+
+ if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " + value
+ + " reason " + reason);
+ ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE);
+ }
+ }
+
+ private void processLockedState() {
+ synchronized (mLock) {
+ if (mUiccApplication == null) {
+ //Don't need to do anything if non-existent application is locked
+ return;
+ }
+ PinState pin1State = mUiccApplication.getPin1State();
+ if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
+ setExternalState(State.PERM_DISABLED);
+ return;
+ }
+
+ AppState appState = mUiccApplication.getState();
+ switch (appState) {
+ case APPSTATE_PIN:
+ mPinLockedRegistrants.notifyRegistrants();
+ setExternalState(State.PIN_REQUIRED);
+ break;
+ case APPSTATE_PUK:
+ setExternalState(State.PUK_REQUIRED);
+ break;
+ }
+ }
+ }
+
+ private void setExternalState(State newState, boolean override) {
+ synchronized (mLock) {
+ if (!override && newState == mExternalState) {
+ return;
+ }
+ mExternalState = newState;
+ SystemProperties.set(PROPERTY_SIM_STATE, mExternalState.toString());
+ broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState),
+ getIccStateReason(mExternalState));
+ }
+ }
+
+ private void setExternalState(State newState) {
+ setExternalState(newState, false);
+ }
+
+ public boolean getIccRecordsLoaded() {
+ synchronized (mLock) {
+ if (mIccRecords != null) {
+ return mIccRecords.getRecordsLoaded();
+ }
+ return false;
+ }
+ }
+
+ private String getIccStateIntentString(State state) {
+ switch (state) {
+ case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT;
+ case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
+ case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
+ case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
+ case READY: return IccCardConstants.INTENT_VALUE_ICC_READY;
+ case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY;
+ case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED;
+ default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN;
+ }
+ }
+
+ /**
+ * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED)
+ * @return reason
+ */
+ private String getIccStateReason(State state) {
+ switch (state) {
+ case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN;
+ case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK;
+ case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK;
+ case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED;
+ default: return null;
+ }
+ }
+
+ /* IccCard interface implementation */
+ @Override
+ public State getState() {
+ synchronized (mLock) {
+ return mExternalState;
+ }
+ }
+
+ @Override
+ public IccRecords getIccRecords() {
+ synchronized (mLock) {
+ return mIccRecords;
+ }
+ }
+
+ @Override
+ public IccFileHandler getIccFileHandler() {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ return mUiccApplication.getIccFileHandler();
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Notifies handler of any transition into State.ABSENT
+ */
+ @Override
+ public void registerForAbsent(Handler h, int what, Object obj) {
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+
+ mAbsentRegistrants.add(r);
+
+ if (getState() == State.ABSENT) {
+ r.notifyRegistrant();
+ }
+ }
+ }
+
+ @Override
+ public void unregisterForAbsent(Handler h) {
+ synchronized (mLock) {
+ mAbsentRegistrants.remove(h);
+ }
+ }
+
+ /**
+ * Notifies handler of any transition into State.NETWORK_LOCKED
+ */
+ @Override
+ public void registerForNetworkLocked(Handler h, int what, Object obj) {
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+
+ mNetworkLockedRegistrants.add(r);
+
+ if (getState() == State.NETWORK_LOCKED) {
+ r.notifyRegistrant();
+ }
+ }
+ }
+
+ @Override
+ public void unregisterForNetworkLocked(Handler h) {
+ synchronized (mLock) {
+ mNetworkLockedRegistrants.remove(h);
+ }
+ }
+
+ /**
+ * Notifies handler of any transition into State.isPinLocked()
+ */
+ @Override
+ public void registerForLocked(Handler h, int what, Object obj) {
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+
+ mPinLockedRegistrants.add(r);
+
+ if (getState().isPinLocked()) {
+ r.notifyRegistrant();
+ }
+ }
+ }
+
+ @Override
+ public void unregisterForLocked(Handler h) {
+ synchronized (mLock) {
+ mPinLockedRegistrants.remove(h);
+ }
+ }
+
+ @Override
+ public void supplyPin(String pin, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.supplyPin(pin, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void supplyPuk(String puk, String newPin, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.supplyPuk(puk, newPin, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void supplyPin2(String pin2, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.supplyPin2(pin2, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void supplyPuk2(String puk2, String newPin2, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.supplyPuk2(puk2, newPin2, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void supplyNetworkDepersonalization(String pin, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.supplyNetworkDepersonalization(pin, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("CommandsInterface is not set.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public boolean getIccLockEnabled() {
+ synchronized (mLock) {
+ /* defaults to true, if ICC is absent */
+ Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccLockEnabled() : true;
+ return retValue;
+ }
+ }
+
+ @Override
+ public boolean getIccFdnEnabled() {
+ synchronized (mLock) {
+ Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnEnabled() : false;
+ return retValue;
+ }
+ }
+
+ @Override
+ public void setIccLockEnabled(boolean enabled, String password, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.setIccLockEnabled(enabled, password, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.setIccFdnEnabled(enabled, password, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) {
+ synchronized (mLock) {
+ if (mUiccApplication != null) {
+ mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete);
+ } else if (onComplete != null) {
+ Exception e = new RuntimeException("ICC card is absent.");
+ AsyncResult.forMessage(onComplete).exception = e;
+ onComplete.sendToTarget();
+ return;
+ }
+ }
+ }
+
+ @Override
+ public String getServiceProviderName() {
+ synchronized (mLock) {
+ if (mIccRecords != null) {
+ return mIccRecords.getServiceProviderName();
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
+ synchronized (mLock) {
+ Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false;
+ return retValue;
+ }
+ }
+
+ @Override
+ public boolean hasIccCard() {
+ synchronized (mLock) {
+ if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private void log(String s) {
+ Log.d(LOG_TAG, s);
+ }
+
+ private void loge(String msg) {
+ Log.e(LOG_TAG, msg);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/IccCardStatus.java b/src/java/com/android/internal/telephony/IccCardStatus.java
index a3bdd76..b4a5e68 100644
--- a/src/java/com/android/internal/telephony/IccCardStatus.java
+++ b/src/java/com/android/internal/telephony/IccCardStatus.java
@@ -57,19 +57,13 @@ public class IccCardStatus {
}
}
- private CardState mCardState;
- private PinState mUniversalPinState;
- private int mGsmUmtsSubscriptionAppIndex;
- private int mCdmaSubscriptionAppIndex;
- private int mImsSubscriptionAppIndex;
- private int mNumApplications;
-
- private ArrayList<IccCardApplication> mApplications =
- new ArrayList<IccCardApplication>(CARD_MAX_APPS);
-
- public CardState getCardState() {
- return mCardState;
- }
+ public CardState mCardState;
+ public PinState mUniversalPinState;
+ public int mGsmUmtsSubscriptionAppIndex;
+ public int mCdmaSubscriptionAppIndex;
+ public int mImsSubscriptionAppIndex;
+
+ public IccCardApplicationStatus[] mApplications;
public void setCardState(int state) {
switch(state) {
@@ -87,10 +81,6 @@ public class IccCardStatus {
}
}
- public PinState getUniversalPinState() {
- return mUniversalPinState;
- }
-
public void setUniversalPinState(int state) {
switch(state) {
case 0:
@@ -116,69 +106,34 @@ public class IccCardStatus {
}
}
- public int getGsmUmtsSubscriptionAppIndex() {
- return mGsmUmtsSubscriptionAppIndex;
- }
-
- public void setGsmUmtsSubscriptionAppIndex(int gsmUmtsSubscriptionAppIndex) {
- mGsmUmtsSubscriptionAppIndex = gsmUmtsSubscriptionAppIndex;
- }
-
- public int getCdmaSubscriptionAppIndex() {
- return mCdmaSubscriptionAppIndex;
- }
-
- public void setCdmaSubscriptionAppIndex(int cdmaSubscriptionAppIndex) {
- mCdmaSubscriptionAppIndex = cdmaSubscriptionAppIndex;
- }
-
- public int getImsSubscriptionAppIndex() {
- return mImsSubscriptionAppIndex;
- }
-
- public void setImsSubscriptionAppIndex(int imsSubscriptionAppIndex) {
- mImsSubscriptionAppIndex = imsSubscriptionAppIndex;
- }
-
- public int getNumApplications() {
- return mNumApplications;
- }
-
- public void setNumApplications(int numApplications) {
- mNumApplications = numApplications;
- }
-
- public void addApplication(IccCardApplication application) {
- mApplications.add(application);
- }
-
- public IccCardApplication getApplication(int index) {
- return mApplications.get(index);
- }
-
@Override
public String toString() {
- IccCardApplication app;
+ IccCardApplicationStatus app;
StringBuilder sb = new StringBuilder();
sb.append("IccCardState {").append(mCardState).append(",")
.append(mUniversalPinState)
- .append(",num_apps=").append(mNumApplications)
+ .append(",num_apps=").append(mApplications.length)
.append(",gsm_id=").append(mGsmUmtsSubscriptionAppIndex);
if (mGsmUmtsSubscriptionAppIndex >=0
&& mGsmUmtsSubscriptionAppIndex <CARD_MAX_APPS) {
- app = getApplication(mGsmUmtsSubscriptionAppIndex);
+ app = mApplications[mGsmUmtsSubscriptionAppIndex];
sb.append(app == null ? "null" : app);
}
sb.append(",cmda_id=").append(mCdmaSubscriptionAppIndex);
if (mCdmaSubscriptionAppIndex >=0
&& mCdmaSubscriptionAppIndex <CARD_MAX_APPS) {
- app = getApplication(mCdmaSubscriptionAppIndex);
+ app = mApplications[mCdmaSubscriptionAppIndex];
sb.append(app == null ? "null" : app);
}
- sb.append(",ism_id=").append(mImsSubscriptionAppIndex);
+ sb.append(",ims_id=").append(mImsSubscriptionAppIndex);
+ if (mImsSubscriptionAppIndex >=0
+ && mImsSubscriptionAppIndex <CARD_MAX_APPS) {
+ app = mApplications[mImsSubscriptionAppIndex];
+ sb.append(app == null ? "null" : app);
+ }
sb.append("}");
diff --git a/src/java/com/android/internal/telephony/IccConstants.java b/src/java/com/android/internal/telephony/IccConstants.java
index 1ba6dfe..847c883 100644
--- a/src/java/com/android/internal/telephony/IccConstants.java
+++ b/src/java/com/android/internal/telephony/IccConstants.java
@@ -31,6 +31,7 @@ public interface IccConstants {
static final int EF_MWIS = 0x6FCA;
static final int EF_MBDN = 0x6fc7;
static final int EF_PNN = 0x6fc5;
+ static final int EF_OPL = 0x6fc6;
static final int EF_SPN = 0x6F46;
static final int EF_SMS = 0x6F3C;
static final int EF_ICCID = 0x2fe2;
@@ -85,6 +86,6 @@ public interface IccConstants {
static final String DF_GSM = "7F20";
static final String DF_CDMA = "7F25";
- //ISIM access
- static final String DF_ADFISIM = "7FFF";
+ //UICC access
+ static final String DF_ADF = "7FFF";
}
diff --git a/src/java/com/android/internal/telephony/IccFileHandler.java b/src/java/com/android/internal/telephony/IccFileHandler.java
index 70d8f7a..98ab17b 100644
--- a/src/java/com/android/internal/telephony/IccFileHandler.java
+++ b/src/java/com/android/internal/telephony/IccFileHandler.java
@@ -91,8 +91,8 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
// member variables
protected final CommandsInterface mCi;
- protected final IccCard mParentCard;
- protected String mAid;
+ protected final UiccCardApplication mParentApp;
+ protected final String mAid;
static class LoadLinearFixedContext {
@@ -122,8 +122,8 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
/**
* Default constructor
*/
- protected IccFileHandler(IccCard card, String aid, CommandsInterface ci) {
- mParentCard = card;
+ protected IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
+ mParentApp = app;
mAid = aid;
mCi = ci;
}
@@ -225,6 +225,24 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
}
/**
+ * Load first @size bytes from SIM Transparent EF
+ *
+ * @param fileid EF id
+ * @param size
+ * @param onLoaded
+ *
+ * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+ *
+ */
+ public void loadEFTransparent(int fileid, int size, Message onLoaded) {
+ Message response = obtainMessage(EVENT_READ_BINARY_DONE,
+ fileid, 0, onLoaded);
+
+ mCi.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
+ 0, 0, size, null, null, mAid, response);
+ }
+
+ /**
* Load a SIM Transparent EF-IMG. Used right after loadEFImgLinearFixed to
* retrive STK's icon data.
*
@@ -534,6 +552,9 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
case EF_ICCID:
case EF_PL:
return MF_SIM;
+ case EF_PBR:
+ // we only support global phonebook.
+ return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
case EF_IMG:
return MF_SIM + DF_TELECOM + DF_GRAPHICS;
}
@@ -544,8 +565,5 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
protected abstract void logd(String s);
protected abstract void loge(String s);
- protected void setAid(String aid) {
- mAid = aid;
- }
}
diff --git a/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index 0e5f2da..dabe4ee 100644
--- a/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -23,6 +23,8 @@ import android.os.Looper;
import android.os.Message;
import android.os.ServiceManager;
+import com.android.internal.telephony.IccCardApplicationStatus.AppType;
+
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -291,7 +293,7 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
private int updateEfForIccType(int efid) {
// Check if we are trying to read ADN records
if (efid == IccConstants.EF_ADN) {
- if (phone.getIccCard().isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
+ if (phone.getIccCard().isApplicationOnIcc(AppType.APPTYPE_USIM)) {
return IccConstants.EF_PBR;
}
}
diff --git a/src/java/com/android/internal/telephony/IccRecords.java b/src/java/com/android/internal/telephony/IccRecords.java
index 3c90647..cfcc412 100644
--- a/src/java/com/android/internal/telephony/IccRecords.java
+++ b/src/java/com/android/internal/telephony/IccRecords.java
@@ -39,9 +39,10 @@ public abstract class IccRecords extends Handler implements IccConstants {
protected Context mContext;
protected CommandsInterface mCi;
protected IccFileHandler mFh;
- protected IccCard mParentCard;
+ protected UiccCardApplication mParentApp;
protected RegistrantList recordsLoadedRegistrants = new RegistrantList();
+ protected RegistrantList mImsiReadyRegistrants = new RegistrantList();
protected RegistrantList mRecordsEventsRegistrants = new RegistrantList();
protected RegistrantList mNewSmsRegistrants = new RegistrantList();
protected RegistrantList mNetworkSelectionModeAutomaticRegistrants = new RegistrantList();
@@ -63,6 +64,7 @@ public abstract class IccRecords extends Handler implements IccConstants {
protected String newVoiceMailTag = null;
protected boolean isVoiceMailFixed = false;
protected int countVoiceMessages = 0;
+ protected String mImsi;
protected int mncLength = UNINITIALIZED;
protected int mailboxIndex = 0; // 0 is no mailbox dailing number associated
@@ -104,11 +106,11 @@ public abstract class IccRecords extends Handler implements IccConstants {
}
// ***** Constructor
- public IccRecords(IccCard card, Context c, CommandsInterface ci) {
+ public IccRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
mContext = c;
mCi = ci;
- mFh = card.getIccFileHandler();
- mParentCard = card;
+ mFh = app.getIccFileHandler();
+ mParentApp = app;
}
/**
@@ -116,13 +118,12 @@ public abstract class IccRecords extends Handler implements IccConstants {
*/
public void dispose() {
mDestroyed.set(true);
- mParentCard = null;
+ mParentApp = null;
mFh = null;
mCi = null;
mContext = null;
}
- protected abstract void onRadioOffOrNotAvailable();
public abstract void onReady();
//***** Public Methods
@@ -146,6 +147,22 @@ public abstract class IccRecords extends Handler implements IccConstants {
recordsLoadedRegistrants.remove(h);
}
+ public void registerForImsiReady(Handler h, int what, Object obj) {
+ if (mDestroyed.get()) {
+ return;
+ }
+
+ Registrant r = new Registrant(h, what, obj);
+ mImsiReadyRegistrants.add(r);
+
+ if (mImsi != null) {
+ r.notifyRegistrant(new AsyncResult(null, null, null));
+ }
+ }
+ public void unregisterForImsiReady(Handler h) {
+ mImsiReadyRegistrants.remove(h);
+ }
+
public void registerForRecordsEvents(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mRecordsEventsRegistrants.add(r);
@@ -182,6 +199,15 @@ public abstract class IccRecords extends Handler implements IccConstants {
return null;
}
+ /**
+ * Imsi could be set by ServiceStateTrackers in case of cdma
+ * @param imsi
+ */
+ public void setImsi(String imsi) {
+ this.mImsi = imsi;
+ mImsiReadyRegistrants.notifyRegistrants();
+ }
+
public String getMsisdnNumber() {
return msisdn;
}
diff --git a/src/java/com/android/internal/telephony/PhoneBase.java b/src/java/com/android/internal/telephony/PhoneBase.java
index 7c2f2e0..113e8f4 100755
--- a/src/java/com/android/internal/telephony/PhoneBase.java
+++ b/src/java/com/android/internal/telephony/PhoneBase.java
@@ -37,6 +37,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.internal.R;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.gsm.UsimServiceTable;
import com.android.internal.telephony.ims.IsimRecords;
import com.android.internal.telephony.test.SimulatedRadioControl;
@@ -130,9 +131,10 @@ public abstract class PhoneBase extends Handler implements Phone {
boolean mIsVoiceCapable = true;
protected UiccController mUiccController = null;
public AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
- protected AtomicReference<IccCard> mIccCard = new AtomicReference<IccCard>();
public SmsStorageMonitor mSmsStorageMonitor;
public SmsUsageMonitor mSmsUsageMonitor;
+ protected AtomicReference<UiccCardApplication> mUiccApplication =
+ new AtomicReference<UiccCardApplication>();
public SMSDispatcher mSMS;
/**
@@ -254,7 +256,7 @@ public abstract class PhoneBase extends Handler implements Phone {
// Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
mSmsStorageMonitor = new SmsStorageMonitor(this);
mSmsUsageMonitor = new SmsUsageMonitor(context);
- mUiccController = UiccController.getInstance(this);
+ mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
}
@@ -276,7 +278,7 @@ public abstract class PhoneBase extends Handler implements Phone {
mSmsUsageMonitor = null;
mSMS = null;
mIccRecords.set(null);
- mIccCard.set(null);
+ mUiccApplication.set(null);
mDataConnectionTracker = null;
mUiccController = null;
}
@@ -653,9 +655,9 @@ public abstract class PhoneBase extends Handler implements Phone {
* Retrieves the IccFileHandler of the Phone instance
*/
public IccFileHandler getIccFileHandler(){
- IccCard iccCard = mIccCard.get();
- if (iccCard == null) return null;
- return iccCard.getIccFileHandler();
+ UiccCardApplication uiccApplication = mUiccApplication.get();
+ if (uiccApplication == null) return null;
+ return uiccApplication.getIccFileHandler();
}
/*
@@ -681,7 +683,8 @@ public abstract class PhoneBase extends Handler implements Phone {
@Override
public IccCard getIccCard() {
- return mIccCard.get();
+ return null;
+ //throw new Exception("getIccCard Shouldn't be called from PhoneBase");
}
@Override
@@ -1186,7 +1189,7 @@ public abstract class PhoneBase extends Handler implements Phone {
pw.println(" mIsTheCurrentActivePhone=" + mIsTheCurrentActivePhone);
pw.println(" mIsVoiceCapable=" + mIsVoiceCapable);
pw.println(" mIccRecords=" + mIccRecords.get());
- pw.println(" mIccCard=" + mIccCard.get());
+ pw.println(" mUiccApplication=" + mUiccApplication.get());
pw.println(" mSmsStorageMonitor=" + mSmsStorageMonitor);
pw.println(" mSmsUsageMonitor=" + mSmsUsageMonitor);
pw.println(" mSMS=" + mSMS);
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 2c85dc6..2600c79 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -30,6 +30,7 @@ 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;
+import com.android.internal.telephony.uicc.UiccController;
/**
* {@hide}
@@ -138,6 +139,9 @@ public class PhoneFactory {
//reads the system properties and makes commandsinterface
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
+ // Instantiate UiccController so that all other classes can just call getInstance()
+ UiccController.make(context, sCommandsInterface);
+
int phoneType = TelephonyManager.getPhoneType(networkMode);
if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
Log.i(LOG_TAG, "Creating GSMPhone");
diff --git a/src/java/com/android/internal/telephony/PhoneProxy.java b/src/java/com/android/internal/telephony/PhoneProxy.java
index 77135d4..3387840 100644
--- a/src/java/com/android/internal/telephony/PhoneProxy.java
+++ b/src/java/com/android/internal/telephony/PhoneProxy.java
@@ -48,6 +48,7 @@ public class PhoneProxy extends Handler implements Phone {
private IccSmsInterfaceManagerProxy mIccSmsInterfaceManagerProxy;
private IccPhoneBookInterfaceManagerProxy mIccPhoneBookInterfaceManagerProxy;
private PhoneSubInfoProxy mPhoneSubInfoProxy;
+ private IccCardProxy mIccCardProxy;
private boolean mResetModemOnRadioTechnologyChange = false;
@@ -61,7 +62,7 @@ public class PhoneProxy extends Handler implements Phone {
private static final String LOG_TAG = "PHONE";
//***** Class Methods
- public PhoneProxy(Phone phone) {
+ public PhoneProxy(PhoneBase phone) {
mActivePhone = phone;
mResetModemOnRadioTechnologyChange = SystemProperties.getBoolean(
TelephonyProperties.PROPERTY_RESET_ON_RADIO_TECH_CHANGE, false);
@@ -76,6 +77,13 @@ public class PhoneProxy extends Handler implements Phone {
mCommandsInterface.registerForOn(this, EVENT_RADIO_ON, null);
mCommandsInterface.registerForVoiceRadioTechChanged(
this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
+ mIccCardProxy = new IccCardProxy(phone.getContext(), mCommandsInterface);
+ if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
+ // For the purpose of IccCardProxy we only care about the technology family
+ mIccCardProxy.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
+ } else if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
+ mIccCardProxy.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT);
+ }
}
@Override
@@ -197,6 +205,7 @@ public class PhoneProxy extends Handler implements Phone {
mPhoneSubInfoProxy.setmPhoneSubInfo(this.mActivePhone.getPhoneSubInfo());
mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
+ mIccCardProxy.setVoiceRadioTech(newVoiceRadioTech);
// Send an Intent to the PhoneApp that we had a radio technology change
Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
@@ -457,11 +466,11 @@ public class PhoneProxy extends Handler implements Phone {
}
public boolean getIccRecordsLoaded() {
- return mActivePhone.getIccRecordsLoaded();
+ return mIccCardProxy.getIccRecordsLoaded();
}
public IccCard getIccCard() {
- return mActivePhone.getIccCard();
+ return mIccCardProxy;
}
public void acceptCall() throws CallStateException {
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index c359652..99294ed 100755
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -51,6 +51,7 @@ import android.util.Log;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.IccCardApplicationStatus;
import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
import com.android.internal.telephony.cdma.CdmaInformationRecords;
import com.android.internal.telephony.IccRefreshResponse;
@@ -2986,35 +2987,34 @@ public final class RIL extends BaseCommands implements CommandsInterface {
private Object
responseIccCardStatus(Parcel p) {
- IccCardApplication ca;
-
- IccCardStatus status = new IccCardStatus();
- status.setCardState(p.readInt());
- status.setUniversalPinState(p.readInt());
- status.setGsmUmtsSubscriptionAppIndex(p.readInt());
- status.setCdmaSubscriptionAppIndex(p.readInt());
- status.setImsSubscriptionAppIndex(p.readInt());
+ IccCardApplicationStatus appStatus;
+
+ IccCardStatus cardStatus = new IccCardStatus();
+ cardStatus.setCardState(p.readInt());
+ cardStatus.setUniversalPinState(p.readInt());
+ cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt();
+ cardStatus.mCdmaSubscriptionAppIndex = p.readInt();
+ cardStatus.mImsSubscriptionAppIndex = p.readInt();
int numApplications = p.readInt();
// limit to maximum allowed applications
if (numApplications > IccCardStatus.CARD_MAX_APPS) {
numApplications = IccCardStatus.CARD_MAX_APPS;
}
- status.setNumApplications(numApplications);
-
+ cardStatus.mApplications = new IccCardApplicationStatus[numApplications];
for (int i = 0 ; i < numApplications ; i++) {
- ca = new IccCardApplication();
- ca.app_type = ca.AppTypeFromRILInt(p.readInt());
- ca.app_state = ca.AppStateFromRILInt(p.readInt());
- ca.perso_substate = ca.PersoSubstateFromRILInt(p.readInt());
- ca.aid = p.readString();
- ca.app_label = p.readString();
- ca.pin1_replaced = p.readInt();
- ca.pin1 = ca.PinStateFromRILInt(p.readInt());
- ca.pin2 = ca.PinStateFromRILInt(p.readInt());
- status.addApplication(ca);
- }
- return status;
+ appStatus = new IccCardApplicationStatus();
+ appStatus.app_type = appStatus.AppTypeFromRILInt(p.readInt());
+ appStatus.app_state = appStatus.AppStateFromRILInt(p.readInt());
+ appStatus.perso_substate = appStatus.PersoSubstateFromRILInt(p.readInt());
+ appStatus.aid = p.readString();
+ appStatus.app_label = p.readString();
+ appStatus.pin1_replaced = p.readInt();
+ appStatus.pin1 = appStatus.PinStateFromRILInt(p.readInt());
+ appStatus.pin2 = appStatus.PinStateFromRILInt(p.readInt());
+ cardStatus.mApplications[i] = appStatus;
+ }
+ return cardStatus;
}
private Object
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 1628a3d..090e38d 100755
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.content.Context;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
@@ -29,6 +30,7 @@ import android.util.TimeUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.uicc.UiccController;
/**
@@ -38,7 +40,7 @@ public abstract class ServiceStateTracker extends Handler {
protected CommandsInterface cm;
protected UiccController mUiccController = null;
- protected IccCard mIccCard = null;
+ protected UiccCardApplication mUiccApplcation = null;
protected IccRecords mIccRecords = null;
public ServiceState ss;
@@ -174,7 +176,7 @@ public abstract class ServiceStateTracker extends Handler {
protected static final String REGISTRATION_DENIED_GEN = "General";
protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
- public ServiceStateTracker(PhoneBase p, CommandsInterface ci) {
+ public ServiceStateTracker(Context c, CommandsInterface ci) {
cm = ci;
mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
@@ -548,16 +550,16 @@ public abstract class ServiceStateTracker extends Handler {
}
// Determine if the Icc card exists
- IccCard iccCard = phoneBase.getIccCard();
- boolean iccCardExist = (iccCard != null) && iccCard.getState().iccCardExist();
+ boolean iccCardExist = false;
+ if (mUiccApplcation != null) {
+ iccCardExist = mUiccApplcation.getState() != AppState.APPSTATE_UNKNOWN;
+ }
// Determine retVal
boolean retVal = ((iccCardExist && (mcc != prevMcc)) || needToFixTimeZone);
if (DBG) {
long ctm = System.currentTimeMillis();
log("shouldFixTimeZoneNow: retVal=" + retVal +
- " iccCard=" + iccCard +
- " iccCard.state=" + (iccCard == null ? "null" : iccCard.getState().toString()) +
" iccCardExist=" + iccCardExist +
" operatorNumeric=" + operatorNumeric + " mcc=" + mcc +
" prevOperatorNumeric=" + prevOperatorNumeric + " prevMcc=" + prevMcc +
diff --git a/src/java/com/android/internal/telephony/UiccCard.java b/src/java/com/android/internal/telephony/UiccCard.java
new file mode 100644
index 0000000..038a138
--- /dev/null
+++ b/src/java/com/android/internal/telephony/UiccCard.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2006, 2012 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;
+
+import static android.Manifest.permission.READ_PHONE_STATE;
+import android.app.ActivityManagerNative;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.CommandsInterface.RadioState;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.IccCardApplicationStatus;
+import com.android.internal.telephony.IccCardApplicationStatus.AppType;
+import com.android.internal.telephony.IccCardStatus.CardState;
+import com.android.internal.telephony.IccCardStatus.PinState;
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.gsm.SIMFileHandler;
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.uicc.UiccController;
+import com.android.internal.telephony.cat.CatService;
+import com.android.internal.telephony.cdma.CDMALTEPhone;
+import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
+import com.android.internal.telephony.cdma.RuimFileHandler;
+import com.android.internal.telephony.cdma.RuimRecords;
+
+import android.os.SystemProperties;
+
+import com.android.internal.R;
+
+/**
+ * {@hide}
+ */
+public class UiccCard {
+ protected static final String LOG_TAG = "RIL_UiccCard";
+ protected static final boolean DBG = true;
+
+ private final Object mLock = new Object();
+ private CardState mCardState;
+ private PinState mUniversalPinState;
+ private int mGsmUmtsSubscriptionAppIndex;
+ private int mCdmaSubscriptionAppIndex;
+ private int mImsSubscriptionAppIndex;
+ private UiccCardApplication[] mUiccApplications =
+ new UiccCardApplication[IccCardStatus.CARD_MAX_APPS];
+ private Context mContext;
+ private CommandsInterface mCi;
+ private CatService mCatService;
+ private boolean mDestroyed = false; //set to true once this card is commanded to be disposed of.
+ private RadioState mLastRadioState = RadioState.RADIO_UNAVAILABLE;
+
+ private RegistrantList mAbsentRegistrants = new RegistrantList();
+
+ private static final int EVENT_CARD_REMOVED = 13;
+ private static final int EVENT_CARD_ADDED = 14;
+
+ public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics) {
+ if (DBG) log("Creating");
+ mCardState = ics.mCardState;
+ update(c, ci, ics);
+ }
+
+ public void dispose() {
+ synchronized (mLock) {
+ if (DBG) log("Disposing card");
+ if (mCatService != null) mCatService.dispose();
+ for (UiccCardApplication app : mUiccApplications) {
+ if (app != null) {
+ app.dispose();
+ }
+ }
+ mCatService = null;
+ mUiccApplications = null;
+ }
+ }
+
+ public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ loge("Updated after destroyed! Fix me!");
+ return;
+ }
+ CardState oldState = mCardState;
+ mCardState = ics.mCardState;
+ mUniversalPinState = ics.mUniversalPinState;
+ mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
+ mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
+ mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
+ mContext = c;
+ mCi = ci;
+ //update applications
+ if (DBG) log(ics.mApplications.length + " applications");
+ for ( int i = 0; i < mUiccApplications.length; i++) {
+ if (mUiccApplications[i] == null) {
+ //Create newly added Applications
+ if (i < ics.mApplications.length) {
+ mUiccApplications[i] = new UiccCardApplication(this,
+ ics.mApplications[i], mContext, mCi);
+ }
+ } else if (i >= ics.mApplications.length) {
+ //Delete removed applications
+ mUiccApplications[i].dispose();
+ mUiccApplications[i] = null;
+ } else {
+ //Update the rest
+ mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
+ }
+ }
+
+ if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
+ // Initialize or Reinitialize CatService
+ mCatService = CatService.getInstance(mCi,
+ mContext,
+ this);
+ } else {
+ if (mCatService != null) {
+ mCatService.dispose();
+ }
+ mCatService = null;
+ }
+
+ sanitizeApplicationIndexes();
+
+ RadioState radioState = mCi.getRadioState();
+ if (DBG) log("update: radioState=" + radioState + " mLastRadioState="
+ + mLastRadioState);
+ // No notifications while radio is off or we just powering up
+ if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
+ if (oldState != CardState.CARDSTATE_ABSENT &&
+ mCardState == CardState.CARDSTATE_ABSENT) {
+ if (DBG) log("update: notify card removed");
+ mAbsentRegistrants.notifyRegistrants();
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
+ } else if (oldState == CardState.CARDSTATE_ABSENT &&
+ mCardState != CardState.CARDSTATE_ABSENT) {
+ if (DBG) log("update: notify card added");
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
+ }
+ }
+ mLastRadioState = radioState;
+ }
+ }
+
+ protected void finalize() {
+ if (DBG) log("UiccCard finalized");
+ }
+
+ /**
+ * This function makes sure that application indexes are valid
+ * and resets invalid indexes. (This should never happen, but in case
+ * RIL misbehaves we need to manage situation gracefully)
+ */
+ private void sanitizeApplicationIndexes() {
+ mGsmUmtsSubscriptionAppIndex =
+ checkIndex(mGsmUmtsSubscriptionAppIndex, AppType.APPTYPE_SIM, AppType.APPTYPE_USIM);
+ mCdmaSubscriptionAppIndex =
+ checkIndex(mCdmaSubscriptionAppIndex, AppType.APPTYPE_RUIM, AppType.APPTYPE_CSIM);
+ mImsSubscriptionAppIndex =
+ checkIndex(mImsSubscriptionAppIndex, AppType.APPTYPE_ISIM, null);
+ }
+
+ private int checkIndex(int index, AppType expectedAppType, AppType altExpectedAppType) {
+ if (mUiccApplications == null || index >= mUiccApplications.length) {
+ loge("App index " + index + " is invalid since there are no applications");
+ return -1;
+ }
+
+ if (index < 0) {
+ // This is normal. (i.e. no application of this type)
+ return -1;
+ }
+
+ if (mUiccApplications[index].getType() != expectedAppType &&
+ mUiccApplications[index].getType() != altExpectedAppType) {
+ loge("App index " + index + " is invalid since it's not " +
+ expectedAppType + " and not " + altExpectedAppType);
+ return -1;
+ }
+
+ // Seems to be valid
+ return index;
+ }
+
+ /**
+ * Notifies handler of any transition into State.ABSENT
+ */
+ public void registerForAbsent(Handler h, int what, Object obj) {
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+
+ mAbsentRegistrants.add(r);
+
+ if (mCardState == CardState.CARDSTATE_ABSENT) {
+ r.notifyRegistrant();
+ }
+ }
+ }
+
+ public void unregisterForAbsent(Handler h) {
+ synchronized (mLock) {
+ mAbsentRegistrants.remove(h);
+ }
+ }
+
+ private void onIccSwap(boolean isAdded) {
+ synchronized (mLock) {
+ // TODO: Here we assume the device can't handle SIM hot-swap
+ // and has to reboot. We may want to add a property,
+ // e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support
+ // hot-swap.
+ DialogInterface.OnClickListener listener = null;
+
+
+ // TODO: SimRecords is not reset while SIM ABSENT (only reset while
+ // Radio_off_or_not_available). Have to reset in both both
+ // added or removed situation.
+ listener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ synchronized (mLock) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ if (DBG) log("Reboot due to SIM swap");
+ PowerManager pm = (PowerManager) mContext
+ .getSystemService(Context.POWER_SERVICE);
+ pm.reboot("SIM is added.");
+ }
+ }
+ }
+
+ };
+
+ Resources r = Resources.getSystem();
+
+ String title = (isAdded) ? r.getString(R.string.sim_added_title) :
+ r.getString(R.string.sim_removed_title);
+ String message = (isAdded) ? r.getString(R.string.sim_added_message) :
+ r.getString(R.string.sim_removed_message);
+ String buttonTxt = r.getString(R.string.sim_restart_button);
+
+ AlertDialog dialog = new AlertDialog.Builder(mContext)
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(buttonTxt, listener)
+ .create();
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ dialog.show();
+ }
+ }
+
+ protected Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg){
+ if (mDestroyed) {
+ loge("Received message " + msg + "[" + msg.what
+ + "] while being destroyed. Ignoring.");
+ return;
+ }
+
+ switch (msg.what) {
+ case EVENT_CARD_REMOVED:
+ onIccSwap(false);
+ break;
+ case EVENT_CARD_ADDED:
+ onIccSwap(true);
+ break;
+ default:
+ loge("Unknown Event " + msg.what);
+ }
+ }
+ };
+
+ public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
+ synchronized (mLock) {
+ for (int i = 0 ; i < mUiccApplications.length; i++) {
+ if (mUiccApplications[i] != null && mUiccApplications[i].getType() == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ public CardState getCardState() {
+ synchronized (mLock) {
+ return mCardState;
+ }
+ }
+
+ public PinState getUniversalPinState() {
+ synchronized (mLock) {
+ return mUniversalPinState;
+ }
+ }
+
+ public UiccCardApplication getApplication(int family) {
+ synchronized (mLock) {
+ int index = IccCardStatus.CARD_MAX_APPS;
+ switch (family) {
+ case UiccController.APP_FAM_3GPP:
+ index = mGsmUmtsSubscriptionAppIndex;
+ break;
+ case UiccController.APP_FAM_3GPP2:
+ index = mCdmaSubscriptionAppIndex;
+ break;
+ case UiccController.APP_FAM_IMS:
+ index = mImsSubscriptionAppIndex;
+ break;
+ }
+ if (index >= 0 && index < mUiccApplications.length) {
+ return mUiccApplications[index];
+ }
+ return null;
+ }
+ }
+
+ public UiccCardApplication getApplicationIndex(int index) {
+ synchronized (mLock) {
+ if (index >= 0 && index < mUiccApplications.length) {
+ return mUiccApplications[index];
+ }
+ return null;
+ }
+ }
+
+ private void log(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+
+ private void loge(String msg) {
+ Log.e(LOG_TAG, msg);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/UiccCardApplication.java b/src/java/com/android/internal/telephony/UiccCardApplication.java
new file mode 100644
index 0000000..9ec16fc
--- /dev/null
+++ b/src/java/com/android/internal/telephony/UiccCardApplication.java
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2006, 2012 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;
+
+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.util.Log;
+
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
+import com.android.internal.telephony.IccCardApplicationStatus.AppType;
+import com.android.internal.telephony.IccCardApplicationStatus.PersoSubState;
+import com.android.internal.telephony.IccCardStatus.PinState;
+import com.android.internal.telephony.cdma.RuimFileHandler;
+import com.android.internal.telephony.cdma.RuimRecords;
+import com.android.internal.telephony.gsm.SIMFileHandler;
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.ims.IsimFileHandler;
+import com.android.internal.telephony.ims.IsimUiccRecords;
+
+/**
+ * {@hide}
+ */
+public class UiccCardApplication {
+ private static final String LOG_TAG = "RIL_UiccCardApplication";
+ private static final boolean DBG = true;
+
+ private static final int EVENT_QUERY_FACILITY_FDN_DONE = 1;
+ private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 2;
+ private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 3;
+ private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 4;
+
+ private final Object mLock = new Object();
+ private UiccCard mUiccCard; //parent
+ private AppState mAppState;
+ private AppType mAppType;
+ private PersoSubState mPersoSubState;
+ private String mAid;
+ private String mAppLabel;
+ private boolean mPin1Replaced;
+ private PinState mPin1State;
+ private PinState mPin2State;
+ private boolean mIccFdnEnabled;
+ private boolean mDesiredFdnEnabled;
+ private boolean mIccLockEnabled;
+ private boolean mDesiredPinLocked;
+
+ private CommandsInterface mCi;
+ private Context mContext;
+ private IccRecords mIccRecords;
+ private IccFileHandler mIccFh;
+
+ private boolean mDestroyed;//set to true once this App is commanded to be disposed of.
+
+ private RegistrantList mReadyRegistrants = new RegistrantList();
+ private RegistrantList mPinLockedRegistrants = new RegistrantList();
+ private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
+
+ UiccCardApplication(UiccCard uiccCard,
+ IccCardApplicationStatus as,
+ Context c,
+ CommandsInterface ci) {
+ if (DBG) log("Creating UiccApp: " + as);
+ mUiccCard = uiccCard;
+ mAppState = as.app_state;
+ mAppType = as.app_type;
+ mPersoSubState = as.perso_substate;
+ mAid = as.aid;
+ mAppLabel = as.app_label;
+ mPin1Replaced = (as.pin1_replaced != 0);
+ mPin1State = as.pin1;
+ mPin2State = as.pin2;
+
+ mContext = c;
+ mCi = ci;
+
+ mIccFh = createIccFileHandler(as.app_type);
+ mIccRecords = createIccRecords(as.app_type, mContext, mCi);
+ if (mAppState == AppState.APPSTATE_READY) {
+ queryFdn();
+ queryPin1State();
+ }
+ }
+
+ void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ loge("Application updated after destroyed! Fix me!");
+ return;
+ }
+
+ if (DBG) log(mAppType + " update. New " + as);
+ mContext = c;
+ mCi = ci;
+ AppType oldAppType = mAppType;
+ AppState oldAppState = mAppState;
+ PersoSubState oldPersoSubState = mPersoSubState;
+ mAppType = as.app_type;
+ mAppState = as.app_state;
+ mPersoSubState = as.perso_substate;
+ mAid = as.aid;
+ mAppLabel = as.app_label;
+ mPin1Replaced = (as.pin1_replaced != 0);
+ mPin1State = as.pin1;
+ mPin2State = as.pin2;
+
+ if (mAppType != oldAppType) {
+ mIccFh.dispose();
+ mIccRecords.dispose();
+ mIccFh = createIccFileHandler(as.app_type);
+ mIccRecords = createIccRecords(as.app_type, c, ci);
+ }
+
+ if (mPersoSubState != oldPersoSubState &&
+ mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
+ notifyNetworkLockedRegistrantsIfNeeded(null);
+ }
+
+ if (mAppState != oldAppState) {
+ if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState);
+ // If the app state turns to APPSTATE_READY, then query FDN status,
+ //as it might have failed in earlier attempt.
+ if (mAppState == AppState.APPSTATE_READY) {
+ queryFdn();
+ queryPin1State();
+ }
+ notifyPinLockedRegistrantsIfNeeded(null);
+ notifyReadyRegistrantsIfNeeded(null);
+ }
+ }
+ }
+
+ void dispose() {
+ synchronized (mLock) {
+ if (DBG) log(mAppType + " being Disposed");
+ mDestroyed = true;
+ if (mIccRecords != null) { mIccRecords.dispose();}
+ if (mIccFh != null) { mIccFh.dispose();}
+ mIccRecords = null;
+ mIccFh = null;
+ }
+ }
+
+ private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) {
+ if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) {
+ return new SIMRecords(this, c, ci);
+ } else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){
+ return new RuimRecords(this, c, ci);
+ } else if (type == AppType.APPTYPE_ISIM) {
+ return new IsimUiccRecords(this, c, ci);
+ } else {
+ // Unknown app type (maybe detection is still in progress)
+ return null;
+ }
+ }
+
+ private IccFileHandler createIccFileHandler(AppType type) {
+ switch (type) {
+ case APPTYPE_SIM:
+ return new SIMFileHandler(this, mAid, mCi);
+ case APPTYPE_RUIM:
+ return new RuimFileHandler(this, mAid, mCi);
+ case APPTYPE_USIM:
+ return new UsimFileHandler(this, mAid, mCi);
+ case APPTYPE_CSIM:
+ return new CsimFileHandler(this, mAid, mCi);
+ case APPTYPE_ISIM:
+ return new IsimFileHandler(this, mAid, mCi);
+ default:
+ return null;
+ }
+ }
+
+ /** Assumes mLock is held. */
+ private void queryFdn() {
+ //This shouldn't change run-time. So needs to be called only once.
+ int serviceClassX;
+
+ serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
+ CommandsInterface.SERVICE_CLASS_DATA +
+ CommandsInterface.SERVICE_CLASS_FAX;
+ mCi.queryFacilityLockForApp (
+ CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX,
+ mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
+ }
+ /**
+ * Interpret EVENT_QUERY_FACILITY_LOCK_DONE
+ * @param ar is asyncResult of Query_Facility_Locked
+ */
+ private void onQueryFdnEnabled(AsyncResult ar) {
+ synchronized (mLock) {
+ if (ar.exception != null) {
+ if (DBG) log("Error in querying facility lock:" + ar.exception);
+ return;
+ }
+
+ int[] ints = (int[])ar.result;
+ if(ints.length != 0) {
+ mIccFdnEnabled = (0!=ints[0]);
+ if (DBG) log("Query facility lock : " + mIccFdnEnabled);
+ } else {
+ loge("Bogus facility lock response");
+ }
+ }
+ }
+
+ private void onChangeFdnDone(AsyncResult ar) {
+ synchronized (mLock) {
+ if (ar.exception == null) {
+ mIccFdnEnabled = mDesiredFdnEnabled;
+ if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " +
+ "mIccFdnEnabled=" + mIccFdnEnabled);
+ } else {
+ loge("Error change facility fdn with exception " + ar.exception);
+ }
+ Message response = (Message)ar.userObj;
+ AsyncResult.forMessage(response).exception = ar.exception;
+ response.sendToTarget();
+ }
+ }
+
+ /** REMOVE when mIccLockEnabled is not needed, assumes mLock is held */
+ private void queryPin1State() {
+ int serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
+ CommandsInterface.SERVICE_CLASS_DATA +
+ CommandsInterface.SERVICE_CLASS_FAX;
+ mCi.queryFacilityLockForApp (
+ CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
+ mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
+ }
+
+ /** REMOVE when mIccLockEnabled is not needed*/
+ private void onQueryFacilityLock(AsyncResult ar) {
+ synchronized (mLock) {
+ if(ar.exception != null) {
+ if (DBG) log("Error in querying facility lock:" + ar.exception);
+ return;
+ }
+
+ int[] ints = (int[])ar.result;
+ if(ints.length != 0) {
+ if (DBG) log("Query facility lock : " + ints[0]);
+
+ mIccLockEnabled = (ints[0] != 0);
+
+ if (mIccLockEnabled) {
+ mPinLockedRegistrants.notifyRegistrants();
+ }
+
+ // Sanity check: we expect mPin1State to match mIccLockEnabled.
+ // When mPin1State is DISABLED mIccLockEanbled should be false.
+ // When mPin1State is ENABLED mIccLockEnabled should be true.
+ //
+ // Here we validate these assumptions to assist in identifying which ril/radio's
+ // have not correctly implemented GET_SIM_STATUS
+ switch (mPin1State) {
+ case PINSTATE_DISABLED:
+ if (mIccLockEnabled) {
+ loge("QUERY_FACILITY_LOCK:enabled GET_SIM_STATUS.Pin1:disabled."
+ + " Fixme");
+ }
+ break;
+ case PINSTATE_ENABLED_NOT_VERIFIED:
+ case PINSTATE_ENABLED_VERIFIED:
+ case PINSTATE_ENABLED_BLOCKED:
+ case PINSTATE_ENABLED_PERM_BLOCKED:
+ if (!mIccLockEnabled) {
+ loge("QUERY_FACILITY_LOCK:disabled GET_SIM_STATUS.Pin1:enabled."
+ + " Fixme");
+ }
+ }
+ } else {
+ loge("Bogus facility lock response");
+ }
+ }
+ }
+
+ /** REMOVE when mIccLockEnabled is not needed */
+ private void onChangeFacilityLock(AsyncResult ar) {
+ synchronized (mLock) {
+ if (ar.exception == null) {
+ mIccLockEnabled = mDesiredPinLocked;
+ if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: mIccLockEnabled= "
+ + mIccLockEnabled);
+ } else {
+ loge("Error change facility lock with exception " + ar.exception);
+ }
+ AsyncResult.forMessage(((Message)ar.userObj)).exception = ar.exception;
+ ((Message)ar.userObj).sendToTarget();
+ }
+ }
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg){
+ AsyncResult ar;
+
+ if (mDestroyed) {
+ loge("Received message " + msg + "[" + msg.what
+ + "] while being destroyed. Ignoring.");
+ return;
+ }
+
+ switch (msg.what) {
+ case EVENT_QUERY_FACILITY_FDN_DONE:
+ ar = (AsyncResult)msg.obj;
+ onQueryFdnEnabled(ar);
+ break;
+ case EVENT_CHANGE_FACILITY_FDN_DONE:
+ ar = (AsyncResult)msg.obj;
+ onChangeFdnDone(ar);
+ break;
+ case EVENT_QUERY_FACILITY_LOCK_DONE:
+ ar = (AsyncResult)msg.obj;
+ onQueryFacilityLock(ar);
+ break;
+ case EVENT_CHANGE_FACILITY_LOCK_DONE:
+ ar = (AsyncResult)msg.obj;
+ onChangeFacilityLock(ar);
+ break;
+ default:
+ loge("Unknown Event " + msg.what);
+ }
+ }
+ };
+
+ public void registerForReady(Handler h, int what, Object obj) {
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+ mReadyRegistrants.add(r);
+ notifyReadyRegistrantsIfNeeded(r);
+ }
+ }
+
+ public void unregisterForReady(Handler h) {
+ synchronized (mLock) {
+ mReadyRegistrants.remove(h);
+ }
+ }
+
+ /**
+ * Notifies handler of any transition into State.isPinLocked()
+ */
+ public void registerForLocked(Handler h, int what, Object obj) {
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+ mPinLockedRegistrants.add(r);
+ notifyPinLockedRegistrantsIfNeeded(r);
+ }
+ }
+
+ public void unregisterForLocked(Handler h) {
+ synchronized (mLock) {
+ mPinLockedRegistrants.remove(h);
+ }
+ }
+
+ /**
+ * Notifies handler of any transition into State.NETWORK_LOCKED
+ */
+ public void registerForNetworkLocked(Handler h, int what, Object obj) {
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+ mNetworkLockedRegistrants.add(r);
+ notifyNetworkLockedRegistrantsIfNeeded(r);
+ }
+ }
+
+ public void unregisterForNetworkLocked(Handler h) {
+ synchronized (mLock) {
+ mNetworkLockedRegistrants.remove(h);
+ }
+ }
+
+ /**
+ * Notifies specified registrant, assume mLock is held.
+ *
+ * @param r Registrant to be notified. If null - all registrants will be notified
+ */
+ private void notifyReadyRegistrantsIfNeeded(Registrant r) {
+ if (mDestroyed) {
+ return;
+ }
+ if (mAppState == AppState.APPSTATE_READY) {
+ if (mPin1State == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
+ mPin1State == PinState.PINSTATE_ENABLED_BLOCKED ||
+ mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
+ loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!");
+ // Don't notify if application is in insane state
+ return;
+ }
+ if (r == null) {
+ if (DBG) log("Notifying registrants: READY");
+ mReadyRegistrants.notifyRegistrants();
+ } else {
+ if (DBG) log("Notifying 1 registrant: READY");
+ r.notifyRegistrant(new AsyncResult(null, null, null));
+ }
+ }
+ }
+
+ /**
+ * Notifies specified registrant, assume mLock is held.
+ *
+ * @param r Registrant to be notified. If null - all registrants will be notified
+ */
+ private void notifyPinLockedRegistrantsIfNeeded(Registrant r) {
+ if (mDestroyed) {
+ return;
+ }
+
+ if (mAppState == AppState.APPSTATE_PIN ||
+ mAppState == AppState.APPSTATE_PUK) {
+ if (mPin1State == PinState.PINSTATE_ENABLED_VERIFIED ||
+ mPin1State == PinState.PINSTATE_DISABLED) {
+ loge("Sanity check failed! APPSTATE is locked while PIN1 is not!!!");
+ //Don't notify if application is in insane state
+ return;
+ }
+ if (r == null) {
+ if (DBG) log("Notifying registrants: LOCKED");
+ mPinLockedRegistrants.notifyRegistrants();
+ } else {
+ if (DBG) log("Notifying 1 registrant: LOCKED");
+ r.notifyRegistrant(new AsyncResult(null, null, null));
+ }
+ }
+ }
+
+ /**
+ * Notifies specified registrant, assume mLock is held.
+ *
+ * @param r Registrant to be notified. If null - all registrants will be notified
+ */
+ private void notifyNetworkLockedRegistrantsIfNeeded(Registrant r) {
+ if (mDestroyed) {
+ return;
+ }
+
+ if (mAppState == AppState.APPSTATE_SUBSCRIPTION_PERSO &&
+ mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {
+ if (r == null) {
+ if (DBG) log("Notifying registrants: NETWORK_LOCKED");
+ mNetworkLockedRegistrants.notifyRegistrants();
+ } else {
+ if (DBG) log("Notifying 1 registrant: NETWORK_LOCED");
+ r.notifyRegistrant(new AsyncResult(null, null, null));
+ }
+ }
+ }
+
+ public AppState getState() {
+ synchronized (mLock) {
+ return mAppState;
+ }
+ }
+
+ public AppType getType() {
+ synchronized (mLock) {
+ return mAppType;
+ }
+ }
+
+ public PersoSubState getPersoSubState() {
+ synchronized (mLock) {
+ return mPersoSubState;
+ }
+ }
+
+ public String getAid() {
+ synchronized (mLock) {
+ return mAid;
+ }
+ }
+
+ public PinState getPin1State() {
+ synchronized (mLock) {
+ if (mPin1Replaced) {
+ return mUiccCard.getUniversalPinState();
+ }
+ return mPin1State;
+ }
+ }
+
+ public IccFileHandler getIccFileHandler() {
+ synchronized (mLock) {
+ return mIccFh;
+ }
+ }
+
+ public IccRecords getIccRecords() {
+ synchronized (mLock) {
+ return mIccRecords;
+ }
+ }
+
+ /**
+ * Supply the ICC PIN to the ICC
+ *
+ * When the operation is complete, onComplete will be sent to its
+ * Handler.
+ *
+ * onComplete.obj will be an AsyncResult
+ *
+ * ((AsyncResult)onComplete.obj).exception == null on success
+ * ((AsyncResult)onComplete.obj).exception != null on fail
+ *
+ * If the supplied PIN is incorrect:
+ * ((AsyncResult)onComplete.obj).exception != null
+ * && ((AsyncResult)onComplete.obj).exception
+ * instanceof com.android.internal.telephony.gsm.CommandException)
+ * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
+ * .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
+ *
+ *
+ */
+ public void supplyPin (String pin, Message onComplete) {
+ synchronized (mLock) {
+ mCi.supplyIccPin(pin, onComplete);
+ }
+ }
+
+ public void supplyPuk (String puk, String newPin, Message onComplete) {
+ synchronized (mLock) {
+ mCi.supplyIccPuk(puk, newPin, onComplete);
+ }
+ }
+
+ public void supplyPin2 (String pin2, Message onComplete) {
+ synchronized (mLock) {
+ mCi.supplyIccPin2(pin2, onComplete);
+ }
+ }
+
+ public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
+ synchronized (mLock) {
+ mCi.supplyIccPuk2(puk2, newPin2, onComplete);
+ }
+ }
+
+ public void supplyNetworkDepersonalization (String pin, Message onComplete) {
+ synchronized (mLock) {
+ if (DBG) log("supplyNetworkDepersonalization");
+ mCi.supplyNetworkDepersonalization(pin, onComplete);
+ }
+ }
+
+ /**
+ * Check whether ICC pin lock is enabled
+ * This is a sync call which returns the cached pin enabled state
+ *
+ * @return true for ICC locked enabled
+ * false for ICC locked disabled
+ */
+ public boolean getIccLockEnabled() {
+ return mIccLockEnabled;
+ /* STOPSHIP: Remove line above and all code associated with setting
+ mIccLockEanbled once all RIL correctly sends the pin1 state.
+ // Use getPin1State to take into account pin1Replaced flag
+ PinState pinState = getPin1State();
+ return pinState == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
+ pinState == PinState.PINSTATE_ENABLED_VERIFIED ||
+ pinState == PinState.PINSTATE_ENABLED_BLOCKED ||
+ pinState == PinState.PINSTATE_ENABLED_PERM_BLOCKED;*/
+ }
+
+ /**
+ * Check whether ICC fdn (fixed dialing number) is enabled
+ * This is a sync call which returns the cached pin enabled state
+ *
+ * @return true for ICC fdn enabled
+ * false for ICC fdn disabled
+ */
+ public boolean getIccFdnEnabled() {
+ synchronized (mLock) {
+ return mIccFdnEnabled;
+ }
+ }
+
+ /**
+ * Set the ICC pin lock enabled or disabled
+ * When the operation is complete, onComplete will be sent to its handler
+ *
+ * @param enabled "true" for locked "false" for unlocked.
+ * @param password needed to change the ICC pin state, aka. Pin1
+ * @param onComplete
+ * onComplete.obj will be an AsyncResult
+ * ((AsyncResult)onComplete.obj).exception == null on success
+ * ((AsyncResult)onComplete.obj).exception != null on fail
+ */
+ public void setIccLockEnabled (boolean enabled,
+ String password, Message onComplete) {
+ synchronized (mLock) {
+ int serviceClassX;
+ serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
+ CommandsInterface.SERVICE_CLASS_DATA +
+ CommandsInterface.SERVICE_CLASS_FAX;
+
+ mDesiredPinLocked = enabled;
+
+ mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_SIM,
+ enabled, password, serviceClassX, mAid,
+ mHandler.obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
+ }
+ }
+
+ /**
+ * Set the ICC fdn enabled or disabled
+ * When the operation is complete, onComplete will be sent to its handler
+ *
+ * @param enabled "true" for locked "false" for unlocked.
+ * @param password needed to change the ICC fdn enable, aka Pin2
+ * @param onComplete
+ * onComplete.obj will be an AsyncResult
+ * ((AsyncResult)onComplete.obj).exception == null on success
+ * ((AsyncResult)onComplete.obj).exception != null on fail
+ */
+ public void setIccFdnEnabled (boolean enabled,
+ String password, Message onComplete) {
+ synchronized (mLock) {
+ int serviceClassX;
+ serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
+ CommandsInterface.SERVICE_CLASS_DATA +
+ CommandsInterface.SERVICE_CLASS_FAX +
+ CommandsInterface.SERVICE_CLASS_SMS;
+
+ mDesiredFdnEnabled = enabled;
+
+ mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_FD,
+ enabled, password, serviceClassX, mAid,
+ mHandler.obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
+ }
+ }
+
+ /**
+ * Change the ICC password used in ICC pin lock
+ * When the operation is complete, onComplete will be sent to its handler
+ *
+ * @param oldPassword is the old password
+ * @param newPassword is the new password
+ * @param onComplete
+ * onComplete.obj will be an AsyncResult
+ * ((AsyncResult)onComplete.obj).exception == null on success
+ * ((AsyncResult)onComplete.obj).exception != null on fail
+ */
+ public void changeIccLockPassword(String oldPassword, String newPassword,
+ Message onComplete) {
+ synchronized (mLock) {
+ if (DBG) log("changeIccLockPassword");
+ mCi.changeIccPinForApp(oldPassword, newPassword, mAid,
+ onComplete);
+ }
+ }
+
+ /**
+ * Change the ICC password used in ICC fdn enable
+ * When the operation is complete, onComplete will be sent to its handler
+ *
+ * @param oldPassword is the old password
+ * @param newPassword is the new password
+ * @param onComplete
+ * onComplete.obj will be an AsyncResult
+ * ((AsyncResult)onComplete.obj).exception == null on success
+ * ((AsyncResult)onComplete.obj).exception != null on fail
+ */
+ public void changeIccFdnPassword(String oldPassword, String newPassword,
+ Message onComplete) {
+ synchronized (mLock) {
+ if (DBG) log("changeIccFdnPassword");
+ mCi.changeIccPin2ForApp(oldPassword, newPassword, mAid,
+ onComplete);
+ }
+ }
+
+ private void log(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+
+ private void loge(String msg) {
+ Log.e(LOG_TAG, msg);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/UsimFileHandler.java b/src/java/com/android/internal/telephony/UsimFileHandler.java
new file mode 100644
index 0000000..5ef0333
--- /dev/null
+++ b/src/java/com/android/internal/telephony/UsimFileHandler.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2006, 2012 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;
+
+import android.util.Log;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.UiccCardApplication;
+
+/**
+ * {@hide}
+ * This class should be used to access files in USIM ADF
+ */
+public final class UsimFileHandler extends IccFileHandler implements IccConstants {
+ static final String LOG_TAG = "RIL_UsimFH";
+
+ public UsimFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
+ super(app, aid, ci);
+ }
+
+ @Override
+ protected String getEFPath(int efid) {
+ switch(efid) {
+ case EF_SMS:
+ case EF_EXT6:
+ case EF_MWIS:
+ case EF_MBI:
+ case EF_SPN:
+ case EF_AD:
+ case EF_MBDN:
+ case EF_PNN:
+ case EF_OPL:
+ case EF_SPDI:
+ case EF_SST:
+ case EF_CFIS:
+ case EF_MAILBOX_CPHS:
+ case EF_VOICE_MAIL_INDICATOR_CPHS:
+ case EF_CFF_CPHS:
+ case EF_SPN_CPHS:
+ case EF_SPN_SHORT_CPHS:
+ case EF_FDN:
+ case EF_MSISDN:
+ case EF_EXT2:
+ case EF_INFO_CPHS:
+ case EF_CSP_CPHS:
+ return MF_SIM + DF_ADF;
+
+ case EF_PBR:
+ // we only support global phonebook.
+ return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
+ }
+ String path = getCommonIccEFPath(efid);
+ if (path == null) {
+ // The EFids in USIM phone book entries are decided by the card manufacturer.
+ // So if we don't match any of the cases above and if its a USIM return
+ // the phone book path.
+ return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
+ }
+ return path;
+ }
+
+ @Override
+ protected void logd(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+
+ @Override
+ protected void loge(String msg) {
+ Log.e(LOG_TAG, msg);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
index 2b37072..f749cba 100644
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -28,9 +28,10 @@ import android.os.SystemProperties;
import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccFileHandler;
import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.UiccCard;
+import com.android.internal.telephony.UiccCardApplication;
import java.io.ByteArrayOutputStream;
@@ -64,6 +65,7 @@ public class CatService extends Handler implements AppInterface {
// Class members
private static IccRecords mIccRecords;
+ private static UiccCardApplication mUiccApplication;
// Service members.
// Protects singleton instance lazy initialization.
@@ -101,9 +103,9 @@ public class CatService extends Handler implements AppInterface {
static final String STK_DEFAULT = "Defualt Message";
/* Intentionally private for singleton */
- private CatService(CommandsInterface ci, IccRecords ir, Context context,
- IccFileHandler fh, IccCard ic) {
- if (ci == null || ir == null || context == null || fh == null
+ private CatService(CommandsInterface ci, UiccCardApplication ca, IccRecords ir,
+ Context context, IccFileHandler fh, UiccCard ic) {
+ if (ci == null || ca == null || ir == null || context == null || fh == null
|| ic == null) {
throw new NullPointerException(
"Service: Input parameters must not be null");
@@ -122,9 +124,10 @@ public class CatService extends Handler implements AppInterface {
//mCmdIf.setOnSimRefresh(this, MSG_ID_REFRESH, null);
mIccRecords = ir;
+ mUiccApplication = ca;
// Register for SIM ready event.
- ic.registerForReady(this, MSG_ID_SIM_READY, null);
+ mUiccApplication.registerForReady(this, MSG_ID_SIM_READY, null);
mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
// Check if STK application is availalbe
@@ -553,24 +556,47 @@ public class CatService extends Handler implements AppInterface {
* @param ic Icc card
* @return The only Service object in the system
*/
- public static CatService getInstance(CommandsInterface ci, IccRecords ir,
- Context context, IccFileHandler fh, IccCard ic) {
+ public static CatService getInstance(CommandsInterface ci,
+ Context context, UiccCard ic) {
+ UiccCardApplication ca = null;
+ IccFileHandler fh = null;
+ IccRecords ir = null;
+ if (ic != null) {
+ /* Since Cat is not tied to any application, but rather is Uicc application
+ * in itself - just get first FileHandler and IccRecords object
+ */
+ ca = ic.getApplicationIndex(0);
+ if (ca != null) {
+ fh = ca.getIccFileHandler();
+ ir = ca.getIccRecords();
+ }
+ }
synchronized (sInstanceLock) {
if (sInstance == null) {
- if (ci == null || ir == null || context == null || fh == null
+ if (ci == null || ca == null || ir == null || context == null || fh == null
|| ic == null) {
return null;
}
HandlerThread thread = new HandlerThread("Cat Telephony service");
thread.start();
- sInstance = new CatService(ci, ir, context, fh, ic);
+ sInstance = new CatService(ci, ca, ir, context, fh, ic);
CatLog.d(sInstance, "NEW sInstance");
} else if ((ir != null) && (mIccRecords != ir)) {
- CatLog.d(sInstance, "Reinitialize the Service with SIMRecords");
+ if (mIccRecords != null) {
+ mIccRecords.unregisterForRecordsLoaded(sInstance);
+ }
+
+ if (mUiccApplication != null) {
+ mUiccApplication.unregisterForReady(sInstance);
+ }
+ CatLog.d(sInstance,
+ "Reinitialize the Service with SIMRecords and UiccCardApplication");
mIccRecords = ir;
+ mUiccApplication = ca;
// re-Register for SIM ready event.
mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
+ mUiccApplication.registerForReady(sInstance, MSG_ID_SIM_READY, null);
CatLog.d(sInstance, "sr changed reinitialize and return current sInstance");
} else {
CatLog.d(sInstance, "Return current sInstance");
@@ -585,7 +611,7 @@ public class CatService extends Handler implements AppInterface {
* @return The only Service object in the system
*/
public static AppInterface getInstance() {
- return getInstance(null, null, null, null, null);
+ return getInstance(null, null, null);
}
@Override
diff --git a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index f125484..cc59b67 100644
--- a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -28,17 +28,18 @@ import android.provider.Telephony;
import android.util.Log;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.IccRecords;
import com.android.internal.telephony.OperatorInfo;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneNotifier;
import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.SMSDispatcher;
+import com.android.internal.telephony.UiccCardApplication;
import com.android.internal.telephony.gsm.GsmSMSDispatcher;
+import com.android.internal.telephony.gsm.SIMRecords;
import com.android.internal.telephony.gsm.SmsMessage;
import com.android.internal.telephony.ims.IsimRecords;
+import com.android.internal.telephony.ims.IsimUiccRecords;
import com.android.internal.telephony.uicc.UiccController;
import java.io.FileDescriptor;
@@ -52,6 +53,12 @@ public class CDMALTEPhone extends CDMAPhone {
/** Secondary SMSDispatcher for 3GPP format messages. */
SMSDispatcher m3gppSMS;
+ /** CdmaLtePhone in addition to RuimRecords available from
+ * PhoneBase needs access to SIMRecords and IsimUiccRecords
+ */
+ private SIMRecords mSimRecords;
+ private IsimUiccRecords mIsimUiccRecords;
+
/**
* Small container class used to hold information relevant to
* the carrier selection process. operatorNumeric can be ""
@@ -200,12 +207,11 @@ public class CDMALTEPhone extends CDMAPhone {
@Override
public boolean updateCurrentCarrierInProvider() {
- IccRecords r = mIccRecords.get();
- if (r != null) {
+ if (mSimRecords != null) {
try {
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
ContentValues map = new ContentValues();
- String operatorNumeric = r.getOperatorNumeric();
+ String operatorNumeric = mSimRecords.getOperatorNumeric();
map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
if (DBG) log("updateCurrentCarrierInProvider from UICC: numeric=" +
operatorNumeric);
@@ -223,8 +229,7 @@ public class CDMALTEPhone extends CDMAPhone {
// return IMSI from USIM as subscriber ID.
@Override
public String getSubscriberId() {
- IccRecords r = mIccRecords.get();
- return (r != null) ? r.getIMSI() : "";
+ return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
}
@Override
@@ -239,14 +244,12 @@ public class CDMALTEPhone extends CDMAPhone {
@Override
public IsimRecords getIsimRecords() {
- IccRecords r = mIccRecords.get();
- return (r != null) ? r.getIsimRecords() : null;
+ return mIsimUiccRecords;
}
@Override
public String getMsisdn() {
- IccRecords r = mIccRecords.get();
- return (r != null) ? r.getMsisdnNumber() : null;
+ return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
}
@Override
@@ -260,23 +263,41 @@ public class CDMALTEPhone extends CDMAPhone {
}
@Override
- protected void registerForRuimRecordEvents() {
- IccRecords r = mIccRecords.get();
- if (r == null) {
+ protected void onUpdateIccAvailability() {
+ if (mUiccController == null ) {
return;
}
- r.registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
- super.registerForRuimRecordEvents();
- }
- @Override
- protected void unregisterForRuimRecordEvents() {
- IccRecords r = mIccRecords.get();
- if (r == null) {
- return;
+ // Update IsimRecords
+ UiccCardApplication newUiccApplication =
+ mUiccController.getUiccCardApplication(UiccController.APP_FAM_IMS);
+ IsimUiccRecords newIsimUiccRecords = null;
+
+ if (newUiccApplication != null) {
+ newIsimUiccRecords = (IsimUiccRecords)newUiccApplication.getIccRecords();
}
- r.unregisterForNewSms(this);
- super.unregisterForRuimRecordEvents();
+ mIsimUiccRecords = newIsimUiccRecords;
+
+ // Update UsimRecords
+ newUiccApplication = mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
+ SIMRecords newSimRecords = null;
+ if (newUiccApplication != null) {
+ newSimRecords = (SIMRecords)newUiccApplication.getIccRecords();
+ }
+ if (mSimRecords != newSimRecords) {
+ if (mSimRecords != null) {
+ log("Removing stale SIMRecords object.");
+ mSimRecords.unregisterForNewSms(this);
+ mSimRecords = null;
+ }
+ if (newSimRecords != null) {
+ log("New SIMRecords found");
+ mSimRecords = newSimRecords;
+ mSimRecords.registerForNewSms(this, EVENT_NEW_ICC_SMS, null);
+ }
+ }
+
+ super.onUpdateIccAvailability();
}
@Override
diff --git a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 227b406..910b9c1 100755
--- a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -64,7 +64,10 @@ import com.android.internal.telephony.PhoneSubInfo;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.UiccCard;
+import com.android.internal.telephony.UiccCardApplication;
import com.android.internal.telephony.UUSInfo;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.cat.CatService;
import com.android.internal.telephony.uicc.UiccController;
@@ -1066,29 +1069,26 @@ public class CDMAPhone extends PhoneBase {
return;
}
- IccCard newIccCard = mUiccController.getIccCard();
+ UiccCardApplication newUiccApplication =
+ mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP2);
- IccCard c = mIccCard.get();
- if (c != newIccCard) {
- if (c != null) {
+ UiccCardApplication app = mUiccApplication.get();
+ if (app != newUiccApplication) {
+ if (app != null) {
log("Removing stale icc objects.");
if (mIccRecords.get() != null) {
unregisterForRuimRecordEvents();
- if (mRuimPhoneBookInterfaceManager != null) {
- mRuimPhoneBookInterfaceManager.updateIccRecords(null);
- }
+ mRuimPhoneBookInterfaceManager.updateIccRecords(null);
}
mIccRecords.set(null);
- mIccCard.set(null);
+ mUiccApplication.set(null);
}
- if (newIccCard != null) {
- log("New card found");
- mIccCard.set(newIccCard);
- mIccRecords.set(newIccCard.getIccRecords());
+ if (newUiccApplication != null) {
+ log("New Uicc application found");
+ mUiccApplication.set(newUiccApplication);
+ mIccRecords.set(newUiccApplication.getIccRecords());
registerForRuimRecordEvents();
- if (mRuimPhoneBookInterfaceManager != null) {
- mRuimPhoneBookInterfaceManager.updateIccRecords(mIccRecords.get());
- }
+ mRuimPhoneBookInterfaceManager.updateIccRecords(mIccRecords.get());
}
}
}
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaConnection.java b/src/java/com/android/internal/telephony/cdma/CdmaConnection.java
index c75290e..17eecbd 100755
--- a/src/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -31,8 +31,11 @@ import android.text.TextUtils;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
+
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.uicc.UiccController;
/**
* {@hide}
@@ -415,14 +418,18 @@ public class CdmaConnection extends Connection {
default:
CDMAPhone phone = owner.phone;
int serviceState = phone.getServiceState().getState();
+ AppState uiccAppState = UiccController
+ .getInstance()
+ .getUiccCardApplication(UiccController.APP_FAM_3GPP2)
+ .getState();
if (serviceState == ServiceState.STATE_POWER_OFF) {
return DisconnectCause.POWER_OFF;
} else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
|| serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
return DisconnectCause.OUT_OF_SERVICE;
} else if (phone.mCdmaSubscriptionSource ==
- CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM
- && phone.getIccCard().getState() != IccCardConstants.State.READY) {
+ CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM
+ && uiccAppState != AppState.APPSTATE_READY) {
return DisconnectCause.ICC_ERROR;
} else if (causeCode==CallFailCause.NORMAL_CLEARING) {
return DisconnectCause.NORMAL;
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 0d48eb3..c0dbf9f 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -41,13 +41,13 @@ import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.UiccCard;
+import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.AsyncChannel;
-import com.android.internal.telephony.RILConstants;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -921,11 +921,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
return;
}
- IccCard newIccCard = mUiccController.getIccCard();
- IccRecords newIccRecords = null;
- if (newIccCard != null) {
- newIccRecords = newIccCard.getIccRecords();
- }
+ IccRecords newIccRecords = mUiccController.getIccRecords(UiccController.APP_FAM_3GPP2);
IccRecords r = mIccRecords.get();
if (r != newIccRecords) {
@@ -935,7 +931,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
mIccRecords.set(null);
}
if (newIccRecords != null) {
- log("New card found");
+ log("New records found");
mIccRecords.set(newIccRecords);
newIccRecords.registerForRecordsLoaded(
this, DctConstants.EVENT_RECORDS_LOADED, null);
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index c19cc5e..cd0ba72 100755
--- a/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -35,6 +35,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.EventLog;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
import com.android.internal.telephony.IccCardConstants;
@@ -66,12 +67,12 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
handlePollStateResult(msg.what, ar);
break;
case EVENT_RUIM_RECORDS_LOADED:
- CdmaLteUiccRecords sim = (CdmaLteUiccRecords)mIccRecords;
- if ((sim != null) && sim.isProvisioned()) {
- mMdn = sim.getMdn();
- mMin = sim.getMin();
- parseSidNid(sim.getSid(), sim.getNid());
- mPrlVersion = sim.getPrlVersion();;
+ RuimRecords ruim = (RuimRecords)mIccRecords;
+ if ((ruim != null) && ruim.isProvisioned()) {
+ mMdn = ruim.getMdn();
+ mMin = ruim.getMin();
+ parseSidNid(ruim.getSid(), ruim.getNid());
+ mPrlVersion = ruim.getPrlVersion();;
mIsMinInfoReady = true;
updateOtaspState();
}
@@ -353,12 +354,12 @@ public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
ss.setOperatorAlphaLong(eriText);
}
- if (mIccCard != null && mIccCard.getState() == IccCardConstants.State.READY &&
+ if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY &&
mIccRecords != null) {
// SIM is found on the device. If ERI roaming is OFF, and SID/NID matches
// one configfured in SIM, use operator name from CSIM record.
boolean showSpn =
- ((CdmaLteUiccRecords)mIccRecords).getCsimSpnDisplayCondition();
+ ((RuimRecords)mIccRecords).getCsimSpnDisplayCondition();
int iconIndex = ss.getCdmaEriIconIndex();
if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) &&
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/src/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
deleted file mode 100644
index 93a6290..0000000
--- a/src/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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 android.util.Log;
-
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.IccConstants;
-import com.android.internal.telephony.IccFileHandler;
-import android.os.Message;
-
-/**
- * {@hide}
- */
-public final class CdmaLteUiccFileHandler extends IccFileHandler {
- static final String LOG_TAG = "CDMA";
-
- public CdmaLteUiccFileHandler(IccCard card, String aid, CommandsInterface ci) {
- super(card, aid, ci);
- }
-
- protected String getEFPath(int efid) {
- switch(efid) {
- case EF_CSIM_SPN:
- case EF_CSIM_LI:
- case EF_CSIM_MDN:
- case EF_CSIM_IMSIM:
- case EF_CSIM_CDMAHOME:
- case EF_CSIM_EPRL:
- return MF_SIM + DF_CDMA;
- case EF_AD:
- return MF_SIM + DF_GSM;
- case EF_IMPI:
- case EF_DOMAIN:
- case EF_IMPU:
- return MF_SIM + DF_ADFISIM;
- }
- return getCommonIccEFPath(efid);
- }
-
- @Override
- public void loadEFTransparent(int fileid, Message onLoaded) {
- if (fileid == EF_CSIM_EPRL) {
- // Entire PRL could be huge. We are only interested in
- // the first 4 bytes of the record.
- mCi.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
- 0, 0, 4, null, null, mAid,
- obtainMessage(EVENT_READ_BINARY_DONE,
- fileid, 0, onLoaded));
- } else {
- super.loadEFTransparent(fileid, onLoaded);
- }
- }
-
-
- protected void logd(String msg) {
- Log.d(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg);
- }
-
- protected void loge(String msg) {
- Log.e(LOG_TAG, "[CdmaLteUiccFileHandler] " + msg);
- }
-
-}
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/src/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
deleted file mode 100755
index 97f973f..0000000
--- a/src/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * 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 android.content.Context;
-import android.os.AsyncResult;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import com.android.internal.telephony.AdnRecordLoader;
-import com.android.internal.telephony.GsmAlphabet;
-import com.android.internal.telephony.IccCardApplication.AppType;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.IccFileHandler;
-import com.android.internal.telephony.IccUtils;
-import com.android.internal.telephony.MccTable;
-import com.android.internal.telephony.PhoneBase;
-import com.android.internal.telephony.SmsMessageBase;
-import com.android.internal.telephony.cdma.sms.UserData;
-import com.android.internal.telephony.gsm.SIMRecords;
-import com.android.internal.telephony.ims.IsimRecords;
-import com.android.internal.telephony.ims.IsimUiccRecords;
-
-import java.util.ArrayList;
-import java.util.Locale;
-
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM;
-
-/**
- * {@hide}
- */
-public final class CdmaLteUiccRecords extends SIMRecords {
- // From CSIM application
- private byte[] mEFpl = null;
- private byte[] mEFli = null;
- boolean mCsimSpnDisplayCondition = false;
- private String mMdn;
- private String mMin;
- private String mPrlVersion;
- private String mHomeSystemId;
- private String mHomeNetworkId;
-
- private final IsimUiccRecords mIsimUiccRecords = new IsimUiccRecords();
-
- public CdmaLteUiccRecords(IccCard card, Context c, CommandsInterface ci) {
- super(card, c, ci);
- }
-
- // Refer to ETSI TS 102.221
- private class EfPlLoaded implements IccRecordLoaded {
- public String getEfName() {
- return "EF_PL";
- }
-
- public void onRecordLoaded(AsyncResult ar) {
- mEFpl = (byte[]) ar.result;
- if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl));
- }
- }
-
- // Refer to C.S0065 5.2.26
- private class EfCsimLiLoaded implements IccRecordLoaded {
- public String getEfName() {
- return "EF_CSIM_LI";
- }
-
- public void onRecordLoaded(AsyncResult ar) {
- mEFli = (byte[]) ar.result;
- // convert csim efli data to iso 639 format
- for (int i = 0; i < mEFli.length; i+=2) {
- switch(mEFli[i+1]) {
- case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break;
- case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break;
- case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break;
- case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break;
- case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break;
- case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break;
- case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break;
- default: mEFli[i] = ' '; mEFli[i+1] = ' ';
- }
- }
-
- if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli));
- }
- }
-
- // Refer to C.S0065 5.2.32
- private class EfCsimSpnLoaded implements IccRecordLoaded {
- public String getEfName() {
- return "EF_CSIM_SPN";
- }
-
- public void onRecordLoaded(AsyncResult ar) {
- byte[] data = (byte[]) ar.result;
- if (DBG) log("CSIM_SPN=" +
- IccUtils.bytesToHexString(data));
-
- // C.S0065 for EF_SPN decoding
- mCsimSpnDisplayCondition = ((0x01 & data[0]) != 0);
-
- int encoding = data[1];
- int language = data[2];
- byte[] spnData = new byte[32];
- int len = ((data.length - 3) < 32) ? (data.length - 3) : 32;
- System.arraycopy(data, 3, spnData, 0, len);
-
- int numBytes;
- for (numBytes = 0; numBytes < spnData.length; numBytes++) {
- if ((spnData[numBytes] & 0xFF) == 0xFF) break;
- }
-
- if (numBytes == 0) {
- spn = "";
- return;
- }
- try {
- switch (encoding) {
- case UserData.ENCODING_OCTET:
- case UserData.ENCODING_LATIN:
- spn = new String(spnData, 0, numBytes, "ISO-8859-1");
- break;
- case UserData.ENCODING_IA5:
- case UserData.ENCODING_GSM_7BIT_ALPHABET:
- case UserData.ENCODING_7BIT_ASCII:
- spn = GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7);
- break;
- case UserData.ENCODING_UNICODE_16:
- spn = new String(spnData, 0, numBytes, "utf-16");
- break;
- default:
- log("SPN encoding not supported");
- }
- } catch(Exception e) {
- log("spn decode error: " + e);
- }
- if (DBG) log("spn=" + spn);
- if (DBG) log("spnCondition=" + mCsimSpnDisplayCondition);
- SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, spn);
- }
- }
-
- private class EfCsimMdnLoaded implements IccRecordLoaded {
- public String getEfName() {
- return "EF_CSIM_MDN";
- }
-
- public void onRecordLoaded(AsyncResult ar) {
- byte[] data = (byte[]) ar.result;
- if (DBG) log("CSIM_MDN=" + IccUtils.bytesToHexString(data));
- int mdnDigitsNum = 0x0F & data[0];
- mMdn = IccUtils.cdmaBcdToString(data, 1, mdnDigitsNum);
- if (DBG) log("CSIM MDN=" + mMdn);
- }
- }
-
- private class EfCsimImsimLoaded implements IccRecordLoaded {
- public String getEfName() {
- return "EF_CSIM_IMSIM";
- }
-
- public void onRecordLoaded(AsyncResult ar) {
- byte[] data = (byte[]) ar.result;
- if (DBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data));
- // C.S0065 section 5.2.2 for IMSI_M encoding
- // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
- boolean provisioned = ((data[7] & 0x80) == 0x80);
-
- if (provisioned) {
- int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
- int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
- int digit7 = 0x0F & (data[4] >> 2);
- if (digit7 > 0x09) digit7 = 0;
- int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);
- first3digits = adjstMinDigits(first3digits);
- second3digits = adjstMinDigits(second3digits);
- last3digits = adjstMinDigits(last3digits);
-
- StringBuilder builder = new StringBuilder();
- builder.append(String.format(Locale.US, "%03d", first3digits));
- builder.append(String.format(Locale.US, "%03d", second3digits));
- builder.append(String.format(Locale.US, "%d", digit7));
- builder.append(String.format(Locale.US, "%03d", last3digits));
- mMin = builder.toString();
- if (DBG) log("min present=" + mMin);
- } else {
- if (DBG) log("min not present");
- }
- }
- }
-
- private class EfCsimCdmaHomeLoaded implements IccRecordLoaded {
- public String getEfName() {
- return "EF_CSIM_CDMAHOME";
- }
-
- public void onRecordLoaded(AsyncResult ar) {
- // Per C.S0065 section 5.2.8
- ArrayList<byte[]> dataList = (ArrayList<byte[]>) ar.result;
- if (DBG) log("CSIM_CDMAHOME data size=" + dataList.size());
- if (dataList.isEmpty()) {
- return;
- }
- StringBuilder sidBuf = new StringBuilder();
- StringBuilder nidBuf = new StringBuilder();
-
- for (byte[] data : dataList) {
- if (data.length == 5) {
- int sid = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
- int nid = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF);
- sidBuf.append(sid).append(',');
- nidBuf.append(nid).append(',');
- }
- }
- // remove trailing ","
- sidBuf.setLength(sidBuf.length()-1);
- nidBuf.setLength(nidBuf.length()-1);
-
- mHomeSystemId = sidBuf.toString();
- mHomeNetworkId = nidBuf.toString();
- }
- }
-
- private class EfCsimEprlLoaded implements IccRecordLoaded {
- public String getEfName() {
- return "EF_CSIM_EPRL";
- }
- public void onRecordLoaded(AsyncResult ar) {
- onGetCSimEprlDone(ar);
- }
- }
-
- @Override
- protected void onRecordLoaded() {
- // One record loaded successfully or failed, In either case
- // we need to update the recordsToLoad count
- recordsToLoad -= 1;
-
- if (recordsToLoad == 0 && recordsRequested == true) {
- onAllRecordsLoaded();
- } else if (recordsToLoad < 0) {
- Log.e(LOG_TAG, "SIMRecords: recordsToLoad <0, programmer error suspected");
- recordsToLoad = 0;
- }
- }
-
- @Override
- protected void onAllRecordsLoaded() {
- setLocaleFromCsim();
- super.onAllRecordsLoaded(); // broadcasts ICC state change to "LOADED"
- }
-
- @Override
- protected void fetchSimRecords() {
- recordsRequested = true;
-
- mCi.getIMSIForApp(mParentCard.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_PL,
- obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded()));
- recordsToLoad++;
-
- new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, EF_EXT1, 1,
- obtainMessage(EVENT_GET_MSISDN_DONE));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_CSIM_LI,
- obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimLiLoaded()));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_CSIM_SPN,
- obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimSpnLoaded()));
- recordsToLoad++;
-
- mFh.loadEFLinearFixed(EF_CSIM_MDN, 1,
- obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMdnLoaded()));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_CSIM_IMSIM,
- obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded()));
- recordsToLoad++;
-
- mFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME,
- obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimCdmaHomeLoaded()));
- recordsToLoad++;
-
- mFh.loadEFTransparent(EF_CSIM_EPRL,
- obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimEprlLoaded()));
- recordsToLoad++;
-
- // load ISIM records
- recordsToLoad += mIsimUiccRecords.fetchIsimRecords(mFh, this);
- }
-
- private int adjstMinDigits (int digits) {
- // Per C.S0005 section 2.3.1.
- digits += 111;
- digits = (digits % 10 == 0)?(digits - 10):digits;
- digits = ((digits / 10) % 10 == 0)?(digits - 100):digits;
- digits = ((digits / 100) % 10 == 0)?(digits - 1000):digits;
- return digits;
- }
-
- private void onGetCSimEprlDone(AsyncResult ar) {
- // C.S0065 section 5.2.57 for EFeprl encoding
- // C.S0016 section 3.5.5 for PRL format.
- byte[] data = (byte[]) ar.result;
- if (DBG) log("CSIM_EPRL=" + IccUtils.bytesToHexString(data));
-
- // Only need the first 4 bytes of record
- if (data.length > 3) {
- int prlId = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
- mPrlVersion = Integer.toString(prlId);
- }
- if (DBG) log("CSIM PRL version=" + mPrlVersion);
- }
-
- private void setLocaleFromCsim() {
- String prefLang = null;
- // check EFli then EFpl
- prefLang = findBestLanguage(mEFli);
-
- if (prefLang == null) {
- prefLang = findBestLanguage(mEFpl);
- }
-
- if (prefLang != null) {
- // check country code from SIM
- String imsi = getIMSI();
- String country = null;
- if (imsi != null) {
- country = MccTable.countryCodeForMcc(
- Integer.parseInt(imsi.substring(0,3)));
- }
- log("Setting locale to " + prefLang + "_" + country);
- MccTable.setSystemLocale(mContext, prefLang, country);
- } else {
- log ("No suitable CSIM selected locale");
- }
- }
-
- private String findBestLanguage(byte[] languages) {
- String bestMatch = null;
- String[] locales = mContext.getAssets().getLocales();
-
- if ((languages == null) || (locales == null)) return null;
-
- // Each 2-bytes consists of one language
- for (int i = 0; (i + 1) < languages.length; i += 2) {
- try {
- String lang = new String(languages, i, 2, "ISO-8859-1");
- for (int j = 0; j < locales.length; j++) {
- if (locales[j] != null && locales[j].length() >= 2 &&
- locales[j].substring(0, 2).equals(lang)) {
- return lang;
- }
- }
- if (bestMatch != null) break;
- } catch(java.io.UnsupportedEncodingException e) {
- log ("Failed to parse SIM language records");
- }
- }
- // no match found. return null
- return null;
- }
-
- @Override
- protected void log(String s) {
- Log.d(LOG_TAG, "[CSIM] " + s);
- }
-
- @Override
- protected void loge(String s) {
- Log.e(LOG_TAG, "[CSIM] " + s);
- }
-
- public String getMdn() {
- return mMdn;
- }
-
- public String getMin() {
- return mMin;
- }
-
- public String getSid() {
- return mHomeSystemId;
- }
-
- public String getNid() {
- return mHomeNetworkId;
- }
-
- public String getPrlVersion() {
- return mPrlVersion;
- }
-
- public boolean getCsimSpnDisplayCondition() {
- return mCsimSpnDisplayCondition;
- }
-
- @Override
- public IsimRecords getIsimRecords() {
- return mIsimUiccRecords;
- }
-
- @Override
- public boolean isProvisioned() {
- // If UICC card has CSIM app, look for MDN and MIN field
- // to determine if the SIM is provisioned. Otherwise,
- // consider the SIM is provisioned. (for case of ordinal
- // USIM only UICC.)
- // If PROPERTY_TEST_CSIM is defined, bypess provision check
- // and consider the SIM is provisioned.
- if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) {
- return true;
- }
-
- if (mParentCard == null) {
- return false;
- }
-
- if (mParentCard.isApplicationOnIcc(AppType.APPTYPE_CSIM) &&
- ((mMdn == null) || (mMin == null))) {
- return false;
- }
- return true;
- }
-}
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 697ad73..03a71d8 100755
--- a/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -20,7 +20,6 @@ import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags;
-import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.PhoneConstants;
@@ -29,7 +28,10 @@ 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.UiccCard;
+import com.android.internal.telephony.UiccCardApplication;
import com.android.internal.telephony.CommandsInterface.RadioState;
+import com.android.internal.telephony.uicc.UiccController;
import android.app.AlarmManager;
import android.content.ContentResolver;
@@ -157,7 +159,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
};
public CdmaServiceStateTracker(CDMAPhone phone) {
- super(phone, phone.mCM);
+ super(phone.getContext(), phone.mCM);
this.phone = phone;
cr = phone.getContext().getContentResolver();
@@ -206,7 +208,7 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
cm.unregisterForVoiceNetworkStateChanged(this);
cm.unregisterForCdmaOtaProvision(this);
phone.unregisterForEriFileLoaded(this);
- if (mIccCard != null) {mIccCard.unregisterForReady(this);}
+ if (mUiccApplcation != null) {mUiccApplcation.unregisterForReady(this);}
if (mIccRecords != null) {mIccRecords.unregisterForRecordsLoaded(this);}
cm.unSetOnSignalStrengthUpdate(this);
cm.unSetOnNITZTime(this);
@@ -397,17 +399,15 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
mIsMinInfoReady = true;
updateOtaspState();
- if (mIccCard != null) {
+ if (!isSubscriptionFromRuim && mIccRecords != null) {
if (DBG) {
- log("GET_CDMA_SUBSCRIPTION broadcast Icc state changed");
+ log("GET_CDMA_SUBSCRIPTION set imsi in mIccRecords");
}
- mIccCard.broadcastIccStateChangedIntent(
- IccCardConstants.INTENT_VALUE_ICC_IMSI,
- null);
+ mIccRecords.setImsi(getImsi());
} else {
if (DBG) {
- log("GET_CDMA_SUBSCRIPTION mIccCard is null (probably NV type device)" +
- " can't broadcast Icc state changed");
+ log("GET_CDMA_SUBSCRIPTION either mIccRecords is null or NV type device" +
+ " - not setting Imsi in mIccRecords");
}
}
} else {
@@ -1665,24 +1665,25 @@ public class CdmaServiceStateTracker extends ServiceStateTracker {
return;
}
- IccCard newIccCard = mUiccController.getIccCard();
+ UiccCardApplication newUiccApplication =
+ mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP2);
- if (mIccCard != newIccCard) {
- if (mIccCard != null) {
+ if (mUiccApplcation != newUiccApplication) {
+ if (mUiccApplcation != null) {
log("Removing stale icc objects.");
- mIccCard.unregisterForReady(this);
+ mUiccApplcation.unregisterForReady(this);
if (mIccRecords != null) {
mIccRecords.unregisterForRecordsLoaded(this);
}
mIccRecords = null;
- mIccCard = null;
+ mUiccApplcation = null;
}
- if (newIccCard != null) {
+ if (newUiccApplication != null) {
log("New card found");
- mIccCard = newIccCard;
- mIccRecords = mIccCard.getIccRecords();
+ mUiccApplcation = newUiccApplication;
+ mIccRecords = mUiccApplcation.getIccRecords();
if (isSubscriptionFromRuim) {
- mIccCard.registerForReady(this, EVENT_RUIM_READY, null);
+ mUiccApplcation.registerForReady(this, EVENT_RUIM_READY, null);
if (mIccRecords != null) {
mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
}
diff --git a/src/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/src/java/com/android/internal/telephony/cdma/RuimFileHandler.java
index f440935..4c271f9 100644
--- a/src/java/com/android/internal/telephony/cdma/RuimFileHandler.java
+++ b/src/java/com/android/internal/telephony/cdma/RuimFileHandler.java
@@ -20,17 +20,8 @@ import android.os.*;
import android.util.Log;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.IccConstants;
-import com.android.internal.telephony.IccException;
import com.android.internal.telephony.IccFileHandler;
-import com.android.internal.telephony.IccFileTypeMismatch;
-import com.android.internal.telephony.IccIoResult;
-import com.android.internal.telephony.IccUtils;
-import com.android.internal.telephony.PhoneBase;
-import com.android.internal.telephony.PhoneProxy;
-
-import java.util.ArrayList;
+import com.android.internal.telephony.UiccCardApplication;
/**
* {@hide}
@@ -41,12 +32,8 @@ public final class RuimFileHandler extends IccFileHandler {
//***** Instance Variables
//***** Constructor
- public RuimFileHandler(IccCard card, String aid, CommandsInterface ci) {
- super(card, aid, ci);
- }
-
- protected void finalize() {
- Log.d(LOG_TAG, "RuimFileHandler finalized");
+ public RuimFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
+ super(app, aid, ci);
}
//***** Overridden from IccFileHandler
@@ -63,25 +50,27 @@ public final class RuimFileHandler extends IccFileHandler {
}
@Override
- public void handleMessage(Message msg) {
-
- super.handleMessage(msg);
- }
-
protected String getEFPath(int efid) {
switch(efid) {
case EF_SMS:
case EF_CST:
case EF_RUIM_SPN:
+ case EF_CSIM_LI:
+ case EF_CSIM_MDN:
+ case EF_CSIM_IMSIM:
+ case EF_CSIM_CDMAHOME:
+ case EF_CSIM_EPRL:
return MF_SIM + DF_CDMA;
}
return getCommonIccEFPath(efid);
}
+ @Override
protected void logd(String msg) {
Log.d(LOG_TAG, "[RuimFileHandler] " + msg);
}
+ @Override
protected void loge(String msg) {
Log.e(LOG_TAG, "[RuimFileHandler] " + msg);
}
diff --git a/src/java/com/android/internal/telephony/cdma/RuimRecords.java b/src/java/com/android/internal/telephony/cdma/RuimRecords.java
index d3e04bd..e8cd8f3 100755
--- a/src/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/src/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -16,8 +16,15 @@
package com.android.internal.telephony.cdma;
+
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_TEST_CSIM;
+
+import java.util.ArrayList;
+import java.util.Locale;
import android.content.Context;
import android.os.AsyncResult;
import android.os.Handler;
@@ -31,11 +38,12 @@ import com.android.internal.telephony.AdnRecordCache;
import com.android.internal.telephony.AdnRecordLoader;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.IccRefreshResponse;
-import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.UiccCardApplication;
// can't be used since VoiceMailConstants is not public
//import com.android.internal.telephony.gsm.VoiceMailConstants;
@@ -43,6 +51,9 @@ import com.android.internal.telephony.IccException;
import com.android.internal.telephony.IccRecords;
import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.IccCardApplicationStatus.AppType;
+import com.android.internal.telephony.IccRecords.IccRecordLoaded;
+import com.android.internal.telephony.cdma.sms.UserData;
/**
@@ -56,15 +67,21 @@ public final class RuimRecords extends IccRecords {
// ***** Instance Variables
- private String mImsi;
private String mMyMobileNumber;
private String mMin2Min1;
private String mPrlVersion;
+ // From CSIM application
+ private byte[] mEFpl = null;
+ private byte[] mEFli = null;
+ boolean mCsimSpnDisplayCondition = false;
+ private String mMdn;
+ private String mMin;
+ private String mHomeSystemId;
+ private String mHomeNetworkId;
// ***** Event Constants
-
- private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
+ private static final int EVENT_APP_READY = 1;
private static final int EVENT_GET_IMSI_DONE = 3;
private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
private static final int EVENT_GET_ICCID_DONE = 5;
@@ -79,9 +96,8 @@ public final class RuimRecords extends IccRecords {
private static final int EVENT_RUIM_REFRESH = 31;
-
- public RuimRecords(IccCard card, Context c, CommandsInterface ci) {
- super(card, c, ci);
+ public RuimRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
+ super(app, c, ci);
adnCache = new AdnRecordCache(mFh);
@@ -90,21 +106,22 @@ public final class RuimRecords extends IccRecords {
// recordsToLoad is set to 0 because no requests are made yet
recordsToLoad = 0;
- mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
// NOTE the EVENT_SMS_ON_RUIM is not registered
mCi.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
// Start off by setting empty state
- onRadioOffOrNotAvailable();
+ resetRecords();
+ mParentApp.registerForReady(this, EVENT_APP_READY, null);
}
@Override
public void dispose() {
if (DBG) log("Disposing RuimRecords " + this);
//Unregister for all events
- mCi.unregisterForOffOrNotAvailable( this);
mCi.unregisterForIccRefresh(this);
+ mParentApp.unregisterForReady(this);
+ resetRecords();
super.dispose();
}
@@ -113,8 +130,7 @@ public final class RuimRecords extends IccRecords {
if(DBG) log("RuimRecords finalized");
}
- @Override
- protected void onRadioOffOrNotAvailable() {
+ protected void resetRecords() {
countVoiceMessages = 0;
mncLength = UNINITIALIZED;
iccid = null;
@@ -133,6 +149,11 @@ public final class RuimRecords extends IccRecords {
recordsRequested = false;
}
+ @Override
+ public String getIMSI() {
+ return mImsi;
+ }
+
public String getMdnNumber() {
return mMyMobileNumber;
}
@@ -170,6 +191,15 @@ public final class RuimRecords extends IccRecords {
}
}
+ private int adjstMinDigits (int digits) {
+ // Per C.S0005 section 2.3.1.
+ digits += 111;
+ digits = (digits % 10 == 0)?(digits - 10):digits;
+ digits = ((digits / 10) % 10 == 0)?(digits - 100):digits;
+ digits = ((digits / 100) % 10 == 0)?(digits - 1000):digits;
+ return digits;
+ }
+
/**
* Returns the 5 or 6 digit MCC/MNC of the operator that
* provided the RUIM card. Returns null of RUIM is not yet ready
@@ -192,6 +222,204 @@ public final class RuimRecords extends IccRecords {
return mImsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
}
+ // Refer to ETSI TS 102.221
+ private class EfPlLoaded implements IccRecordLoaded {
+ public String getEfName() {
+ return "EF_PL";
+ }
+
+ public void onRecordLoaded(AsyncResult ar) {
+ mEFpl = (byte[]) ar.result;
+ if (DBG) log("EF_PL=" + IccUtils.bytesToHexString(mEFpl));
+ }
+ }
+
+ // Refer to C.S0065 5.2.26
+ private class EfCsimLiLoaded implements IccRecordLoaded {
+ public String getEfName() {
+ return "EF_CSIM_LI";
+ }
+
+ public void onRecordLoaded(AsyncResult ar) {
+ mEFli = (byte[]) ar.result;
+ // convert csim efli data to iso 639 format
+ for (int i = 0; i < mEFli.length; i+=2) {
+ switch(mEFli[i+1]) {
+ case 0x01: mEFli[i] = 'e'; mEFli[i+1] = 'n';break;
+ case 0x02: mEFli[i] = 'f'; mEFli[i+1] = 'r';break;
+ case 0x03: mEFli[i] = 'e'; mEFli[i+1] = 's';break;
+ case 0x04: mEFli[i] = 'j'; mEFli[i+1] = 'a';break;
+ case 0x05: mEFli[i] = 'k'; mEFli[i+1] = 'o';break;
+ case 0x06: mEFli[i] = 'z'; mEFli[i+1] = 'h';break;
+ case 0x07: mEFli[i] = 'h'; mEFli[i+1] = 'e';break;
+ default: mEFli[i] = ' '; mEFli[i+1] = ' ';
+ }
+ }
+
+ if (DBG) log("EF_LI=" + IccUtils.bytesToHexString(mEFli));
+ }
+ }
+
+ // Refer to C.S0065 5.2.32
+ private class EfCsimSpnLoaded implements IccRecordLoaded {
+ public String getEfName() {
+ return "EF_CSIM_SPN";
+ }
+
+ public void onRecordLoaded(AsyncResult ar) {
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_SPN=" +
+ IccUtils.bytesToHexString(data));
+
+ // C.S0065 for EF_SPN decoding
+ mCsimSpnDisplayCondition = ((0x01 & data[0]) != 0);
+
+ int encoding = data[1];
+ int language = data[2];
+ byte[] spnData = new byte[32];
+ int len = ((data.length - 3) < 32) ? (data.length - 3) : 32;
+ System.arraycopy(data, 3, spnData, 0, len);
+
+ int numBytes;
+ for (numBytes = 0; numBytes < spnData.length; numBytes++) {
+ if ((spnData[numBytes] & 0xFF) == 0xFF) break;
+ }
+
+ if (numBytes == 0) {
+ spn = "";
+ return;
+ }
+ try {
+ switch (encoding) {
+ case UserData.ENCODING_OCTET:
+ case UserData.ENCODING_LATIN:
+ spn = new String(spnData, 0, numBytes, "ISO-8859-1");
+ break;
+ case UserData.ENCODING_IA5:
+ case UserData.ENCODING_GSM_7BIT_ALPHABET:
+ case UserData.ENCODING_7BIT_ASCII:
+ spn = GsmAlphabet.gsm7BitPackedToString(spnData, 0, (numBytes*8)/7);
+ break;
+ case UserData.ENCODING_UNICODE_16:
+ spn = new String(spnData, 0, numBytes, "utf-16");
+ break;
+ default:
+ log("SPN encoding not supported");
+ }
+ } catch(Exception e) {
+ log("spn decode error: " + e);
+ }
+ if (DBG) log("spn=" + spn);
+ if (DBG) log("spnCondition=" + mCsimSpnDisplayCondition);
+ SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, spn);
+ }
+ }
+
+ private class EfCsimMdnLoaded implements IccRecordLoaded {
+ public String getEfName() {
+ return "EF_CSIM_MDN";
+ }
+
+ public void onRecordLoaded(AsyncResult ar) {
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_MDN=" + IccUtils.bytesToHexString(data));
+ // Refer to C.S0065 5.2.35
+ int mdnDigitsNum = 0x0F & data[0];
+ mMdn = IccUtils.cdmaBcdToString(data, 1, mdnDigitsNum);
+ if (DBG) log("CSIM MDN=" + mMdn);
+ }
+ }
+
+ private class EfCsimImsimLoaded implements IccRecordLoaded {
+ public String getEfName() {
+ return "EF_CSIM_IMSIM";
+ }
+
+ public void onRecordLoaded(AsyncResult ar) {
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_IMSIM=" + IccUtils.bytesToHexString(data));
+ // C.S0065 section 5.2.2 for IMSI_M encoding
+ // C.S0005 section 2.3.1 for MIN encoding in IMSI_M.
+ boolean provisioned = ((data[7] & 0x80) == 0x80);
+
+ if (provisioned) {
+ int first3digits = ((0x03 & data[2]) << 8) + (0xFF & data[1]);
+ int second3digits = (((0xFF & data[5]) << 8) | (0xFF & data[4])) >> 6;
+ int digit7 = 0x0F & (data[4] >> 2);
+ if (digit7 > 0x09) digit7 = 0;
+ int last3digits = ((0x03 & data[4]) << 8) | (0xFF & data[3]);
+ first3digits = adjstMinDigits(first3digits);
+ second3digits = adjstMinDigits(second3digits);
+ last3digits = adjstMinDigits(last3digits);
+
+ StringBuilder builder = new StringBuilder();
+ builder.append(String.format(Locale.US, "%03d", first3digits));
+ builder.append(String.format(Locale.US, "%03d", second3digits));
+ builder.append(String.format(Locale.US, "%d", digit7));
+ builder.append(String.format(Locale.US, "%03d", last3digits));
+ mMin = builder.toString();
+ if (DBG) log("min present=" + mMin);
+ } else {
+ if (DBG) log("min not present");
+ }
+ }
+ }
+
+ private class EfCsimCdmaHomeLoaded implements IccRecordLoaded {
+ public String getEfName() {
+ return "EF_CSIM_CDMAHOME";
+ }
+
+ public void onRecordLoaded(AsyncResult ar) {
+ // Per C.S0065 section 5.2.8
+ ArrayList<byte[]> dataList = (ArrayList<byte[]>) ar.result;
+ if (DBG) log("CSIM_CDMAHOME data size=" + dataList.size());
+ if (dataList.isEmpty()) {
+ return;
+ }
+ StringBuilder sidBuf = new StringBuilder();
+ StringBuilder nidBuf = new StringBuilder();
+
+ for (byte[] data : dataList) {
+ if (data.length == 5) {
+ int sid = ((data[1] & 0xFF) << 8) | (data[0] & 0xFF);
+ int nid = ((data[3] & 0xFF) << 8) | (data[2] & 0xFF);
+ sidBuf.append(sid).append(',');
+ nidBuf.append(nid).append(',');
+ }
+ }
+ // remove trailing ","
+ sidBuf.setLength(sidBuf.length()-1);
+ nidBuf.setLength(nidBuf.length()-1);
+
+ mHomeSystemId = sidBuf.toString();
+ mHomeNetworkId = nidBuf.toString();
+ }
+ }
+
+ private class EfCsimEprlLoaded implements IccRecordLoaded {
+ public String getEfName() {
+ return "EF_CSIM_EPRL";
+ }
+ public void onRecordLoaded(AsyncResult ar) {
+ onGetCSimEprlDone(ar);
+ }
+ }
+
+ private void onGetCSimEprlDone(AsyncResult ar) {
+ // C.S0065 section 5.2.57 for EFeprl encoding
+ // C.S0016 section 3.5.5 for PRL format.
+ byte[] data = (byte[]) ar.result;
+ if (DBG) log("CSIM_EPRL=" + IccUtils.bytesToHexString(data));
+
+ // Only need the first 4 bytes of record
+ if (data.length > 3) {
+ int prlId = ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
+ mPrlVersion = Integer.toString(prlId);
+ }
+ if (DBG) log("CSIM PRL version=" + mPrlVersion);
+ }
+
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
@@ -207,9 +435,9 @@ public final class RuimRecords extends IccRecords {
}
try { switch (msg.what) {
- case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
- onRadioOffOrNotAvailable();
- break;
+ case EVENT_APP_READY:
+ onReady();
+ break;
case EVENT_GET_DEVICE_IDENTITY_DONE:
log("Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
@@ -302,6 +530,9 @@ public final class RuimRecords extends IccRecords {
}
break;
+ default:
+ super.handleMessage(msg); // IccRecords handles generic record load responses
+
}}catch (RuntimeException exc) {
// I don't want these exceptions to be fatal
Log.w(LOG_TAG, "Exception parsing RUIM record", exc);
@@ -313,6 +544,55 @@ public final class RuimRecords extends IccRecords {
}
}
+ private String findBestLanguage(byte[] languages) {
+ String bestMatch = null;
+ String[] locales = mContext.getAssets().getLocales();
+
+ if ((languages == null) || (locales == null)) return null;
+
+ // Each 2-bytes consists of one language
+ for (int i = 0; (i + 1) < languages.length; i += 2) {
+ try {
+ String lang = new String(languages, i, 2, "ISO-8859-1");
+ for (int j = 0; j < locales.length; j++) {
+ if (locales[j] != null && locales[j].length() >= 2 &&
+ locales[j].substring(0, 2).equals(lang)) {
+ return lang;
+ }
+ }
+ if (bestMatch != null) break;
+ } catch(java.io.UnsupportedEncodingException e) {
+ log ("Failed to parse SIM language records");
+ }
+ }
+ // no match found. return null
+ return null;
+ }
+
+ private void setLocaleFromCsim() {
+ String prefLang = null;
+ // check EFli then EFpl
+ prefLang = findBestLanguage(mEFli);
+
+ if (prefLang == null) {
+ prefLang = findBestLanguage(mEFpl);
+ }
+
+ if (prefLang != null) {
+ // check country code from SIM
+ String imsi = getIMSI();
+ String country = null;
+ if (imsi != null) {
+ country = MccTable.countryCodeForMcc(
+ Integer.parseInt(imsi.substring(0,3)));
+ }
+ log("Setting locale to " + prefLang + "_" + country);
+ MccTable.setSystemLocale(mContext, prefLang, country);
+ } else {
+ log ("No suitable CSIM selected locale");
+ }
+ }
+
@Override
protected void onRecordLoaded() {
// One record loaded successfully or failed, In either case
@@ -343,10 +623,10 @@ public final class RuimRecords extends IccRecords {
SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
MccTable.countryCodeForMcc(Integer.parseInt(mImsi.substring(0,3))));
}
+
+ setLocaleFromCsim();
recordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
- mParentCard.broadcastIccStateChangedIntent(
- IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
}
@Override
@@ -362,13 +642,43 @@ public final class RuimRecords extends IccRecords {
if (DBG) log("fetchRuimRecords " + recordsToLoad);
- mCi.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE));
+ mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
recordsToLoad++;
mFh.loadEFTransparent(EF_ICCID,
obtainMessage(EVENT_GET_ICCID_DONE));
recordsToLoad++;
+ mFh.loadEFTransparent(EF_PL,
+ obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfPlLoaded()));
+ recordsToLoad++;
+
+ mFh.loadEFTransparent(EF_CSIM_LI,
+ obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimLiLoaded()));
+ recordsToLoad++;
+
+ mFh.loadEFTransparent(EF_CSIM_SPN,
+ obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimSpnLoaded()));
+ recordsToLoad++;
+
+ mFh.loadEFLinearFixed(EF_CSIM_MDN, 1,
+ obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimMdnLoaded()));
+ recordsToLoad++;
+
+ mFh.loadEFTransparent(EF_CSIM_IMSIM,
+ obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimImsimLoaded()));
+ recordsToLoad++;
+
+ mFh.loadEFLinearFixedAll(EF_CSIM_CDMAHOME,
+ obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimCdmaHomeLoaded()));
+ recordsToLoad++;
+
+ // Entire PRL could be huge. We are only interested in
+ // the first 4 bytes of the record.
+ mFh.loadEFTransparent(EF_CSIM_EPRL, 4,
+ obtainMessage(EVENT_GET_ICC_RECORD_DONE, new EfCsimEprlLoaded()));
+ recordsToLoad++;
+
if (DBG) log("fetchRuimRecords " + recordsToLoad + " requested: " + recordsRequested);
// Further records that can be inserted are Operator/OEM dependent
}
@@ -385,6 +695,29 @@ public final class RuimRecords extends IccRecords {
}
@Override
+ public boolean isProvisioned() {
+ // If UICC card has CSIM app, look for MDN and MIN field
+ // to determine if the SIM is provisioned. Otherwise,
+ // consider the SIM is provisioned. (for case of ordinal
+ // USIM only UICC.)
+ // If PROPERTY_TEST_CSIM is defined, bypess provision check
+ // and consider the SIM is provisioned.
+ if (SystemProperties.getBoolean(PROPERTY_TEST_CSIM, false)) {
+ return true;
+ }
+
+ if (mParentApp == null) {
+ return false;
+ }
+
+ if (mParentApp.getType() == AppType.APPTYPE_CSIM &&
+ ((mMdn == null) || (mMin == null))) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
public void setVoiceMessageWaiting(int line, int countWaiting) {
if (line != 1) {
// only profile 1 is supported
@@ -411,7 +744,7 @@ public final class RuimRecords extends IccRecords {
}
if (refreshResponse.aid != null &&
- !refreshResponse.aid.equals(mParentCard.getAid())) {
+ !refreshResponse.aid.equals(mParentApp.getAid())) {
// This is for different app. Ignore.
return;
}
@@ -445,6 +778,25 @@ public final class RuimRecords extends IccRecords {
}
}
+ public String getMdn() {
+ return mMdn;
+ }
+
+ public String getMin() {
+ return mMin;
+ }
+
+ public String getSid() {
+ return mHomeSystemId;
+ }
+
+ public String getNid() {
+ return mHomeNetworkId;
+ }
+
+ public boolean getCsimSpnDisplayCondition() {
+ return mCsimSpnDisplayCondition;
+ }
@Override
protected void log(String s) {
Log.d(LOG_TAG, "[RuimRecords] " + s);
diff --git a/src/java/com/android/internal/telephony/gsm/GSMPhone.java b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
index b429cd2..c1cd019 100644
--- a/src/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -50,13 +50,13 @@ import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDI
import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
import com.android.internal.telephony.cat.CatService;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallForwardInfo;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Connection;
-import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccFileHandler;
import com.android.internal.telephony.IccPhoneBookInterfaceManager;
import com.android.internal.telephony.IccRecords;
@@ -71,6 +71,8 @@ import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.PhoneSubInfo;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.UUSInfo;
+import com.android.internal.telephony.UiccCard;
+import com.android.internal.telephony.UiccCardApplication;
import com.android.internal.telephony.test.SimulatedRadioControl;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.IccVmNotSupportedException;
@@ -710,7 +712,8 @@ public class GSMPhone extends PhoneBase {
// Only look at the Network portion for mmi
String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
- GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this);
+ GsmMmiCode mmi =
+ GsmMmiCode.newFromDialString(networkPortion, this, mUiccApplication.get());
if (LOCAL_DEBUG) Log.d(LOG_TAG,
"dialing w/ mmi '" + mmi + "'...");
@@ -729,7 +732,7 @@ public class GSMPhone extends PhoneBase {
}
public boolean handlePinMmi(String dialString) {
- GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this);
+ GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
if (mmi != null && mmi.isPinCommand()) {
mPendingMMIs.add(mmi);
@@ -742,7 +745,7 @@ public class GSMPhone extends PhoneBase {
}
public void sendUssdResponse(String ussdMessge) {
- GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this);
+ GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this, mUiccApplication.get());
mPendingMMIs.add(mmi);
mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
mmi.sendUssd(ussdMessge);
@@ -1139,7 +1142,8 @@ public class GSMPhone extends PhoneBase {
GsmMmiCode mmi;
mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
isUssdRequest,
- GSMPhone.this);
+ GSMPhone.this,
+ mUiccApplication.get());
onNetworkInitiatedUssd(mmi);
}
}
@@ -1339,23 +1343,24 @@ public class GSMPhone extends PhoneBase {
return;
}
- IccCard newIccCard = mUiccController.getIccCard();
+ UiccCardApplication newUiccApplication =
+ mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
- IccCard c = mIccCard.get();
- if (c != newIccCard) {
- if (c != null) {
+ UiccCardApplication app = mUiccApplication.get();
+ if (app != newUiccApplication) {
+ if (app != null) {
if (LOCAL_DEBUG) log("Removing stale icc objects.");
if (mIccRecords.get() != null) {
unregisterForSimRecordEvents();
mSimPhoneBookIntManager.updateIccRecords(null);
}
mIccRecords.set(null);
- mIccCard.set(null);
+ mUiccApplication.set(null);
}
- if (newIccCard != null) {
- if (LOCAL_DEBUG) log("New card found");
- mIccCard.set(newIccCard);
- mIccRecords.set(newIccCard.getIccRecords());
+ if (newUiccApplication != null) {
+ if (LOCAL_DEBUG) log("New Uicc application found");
+ mUiccApplication.set(newUiccApplication);
+ mIccRecords.set(newUiccApplication.getIccRecords());
registerForSimRecordEvents();
mSimPhoneBookIntManager.updateIccRecords(mIccRecords.get());
}
diff --git a/src/java/com/android/internal/telephony/gsm/GsmConnection.java b/src/java/com/android/internal/telephony/gsm/GsmConnection.java
index 83e1b0e..875b680 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmConnection.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -29,6 +29,8 @@ import android.telephony.ServiceState;
import android.text.TextUtils;
import com.android.internal.telephony.*;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
+import com.android.internal.telephony.uicc.UiccController;
/**
* {@hide}
@@ -371,13 +373,16 @@ public class GsmConnection extends Connection {
default:
GSMPhone phone = owner.phone;
int serviceState = phone.getServiceState().getState();
+ AppState uiccAppState = UiccController
+ .getInstance()
+ .getUiccCardApplication(UiccController.APP_FAM_3GPP)
+ .getState();
if (serviceState == ServiceState.STATE_POWER_OFF) {
return DisconnectCause.POWER_OFF;
} else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
|| serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
return DisconnectCause.OUT_OF_SERVICE;
- } else if (phone.getIccCard() != null &&
- phone.getIccCard().getState() != IccCardConstants.State.READY) {
+ } else if (uiccAppState != AppState.APPSTATE_READY) {
return DisconnectCause.ICC_ERROR;
} else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
if (phone.mSST.mRestrictedState.isCsRestricted()) {
diff --git a/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 9bacbae..6ca7c0c 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -67,6 +67,8 @@ import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
+import com.android.internal.telephony.UiccCard;
+import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.AsyncChannel;
import java.io.FileDescriptor;
@@ -2349,11 +2351,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return;
}
- IccCard newIccCard = mUiccController.getIccCard();
- IccRecords newIccRecords = null;
- if (newIccCard != null) {
- newIccRecords = newIccCard.getIccRecords();
- }
+ IccRecords newIccRecords = mUiccController.getIccRecords(UiccController.APP_FAM_3GPP);
IccRecords r = mIccRecords.get();
if (r != newIccRecords) {
@@ -2363,7 +2361,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
mIccRecords.set(null);
}
if (newIccRecords != null) {
- log("New card found");
+ log("New records found");
mIccRecords.set(newIccRecords);
newIccRecords.registerForRecordsLoaded(
this, DctConstants.EVENT_RECORDS_LOADED, null);
diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 1f7836e..fdc0606 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -18,6 +18,7 @@ package com.android.internal.telephony.gsm;
import android.content.Context;
import com.android.internal.telephony.*;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
import android.os.*;
import android.telephony.PhoneNumberUtils;
@@ -110,6 +111,8 @@ public final class GsmMmiCode extends Handler implements MmiCode {
GSMPhone phone;
Context context;
+ UiccCardApplication mUiccApplication;
+ IccRecords mIccRecords;
String action; // One of ACTION_*
String sc; // Service Code
@@ -173,7 +176,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
*/
static GsmMmiCode
- newFromDialString(String dialString, GSMPhone phone) {
+ newFromDialString(String dialString, GSMPhone phone, UiccCardApplication app) {
Matcher m;
GsmMmiCode ret = null;
@@ -181,7 +184,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
// Is this formatted like a standard supplementary service code?
if (m.matches()) {
- ret = new GsmMmiCode(phone);
+ ret = new GsmMmiCode(phone, app);
ret.poundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
ret.sc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
@@ -196,14 +199,14 @@ public final class GsmMmiCode extends Handler implements MmiCode {
// "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
// (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
- ret = new GsmMmiCode(phone);
+ ret = new GsmMmiCode(phone, app);
ret.poundString = dialString;
} else if (isTwoDigitShortCode(phone.getContext(), dialString)) {
//Is a country-specific exception to short codes as defined in TS 22.030, 6.5.3.2
ret = null;
} else if (isShortCode(dialString, phone)) {
// this may be a short code, as defined in TS 22.030, 6.5.3.2
- ret = new GsmMmiCode(phone);
+ ret = new GsmMmiCode(phone, app);
ret.dialingNumber = dialString;
}
@@ -212,10 +215,10 @@ public final class GsmMmiCode extends Handler implements MmiCode {
static GsmMmiCode
newNetworkInitiatedUssd (String ussdMessage,
- boolean isUssdRequest, GSMPhone phone) {
+ boolean isUssdRequest, GSMPhone phone, UiccCardApplication app) {
GsmMmiCode ret;
- ret = new GsmMmiCode(phone);
+ ret = new GsmMmiCode(phone, app);
ret.message = ussdMessage;
ret.isUssdRequest = isUssdRequest;
@@ -231,8 +234,10 @@ public final class GsmMmiCode extends Handler implements MmiCode {
return ret;
}
- static GsmMmiCode newFromUssdUserInput(String ussdMessge, GSMPhone phone) {
- GsmMmiCode ret = new GsmMmiCode(phone);
+ static GsmMmiCode newFromUssdUserInput(String ussdMessge,
+ GSMPhone phone,
+ UiccCardApplication app) {
+ GsmMmiCode ret = new GsmMmiCode(phone, app);
ret.message = ussdMessge;
ret.state = State.PENDING;
@@ -383,12 +388,16 @@ public final class GsmMmiCode extends Handler implements MmiCode {
//***** Constructor
- GsmMmiCode (GSMPhone phone) {
+ GsmMmiCode (GSMPhone phone, UiccCardApplication app) {
// The telephony unit-test cases may create GsmMmiCode's
// in secondary threads
super(phone.getHandler().getLooper());
this.phone = phone;
this.context = phone.getContext();
+ mUiccApplication = app;
+ if (app != null) {
+ mIccRecords = app.getIccRecords();
+ }
}
//***** MmiCode implementation
@@ -764,8 +773,9 @@ public final class GsmMmiCode extends Handler implements MmiCode {
} else if (pinLen < 4 || pinLen > 8 ) {
// invalid length
handlePasswordError(com.android.internal.R.string.invalidPin);
- } else if (sc.equals(SC_PIN) && phone.getIccCard().getState() ==
- IccCardConstants.State.PUK_REQUIRED ) {
+ } else if (sc.equals(SC_PIN) &&
+ mUiccApplication != null &&
+ mUiccApplication.getState() == AppState.APPSTATE_PUK ) {
// Sim is puk-locked
handlePasswordError(com.android.internal.R.string.needPuk);
} else {
@@ -885,9 +895,8 @@ public final class GsmMmiCode extends Handler implements MmiCode {
*/
if ((ar.exception == null) && (msg.arg1 == 1)) {
boolean cffEnabled = (msg.arg2 == 1);
- IccRecords r = phone.mIccRecords.get();
- if (r != null) {
- r.setVoiceCallForwardingFlag(1, cffEnabled);
+ if (mIccRecords != null) {
+ mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
}
}
@@ -1206,9 +1215,8 @@ public final class GsmMmiCode extends Handler implements MmiCode {
(info.serviceClass & serviceClassMask)
== CommandsInterface.SERVICE_CLASS_VOICE) {
boolean cffEnabled = (info.status == 1);
- IccRecords r = phone.mIccRecords.get();
- if (r != null) {
- r.setVoiceCallForwardingFlag(1, cffEnabled);
+ if (mIccRecords != null) {
+ mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
}
}
@@ -1234,9 +1242,8 @@ public final class GsmMmiCode extends Handler implements MmiCode {
sb.append(context.getText(com.android.internal.R.string.serviceDisabled));
// Set unconditional CFF in SIM to false
- IccRecords r = phone.mIccRecords.get();
- if (r != null) {
- r.setVoiceCallForwardingFlag(1, false);
+ if (mIccRecords != null) {
+ mIccRecords.setVoiceCallForwardingFlag(1, false);
}
} else {
diff --git a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 42443fe..a0be5d0 100755
--- a/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -30,6 +30,10 @@ import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.UiccCard;
+import com.android.internal.telephony.UiccCardApplication;
+import com.android.internal.telephony.IccCardApplicationStatus.AppState;
+import com.android.internal.telephony.uicc.UiccController;
import android.app.AlarmManager;
import android.app.Notification;
@@ -187,7 +191,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
};
public GsmServiceStateTracker(GSMPhone phone) {
- super(phone, phone.mCM);
+ super(phone.getContext(), phone.mCM);
this.phone = phone;
ss = new ServiceState();
@@ -239,7 +243,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
cm.unregisterForAvailable(this);
cm.unregisterForRadioStateChanged(this);
cm.unregisterForVoiceNetworkStateChanged(this);
- if (mIccCard != null) {mIccCard.unregisterForReady(this);}
+ if (mUiccApplcation != null) {mUiccApplcation.unregisterForReady(this);}
if (mIccRecords != null) {mIccRecords.unregisterForRecordsLoaded(this);}
cm.unSetOnSignalStrengthUpdate(this);
cm.unSetOnRestrictedStateChanged(this);
@@ -1087,7 +1091,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
//ignore the normal call and data restricted state before SIM READY
- if (mIccCard != null && mIccCard.getState() == IccCardConstants.State.READY) {
+ if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY) {
newRs.setCsNormalRestricted(
((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
@@ -1619,23 +1623,24 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
return;
}
- IccCard newIccCard = mUiccController.getIccCard();
+ UiccCardApplication newUiccApplication =
+ mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
- if (mIccCard != newIccCard) {
- if (mIccCard != null) {
+ if (mUiccApplcation != newUiccApplication) {
+ if (mUiccApplcation != null) {
log("Removing stale icc objects.");
- mIccCard.unregisterForReady(this);
+ mUiccApplcation.unregisterForReady(this);
if (mIccRecords != null) {
mIccRecords.unregisterForRecordsLoaded(this);
}
mIccRecords = null;
- mIccCard = null;
+ mUiccApplcation = null;
}
- if (newIccCard != null) {
+ if (newUiccApplication != null) {
log("New card found");
- mIccCard = newIccCard;
- mIccRecords = mIccCard.getIccRecords();
- mIccCard.registerForReady(this, EVENT_SIM_READY, null);
+ mUiccApplcation = newUiccApplication;
+ mIccRecords = mUiccApplcation.getIccRecords();
+ mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null);
if (mIccRecords != null) {
mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
}
diff --git a/src/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/src/java/com/android/internal/telephony/gsm/SIMFileHandler.java
index dcc9cfd..0387a70 100644
--- a/src/java/com/android/internal/telephony/gsm/SIMFileHandler.java
+++ b/src/java/com/android/internal/telephony/gsm/SIMFileHandler.java
@@ -20,11 +20,9 @@ import android.os.Message;
import android.util.Log;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.IccCardApplication;
import com.android.internal.telephony.IccConstants;
import com.android.internal.telephony.IccFileHandler;
-import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.UiccCardApplication;
/**
* {@hide}
@@ -36,21 +34,13 @@ public final class SIMFileHandler extends IccFileHandler implements IccConstants
//***** Constructor
- public SIMFileHandler(IccCard card, String aid, CommandsInterface ci) {
- super(card, aid, ci);
- }
-
- protected void finalize() {
- Log.d(LOG_TAG, "SIMFileHandler finalized");
+ public SIMFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
+ super(app, aid, ci);
}
//***** Overridden from IccFileHandler
@Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- }
-
protected String getEFPath(int efid) {
// TODO(): DF_GSM can be 7F20 or 7F21 to handle backward compatibility.
// Implement this after discussion with OEMs.
@@ -78,29 +68,20 @@ public final class SIMFileHandler extends IccFileHandler implements IccConstants
case EF_INFO_CPHS:
case EF_CSP_CPHS:
return MF_SIM + DF_GSM;
-
- case EF_PBR:
- // we only support global phonebook.
- return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
}
String path = getCommonIccEFPath(efid);
if (path == null) {
- // The EFids in USIM phone book entries are decided by the card manufacturer.
- // So if we don't match any of the cases above and if its a USIM return
- // the phone book path.
- if (mParentCard != null
- && mParentCard.isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
- return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
- }
Log.e(LOG_TAG, "Error: EF Path being returned in null");
}
return path;
}
+ @Override
protected void logd(String msg) {
Log.d(LOG_TAG, "[SIMFileHandler] " + msg);
}
+ @Override
protected void loge(String msg) {
Log.e(LOG_TAG, "[SIMFileHandler] " + msg);
}
diff --git a/src/java/com/android/internal/telephony/gsm/SIMRecords.java b/src/java/com/android/internal/telephony/gsm/SIMRecords.java
index be33d6e..ddaf4b9 100755
--- a/src/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/src/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -31,7 +31,6 @@ import com.android.internal.telephony.AdnRecordCache;
import com.android.internal.telephony.AdnRecordLoader;
import com.android.internal.telephony.BaseCommands;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccFileHandler;
import com.android.internal.telephony.IccRecords;
@@ -43,6 +42,7 @@ import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.SmsMessageBase;
import com.android.internal.telephony.IccRefreshResponse;
+import com.android.internal.telephony.UiccCardApplication;
import java.util.ArrayList;
@@ -66,7 +66,6 @@ public class SIMRecords extends IccRecords {
// ***** Cached SIM State; cleared on channel close
- private String imsi;
private boolean callForwardingEnabled;
@@ -125,9 +124,9 @@ public class SIMRecords extends IccRecords {
// ***** Event Constants
- private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
- protected static final int EVENT_GET_IMSI_DONE = 3;
- protected static final int EVENT_GET_ICCID_DONE = 4;
+ private static final int EVENT_APP_READY = 1;
+ private static final int EVENT_GET_IMSI_DONE = 3;
+ private static final int EVENT_GET_ICCID_DONE = 4;
private static final int EVENT_GET_MBI_DONE = 5;
private static final int EVENT_GET_MBDN_DONE = 6;
private static final int EVENT_GET_MWIS_DONE = 7;
@@ -176,8 +175,8 @@ public class SIMRecords extends IccRecords {
// ***** Constructor
- public SIMRecords(IccCard card, Context c, CommandsInterface ci) {
- super(card, c, ci);
+ public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
+ super(app, c, ci);
adnCache = new AdnRecordCache(mFh);
@@ -189,23 +188,22 @@ public class SIMRecords extends IccRecords {
// recordsToLoad is set to 0 because no requests are made yet
recordsToLoad = 0;
- mCi.registerForOffOrNotAvailable(
- this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null);
// Start off by setting empty state
- onRadioOffOrNotAvailable();
-
+ resetRecords();
+ mParentApp.registerForReady(this, EVENT_APP_READY, null);
}
@Override
public void dispose() {
if (DBG) log("Disposing SIMRecords " + this);
//Unregister for all events
- mCi.unregisterForOffOrNotAvailable( this);
mCi.unregisterForIccRefresh(this);
mCi.unSetOnSmsOnSim(this);
+ mParentApp.unregisterForReady(this);
+ resetRecords();
super.dispose();
}
@@ -213,8 +211,8 @@ public class SIMRecords extends IccRecords {
if(DBG) log("finalized");
}
- protected void onRadioOffOrNotAvailable() {
- imsi = null;
+ protected void resetRecords() {
+ mImsi = null;
msisdn = null;
voiceMailNum = null;
countVoiceMessages = 0;
@@ -248,7 +246,7 @@ public class SIMRecords extends IccRecords {
*/
@Override
public String getIMSI() {
- return imsi;
+ return mImsi;
}
public String getMsisdnNumber() {
@@ -499,7 +497,7 @@ public class SIMRecords extends IccRecords {
*/
@Override
public String getOperatorNumeric() {
- if (imsi == null) {
+ if (mImsi == null) {
log("getOperatorNumeric: IMSI == null");
return null;
}
@@ -510,7 +508,7 @@ public class SIMRecords extends IccRecords {
// Length = length of MCC + length of MNC
// length of mcc = 3 (TS 23.003 Section 2.2)
- return imsi.substring(0, 3 + mncLength);
+ return mImsi.substring(0, 3 + mncLength);
}
// ***** Overridden from Handler
@@ -529,9 +527,9 @@ public class SIMRecords extends IccRecords {
}
try { switch (msg.what) {
- case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
- onRadioOffOrNotAvailable();
- break;
+ case EVENT_APP_READY:
+ onReady();
+ break;
/* IO events */
case EVENT_GET_IMSI_DONE:
@@ -544,20 +542,20 @@ public class SIMRecords extends IccRecords {
break;
}
- imsi = (String) ar.result;
+ mImsi = (String) ar.result;
// 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)) {
- loge("invalid IMSI " + imsi);
- imsi = null;
+ if (mImsi != null && (mImsi.length() < 6 || mImsi.length() > 15)) {
+ loge("invalid IMSI " + mImsi);
+ mImsi = null;
}
log("IMSI: " + /* imsi.substring(0, 6) +*/ "xxxxxxx");
if (((mncLength == UNKNOWN) || (mncLength == 2)) &&
- ((imsi != null) && (imsi.length() >= 6))) {
- String mccmncCode = imsi.substring(0, 6);
+ ((mImsi != null) && (mImsi.length() >= 6))) {
+ String mccmncCode = mImsi.substring(0, 6);
for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
if (mccmnc.equals(mccmncCode)) {
mncLength = 3;
@@ -570,7 +568,7 @@ public class SIMRecords extends IccRecords {
// the SIM has told us all it knows, but it didn't know the mnc length.
// guess using the mcc
try {
- int mcc = Integer.parseInt(imsi.substring(0,3));
+ int mcc = Integer.parseInt(mImsi.substring(0,3));
mncLength = MccTable.smallestDigitsMccForMnc(mcc);
} catch (NumberFormatException e) {
mncLength = UNKNOWN;
@@ -580,10 +578,9 @@ public class SIMRecords extends IccRecords {
if (mncLength != UNKNOWN && mncLength != UNINITIALIZED) {
// finally have both the imsi and the mncLength and can parse the imsi properly
- MccTable.updateMccMncConfiguration(mContext, imsi.substring(0, 3 + mncLength));
+ MccTable.updateMccMncConfiguration(mContext, mImsi.substring(0, 3 + mncLength));
}
- mParentCard.broadcastIccStateChangedIntent(
- IccCardConstants.INTENT_VALUE_ICC_IMSI, null);
+ mImsiReadyRegistrants.notifyRegistrants();
break;
case EVENT_GET_MBI_DONE:
@@ -815,8 +812,8 @@ public class SIMRecords extends IccRecords {
}
} finally {
if (((mncLength == UNINITIALIZED) || (mncLength == UNKNOWN) ||
- (mncLength == 2)) && ((imsi != null) && (imsi.length() >= 6))) {
- String mccmncCode = imsi.substring(0, 6);
+ (mncLength == 2)) && ((mImsi != null) && (mImsi.length() >= 6))) {
+ String mccmncCode = mImsi.substring(0, 6);
for (String mccmnc : MCCMNC_CODES_HAVING_3DIGITS_MNC) {
if (mccmnc.equals(mccmncCode)) {
mncLength = 3;
@@ -826,9 +823,9 @@ public class SIMRecords extends IccRecords {
}
if (mncLength == UNKNOWN || mncLength == UNINITIALIZED) {
- if (imsi != null) {
+ if (mImsi != null) {
try {
- int mcc = Integer.parseInt(imsi.substring(0,3));
+ int mcc = Integer.parseInt(mImsi.substring(0,3));
mncLength = MccTable.smallestDigitsMccForMnc(mcc);
} catch (NumberFormatException e) {
@@ -842,11 +839,11 @@ public class SIMRecords extends IccRecords {
log("MNC length not present in EF_AD");
}
}
- if (imsi != null && mncLength != UNKNOWN) {
+ if (mImsi != null && mncLength != UNKNOWN) {
// finally have both imsi and the length of the mnc and can parse
// the imsi properly
MccTable.updateMccMncConfiguration(mContext,
- imsi.substring(0, 3 + mncLength));
+ mImsi.substring(0, 3 + mncLength));
}
}
break;
@@ -1141,7 +1138,7 @@ public class SIMRecords extends IccRecords {
}
if (refreshResponse.aid != null &&
- !refreshResponse.aid.equals(mParentCard.getAid())) {
+ !refreshResponse.aid.equals(mParentApp.getAid())) {
// This is for different app. Ignore.
return;
}
@@ -1264,9 +1261,9 @@ public class SIMRecords extends IccRecords {
operator + "'");
SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
- if (imsi != null) {
+ if (mImsi != null) {
SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
- MccTable.countryCodeForMcc(Integer.parseInt(imsi.substring(0,3))));
+ MccTable.countryCodeForMcc(Integer.parseInt(mImsi.substring(0,3))));
}
else {
loge("onAllRecordsLoaded: imsi is NULL!");
@@ -1277,8 +1274,6 @@ public class SIMRecords extends IccRecords {
recordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
- mParentCard.broadcastIccStateChangedIntent(
- IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
}
//***** Private methods
@@ -1308,7 +1303,7 @@ public class SIMRecords extends IccRecords {
if (DBG) log("fetchSimRecords " + recordsToLoad);
- mCi.getIMSIForApp(mParentCard.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
+ mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
recordsToLoad++;
mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
diff --git a/src/java/com/android/internal/telephony/ims/IsimFileHandler.java b/src/java/com/android/internal/telephony/ims/IsimFileHandler.java
new file mode 100644
index 0000000..2e00c19
--- /dev/null
+++ b/src/java/com/android/internal/telephony/ims/IsimFileHandler.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2006, 2012 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.ims;
+
+import android.util.Log;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.UiccCardApplication;
+
+/**
+ * {@hide}
+ * This class should be used to access files in ISIM ADF
+ */
+public final class IsimFileHandler extends IccFileHandler implements IccConstants {
+ static final String LOG_TAG = "RIL_IsimFH";
+
+ public IsimFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) {
+ super(app, aid, ci);
+ }
+
+ @Override
+ protected String getEFPath(int efid) {
+ switch(efid) {
+ case EF_IMPI:
+ case EF_IMPU:
+ case EF_DOMAIN:
+ return MF_SIM + DF_ADF;
+ }
+ String path = getCommonIccEFPath(efid);
+ return path;
+ }
+
+ @Override
+ protected void logd(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+
+ @Override
+ protected void loge(String msg) {
+ Log.e(LOG_TAG, msg);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/ims/IsimUiccRecords.java b/src/java/com/android/internal/telephony/ims/IsimUiccRecords.java
index ee1a42d..2a658bf 100644
--- a/src/java/com/android/internal/telephony/ims/IsimUiccRecords.java
+++ b/src/java/com/android/internal/telephony/ims/IsimUiccRecords.java
@@ -16,13 +16,21 @@
package com.android.internal.telephony.ims;
+import android.content.Context;
import android.os.AsyncResult;
import android.os.Handler;
+import android.os.Message;
import android.util.Log;
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.IccFileHandler;
import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.UiccCardApplication;
import com.android.internal.telephony.gsm.SimTlv;
+import com.android.internal.telephony.gsm.SpnOverride;
+//import com.android.internal.telephony.gsm.VoiceMailConstants;
import java.nio.charset.Charset;
import java.util.ArrayList;
@@ -34,12 +42,14 @@ import static com.android.internal.telephony.IccConstants.EF_IMPU;
/**
* {@hide}
*/
-public final class IsimUiccRecords implements IsimRecords {
+public final class IsimUiccRecords extends IccRecords implements IsimRecords {
protected static final String LOG_TAG = "GSM";
private static final boolean DBG = true;
private static final boolean DUMP_RECORDS = false; // Note: PII is logged when this is true
+ private static final int EVENT_APP_READY = 1;
+
// ISIM EF records (see 3GPP TS 31.103)
private String mIsimImpi; // IMS private user identity
private String mIsimDomain; // IMS home network domain name
@@ -47,6 +57,75 @@ public final class IsimUiccRecords implements IsimRecords {
private static final int TAG_ISIM_VALUE = 0x80; // From 3GPP TS 31.103
+ public IsimUiccRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
+ super(app, c, ci);
+
+ recordsRequested = false; // No load request is made till SIM ready
+
+ // recordsToLoad is set to 0 because no requests are made yet
+ recordsToLoad = 0;
+
+ mParentApp.registerForReady(this, EVENT_APP_READY, null);
+ }
+
+ @Override
+ public void dispose() {
+ log("Disposing " + this);
+ //Unregister for all events
+ mParentApp.unregisterForReady(this);
+ resetRecords();
+ super.dispose();
+ }
+
+ // ***** Overridden from Handler
+ public void handleMessage(Message msg) {
+ if (mDestroyed.get()) {
+ Log.e(LOG_TAG, "Received message " + msg +
+ "[" + msg.what + "] while being destroyed. Ignoring.");
+ return;
+ }
+
+ try {
+ switch (msg.what) {
+ case EVENT_APP_READY:
+ onReady();
+ break;
+
+ default:
+ super.handleMessage(msg); // IccRecords handles generic record load responses
+
+ }
+ } catch (RuntimeException exc) {
+ // I don't want these exceptions to be fatal
+ Log.w(LOG_TAG, "Exception parsing SIM record", exc);
+ }
+ }
+
+ protected void fetchIsimRecords() {
+ recordsRequested = true;
+
+ mFh.loadEFTransparent(EF_IMPI, obtainMessage(
+ IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimImpiLoaded()));
+ recordsToLoad++;
+
+ mFh.loadEFLinearFixedAll(EF_IMPU, obtainMessage(
+ IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimImpuLoaded()));
+ recordsToLoad++;
+
+ mFh.loadEFTransparent(EF_DOMAIN, obtainMessage(
+ IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimDomainLoaded()));
+ recordsToLoad++;
+
+ log("fetchIsimRecords " + recordsToLoad);
+ }
+
+ protected void resetRecords() {
+ // recordsRequested is set to false indicating that the SIM
+ // read requests made so far are not valid. This is set to
+ // true only when fresh set of read requests are made.
+ recordsRequested = false;
+ }
+
private class EfIsimImpiLoaded implements IccRecords.IccRecordLoaded {
public String getEfName() {
return "EF_ISIM_IMPI";
@@ -87,22 +166,6 @@ public final class IsimUiccRecords implements IsimRecords {
}
/**
- * Request the ISIM records to load.
- * @param iccFh the IccFileHandler to load the records from
- * @param h the Handler to which the response message will be sent
- * @return the number of EF record requests that were added
- */
- public int fetchIsimRecords(IccFileHandler iccFh, Handler h) {
- iccFh.loadEFTransparent(EF_IMPI, h.obtainMessage(
- IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimImpiLoaded()));
- iccFh.loadEFLinearFixedAll(EF_IMPU, h.obtainMessage(
- IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimImpuLoaded()));
- iccFh.loadEFTransparent(EF_DOMAIN, h.obtainMessage(
- IccRecords.EVENT_GET_ICC_RECORD_DONE, new EfIsimDomainLoaded()));
- return 3; // number of EF record load requests
- }
-
- /**
* ISIM records for IMS are stored inside a Tag-Length-Value record as a UTF-8 string
* with tag value 0x80.
* @param record the byte array containing the IMS data string
@@ -120,12 +183,24 @@ public final class IsimUiccRecords implements IsimRecords {
return null;
}
- void log(String s) {
- if (DBG) Log.d(LOG_TAG, "[ISIM] " + s);
+ @Override
+ protected void onRecordLoaded() {
+ // One record loaded successfully or failed, In either case
+ // we need to update the recordsToLoad count
+ recordsToLoad -= 1;
+
+ if (recordsToLoad == 0 && recordsRequested == true) {
+ onAllRecordsLoaded();
+ } else if (recordsToLoad < 0) {
+ loge("recordsToLoad <0, programmer error suspected");
+ recordsToLoad = 0;
+ }
}
- void loge(String s) {
- if (DBG) Log.e(LOG_TAG, "[ISIM] " + s);
+ @Override
+ protected void onAllRecordsLoaded() {
+ recordsLoadedRegistrants.notifyRegistrants(
+ new AsyncResult(null, null, null));
}
/**
@@ -133,6 +208,7 @@ public final class IsimUiccRecords implements IsimRecords {
* Returns null if the IMPI hasn't been loaded or isn't present on the ISIM.
* @return the IMS private user identity string, or null if not available
*/
+ @Override
public String getIsimImpi() {
return mIsimImpi;
}
@@ -142,6 +218,7 @@ public final class IsimUiccRecords implements IsimRecords {
* Returns null if the IMS domain hasn't been loaded or isn't present on the ISIM.
* @return the IMS home network domain name, or null if not available
*/
+ @Override
public String getIsimDomain() {
return mIsimDomain;
}
@@ -151,7 +228,45 @@ public final class IsimUiccRecords implements IsimRecords {
* Returns null if the IMPU hasn't been loaded or isn't present on the ISIM.
* @return an array of IMS public user identity strings, or null if not available
*/
+ @Override
public String[] getIsimImpu() {
return (mIsimImpu != null) ? mIsimImpu.clone() : null;
}
+
+ @Override
+ public int getDisplayRule(String plmn) {
+ // Not applicable to Isim
+ return 0;
+ }
+
+ @Override
+ public void onReady() {
+ fetchIsimRecords();
+ }
+
+ @Override
+ public void onRefresh(boolean fileChanged, int[] fileList) {
+ // We do not handle it in Isim
+ }
+
+ @Override
+ public void setVoiceMailNumber(String alphaTag, String voiceNumber,
+ Message onComplete) {
+ // Not applicable to Isim
+ }
+
+ @Override
+ public void setVoiceMessageWaiting(int line, int countWaiting) {
+ // Not applicable to Isim
+ }
+
+ @Override
+ protected void log(String s) {
+ if (DBG) Log.d(LOG_TAG, "[ISIM] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ if (DBG) Log.e(LOG_TAG, "[ISIM] " + s);
+ }
}
diff --git a/src/java/com/android/internal/telephony/uicc/README b/src/java/com/android/internal/telephony/uicc/README
new file mode 100644
index 0000000..4d04390
--- /dev/null
+++ b/src/java/com/android/internal/telephony/uicc/README
@@ -0,0 +1 @@
+You can see documentation in UiccController.java
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 53a222e..43404be 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-2012 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.
@@ -16,13 +16,7 @@
package com.android.internal.telephony.uicc;
-import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.IccCardStatus;
-import com.android.internal.telephony.IccCardStatus.CardState;
-import com.android.internal.telephony.PhoneBase;
-import com.android.internal.telephony.sip.SipPhone;
-
+import android.content.Context;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
@@ -30,76 +24,179 @@ import android.os.Registrant;
import android.os.RegistrantList;
import android.util.Log;
-/* This class is responsible for keeping all knowledge about
- * ICCs in the system. It is also used as API to get appropriate
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccCardStatus;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.UiccCard;
+import com.android.internal.telephony.UiccCardApplication;
+
+/**
+ * This class is responsible for keeping all knowledge about
+ * Universal Integrated Circuit Card (UICC), also know as SIM's,
+ * in the system. It is also used as API to get appropriate
* applications to pass them to phone and service trackers.
+ *
+ * UiccController is created with the call to make() function.
+ * UiccController is a singleton and make() must only be called once
+ * and throws an exception if called multiple times.
+ *
+ * Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed"
+ * notifications. When such notification arrives UiccController will call
+ * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS
+ * request appropriate tree of uicc objects will be created.
+ *
+ * Following is class diagram for uicc classes:
+ *
+ * UiccController
+ * #
+ * |
+ * UiccCard
+ * # #
+ * | ------------------
+ * UiccCardApplication CatService
+ * # #
+ * | |
+ * IccRecords IccFileHandler
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * SIMRecords---- | | | | | | ---SIMFileHandler
+ * RuimRecords----- | | | | ----RuimFileHandler
+ * IsimUiccRecords--- | | -----UsimFileHandler
+ * | ------CsimFileHandler
+ * ----IsimFileHandler
+ *
+ * Legend: # stands for Composition
+ * ^ stands for Generalization
+ *
+ * See also {@link com.android.internal.telephony.IccCard}
+ * and {@link com.android.internal.telephony.IccCardProxy}
*/
public class UiccController extends Handler {
private static final boolean DBG = true;
private static final String LOG_TAG = "RIL_UiccController";
+ public static final int APP_FAM_3GPP = 1;
+ public static final int APP_FAM_3GPP2 = 2;
+ public static final int APP_FAM_IMS = 3;
+
private static final int EVENT_ICC_STATUS_CHANGED = 1;
private static final int EVENT_GET_ICC_STATUS_DONE = 2;
+ private static final Object mLock = new Object();
private static UiccController mInstance;
- private PhoneBase mCurrentPhone;
+ private Context mContext;
private CommandsInterface mCi;
- private IccCard mIccCard;
- private boolean mRegisteredWithCi = false;
+ private UiccCard mUiccCard;
private RegistrantList mIccChangedRegistrants = new RegistrantList();
- public static synchronized UiccController getInstance(PhoneBase phone) {
- if (mInstance == null) {
- mInstance = new UiccController(phone);
- } else if (phone != null) {
- mInstance.setNewPhone(phone);
+ public static UiccController make(Context c, CommandsInterface ci) {
+ synchronized (mLock) {
+ if (mInstance != null) {
+ throw new RuntimeException("UiccController.make() should only be called once");
+ }
+ mInstance = new UiccController(c, ci);
+ return mInstance;
}
- return mInstance;
}
- // This method is not synchronized as getInstance(PhoneBase) is.
public static UiccController getInstance() {
- return getInstance(null);
+ synchronized (mLock) {
+ if (mInstance == null) {
+ throw new RuntimeException(
+ "UiccController.getInstance can't be called before make()");
+ }
+ return mInstance;
+ }
+ }
+
+ public UiccCard getUiccCard() {
+ synchronized (mLock) {
+ return mUiccCard;
+ }
+ }
+
+ // Easy to use API
+ public UiccCardApplication getUiccCardApplication(int family) {
+ synchronized (mLock) {
+ if (mUiccCard != null) {
+ return mUiccCard.getApplication(family);
+ }
+ return null;
+ }
}
- public synchronized IccCard getIccCard() {
- return mIccCard;
+ // Easy to use API
+ public IccRecords getIccRecords(int family) {
+ synchronized (mLock) {
+ if (mUiccCard != null) {
+ UiccCardApplication app = mUiccCard.getApplication(family);
+ if (app != null) {
+ return app.getIccRecords();
+ }
+ }
+ return null;
+ }
+ }
+
+ // Easy to use API
+ public IccFileHandler getIccFileHandler(int family) {
+ synchronized (mLock) {
+ if (mUiccCard != null) {
+ UiccCardApplication app = mUiccCard.getApplication(family);
+ if (app != null) {
+ return app.getIccFileHandler();
+ }
+ }
+ return null;
+ }
}
//Notifies when card status changes
public void registerForIccChanged(Handler h, int what, Object obj) {
- Registrant r = new Registrant (h, what, obj);
- mIccChangedRegistrants.add(r);
- //Notify registrant right after registering, so that it will get the latest ICC status,
- //otherwise which may not happen until there is an actual change in ICC status.
- r.notifyRegistrant();
+ synchronized (mLock) {
+ Registrant r = new Registrant (h, what, obj);
+ mIccChangedRegistrants.add(r);
+ //Notify registrant right after registering, so that it will get the latest ICC status,
+ //otherwise which may not happen until there is an actual change in ICC status.
+ r.notifyRegistrant();
+ }
}
+
public void unregisterForIccChanged(Handler h) {
- mIccChangedRegistrants.remove(h);
+ synchronized (mLock) {
+ mIccChangedRegistrants.remove(h);
+ }
}
@Override
public void handleMessage (Message msg) {
- switch (msg.what) {
- case EVENT_ICC_STATUS_CHANGED:
- if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
- mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
- break;
- case EVENT_GET_ICC_STATUS_DONE:
- if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
- AsyncResult ar = (AsyncResult)msg.obj;
- onGetIccCardStatusDone(ar);
- break;
- default:
- Log.e(LOG_TAG, " Unknown Event " + msg.what);
+ synchronized (mLock) {
+ switch (msg.what) {
+ case EVENT_ICC_STATUS_CHANGED:
+ if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
+ mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
+ break;
+ case EVENT_GET_ICC_STATUS_DONE:
+ if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
+ AsyncResult ar = (AsyncResult)msg.obj;
+ onGetIccCardStatusDone(ar);
+ break;
+ default:
+ Log.e(LOG_TAG, " Unknown Event " + msg.what);
+ }
}
}
- private UiccController(PhoneBase phone) {
+ private UiccController(Context c, CommandsInterface ci) {
if (DBG) log("Creating UiccController");
- setNewPhone(phone);
+ mContext = c;
+ mCi = ci;
+ mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
+ // TODO remove this once modem correctly notifies the unsols
+ //mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);
}
private synchronized void onGetIccCardStatusDone(AsyncResult ar) {
@@ -112,55 +209,18 @@ public class UiccController extends Handler {
IccCardStatus status = (IccCardStatus)ar.result;
- //Update already existing card
- if (mIccCard != null) {
- mIccCard.update(mCurrentPhone, status);
- }
-
- //Create new card
- if (mIccCard == null) {
- mIccCard = new IccCard(mCurrentPhone, status, mCurrentPhone.getPhoneName(), true);
+ if (mUiccCard == null) {
+ //Create new card
+ mUiccCard = new UiccCard(mContext, mCi, status);
+ } else {
+ //Update already existing card
+ mUiccCard.update(mContext, mCi , status);
}
if (DBG) log("Notifying IccChangedRegistrants");
mIccChangedRegistrants.notifyRegistrants();
}
- private void setNewPhone(PhoneBase phone) {
- if (phone == null) {
- throw new RuntimeException("Phone can't be null in UiccController");
- //return;
- }
-
- if (DBG) log("setNewPhone");
- // TODO: remove this
- if (phone instanceof SipPhone) {
- if (DBG) log("Got SipPhone. Ignore.");
- return;
- }
-
- if (mCurrentPhone != phone) {
- if (mIccCard != null) {
- // Refresh card if phone changed
- // TODO: Remove once card is simplified
- if (DBG) log("Disposing card since phone object changed");
- mIccCard.dispose();
- mIccCard = null;
- }
- sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED));
- mCurrentPhone = phone;
-
- if (!mRegisteredWithCi) {
- // This needs to be done only once after we have valid phone object
- mCi = mCurrentPhone.mCM;
- mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
- // TODO remove this once modem correctly notifies the unsols
- mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);
- mRegisteredWithCi = true;
- }
- }
- }
-
private void log(String string) {
Log.d(LOG_TAG, string);
}