summaryrefslogtreecommitdiffstats
path: root/telephony/java
diff options
context:
space:
mode:
Diffstat (limited to 'telephony/java')
-rw-r--r--telephony/java/android/telephony/ServiceState.java15
-rw-r--r--telephony/java/android/telephony/SignalStrength.java34
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java23
-rw-r--r--telephony/java/com/android/internal/telephony/ApnContext.java213
-rw-r--r--telephony/java/com/android/internal/telephony/ApnSetting.java30
-rw-r--r--telephony/java/com/android/internal/telephony/BaseCommands.java162
-rw-r--r--telephony/java/com/android/internal/telephony/CallTracker.java4
-rw-r--r--telephony/java/com/android/internal/telephony/CommandsInterface.java99
-rw-r--r--telephony/java/com/android/internal/telephony/DataCallState.java160
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnection.java819
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionAc.java377
-rw-r--r--telephony/java/com/android/internal/telephony/DataConnectionTracker.java484
-rw-r--r--telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java4
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl10
-rw-r--r--telephony/java/com/android/internal/telephony/IccCard.java217
-rw-r--r--telephony/java/com/android/internal/telephony/IccCardApplication.java4
-rw-r--r--telephony/java/com/android/internal/telephony/IccConstants.java10
-rw-r--r--telephony/java/com/android/internal/telephony/IccRecords.java65
-rw-r--r--telephony/java/com/android/internal/telephony/Phone.java47
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneBase.java90
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneFactory.java74
-rw-r--r--telephony/java/com/android/internal/telephony/PhoneProxy.java24
-rw-r--r--telephony/java/com/android/internal/telephony/RIL.java157
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java23
-rw-r--r--telephony/java/com/android/internal/telephony/RestrictedState.java (renamed from telephony/java/com/android/internal/telephony/gsm/RestrictedState.java)2
-rw-r--r--telephony/java/com/android/internal/telephony/RetryManager.java4
-rwxr-xr-xtelephony/java/com/android/internal/telephony/SMSDispatcher.java29
-rw-r--r--telephony/java/com/android/internal/telephony/ServiceStateTracker.java212
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java7
-rw-r--r--telephony/java/com/android/internal/telephony/cat/CatService.java109
-rw-r--r--telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java5
-rw-r--r--telephony/java/com/android/internal/telephony/cat/ResponseData.java107
-rw-r--r--telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java16
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java147
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CDMAPhone.java109
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java8
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaConnection.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java17
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java260
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java480
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java8
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java658
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/RuimCard.java7
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java2
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/RuimRecords.java16
-rwxr-xr-x[-rw-r--r--]telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java34
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GSMPhone.java103
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmConnection.java6
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java109
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java1736
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java8
-rwxr-xr-xtelephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java8
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java298
-rwxr-xr-xtelephony/java/com/android/internal/telephony/gsm/SIMRecords.java85
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SimCard.java28
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java2
-rw-r--r--telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java4
-rw-r--r--telephony/java/com/android/internal/telephony/test/SimulatedCommands.java5
58 files changed, 5470 insertions, 2306 deletions
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 290f2c1..ba05837 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -91,6 +91,12 @@ public class ServiceState implements Parcelable {
public static final int RADIO_TECHNOLOGY_HSPA = 11;
/** @hide */
public static final int RADIO_TECHNOLOGY_EVDO_B = 12;
+ /** @hide */
+ public static final int RADIO_TECHNOLOGY_EHRPD = 13;
+ /** @hide */
+ public static final int RADIO_TECHNOLOGY_LTE = 14;
+ /** @hide */
+ public static final int RADIO_TECHNOLOGY_HSPAP = 15;
/**
* Available registration states for GSM, UMTS and CDMA.
@@ -424,6 +430,15 @@ public class ServiceState implements Parcelable {
case 12:
radioTechnology = "EvDo rev. B";
break;
+ case 13:
+ radioTechnology = "eHRPD";
+ break;
+ case 14:
+ radioTechnology = "LTE";
+ break;
+ case 15:
+ radioTechnology = "HSPAP";
+ break;
default:
Log.w(LOG_TAG, "mRadioTechnology variable out of range.");
break;
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 1767dd9..a88825b 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -556,10 +556,7 @@ public class SignalStrength implements Parcelable {
* @hide
*/
public int getLteDbm() {
- log("TODO: teach getLteDbm to compute dBm properly");
- int level = -1;
- if (DBG) log("getLteDbm=" + level);
- return level;
+ return mLteRsrp;
}
/**
@@ -568,22 +565,33 @@ public class SignalStrength implements Parcelable {
* @hide
*/
public int getLteLevel() {
- log("TODO: teach getLteLevel to compute Level properly");
- int level = SIGNAL_STRENGTH_MODERATE;
- if (DBG) log("getLteLevel=" + level);
- return level;
+ int levelLteRsrp = 0;
+
+ if (mLteRsrp == -1) levelLteRsrp = 0;
+ else if (mLteRsrp >= -85) levelLteRsrp = SIGNAL_STRENGTH_GREAT;
+ else if (mLteRsrp >= -95) levelLteRsrp = SIGNAL_STRENGTH_GOOD;
+ else if (mLteRsrp >= -105) levelLteRsrp = SIGNAL_STRENGTH_MODERATE;
+ else if (mLteRsrp >= -115) levelLteRsrp = SIGNAL_STRENGTH_POOR;
+ else levelLteRsrp = 0;
+
+ if (DBG) log("Lte level: "+levelLteRsrp);
+ return levelLteRsrp;
}
/**
- * Get the LTE signal level as an asu value between 0..31, 99 is unknown
+ * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+ * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
*
* @hide
*/
public int getLteAsuLevel() {
- log("TODO: teach getLteAsuLevel to compute asu Level properly");
- int level = 4;
- if (DBG) log("getLteAsuLevel=" + level);
- return level;
+ int lteAsuLevel = 99;
+ int lteDbm = getLteDbm();
+ if (lteDbm <= -140) lteAsuLevel = 0;
+ else if (lteDbm >= -43) lteAsuLevel = 97;
+ else lteAsuLevel = lteDbm + 140;
+ if (DBG) log("Lte Asu level: "+lteAsuLevel);
+ return lteAsuLevel;
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 23b67e3..8732e21 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -30,7 +30,6 @@ import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
-import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyProperties;
import java.util.List;
@@ -630,6 +629,28 @@ public class TelephonyManager {
}
}
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link Phone#LTE_ON_CDMA_TRUE}
+ *
+ * @hide
+ */
+ public int getLteOnCdmaMode() {
+ try {
+ return getITelephony().getLteOnCdmaMode();
+ } catch (RemoteException ex) {
+ // Assume no ICC card if remote exception which shouldn't happen
+ return Phone.LTE_ON_CDMA_UNKNOWN;
+ } catch (NullPointerException ex) {
+ // This could happen before phone restarts due to crashing
+ return Phone.LTE_ON_CDMA_UNKNOWN;
+ }
+ }
+
//
//
// Subscriber Info
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
new file mode 100644
index 0000000..496c43c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2006 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.app.PendingIntent;
+
+import android.util.Log;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Maintain the Apn context
+ */
+public class ApnContext {
+
+ public final String LOG_TAG;
+
+ protected static final boolean DBG = true;
+
+ private final String mApnType;
+
+ private DataConnectionTracker.State mState;
+
+ private ArrayList<ApnSetting> mWaitingApns = null;
+
+ /** A zero indicates that all waiting APNs had a permanent error */
+ private AtomicInteger mWaitingApnsPermanentFailureCountDown;
+
+ private ApnSetting mApnSetting;
+
+ DataConnection mDataConnection;
+
+ DataConnectionAc mDataConnectionAc;
+
+ String mReason;
+
+ PendingIntent mReconnectIntent;
+
+ /**
+ * user/app requested connection on this APN
+ */
+ AtomicBoolean mDataEnabled;
+
+ /**
+ * carrier requirements met
+ */
+ AtomicBoolean mDependencyMet;
+
+ public ApnContext(String apnType, String logTag) {
+ mApnType = apnType;
+ mState = DataConnectionTracker.State.IDLE;
+ setReason(Phone.REASON_DATA_ENABLED);
+ mDataEnabled = new AtomicBoolean(false);
+ mDependencyMet = new AtomicBoolean(true);
+ mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0);
+ LOG_TAG = logTag;
+ }
+
+ public String getApnType() {
+ return mApnType;
+ }
+
+ public synchronized DataConnection getDataConnection() {
+ return mDataConnection;
+ }
+
+ public synchronized void setDataConnection(DataConnection dataConnection) {
+ mDataConnection = dataConnection;
+ }
+
+
+ public synchronized DataConnectionAc getDataConnectionAc() {
+ return mDataConnectionAc;
+ }
+
+ public synchronized void setDataConnectionAc(DataConnectionAc dcac) {
+ mDataConnectionAc = dcac;
+ }
+
+ public synchronized ApnSetting getApnSetting() {
+ return mApnSetting;
+ }
+
+ public synchronized void setApnSetting(ApnSetting apnSetting) {
+ mApnSetting = apnSetting;
+ }
+
+ public synchronized void setWaitingApns(ArrayList<ApnSetting> waitingApns) {
+ mWaitingApns = waitingApns;
+ mWaitingApnsPermanentFailureCountDown.set(mWaitingApns.size());
+ }
+
+ public int getWaitingApnsPermFailCount() {
+ return mWaitingApnsPermanentFailureCountDown.get();
+ }
+
+ public void decWaitingApnsPermFailCount() {
+ mWaitingApnsPermanentFailureCountDown.decrementAndGet();
+ }
+
+ public synchronized ApnSetting getNextWaitingApn() {
+ ArrayList<ApnSetting> list = mWaitingApns;
+ ApnSetting apn = null;
+
+ if (list != null) {
+ if (!list.isEmpty()) {
+ apn = list.get(0);
+ }
+ }
+ return apn;
+ }
+
+ public synchronized void removeNextWaitingApn() {
+ if ((mWaitingApns != null) && (!mWaitingApns.isEmpty())) {
+ mWaitingApns.remove(0);
+ }
+ }
+
+ public synchronized ArrayList<ApnSetting> getWaitingApns() {
+ return mWaitingApns;
+ }
+
+ public synchronized void setState(DataConnectionTracker.State s) {
+ if (DBG) {
+ log("setState: " + s + " for type " + mApnType + ", previous state:" + mState);
+ }
+
+ mState = s;
+
+ if (mState == DataConnectionTracker.State.FAILED) {
+ if (mWaitingApns != null) {
+ mWaitingApns.clear(); // when teardown the connection and set to IDLE
+ }
+ }
+ }
+
+ public synchronized DataConnectionTracker.State getState() {
+ return mState;
+ }
+
+ public synchronized void setReason(String reason) {
+ if (DBG) {
+ log("set reason as " + reason + ", for type " + mApnType + ",current state " + mState);
+ }
+ mReason = reason;
+ }
+
+ public synchronized String getReason() {
+ return mReason;
+ }
+
+ public synchronized void setReconnectIntent(PendingIntent intent) {
+ if (DBG)
+ log("set ReconnectIntent for type " + mApnType);
+ mReconnectIntent = intent;
+ }
+
+ public synchronized PendingIntent getReconnectIntent() {
+ return mReconnectIntent;
+ }
+
+ public boolean isReady() {
+ return mDataEnabled.get() && mDependencyMet.get();
+ }
+
+ public void setEnabled(boolean enabled) {
+ if (DBG) {
+ log("set enabled as " + enabled + ", for type " +
+ mApnType + ", current state is " + mDataEnabled.get());
+ }
+ mDataEnabled.set(enabled);
+ }
+
+ public boolean isEnabled() {
+ return mDataEnabled.get();
+ }
+
+ public void setDependencyMet(boolean met) {
+ if (DBG) {
+ log("set mDependencyMet as " + met + ", for type " + mApnType +
+ ", current state is " + mDependencyMet.get());
+ }
+ mDependencyMet.set(met);
+ }
+
+ public boolean getDependencyMet() {
+ return mDependencyMet.get();
+ }
+
+ @Override
+ public String toString() {
+ return "state=" + getState() + " apnType=" + mApnType;
+ }
+
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[ApnContext] " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/ApnSetting.java b/telephony/java/com/android/internal/telephony/ApnSetting.java
index 20dbaf3..b88bcf7 100644
--- a/telephony/java/com/android/internal/telephony/ApnSetting.java
+++ b/telephony/java/com/android/internal/telephony/ApnSetting.java
@@ -23,21 +23,21 @@ public class ApnSetting {
static final String V2_FORMAT_REGEX = "^\\[ApnSettingV2\\]\\s*";
- public String carrier;
- public String apn;
- public String proxy;
- public String port;
- public String mmsc;
- public String mmsProxy;
- public String mmsPort;
- public String user;
- public String password;
- public int authType;
- public String[] types;
- public int id;
- public String numeric;
- public String protocol;
- public String roamingProtocol;
+ public final String carrier;
+ public final String apn;
+ public final String proxy;
+ public final String port;
+ public final String mmsc;
+ public final String mmsProxy;
+ public final String mmsPort;
+ public final String user;
+ public final String password;
+ public final int authType;
+ public final String[] types;
+ public final int id;
+ public final String numeric;
+ public final String protocol;
+ public final String roamingProtocol;
public ApnSetting(int id, String numeric, String carrier, String apn,
String proxy, String port,
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index 9b19600..e1d8c85 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -22,9 +22,15 @@ import android.os.RegistrantList;
import android.os.Registrant;
import android.os.Handler;
import android.os.AsyncResult;
+import android.os.SystemProperties;
import android.util.Config;
import android.util.Log;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* {@hide}
*/
@@ -34,6 +40,9 @@ public abstract class BaseCommands implements CommandsInterface {
//***** Instance Variables
protected Context mContext;
protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
+ protected RadioState mSimState = RadioState.RADIO_UNAVAILABLE;
+ protected RadioState mRuimState = RadioState.RADIO_UNAVAILABLE;
+ protected RadioState mNvState = RadioState.RADIO_UNAVAILABLE;
protected Object mStateMonitor = new Object();
protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
@@ -68,6 +77,8 @@ public abstract class BaseCommands implements CommandsInterface {
protected RegistrantList mCdmaSubscriptionChangedRegistrants = new RegistrantList();
protected RegistrantList mCdmaPrlChangedRegistrants = new RegistrantList();
protected RegistrantList mExitEmergencyCallbackModeRegistrants = new RegistrantList();
+ protected RegistrantList mRilConnectedRegistrants = new RegistrantList();
+ protected RegistrantList mIccRefreshRegistrants = new RegistrantList();
protected Registrant mSMSRegistrant;
protected Registrant mNITZTimeRegistrant;
@@ -82,7 +93,6 @@ public abstract class BaseCommands implements CommandsInterface {
protected Registrant mCatCallSetUpRegistrant;
protected Registrant mIccSmsFullRegistrant;
protected Registrant mEmergencyCallbackModeRegistrant;
- protected Registrant mIccRefreshRegistrant;
protected Registrant mRingRegistrant;
protected Registrant mRestrictedStateRegistrant;
protected Registrant mGsmBroadcastSmsRegistrant;
@@ -93,7 +103,8 @@ public abstract class BaseCommands implements CommandsInterface {
protected int mCdmaSubscription;
// Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
protected int mPhoneType;
-
+ // RIL Version
+ protected int mRilVersion = -1;
public BaseCommands(Context context) {
mContext = context; // May be null (if so we won't log statistics)
@@ -105,6 +116,18 @@ public abstract class BaseCommands implements CommandsInterface {
return mState;
}
+ public RadioState getSimState() {
+ return mSimState;
+ }
+
+ public RadioState getRuimState() {
+ return mRuimState;
+ }
+
+ public RadioState getNvState() {
+ return mNvState;
+ }
+
public void registerForRadioStateChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
@@ -200,7 +223,7 @@ public abstract class BaseCommands implements CommandsInterface {
synchronized (mStateMonitor) {
mSIMReadyRegistrants.add(r);
- if (mState.isSIMReady()) {
+ if (mSimState.isSIMReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -219,7 +242,7 @@ public abstract class BaseCommands implements CommandsInterface {
synchronized (mStateMonitor) {
mRUIMReadyRegistrants.add(r);
- if (mState.isRUIMReady()) {
+ if (mRuimState.isRUIMReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -238,7 +261,7 @@ public abstract class BaseCommands implements CommandsInterface {
synchronized (mStateMonitor) {
mNVReadyRegistrants.add(r);
- if (mState.isNVReady()) {
+ if (mNvState.isNVReady()) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -256,7 +279,7 @@ public abstract class BaseCommands implements CommandsInterface {
synchronized (mStateMonitor) {
mSIMLockedRegistrants.add(r);
- if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
+ if (mSimState == RadioState.SIM_LOCKED_OR_ABSENT) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -274,7 +297,7 @@ public abstract class BaseCommands implements CommandsInterface {
synchronized (mStateMonitor) {
mRUIMLockedRegistrants.add(r);
- if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
+ if (mRuimState == RadioState.RUIM_LOCKED_OR_ABSENT) {
r.notifyRegistrant(new AsyncResult(null, null, null));
}
}
@@ -438,16 +461,23 @@ public abstract class BaseCommands implements CommandsInterface {
mIccSmsFullRegistrant.clear();
}
+ public void registerForIccRefresh(Handler h, int what, Object obj) {
+ Registrant r = new Registrant (h, what, obj);
+ mIccRefreshRegistrants.add(r);
+ }
public void setOnIccRefresh(Handler h, int what, Object obj) {
- mIccRefreshRegistrant = new Registrant (h, what, obj);
+ registerForIccRefresh(h, what, obj);
}
public void setEmergencyCallbackMode(Handler h, int what, Object obj) {
mEmergencyCallbackModeRegistrant = new Registrant (h, what, obj);
}
- public void unSetOnIccRefresh(Handler h) {
- mIccRefreshRegistrant.clear();
+ public void unregisterForIccRefresh(Handler h) {
+ mIccRefreshRegistrants.remove(h);
+ }
+ public void unsetOnIccRefresh(Handler h) {
+ unregisterForIccRefresh(h);
}
public void setOnCallRing(Handler h, int what, Object obj) {
@@ -624,6 +654,25 @@ public abstract class BaseCommands implements CommandsInterface {
mExitEmergencyCallbackModeRegistrants.remove(h);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void registerForRilConnected(Handler h, int what, Object obj) {
+ Log.d(LOG_TAG, "registerForRilConnected h=" + h + " w=" + what);
+ Registrant r = new Registrant (h, what, obj);
+ mRilConnectedRegistrants.add(r);
+ if (mRilVersion != -1) {
+ Log.d(LOG_TAG, "Notifying: ril connected mRilVersion=" + mRilVersion);
+ r.notifyRegistrant(new AsyncResult(null, new Integer(mRilVersion), null));
+ }
+ }
+
+ @Override
+ public void unregisterForRilConnected(Handler h) {
+ mRilConnectedRegistrants.remove(h);
+ }
+
//***** Protected Methods
/**
* Store new RadioState and send notification based on the changes
@@ -653,6 +702,22 @@ public abstract class BaseCommands implements CommandsInterface {
return;
}
+ // FIXME: Use Constants or Enums
+ if(mState.getType() == 0) {
+ mSimState = mState;
+ mRuimState = mState;
+ mNvState = mState;
+ }
+ else if (mState.getType() == 1) {
+ mSimState = mState;
+ }
+ else if (mState.getType() == 2) {
+ mRuimState = mState;
+ }
+ else if (mState.getType() == 3) {
+ mNvState = mState;
+ }
+
mRadioStateChangedRegistrants.notifyRegistrants();
if (mState.isAvailable() && !oldState.isAvailable()) {
@@ -733,4 +798,81 @@ public abstract class BaseCommands implements CommandsInterface {
protected void onRadioAvailable() {
}
+
+ /**
+ * The contents of the /proc/cmdline file
+ */
+ private static String getProcCmdLine()
+ {
+ String cmdline = "";
+ FileInputStream is = null;
+ try {
+ is = new FileInputStream("/proc/cmdline");
+ byte [] buffer = new byte[2048];
+ int count = is.read(buffer);
+ if (count > 0) {
+ cmdline = new String(buffer, 0, count);
+ }
+ } catch (IOException e) {
+ Log.d(LOG_TAG, "No /proc/cmdline exception=" + e);
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ Log.d(LOG_TAG, "/proc/cmdline=" + cmdline);
+ return cmdline;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getLteOnCdmaMode() {
+ return getLteOnCdmaModeStatic();
+ }
+
+ /** Kernel command line */
+ private static final String sKernelCmdLine = getProcCmdLine();
+
+ /** Pattern for selecting the product type from the kernel command line */
+ private static final Pattern sProductTypePattern =
+ Pattern.compile("\\sproduct_type\\s*=\\s*(\\w+)");
+
+ /** The ProductType used for LTE on CDMA devices */
+ private static final String sLteOnCdmaProductType =
+ SystemProperties.get(TelephonyProperties.PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE, "");
+
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link Phone#LTE_ON_CDMA_TRUE}
+ */
+ public static int getLteOnCdmaModeStatic() {
+ int retVal;
+ String productType;
+
+ Matcher matcher = sProductTypePattern.matcher(sKernelCmdLine);
+ if (matcher.find()) {
+ productType = matcher.group(1);
+ if (sLteOnCdmaProductType.equals(productType)) {
+ retVal = Phone.LTE_ON_CDMA_TRUE;
+ } else {
+ retVal = Phone.LTE_ON_CDMA_FALSE;
+ }
+ } else {
+ retVal = Phone.LTE_ON_CDMA_FALSE;
+ productType = "";
+ }
+
+ Log.d(LOG_TAG, "getLteOnCdmaMode=" + retVal + " product_type='" + productType +
+ "' lteOnCdmaProductType='" + sLteOnCdmaProductType + "'");
+ return retVal;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/CallTracker.java b/telephony/java/com/android/internal/telephony/CallTracker.java
index 9619a66..31f9e18 100644
--- a/telephony/java/com/android/internal/telephony/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/CallTracker.java
@@ -119,6 +119,10 @@ public abstract class CallTracker extends Handler {
//***** Overridden from Handler
public abstract void handleMessage (Message msg);
+ public abstract void registerForVoiceCallStarted(Handler h, int what, Object obj);
+ public abstract void unregisterForVoiceCallStarted(Handler h);
+ public abstract void registerForVoiceCallEnded(Handler h, int what, Object obj);
+ public abstract void unregisterForVoiceCallEnded(Handler h);
protected abstract void log(String msg);
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index ad21a18..b68cbe9 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -20,6 +20,7 @@ import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import android.os.Message;
import android.os.Handler;
+import android.os.SystemProperties;
/**
@@ -27,18 +28,18 @@ import android.os.Handler;
*/
public interface CommandsInterface {
enum RadioState {
- RADIO_OFF, /* Radio explicitly powered off (e.g. CFUN=0) */
- RADIO_UNAVAILABLE, /* Radio unavailable (e.g. resetting or not booted) */
- SIM_NOT_READY, /* Radio is on, but the SIM interface is not ready */
- SIM_LOCKED_OR_ABSENT, /* SIM PIN locked, PUK required, network
- personalization, or SIM absent */
- SIM_READY, /* Radio is on and SIM interface is available */
- RUIM_NOT_READY, /* Radio is on, but the RUIM interface is not ready */
- RUIM_READY, /* Radio is on and the RUIM interface is available */
- RUIM_LOCKED_OR_ABSENT, /* RUIM PIN locked, PUK required, network
- personalization locked, or RUIM absent */
- NV_NOT_READY, /* Radio is on, but the NV interface is not available */
- NV_READY; /* Radio is on and the NV interface is available */
+ RADIO_OFF(0), /* Radio explictly powered off (eg CFUN=0) */
+ RADIO_UNAVAILABLE(0), /* Radio unavailable (eg, resetting or not booted) */
+ SIM_NOT_READY(1), /* Radio is on, but the SIM interface is not ready */
+ SIM_LOCKED_OR_ABSENT(1), /* SIM PIN locked, PUK required, network
+ personalization, or SIM absent */
+ SIM_READY(1), /* Radio is on and SIM interface is available */
+ RUIM_NOT_READY(2), /* Radio is on, but the RUIM interface is not ready */
+ RUIM_READY(2), /* Radio is on and the RUIM interface is available */
+ RUIM_LOCKED_OR_ABSENT(2), /* RUIM PIN locked, PUK required, network
+ personalization locked, or RUIM absent */
+ NV_NOT_READY(3), /* Radio is on, but the NV interface is not available */
+ NV_READY(3); /* Radio is on and the NV interface is available */
public boolean isOn() /* and available...*/ {
return this == SIM_NOT_READY
@@ -50,6 +51,14 @@ public interface CommandsInterface {
|| this == NV_NOT_READY
|| this == NV_READY;
}
+ private int stateType;
+ private RadioState (int type) {
+ stateType = type;
+ }
+
+ public int getType() {
+ return stateType;
+ }
public boolean isAvailable() {
return this != RADIO_UNAVAILABLE;
@@ -68,17 +77,25 @@ public interface CommandsInterface {
}
public boolean isGsm() {
- return this == SIM_NOT_READY
- || this == SIM_LOCKED_OR_ABSENT
- || this == SIM_READY;
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ return false;
+ } else {
+ return this == SIM_NOT_READY
+ || this == SIM_LOCKED_OR_ABSENT
+ || this == SIM_READY;
+ }
}
public boolean isCdma() {
- return this == RUIM_NOT_READY
- || this == RUIM_READY
- || this == RUIM_LOCKED_OR_ABSENT
- || this == NV_NOT_READY
- || this == NV_READY;
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ return true;
+ } else {
+ return this == RUIM_NOT_READY
+ || this == RUIM_READY
+ || this == RUIM_LOCKED_OR_ABSENT
+ || this == NV_NOT_READY
+ || this == NV_READY;
+ }
}
}
@@ -153,6 +170,9 @@ public interface CommandsInterface {
//***** Methods
RadioState getRadioState();
+ RadioState getSimState();
+ RadioState getRuimState();
+ RadioState getNvState();
/**
* Fires on any RadioState transition
@@ -214,6 +234,9 @@ public interface CommandsInterface {
void registerForSIMLockedOrAbsent(Handler h, int what, Object obj);
void unregisterForSIMLockedOrAbsent(Handler h);
+ void registerForIccStatusChanged(Handler h, int what, Object obj);
+ void unregisterForIccStatusChanged(Handler h);
+
void registerForCallStateChanged(Handler h, int what, Object obj);
void unregisterForCallStateChanged(Handler h);
void registerForVoiceNetworkStateChanged(Handler h, int what, Object obj);
@@ -330,14 +353,16 @@ public interface CommandsInterface {
/**
* Sets the handler for SIM Refresh notifications.
- * Unlike the register* methods, there's only one notification handler
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
+ void registerForIccRefresh(Handler h, int what, Object obj);
+ void unregisterForIccRefresh(Handler h);
+
void setOnIccRefresh(Handler h, int what, Object obj);
- void unSetOnIccRefresh(Handler h);
+ void unsetOnIccRefresh(Handler h);
/**
* Sets the handler for RING notifications.
@@ -582,6 +607,20 @@ public interface CommandsInterface {
void registerForExitEmergencyCallbackMode(Handler h, int what, Object obj);
void unregisterForExitEmergencyCallbackMode(Handler h);
+ /**
+ * Registers the handler for RIL_UNSOL_RIL_CONNECT events.
+ *
+ * When ril connects or disconnects a message is sent to the registrant
+ * which contains an AsyncResult, ar, in msg.obj. The ar.result is an
+ * Integer which is the version of the ril or -1 if the ril disconnected.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ void registerForRilConnected(Handler h, int what, Object obj);
+ void unregisterForRilConnected(Handler h);
+
/**
* Supply the ICC PIN to the ICC card
*
@@ -1419,6 +1458,12 @@ public interface CommandsInterface {
void setCdmaSubscriptionSource(int cdmaSubscriptionType, Message response);
/**
+ * Requests to get the CDMA subscription srouce
+ * @param response is callback message
+ */
+ void getCdmaSubscriptionSource(Message response);
+
+ /**
* Set the TTY mode
*
* @param ttyMode one of the following:
@@ -1528,4 +1573,14 @@ public interface CommandsInterface {
* Callback message containing {@link IccCardStatus} structure for the card.
*/
public void getIccCardStatus(Message result);
+
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link Phone#LTE_ON_CDMA_TRUE}
+ */
+ public int getLteOnCdmaMode();
}
diff --git a/telephony/java/com/android/internal/telephony/DataCallState.java b/telephony/java/com/android/internal/telephony/DataCallState.java
index fda1e47..1d67d45 100644
--- a/telephony/java/com/android/internal/telephony/DataCallState.java
+++ b/telephony/java/com/android/internal/telephony/DataCallState.java
@@ -17,11 +17,27 @@
package com.android.internal.telephony;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkUtils;
+import android.net.RouteInfo;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import com.android.internal.telephony.DataConnection.FailCause;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
/**
* This is RIL_Data_Call_Response_v5 from ril.h
* TODO: Rename to DataCallResponse.
*/
public class DataCallState {
+ private final boolean DBG = true;
+ private final String LOG_TAG = "GSM";
+
public int version = 0;
public int status = 0;
public int cid = 0;
@@ -32,6 +48,29 @@ public class DataCallState {
public String [] dnses = new String[0];
public String[] gateways = new String[0];
+ /**
+ * Class returned by onSetupConnectionCompleted.
+ */
+ protected enum SetupResult {
+ SUCCESS,
+ ERR_BadCommand,
+ ERR_UnacceptableParameter,
+ ERR_GetLastErrorFromRil,
+ ERR_Stale,
+ ERR_RilError;
+
+ public FailCause mFailCause;
+
+ SetupResult() {
+ mFailCause = FailCause.fromInt(0);
+ }
+
+ @Override
+ public String toString() {
+ return name() + " SetupResult.mFailCause=" + mFailCause;
+ }
+ }
+
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
@@ -63,4 +102,125 @@ public class DataCallState {
sb.append("]}");
return sb.toString();
}
+
+ public SetupResult setLinkProperties(LinkProperties linkProperties,
+ boolean okToUseSystemPropertyDns) {
+ SetupResult result;
+
+ // Start with clean network properties and if we have
+ // a failure we'll clear again at the bottom of this code.
+ if (linkProperties == null)
+ linkProperties = new LinkProperties();
+ else
+ linkProperties.clear();
+
+ if (status == FailCause.NONE.getErrorCode()) {
+ String propertyPrefix = "net." + ifname + ".";
+
+ try {
+ // set interface name
+ linkProperties.setInterfaceName(ifname);
+
+ // set link addresses
+ if (addresses != null && addresses.length > 0) {
+ for (String addr : addresses) {
+ LinkAddress la;
+ int addrPrefixLen;
+
+ String [] ap = addr.split("/");
+ if (ap.length == 2) {
+ addr = ap[0];
+ addrPrefixLen = Integer.parseInt(ap[1]);
+ } else {
+ addrPrefixLen = 0;
+ }
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(addr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric ip addr=" + addr);
+ }
+ if (addrPrefixLen == 0) {
+ // Assume point to point
+ addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
+ }
+ if (DBG) Log.d(LOG_TAG, "addr/pl=" + addr + "/" + addrPrefixLen);
+ la = new LinkAddress(ia, addrPrefixLen);
+ linkProperties.addLinkAddress(la);
+ }
+ } else {
+ throw new UnknownHostException("no address for ifname=" + ifname);
+ }
+
+ // set dns servers
+ if (dnses != null && dnses.length > 0) {
+ for (String addr : dnses) {
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(addr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric dns addr=" + addr);
+ }
+ linkProperties.addDns(ia);
+ }
+ } else if (okToUseSystemPropertyDns){
+ String dnsServers[] = new String[2];
+ dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
+ dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
+ for (String dnsAddr : dnsServers) {
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(dnsAddr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric dns addr="
+ + dnsAddr);
+ }
+ linkProperties.addDns(ia);
+ }
+ } else {
+ throw new UnknownHostException("Empty dns response and no system default dns");
+ }
+
+ // set gateways
+ if ((gateways == null) || (gateways.length == 0)) {
+ String sysGateways = SystemProperties.get(propertyPrefix + "gw");
+ if (sysGateways != null) {
+ gateways = sysGateways.split(" ");
+ } else {
+ gateways = new String[0];
+ }
+ }
+ for (String addr : gateways) {
+ InetAddress ia;
+ try {
+ ia = NetworkUtils.numericToInetAddress(addr);
+ } catch (IllegalArgumentException e) {
+ throw new UnknownHostException("Non-numeric gateway addr=" + addr);
+ }
+ linkProperties.addRoute(new RouteInfo(ia));
+ }
+
+ result = SetupResult.SUCCESS;
+ } catch (UnknownHostException e) {
+ Log.d(LOG_TAG, "onSetupCompleted: UnknownHostException " + e);
+ e.printStackTrace();
+ result = SetupResult.ERR_UnacceptableParameter;
+ }
+ } else {
+ if (version < 4) {
+ result = SetupResult.ERR_GetLastErrorFromRil;
+ } else {
+ result = SetupResult.ERR_RilError;
+ }
+ }
+
+ // An error occurred so clear properties
+ if (result != SetupResult.SUCCESS) {
+ if(DBG) Log.d(LOG_TAG,
+ "onSetupConnectionCompleted with an error, clearing LinkProperties");
+ linkProperties.clear();
+ }
+
+ return result;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index 89513fd..c21a96a 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -17,27 +17,32 @@
package com.android.internal.telephony;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkUtils;
+import android.net.ProxyProperties;
import android.os.AsyncResult;
+import android.os.Bundle;
import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.SystemProperties;
import android.text.TextUtils;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* {@hide}
*
- * DataConnection HierarchicalStateMachine.
+ * DataConnection StateMachine.
*
* This is an abstract base class for representing a single data connection.
* Instances of this class such as <code>CdmaDataConnection</code> and
@@ -55,34 +60,14 @@ import java.util.HashMap;
*
* The other public methods are provided for debugging.
*/
-public abstract class DataConnection extends HierarchicalStateMachine {
+public abstract class DataConnection extends StateMachine {
protected static final boolean DBG = true;
+ protected static final boolean VDBG = false;
protected static Object mCountLock = new Object();
protected static int mCount;
+ protected AsyncChannel mAc;
- /**
- * Class returned by onSetupConnectionCompleted.
- */
- protected enum SetupResult {
- SUCCESS,
- ERR_BadCommand,
- ERR_UnacceptableParameter,
- ERR_GetLastErrorFromRil,
- ERR_Stale,
- ERR_RilError;
-
- public FailCause mFailCause;
-
- SetupResult() {
- mFailCause = FailCause.fromInt(0);
- }
-
- @Override
- public String toString() {
- return name() + " SetupResult.mFailCause=" + mFailCause;
- }
- }
/**
* Used internally for saving connecting parameters.
@@ -99,26 +84,16 @@ public abstract class DataConnection extends HierarchicalStateMachine {
}
/**
- * An instance used for notification of blockingReset.
- * TODO: Remove when blockingReset is removed.
- */
- class ResetSynchronouslyLock {
- }
-
- /**
* Used internally for saving disconnecting parameters.
*/
protected static class DisconnectParams {
- public DisconnectParams(Message onCompletedMsg) {
+ public DisconnectParams(String reason, Message onCompletedMsg) {
+ this.reason = reason;
this.onCompletedMsg = onCompletedMsg;
}
- public DisconnectParams(ResetSynchronouslyLock lockObj) {
- this.lockObj = lockObj;
- }
-
public int tag;
+ public String reason;
public Message onCompletedMsg;
- public ResetSynchronouslyLock lockObj;
}
/**
@@ -167,7 +142,7 @@ public abstract class DataConnection extends HierarchicalStateMachine {
static {
sErrorCodeToFailCauseMap = new HashMap<Integer, FailCause>();
for (FailCause fc : values()) {
- sErrorCodeToFailCauseMap.put(fc.ordinal(), fc);
+ sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
}
}
@@ -208,21 +183,22 @@ public abstract class DataConnection extends HierarchicalStateMachine {
}
// ***** Event codes for driving the state machine
- protected static final int EVENT_RESET = 1;
- protected static final int EVENT_CONNECT = 2;
- protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 3;
- protected static final int EVENT_GET_LAST_FAIL_DONE = 4;
- protected static final int EVENT_DEACTIVATE_DONE = 5;
- protected static final int EVENT_DISCONNECT = 6;
+ protected static final int BASE = Protocol.BASE_DATA_CONNECTION;
+ protected static final int EVENT_CONNECT = BASE + 0;
+ protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
+ protected static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2;
+ protected static final int EVENT_DEACTIVATE_DONE = BASE + 3;
+ protected static final int EVENT_DISCONNECT = BASE + 4;
+ protected static final int EVENT_RIL_CONNECTED = BASE + 5;
//***** Tag IDs for EventLog
protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
//***** Member Variables
- protected int mId;
+ protected ApnSetting mApn;
protected int mTag;
protected PhoneBase phone;
- protected RetryManager mRetryMgr;
+ protected int mRilVersion = -1;
protected int cid;
protected LinkProperties mLinkProperties = new LinkProperties();
protected LinkCapabilities mCapabilities = new LinkCapabilities();
@@ -230,6 +206,7 @@ public abstract class DataConnection extends HierarchicalStateMachine {
protected long lastFailTime;
protected FailCause lastFailCause;
protected static final String NULL_IP = "0.0.0.0";
+ private int mRefCount;
Object userData;
//***** Abstract methods
@@ -244,10 +221,11 @@ public abstract class DataConnection extends HierarchicalStateMachine {
//***** Constructor
- protected DataConnection(PhoneBase phone, String name, RetryManager rm) {
+ protected DataConnection(PhoneBase phone, String name, int id, RetryManager rm) {
super(name);
if (DBG) log("DataConnection constructor E");
this.phone = phone;
+ mId = id;
mRetryMgr = rm;
this.cid = -1;
clearSettings();
@@ -274,10 +252,10 @@ public abstract class DataConnection extends HierarchicalStateMachine {
if ((o != null) && (o instanceof DisconnectParams)) {
DisconnectParams dp = (DisconnectParams)o;
Message m = dp.onCompletedMsg;
- if ((m != null) && (m.obj != null) && (m.obj instanceof String)) {
- String reason = (String)m.obj;
- if (TextUtils.equals(reason, Phone.REASON_RADIO_TURNED_OFF))
- discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;
+ if (TextUtils.equals(dp.reason, Phone.REASON_RADIO_TURNED_OFF)) {
+ discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;
+ } else if (TextUtils.equals(dp.reason, Phone.REASON_PDP_RESET)) {
+ discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET;
}
}
if (phone.mCM.getRadioState().isOn()) {
@@ -313,7 +291,7 @@ public abstract class DataConnection extends HierarchicalStateMachine {
lastFailTime = timeStamp;
AsyncResult.forMessage(connectionCompletedMsg, cause, new Exception());
}
- if (DBG) log("notifyConnection at " + timeStamp + " cause=" + cause);
+ if (DBG) log("notifyConnectionCompleted at " + timeStamp + " cause=" + cause);
connectionCompletedMsg.sendToTarget();
}
@@ -324,39 +302,140 @@ public abstract class DataConnection extends HierarchicalStateMachine {
* @param dp is the DisconnectParams.
*/
private void notifyDisconnectCompleted(DisconnectParams dp) {
- if (DBG) log("NotifyDisconnectCompleted");
+ if (VDBG) log("NotifyDisconnectCompleted");
if (dp.onCompletedMsg != null) {
Message msg = dp.onCompletedMsg;
- log(String.format("msg=%s msg.obj=%s", msg.toString(),
+ if (VDBG) {
+ log(String.format("msg=%s msg.obj=%s", msg.toString(),
((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>")));
+ }
AsyncResult.forMessage(msg);
msg.sendToTarget();
}
- if (dp.lockObj != null) {
- synchronized(dp.lockObj) {
- dp.lockObj.notify();
- }
+ clearSettings();
+ if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
+ }
+
+ protected int getRadioTechnology(int defaultRadioTechnology) {
+ int radioTechnology;
+ if (mRilVersion < 6) {
+ radioTechnology = defaultRadioTechnology;
+ } else {
+ radioTechnology = phone.getServiceState().getRadioTechnology() + 2;
}
+ return radioTechnology;
+ }
- clearSettings();
+ /*
+ * **************************************************************************
+ * Begin Members and methods owned by DataConnectionTracker but stored
+ * in a DataConnection because there is one per connection.
+ * **************************************************************************
+ */
+
+ /*
+ * The id is owned by DataConnectionTracker.
+ */
+ private int mId;
+
+ /**
+ * Get the DataConnection ID
+ */
+ public int getDataConnectionId() {
+ return mId;
}
- public RetryManager getRetryMgr() {
- return mRetryMgr;
+ /*
+ * The retry manager is currently owned by the DataConnectionTracker but is stored
+ * in the DataConnection because there is one per connection. These methods
+ * should only be used by the DataConnectionTracker although someday the retrying
+ * maybe managed by the DataConnection itself and these methods could disappear.
+ */
+ private RetryManager mRetryMgr;
+
+ /**
+ * @return retry manager retryCount
+ */
+ public int getRetryCount() {
+ return mRetryMgr.getRetryCount();
}
/**
+ * @return retry manager retryTimer
+ */
+ public int getRetryTimer() {
+ return mRetryMgr.getRetryTimer();
+ }
+
+ /**
+ * increaseRetryCount of retry manager
+ */
+ public void increaseRetryCount() {
+ mRetryMgr.increaseRetryCount();
+ }
+
+ /**
+ * @return retry manager isRetryNeeded
+ */
+ public boolean isRetryNeeded() {
+ return mRetryMgr.isRetryNeeded();
+ }
+
+ /**
+ * resetRetryCount of retry manager
+ */
+ public void resetRetryCount() {
+ mRetryMgr.resetRetryCount();
+ }
+
+ /**
+ * set retryForeverUsingLasttimeout of retry manager
+ */
+ public void retryForeverUsingLastTimeout() {
+ mRetryMgr.retryForeverUsingLastTimeout();
+ }
+
+ /**
+ * @return retry manager isRetryForever
+ */
+ public boolean isRetryForever() {
+ return mRetryMgr.isRetryForever();
+ }
+
+ /**
+ * @return whether the retry config is set successfully or not
+ */
+ public boolean configureRetry(int maxRetryCount, int retryTime, int randomizationTime) {
+ return mRetryMgr.configure(maxRetryCount, retryTime, randomizationTime);
+ }
+
+ /**
+ * @return whether the retry config is set successfully or not
+ */
+ public boolean configureRetry(String configStr) {
+ return mRetryMgr.configure(configStr);
+ }
+
+ /*
+ * **************************************************************************
+ * End members owned by DataConnectionTracker
+ * **************************************************************************
+ */
+
+ /**
* Clear all settings called when entering mInactiveState.
*/
protected void clearSettings() {
if (DBG) log("clearSettings");
- this.createTime = -1;
- this.lastFailTime = -1;
- this.lastFailCause = FailCause.NONE;
+ createTime = -1;
+ lastFailTime = -1;
+ lastFailCause = FailCause.NONE;
+ mRefCount = 0;
mLinkProperties = new LinkProperties();
+ mApn = null;
}
/**
@@ -365,10 +444,10 @@ public abstract class DataConnection extends HierarchicalStateMachine {
* @param ar is the result
* @return SetupResult.
*/
- private SetupResult onSetupConnectionCompleted(AsyncResult ar) {
+ private DataCallState.SetupResult onSetupConnectionCompleted(AsyncResult ar) {
DataCallState response = (DataCallState) ar.result;
ConnectionParams cp = (ConnectionParams) ar.userObj;
- SetupResult result;
+ DataCallState.SetupResult result;
if (ar.exception != null) {
if (DBG) {
@@ -379,168 +458,189 @@ public abstract class DataConnection extends HierarchicalStateMachine {
if (ar.exception instanceof CommandException
&& ((CommandException) (ar.exception)).getCommandError()
== CommandException.Error.RADIO_NOT_AVAILABLE) {
- result = SetupResult.ERR_BadCommand;
+ result = DataCallState.SetupResult.ERR_BadCommand;
result.mFailCause = FailCause.RADIO_NOT_AVAILABLE;
} else if ((response == null) || (response.version < 4)) {
- result = SetupResult.ERR_GetLastErrorFromRil;
+ result = DataCallState.SetupResult.ERR_GetLastErrorFromRil;
} else {
- result = SetupResult.ERR_RilError;
+ result = DataCallState.SetupResult.ERR_RilError;
result.mFailCause = FailCause.fromInt(response.status);
}
} else if (cp.tag != mTag) {
if (DBG) {
log("BUG: onSetupConnectionCompleted is stale cp.tag=" + cp.tag + ", mtag=" + mTag);
}
- result = SetupResult.ERR_Stale;
+ result = DataCallState.SetupResult.ERR_Stale;
+ } else if (response.status != 0) {
+ result = DataCallState.SetupResult.ERR_RilError;
+ result.mFailCause = FailCause.fromInt(response.status);
} else {
- log("onSetupConnectionCompleted received DataCallState: " + response);
-
- // Start with clean network properties and if we have
- // a failure we'll clear again at the bottom of this code.
- LinkProperties linkProperties = new LinkProperties();
- if (response.status == FailCause.NONE.getErrorCode()) {
- String propertyPrefix = "net." + response.ifname + ".";
-
- try {
- cid = response.cid;
- linkProperties.setInterfaceName(response.ifname);
- if (response.addresses != null && response.addresses.length > 0) {
- for (String addr : response.addresses) {
- LinkAddress la;
- int addrPrefixLen;
-
- String [] ap = addr.split("/");
- if (ap.length == 2) {
- addr = ap[0];
- addrPrefixLen = Integer.parseInt(ap[1]);
- } else {
- addrPrefixLen = 0;
- }
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(addr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writeBadIpAddress(addr);
- throw new UnknownHostException("Non-numeric ip addr=" + addr);
- }
- if (addrPrefixLen == 0) {
- // Assume point to point
- addrPrefixLen = (ia instanceof Inet4Address) ? 32 : 128;
- }
- if (DBG) log("addr/pl=" + addr + "/" + addrPrefixLen);
- la = new LinkAddress(ia, addrPrefixLen);
- linkProperties.addLinkAddress(la);
- }
- } else {
- EventLogTags.writeBadIpAddress("no address for ifname=" + response.ifname);
- throw new UnknownHostException("no address for ifname=" + response.ifname);
- }
- if (response.dnses != null && response.dnses.length > 0) {
- for (String addr : response.dnses) {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(addr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writePdpBadDnsAddress("dns=" + addr);
- throw new UnknownHostException("Non-numeric dns addr=" + addr);
- }
- linkProperties.addDns(ia);
- }
- result = SetupResult.SUCCESS;
- } else {
- String dnsServers[] = new String[2];
- dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
- dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
- if (isDnsOk(dnsServers)) {
- for (String dnsAddr : dnsServers) {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(dnsAddr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writePdpBadDnsAddress("dnsAddr=" + dnsAddr);
- throw new UnknownHostException("Non-numeric dns addr="
- + dnsAddr);
- }
- linkProperties.addDns(ia);
- }
- result = SetupResult.SUCCESS;
- } else {
- StringBuilder sb = new StringBuilder();
- for (String dnsAddr : dnsServers) {
- sb.append(dnsAddr);
- sb.append(" ");
- }
- EventLogTags.writePdpBadDnsAddress("Unacceptable dns addresses=" + sb);
- throw new UnknownHostException("Unacceptable dns addresses=" + sb);
- }
- }
- if ((response.gateways == null) || (response.gateways.length == 0)) {
- String gateways = SystemProperties.get(propertyPrefix + "gw");
- if (gateways != null) {
- response.gateways = gateways.split(" ");
- } else {
- response.gateways = new String[0];
- }
- }
- for (String addr : response.gateways) {
- InetAddress ia;
- try {
- ia = NetworkUtils.numericToInetAddress(addr);
- } catch (IllegalArgumentException e) {
- EventLogTags.writePdpBadDnsAddress("gateway=" + addr);
- throw new UnknownHostException("Non-numeric gateway addr=" + addr);
- }
- linkProperties.addGateway(ia);
- }
- result = SetupResult.SUCCESS;
- } catch (UnknownHostException e) {
- log("onSetupCompleted: UnknownHostException " + e);
- e.printStackTrace();
- result = SetupResult.ERR_UnacceptableParameter;
- }
- } else {
- if (response.version < 4) {
- result = SetupResult.ERR_GetLastErrorFromRil;
- } else {
- result = SetupResult.ERR_RilError;
- }
- }
+ if (DBG) log("onSetupConnectionCompleted received DataCallState: " + response);
+ cid = response.cid;
+ // set link properties based on data call response
+ result = setLinkProperties(response, mLinkProperties);
+ }
+
+ return result;
+ }
+
+ private DataCallState.SetupResult setLinkProperties(DataCallState response,
+ LinkProperties lp) {
+ // Check if system property dns usable
+ boolean okToUseSystemPropertyDns = false;
+ String propertyPrefix = "net." + response.ifname + ".";
+ String dnsServers[] = new String[2];
+ dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1");
+ dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2");
+ okToUseSystemPropertyDns = isDnsOk(dnsServers);
+
+ // set link properties based on data call response
+ return response.setLinkProperties(lp, okToUseSystemPropertyDns);
+ }
+
+ private DataConnectionAc.LinkPropertyChangeAction updateLinkProperty(
+ DataCallState newState) {
+ DataConnectionAc.LinkPropertyChangeAction changed =
+ DataConnectionAc.LinkPropertyChangeAction.NONE;
- // An error occurred so clear properties
- if (result != SetupResult.SUCCESS) {
- log("onSetupConnectionCompleted with an error, clearing LinkProperties");
- linkProperties.clear();
+ if (newState == null) return changed;
+
+ DataCallState.SetupResult result;
+ LinkProperties newLp = new LinkProperties();
+
+ // set link properties based on data call response
+ result = setLinkProperties(newState, newLp);
+ if (result != DataCallState.SetupResult.SUCCESS) {
+ if (DBG) log("UpdateLinkProperty failed : " + result);
+ return changed;
+ }
+ // copy HTTP proxy as it is not part DataCallState.
+ newLp.setHttpProxy(mLinkProperties.getHttpProxy());
+
+ if (DBG) log("old LP=" + mLinkProperties);
+ if (DBG) log("new LP=" + newLp);
+
+ // Check consistency of link address. Currently we expect
+ // only one "global" address is assigned per each IP type.
+ Collection<LinkAddress> oLinks = mLinkProperties.getLinkAddresses();
+ Collection<LinkAddress> nLinks = newLp.getLinkAddresses();
+ for (LinkAddress oldLink : oLinks) {
+ for (LinkAddress newLink : nLinks) {
+ if ((NetworkUtils.addressTypeMatches(oldLink.getAddress(),
+ newLink.getAddress())) &&
+ (oldLink.equals(newLink) == false)) {
+ return DataConnectionAc.LinkPropertyChangeAction.RESET;
+ }
}
- mLinkProperties = linkProperties;
}
- if (DBG) {
- log("onSetupConnectionCompleted: DataConnection setup result='"
- + result + "' on cid=" + cid);
- if (result == SetupResult.SUCCESS) {
- log("onSetupConnectionCompleted: LinkProperties: " + mLinkProperties.toString());
- }
+ if (mLinkProperties == null || !mLinkProperties.equals(newLp)) {
+ mLinkProperties = newLp;
+ changed = DataConnectionAc.LinkPropertyChangeAction.CHANGED;
}
- return result;
+
+ return changed;
}
/**
* The parent state for all other states.
*/
- private class DcDefaultState extends HierarchicalState {
+ private class DcDefaultState extends State {
+ @Override
+ public void enter() {
+ phone.mCM.registerForRilConnected(getHandler(), EVENT_RIL_CONNECTED, null);
+ }
+ @Override
+ public void exit() {
+ phone.mCM.unregisterForRilConnected(getHandler());
+ }
@Override
- protected boolean processMessage(Message msg) {
+ public boolean processMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
- case EVENT_RESET:
- if (DBG) log("DcDefaultState: msg.what=EVENT_RESET");
- clearSettings();
- if (msg.obj != null) {
- notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+ if (mAc != null) {
+ if (VDBG) log("Disconnecting to previous connection mAc=" + mAc);
+ mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED);
+ } else {
+ mAc = new AsyncChannel();
+ mAc.connected(null, getHandler(), msg.replyTo);
+ if (VDBG) log("DcDefaultState: FULL_CONNECTION reply connected");
+ mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_SUCCESSFUL, mId, "hi");
}
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECT");
+ mAc.disconnect();
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECTED");
+ mAc = null;
+ break;
+ }
+ case DataConnectionAc.REQ_IS_INACTIVE: {
+ boolean val = getCurrentState() == mInactiveState;
+ if (VDBG) log("REQ_IS_INACTIVE isInactive=" + val);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_IS_INACTIVE, val ? 1 : 0);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_CID: {
+ if (VDBG) log("REQ_GET_CID cid=" + cid);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_CID, cid);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_APNSETTING: {
+ if (VDBG) log("REQ_GET_APNSETTING apnSetting=" + mApn);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNSETTING, mApn);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_PROPERTIES: {
+ LinkProperties lp = new LinkProperties(mLinkProperties);
+ if (VDBG) log("REQ_GET_LINK_PROPERTIES linkProperties" + lp);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_PROPERTIES, lp);
+ break;
+ }
+ case DataConnectionAc.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: {
+ ProxyProperties proxy = (ProxyProperties) msg.obj;
+ if (VDBG) log("REQ_SET_LINK_PROPERTIES_HTTP_PROXY proxy=" + proxy);
+ mLinkProperties.setHttpProxy(proxy);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
+ break;
+ }
+ case DataConnectionAc.REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE: {
+ DataCallState newState = (DataCallState) msg.obj;
+ DataConnectionAc.LinkPropertyChangeAction action = updateLinkProperty(newState);
+ if (VDBG) {
+ log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE action="
+ + action + " newState=" + newState);
+ }
+ mAc.replyToMessage(msg,
+ DataConnectionAc.RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE,
+ action.ordinal());
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_CAPABILITIES: {
+ LinkCapabilities lc = new LinkCapabilities(mCapabilities);
+ if (VDBG) log("REQ_GET_LINK_CAPABILITIES linkCapabilities" + lc);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_LINK_CAPABILITIES, lc);
+ break;
+ }
+ case DataConnectionAc.REQ_RESET:
+ if (VDBG) log("DcDefaultState: msg.what=REQ_RESET");
+ clearSettings();
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
transitionTo(mInactiveState);
break;
+ case DataConnectionAc.REQ_GET_REFCOUNT: {
+ if (VDBG) log("REQ_GET_REFCOUNT refCount=" + mRefCount);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mRefCount);
+ break;
+ }
case EVENT_CONNECT:
if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
@@ -553,14 +653,29 @@ public abstract class DataConnection extends HierarchicalStateMachine {
notifyDisconnectCompleted((DisconnectParams) msg.obj);
break;
+ case EVENT_RIL_CONNECTED:
+ ar = (AsyncResult)msg.obj;
+ if (ar.exception == null) {
+ mRilVersion = (Integer)ar.result;
+ if (DBG) {
+ log("DcDefaultState: msg.what=EVENT_RIL_CONNECTED mRilVersion=" +
+ mRilVersion);
+ }
+ } else {
+ log("Unexpected exception on EVENT_RIL_CONNECTED");
+ mRilVersion = -1;
+ }
+ break;
+
default:
if (DBG) {
- log("DcDefaultState: shouldn't happen but ignore msg.what=" + msg.what);
+ log("DcDefaultState: shouldn't happen but ignore msg.what=0x" +
+ Integer.toHexString(msg.what));
}
break;
}
- return true;
+ return HANDLED;
}
}
private DcDefaultState mDefaultState = new DcDefaultState();
@@ -568,23 +683,24 @@ public abstract class DataConnection extends HierarchicalStateMachine {
/**
* The state machine is inactive and expects a EVENT_CONNECT.
*/
- private class DcInactiveState extends HierarchicalState {
+ private class DcInactiveState extends State {
private ConnectionParams mConnectionParams = null;
private FailCause mFailCause = null;
private DisconnectParams mDisconnectParams = null;
public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
- log("DcInactiveState: setEnterNoticationParams cp,cause");
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
mConnectionParams = cp;
mFailCause = cause;
}
public void setEnterNotificationParams(DisconnectParams dp) {
- log("DcInactiveState: setEnterNoticationParams dp");
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams dp");
mDisconnectParams = dp;
}
- @Override protected void enter() {
+ @Override
+ public void enter() {
mTag += 1;
/**
@@ -595,48 +711,55 @@ public abstract class DataConnection extends HierarchicalStateMachine {
* call to isInactive.
*/
if ((mConnectionParams != null) && (mFailCause != null)) {
- log("DcInactiveState: enter notifyConnectCompleted");
+ if (VDBG) log("DcInactiveState: enter notifyConnectCompleted");
notifyConnectCompleted(mConnectionParams, mFailCause);
}
if (mDisconnectParams != null) {
- log("DcInactiveState: enter notifyDisconnectCompleted");
+ if (VDBG) log("DcInactiveState: enter notifyDisconnectCompleted");
notifyDisconnectCompleted(mDisconnectParams);
}
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
// clear notifications
mConnectionParams = null;
mFailCause = null;
mDisconnectParams = null;
}
- @Override protected boolean processMessage(Message msg) {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
- case EVENT_RESET:
+ case DataConnectionAc.REQ_RESET:
if (DBG) {
- log("DcInactiveState: msg.what=EVENT_RESET, ignore we're already reset");
+ log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
}
- if (msg.obj != null) {
- notifyDisconnectCompleted((DisconnectParams) msg.obj);
- }
- retVal = true;
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
+ retVal = HANDLED;
break;
case EVENT_CONNECT:
- if (DBG) log("DcInactiveState msg.what=EVENT_CONNECT");
ConnectionParams cp = (ConnectionParams) msg.obj;
cp.tag = mTag;
+ if (DBG) {
+ log("DcInactiveState msg.what=EVENT_CONNECT." + "RefCount = "
+ + mRefCount);
+ }
+ mRefCount = 1;
onConnect(cp);
transitionTo(mActivatingState);
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcInactiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcInactiveState nothandled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -647,17 +770,26 @@ public abstract class DataConnection extends HierarchicalStateMachine {
/**
* The state machine is activating a connection.
*/
- private class DcActivatingState extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class DcActivatingState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
AsyncResult ar;
ConnectionParams cp;
switch (msg.what) {
case EVENT_DISCONNECT:
- if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT");
+ if (DBG) log("DcActivatingState deferring msg.what=EVENT_DISCONNECT"
+ + mRefCount);
+ deferMessage(msg);
+ retVal = HANDLED;
+ break;
+
+ case EVENT_CONNECT:
+ if (DBG) log("DcActivatingState deferring msg.what=EVENT_CONNECT refCount = "
+ + mRefCount);
deferMessage(msg);
- retVal = true;
+ retVal = HANDLED;
break;
case EVENT_SETUP_DATA_CONNECTION_DONE:
@@ -666,7 +798,7 @@ public abstract class DataConnection extends HierarchicalStateMachine {
ar = (AsyncResult) msg.obj;
cp = (ConnectionParams) ar.userObj;
- SetupResult result = onSetupConnectionCompleted(ar);
+ DataCallState.SetupResult result = onSetupConnectionCompleted(ar);
if (DBG) log("DcActivatingState onSetupConnectionCompleted result=" + result);
switch (result) {
case SUCCESS:
@@ -700,9 +832,9 @@ public abstract class DataConnection extends HierarchicalStateMachine {
// Request is stale, ignore.
break;
default:
- throw new RuntimeException("Unkown SetupResult, should not happen");
+ throw new RuntimeException("Unknown SetupResult, should not happen");
}
- retVal = true;
+ retVal = HANDLED;
break;
case EVENT_GET_LAST_FAIL_DONE:
@@ -727,12 +859,15 @@ public abstract class DataConnection extends HierarchicalStateMachine {
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcActivatingState not handled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcActivatingState not handled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -743,12 +878,12 @@ public abstract class DataConnection extends HierarchicalStateMachine {
/**
* The state machine is connected, expecting an EVENT_DISCONNECT.
*/
- private class DcActiveState extends HierarchicalState {
+ private class DcActiveState extends State {
private ConnectionParams mConnectionParams = null;
private FailCause mFailCause = null;
public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
- log("DcInactiveState: setEnterNoticationParams cp,cause");
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
mConnectionParams = cp;
mFailCause = cause;
}
@@ -762,33 +897,54 @@ public abstract class DataConnection extends HierarchicalStateMachine {
* call to isActive.
*/
if ((mConnectionParams != null) && (mFailCause != null)) {
- log("DcActiveState: enter notifyConnectCompleted");
+ if (VDBG) log("DcActiveState: enter notifyConnectCompleted");
notifyConnectCompleted(mConnectionParams, mFailCause);
}
}
- @Override protected void exit() {
+ @Override
+ public void exit() {
// clear notifications
mConnectionParams = null;
mFailCause = null;
}
- @Override protected boolean processMessage(Message msg) {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
+ case EVENT_CONNECT:
+ mRefCount++;
+ if (DBG) log("DcActiveState msg.what=EVENT_CONNECT RefCount=" + mRefCount);
+ if (msg.obj != null) {
+ notifyConnectCompleted((ConnectionParams) msg.obj, FailCause.NONE);
+ }
+ retVal = HANDLED;
+ break;
case EVENT_DISCONNECT:
- if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT");
- DisconnectParams dp = (DisconnectParams) msg.obj;
- dp.tag = mTag;
- tearDownData(dp);
- transitionTo(mDisconnectingState);
- retVal = true;
+ mRefCount--;
+ if (DBG) log("DcActiveState msg.what=EVENT_DISCONNECT RefCount=" + mRefCount);
+ if (mRefCount == 0)
+ {
+ DisconnectParams dp = (DisconnectParams) msg.obj;
+ dp.tag = mTag;
+ tearDownData(dp);
+ transitionTo(mDisconnectingState);
+ } else {
+ if (msg.obj != null) {
+ notifyDisconnectCompleted((DisconnectParams) msg.obj);
+ }
+ }
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcActiveState nothandled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcActiveState not handled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -799,11 +955,19 @@ public abstract class DataConnection extends HierarchicalStateMachine {
/**
* The state machine is disconnecting.
*/
- private class DcDisconnectingState extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class DcDisconnectingState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
+ case EVENT_CONNECT:
+ if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = "
+ + mRefCount);
+ deferMessage(msg);
+ retVal = HANDLED;
+ break;
+
case EVENT_DEACTIVATE_DONE:
if (DBG) log("DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE");
AsyncResult ar = (AsyncResult) msg.obj;
@@ -817,12 +981,15 @@ public abstract class DataConnection extends HierarchicalStateMachine {
if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag="
+ dp.tag + " mTag=" + mTag);
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) log("DcDisconnectingState not handled msg.what=" + msg.what);
- retVal = false;
+ if (VDBG) {
+ log("DcDisconnectingState not handled msg.what=0x" +
+ Integer.toHexString(msg.what));
+ }
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -833,8 +1000,9 @@ public abstract class DataConnection extends HierarchicalStateMachine {
/**
* The state machine is disconnecting after an creating a connection.
*/
- private class DcDisconnectionErrorCreatingConnection extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class DcDisconnectionErrorCreatingConnection extends State {
+ @Override
+ public boolean processMessage(Message msg) {
boolean retVal;
switch (msg.what) {
@@ -858,15 +1026,15 @@ public abstract class DataConnection extends HierarchicalStateMachine {
" stale dp.tag=" + cp.tag + ", mTag=" + mTag);
}
}
- retVal = true;
+ retVal = HANDLED;
break;
default:
- if (DBG) {
- log("DcDisconnectionErrorCreatingConnection not handled msg.what="
- + msg.what);
+ if (VDBG) {
+ log("DcDisconnectionErrorCreatingConnection not handled msg.what=0x"
+ + Integer.toHexString(msg.what));
}
- retVal = false;
+ retVal = NOT_HANDLED;
break;
}
return retVal;
@@ -878,143 +1046,26 @@ public abstract class DataConnection extends HierarchicalStateMachine {
// ******* public interface
/**
- * Disconnect from the network.
- *
- * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
- * With AsyncResult.userObj set to the original msg.obj.
- */
- public void reset(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(onCompletedMsg)));
- }
-
- /**
- * Reset the connection and wait for it to complete.
- * TODO: Remove when all callers only need the asynchronous
- * reset defined above.
- */
- public void resetSynchronously() {
- ResetSynchronouslyLock lockObj = new ResetSynchronouslyLock();
- synchronized(lockObj) {
- sendMessage(obtainMessage(EVENT_RESET, new DisconnectParams(lockObj)));
- try {
- lockObj.wait();
- } catch (InterruptedException e) {
- log("blockingReset: unexpected interrupted of wait()");
- }
- }
- }
-
- /**
- * Connect to the apn and return an AsyncResult in onCompletedMsg.
+ * Bring up a connection to the apn and return an AsyncResult in onCompletedMsg.
* Used for cellular networks that use Acesss Point Names (APN) such
* as GSM networks.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj,
* AsyncResult.result = FailCause and AsyncResult.exception = Exception().
- * @param apn is the Access Point Name to connect to
+ * @param apn is the Access Point Name to bring up a connection to
*/
- public void connect(Message onCompletedMsg, ApnSetting apn) {
+ public void bringUp(Message onCompletedMsg, ApnSetting apn) {
sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apn, onCompletedMsg)));
}
/**
- * Connect to the apn and return an AsyncResult in onCompletedMsg.
- *
- * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
- * With AsyncResult.userObj set to the original msg.obj,
- * AsyncResult.result = FailCause and AsyncResult.exception = Exception().
- */
- public void connect(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(null, onCompletedMsg)));
- }
-
- /**
- * Disconnect from the network.
+ * Tear down the connection through the apn on the network.
*
* @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
* With AsyncResult.userObj set to the original msg.obj.
*/
- public void disconnect(Message onCompletedMsg) {
- sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(onCompletedMsg)));
- }
-
- // ****** The following are used for debugging.
-
- /**
- * TODO: This should be an asynchronous call and we wouldn't
- * have to use handle the notification in the DcInactiveState.enter.
- *
- * @return true if the state machine is in the inactive state.
- */
- public boolean isInactive() {
- boolean retVal = getCurrentState() == mInactiveState;
- return retVal;
- }
-
- /**
- * TODO: This should be an asynchronous call and we wouldn't
- * have to use handle the notification in the DcActiveState.enter.
- *
- * @return true if the state machine is in the active state.
- */
- public boolean isActive() {
- boolean retVal = getCurrentState() == mActiveState;
- return retVal;
- }
-
- /**
- * Get the DataConnection ID
- */
- public int getDataConnectionId() {
- return mId;
- }
-
- /**
- * Return the LinkProperties for the connection.
- *
- * @return a copy of the LinkProperties, is never null.
- */
- public LinkProperties getLinkProperties() {
- return new LinkProperties(mLinkProperties);
- }
-
- /**
- * A capability is an Integer/String pair, the capabilities
- * are defined in the class LinkSocket#Key.
- *
- * @return a copy of this connections capabilities, may be empty but never null.
- */
- public LinkCapabilities getLinkCapabilities() {
- return new LinkCapabilities(mCapabilities);
- }
-
- /**
- * @return the current state as a string.
- */
- public String getStateAsString() {
- String retVal = getCurrentState().getName();
- return retVal;
- }
-
- /**
- * @return the time of when this connection was created.
- */
- public long getConnectionTime() {
- return createTime;
- }
-
- /**
- * @return the time of the last failure.
- */
- public long getLastFailTime() {
- return lastFailTime;
- }
-
- /**
- * @return the last cause of failure.
- */
- public FailCause getLastFailCause() {
- return lastFailCause;
+ public void tearDown(String reason, Message onCompletedMsg) {
+ sendMessage(obtainMessage(EVENT_DISCONNECT, new DisconnectParams(reason, onCompletedMsg)));
}
}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionAc.java b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
new file mode 100644
index 0000000..62b90ae
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnectionAc.java
@@ -0,0 +1,377 @@
+/*
+ * 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;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.ProxyProperties;
+import android.os.Message;
+
+/**
+ * AsyncChannel to a DataConnection
+ */
+public class DataConnectionAc extends AsyncChannel {
+ private static final boolean DBG = false;
+ private String mLogTag;
+
+ public DataConnection dataConnection;
+
+ public static final int BASE = Protocol.BASE_DATA_CONNECTION_AC;
+
+ public static final int REQ_IS_INACTIVE = BASE + 0;
+ public static final int RSP_IS_INACTIVE = BASE + 1;
+
+ public static final int REQ_GET_CID = BASE + 2;
+ public static final int RSP_GET_CID = BASE + 3;
+
+ public static final int REQ_GET_APNSETTING = BASE + 4;
+ public static final int RSP_GET_APNSETTING = BASE + 5;
+
+ public static final int REQ_GET_LINK_PROPERTIES = BASE + 6;
+ public static final int RSP_GET_LINK_PROPERTIES = BASE + 7;
+
+ public static final int REQ_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 8;
+ public static final int RSP_SET_LINK_PROPERTIES_HTTP_PROXY = BASE + 9;
+
+ public static final int REQ_GET_LINK_CAPABILITIES = BASE + 10;
+ public static final int RSP_GET_LINK_CAPABILITIES = BASE + 11;
+
+ public static final int REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 12;
+ public static final int RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE = BASE + 13;
+
+ public static final int REQ_RESET = BASE + 14;
+ public static final int RSP_RESET = BASE + 15;
+
+ public static final int REQ_GET_REFCOUNT = BASE + 16;
+ public static final int RSP_GET_REFCOUNT = BASE + 17;
+
+ /**
+ * enum used to notify action taken or necessary to be
+ * taken after the link property is changed.
+ */
+ public enum LinkPropertyChangeAction {
+ NONE, CHANGED, RESET;
+
+ public static LinkPropertyChangeAction fromInt(int value) {
+ if (value == NONE.ordinal()) {
+ return NONE;
+ } else if (value == CHANGED.ordinal()) {
+ return CHANGED;
+ } else if (value == RESET.ordinal()) {
+ return RESET;
+ } else {
+ throw new RuntimeException("LinkPropertyChangeAction.fromInt: bad value=" + value);
+ }
+ }
+ }
+
+ public DataConnectionAc(DataConnection dc, String logTag) {
+ dataConnection = dc;
+ mLogTag = logTag;
+ }
+
+ /**
+ * Request if the state machine is in the inactive state.
+ * Response {@link #rspIsInactive}
+ */
+ public void reqIsInactive() {
+ sendMessage(REQ_IS_INACTIVE);
+ if (DBG) log("reqIsInactive");
+ }
+
+ /**
+ * Evaluate RSP_IS_INACTIVE.
+ *
+ * @return true if the state machine is in the inactive state.
+ */
+ public boolean rspIsInactive(Message response) {
+ boolean retVal = response.arg1 == 1;
+ if (DBG) log("rspIsInactive=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return true if the state machine is in the inactive state.
+ */
+ public boolean isInactiveSync() {
+ Message response = sendMessageSynchronously(REQ_IS_INACTIVE);
+ if ((response != null) && (response.what == RSP_IS_INACTIVE)) {
+ return rspIsInactive(response);
+ } else {
+ log("rspIsInactive error response=" + response);
+ return false;
+ }
+ }
+
+ /**
+ * Request the Connection ID.
+ * Response {@link #rspCid}
+ */
+ public void reqCid() {
+ sendMessage(REQ_GET_CID);
+ if (DBG) log("reqCid");
+ }
+
+ /**
+ * Evaluate a RSP_GET_CID message and return the cid.
+ *
+ * @param response Message
+ * @return connection id or -1 if an error
+ */
+ public int rspCid(Message response) {
+ int retVal = response.arg1;
+ if (DBG) log("rspCid=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return connection id or -1 if an error
+ */
+ public int getCidSync() {
+ Message response = sendMessageSynchronously(REQ_GET_CID);
+ if ((response != null) && (response.what == RSP_GET_CID)) {
+ return rspCid(response);
+ } else {
+ log("rspCid error response=" + response);
+ return -1;
+ }
+ }
+
+ /**
+ * Request the Reference Count.
+ * Response {@link #rspRefCount}
+ */
+ public void reqRefCount() {
+ sendMessage(REQ_GET_REFCOUNT);
+ if (DBG) log("reqRefCount");
+ }
+
+ /**
+ * Evaluate a RSP_GET_REFCOUNT message and return the refCount.
+ *
+ * @param response Message
+ * @return ref count or -1 if an error
+ */
+ public int rspRefCount(Message response) {
+ int retVal = response.arg1;
+ if (DBG) log("rspRefCount=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * @return connection id or -1 if an error
+ */
+ public int getRefCountSync() {
+ Message response = sendMessageSynchronously(REQ_GET_REFCOUNT);
+ if ((response != null) && (response.what == RSP_GET_REFCOUNT)) {
+ return rspRefCount(response);
+ } else {
+ log("rspRefCount error response=" + response);
+ return -1;
+ }
+ }
+
+ /**
+ * Request the connections ApnSetting.
+ * Response {@link #rspApnSetting}
+ */
+ public void reqApnSetting() {
+ sendMessage(REQ_GET_APNSETTING);
+ if (DBG) log("reqApnSetting");
+ }
+
+ /**
+ * Evaluate a RSP_APN_SETTING message and return the ApnSetting.
+ *
+ * @param response Message
+ * @return ApnSetting, maybe null
+ */
+ public ApnSetting rspApnSetting(Message response) {
+ ApnSetting retVal = (ApnSetting) response.obj;
+ if (DBG) log("rspApnSetting=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections ApnSetting.
+ *
+ * @return ApnSetting or null if an error
+ */
+ public ApnSetting getApnSettingSync() {
+ Message response = sendMessageSynchronously(REQ_GET_APNSETTING);
+ if ((response != null) && (response.what == RSP_GET_APNSETTING)) {
+ return rspApnSetting(response);
+ } else {
+ log("getApnSetting error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request the connections LinkProperties.
+ * Response {@link #rspLinkProperties}
+ */
+ public void reqLinkProperties() {
+ sendMessage(REQ_GET_LINK_PROPERTIES);
+ if (DBG) log("reqLinkProperties");
+ }
+
+ /**
+ * Evaluate RSP_GET_LINK_PROPERTIES
+ *
+ * @param response
+ * @return LinkProperties, maybe null.
+ */
+ public LinkProperties rspLinkProperties(Message response) {
+ LinkProperties retVal = (LinkProperties) response.obj;
+ if (DBG) log("rspLinkProperties=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections LinkProperties.
+ *
+ * @return LinkProperties or null if an error
+ */
+ public LinkProperties getLinkPropertiesSync() {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_PROPERTIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_PROPERTIES)) {
+ return rspLinkProperties(response);
+ } else {
+ log("getLinkProperties error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request setting the connections LinkProperties.HttpProxy.
+ * Response RSP_SET_LINK_PROPERTIES when complete.
+ */
+ public void reqSetLinkPropertiesHttpProxy(ProxyProperties proxy) {
+ sendMessage(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
+ if (DBG) log("reqSetLinkPropertiesHttpProxy proxy=" + proxy);
+ }
+
+ /**
+ * Set the connections LinkProperties.HttpProxy
+ */
+ public void setLinkPropertiesHttpProxySync(ProxyProperties proxy) {
+ Message response =
+ sendMessageSynchronously(REQ_SET_LINK_PROPERTIES_HTTP_PROXY, proxy);
+ if ((response != null) && (response.what == RSP_SET_LINK_PROPERTIES_HTTP_PROXY)) {
+ if (DBG) log("setLinkPropertiesHttpPoxy ok");
+ } else {
+ log("setLinkPropertiesHttpPoxy error response=" + response);
+ }
+ }
+
+ /**
+ * Request update LinkProperties from DataCallState
+ * Response {@link #rspUpdateLinkPropertiesDataCallState}
+ */
+ public void reqUpdateLinkPropertiesDataCallState(DataCallState newState) {
+ sendMessage(REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE, newState);
+ if (DBG) log("reqUpdateLinkPropertiesDataCallState");
+ }
+
+ public LinkPropertyChangeAction rspUpdateLinkPropertiesDataCallState(Message response) {
+ LinkPropertyChangeAction retVal = LinkPropertyChangeAction.fromInt(response.arg1);
+ if (DBG) log("rspUpdateLinkPropertiesState=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Update link properties in the data connection
+ *
+ * @return true if link property has been updated. false otherwise.
+ */
+ public LinkPropertyChangeAction updateLinkPropertiesDataCallStateSync(DataCallState newState) {
+ Message response =
+ sendMessageSynchronously(REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE, newState);
+ if ((response != null) &&
+ (response.what == RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE)) {
+ return rspUpdateLinkPropertiesDataCallState(response);
+ } else {
+ log("getLinkProperties error response=" + response);
+ return LinkPropertyChangeAction.NONE;
+ }
+ }
+
+ /**
+ * Request the connections LinkCapabilities.
+ * Response {@link #rspLinkCapabilities}
+ */
+ public void reqLinkCapabilities() {
+ sendMessage(REQ_GET_LINK_CAPABILITIES);
+ if (DBG) log("reqLinkCapabilities");
+ }
+
+ /**
+ * Evaluate RSP_GET_LINK_CAPABILITIES
+ *
+ * @param response
+ * @return LinkCapabilites, maybe null.
+ */
+ public LinkCapabilities rspLinkCapabilities(Message response) {
+ LinkCapabilities retVal = (LinkCapabilities) response.obj;
+ if (DBG) log("rspLinkCapabilities=" + retVal);
+ return retVal;
+ }
+
+ /**
+ * Get the connections LinkCapabilities.
+ *
+ * @return LinkCapabilities or null if an error
+ */
+ public LinkCapabilities getLinkCapabilitiesSync() {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_CAPABILITIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_CAPABILITIES)) {
+ return rspLinkCapabilities(response);
+ } else {
+ log("getLinkCapabilities error response=" + response);
+ return null;
+ }
+ }
+
+ /**
+ * Request the connections LinkCapabilities.
+ * Response RSP_RESET when complete
+ */
+ public void reqReset() {
+ sendMessage(REQ_RESET);
+ if (DBG) log("reqReset");
+ }
+
+ /**
+ * Reset the connection and wait for it to complete.
+ */
+ public void resetSync() {
+ Message response = sendMessageSynchronously(REQ_RESET);
+ if ((response != null) && (response.what == RSP_RESET)) {
+ if (DBG) log("restSync ok");
+ } else {
+ log("restSync error response=" + response);
+ }
+ }
+
+ private void log(String s) {
+ android.util.Log.d(mLogTag, "DataConnectionAc " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 7f8485b..5d6aaa6 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -22,24 +22,30 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.net.IConnectivityManager;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncResult;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
-import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.R;
+import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -87,38 +93,39 @@ public abstract class DataConnectionTracker extends Handler {
public static String EXTRA_MESSENGER = "EXTRA_MESSENGER";
/***** Event Codes *****/
- protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
- protected static final int EVENT_RADIO_AVAILABLE = 3;
- protected static final int EVENT_RECORDS_LOADED = 4;
- protected static final int EVENT_TRY_SETUP_DATA = 5;
- protected static final int EVENT_DATA_STATE_CHANGED = 6;
- protected static final int EVENT_POLL_PDP = 7;
- protected static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
- protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
- protected static final int EVENT_VOICE_CALL_STARTED = 14;
- protected static final int EVENT_VOICE_CALL_ENDED = 15;
- protected static final int EVENT_GPRS_DETACHED = 19;
- protected static final int EVENT_LINK_STATE_CHANGED = 20;
- protected static final int EVENT_ROAMING_ON = 21;
- protected static final int EVENT_ROAMING_OFF = 22;
- protected static final int EVENT_ENABLE_NEW_APN = 23;
- protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
- protected static final int EVENT_DISCONNECT_DONE = 25;
- protected static final int EVENT_GPRS_ATTACHED = 26;
- protected static final int EVENT_START_NETSTAT_POLL = 27;
- protected static final int EVENT_START_RECOVERY = 28;
- protected static final int EVENT_APN_CHANGED = 29;
- protected static final int EVENT_CDMA_DATA_DETACHED = 30;
- protected static final int EVENT_NV_READY = 31;
- protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
- protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
- public static final int EVENT_CLEAN_UP_CONNECTION = 34;
- protected static final int EVENT_CDMA_OTA_PROVISION = 35;
- protected static final int EVENT_RESTART_RADIO = 36;
- protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37;
- protected static final int EVENT_RESET_DONE = 38;
-
- public static final int CMD_SET_DATA_ENABLE = 39;
+ protected static final int BASE = Protocol.BASE_DATA_CONNECTION_TRACKER;
+ protected static final int EVENT_DATA_SETUP_COMPLETE = BASE + 0;
+ protected static final int EVENT_RADIO_AVAILABLE = BASE + 1;
+ protected static final int EVENT_RECORDS_LOADED = BASE + 2;
+ protected static final int EVENT_TRY_SETUP_DATA = BASE + 3;
+ protected static final int EVENT_DATA_STATE_CHANGED = BASE + 4;
+ protected static final int EVENT_POLL_PDP = BASE + 5;
+ protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = BASE + 6;
+ protected static final int EVENT_VOICE_CALL_STARTED = BASE + 7;
+ protected static final int EVENT_VOICE_CALL_ENDED = BASE + 8;
+ protected static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9;
+ protected static final int EVENT_LINK_STATE_CHANGED = BASE + 10;
+ protected static final int EVENT_ROAMING_ON = BASE + 11;
+ protected static final int EVENT_ROAMING_OFF = BASE + 12;
+ protected static final int EVENT_ENABLE_NEW_APN = BASE + 13;
+ protected static final int EVENT_RESTORE_DEFAULT_APN = BASE + 14;
+ protected static final int EVENT_DISCONNECT_DONE = BASE + 15;
+ protected static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16;
+ protected static final int EVENT_START_NETSTAT_POLL = BASE + 17;
+ protected static final int EVENT_START_RECOVERY = BASE + 18;
+ protected static final int EVENT_APN_CHANGED = BASE + 19;
+ protected static final int EVENT_CDMA_DATA_DETACHED = BASE + 20;
+ protected static final int EVENT_NV_READY = BASE + 21;
+ protected static final int EVENT_PS_RESTRICT_ENABLED = BASE + 22;
+ protected static final int EVENT_PS_RESTRICT_DISABLED = BASE + 23;
+ public static final int EVENT_CLEAN_UP_CONNECTION = BASE + 24;
+ protected static final int EVENT_CDMA_OTA_PROVISION = BASE + 25;
+ protected static final int EVENT_RESTART_RADIO = BASE + 26;
+ protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = BASE + 27;
+ protected static final int EVENT_RESET_DONE = BASE + 28;
+ public static final int CMD_SET_DATA_ENABLE = BASE + 29;
+ public static final int EVENT_CLEAN_UP_ALL_CONNECTIONS = BASE + 30;
+ public static final int CMD_SET_DEPENDENCY_MET = BASE + 31;
/***** Constants *****/
@@ -128,11 +135,19 @@ public abstract class DataConnectionTracker extends Handler {
protected static final int APN_SUPL_ID = 2;
protected static final int APN_DUN_ID = 3;
protected static final int APN_HIPRI_ID = 4;
- protected static final int APN_NUM_TYPES = 5;
+ protected static final int APN_IMS_ID = 5;
+ protected static final int APN_FOTA_ID = 6;
+ protected static final int APN_CBS_ID = 7;
+ protected static final int APN_NUM_TYPES = 8;
public static final int DISABLED = 0;
public static final int ENABLED = 1;
+ public static final String APN_TYPE_KEY = "apnType";
+
+ /** Delay between APN attempts */
+ protected static final int APN_DELAY_MILLIS = 5000;
+
// responds to the setInternalDataEnabled call - used internally to turn off data
// for example during emergency calls
protected boolean mInternalDataEnabled = true;
@@ -192,6 +207,21 @@ public abstract class DataConnectionTracker extends Handler {
// getActionIntentReconnectAlarm.
protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+ // Used for debugging. Send the INTENT with an optional counter value with the number
+ // of times the setup is to fail before succeeding. If the counter isn't passed the
+ // setup will fail once. Example fail two times with FailCause.SIGNAL_LOST(-3)
+ // adb shell am broadcast \
+ // -a com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter \
+ // --ei fail_data_setup_counter 3 --ei fail_data_setup_fail_cause -3
+ protected static final String INTENT_SET_FAIL_DATA_SETUP_COUNTER =
+ "com.android.internal.telephony.dataconnectiontracker.intent_set_fail_data_setup_counter";
+ protected static final String FAIL_DATA_SETUP_COUNTER = "fail_data_setup_counter";
+ protected int mFailDataSetupCounter = 0;
+ protected static final String FAIL_DATA_SETUP_FAIL_CAUSE = "fail_data_setup_fail_cause";
+ protected FailCause mFailDataSetupFailCause = FailCause.ERROR_UNSPECIFIED;
+
+ protected static final String DEFALUT_DATA_ON_BOOT_PROP = "net.def_data_on_boot";
+
// member variables
protected PhoneBase mPhone;
protected Activity mActivity = Activity.NONE;
@@ -206,9 +236,6 @@ public abstract class DataConnectionTracker extends Handler {
protected int mNoRecvPollCount = 0;
protected boolean mNetStatPollEnabled = false;
- /** Manage the behavior of data retry after failure (TODO: One per connection in the future?) */
- protected RetryManager mRetryMgr = new RetryManager();
-
// wifi connection status will be updated by sticky intent
protected boolean mIsWifiConnected = false;
@@ -221,7 +248,7 @@ public abstract class DataConnectionTracker extends Handler {
/** indication of our availability (preconditions to trysetupData are met) **/
protected boolean mAvailability = false;
- // When false we will not auto attach and manully attaching is required.
+ // When false we will not auto attach and manually attaching is required.
protected boolean mAutoAttachOnCreation = false;
// State of screen
@@ -229,12 +256,6 @@ public abstract class DataConnectionTracker extends Handler {
// really a lower power mode")
protected boolean mIsScreenOn = true;
- /** The link properties (dns, gateway, ip, etc) */
- protected LinkProperties mLinkProperties = new LinkProperties();
-
- /** The link capabilities */
- protected LinkCapabilities mLinkCapabilities = new LinkCapabilities();
-
/** Allows the generation of unique Id's for DataConnection objects */
protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
@@ -242,15 +263,39 @@ public abstract class DataConnectionTracker extends Handler {
protected HashMap<Integer, DataConnection> mDataConnections =
new HashMap<Integer, DataConnection>();
+ /** The data connection async channels */
+ protected HashMap<Integer, DataConnectionAc> mDataConnectionAsyncChannels =
+ new HashMap<Integer, DataConnectionAc>();
+
+ /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
+ protected HashMap<String, Integer> mApnToDataConnectionId =
+ new HashMap<String, Integer>();
+
+ /** Phone.APN_TYPE_* ===> ApnContext */
+ protected ConcurrentHashMap<String, ApnContext> mApnContexts;
+
/* Currently active APN */
protected ApnSetting mActiveApn;
+ /** allApns holds all apns */
+ protected ArrayList<ApnSetting> mAllApns = null;
+
+ /** preferred apn */
+ protected ApnSetting mPreferredApn = null;
+
+ /** Is packet service restricted by network */
+ protected boolean mIsPsRestricted = false;
+
+ /* Once disposed dont handle any messages */
+ protected boolean mIsDisposed = false;
+
protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
+ if (DBG) log("onReceive: action=" + action);
if (action.equals(Intent.ACTION_SCREEN_ON)) {
mIsScreenOn = true;
stopNetStatPoll();
@@ -259,17 +304,10 @@ public abstract class DataConnectionTracker extends Handler {
mIsScreenOn = false;
stopNetStatPoll();
startNetStatPoll();
- } else if (action.equals(getActionIntentReconnectAlarm())) {
+ } else if (action.startsWith(getActionIntentReconnectAlarm())) {
log("Reconnect alarm. Previous state was " + mState);
+ onActionIntentReconnectAlarm(intent);
- String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- if (mState == State.FAILED) {
- Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 0; // tearDown is false
- msg.obj = reason;
- sendMessage(msg);
- }
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
final android.net.NetworkInfo networkInfo = (NetworkInfo)
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
@@ -283,10 +321,48 @@ public abstract class DataConnectionTracker extends Handler {
// quit and won't report disconnected until next enabling.
mIsWifiConnected = false;
}
+ } else if (action.equals(INTENT_SET_FAIL_DATA_SETUP_COUNTER)) {
+ mFailDataSetupCounter = intent.getIntExtra(FAIL_DATA_SETUP_COUNTER, 1);
+ mFailDataSetupFailCause = FailCause.fromInt(
+ intent.getIntExtra(FAIL_DATA_SETUP_FAIL_CAUSE,
+ FailCause.ERROR_UNSPECIFIED.getErrorCode()));
+ if (DBG) log("set mFailDataSetupCounter=" + mFailDataSetupCounter +
+ " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
}
}
};
+ protected boolean isDataSetupCompleteOk(AsyncResult ar) {
+ if (ar.exception != null) {
+ if (DBG) log("isDataSetupCompleteOk return false, ar.result=" + ar.result);
+ return false;
+ }
+ if (mFailDataSetupCounter <= 0) {
+ if (DBG) log("isDataSetupCompleteOk return true");
+ return true;
+ }
+ ar.result = mFailDataSetupFailCause;
+ if (DBG) {
+ log("isDataSetupCompleteOk return false" +
+ " mFailDataSetupCounter=" + mFailDataSetupCounter +
+ " mFailDataSetupFailCause=" + mFailDataSetupFailCause);
+ }
+ mFailDataSetupCounter -= 1;
+ return false;
+ }
+
+ protected void onActionIntentReconnectAlarm(Intent intent) {
+ String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+ if (mState == State.FAILED) {
+ Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 0; // tearDown is false
+ msg.arg2 = 0;
+ msg.obj = reason;
+ sendMessage(msg);
+ }
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+ }
+
/**
* Default constructor
*/
@@ -300,6 +376,7 @@ public abstract class DataConnectionTracker extends Handler {
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ filter.addAction(INTENT_SET_FAIL_DATA_SETUP_COUNTER);
mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(),
Settings.Secure.MOBILE_DATA, 1) == 1;
@@ -310,16 +387,23 @@ public abstract class DataConnectionTracker extends Handler {
// This preference tells us 1) initial condition for "dataEnabled",
// and 2) whether the RIL will setup the baseband to auto-PS attach.
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
- dataEnabled[APN_DEFAULT_ID] =
- !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
+
+ dataEnabled[APN_DEFAULT_ID] = SystemProperties.getBoolean(DEFALUT_DATA_ON_BOOT_PROP,
+ true);
if (dataEnabled[APN_DEFAULT_ID]) {
enabledCount++;
}
- mAutoAttachOnCreation = dataEnabled[APN_DEFAULT_ID];
+
+ SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
+ mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
}
public void dispose() {
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ dcac.disconnect();
+ }
+ mDataConnectionAsyncChannels.clear();
+ mIsDisposed = true;
mPhone.getContext().unregisterReceiver(this.mIntentReceiver);
}
@@ -333,34 +417,26 @@ public abstract class DataConnectionTracker extends Handler {
return mActivity;
}
- public State getState() {
- return mState;
- }
-
- public String getStateInString() {
- switch (mState) {
- case IDLE: return "IDLE";
- case INITING: return "INIT";
- case CONNECTING: return "CING";
- case SCANNING: return "SCAN";
- case CONNECTED: return "CNTD";
- case DISCONNECTING: return "DING";
- case FAILED: return "FAIL";
- default: return "ERRO";
+ public boolean isApnTypeActive(String type) {
+ // TODO: support simultaneous with List instead
+ if (Phone.APN_TYPE_DUN.equals(type)) {
+ ApnSetting dunApn = fetchDunApn();
+ if (dunApn != null) {
+ return ((mActiveApn != null) && (dunApn.toString().equals(mActiveApn.toString())));
+ }
}
+ return mActiveApn != null && mActiveApn.canHandleType(type);
}
- /**
- * @return the data connections
- */
- public ArrayList<DataConnection> getAllDataConnections() {
- /** TODO: change return type to Collection? */
- return new ArrayList<DataConnection>(mDataConnections.values());
- }
+ protected ApnSetting fetchDunApn() {
+ Context c = mPhone.getContext();
+ String apnData = Settings.Secure.getString(c.getContentResolver(),
+ Settings.Secure.TETHER_DUN_APN);
+ ApnSetting dunSetting = ApnSetting.fromString(apnData);
+ if (dunSetting != null) return dunSetting;
- public boolean isApnTypeActive(String type) {
- // TODO: support simultaneous with List instead
- return mActiveApn != null && mActiveApn.canHandleType(type);
+ apnData = c.getResources().getString(R.string.config_tether_apndata);
+ return ApnSetting.fromString(apnData);
}
public String[] getActiveApnTypes() {
@@ -374,17 +450,8 @@ public abstract class DataConnectionTracker extends Handler {
return result;
}
- public String getActiveApnType() {
- String result;
- if (mActiveApn != null) {
- result = apnIdToType(mActiveApn.id);
- } else {
- result = null;
- }
- return result;
- }
-
- protected String getActiveApnString() {
+ /** TODO: See if we can remove */
+ public String getActiveApnString(String apnType) {
String result = null;
if (mActiveApn != null) {
result = mActiveApn.apn;
@@ -392,17 +459,6 @@ public abstract class DataConnectionTracker extends Handler {
return result;
}
- /**
- * The data connection is expected to be setup while device
- * 1. has Icc card
- * 2. registered for data service
- * 3. user doesn't explicitly disable data service
- * 4. wifi is not on
- *
- * @return false while no data connection if all above requirements are met.
- */
- public abstract boolean isDataConnectionAsDesired();
-
//The data roaming setting is now located in the shared preferences.
// See if the requested preference value is the same as that stored in
// the shared values. If it is not, then update it.
@@ -412,7 +468,7 @@ public abstract class DataConnectionTracker extends Handler {
Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
if (mPhone.getServiceState().getRoaming()) {
if (enabled) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
}
sendMessage(obtainMessage(EVENT_ROAMING_ON));
}
@@ -429,10 +485,19 @@ public abstract class DataConnectionTracker extends Handler {
}
}
-
+ // abstract methods
protected abstract String getActionIntentReconnectAlarm();
+ protected abstract void startNetStatPoll();
+ protected abstract void stopNetStatPoll();
+ protected abstract void restartRadio();
+ protected abstract void log(String s);
+ protected abstract void loge(String s);
+ protected abstract boolean isDataAllowed();
+ protected abstract boolean isApnTypeAvailable(String type);
+ public abstract State getState(String apnType);
+ protected abstract void setState(State s);
+ protected abstract void gotoIdleAndNotifyDataConnection(String reason);
- // abstract handler methods
protected abstract boolean onTrySetupData(String reason);
protected abstract void onRoamingOff();
protected abstract void onRoamingOn();
@@ -440,15 +505,23 @@ public abstract class DataConnectionTracker extends Handler {
protected abstract void onRadioOffOrNotAvailable();
protected abstract void onDataSetupComplete(AsyncResult ar);
protected abstract void onDisconnectDone(int connId, AsyncResult ar);
- protected abstract void onResetDone(AsyncResult ar);
protected abstract void onVoiceCallStarted();
protected abstract void onVoiceCallEnded();
- protected abstract void onCleanUpConnection(boolean tearDown, String reason);
+ protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason);
+ protected abstract void onCleanUpAllConnections(String cause);
+ protected abstract boolean isDataPossible();
+ protected abstract boolean isDataPossible(String apnType);
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
-
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ log("DISCONNECTED_CONNECTED: msg=" + msg);
+ DataConnectionAc dcac = (DataConnectionAc) msg.obj;
+ mDataConnectionAsyncChannels.remove(dcac.dataConnection.getDataConnectionId());
+ dcac.disconnected();
+ break;
+ }
case EVENT_ENABLE_NEW_APN:
onEnableApn(msg.arg1, msg.arg2);
break;
@@ -463,7 +536,7 @@ public abstract class DataConnectionTracker extends Handler {
case EVENT_ROAMING_OFF:
if (getDataOnRoamingEnabled() == false) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
}
onRoamingOff();
break;
@@ -498,28 +571,47 @@ public abstract class DataConnectionTracker extends Handler {
onVoiceCallEnded();
break;
- case EVENT_CLEAN_UP_CONNECTION:
+ case EVENT_CLEAN_UP_ALL_CONNECTIONS: {
+ onCleanUpAllConnections((String) msg.obj);
+ break;
+ }
+ case EVENT_CLEAN_UP_CONNECTION: {
boolean tearDown = (msg.arg1 == 0) ? false : true;
- onCleanUpConnection(tearDown, (String) msg.obj);
+ onCleanUpConnection(tearDown, msg.arg2, (String) msg.obj);
break;
-
+ }
case EVENT_SET_INTERNAL_DATA_ENABLE: {
boolean enabled = (msg.arg1 == ENABLED) ? true : false;
onSetInternalDataEnabled(enabled);
break;
}
- case EVENT_RESET_DONE:
+ case EVENT_RESET_DONE: {
+ if (DBG) log("EVENT_RESET_DONE");
onResetDone((AsyncResult) msg.obj);
break;
+ }
case CMD_SET_DATA_ENABLE: {
- log("CMD_SET_DATA_ENABLE msg=" + msg);
boolean enabled = (msg.arg1 == ENABLED) ? true : false;
+ if (DBG) log("CMD_SET_DATA_ENABLE enabled=" + enabled);
onSetDataEnabled(enabled);
break;
}
+ case CMD_SET_DEPENDENCY_MET: {
+ boolean met = (msg.arg1 == ENABLED) ? true : false;
+ if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met);
+ Bundle bundle = msg.getData();
+ if (bundle != null) {
+ String apnType = (String)bundle.get(APN_TYPE_KEY);
+ if (apnType != null) {
+ onSetDependencyMet(apnType, met);
+ }
+ }
+ break;
+ }
+
default:
- Log.e("DATA", "Unidentified event = " + msg.what);
+ Log.e("DATA", "Unidentified event msg=" + msg);
break;
}
}
@@ -536,16 +628,6 @@ public abstract class DataConnectionTracker extends Handler {
return result;
}
- protected abstract void startNetStatPoll();
-
- protected abstract void stopNetStatPoll();
-
- protected abstract void restartRadio();
-
- protected abstract void log(String s);
-
- protected abstract void loge(String s);
-
protected int apnTypeToId(String type) {
if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
return APN_DEFAULT_ID;
@@ -557,6 +639,12 @@ public abstract class DataConnectionTracker extends Handler {
return APN_DUN_ID;
} else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
return APN_HIPRI_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_IMS)) {
+ return APN_IMS_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_FOTA)) {
+ return APN_FOTA_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_CBS)) {
+ return APN_CBS_ID;
} else {
return APN_INVALID_ID;
}
@@ -574,20 +662,25 @@ public abstract class DataConnectionTracker extends Handler {
return Phone.APN_TYPE_DUN;
case APN_HIPRI_ID:
return Phone.APN_TYPE_HIPRI;
+ case APN_IMS_ID:
+ return Phone.APN_TYPE_IMS;
+ case APN_FOTA_ID:
+ return Phone.APN_TYPE_FOTA;
+ case APN_CBS_ID:
+ return Phone.APN_TYPE_CBS;
default:
log("Unknown id (" + id + ") in apnIdToType");
return Phone.APN_TYPE_DEFAULT;
}
}
- protected abstract boolean isApnTypeAvailable(String type);
-
- protected abstract void setState(State s);
-
protected LinkProperties getLinkProperties(String apnType) {
int id = apnTypeToId(apnType);
+
if (isApnIdEnabled(id)) {
- return new LinkProperties(mLinkProperties);
+ // TODO - remove this cdma-only hack and support multiple DCs.
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
+ return dcac.getLinkPropertiesSync();
} else {
return new LinkProperties();
}
@@ -596,33 +689,14 @@ public abstract class DataConnectionTracker extends Handler {
protected LinkCapabilities getLinkCapabilities(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
- return new LinkCapabilities(mLinkCapabilities);
+ // TODO - remove this cdma-only hack and support multiple DCs.
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
+ return dcac.getLinkCapabilitiesSync();
} else {
return new LinkCapabilities();
}
}
- /**
- * Return the LinkProperties for the connection.
- *
- * @param connection
- * @return a copy of the LinkProperties, is never null.
- */
- protected LinkProperties getLinkProperties(DataConnection connection) {
- return connection.getLinkProperties();
- }
-
- /**
- * A capability is an Integer/String pair, the capabilities
- * are defined in the class LinkSocket#Key.
- *
- * @param connection
- * @return a copy of this connections capabilities, may be empty but never null.
- */
- protected LinkCapabilities getLinkCapabilities(DataConnection connection) {
- return connection.getLinkCapabilities();
- }
-
// tell all active apns of the current condition
protected void notifyDataConnection(String reason) {
for (int id = 0; id < APN_NUM_TYPES; id++) {
@@ -681,36 +755,12 @@ public abstract class DataConnectionTracker extends Handler {
notifyOffApnsOfAvailability(reason, isDataPossible());
}
- /**
- * The only circumstances under which we report that data connectivity is not
- * possible are
- * <ul>
- * <li>Data is disallowed (roaming, power state, voice call, etc).</li>
- * <li>The current data state is {@code DISCONNECTED} for a reason other than
- * having explicitly disabled connectivity. In other words, data is not available
- * because the phone is out of coverage or some like reason.</li>
- * </ul>
- * @return {@code true} if data connectivity is possible, {@code false} otherwise.
- */
- protected boolean isDataPossible() {
- boolean dataAllowed = isDataAllowed();
- boolean anyDataEnabled = getAnyDataEnabled();
- boolean possible = (dataAllowed
- && !(anyDataEnabled && (mState == State.FAILED || mState == State.IDLE)));
- if (!possible && DBG) {
- log("isDataPossible() " + possible + ", dataAllowed=" + dataAllowed +
- " anyDataEnabled=" + anyDataEnabled + " dataState=" + mState);
- }
- return possible;
- }
-
- protected abstract boolean isDataAllowed();
-
public boolean isApnTypeEnabled(String apnType) {
if (apnType == null) {
- apnType = getActiveApnType();
+ return false;
+ } else {
+ return isApnIdEnabled(apnTypeToId(apnType));
}
- return isApnIdEnabled(apnTypeToId(apnType));
}
protected synchronized boolean isApnIdEnabled(int id) {
@@ -790,7 +840,7 @@ public abstract class DataConnectionTracker extends Handler {
}
}
- private void setEnabled(int id, boolean enable) {
+ protected void setEnabled(int id, boolean enable) {
if (DBG) {
log("setEnabled(" + id + ", " + enable + ") with old state = " + dataEnabled[id]
+ " and enabledCount = " + enabledCount);
@@ -801,7 +851,7 @@ public abstract class DataConnectionTracker extends Handler {
sendMessage(msg);
}
- protected synchronized void onEnableApn(int apnId, int enabled) {
+ protected void onEnableApn(int apnId, int enabled) {
if (DBG) {
log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) +
", enabled=" + enabled + ", dataEnabled = " + dataEnabled[apnId] +
@@ -809,9 +859,11 @@ public abstract class DataConnectionTracker extends Handler {
isApnTypeActive(apnIdToType(apnId)));
}
if (enabled == ENABLED) {
- if (!dataEnabled[apnId]) {
- dataEnabled[apnId] = true;
- enabledCount++;
+ synchronized (this) {
+ if (!dataEnabled[apnId]) {
+ dataEnabled[apnId] = true;
+ enabledCount++;
+ }
}
String type = apnIdToType(apnId);
if (!isApnTypeActive(type)) {
@@ -822,12 +874,16 @@ public abstract class DataConnectionTracker extends Handler {
}
} else {
// disable
- if (dataEnabled[apnId]) {
- dataEnabled[apnId] = false;
- enabledCount--;
- if (enabledCount == 0) {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ boolean didDisable = false;
+ synchronized (this) {
+ if (dataEnabled[apnId]) {
+ dataEnabled[apnId] = false;
+ enabledCount--;
+ didDisable = true;
}
+ }
+ if (didDisable && enabledCount == 0) {
+ onCleanUpConnection(true, apnId, Phone.REASON_DATA_DISABLED);
// send the disconnect msg manually, since the normal route wont send
// it (it's not enabled)
@@ -855,6 +911,22 @@ public abstract class DataConnectionTracker extends Handler {
}
/**
+ * Called when EVENT_RESET_DONE is received so goto
+ * IDLE state and send notifications to those interested.
+ *
+ * TODO - currently unused. Needs to be hooked into DataConnection cleanup
+ * TODO - needs to pass some notion of which connection is reset..
+ */
+ protected void onResetDone(AsyncResult ar) {
+ if (DBG) log("EVENT_RESET_DONE");
+ String reason = null;
+ if (ar.userObj instanceof String) {
+ reason = (String) ar.userObj;
+ }
+ gotoIdleAndNotifyDataConnection(reason);
+ }
+
+ /**
* Prevent mobile data connections from being established, or once again
* allow mobile data connections. If the state toggles, then either tear
* down or set up data, as appropriate to match the new state.
@@ -881,17 +953,25 @@ public abstract class DataConnectionTracker extends Handler {
}
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ cleanUpAllConnections(null);
}
}
}
}
- public synchronized boolean getDataEnabled() {
- return mDataEnabled;
+ public void cleanUpAllConnections(String cause) {
+ Message msg = obtainMessage(EVENT_CLEAN_UP_ALL_CONNECTIONS);
+ msg.obj = cause;
+ sendMessage(msg);
+ }
+
+ public boolean isAnyActiveDataConnections() {
+ // TODO: Remember if there are any connected or
+ // loop asking each DC/APN?
+ return true;
}
protected void onSetDataEnabled(boolean enable) {
@@ -904,12 +984,22 @@ public abstract class DataConnectionTracker extends Handler {
Settings.Secure.MOBILE_DATA, enable ? 1 : 0);
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
- mRetryMgr.resetRetryCount();
+ resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
- onCleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+ onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
}
}
}
}
+
+ protected void onSetDependencyMet(String apnType, boolean met) {
+ }
+
+
+ protected void resetAllRetryCounts() {
+ for (DataConnection dc : mDataConnections.values()) {
+ dc.resetRetryCount();
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 83db3d1..910905a 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -114,8 +114,8 @@ public class DefaultPhoneNotifier implements PhoneNotifier {
try {
mRegistry.notifyDataConnection(
convertDataState(state),
- sender.isDataConnectivityPossible(), reason,
- sender.getActiveApnHost(),
+ sender.isDataConnectivityPossible(apnType), reason,
+ sender.getActiveApnHost(apnType),
apnType,
linkProperties,
linkCapabilities,
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 3c4bb12..da233cc 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -259,5 +259,15 @@ interface ITelephony {
* Return true if an ICC card is present
*/
boolean hasIccCard();
+
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
+ * or {@link PHone#LTE_ON_CDMA_TRUE}
+ */
+ int getLteOnCdmaMode();
}
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index e270ce9..5d8fc78 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -18,16 +18,28 @@ 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.Power;
+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.SIMRecords;
+
+import android.os.SystemProperties;
+
+import com.android.internal.R;
/**
* {@hide}
@@ -84,6 +96,9 @@ public abstract class IccCard {
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;
/*
UNKNOWN is a transient state, for example, after uesr inputs ICC pin under
@@ -102,6 +117,11 @@ public abstract class IccCard {
public boolean isPinLocked() {
return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED));
}
+
+ public boolean iccCardExist() {
+ return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)
+ || (this == NETWORK_LOCKED) || (this == READY));
+ }
}
public State getState() {
@@ -137,11 +157,14 @@ public abstract class IccCard {
public IccCard(PhoneBase phone, String logTag, Boolean dbg) {
mPhone = phone;
+ mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_STATUS_CHANGED, null);
mLogTag = logTag;
mDbg = dbg;
}
- abstract public void dispose();
+ public void dispose() {
+ mPhone.mCM.unregisterForIccStatusChanged(mHandler);
+ }
protected void finalize() {
if(mDbg) Log.d(mLogTag, "IccCard finalized");
@@ -393,6 +416,8 @@ public abstract class IccCard {
boolean transitionedIntoPinLocked;
boolean transitionedIntoAbsent;
boolean transitionedIntoNetworkLocked;
+ boolean isIccCardRemoved;
+ boolean isIccCardAdded;
State oldState, newState;
@@ -409,23 +434,87 @@ public abstract class IccCard {
transitionedIntoAbsent = (oldState != State.ABSENT && newState == State.ABSENT);
transitionedIntoNetworkLocked = (oldState != State.NETWORK_LOCKED
&& newState == State.NETWORK_LOCKED);
+ isIccCardRemoved = (oldState != null &&
+ oldState.iccCardExist() && newState == State.ABSENT);
+ isIccCardAdded = (oldState == State.ABSENT &&
+ newState != null && newState.iccCardExist());
if (transitionedIntoPinLocked) {
- if(mDbg) log("Notify SIM pin or puk locked.");
+ if (mDbg) log("Notify SIM pin or puk locked.");
mPinLockedRegistrants.notifyRegistrants();
broadcastIccStateChangedIntent(INTENT_VALUE_ICC_LOCKED,
(newState == State.PIN_REQUIRED) ?
INTENT_VALUE_LOCKED_ON_PIN : INTENT_VALUE_LOCKED_ON_PUK);
} else if (transitionedIntoAbsent) {
- if(mDbg) log("Notify SIM missing.");
+ if (mDbg) log("Notify SIM missing.");
mAbsentRegistrants.notifyRegistrants();
broadcastIccStateChangedIntent(INTENT_VALUE_ICC_ABSENT, null);
} else if (transitionedIntoNetworkLocked) {
- if(mDbg) log("Notify SIM network locked.");
+ if (mDbg) log("Notify SIM network locked.");
mNetworkLockedRegistrants.notifyRegistrants();
broadcastIccStateChangedIntent(INTENT_VALUE_ICC_LOCKED,
INTENT_VALUE_LOCKED_NETWORK);
}
+
+ if (isIccCardRemoved) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
+ } else if (isIccCardAdded) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
+ }
+
+
+
+ /*
+ * TODO: We need to try to remove this, maybe if the RIL sends up a RIL_UNSOL_SIM_REFRESH?
+ */
+ if (oldState != State.READY && newState == State.READY &&
+ mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+ if (mPhone.mIccRecords instanceof SIMRecords) {
+ ((SIMRecords)mPhone.mIccRecords).onSimReady();
+ }
+ }
+
+ }
+
+ 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();
}
/**
@@ -588,6 +677,16 @@ public abstract class IccCard {
= ar.exception;
((Message)ar.userObj).sendToTarget();
break;
+ case EVENT_ICC_STATUS_CHANGED:
+ Log.d(mLogTag, "Received Event EVENT_ICC_STATUS_CHANGED");
+ mPhone.mCM.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
+ break;
+ case EVENT_CARD_REMOVED:
+ onIccSwap(false);
+ break;
+ case EVENT_CARD_ADDED:
+ onIccSwap(true);
+ break;
default:
Log.e(mLogTag, "[IccCard] Unknown Event " + msg.what);
}
@@ -612,61 +711,99 @@ public abstract class IccCard {
currentRadioState == RadioState.SIM_NOT_READY ||
currentRadioState == RadioState.RUIM_NOT_READY ||
currentRadioState == RadioState.NV_NOT_READY ||
- currentRadioState == RadioState.NV_READY) {
+ (currentRadioState == RadioState.NV_READY &&
+ (mPhone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE))) {
return IccCard.State.NOT_READY;
}
if( currentRadioState == RadioState.SIM_LOCKED_OR_ABSENT ||
currentRadioState == RadioState.SIM_READY ||
currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
- currentRadioState == RadioState.RUIM_READY) {
+ currentRadioState == RadioState.RUIM_READY ||
+ (currentRadioState == RadioState.NV_READY &&
+ (mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE))) {
- int index;
+ State csimState =
+ getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
+ State usimState =
+ getAppState(mIccCardStatus.getGsmUmtsSubscriptionAppIndex());
+
+ if(mDbg) log("USIM=" + usimState + " CSIM=" + csimState);
+
+ if (mPhone.getLteOnCdmaMode() == Phone.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 (currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
currentRadioState == RadioState.RUIM_READY) {
- index = mIccCardStatus.getCdmaSubscriptionAppIndex();
- }
- else {
- index = mIccCardStatus.getGsmUmtsSubscriptionAppIndex();
+ return csimState;
}
+ return usimState;
+ }
- IccCardApplication app;
- if (index >= 0 && index < IccCardStatus.CARD_MAX_APPS) {
- app = mIccCardStatus.getApplication(index);
- } else {
- Log.e(mLogTag, "[IccCard] Invalid Subscription Application index:" + index);
- return IccCard.State.ABSENT;
- }
+ return IccCard.State.ABSENT;
+ }
- if (app == null) {
- Log.e(mLogTag, "[IccCard] Subscription Application in not present");
- return IccCard.State.ABSENT;
- }
+ private 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 IccCard.State.ABSENT;
+ }
- // check if PIN required
- if (app.app_state.isPinRequired()) {
- return IccCard.State.PIN_REQUIRED;
- }
- if (app.app_state.isPukRequired()) {
- return IccCard.State.PUK_REQUIRED;
- }
- if (app.app_state.isSubscriptionPersoEnabled()) {
- return IccCard.State.NETWORK_LOCKED;
- }
- if (app.app_state.isAppReady()) {
- return IccCard.State.READY;
- }
- if (app.app_state.isAppNotReady()) {
- return IccCard.State.NOT_READY;
- }
- return IccCard.State.NOT_READY;
+ if (app == null) {
+ Log.e(mLogTag, "[IccCard] Subscription Application in not present");
+ return IccCard.State.ABSENT;
}
- return IccCard.State.ABSENT;
+ // check if PIN required
+ if (app.app_state.isPinRequired()) {
+ return IccCard.State.PIN_REQUIRED;
+ }
+ if (app.app_state.isPukRequired()) {
+ return IccCard.State.PUK_REQUIRED;
+ }
+ if (app.app_state.isSubscriptionPersoEnabled()) {
+ return IccCard.State.NETWORK_LOCKED;
+ }
+ if (app.app_state.isAppReady()) {
+ return IccCard.State.READY;
+ }
+ if (app.app_state.isAppNotReady()) {
+ return IccCard.State.NOT_READY;
+ }
+ return IccCard.State.NOT_READY;
}
+ private State getConsolidatedState(State left, State right, State preferredState) {
+ // Check if either is absent.
+ if (right == IccCard.State.ABSENT) return left;
+ if (left == IccCard.State.ABSENT) return right;
+
+ // Only if both are ready, return ready
+ if ((left == IccCard.State.READY) && (right == IccCard.State.READY)) {
+ return State.READY;
+ }
+
+ // Case one is ready, but the other is not.
+ if (((right == IccCard.State.NOT_READY) && (left == IccCard.State.READY)) ||
+ ((left == IccCard.State.NOT_READY) && (right == IccCard.State.READY))) {
+ return IccCard.State.NOT_READY;
+ }
+
+ // At this point, the other state is assumed to be one of locked state
+ if (right == IccCard.State.NOT_READY) return left;
+ if (left == IccCard.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;
diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java
index 9f60a6c..4cf21ee 100644
--- a/telephony/java/com/android/internal/telephony/IccCardApplication.java
+++ b/telephony/java/com/android/internal/telephony/IccCardApplication.java
@@ -28,7 +28,8 @@ public class IccCardApplication {
APPTYPE_SIM,
APPTYPE_USIM,
APPTYPE_RUIM,
- APPTYPE_CSIM
+ APPTYPE_CSIM,
+ APPTYPE_ISIM
};
public enum AppState{
@@ -115,6 +116,7 @@ public class IccCardApplication {
case 2: newType = AppType.APPTYPE_USIM; break;
case 3: newType = AppType.APPTYPE_RUIM; break;
case 4: newType = AppType.APPTYPE_CSIM; break;
+ case 5: newType = AppType.APPTYPE_ISIM; break;
default:
throw new RuntimeException(
"Unrecognized RIL_AppType: " +type);
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index b12d2d4..b40f945 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -58,6 +58,13 @@ public interface IccConstants {
static final int EF_CST = 0x6f32;
static final int EF_RUIM_SPN =0x6F41;
+ //ISIM access
+ static final int EF_IMPU = 0x6f04;
+ static final int EF_IMPI = 0x6f02;
+ static final int EF_DOMAIN = 0x6f03;
+ static final int EF_IST = 0x6f07;
+ static final int EF_PCSCF = 0x6f09;
+
// SMS record length from TS 51.011 10.5.3
static public final int SMS_RECORD_LENGTH = 176;
@@ -67,4 +74,7 @@ public interface IccConstants {
static final String DF_GRAPHICS = "5F50";
static final String DF_GSM = "7F20";
static final String DF_CDMA = "7F25";
+
+ //ISIM access
+ static final String DF_ADFISIM = "7FFF";
}
diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java
index b8d9e3c..10a3b69 100644
--- a/telephony/java/com/android/internal/telephony/IccRecords.java
+++ b/telephony/java/com/android/internal/telephony/IccRecords.java
@@ -21,9 +21,6 @@ import android.os.Handler;
import android.os.Message;
import android.os.Registrant;
import android.os.RegistrantList;
-import android.util.Log;
-
-import java.util.ArrayList;
/**
* {@hide}
@@ -79,6 +76,11 @@ public abstract class IccRecords extends Handler implements IccConstants {
this.phone = p;
}
+ /**
+ * Call when the IccRecords object is no longer going to be used.
+ */
+ public abstract void dispose();
+
protected abstract void onRadioOffOrNotAvailable();
//***** Public Methods
@@ -99,6 +101,17 @@ public abstract class IccRecords extends Handler implements IccConstants {
recordsLoadedRegistrants.remove(h);
}
+ /**
+ * Get the International Mobile Subscriber ID (IMSI) on a SIM
+ * for GSM, UMTS and like networks. Default is null if IMSI is
+ * not supported or unavailable.
+ *
+ * @return null if SIM is not yet ready or unavailable
+ */
+ public String getIMSI() {
+ return null;
+ }
+
public String getMsisdnNumber() {
return msisdn;
}
@@ -220,6 +233,7 @@ public abstract class IccRecords extends Handler implements IccConstants {
}
//***** Overridden from Handler
+ @Override
public abstract void handleMessage(Message msg);
protected abstract void onRecordLoaded();
@@ -232,8 +246,51 @@ public abstract class IccRecords extends Handler implements IccConstants {
* and TS 51.011 10.3.11 for details.
*
* If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
+ * Generally used for GSM/UMTS and the like SIMs.
+ */
+ public abstract int getDisplayRule(String plmn);
+
+ /**
+ * Return true if "Restriction of menu options for manual PLMN selection"
+ * bit is set or EF_CSP data is unavailable, return false otherwise.
+ * Generally used for GSM/UMTS and the like SIMs.
+ */
+ public boolean isCspPlmnEnabled() {
+ return false;
+ }
+
+ /**
+ * Returns the 5 or 6 digit MCC/MNC of the operator that
+ * provided the SIM card. Returns null of SIM is not yet ready
+ * or is not valid for the type of IccCard. Generally used for
+ * GSM/UMTS and the like SIMS
+ */
+ public String getOperatorNumeric() {
+ return null;
+ }
+
+ /**
+ * Get the current Voice call forwarding flag for GSM/UMTS and the like SIMs
+ *
+ * @return true if enabled
*/
- protected abstract int getDisplayRule(String plmn);
+ public boolean getVoiceCallForwardingFlag() {
+ return false;
+ }
+ /**
+ * Set the voice call forwarding flag for GSM/UMTS and the like SIMs
+ *
+ * @param line to enable/disable
+ * @param enable
+ */
+ public void setVoiceCallForwardingFlag(int line, boolean enable) {
+ }
+
+ /**
+ * Write string to log file
+ *
+ * @param s is the string to write
+ */
protected abstract void log(String s);
}
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index acb86d4..48c5318 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -21,6 +21,7 @@ import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemProperties;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
@@ -125,6 +126,12 @@ public interface Phone {
static final String APN_TYPE_DUN = "dun";
/** APN type for HiPri traffic */
static final String APN_TYPE_HIPRI = "hipri";
+ /** APN type for FOTA */
+ static final String APN_TYPE_FOTA = "fota";
+ /** APN type for IMS */
+ static final String APN_TYPE_IMS = "ims";
+ /** APN type for CBS */
+ static final String APN_TYPE_CBS = "cbs";
// "Features" accessible through the connectivity manager
static final String FEATURE_ENABLE_MMS = "enableMMS";
@@ -132,6 +139,9 @@ public interface Phone {
static final String FEATURE_ENABLE_DUN = "enableDUN";
static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
static final String FEATURE_ENABLE_DUN_ALWAYS = "enableDUNAlways";
+ static final String FEATURE_ENABLE_FOTA = "enableFOTA";
+ static final String FEATURE_ENABLE_IMS = "enableIMS";
+ static final String FEATURE_ENABLE_CBS = "enableCBS";
/**
* Return codes for <code>enableApnType()</code>
@@ -140,6 +150,7 @@ public interface Phone {
static final int APN_REQUEST_STARTED = 1;
static final int APN_TYPE_NOT_AVAILABLE = 2;
static final int APN_REQUEST_FAILED = 3;
+ static final int APN_ALREADY_INACTIVE = 4;
/**
@@ -149,8 +160,8 @@ public interface Phone {
static final String REASON_ROAMING_OFF = "roamingOff";
static final String REASON_DATA_DISABLED = "dataDisabled";
static final String REASON_DATA_ENABLED = "dataEnabled";
- static final String REASON_GPRS_ATTACHED = "gprsAttached";
- static final String REASON_GPRS_DETACHED = "gprsDetached";
+ static final String REASON_DATA_ATTACHED = "dataAttached";
+ static final String REASON_DATA_DETACHED = "dataDetached";
static final String REASON_CDMA_DATA_ATTACHED = "cdmaDataAttached";
static final String REASON_CDMA_DATA_DETACHED = "cdmaDataDetached";
static final String REASON_APN_CHANGED = "apnChanged";
@@ -164,6 +175,10 @@ public interface Phone {
static final String REASON_PS_RESTRICT_ENABLED = "psRestrictEnabled";
static final String REASON_PS_RESTRICT_DISABLED = "psRestrictDisabled";
static final String REASON_SIM_LOADED = "simLoaded";
+ static final String REASON_NW_TYPE_CHANGED = "nwTypeChanged";
+ static final String REASON_DATA_DEPENDENCY_MET = "dependencyMet";
+ static final String REASON_DATA_DEPENDENCY_UNMET = "dependencyUnmet";
+ static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged";
// Used for band mode selection methods
static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
@@ -180,6 +195,11 @@ public interface Phone {
static final int PHONE_TYPE_CDMA = RILConstants.CDMA_PHONE;
static final int PHONE_TYPE_SIP = RILConstants.SIP_PHONE;
+ // Modes for LTE_ON_CDMA
+ static final int LTE_ON_CDMA_UNKNOWN = RILConstants.LTE_ON_CDMA_UNKNOWN;
+ static final int LTE_ON_CDMA_FALSE = RILConstants.LTE_ON_CDMA_FALSE;
+ static final int LTE_ON_CDMA_TRUE = RILConstants.LTE_ON_CDMA_TRUE;
+
// Used for preferred network type
// Note NT_* substitute RILConstants.NETWORK_MODE_* above the Phone
int NT_MODE_WCDMA_PREF = RILConstants.NETWORK_MODE_WCDMA_PREF;
@@ -193,6 +213,7 @@ public interface Phone {
int NT_MODE_EVDO_NO_CDMA = RILConstants.NETWORK_MODE_EVDO_NO_CDMA;
int NT_MODE_GLOBAL = RILConstants.NETWORK_MODE_GLOBAL;
+ int NT_MODE_LTE_ONLY = RILConstants.NETWORK_MODE_LTE_ONLY;
int PREFERRED_NT_MODE = RILConstants.PREFERRED_NETWORK_MODE;
@@ -319,7 +340,7 @@ public interface Phone {
* Returns string for the active APN host.
* @return type as a string or null if none.
*/
- String getActiveApnHost();
+ String getActiveApnHost(String apnType);
/**
* Return the LinkProperties for the named apn or null if not available
@@ -1236,13 +1257,6 @@ public interface Phone {
void getDataCallList(Message response);
/**
- * Get current mutiple data connection status
- *
- * @return list of data connections
- */
- List<DataConnection> getCurrentDataConnectionList();
-
- /**
* Update the ServiceState CellLocation for current network registration.
*/
void updateServiceLocation();
@@ -1361,6 +1375,11 @@ public interface Phone {
boolean isDataConnectivityPossible();
/**
+ * Report on whether data connectivity is allowed for an APN.
+ */
+ boolean isDataConnectivityPossible(String apnType);
+
+ /**
* Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
*/
String getDeviceId();
@@ -1686,6 +1705,14 @@ public interface Phone {
*/
void unsetOnEcbModeExitResponse(Handler h);
+ /**
+ * Return if the current radio is LTE on CDMA. This
+ * is a tri-state return value as for a period of time
+ * the mode may be unknown.
+ *
+ * @return {@link #LTE_ON_CDMA_UNKNOWN}, {@link #LTE_ON_CDMA_FALSE} or {@link #LTE_ON_CDMA_TRUE}
+ */
+ public int getLteOnCdmaMode();
/**
* TODO: Adding a function for each property is not good.
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 54341b1..b77e134 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -38,6 +38,8 @@ import android.util.Log;
import com.android.internal.R;
import com.android.internal.telephony.test.SimulatedRadioControl;
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.gsm.SimCard;
import java.util.Locale;
@@ -110,12 +112,15 @@ public abstract class PhoneBase extends Handler implements Phone {
public CommandsInterface mCM;
protected IccFileHandler mIccFileHandler;
boolean mDnsCheckDisabled = false;
- public DataConnectionTracker mDataConnection;
+ public DataConnectionTracker mDataConnectionTracker;
boolean mDoesRilSendMultipleCallRing;
int mCallRingContinueToken = 0;
int mCallRingDelay;
public boolean mIsTheCurrentActivePhone = true;
boolean mIsVoiceCapable = true;
+ public IccRecords mIccRecords;
+ public IccCard mIccCard;
+ public SMSDispatcher mSMS;
/**
* Set a system property, unless we're in unit test mode
@@ -237,7 +242,8 @@ public abstract class PhoneBase extends Handler implements Phone {
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
mCM.unSetOnCallRing(this);
- mDataConnection.onCleanUpConnection(false, REASON_RADIO_TURNED_OFF);
+ // Must cleanup all connectionS and needs to use sendMessage!
+ mDataConnectionTracker.cleanUpAllConnections(null);
mIsTheCurrentActivePhone = false;
}
}
@@ -662,6 +668,45 @@ public abstract class PhoneBase extends Handler implements Phone {
}
/**
+ * Retrieves the ServiceStateTracker of the phone instance.
+ */
+ public ServiceStateTracker getServiceStateTracker() {
+ return null;
+ }
+
+ /**
+ * Get call tracker
+ */
+ public CallTracker getCallTracker() {
+ return null;
+ }
+
+ @Override
+ public IccCard getIccCard() {
+ return mIccCard;
+ }
+
+ @Override
+ public String getIccSerialNumber() {
+ return mIccRecords.iccid;
+ }
+
+ @Override
+ public boolean getIccRecordsLoaded() {
+ return mIccRecords.getRecordsLoaded();
+ }
+
+ @Override
+ public boolean getMessageWaitingIndicator() {
+ return mIccRecords.getVoiceMessageWaiting();
+ }
+
+ @Override
+ public boolean getCallForwardingIndicator() {
+ return mIccRecords.getVoiceCallForwardingFlag();
+ }
+
+ /**
* Query the status of the CDMA roaming preference
*/
public void queryCdmaRoamingPreference(Message response) {
@@ -954,31 +999,36 @@ public abstract class PhoneBase extends Handler implements Phone {
}
public String[] getActiveApnTypes() {
- return mDataConnection.getActiveApnTypes();
+ return mDataConnectionTracker.getActiveApnTypes();
}
- public String getActiveApnHost() {
- return mDataConnection.getActiveApnString();
+ public String getActiveApnHost(String apnType) {
+ return mDataConnectionTracker.getActiveApnString(apnType);
}
public LinkProperties getLinkProperties(String apnType) {
- return mDataConnection.getLinkProperties(apnType);
+ return mDataConnectionTracker.getLinkProperties(apnType);
}
public LinkCapabilities getLinkCapabilities(String apnType) {
- return mDataConnection.getLinkCapabilities(apnType);
+ return mDataConnectionTracker.getLinkCapabilities(apnType);
}
public int enableApnType(String type) {
- return mDataConnection.enableApnType(type);
+ return mDataConnectionTracker.enableApnType(type);
}
public int disableApnType(String type) {
- return mDataConnection.disableApnType(type);
+ return mDataConnectionTracker.disableApnType(type);
}
public boolean isDataConnectivityPossible() {
- return ((mDataConnection != null) && (mDataConnection.isDataPossible()));
+ return ((mDataConnectionTracker != null) && (mDataConnectionTracker.isDataPossible()));
+ }
+
+ public boolean isDataConnectivityPossible(String apnType) {
+ return ((mDataConnectionTracker != null) &&
+ (mDataConnectionTracker.isDataPossible(apnType)));
}
/**
@@ -1008,7 +1058,7 @@ public abstract class PhoneBase extends Handler implements Phone {
break;
}
- mDataConnection.setState(dcState);
+ mDataConnectionTracker.setState(dcState);
notifyDataConnection(null, Phone.APN_TYPE_DEFAULT);
}
@@ -1080,4 +1130,22 @@ public abstract class PhoneBase extends Handler implements Phone {
Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
"called, GSMPhone inactive.");
}
+
+ // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone.
+ public void notifyCallForwardingIndicator() {
+ // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone.
+ Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+ }
+
+ public void notifyDataConnectionFailed(String reason, String apnType) {
+ mNotifier.notifyDataConnectionFailed(this, reason, apnType);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getLteOnCdmaMode() {
+ return mCM.getLteOnCdmaMode();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 2e391cb..6a2d7c9 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -21,8 +21,10 @@ import android.net.LocalServerSocket;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
+import android.os.SystemProperties;
import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.cdma.CDMALTEPhone;
import com.android.internal.telephony.gsm.GSMPhone;
import com.android.internal.telephony.sip.SipPhone;
import com.android.internal.telephony.sip.SipPhoneFactory;
@@ -34,6 +36,7 @@ public class PhoneFactory {
static final String LOG_TAG = "PHONE";
static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
static final int SOCKET_OPEN_MAX_RETRY = 3;
+
//***** Class Variables
static private Phone sProxyPhone = null;
@@ -101,10 +104,31 @@ public class PhoneFactory {
Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode);
Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
- //Get preferredNetworkMode from Settings.System
- int cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, preferredCdmaSubscription);
- Log.i(LOG_TAG, "Cdma Subscription set to " + Integer.toString(cdmaSubscription));
+ // Get cdmaSubscription
+ // TODO: Change when the ril will provides a way to know at runtime
+ // the configuration, bug 4202572. And the ril issues the
+ // RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED, bug 4295439.
+ int cdmaSubscription;
+ int lteOnCdma = BaseCommands.getLteOnCdmaModeStatic();
+ switch (lteOnCdma) {
+ case Phone.LTE_ON_CDMA_FALSE:
+ cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_NV;
+ Log.i(LOG_TAG, "lteOnCdma is 0 use SUBSCRIPTION_FROM_NV");
+ break;
+ case Phone.LTE_ON_CDMA_TRUE:
+ cdmaSubscription = RILConstants.SUBSCRIPTION_FROM_RUIM;
+ Log.i(LOG_TAG, "lteOnCdma is 1 use SUBSCRIPTION_FROM_RUIM");
+ break;
+ case Phone.LTE_ON_CDMA_UNKNOWN:
+ default:
+ //Get cdmaSubscription mode from Settings.System
+ cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION,
+ preferredCdmaSubscription);
+ Log.i(LOG_TAG, "lteOnCdma not set, using PREFERRED_CDMA_SUBSCRIPTION");
+ break;
+ }
+ Log.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription);
//reads the system properties and makes commandsinterface
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
@@ -115,9 +139,19 @@ public class PhoneFactory {
sProxyPhone = new PhoneProxy(new GSMPhone(context,
sCommandsInterface, sPhoneNotifier));
} else if (phoneType == Phone.PHONE_TYPE_CDMA) {
- Log.i(LOG_TAG, "Creating CDMAPhone");
- sProxyPhone = new PhoneProxy(new CDMAPhone(context,
- sCommandsInterface, sPhoneNotifier));
+ switch (BaseCommands.getLteOnCdmaModeStatic()) {
+ case Phone.LTE_ON_CDMA_TRUE:
+ Log.i(LOG_TAG, "Creating CDMALTEPhone");
+ sProxyPhone = new PhoneProxy(new CDMALTEPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ break;
+ case Phone.LTE_ON_CDMA_FALSE:
+ default:
+ Log.i(LOG_TAG, "Creating CDMAPhone");
+ sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+ sCommandsInterface, sPhoneNotifier));
+ break;
+ }
}
sMadeDefaults = true;
@@ -145,8 +179,18 @@ public class PhoneFactory {
case RILConstants.NETWORK_MODE_GSM_UMTS:
return Phone.PHONE_TYPE_GSM;
+ // Use CDMA Phone for the global mode including CDMA
case RILConstants.NETWORK_MODE_GLOBAL:
+ case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO:
+ case RILConstants.NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA:
return Phone.PHONE_TYPE_CDMA;
+
+ case RILConstants.NETWORK_MODE_LTE_ONLY:
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ return Phone.PHONE_TYPE_CDMA;
+ } else {
+ return Phone.PHONE_TYPE_GSM;
+ }
default:
return Phone.PHONE_TYPE_GSM;
}
@@ -165,10 +209,22 @@ public class PhoneFactory {
}
public static Phone getCdmaPhone() {
+ Phone phone;
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
- Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
- return phone;
+ switch (BaseCommands.getLteOnCdmaModeStatic()) {
+ case Phone.LTE_ON_CDMA_TRUE: {
+ phone = new CDMALTEPhone(sContext, sCommandsInterface, sPhoneNotifier);
+ break;
+ }
+ case Phone.LTE_ON_CDMA_FALSE:
+ case Phone.LTE_ON_CDMA_UNKNOWN:
+ default: {
+ phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
+ break;
+ }
+ }
}
+ return phone;
}
public static Phone getGsmPhone() {
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 15b23bb..68f1c5f 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -208,8 +208,8 @@ public class PhoneProxy extends Handler implements Phone {
return mActivePhone.getActiveApnTypes();
}
- public String getActiveApnHost() {
- return mActivePhone.getActiveApnHost();
+ public String getActiveApnHost(String apnType) {
+ return mActivePhone.getActiveApnHost(apnType);
}
public LinkProperties getLinkProperties(String apnType) {
@@ -593,10 +593,6 @@ public class PhoneProxy extends Handler implements Phone {
mActivePhone.getDataCallList(response);
}
- public List<DataConnection> getCurrentDataConnectionList() {
- return mActivePhone.getCurrentDataConnectionList();
- }
-
public void updateServiceLocation() {
mActivePhone.updateServiceLocation();
}
@@ -661,6 +657,10 @@ public class PhoneProxy extends Handler implements Phone {
return mActivePhone.isDataConnectivityPossible();
}
+ public boolean isDataConnectivityPossible(String apnType) {
+ return mActivePhone.isDataConnectivityPossible(apnType);
+ }
+
public String getDeviceId() {
return mActivePhone.getDeviceId();
}
@@ -741,6 +741,10 @@ public class PhoneProxy extends Handler implements Phone {
return mActivePhone.getCdmaEriIconMode();
}
+ public Phone getActivePhone() {
+ return mActivePhone;
+ }
+
public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete){
mActivePhone.sendBurstDtmf(dtmfString, on, off, onComplete);
}
@@ -832,4 +836,12 @@ public class PhoneProxy extends Handler implements Phone {
public boolean isCspPlmnEnabled() {
return mActivePhone.isCspPlmnEnabled();
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getLteOnCdmaMode() {
+ return mActivePhone.getLteOnCdmaMode();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 804ace4..f9f641c 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -207,9 +207,8 @@ class RILRequest {
*/
public final class RIL extends BaseCommands implements CommandsInterface {
static final String LOG_TAG = "RILJ";
- private static final boolean DBG = false;
- static final boolean RILJ_LOGD = Config.LOGD;
- static final boolean RILJ_LOGV = DBG ? Config.LOGD : Config.LOGV;
+ static final boolean RILJ_LOGD = true;
+ static final boolean RILJ_LOGV = false; // STOP SHIP if true
/**
* Wake lock timeout should be longer than the longest timeout in
@@ -236,9 +235,6 @@ public final class RIL extends BaseCommands implements CommandsInterface {
// WAKE_LOCK_TIMEOUT occurs.
int mRequestMessagesWaiting;
- // Is this the first radio state change?
- private boolean mInitialRadioStateChange = true;
-
//I'd rather this be LinkedList or something
ArrayList<RILRequest> mRequestsList = new ArrayList<RILRequest>();
@@ -606,41 +602,25 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}} catch (Throwable tr) {
Log.e(LOG_TAG,"Uncaught exception", tr);
}
+
+ /* We're disconnected so we don't know the ril version */
+ notifyRegistrantsRilConnectionChanged(-1);
}
}
//***** Constructors
- public
- RIL(Context context) {
- this(context, RILConstants.PREFERRED_NETWORK_MODE,
- RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
- }
public RIL(Context context, int networkMode, int cdmaSubscription) {
super(context);
+ if (RILJ_LOGD) {
+ riljLog("RIL(context, networkMode=" + networkMode +
+ " cdmaSubscription=" + cdmaSubscription + ")");
+ }
mCdmaSubscription = cdmaSubscription;
mNetworkMode = networkMode;
- //At startup mPhoneType is first set from networkMode
- switch(networkMode) {
- case RILConstants.NETWORK_MODE_WCDMA_PREF:
- case RILConstants.NETWORK_MODE_GSM_ONLY:
- case RILConstants.NETWORK_MODE_WCDMA_ONLY:
- case RILConstants.NETWORK_MODE_GSM_UMTS:
- mPhoneType = RILConstants.GSM_PHONE;
- break;
- case RILConstants.NETWORK_MODE_CDMA:
- case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
- case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
- mPhoneType = RILConstants.CDMA_PHONE;
- break;
- case RILConstants.NETWORK_MODE_GLOBAL:
- mPhoneType = RILConstants.CDMA_PHONE;
- break;
- default:
- mPhoneType = RILConstants.CDMA_PHONE;
- }
+ mPhoneType = RILConstants.NO_PHONE;
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
@@ -904,10 +884,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
getIMSI(Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result);
- if (RILJ_LOGD) riljLog(rr.serialString() +
- "> getIMSI:RIL_REQUEST_GET_IMSI " +
- RIL_REQUEST_GET_IMSI +
- " " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@@ -1385,37 +1362,15 @@ public final class RIL extends BaseCommands implements CommandsInterface {
public void
setRadioPower(boolean on, Message result) {
- //if radio is OFF set preferred NW type and cmda subscription
- if(mInitialRadioStateChange) {
- synchronized (mStateMonitor) {
- if (!mState.isOn()) {
- RILRequest rrPnt = RILRequest.obtain(
- RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, null);
-
- rrPnt.mp.writeInt(1);
- rrPnt.mp.writeInt(mNetworkMode);
- if (RILJ_LOGD) riljLog(rrPnt.serialString() + "> "
- + requestToString(rrPnt.mRequest) + " : " + mNetworkMode);
-
- send(rrPnt);
-
- RILRequest rrCs = RILRequest.obtain(
- RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, null);
- rrCs.mp.writeInt(1);
- rrCs.mp.writeInt(mCdmaSubscription);
- if (RILJ_LOGD) riljLog(rrCs.serialString() + "> "
- + requestToString(rrCs.mRequest) + " : " + mCdmaSubscription);
- send(rrCs);
- }
- }
- }
- RILRequest rr
- = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
+ RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
rr.mp.writeInt(1);
rr.mp.writeInt(on ? 1 : 0);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ if (RILJ_LOGD) {
+ riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ + (on ? " on" : " off"));
+ }
send(rr);
}
@@ -2053,25 +2008,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
private void switchToRadioState(RadioState newState) {
-
- if (mInitialRadioStateChange) {
- if (newState.isOn()) {
- /* If this is our first notification, make sure the radio
- * is powered off. This gets the radio into a known state,
- * since it's possible for the phone proc to have restarted
- * (eg, if it or the runtime crashed) without the RIL
- * and/or radio knowing.
- */
- if (RILJ_LOGD) Log.d(LOG_TAG, "Radio ON @ init; reset to OFF");
- setRadioPower(false, null);
- } else {
- if (DBG) Log.d(LOG_TAG, "Radio OFF @ init");
- setRadioState(newState);
- }
- mInitialRadioStateChange = false;
- } else {
- setRadioState(newState);
- }
+ setRadioState(newState);
}
/**
@@ -2361,7 +2298,10 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_REQUEST_GET_IMSI:
case RIL_REQUEST_GET_IMEI:
case RIL_REQUEST_GET_IMEISV:
- return "";
+ if (!RILJ_LOGV) {
+ // If not versbose logging just return and don't display IMSI and IMEI, IMEISV
+ return "";
+ }
}
StringBuilder sb;
@@ -2458,9 +2398,10 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break;
case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break;
- case RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED: ret = responseInts(p); break;
+ case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: ret = responseInts(p); break;
case RIL_UNSOl_CDMA_PRL_CHANGED: ret = responseInts(p); break;
case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
+ case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;
default:
throw new RuntimeException("Unrecognized unsol response: " + response);
@@ -2639,8 +2580,8 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_UNSOL_SIM_REFRESH:
if (RILJ_LOGD) unsljLogRet(response, ret);
- if (mIccRefreshRegistrant != null) {
- mIccRefreshRegistrant.notifyRegistrant(
+ if (mIccRefreshRegistrants != null) {
+ mIccRefreshRegistrants.notifyRegistrants(
new AsyncResult (null, ret, null));
}
break;
@@ -2765,7 +2706,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
}
break;
- case RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED:
+ case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
if (RILJ_LOGD) unsljLogRet(response, ret);
if (mCdmaSubscriptionChangedRegistrants != null) {
@@ -2791,6 +2732,30 @@ public final class RIL extends BaseCommands implements CommandsInterface {
new AsyncResult (null, null, null));
}
break;
+
+ case RIL_UNSOL_RIL_CONNECTED: {
+ if (RILJ_LOGD) unsljLogRet(response, ret);
+
+ // Initial conditions
+ setRadioPower(false, null);
+ setPreferredNetworkType(mNetworkMode, null);
+ setCdmaSubscriptionSource(mCdmaSubscription, null);
+ notifyRegistrantsRilConnectionChanged(((int[])ret)[0]);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Notifiy all registrants that the ril has connected or disconnected.
+ *
+ * @param rilVer is the version of the ril or -1 if disconnected.
+ */
+ private void notifyRegistrantsRilConnectionChanged(int rilVer) {
+ mRilVersion = rilVer;
+ if (mRilConnectedRegistrants != null) {
+ mRilConnectedRegistrants.notifyRegistrants(
+ new AsyncResult (null, new Integer(rilVer), null));
}
}
@@ -2924,7 +2889,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
String s = p.readString();
- if (RILJ_LOGD) riljLog("< iccIO: "
+ if (RILJ_LOGV) riljLog("< iccIO: "
+ " 0x" + Integer.toHexString(sw1)
+ " 0x" + Integer.toHexString(sw2) + " "
+ s);
@@ -3038,7 +3003,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
dataCall.active = p.readInt();
dataCall.type = p.readString();
String addresses = p.readString();
- if (TextUtils.isEmpty(addresses)) {
+ if (!TextUtils.isEmpty(addresses)) {
dataCall.addresses = addresses.split(" ");
}
} else {
@@ -3047,7 +3012,8 @@ public final class RIL extends BaseCommands implements CommandsInterface {
dataCall.active = p.readInt();
dataCall.type = p.readString();
dataCall.ifname = p.readString();
- if (TextUtils.isEmpty(dataCall.ifname)) {
+ if ((dataCall.status == DataConnection.FailCause.NONE.getErrorCode()) &&
+ TextUtils.isEmpty(dataCall.ifname)) {
throw new RuntimeException("getDataCallState, no ifname");
}
String addresses = p.readString();
@@ -3086,7 +3052,7 @@ public final class RIL extends BaseCommands implements CommandsInterface {
responseSetupDataCall(Parcel p) {
int ver = p.readInt();
int num = p.readInt();
- if (RILJ_LOGD) riljLog("responseSetupDataCall ver=" + ver + " num=" + num);
+ if (RILJ_LOGV) riljLog("responseSetupDataCall ver=" + ver + " num=" + num);
DataCallState dataCall;
@@ -3525,9 +3491,10 @@ public final class RIL extends BaseCommands implements CommandsInterface {
case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW";
case RIL_UNSOL_RINGBACK_TONE: return "UNSOL_RINGBACK_TONG";
case RIL_UNSOL_RESEND_INCALL_MUTE: return "UNSOL_RESEND_INCALL_MUTE";
- case RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED: return "CDMA_SUBSCRIPTION_CHANGED";
+ case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: return "CDMA_SUBSCRIPTION_SOURCE_CHANGED";
case RIL_UNSOl_CDMA_PRL_CHANGED: return "UNSOL_CDMA_PRL_CHANGED";
case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
+ case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED";
default: return "<unknown reponse>";
}
}
@@ -3576,7 +3543,9 @@ public final class RIL extends BaseCommands implements CommandsInterface {
send(rr);
}
- public void setPhoneType(int phoneType) { //Set by CDMAPhone and GSMPhone constructor
+ @Override
+ public void setPhoneType(int phoneType) { // Called by CDMAPhone and GSMPhone constructor
+ if (RILJ_LOGD) riljLog("setPhoneType=" + phoneType + " old value=" + mPhoneType);
mPhoneType = phoneType;
}
@@ -3627,12 +3596,12 @@ public final class RIL extends BaseCommands implements CommandsInterface {
/**
* {@inheritDoc}
*/
- public void getCdmaSubscriptionSource(int cdmaSubscription , Message response) {
+ @Override
+ public void getCdmaSubscriptionSource(Message response) {
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, response);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
- + " : " + cdmaSubscription);
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index cdf1977..93fc9ce 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -66,6 +66,11 @@ public interface RILConstants {
int NETWORK_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
int NETWORK_MODE_GLOBAL = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
AVAILABLE Application Settings menu*/
+ int NETWORK_MODE_LTE_CDMA_EVDO = 8; /* LTE, CDMA and EvDo */
+ int NETWORK_MODE_LTE_GSM_WCDMA = 9; /* LTE, GSM/WCDMA */
+ int NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA = 10; /* LTE, CDMA, EvDo, GSM/WCDMA */
+ int NETWORK_MODE_LTE_ONLY = 11; /* LTE Only mode. */
+
int PREFERRED_NETWORK_MODE = NETWORK_MODE_WCDMA_PREF;
/* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
@@ -81,6 +86,10 @@ public interface RILConstants {
int CDMA_PHONE = 2;
int SIP_PHONE = 3;
+ int LTE_ON_CDMA_UNKNOWN = -1;
+ int LTE_ON_CDMA_FALSE = 0;
+ int LTE_ON_CDMA_TRUE = 1;
+
int CDM_TTY_MODE_DISABLED = 0;
int CDM_TTY_MODE_ENABLED = 1;
@@ -104,6 +113,7 @@ public interface RILConstants {
/* Deactivate data call reasons */
int DEACTIVATE_REASON_NONE = 0;
int DEACTIVATE_REASON_RADIO_OFF = 1;
+ int DEACTIVATE_REASON_PDP_RESET = 2;
/*
cat include/telephony/ril.h | \
@@ -138,10 +148,12 @@ cat include/telephony/ril.h | \
int RIL_RESTRICTED_STATE_PS_ALL = 0x10;
/** Data profile for RIL_REQUEST_SETUP_DATA_CALL */
- static final int DATA_PROFILE_DEFAULT = 0;
- static final int DATA_PROFILE_TETHERED = 1;
- static final int DATA_PROFILE_OEM_BASE = 1000;
-
+ public static final int DATA_PROFILE_DEFAULT = 0;
+ public static final int DATA_PROFILE_TETHERED = 1;
+ public static final int DATA_PROFILE_IMS = 2;
+ public static final int DATA_PROFILE_FOTA = 3;
+ public static final int DATA_PROFILE_CBS = 4;
+ public static final int DATA_PROFILE_OEM_BASE = 1000;
int RIL_REQUEST_GET_SIM_STATUS = 1;
int RIL_REQUEST_ENTER_SIM_PIN = 2;
@@ -279,7 +291,8 @@ cat include/telephony/ril.h | \
int RIL_UNSOL_OEM_HOOK_RAW = 1028;
int RIL_UNSOL_RINGBACK_TONE = 1029;
int RIL_UNSOL_RESEND_INCALL_MUTE = 1030;
- int RIL_UNSOL_CDMA_SUBSCRIPTION_CHANGED = 1031;
+ int RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1031;
int RIL_UNSOl_CDMA_PRL_CHANGED = 1032;
int RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE = 1033;
+ int RIL_UNSOL_RIL_CONNECTED = 1034;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/RestrictedState.java b/telephony/java/com/android/internal/telephony/RestrictedState.java
index 3f7d5d7..ad2b88d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RestrictedState.java
+++ b/telephony/java/com/android/internal/telephony/RestrictedState.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
import android.telephony.ServiceState;
diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java
index b1049a2..29bd104 100644
--- a/telephony/java/com/android/internal/telephony/RetryManager.java
+++ b/telephony/java/com/android/internal/telephony/RetryManager.java
@@ -308,12 +308,10 @@ public class RetryManager {
}
/**
- * Reset network re-registration indicator and clear the data-retry counter
- * and turns off retrying forever.
+ * Clear the data-retry counter
*/
public void resetRetryCount() {
mRetryCount = 0;
- mRetryForever = false;
if (DBG) log("resetRetryCount: " + mRetryCount);
}
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index befee8c..6af9b1c 100755
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -582,7 +582,7 @@ public abstract class SMSDispatcher extends Handler {
* {@link Activity#RESULT_OK} if the message has been broadcast
* to applications
*/
- protected abstract int dispatchMessage(SmsMessageBase sms);
+ public abstract int dispatchMessage(SmsMessageBase sms);
/**
@@ -916,7 +916,7 @@ public abstract class SMSDispatcher extends Handler {
* @param response
* Callback message is empty on completion
*/
- protected abstract void activateCellBroadcastSms(int activate, Message response);
+ public abstract void activateCellBroadcastSms(int activate, Message response);
/**
* Query the current configuration of cell broadcast SMS.
@@ -925,7 +925,7 @@ public abstract class SMSDispatcher extends Handler {
* Callback message contains the configuration from the modem on completion
* @see #setCellBroadcastConfig
*/
- protected abstract void getCellBroadcastSmsConfig(Message response);
+ public abstract void getCellBroadcastSmsConfig(Message response);
/**
* Configure cell broadcast SMS.
@@ -937,7 +937,7 @@ public abstract class SMSDispatcher extends Handler {
* @param response
* Callback message is empty on completion
*/
- protected abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
+ public abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
/**
* Send an acknowledge message.
@@ -1006,6 +1006,27 @@ public abstract class SMSDispatcher extends Handler {
return new SmsTracker(data, sentIntent, deliveryIntent);
}
+ public void initSipStack(boolean isObg) {
+ // This function should be overridden by the classes that support
+ // switching modes such as the CdmaSMSDispatcher.
+ // Not implemented in GsmSMSDispatcher.
+ Log.e(TAG, "Error! This function should never be executed.");
+ }
+
+ public void switchToCdma() {
+ // This function should be overridden by the classes that support
+ // switching modes such as the CdmaSMSDispatcher.
+ // Not implemented in GsmSMSDispatcher.
+ Log.e(TAG, "Error! This function should never be executed.");
+ }
+
+ public void switchToGsm() {
+ // This function should be overridden by the classes that support
+ // switching modes such as the CdmaSMSDispatcher.
+ // Not implemented in GsmSMSDispatcher.
+ Log.e(TAG, "Error! This function should never be executed.");
+ }
+
private DialogInterface.OnClickListener mListener =
new DialogInterface.OnClickListener() {
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 3f9ffc3..695805c 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -29,23 +29,6 @@ import android.telephony.SignalStrength;
*/
public abstract class ServiceStateTracker extends Handler {
- /**
- * Access technology currently in use.
- */
- protected static final int DATA_ACCESS_UNKNOWN = 0;
- protected static final int DATA_ACCESS_GPRS = 1;
- protected static final int DATA_ACCESS_EDGE = 2;
- protected static final int DATA_ACCESS_UMTS = 3;
- protected static final int DATA_ACCESS_CDMA_IS95A = 4;
- protected static final int DATA_ACCESS_CDMA_IS95B = 5;
- protected static final int DATA_ACCESS_CDMA_1xRTT = 6;
- protected static final int DATA_ACCESS_CDMA_EvDo_0 = 7;
- protected static final int DATA_ACCESS_CDMA_EvDo_A = 8;
- protected static final int DATA_ACCESS_HSDPA = 9;
- protected static final int DATA_ACCESS_HSUPA = 10;
- protected static final int DATA_ACCESS_HSPA = 11;
- protected static final int DATA_ACCESS_CDMA_EvDo_B = 12;
-
protected CommandsInterface cm;
public ServiceState ss;
@@ -53,6 +36,9 @@ public abstract class ServiceStateTracker extends Handler {
public SignalStrength mSignalStrength;
+ // TODO - this should not be public
+ public RestrictedState mRestrictedState = new RestrictedState();
+
/* The otaspMode passed to PhoneStateListener#onOtaspChanged */
static public final int OTASP_UNINITIALIZED = 0;
static public final int OTASP_UNKNOWN = 1;
@@ -74,9 +60,17 @@ public abstract class ServiceStateTracker extends Handler {
*/
protected boolean dontPollSignalStrength = false;
- protected RegistrantList networkAttachedRegistrants = new RegistrantList();
- protected RegistrantList roamingOnRegistrants = new RegistrantList();
- protected RegistrantList roamingOffRegistrants = new RegistrantList();
+ protected RegistrantList mRoamingOnRegistrants = new RegistrantList();
+ protected RegistrantList mRoamingOffRegistrants = new RegistrantList();
+ protected RegistrantList mAttachedRegistrants = new RegistrantList();
+ protected RegistrantList mDetachedRegistrants = new RegistrantList();
+ protected RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
+ protected RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
+ protected RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
+
+ /* Radio power off pending flag and tag counter */
+ private boolean mPendingRadioPowerOffAfterDataOff = false;
+ private int mPendingRadioPowerOffAfterDataOffTag = 0;
protected static final boolean DBG = true;
@@ -86,8 +80,6 @@ public abstract class ServiceStateTracker extends Handler {
/** Waiting period before recheck gprs and voice registration. */
public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
- public static final int DATA_STATE_POLL_SLEEP_MS = 100;
-
/** GSM events */
protected static final int EVENT_RADIO_STATE_CHANGED = 1;
protected static final int EVENT_NETWORK_STATE_CHANGED = 2;
@@ -163,7 +155,6 @@ public abstract class ServiceStateTracker extends Handler {
protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
public ServiceStateTracker() {
-
}
public boolean getDesiredPowerState() {
@@ -180,7 +171,7 @@ public abstract class ServiceStateTracker extends Handler {
*/
public void registerForRoamingOn(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
- roamingOnRegistrants.add(r);
+ mRoamingOnRegistrants.add(r);
if (ss.getRoaming()) {
r.notifyRegistrant();
@@ -188,7 +179,7 @@ public abstract class ServiceStateTracker extends Handler {
}
public void unregisterForRoamingOn(Handler h) {
- roamingOnRegistrants.remove(h);
+ mRoamingOnRegistrants.remove(h);
}
/**
@@ -201,7 +192,7 @@ public abstract class ServiceStateTracker extends Handler {
*/
public void registerForRoamingOff(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
- roamingOffRegistrants.add(r);
+ mRoamingOffRegistrants.add(r);
if (!ss.getRoaming()) {
r.notifyRegistrant();
@@ -209,7 +200,7 @@ public abstract class ServiceStateTracker extends Handler {
}
public void unregisterForRoamingOff(Handler h) {
- roamingOffRegistrants.remove(h);
+ mRoamingOffRegistrants.remove(h);
}
/**
@@ -272,20 +263,183 @@ public abstract class ServiceStateTracker extends Handler {
}
}
- public abstract void handleMessage(Message msg);
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case EVENT_SET_RADIO_POWER_OFF:
+ synchronized(this) {
+ if (mPendingRadioPowerOffAfterDataOff &&
+ (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) {
+ if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
+ hangupAndPowerOff();
+ mPendingRadioPowerOffAfterDataOffTag += 1;
+ mPendingRadioPowerOffAfterDataOff = false;
+ } else {
+ log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 +
+ "!= tag=" + mPendingRadioPowerOffAfterDataOffTag);
+ }
+ }
+ break;
+
+ default:
+ log("Unhandled message with number: " + msg.what);
+ break;
+ }
+ }
protected abstract Phone getPhone();
protected abstract void handlePollStateResult(int what, AsyncResult ar);
protected abstract void updateSpnDisplay();
protected abstract void setPowerStateToDesired();
protected abstract void log(String s);
+ protected abstract void loge(String s);
+
+ public abstract int getCurrentDataConnectionState();
+ public abstract boolean isConcurrentVoiceAndDataAllowed();
+
+ /**
+ * Registration point for transition into DataConnection attached.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForDataConnectionAttached(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mAttachedRegistrants.add(r);
+
+ if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
+ r.notifyRegistrant();
+ }
+ }
+ public void unregisterForDataConnectionAttached(Handler h) {
+ mAttachedRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition into DataConnection detached.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForDataConnectionDetached(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mDetachedRegistrants.add(r);
+
+ if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
+ r.notifyRegistrant();
+ }
+ }
+ public void unregisterForDataConnectionDetached(Handler h) {
+ mDetachedRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition into network attached.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj in Message.obj
+ */
+ public void registerForNetworkAttached(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+
+ mNetworkAttachedRegistrants.add(r);
+ if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+ r.notifyRegistrant();
+ }
+ }
+ public void unregisterForNetworkAttached(Handler h) {
+ mNetworkAttachedRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition into packet service restricted zone.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mPsRestrictEnabledRegistrants.add(r);
+
+ if (mRestrictedState.isPsRestricted()) {
+ r.notifyRegistrant();
+ }
+ }
+
+ public void unregisterForPsRestrictedEnabled(Handler h) {
+ mPsRestrictEnabledRegistrants.remove(h);
+ }
+
+ /**
+ * Registration point for transition out of packet service restricted zone.
+ * @param h handler to notify
+ * @param what what code of message when delivered
+ * @param obj placed in Message.obj
+ */
+ public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
+ Registrant r = new Registrant(h, what, obj);
+ mPsRestrictDisabledRegistrants.add(r);
+
+ if (mRestrictedState.isPsRestricted()) {
+ r.notifyRegistrant();
+ }
+ }
+
+ public void unregisterForPsRestrictedDisabled(Handler h) {
+ mPsRestrictDisabledRegistrants.remove(h);
+ }
/**
* Clean up existing voice and data connection then turn off radio power.
*
* Hang up the existing voice calls to decrease call drop rate.
*/
- protected abstract void powerOffRadioSafely();
+ public void powerOffRadioSafely(DataConnectionTracker dcTracker) {
+ synchronized (this) {
+ if (!mPendingRadioPowerOffAfterDataOff) {
+ if (dcTracker.isAnyActiveDataConnections()) {
+ dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
+ Message msg = Message.obtain(this);
+ msg.what = EVENT_SET_RADIO_POWER_OFF;
+ msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
+ if (sendMessageDelayed(msg, 30000)) {
+ if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
+ mPendingRadioPowerOffAfterDataOff = true;
+ } else {
+ log("Cannot send delayed Msg, turn off radio right away.");
+ hangupAndPowerOff();
+ }
+ } else {
+ dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
+ if (DBG) log("Data disconnected, turn off radio right away.");
+ hangupAndPowerOff();
+ }
+ }
+ }
+ }
+
+ /**
+ * process the pending request to turn radio off after data is disconnected
+ *
+ * return true if there is pending request to process; false otherwise.
+ */
+ public boolean processPendingRadioPowerOffAfterDataOff() {
+ synchronized(this) {
+ if (mPendingRadioPowerOffAfterDataOff) {
+ if (DBG) log("Process pending request to turn radio off.");
+ mPendingRadioPowerOffAfterDataOffTag += 1;
+ hangupAndPowerOff();
+ mPendingRadioPowerOffAfterDataOff = false;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Hang up all voice call and turn off radio. Implemented by derived class.
+ */
+ protected abstract void hangupAndPowerOff();
/** Cancel a pending (if any) pollState() operation */
protected void cancelPollState() {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index e6189be..4309309 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -72,6 +72,13 @@ public interface TelephonyProperties
*/
static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country";
+ /**
+ * The contents of this property is the value of the kernel command line
+ * product_type variable that corresponds to a product that supports LTE on CDMA.
+ * {@see BaseCommands#getLteOnCdmaMode()}
+ */
+ static final String PROPERTY_LTE_ON_CDMA_PRODUCT_TYPE = "telephony.lteOnCdmaProductType";
+
static final String CURRENT_ACTIVE_PHONE = "gsm.current.phone-type";
//****** SIM Card
diff --git a/telephony/java/com/android/internal/telephony/cat/CatService.java b/telephony/java/com/android/internal/telephony/cat/CatService.java
index 1e23e34..df47350 100644
--- a/telephony/java/com/android/internal/telephony/cat/CatService.java
+++ b/telephony/java/com/android/internal/telephony/cat/CatService.java
@@ -33,6 +33,7 @@ import com.android.internal.telephony.IccRecords;
import android.util.Config;
import java.io.ByteArrayOutputStream;
+import java.util.Locale;
/**
* Enumeration for representing the tag value of COMPREHENSION-TLV objects. If
@@ -118,6 +119,8 @@ public class CatService extends Handler implements AppInterface {
private static IccRecords mIccRecords;
// Service members.
+ // Protects singleton instance lazy initialization.
+ private static final Object sInstanceLock = new Object();
private static CatService sInstance;
private CommandsInterface mCmdIf;
private Context mContext;
@@ -133,6 +136,7 @@ public class CatService extends Handler implements AppInterface {
static final int MSG_ID_CALL_SETUP = 4;
static final int MSG_ID_REFRESH = 5;
static final int MSG_ID_RESPONSE = 6;
+ static final int MSG_ID_SIM_READY = 7;
static final int MSG_ID_RIL_MSG_DECODED = 10;
@@ -170,9 +174,11 @@ public class CatService extends Handler implements AppInterface {
mIccRecords = ir;
// Register for SIM ready event.
+ mCmdIf.registerForSIMReady(this, MSG_ID_SIM_READY, null);
+ mCmdIf.registerForRUIMReady(this, MSG_ID_SIM_READY, null);
+ mCmdIf.registerForNVReady(this, MSG_ID_SIM_READY, null);
mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
- mCmdIf.reportStkServiceIsRunning(null);
CatLog.d(this, "Is running");
}
@@ -269,8 +275,20 @@ public class CatService extends Handler implements AppInterface {
sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
break;
case PROVIDE_LOCAL_INFORMATION:
- sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
- return;
+ ResponseData resp;
+ switch (cmdParams.cmdDet.commandQualifier) {
+ case CommandParamsFactory.DTTZ_SETTING:
+ resp = new DTTZResponseData(null);
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
+ break;
+ case CommandParamsFactory.LANGUAGE_SETTING:
+ resp = new LanguageResponseData(Locale.getDefault().getLanguage());
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
+ break;
+ default:
+ sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
+ return;
+ }
case LAUNCH_BROWSER:
case SELECT_ITEM:
case GET_INPUT:
@@ -373,25 +391,30 @@ public class CatService extends Handler implements AppInterface {
private void encodeOptionalTags(CommandDetails cmdDet,
ResultCode resultCode, Input cmdInput, ByteArrayOutputStream buf) {
- switch (AppInterface.CommandType.fromInt(cmdDet.typeOfCommand)) {
- case GET_INKEY:
- // ETSI TS 102 384,27.22.4.2.8.4.2.
- // If it is a response for GET_INKEY command and the response timeout
- // occured, then add DURATION TLV for variable timeout case.
- if ((resultCode.value() == ResultCode.NO_RESPONSE_FROM_USER.value()) &&
- (cmdInput != null) && (cmdInput.duration != null)) {
- getInKeyResponse(buf, cmdInput);
- }
- break;
- case PROVIDE_LOCAL_INFORMATION:
- if ((cmdDet.commandQualifier == CommandParamsFactory.LANGUAGE_SETTING) &&
- (resultCode.value() == ResultCode.OK.value())) {
- getPliResponse(buf);
- }
- break;
- default:
- CatLog.d(this, "encodeOptionalTags() Unsupported Cmd:" + cmdDet.typeOfCommand);
- break;
+ CommandType cmdType = AppInterface.CommandType.fromInt(cmdDet.typeOfCommand);
+ if (cmdType != null) {
+ switch (cmdType) {
+ case GET_INKEY:
+ // ETSI TS 102 384,27.22.4.2.8.4.2.
+ // If it is a response for GET_INKEY command and the response timeout
+ // occured, then add DURATION TLV for variable timeout case.
+ if ((resultCode.value() == ResultCode.NO_RESPONSE_FROM_USER.value()) &&
+ (cmdInput != null) && (cmdInput.duration != null)) {
+ getInKeyResponse(buf, cmdInput);
+ }
+ break;
+ case PROVIDE_LOCAL_INFORMATION:
+ if ((cmdDet.commandQualifier == CommandParamsFactory.LANGUAGE_SETTING) &&
+ (resultCode.value() == ResultCode.OK.value())) {
+ getPliResponse(buf);
+ }
+ break;
+ default:
+ CatLog.d(this, "encodeOptionalTags() Unsupported Cmd:" + cmdDet.typeOfCommand);
+ break;
+ }
+ } else {
+ CatLog.d(this, "encodeOptionalTags() bad Cmd:" + cmdDet.typeOfCommand);
}
}
@@ -515,26 +538,28 @@ public class CatService extends Handler implements AppInterface {
*/
public static CatService getInstance(CommandsInterface ci, IccRecords ir,
Context context, IccFileHandler fh, IccCard ic) {
- if (sInstance == null) {
- if (ci == null || ir == null || context == null || fh == null
- || ic == null) {
- return null;
+ synchronized (sInstanceLock) {
+ if (sInstance == null) {
+ if (ci == 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);
+ CatLog.d(sInstance, "NEW sInstance");
+ } else if ((ir != null) && (mIccRecords != ir)) {
+ CatLog.d(sInstance, "Reinitialize the Service with SIMRecords");
+ mIccRecords = ir;
+
+ // re-Register for SIM ready event.
+ mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
+ CatLog.d(sInstance, "sr changed reinitialize and return current sInstance");
+ } else {
+ CatLog.d(sInstance, "Return current sInstance");
}
- HandlerThread thread = new HandlerThread("Cat Telephony service");
- thread.start();
- sInstance = new CatService(ci, ir, context, fh, ic);
- CatLog.d(sInstance, "NEW sInstance");
- } else if ((ir != null) && (mIccRecords != ir)) {
- CatLog.d(sInstance, "Reinitialize the Service with SIMRecords");
- mIccRecords = ir;
-
- // re-Register for SIM ready event.
- mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
- CatLog.d(sInstance, "sr changed reinitialize and return current sInstance");
- } else {
- CatLog.d(sInstance, "Return current sInstance");
+ return sInstance;
}
- return sInstance;
}
/**
@@ -579,6 +604,10 @@ public class CatService extends Handler implements AppInterface {
case MSG_ID_RESPONSE:
handleCmdResponse((CatResponseMessage) msg.obj);
break;
+ case MSG_ID_SIM_READY:
+ CatLog.d(this, "SIM ready. Reporting STK service running now...");
+ mCmdIf.reportStkServiceIsRunning(null);
+ break;
default:
throw new AssertionError("Unrecognized CAT command: " + msg.what);
}
diff --git a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
index 12204a0..686fe46 100644
--- a/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
+++ b/telephony/java/com/android/internal/telephony/cat/CommandParamsFactory.java
@@ -53,6 +53,7 @@ class CommandParamsFactory extends Handler {
static final int REFRESH_UICC_RESET = 0x04;
// Command Qualifier values for PLI command
+ static final int DTTZ_SETTING = 0x03;
static final int LANGUAGE_SETTING = 0x04;
static synchronized CommandParamsFactory getInstance(RilMessageDecoder caller,
@@ -883,6 +884,10 @@ class CommandParamsFactory extends Handler {
throws ResultException {
CatLog.d(this, "process ProvideLocalInfo");
switch (cmdDet.commandQualifier) {
+ case DTTZ_SETTING:
+ CatLog.d(this, "PLI [DTTZ_SETTING]");
+ mCmdParams = new CommandParams(cmdDet);
+ break;
case LANGUAGE_SETTING:
CatLog.d(this, "PLI [LANGUAGE_SETTING]");
mCmdParams = new CommandParams(cmdDet);
diff --git a/telephony/java/com/android/internal/telephony/cat/ResponseData.java b/telephony/java/com/android/internal/telephony/cat/ResponseData.java
index 677d66b..4846a3e 100644
--- a/telephony/java/com/android/internal/telephony/cat/ResponseData.java
+++ b/telephony/java/com/android/internal/telephony/cat/ResponseData.java
@@ -18,6 +18,8 @@ package com.android.internal.telephony.cat;
import com.android.internal.telephony.EncodeException;
import com.android.internal.telephony.GsmAlphabet;
+import java.util.Calendar;
+import com.android.internal.telephony.cat.AppInterface.CommandType;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
@@ -147,4 +149,109 @@ class GetInkeyInputResponseData extends ResponseData {
}
}
+// For "PROVIDE LOCAL INFORMATION" command.
+// See TS 31.111 section 6.4.15/ETSI TS 102 223
+// TS 31.124 section 27.22.4.15 for test spec
+class LanguageResponseData extends ResponseData {
+ private String lang;
+
+ public LanguageResponseData(String lang) {
+ super();
+ this.lang = lang;
+ }
+
+ @Override
+ public void format(ByteArrayOutputStream buf) {
+ if (buf == null) {
+ return;
+ }
+
+ // Text string object
+ int tag = 0x80 | ComprehensionTlvTag.LANGUAGE.value();
+ buf.write(tag); // tag
+
+ byte[] data;
+
+ if (lang != null && lang.length() > 0) {
+ data = GsmAlphabet.stringToGsm8BitPacked(lang);
+ }
+ else {
+ data = new byte[0];
+ }
+
+ buf.write(data.length);
+
+ for (byte b : data) {
+ buf.write(b);
+ }
+ }
+}
+
+// For "PROVIDE LOCAL INFORMATION" command.
+// See TS 31.111 section 6.4.15/ETSI TS 102 223
+// TS 31.124 section 27.22.4.15 for test spec
+class DTTZResponseData extends ResponseData {
+ private Calendar calendar;
+
+ public DTTZResponseData(Calendar cal) {
+ super();
+ calendar = cal;
+ }
+
+ @Override
+ public void format(ByteArrayOutputStream buf) {
+ if (buf == null) {
+ return;
+ }
+
+ // DTTZ object
+ int tag = 0x80 | CommandType.PROVIDE_LOCAL_INFORMATION.value();
+ buf.write(tag); // tag
+
+ byte[] data = new byte[8];
+ byte btmp; // temp variable
+
+ data[0] = 0x07; // Write length of DTTZ data
+
+ if (calendar == null) {
+ calendar = Calendar.getInstance();
+ }
+ // Fill year byte
+ btmp = (byte) (calendar.get(java.util.Calendar.YEAR) % 100);
+ data[1] = (byte) (btmp / 10);
+ data[1] += (byte) ((btmp % 10) << 4);
+
+ // Fill month byte
+ btmp = (byte) (calendar.get(java.util.Calendar.MONTH) + 1);
+ data[2] = (byte) (btmp / 10);
+ data[2] += (byte) ((btmp % 10) << 4);
+
+ // Fill day byte
+ btmp = (byte) (calendar.get(java.util.Calendar.DATE));
+ data[3] = (byte) (btmp / 10);
+ data[3] += (byte) ((btmp % 10) << 4);
+
+ // Fill hour byte
+ btmp = (byte) (calendar.get(java.util.Calendar.HOUR_OF_DAY));
+ data[4] = (byte) (btmp / 10);
+ data[4] += (byte) ((btmp % 10) << 4);
+
+ // Fill minute byte
+ btmp = (byte) (calendar.get(java.util.Calendar.MINUTE));
+ data[5] = (byte) (btmp / 10);
+ data[5] += (byte) ((btmp % 10) << 4);
+
+ // Fill second byte
+ btmp = (byte) (calendar.get(java.util.Calendar.SECOND));
+ data[6] = (byte) (btmp / 10);
+ data[6] += (byte) ((btmp % 10) << 4);
+
+ // No time zone info
+ data[7] = (byte) 0xFF;
+
+ for (byte b : data) {
+ buf.write(b);
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java b/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java
index a197c9a..2a1f508 100644
--- a/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java
+++ b/telephony/java/com/android/internal/telephony/cat/RilMessageDecoder.java
@@ -20,15 +20,15 @@ import com.android.internal.telephony.IccFileHandler;
import com.android.internal.telephony.IccUtils;
import android.os.Handler;
-import com.android.internal.util.HierarchicalState;
-import com.android.internal.util.HierarchicalStateMachine;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import android.os.Message;
/**
* Class used for queuing raw ril messages, decoding them into CommanParams
* objects and sending the result back to the CAT Service.
*/
-class RilMessageDecoder extends HierarchicalStateMachine {
+class RilMessageDecoder extends StateMachine {
// constants
private static final int CMD_START = 1;
@@ -101,8 +101,9 @@ class RilMessageDecoder extends HierarchicalStateMachine {
mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh);
}
- private class StateStart extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class StateStart extends State {
+ @Override
+ public boolean processMessage(Message msg) {
if (msg.what == CMD_START) {
if (decodeMessageParams((RilMessage)msg.obj)) {
transitionTo(mStateCmdParamsReady);
@@ -115,8 +116,9 @@ class RilMessageDecoder extends HierarchicalStateMachine {
}
}
- private class StateCmdParamsReady extends HierarchicalState {
- @Override protected boolean processMessage(Message msg) {
+ private class StateCmdParamsReady extends State {
+ @Override
+ public boolean processMessage(Message msg) {
if (msg.what == CMD_PARAMS_READY) {
mCurrentRilMessage.mResCode = ResultCode.fromInt(msg.arg1);
mCurrentRilMessage.mData = msg.obj;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
new file mode 100644
index 0000000..5733164
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2006 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.os.SystemProperties;
+import android.content.Context;
+import android.net.Uri;
+import android.content.Context;
+import android.provider.Telephony;
+import android.content.ContentValues;
+import android.database.SQLException;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+
+import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.gsm.SimCard;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
+
+import android.util.Log;
+
+public class CDMALTEPhone extends CDMAPhone {
+ static final String LOG_TAG = "CDMA";
+
+ private static final boolean DBG = true;
+
+ // Constructors
+ public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
+ this(context, ci, notifier, false);
+ }
+
+ public CDMALTEPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
+ boolean unitTestMode) {
+ super(context, ci, notifier, false);
+ }
+
+ @Override
+ protected void initSstIcc() {
+ mSST = new CdmaLteServiceStateTracker(this);
+ mIccRecords = new SIMRecords(this);
+ mIccCard = new SimCard(this, LOG_TAG, DBG);
+ }
+
+ @Override
+ public DataState getDataConnectionState(String apnType) {
+ // TODO: Remove instanceof if possible.
+ boolean isCdmaDataConnectionTracker = false;
+ if (mDataConnectionTracker instanceof CdmaDataConnectionTracker) {
+ log("getDataConnectionState isCdmaDataConnectionTracker");
+ isCdmaDataConnectionTracker = true;
+ } else {
+ log("getDataConnectionState NOT CdmaDataConnectionTracker");
+ }
+ DataState ret = DataState.DISCONNECTED;
+
+ if (!isCdmaDataConnectionTracker && (SystemProperties.get("adb.connected", "").length()
+ > 0)) {
+ // We're connected to an ADB host and we have USB networking
+ // turned on. No matter what the radio state is,
+ // we report data connected
+
+ ret = DataState.CONNECTED;
+ } else if (mSST == null) {
+ // Radio Technology Change is ongoning, dispose() and
+ // removeReferences() have
+ // already been called
+
+ ret = DataState.DISCONNECTED;
+ } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
+ // If we're out of service, open TCP sockets may still work
+ // but no data will flow
+ ret = DataState.DISCONNECTED;
+ } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false) {
+ ret = DataState.DISCONNECTED;
+ } else {
+ switch (mDataConnectionTracker.getState(apnType)) {
+ case FAILED:
+ case IDLE:
+ ret = DataState.DISCONNECTED;
+ break;
+
+ case CONNECTED:
+ case DISCONNECTING:
+ if (mCT.state != Phone.State.IDLE && !mSST.isConcurrentVoiceAndDataAllowed()) {
+ ret = DataState.SUSPENDED;
+ } else {
+ ret = DataState.CONNECTED;
+ }
+ break;
+
+ case INITING:
+ case CONNECTING:
+ case SCANNING:
+ ret = DataState.CONNECTING;
+ break;
+ }
+ }
+
+ log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
+ return ret;
+ }
+
+ public boolean updateCurrentCarrierInProvider() {
+ if (mIccRecords != null) {
+ try {
+ Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
+ ContentValues map = new ContentValues();
+ map.put(Telephony.Carriers.NUMERIC, mIccRecords.getOperatorNumeric());
+ log("updateCurrentCarrierInProvider insert uri=" + uri);
+ mContext.getContentResolver().insert(uri, map);
+ return true;
+ } catch (SQLException e) {
+ Log.e(LOG_TAG, "[CDMALTEPhone] Can't store current operator ret false", e);
+ }
+ } else {
+ log("updateCurrentCarrierInProvider mIccRecords == null ret false");
+ }
+ return false;
+ }
+
+ @Override
+ protected void log(String s) {
+ if (DBG)
+ Log.d(LOG_TAG, "[CDMALTEPhone] " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 74adebd..c85f7d8 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -49,6 +49,7 @@ import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.IccRecords;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccException;
@@ -66,6 +67,7 @@ import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.UUSInfo;
+import com.android.internal.telephony.CallTracker;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
@@ -97,10 +99,7 @@ public class CDMAPhone extends PhoneBase {
// Instance Variables
CdmaCallTracker mCT;
- CdmaSMSDispatcher mSMS;
CdmaServiceStateTracker mSST;
- RuimRecords mRuimRecords;
- RuimCard mRuimCard;
ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>();
RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
RuimSmsInterfaceManager mRuimSmsInterfaceManager;
@@ -141,34 +140,43 @@ public class CDMAPhone extends PhoneBase {
// Constructors
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
- this(context,ci,notifier, false);
+ super(notifier, context, ci, false);
+ initSstIcc();
+ init(context, notifier);
}
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
super(notifier, context, ci, unitTestMode);
+ initSstIcc();
+ init(context, notifier);
+ }
+
+ protected void initSstIcc() {
+ mSST = new CdmaServiceStateTracker(this);
+ mIccRecords = new RuimRecords(this);
+ mIccCard = new RuimCard(this, LOG_TAG, DBG);
+ }
+ protected void init(Context context, PhoneNotifier notifier) {
mCM.setPhoneType(Phone.PHONE_TYPE_CDMA);
mCT = new CdmaCallTracker(this);
- mSST = new CdmaServiceStateTracker (this);
mSMS = new CdmaSMSDispatcher(this);
mIccFileHandler = new RuimFileHandler(this);
- mRuimRecords = new RuimRecords(this);
- mDataConnection = new CdmaDataConnectionTracker (this);
- mRuimCard = new RuimCard(this);
+ mDataConnectionTracker = new CdmaDataConnectionTracker (this);
mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
- mCcatService = CatService.getInstance(mCM, mRuimRecords, mContext,
- mIccFileHandler, mRuimCard);
+ mCcatService = CatService.getInstance(mCM, mIccRecords, mContext,
+ mIccFileHandler, mIccCard);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
- mRuimRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
+ mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(this, EVENT_RADIO_ON, null);
mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
- mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
+ mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
mCM.registerForNVReady(this, EVENT_NV_READY, null);
mCM.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
@@ -213,14 +221,15 @@ public class CDMAPhone extends PhoneBase {
public void dispose() {
synchronized(PhoneProxy.lockForRadioTechnologyChange) {
super.dispose();
+ log("dispose");
//Unregister from all former registered events
- mRuimRecords.unregisterForRecordsLoaded(this); //EVENT_RUIM_RECORDS_LOADED
+ mIccRecords.unregisterForRecordsLoaded(this); //EVENT_RUIM_RECORDS_LOADED
mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(this); //EVENT_RADIO_ON
mCM.unregisterForNVReady(this); //EVENT_NV_READY
- mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
+ mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnSuppServiceNotification(this);
removeCallbacks(mExitEcmRunnable);
@@ -228,12 +237,12 @@ public class CDMAPhone extends PhoneBase {
//Force all referenced classes to unregister their former registered events
mCT.dispose();
- mDataConnection.dispose();
+ mDataConnectionTracker.dispose();
mSST.dispose();
mSMS.dispose();
mIccFileHandler.dispose(); // instance of RuimFileHandler
- mRuimRecords.dispose();
- mRuimCard.dispose();
+ mIccRecords.dispose();
+ mIccCard.dispose();
mRuimPhoneBookInterfaceManager.dispose();
mRuimSmsInterfaceManager.dispose();
mSubInfo.dispose();
@@ -243,14 +252,15 @@ public class CDMAPhone extends PhoneBase {
}
public void removeReferences() {
+ log("removeReferences");
this.mRuimPhoneBookInterfaceManager = null;
this.mRuimSmsInterfaceManager = null;
this.mSMS = null;
this.mSubInfo = null;
- this.mRuimRecords = null;
+ this.mIccRecords = null;
this.mIccFileHandler = null;
- this.mRuimCard = null;
- this.mDataConnection = null;
+ this.mIccCard = null;
+ this.mDataConnectionTracker = null;
this.mCT = null;
this.mSST = null;
this.mEriManager = null;
@@ -270,10 +280,18 @@ public class CDMAPhone extends PhoneBase {
return mSST.ss;
}
+ public CallTracker getCallTracker() {
+ return mCT;
+ }
+
public Phone.State getState() {
return mCT.state;
}
+ public ServiceStateTracker getServiceStateTracker() {
+ return mSST;
+ }
+
public String getPhoneName() {
return "CDMA";
}
@@ -319,9 +337,9 @@ public class CDMAPhone extends PhoneBase {
public DataActivityState getDataActivityState() {
DataActivityState ret = DataActivityState.NONE;
- if (mSST.getCurrentCdmaDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
+ if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
- switch (mDataConnection.getActivity()) {
+ switch (mDataConnectionTracker.getActivity()) {
case DATAIN:
ret = DataActivityState.DATAIN;
break;
@@ -530,14 +548,6 @@ public class CDMAPhone extends PhoneBase {
Log.e(LOG_TAG, "setLine1Number: not possible in CDMA");
}
- public IccCard getIccCard() {
- return mRuimCard;
- }
-
- public String getIccSerialNumber() {
- return mRuimRecords.iccid;
- }
-
public void setCallWaiting(boolean enable, Message onComplete) {
Log.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
}
@@ -547,7 +557,7 @@ public class CDMAPhone extends PhoneBase {
}
public void setDataRoamingEnabled(boolean enable) {
- mDataConnection.setDataOnRoamingEnabled(enable);
+ mDataConnectionTracker.setDataOnRoamingEnabled(enable);
}
public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
@@ -608,15 +618,15 @@ public class CDMAPhone extends PhoneBase {
// already been called
ret = DataState.DISCONNECTED;
- } else if (mSST.getCurrentCdmaDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
+ } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
// If we're out of service, open TCP sockets may still work
// but no data will flow
ret = DataState.DISCONNECTED;
- } else if (mDataConnection.isApnTypeEnabled(apnType) == false ||
- mDataConnection.isApnTypeActive(apnType) == false) {
+ } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false ||
+ mDataConnectionTracker.isApnTypeActive(apnType) == false) {
ret = DataState.DISCONNECTED;
} else {
- switch (mDataConnection.getState()) {
+ switch (mDataConnectionTracker.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
@@ -625,7 +635,7 @@ public class CDMAPhone extends PhoneBase {
case CONNECTED:
case DISCONNECTING:
if ( mCT.state != Phone.State.IDLE
- && !mSST.isConcurrentVoiceAndData()) {
+ && !mSST.isConcurrentVoiceAndDataAllowed()) {
ret = DataState.SUSPENDED;
} else {
ret = DataState.CONNECTED;
@@ -640,6 +650,7 @@ public class CDMAPhone extends PhoneBase {
}
}
+ log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
return ret;
}
@@ -707,11 +718,7 @@ public class CDMAPhone extends PhoneBase {
}
public boolean getDataRoamingEnabled() {
- return mDataConnection.getDataOnRoamingEnabled();
- }
-
- public List<DataConnection> getCurrentDataConnectionList () {
- return mDataConnection.getAllDataConnections();
+ return mDataConnectionTracker.getDataOnRoamingEnabled();
}
public void setVoiceMailNumber(String alphaTag,
@@ -720,7 +727,7 @@ public class CDMAPhone extends PhoneBase {
Message resp;
mVmNumber = voiceMailNumber;
resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
- mRuimRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
+ mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
public String getVoiceMailNumber() {
@@ -742,7 +749,7 @@ public class CDMAPhone extends PhoneBase {
* @hide
*/
public int getVoiceMessageCount() {
- int voicemailCount = mRuimRecords.getVoiceMessageCount();
+ int voicemailCount = mIccRecords.getVoiceMessageCount();
// If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility
// that phone was power cycled and would have lost the voicemail count.
// So get the count from preferences.
@@ -767,10 +774,6 @@ public class CDMAPhone extends PhoneBase {
return ret;
}
- public boolean getIccRecordsLoaded() {
- return mRuimRecords.getRecordsLoaded();
- }
-
public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
Log.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
}
@@ -851,13 +854,13 @@ public class CDMAPhone extends PhoneBase {
/*package*/ void
updateMessageWaitingIndicator(boolean mwi) {
// this also calls notifyMessageWaitingIndicator()
- mRuimRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
+ mIccRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
}
/* This function is overloaded to send number of voicemails instead of sending true/false */
/*package*/ void
updateMessageWaitingIndicator(int mwi) {
- mRuimRecords.setVoiceMessageWaiting(1, mwi);
+ mIccRecords.setVoiceMessageWaiting(1, mwi);
}
@Override
@@ -912,7 +915,7 @@ public class CDMAPhone extends PhoneBase {
// send an Intent
sendEmergencyCallbackModeChange();
// Re-initiate data connection
- mDataConnection.setInternalDataEnabled(true);
+ mDataConnectionTracker.setInternalDataEnabled(true);
}
}
@@ -1404,6 +1407,7 @@ public class CDMAPhone extends PhoneBase {
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
ContentValues map = new ContentValues();
map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
+ log("updateCurrentCarrierInProvider insert uri=" + uri);
getContext().getContentResolver().insert(uri, map);
// Updates MCC MNC device configuration information
@@ -1416,4 +1420,9 @@ public class CDMAPhone extends PhoneBase {
}
return false;
}
+
+ protected void log(String s) {
+ if (DBG)
+ Log.d(LOG_TAG, "[CDMAPhone] " + s);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index a89f783..db19321 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -134,6 +134,10 @@ public final class CdmaCallTracker extends CallTracker {
public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
Registrant r = new Registrant(h, what, obj);
voiceCallStartedRegistrants.add(r);
+ // Notify if in call when registering
+ if (state != Phone.State.IDLE) {
+ r.notifyRegistrant(new AsyncResult(null, null, null));
+ }
}
public void unregisterForVoiceCallStarted(Handler h) {
voiceCallStartedRegistrants.remove(h);
@@ -1058,7 +1062,7 @@ public final class CdmaCallTracker extends CallTracker {
if (PhoneNumberUtils.isEmergencyNumber(dialString)) {
if (Phone.DEBUG_PHONE) log("disableDataCallInEmergencyCall");
mIsInEmergencyCall = true;
- phone.mDataConnection.setInternalDataEnabled(false);
+ phone.mDataConnectionTracker.setInternalDataEnabled(false);
}
}
@@ -1075,7 +1079,7 @@ public final class CdmaCallTracker extends CallTracker {
}
if (inEcm.compareTo("false") == 0) {
// Re-initiate data connection
- phone.mDataConnection.setInternalDataEnabled(true);
+ phone.mDataConnectionTracker.setInternalDataEnabled(true);
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index fbe455e..1a15393 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -430,7 +430,7 @@ public class CdmaConnection extends Connection {
} else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
|| serviceState == ServiceState.STATE_EMERGENCY_ONLY) {
return DisconnectCause.OUT_OF_SERVICE;
- } else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
+ } else if (phone.mCM.getNvState() != CommandsInterface.RadioState.NV_READY
&& phone.getIccCard().getState() != RuimCard.State.READY) {
return DisconnectCause.ICC_ERROR;
} else if (causeCode==CallFailCause.NORMAL_CLEARING) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 1a0dbc2..d55f346 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -20,7 +20,6 @@ import android.os.Message;
import android.util.Log;
import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
@@ -33,8 +32,8 @@ public class CdmaDataConnection extends DataConnection {
private static final String LOG_TAG = "CDMA";
// ***** Constructor
- private CdmaDataConnection(CDMAPhone phone, String name, RetryManager rm) {
- super(phone, name, rm);
+ private CdmaDataConnection(CDMAPhone phone, String name, int id, RetryManager rm) {
+ super(phone, name, id, rm);
}
/**
@@ -49,11 +48,10 @@ public class CdmaDataConnection extends DataConnection {
synchronized (mCountLock) {
mCount += 1;
}
- CdmaDataConnection cdmaDc = new CdmaDataConnection(phone,
- "CdmaDataConnection-" + mCount, rm);
+ CdmaDataConnection cdmaDc = new CdmaDataConnection(phone, "CdmaDC-" + mCount,
+ id, rm);
cdmaDc.start();
if (DBG) cdmaDc.log("Made " + cdmaDc.getName());
- cdmaDc.mId = id;
return cdmaDc;
}
@@ -68,6 +66,7 @@ public class CdmaDataConnection extends DataConnection {
protected void onConnect(ConnectionParams cp) {
if (DBG) log("CdmaDataConnection Connecting...");
+ mApn = cp.apn;
createTime = -1;
lastFailTime = -1;
lastFailCause = FailCause.NONE;
@@ -84,7 +83,7 @@ public class CdmaDataConnection extends DataConnection {
Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
msg.obj = cp;
phone.mCM.setupDataCall(
- Integer.toString(RILConstants.SETUP_DATA_TECH_CDMA),
+ Integer.toString(getRadioTechnology(RILConstants.SETUP_DATA_TECH_CDMA)),
Integer.toString(dataProfile),
null, null, null,
Integer.toString(RILConstants.SETUP_DATA_AUTH_PAP_CHAP),
@@ -99,9 +98,9 @@ public class CdmaDataConnection extends DataConnection {
@Override
protected boolean isDnsOk(String[] domainNameServers) {
- if ((NULL_IP.equals(domainNameServers[0])
+ if (NULL_IP.equals(domainNameServers[0])
&& NULL_IP.equals(domainNameServers[1])
- && !((CDMAPhone) phone).isDnsCheckDisabled())) {
+ && !phone.isDnsCheckDisabled()) {
return false;
} else {
return true;
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 8c36106..8ce221a 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -37,10 +37,12 @@ import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.Phone;
+import com.android.internal.util.AsyncChannel;
import java.util.ArrayList;
@@ -52,9 +54,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
private CDMAPhone mCdmaPhone;
- //useful for debugging
- boolean mFailNextConnect = false;
-
/** The DataConnection being setup */
private CdmaDataConnection mPendingDataConnection;
@@ -99,13 +98,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
- p.mRuimRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+ p.mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
p.mCM.registerForNVReady(this, EVENT_NV_READY, null);
p.mCM.registerForDataNetworkStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
- p.mSST.registerForCdmaDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
- p.mSST.registerForCdmaDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
+ p.mSST.registerForDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
+ p.mSST.registerForDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
@@ -118,18 +117,20 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override
public void dispose() {
+ cleanUpConnection(false, null);
+
super.dispose();
// Unregister from all events
mPhone.mCM.unregisterForAvailable(this);
mPhone.mCM.unregisterForOffOrNotAvailable(this);
- mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this);
+ mCdmaPhone.mIccRecords.unregisterForRecordsLoaded(this);
mPhone.mCM.unregisterForNVReady(this);
mPhone.mCM.unregisterForDataNetworkStateChanged(this);
mCdmaPhone.mCT.unregisterForVoiceCallEnded(this);
mCdmaPhone.mCT.unregisterForVoiceCallStarted(this);
- mCdmaPhone.mSST.unregisterForCdmaDataConnectionAttached(this);
- mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this);
+ mCdmaPhone.mSST.unregisterForDataConnectionAttached(this);
+ mCdmaPhone.mSST.unregisterForDataConnectionDetached(this);
mCdmaPhone.mSST.unregisterForRoamingOn(this);
mCdmaPhone.mSST.unregisterForRoamingOff(this);
mPhone.mCM.unregisterForCdmaOtaProvision(this);
@@ -158,6 +159,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
@Override
+ public synchronized State getState(String apnType) {
+ return mState;
+ }
+
+ @Override
protected boolean isApnTypeAvailable(String type) {
for (String s : mSupportedApnTypes) {
if (TextUtils.equals(type, s)) {
@@ -167,42 +173,18 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
return false;
}
- /**
- * The data connection is expected to be setup while device
- * 1. has ruim card or non-volatile data store
- * 2. registered to data connection service
- * 3. user doesn't explicitly disable data service
- * 4. wifi is not on
- *
- * @return false while no data connection if all above requirements are met.
- */
- @Override
- public boolean isDataConnectionAsDesired() {
- boolean roaming = mPhone.getServiceState().getRoaming();
-
- if (((mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
- mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
- (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
- ServiceState.STATE_IN_SERVICE) &&
- (!roaming || getDataOnRoamingEnabled()) &&
- !mIsWifiConnected ) {
- return (mState == State.CONNECTED);
- }
- return true;
- }
-
@Override
protected boolean isDataAllowed() {
- int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
+ int psState = mCdmaPhone.mSST.getCurrentDataConnectionState();
boolean roaming = (mPhone.getServiceState().getRoaming() && !getDataOnRoamingEnabled());
boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
boolean allowed =
(psState == ServiceState.STATE_IN_SERVICE ||
mAutoAttachOnCreation) &&
- (mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
- mCdmaPhone.mRuimRecords.getRecordsLoaded()) &&
- (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+ (mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
+ mCdmaPhone.mIccRecords.getRecordsLoaded()) &&
+ (mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
mPhone.getState() == Phone.State.IDLE) &&
!roaming &&
mInternalDataEnabled &&
@@ -214,11 +196,11 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
if (!((psState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
reason += " - psState= " + psState;
}
- if (!(mPhone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY ||
- mCdmaPhone.mRuimRecords.getRecordsLoaded())) {
- reason += " - radioState= " + mPhone.mCM.getRadioState() + " - RUIM not loaded";
+ if (!(mPhone.mCM.getNvState() == CommandsInterface.RadioState.NV_READY ||
+ mCdmaPhone.mIccRecords.getRecordsLoaded())) {
+ reason += " - radioState= " + mPhone.mCM.getNvState() + " - RUIM not loaded";
}
- if (!(mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
+ if (!(mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed() ||
mPhone.getState() == Phone.State.IDLE)) {
reason += " - concurrentVoiceAndData not allowed and state= " + mPhone.getState();
}
@@ -232,6 +214,36 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
return allowed;
}
+ /**
+ * The only circumstances under which we report that data connectivity is not
+ * possible are
+ * <ul>
+ * <li>Data is disallowed (roaming, power state, voice call, etc).</li>
+ * <li>The current data state is {@code DISCONNECTED} for a reason other than
+ * having explicitly disabled connectivity. In other words, data is not available
+ * because the phone is out of coverage or some like reason.</li>
+ * </ul>
+ * @return {@code true} if data connectivity is possible, {@code false} otherwise.
+ */
+ @Override
+ protected boolean isDataPossible() {
+ boolean dataAllowed = isDataAllowed();
+ boolean anyDataEnabled = getAnyDataEnabled();
+ boolean possible = (dataAllowed
+ && !(anyDataEnabled && (mState == State.FAILED || mState == State.IDLE)));
+ if (!possible && DBG) {
+ log("isDataPossible() " + possible + ", dataAllowed=" + dataAllowed +
+ " anyDataEnabled=" + anyDataEnabled + " dataState=" + mState);
+ }
+ return possible;
+ }
+
+ @Override
+ protected boolean isDataPossible(String apnType) {
+ return isDataPossible();
+ }
+
+
private boolean trySetupData(String reason) {
if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
@@ -246,7 +258,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
return true;
}
- int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
+ int psState = mCdmaPhone.mSST.getCurrentDataConnectionState();
boolean roaming = mPhone.getServiceState().getRoaming();
boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
@@ -262,9 +274,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
/**
- * Cleanup all connections.
- *
- * TODO: Cleanup only a specified connection passed as a parameter.
+ * Cleanup the CDMA data connection (only one is supported)
*
* @param tearDown true if the underlying DataConnection should be disconnected.
* @param reason for the clean up.
@@ -286,14 +296,18 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
boolean notificationDeferred = false;
for (DataConnection conn : mDataConnections.values()) {
if(conn != null) {
+ DataConnectionAc dcac =
+ mDataConnectionAsyncChannels.get(conn.getDataConnectionId());
if (tearDown) {
if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
+ conn.tearDown(reason, obtainMessage(EVENT_DISCONNECT_DONE,
conn.getDataConnectionId(), 0, reason));
notificationDeferred = true;
} else {
if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
- conn.resetSynchronously();
+ if (dcac != null) {
+ dcac.resetSync();
+ }
notificationDeferred = false;
}
}
@@ -308,11 +322,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
private CdmaDataConnection findFreeDataConnection() {
- for (DataConnection dc : mDataConnections.values()) {
- if (dc.isInactive()) {
- return (CdmaDataConnection) dc;
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.isInactiveSync()) {
+ log("found free GsmDataConnection");
+ return (CdmaDataConnection) dcac.dataConnection;
}
}
+ log("NO free CdmaDataConnection");
return null;
}
@@ -338,12 +354,12 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
mActiveApn = new ApnSetting(apnId, "", "", "", "", "", "", "", "", "",
"", 0, types, "IP", "IP");
- if (DBG) log("setupData: mActiveApn=" + mActiveApn);
+ if (DBG) log("call conn.bringUp mActiveApn=" + mActiveApn);
Message msg = obtainMessage();
msg.what = EVENT_DATA_SETUP_COMPLETE;
msg.obj = reason;
- conn.connect(msg, mActiveApn);
+ conn.bringUp(msg, mActiveApn);
setState(State.INITING);
notifyDataConnection(reason);
@@ -354,7 +370,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
setState(State.CONNECTED);
notifyDataConnection(reason);
startNetStatPoll();
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
}
private void resetPollStats() {
@@ -386,7 +402,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
protected void restartRadio() {
if (DBG) log("Cleanup connection and wait " +
(TIME_DELAYED_TO_RESTART_RADIO / 1000) + "s to restart radio");
- cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+ cleanUpAllConnections(null);
sendEmptyMessageDelayed(EVENT_RESTART_RADIO, TIME_DELAYED_TO_RESTART_RADIO);
mPendingRestartRadio = true;
}
@@ -504,21 +520,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
* at the last time until the state is changed.
* TODO: Make this configurable?
*/
- int nextReconnectDelay = mRetryMgr.getRetryTimer();
- log("Data Connection activate failed. Scheduling next attempt for "
- + (nextReconnectDelay / 1000) + "s");
-
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- Intent intent = new Intent(INTENT_RECONNECT_ALARM);
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
- mReconnectIntent = PendingIntent.getBroadcast(
- mPhone.getContext(), 0, intent, 0);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + nextReconnectDelay,
- mReconnectIntent);
-
- mRetryMgr.increaseRetryCount();
+ int nextReconnectDelay = mDataConnections.get(0).getRetryTimer();
+ startAlarmForReconnect(nextReconnectDelay, reason);
+ mDataConnections.get(0).increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
log("NOT Posting Data Connection Unavailable notification "
@@ -529,12 +533,28 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
}
+ private void startAlarmForReconnect(int delay, String reason) {
+
+ log("Data Connection activate failed. Scheduling next attempt for "
+ + (delay / 1000) + "s");
+
+ AlarmManager am =
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+ Intent intent = new Intent(INTENT_RECONNECT_ALARM);
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
+ mReconnectIntent = PendingIntent.getBroadcast(
+ mPhone.getContext(), 0, intent, 0);
+ am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delay, mReconnectIntent);
+
+ }
+
private void notifyNoData(FailCause lastFailCauseCode) {
setState(State.FAILED);
notifyDataAvailability(null);
}
- private void gotoIdleAndNotifyDataConnection(String reason) {
+ protected void gotoIdleAndNotifyDataConnection(String reason) {
if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason);
setState(State.IDLE);
notifyDataConnection(reason);
@@ -543,14 +563,14 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
protected void onRecordsLoaded() {
if (mState == State.FAILED) {
- cleanUpConnection(false, null);
+ cleanUpAllConnections(null);
}
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
}
protected void onNVReady() {
if (mState == State.FAILED) {
- cleanUpConnection(false, null);
+ cleanUpAllConnections(null);
}
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
}
@@ -560,6 +580,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
*/
@Override
protected void onEnableNewApn() {
+ // No mRequestedApnType check; only one connection is supported
cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
}
@@ -588,7 +609,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
trySetupData(Phone.REASON_ROAMING_ON);
} else {
if (DBG) log("Tear down data connection on roaming.");
- cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+ cleanUpAllConnections(null);
}
}
@@ -609,7 +630,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
notifyDataAvailability(null);
if (mState != State.IDLE) {
- cleanUpConnection(true, null);
+ cleanUpAllConnections(null);
}
}
@@ -618,7 +639,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
*/
@Override
protected void onRadioOffOrNotAvailable() {
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
@@ -626,7 +647,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
log("We're on the simulator; assuming radio off is meaningless");
} else {
if (DBG) log("Radio is off and clean up all connection");
- cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+ cleanUpAllConnections(null);
}
}
@@ -640,12 +661,8 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
reason = (String) ar.userObj;
}
- if (ar.exception == null) {
- // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
- mLinkProperties = getLinkProperties(mPendingDataConnection);
- mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
-
- // everything is setup
+ if (isDataSetupCompleteOk(ar)) {
+ // Everything is setup
notifyDefaultData(reason);
} else {
FailCause cause = (FailCause) (ar.result);
@@ -688,30 +705,17 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
notifyDataConnection(reason);
mActiveApn = null;
if (retryAfterDisconnected(reason)) {
- trySetupData(reason);
+ // Wait a bit before trying, so we're not tying up RIL command channel.
+ startAlarmForReconnect(APN_DELAY_MILLIS, reason);
}
}
/**
- * Called when EVENT_RESET_DONE is received so goto
- * IDLE state and send notifications to those interested.
- */
- @Override
- protected void onResetDone(AsyncResult ar) {
- if (DBG) log("EVENT_RESET_DONE");
- String reason = null;
- if (ar.userObj instanceof String) {
- reason = (String) ar.userObj;
- }
- gotoIdleAndNotifyDataConnection(reason);
- }
-
- /**
* @override com.android.internal.telephony.DataConnectionTracker
*/
@Override
protected void onVoiceCallStarted() {
- if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+ if (mState == State.CONNECTED && !mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed()) {
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
notifyDataAvailability(Phone.REASON_VOICE_CALL_STARTED);
@@ -724,7 +728,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override
protected void onVoiceCallEnded() {
if (mState == State.CONNECTED) {
- if (!mCdmaPhone.mSST.isConcurrentVoiceAndData()) {
+ if (!mCdmaPhone.mSST.isConcurrentVoiceAndDataAllowed()) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
} else {
@@ -733,36 +737,52 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
notifyDataAvailability(Phone.REASON_VOICE_CALL_ENDED);
} else {
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
// in case data setup was attempted when we were on a voice call
trySetupData(Phone.REASON_VOICE_CALL_ENDED);
}
}
@Override
- protected void onCleanUpConnection(boolean tearDown, String reason) {
+ protected void onCleanUpConnection(boolean tearDown, int apnId, String reason) {
+ // No apnId check; only one connection is supported
cleanUpConnection(tearDown, reason);
}
+ @Override
+ protected void onCleanUpAllConnections(String cause) {
+ // Only one CDMA connection is supported
+ cleanUpConnection(true, cause);
+ }
+
private void createAllDataConnectionList() {
CdmaDataConnection dataConn;
- /** TODO: Use one retry manager for all connections for now */
- RetryManager rm = mRetryMgr;
- if (!rm.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
- if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
- // Should never happen, log an error and default to a simple linear sequence.
- log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
- + DEFAULT_DATA_RETRY_CONFIG);
- rm.configure(20, 2000, 1000);
+ String retryConfig = SystemProperties.get("ro.cdma.data_retry_config");
+ for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
+ RetryManager rm = new RetryManager();
+ if (!rm.configure(retryConfig)) {
+ if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+ // Should never happen, log an error and default to a simple linear sequence.
+ log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+ + DEFAULT_DATA_RETRY_CONFIG);
+ rm.configure(20, 2000, 1000);
+ }
}
- }
- for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
int id = mUniqueIdGenerator.getAndIncrement();
-
dataConn = CdmaDataConnection.makeDataConnection(mCdmaPhone, id, rm);
mDataConnections.put(id, dataConn);
+ DataConnectionAc dcac = new DataConnectionAc(dataConn, LOG_TAG);
+ int status = dcac.fullyConnectSync(mPhone.getContext(), this, dataConn.getHandler());
+ if (status == AsyncChannel.STATUS_SUCCESSFUL) {
+ log("Fully connected");
+ mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
+ } else {
+ log("Could not connect to dcac.dataConnection=" + dcac.dataConnection +
+ " status=" + status);
+ }
+
}
}
@@ -779,7 +799,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
} else {
if (mState == State.FAILED) {
cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
CdmaCellLocation loc = (CdmaCellLocation)(mPhone.getCellLocation());
EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED,
@@ -797,7 +817,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
switch (otaPrivision[0]) {
case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
- mRetryMgr.resetRetryCount();
+ mDataConnections.get(0).resetRetryCount();
break;
default:
break;
@@ -893,8 +913,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@Override
public void handleMessage (Message msg) {
+ if (DBG) log("CdmaDCT handleMessage msg=" + msg);
- if (!mPhone.mIsTheCurrentActivePhone) {
+ if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
log("Ignore CDMA msgs since CDMA phone is inactive");
return;
}
@@ -933,12 +954,17 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
}
@Override
+ public boolean isAnyActiveDataConnections() {
+ return (mState != State.IDLE);
+ }
+
+ @Override
protected void log(String s) {
- Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+ Log.d(LOG_TAG, "[CdmaDCT] " + s);
}
@Override
protected void loge(String s) {
- Log.e(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+ Log.e(LOG_TAG, "[CdmaDCT] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
new file mode 100644
index 0000000..e593bd0
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2008 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 com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.TelephonyProperties;
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.RILConstants;
+
+import android.telephony.SignalStrength;
+import android.telephony.ServiceState;
+import android.telephony.cdma.CdmaCellLocation;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.AsyncResult;
+import android.os.Message;
+
+import android.util.Log;
+import android.util.EventLog;
+
+import com.android.internal.telephony.RestrictedState;
+import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
+
+public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
+ static final String LOG_TAG = "CDMA";
+
+ CDMALTEPhone mCdmaLtePhone;
+
+ private ServiceState mLteSS; // The last LTE state from Voice Registration
+
+ public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
+ super(phone);
+ cm.registerForSIMReady(this, EVENT_SIM_READY, null);
+ mCdmaLtePhone = phone;
+
+ mLteSS = new ServiceState();
+ if (DBG) log("CdmaLteServiceStateTracker Constructors");
+ }
+
+ public void dispose() {
+ cm.unregisterForSIMReady(this);
+ super.dispose();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+ int[] ints;
+ String[] strings;
+ switch (msg.what) {
+ case EVENT_POLL_STATE_GPRS:
+ if (DBG) log("handleMessage EVENT_POLL_STATE_GPRS");
+ ar = (AsyncResult)msg.obj;
+ handlePollStateResult(msg.what, ar);
+ break;
+ case EVENT_SIM_READY:
+ isSubscriptionFromRuim = false;
+ cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
+ pollState();
+ // Signal strength polling stops when radio is off.
+ queueNextSignalStrengthPoll();
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+
+ /**
+ * Set the cdmaSS for EVENT_POLL_STATE_REGISTRATION_CDMA
+ */
+ @Override
+ protected void setCdmaTechnology(int radioTechnology) {
+ // Called on voice registration state response.
+ // Just record new CDMA radio technology
+ newSS.setRadioTechnology(radioTechnology);
+ }
+
+ /**
+ * Handle the result of one of the pollState()-related requests
+ */
+ @Override
+ protected void handlePollStateResultMessage(int what, AsyncResult ar) {
+ if (what == EVENT_POLL_STATE_GPRS) {
+ if (DBG) log("handlePollStateResultMessage: EVENT_POLL_STATE_GPRS");
+ String states[] = (String[])ar.result;
+
+ int type = 0;
+ int regState = -1;
+ if (states.length > 0) {
+ try {
+ regState = Integer.parseInt(states[0]);
+
+ // states[3] (if present) is the current radio technology
+ if (states.length >= 4 && states[3] != null) {
+ type = Integer.parseInt(states[3]);
+ }
+ } catch (NumberFormatException ex) {
+ loge("handlePollStateResultMessage: error parsing GprsRegistrationState: "
+ + ex);
+ }
+ }
+
+ // Not sure if this is needed in CDMALTE phone.
+ // mDataRoaming = regCodeIsRoaming(regState);
+ mLteSS.setRadioTechnology(type);
+ mLteSS.setState(regCodeToServiceState(regState));
+ } else {
+ super.handlePollStateResultMessage(what, ar);
+ }
+ }
+
+ @Override
+ protected void setSignalStrengthDefaultValues() {
+ mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, false);
+ }
+
+ @Override
+ protected void pollState() {
+ pollingContext = new int[1];
+ pollingContext[0] = 0;
+
+ switch (cm.getRadioState()) {
+ case RADIO_UNAVAILABLE:
+ newSS.setStateOutOfService();
+ newCellLoc.setStateInvalid();
+ setSignalStrengthDefaultValues();
+ mGotCountryCode = false;
+
+ pollStateDone();
+ break;
+
+ case RADIO_OFF:
+ newSS.setStateOff();
+ newCellLoc.setStateInvalid();
+ setSignalStrengthDefaultValues();
+ mGotCountryCode = false;
+
+ pollStateDone();
+ break;
+
+ default:
+ // Issue all poll-related commands at once, then count
+ // down the responses which are allowed to arrive
+ // out-of-order.
+
+ pollingContext[0]++;
+ // RIL_REQUEST_OPERATOR is necessary for CDMA
+ cm.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
+
+ pollingContext[0]++;
+ // RIL_REQUEST_VOICE_REGISTRATION_STATE is necessary for CDMA
+ cm.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA,
+ pollingContext));
+
+ int networkMode = android.provider.Settings.Secure.getInt(phone.getContext()
+ .getContentResolver(),
+ android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
+ RILConstants.PREFERRED_NETWORK_MODE);
+ if (DBG) log("pollState: network mode here is = " + networkMode);
+ if ((networkMode == RILConstants.NETWORK_MODE_GLOBAL)
+ || (networkMode == RILConstants.NETWORK_MODE_LTE_ONLY)) {
+ pollingContext[0]++;
+ // RIL_REQUEST_DATA_REGISTRATION_STATE
+ cm.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS,
+ pollingContext));
+ }
+ break;
+ }
+ }
+
+ protected static String networkTypeToString(int type) {
+ String ret = "unknown";
+
+ switch (type) {
+ case ServiceState.RADIO_TECHNOLOGY_IS95A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95B:
+ ret = "CDMA";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_1xRTT:
+ ret = "CDMA - 1xRTT";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_0:
+ ret = "CDMA - EvDo rev. 0";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
+ ret = "CDMA - EvDo rev. A";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_B:
+ ret = "CDMA - EvDo rev. B";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_LTE:
+ ret = "LTE";
+ break;
+ case ServiceState.RADIO_TECHNOLOGY_EHRPD:
+ ret = "CDMA - eHRPD";
+ break;
+ default:
+ sloge("networkTypeToString: Wrong network, can not return a string.");
+ break;
+ }
+ return ret;
+ }
+
+ @Override
+ protected void pollStateDone() {
+ // determine data NetworkType from both LET and CDMA SS
+ if (mLteSS.getState() == ServiceState.STATE_IN_SERVICE) {
+ //in LTE service
+ newNetworkType = mLteSS.getRadioTechnology();
+ mNewDataConnectionState = mLteSS.getState();
+ newSS.setRadioTechnology(newNetworkType);
+ log("pollStateDone LTE/eHRPD STATE_IN_SERVICE newNetworkType = " + newNetworkType);
+ } else {
+ // LTE out of service, get CDMA Service State
+ newNetworkType = newSS.getRadioTechnology();
+ mNewDataConnectionState = radioTechnologyToDataServiceState(newNetworkType);
+ log("pollStateDone CDMA STATE_IN_SERVICE newNetworkType = " + newNetworkType +
+ " mNewDataConnectionState = " + mNewDataConnectionState);
+ }
+
+ if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
+
+ boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
+ && newSS.getState() == ServiceState.STATE_IN_SERVICE;
+
+ boolean hasDeregistered = ss.getState() == ServiceState.STATE_IN_SERVICE
+ && newSS.getState() != ServiceState.STATE_IN_SERVICE;
+
+ boolean hasCdmaDataConnectionAttached =
+ mDataConnectionState != ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
+
+ boolean hasCdmaDataConnectionDetached =
+ mDataConnectionState == ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
+
+ boolean hasCdmaDataConnectionChanged =
+ mDataConnectionState != mNewDataConnectionState;
+
+ boolean hasNetworkTypeChanged = networkType != newNetworkType;
+
+ boolean hasChanged = !newSS.equals(ss);
+
+ boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
+
+ boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
+
+ boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
+
+ boolean has4gHandoff =
+ ((networkType == ServiceState.RADIO_TECHNOLOGY_LTE) &&
+ (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) ||
+ ((networkType == ServiceState.RADIO_TECHNOLOGY_EHRPD) &&
+ (newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE));
+
+ boolean hasMultiApnSupport =
+ (((newNetworkType == ServiceState.RADIO_TECHNOLOGY_LTE) ||
+ (newNetworkType == ServiceState.RADIO_TECHNOLOGY_EHRPD)) &&
+ ((networkType != ServiceState.RADIO_TECHNOLOGY_LTE) &&
+ (networkType != ServiceState.RADIO_TECHNOLOGY_EHRPD)));
+
+ boolean hasLostMultiApnSupport =
+ ((newNetworkType >= ServiceState.RADIO_TECHNOLOGY_IS95A) &&
+ (newNetworkType <= ServiceState.RADIO_TECHNOLOGY_EVDO_A));
+
+ if (DBG) {
+ log("pollStateDone: hasRegistered = "
+ + hasRegistered + " hasCdmaDataConnectionAttached = "
+ + hasCdmaDataConnectionAttached + " hasCdmaDataConnectionChanged = "
+ + hasCdmaDataConnectionChanged + " hasNetworkTypeChanged = "
+ + hasNetworkTypeChanged + " has4gHandoff = " + has4gHandoff
+ + " hasMultiApnSupport = " + hasMultiApnSupport + " hasLostMultiApnSupport = "
+ + hasLostMultiApnSupport);
+ }
+ // Add an event log when connection state changes
+ if (ss.getState() != newSS.getState()
+ || mDataConnectionState != mNewDataConnectionState) {
+ EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, ss.getState(),
+ mDataConnectionState, newSS.getState(), mNewDataConnectionState);
+ }
+
+ ServiceState tss;
+ tss = ss;
+ ss = newSS;
+ newSS = tss;
+ // clean slate for next time
+ newSS.setStateOutOfService();
+ mLteSS.setStateOutOfService();
+
+ if ((hasMultiApnSupport)
+ && (phone.mDataConnectionTracker instanceof CdmaDataConnectionTracker)) {
+ if (DBG) log("GsmDataConnectionTracker Created");
+ phone.mDataConnectionTracker.dispose();
+ phone.mDataConnectionTracker = new GsmDataConnectionTracker(mCdmaLtePhone);
+ }
+
+ if ((hasLostMultiApnSupport)
+ && (phone.mDataConnectionTracker instanceof GsmDataConnectionTracker)) {
+ if (DBG)log("GsmDataConnectionTracker disposed");
+ phone.mDataConnectionTracker.dispose();
+ phone.mDataConnectionTracker = new CdmaDataConnectionTracker((CDMAPhone)phone);
+ }
+
+ CdmaCellLocation tcl = cellLoc;
+ cellLoc = newCellLoc;
+ newCellLoc = tcl;
+
+ mDataConnectionState = mNewDataConnectionState;
+ networkType = newNetworkType;
+
+ newSS.setStateOutOfService(); // clean slate for next time
+
+ if (hasNetworkTypeChanged) {
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
+ networkTypeToString(networkType));
+ }
+
+ if (hasRegistered) {
+ mNetworkAttachedRegistrants.notifyRegistrants();
+ }
+
+ if (hasChanged) {
+ if (cm.getNvState().isNVReady()) {
+ String eriText;
+ // Now the CDMAPhone sees the new ServiceState so it can get the
+ // new ERI text
+ if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+ eriText = phone.getCdmaEriText();
+ } else {
+ // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
+ // for
+ // mRegistrationState 0,2,3 and 4
+ eriText = phone.getContext()
+ .getText(com.android.internal.R.string.roamingTextSearching).toString();
+ }
+ ss.setCdmaEriText(eriText);
+ }
+
+ String operatorNumeric;
+
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
+ ss.getOperatorAlphaLong());
+
+ operatorNumeric = ss.getOperatorNumeric();
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
+
+ if (operatorNumeric == null) {
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
+ } else {
+ String isoCountryCode = "";
+ try {
+ isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric
+ .substring(0, 3)));
+ } catch (NumberFormatException ex) {
+ loge("countryCodeForMcc error" + ex);
+ } catch (StringIndexOutOfBoundsException ex) {
+ loge("countryCodeForMcc error" + ex);
+ }
+
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
+ isoCountryCode);
+ mGotCountryCode = true;
+ if (mNeedFixZone) {
+ fixTimeZone(isoCountryCode);
+ }
+ }
+
+ phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
+ ss.getRoaming() ? "true" : "false");
+
+ updateSpnDisplay();
+ phone.notifyServiceStateChanged(ss);
+ }
+
+ if (hasCdmaDataConnectionAttached) {
+ mAttachedRegistrants.notifyRegistrants();
+ }
+
+ if (hasCdmaDataConnectionDetached) {
+ mDetachedRegistrants.notifyRegistrants();
+ }
+
+ if ((hasCdmaDataConnectionChanged || hasNetworkTypeChanged)) {
+ phone.notifyDataConnection();
+ }
+
+ if (hasRoamingOn) {
+ mRoamingOnRegistrants.notifyRegistrants();
+ }
+
+ if (hasRoamingOff) {
+ mRoamingOffRegistrants.notifyRegistrants();
+ }
+
+ if (hasLocationChanged) {
+ phone.notifyLocationChanged();
+ }
+ }
+
+ protected void onSignalStrengthResult(AsyncResult ar) {
+ SignalStrength oldSignalStrength = mSignalStrength;
+
+ if (ar.exception != null) {
+ // Most likely radio is resetting/disconnected change to default
+ // values.
+ setSignalStrengthDefaultValues();
+ } else {
+ int[] ints = (int[])ar.result;
+ int lteCqi = 99, lteRsrp = -1;
+ int lteRssi = 99;
+ int offset = 2;
+ int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -120;
+ int cdmaEcio = (ints[offset + 1] > 0) ? -ints[offset + 1] : -160;
+ int evdoRssi = (ints[offset + 2] > 0) ? -ints[offset + 2] : -120;
+ int evdoEcio = (ints[offset + 3] > 0) ? -ints[offset + 3] : -1;
+ int evdoSnr = ((ints[offset + 4] > 0) && (ints[offset + 4] <= 8)) ? ints[offset + 4]
+ : -1;
+ if (networkType == ServiceState.RADIO_TECHNOLOGY_LTE) {
+ lteRssi = (ints[offset + 5] >= 0) ? ints[offset + 5] : 99;
+ lteRsrp = (ints[offset + 6] < 0) ? ints[offset + 6] : -1;
+ lteCqi = (ints[offset + 7] >= 0) ? ints[offset + 7] : 99;
+ }
+
+ if (networkType != ServiceState.RADIO_TECHNOLOGY_LTE) {
+ mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio, evdoRssi, evdoEcio,
+ evdoSnr, false);
+ } else {
+ mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio, evdoRssi, evdoEcio,
+ evdoSnr, lteRssi, lteRsrp, -1, -1, lteCqi, true);
+ }
+ }
+
+ try {
+ phone.notifySignalStrength();
+ } catch (NullPointerException ex) {
+ loge("onSignalStrengthResult() Phone already destroyed: " + ex
+ + "SignalStrength not notified");
+ }
+ }
+
+ public boolean isConcurrentVoiceAndDataAllowed() {
+ // Note: it needs to be confirmed which CDMA network types
+ // can support voice and data calls concurrently.
+ // For the time-being, the return value will be false.
+ // return (networkType >= ServiceState.RADIO_TECHNOLOGY_LTE);
+ return false;
+ }
+
+ @Override
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+
+ protected static void sloge(String s) {
+ Log.e(LOG_TAG, "[CdmaLteSST] " + s);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 6bd2d09..c0bfd23 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -94,7 +94,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
/** {@inheritDoc} */
@Override
- protected int dispatchMessage(SmsMessageBase smsb) {
+ public int dispatchMessage(SmsMessageBase smsb) {
// If sms is null, means there was a parsing error.
if (smsb == null) {
@@ -485,19 +485,19 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
/** {@inheritDoc} */
@Override
- protected void activateCellBroadcastSms(int activate, Message response) {
+ public void activateCellBroadcastSms(int activate, Message response) {
mCm.setCdmaBroadcastActivation((activate == 0), response);
}
/** {@inheritDoc} */
@Override
- protected void getCellBroadcastSmsConfig(Message response) {
+ public void getCellBroadcastSmsConfig(Message response) {
mCm.getCdmaBroadcastConfig(response);
}
/** {@inheritDoc} */
@Override
- protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+ public void setCellBroadcastConfig(int[] configValuesArray, Message response) {
mCm.setCdmaBroadcastConfig(configValuesArray, response);
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 0debb42..56b335e 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -16,8 +16,6 @@
package com.android.internal.telephony.cdma;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
-
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataConnectionTracker;
@@ -61,7 +59,7 @@ import java.util.TimeZone;
/**
* {@hide}
*/
-final class CdmaServiceStateTracker extends ServiceStateTracker {
+public class CdmaServiceStateTracker extends ServiceStateTracker {
static final String LOG_TAG = "CDMA";
CDMAPhone phone;
@@ -86,10 +84,10 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
NITZ_UPDATE_DIFF_DEFAULT);
/**
- * Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
+ * Values correspond to ServiceState.RADIO_TECHNOLOGY_ definitions.
*/
- private int networkType = 0;
- private int newNetworkType = 0;
+ protected int networkType = 0;
+ protected int newNetworkType = 0;
private boolean mCdmaRoaming = false;
private int mRoamingIndicator;
@@ -99,23 +97,21 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
/**
* Initially assume no data connection.
*/
- private int cdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
- private int newCdmaDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
- private int mRegistrationState = -1;
- private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList();
- private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
- private RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
+ protected int mDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+ protected int mNewDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
+ protected int mRegistrationState = -1;
+ protected RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
/**
* Sometimes we get the NITZ time before we know what country we
* are in. Keep the time zone information from the NITZ string so
* we can fix the time zone once know the country.
*/
- private boolean mNeedFixZone = false;
+ protected boolean mNeedFixZone = false;
private int mZoneOffset;
private boolean mZoneDst;
private long mZoneTime;
- private boolean mGotCountryCode = false;
+ protected boolean mGotCountryCode = false;
String mSavedTimeZone;
long mSavedTime;
long mSavedAtTime;
@@ -141,9 +137,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
private boolean mIsMinInfoReady = false;
private boolean isEriTextLoaded = false;
- private boolean isSubscriptionFromRuim = false;
-
- private boolean mPendingRadioPowerOffAfterDataOff = false;
+ protected boolean isSubscriptionFromRuim = false;
/* Used only for debugging purposes. */
private String mRegistrationDeniedReason;
@@ -154,7 +148,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
- Log.i("CdmaServiceStateTracker", "Auto time state changed");
+ if (DBG) log("Auto time state changed");
revertToNitzTime();
}
};
@@ -162,7 +156,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
private ContentObserver mAutoTimeZoneObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
- Log.i("CdmaServiceStateTracker", "Auto time zone state changed");
+ if (DBG) log("Auto time zone state changed");
revertToNitzTimeZone();
}
};
@@ -220,11 +214,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
cm.unregisterForNVReady(this);
cm.unregisterForCdmaOtaProvision(this);
phone.unregisterForEriFileLoaded(this);
- phone.mRuimRecords.unregisterForRecordsLoaded(this);
+ phone.mIccRecords.unregisterForRecordsLoaded(this);
cm.unSetOnSignalStrengthUpdate(this);
cm.unSetOnNITZTime(this);
- cr.unregisterContentObserver(this.mAutoTimeObserver);
- cr.unregisterContentObserver(this.mAutoTimeZoneObserver);
+ cr.unregisterContentObserver(mAutoTimeObserver);
+ cr.unregisterContentObserver(mAutoTimeZoneObserver);
}
@Override
@@ -232,57 +226,6 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (DBG) log("CdmaServiceStateTracker finalized");
}
- void registerForNetworkAttach(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- networkAttachedRegistrants.add(r);
-
- if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForNetworkAttach(Handler h) {
- networkAttachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into Data attached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForCdmaDataConnectionAttached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- cdmaDataConnectionAttachedRegistrants.add(r);
-
- if (cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForCdmaDataConnectionAttached(Handler h) {
- cdmaDataConnectionAttachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into Data detached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForCdmaDataConnectionDetached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- cdmaDataConnectionDetachedRegistrants.add(r);
-
- if (cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForCdmaDataConnectionDetached(Handler h) {
- cdmaDataConnectionDetachedRegistrants.remove(h);
- }
-
/**
* Registration point for subscription info ready
* @param h handler to notify
@@ -317,7 +260,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
// unlocked. At this stage, the radio is already powered on.
isSubscriptionFromRuim = true;
if (mNeedToRegForRuimLoaded) {
- phone.mRuimRecords.registerForRecordsLoaded(this,
+ phone.mIccRecords.registerForRecordsLoaded(this,
EVENT_RUIM_RECORDS_LOADED, null);
mNeedToRegForRuimLoaded = false;
}
@@ -401,7 +344,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
networkId = Integer.parseInt(states[9]);
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing cell location data: " + ex);
+ loge("error parsing cell location data: " + ex);
}
}
@@ -435,11 +378,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
try {
mHomeSystemId[i] = Integer.parseInt(sid[i]);
} catch (NumberFormatException ex) {
- Log.e(LOG_TAG, "error parsing system id: ", ex);
+ loge("error parsing system id: " + ex);
}
}
}
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION SID=" + cdmaSubscription[1] );
+ if (DBG) log("GET_CDMA_SUBSCRIPTION: SID=" + cdmaSubscription[1] );
if (cdmaSubscription[2] != null) {
String[] nid = cdmaSubscription[2].split(",");
@@ -448,14 +391,14 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
try {
mHomeNetworkId[i] = Integer.parseInt(nid[i]);
} catch (NumberFormatException ex) {
- Log.e(LOG_TAG, "error parsing network id: ", ex);
+ loge("GET_CDMA_SUBSCRIPTION: error parsing network id: " + ex);
}
}
}
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION NID=" + cdmaSubscription[2] );
+ if (DBG) log("GET_CDMA_SUBSCRIPTION: NID=" + cdmaSubscription[2]);
mMin = cdmaSubscription[3];
mPrlVersion = cdmaSubscription[4];
- Log.d(LOG_TAG,"GET_CDMA_SUBSCRIPTION MDN=" + mMdn);
+ if (DBG) log("GET_CDMA_SUBSCRIPTION: MDN=" + mMdn);
mIsMinInfoReady = true;
@@ -465,19 +408,23 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
// Notify apps subscription info is ready
if (cdmaForSubscriptionInfoReadyRegistrants != null) {
- Log.d(LOG_TAG, "call cdmaForSubscriptionInfoReady.notifyRegistrants()");
+ if (DBG) log("GET_CDMA_SUBSCRIPTION: call notifyRegistrants()");
cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
}
if (oldOtaspMode != mCurrentOtaspMode) {
- Log.d(LOG_TAG, "call phone.notifyOtaspChanged old otaspMode=" +
+ if (DBG) {
+ log("GET_CDMA_SUBSCRIPTION: call notifyOtaspChanged old otaspMode=" +
oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode);
+ }
phone.notifyOtaspChanged(mCurrentOtaspMode);
}
phone.getIccCard().broadcastIccStateChangedIntent(IccCard.INTENT_VALUE_ICC_IMSI,
null);
} else {
- Log.w(LOG_TAG,"error parsing cdmaSubscription params num="
+ if (DBG) {
+ log("GET_CDMA_SUBSCRIPTION: error parsing cdmaSubscription params num="
+ cdmaSubscription.length);
+ }
}
}
break;
@@ -532,26 +479,16 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (ar.exception == null) {
ints = (int[]) ar.result;
int otaStatus = ints[0];
- if (otaStatus == phone.CDMA_OTA_PROVISION_STATUS_COMMITTED
- || otaStatus == phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) {
- Log.d(LOG_TAG, "Received OTA_PROGRAMMING Complete,Reload MDN ");
+ if (otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED
+ || otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) {
+ if (DBG) log("EVENT_OTA_PROVISION_STATUS_CHANGE: Complete, Reload MDN");
cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
}
}
break;
- case EVENT_SET_RADIO_POWER_OFF:
- synchronized(this) {
- if (mPendingRadioPowerOffAfterDataOff) {
- if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
- hangupAndPowerOff();
- mPendingRadioPowerOffAfterDataOff = false;
- }
- }
- break;
-
default:
- Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+ super.handleMessage(msg);
break;
}
}
@@ -565,51 +502,14 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
&& cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
cm.setRadioPower(true, null);
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
- DataConnectionTracker dcTracker = phone.mDataConnection;
- if (! dcTracker.isDataConnectionAsDesired()) {
- EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
- dcTracker.getStateInString(),
- dcTracker.getAnyDataEnabled() ? 1 : 0);
- }
+ DataConnectionTracker dcTracker = phone.mDataConnectionTracker;
// If it's on and available and we want it off gracefully
- powerOffRadioSafely();
+ powerOffRadioSafely(dcTracker);
} // Otherwise, we're in the desired state
}
@Override
- protected void powerOffRadioSafely() {
- DataConnectionTracker dcTracker = phone.mDataConnection;
-
- Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
- msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
-
- synchronized (this) {
- if (!mPendingRadioPowerOffAfterDataOff) {
- DataConnectionTracker.State currentState = dcTracker.getState();
- if (currentState != DataConnectionTracker.State.CONNECTED
- && currentState != DataConnectionTracker.State.DISCONNECTING
- && currentState != DataConnectionTracker.State.INITING) {
- msg.arg1 = 0; // tearDown is false as it is not needed.
- dcTracker.sendMessage(msg);
- if (DBG) log("Data disconnected, turn off radio right away.");
- hangupAndPowerOff();
- } else {
- msg.arg1 = 1; // tearDown is true
- dcTracker.sendMessage(msg);
- if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 30000)) {
- if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
- mPendingRadioPowerOffAfterDataOff = true;
- } else {
- Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away.");
- hangupAndPowerOff();
- }
- }
- }
- }
- }
-
- @Override
protected void updateSpnDisplay() {
// TODO RUIM SPN is not implemented, EF_SPN has to be read and Display Condition
// Character Encoding, Language Indicator and SPN has to be set, something like below:
@@ -626,9 +526,10 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
// null and not blank. But this would cause us to incorrectly display
// "No Service". Now showPlmn is set to true for any non null string.
boolean showPlmn = plmn != null;
- Log.d(LOG_TAG,
- String.format("updateSpnDisplay: changed sending intent" +
+ if (DBG) {
+ log(String.format("updateSpnDisplay: changed sending intent" +
" showPlmn='%b' plmn='%s'", showPlmn, plmn));
+ }
Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Intents.EXTRA_SHOW_SPN, false);
@@ -647,14 +548,164 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
/**
- * Handle the result of one of the pollState()-related requests
- */
+ * Determine data network type based on radio technology.
+ */
+ protected void setCdmaTechnology(int radioTechnology){
+ mNewDataConnectionState = radioTechnologyToDataServiceState(radioTechnology);
+ newSS.setRadioTechnology(radioTechnology);
+ newNetworkType = radioTechnology;
+ }
- @Override
- protected void handlePollStateResult (int what, AsyncResult ar) {
+ /**
+ * Hanlde the PollStateResult message
+ */
+ protected void handlePollStateResultMessage(int what, AsyncResult ar){
int ints[];
String states[];
+ switch (what) {
+ case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE.
+ states = (String[])ar.result;
+
+ int registrationState = 4; //[0] registrationState
+ int radioTechnology = -1; //[3] radioTechnology
+ int baseStationId = -1; //[4] baseStationId
+ //[5] baseStationLatitude
+ int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ //[6] baseStationLongitude
+ int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+ int cssIndicator = 0; //[7] init with 0, because it is treated as a boolean
+ int systemId = 0; //[8] systemId
+ int networkId = 0; //[9] networkId
+ int roamingIndicator = -1; //[10] Roaming indicator
+ int systemIsInPrl = 0; //[11] Indicates if current system is in PRL
+ int defaultRoamingIndicator = 0; //[12] Is default roaming indicator from PRL
+ int reasonForDenial = 0; //[13] Denial reason if registrationState = 3
+
+ if (states.length == 14) {
+ try {
+ if (states[0] != null) {
+ registrationState = Integer.parseInt(states[0]);
+ }
+ if (states[3] != null) {
+ radioTechnology = Integer.parseInt(states[3]);
+ }
+ if (states[4] != null) {
+ baseStationId = Integer.parseInt(states[4]);
+ }
+ if (states[5] != null) {
+ baseStationLatitude = Integer.parseInt(states[5]);
+ }
+ if (states[6] != null) {
+ baseStationLongitude = Integer.parseInt(states[6]);
+ }
+ // Some carriers only return lat-lngs of 0,0
+ if (baseStationLatitude == 0 && baseStationLongitude == 0) {
+ baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+ baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+ }
+ if (states[7] != null) {
+ cssIndicator = Integer.parseInt(states[7]);
+ }
+ if (states[8] != null) {
+ systemId = Integer.parseInt(states[8]);
+ }
+ if (states[9] != null) {
+ networkId = Integer.parseInt(states[9]);
+ }
+ if (states[10] != null) {
+ roamingIndicator = Integer.parseInt(states[10]);
+ }
+ if (states[11] != null) {
+ systemIsInPrl = Integer.parseInt(states[11]);
+ }
+ if (states[12] != null) {
+ defaultRoamingIndicator = Integer.parseInt(states[12]);
+ }
+ if (states[13] != null) {
+ reasonForDenial = Integer.parseInt(states[13]);
+ }
+ } catch (NumberFormatException ex) {
+ loge("EVENT_POLL_STATE_REGISTRATION_CDMA: error parsing: " + ex);
+ }
+ } else {
+ throw new RuntimeException("Warning! Wrong number of parameters returned from "
+ + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
+ + states.length);
+ }
+
+ mRegistrationState = registrationState;
+ // When registration state is roaming and TSB58
+ // roaming indicator is not in the carrier-specified
+ // list of ERIs for home system, mCdmaRoaming is true.
+ mCdmaRoaming =
+ regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
+ newSS.setState (regCodeToServiceState(registrationState));
+
+ setCdmaTechnology(radioTechnology);
+
+ newSS.setCssIndicator(cssIndicator);
+ newSS.setSystemAndNetworkId(systemId, networkId);
+ mRoamingIndicator = roamingIndicator;
+ mIsInPrl = (systemIsInPrl == 0) ? false : true;
+ mDefaultRoamingIndicator = defaultRoamingIndicator;
+
+
+ // Values are -1 if not available.
+ newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
+ baseStationLongitude, systemId, networkId);
+
+ if (reasonForDenial == 0) {
+ mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
+ } else if (reasonForDenial == 1) {
+ mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
+ } else {
+ mRegistrationDeniedReason = "";
+ }
+
+ if (mRegistrationState == 3) {
+ if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
+ }
+ break;
+ case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
+ String opNames[] = (String[])ar.result;
+
+ if (opNames != null && opNames.length >= 3) {
+ // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
+ if ((opNames[2] == null) || (opNames[2].length() < 5)
+ || ("00000".equals(opNames[2]))) {
+ opNames[2] = SystemProperties.get(
+ CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
+ if (DBG) {
+ log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
+ " is bad. Using SystemProperties '" +
+ CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
+ "'= " + opNames[2]);
+ }
+ }
+ if (cm.getNvState().isNVReady()) {
+ // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
+ // ERI text, so here it is ignored what is coming from the modem.
+ newSS.setOperatorName(null, opNames[1], opNames[2]);
+ } else {
+ newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
+ }
+ } else {
+ if (DBG) log("EVENT_POLL_STATE_OPERATOR_CDMA: error parsing opNames");
+ }
+ break;
+ default:
+ loge("handlePollStateResultMessage: RIL response handle in wrong phone!"
+ + " Expected CDMA RIL request and get GSM RIL request.");
+ break;
+ }
+ }
+
+ /**
+ * Handle the result of one of the pollState() - related requests
+ */
+ @Override
+ protected void handlePollStateResult(int what, AsyncResult ar) {
// Ignore stale requests from last poll.
if (ar.userObj != pollingContext) return;
@@ -677,158 +728,15 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
return;
}
- if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
- err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
- Log.e(LOG_TAG,
- "RIL implementation has returned an error where it must succeed",
- ar.exception);
+ if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
+ loge("handlePollStateResult: RIL returned an error where it must succeed"
+ + ar.exception);
}
} else try {
- switch (what) {
- case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE.
- states = (String[])ar.result;
-
- int registrationState = 4; //[0] registrationState
- int radioTechnology = -1; //[3] radioTechnology
- int baseStationId = -1; //[4] baseStationId
- //[5] baseStationLatitude
- int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
- //[6] baseStationLongitude
- int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
- int cssIndicator = 0; //[7] init with 0, because it is treated as a boolean
- int systemId = 0; //[8] systemId
- int networkId = 0; //[9] networkId
- int roamingIndicator = -1; //[10] Roaming indicator
- int systemIsInPrl = 0; //[11] Indicates if current system is in PRL
- int defaultRoamingIndicator = 0; //[12] Is default roaming indicator from PRL
- int reasonForDenial = 0; //[13] Denial reason if registrationState = 3
-
- if (states.length == 14) {
- try {
- if (states[0] != null) {
- registrationState = Integer.parseInt(states[0]);
- }
- if (states[3] != null) {
- radioTechnology = Integer.parseInt(states[3]);
- }
- if (states[4] != null) {
- baseStationId = Integer.parseInt(states[4]);
- }
- if (states[5] != null) {
- baseStationLatitude = Integer.parseInt(states[5]);
- }
- if (states[6] != null) {
- baseStationLongitude = Integer.parseInt(states[6]);
- }
- // Some carriers only return lat-lngs of 0,0
- if (baseStationLatitude == 0 && baseStationLongitude == 0) {
- baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
- baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
- }
- if (states[7] != null) {
- cssIndicator = Integer.parseInt(states[7]);
- }
- if (states[8] != null) {
- systemId = Integer.parseInt(states[8]);
- }
- if (states[9] != null) {
- networkId = Integer.parseInt(states[9]);
- }
- if (states[10] != null) {
- roamingIndicator = Integer.parseInt(states[10]);
- }
- if (states[11] != null) {
- systemIsInPrl = Integer.parseInt(states[11]);
- }
- if (states[12] != null) {
- defaultRoamingIndicator = Integer.parseInt(states[12]);
- }
- if (states[13] != null) {
- reasonForDenial = Integer.parseInt(states[13]);
- }
- } catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
- }
- } else {
- throw new RuntimeException("Warning! Wrong number of parameters returned from "
- + "RIL_REQUEST_REGISTRATION_STATE: expected 14 got "
- + states.length);
- }
-
- mRegistrationState = registrationState;
- // When registration state is roaming and TSB58
- // roaming indicator is not in the carrier-specified
- // list of ERIs for home system, mCdmaRoaming is true.
- mCdmaRoaming =
- regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
- newSS.setState (regCodeToServiceState(registrationState));
-
- this.newCdmaDataConnectionState =
- radioTechnologyToDataServiceState(radioTechnology);
- newSS.setRadioTechnology(radioTechnology);
- newNetworkType = radioTechnology;
-
- newSS.setCssIndicator(cssIndicator);
- newSS.setSystemAndNetworkId(systemId, networkId);
- mRoamingIndicator = roamingIndicator;
- mIsInPrl = (systemIsInPrl == 0) ? false : true;
- mDefaultRoamingIndicator = defaultRoamingIndicator;
-
-
- // Values are -1 if not available.
- newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
- baseStationLongitude, systemId, networkId);
-
- if (reasonForDenial == 0) {
- mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
- } else if (reasonForDenial == 1) {
- mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
- } else {
- mRegistrationDeniedReason = "";
- }
-
- if (mRegistrationState == 3) {
- if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
- }
- break;
-
- case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
- String opNames[] = (String[])ar.result;
-
- if (opNames != null && opNames.length >= 3) {
- // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
- if ((opNames[2] == null) || (opNames[2].length() < 5)
- || ("00000".equals(opNames[2]))) {
- opNames[2] = SystemProperties.get(
- CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
- if (DBG) {
- log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
- " is bad. Using SystemProperties '" +
- CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
- "'= " + opNames[2]);
- }
- }
- if (cm.getRadioState().isNVReady()) {
- // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
- // ERI text, so here it is ignored what is coming from the modem.
- newSS.setOperatorName(null, opNames[1], opNames[2]);
- } else {
- newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
- }
- } else {
- Log.w(LOG_TAG, "error parsing opNames");
- }
- break;
-
- default:
- Log.e(LOG_TAG, "RIL response handle in wrong phone!"
- + " Expected CDMA RIL request and get GSM RIL request.");
- break;
- }
-
+ handlePollStateResultMessage(what, ar);
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "Exception while polling service state. "
- + "Probably malformed RIL response.", ex);
+ loge("handlePollStateResult: Exception while polling service state. "
+ + "Probably malformed RIL response." + ex);
}
pollingContext[0]--;
@@ -896,9 +804,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
- private void setSignalStrengthDefaultValues() {
- mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, false);
+ protected void setSignalStrengthDefaultValues() {
+ mSignalStrength = new SignalStrength(99, -1, -1, -1, -1, -1, -1, false);
}
/**
@@ -909,7 +816,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
* and start over again if the radio notifies us that some
* event has changed
*/
- private void
+ protected void
pollState() {
pollingContext = new int[1];
pollingContext[0] = 0;
@@ -936,7 +843,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
case SIM_NOT_READY:
case SIM_LOCKED_OR_ABSENT:
case SIM_READY:
- log("Radio Technology Change ongoing, setting SS to off");
+ if (DBG) log("Radio Technology Change ongoing, setting SS to off");
newSS.setStateOff();
newCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
@@ -964,29 +871,29 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
}
- private static String networkTypeToString(int type) {
+ protected static String networkTypeToString(int type) {
String ret = "unknown";
switch (type) {
- case DATA_ACCESS_CDMA_IS95A:
- case DATA_ACCESS_CDMA_IS95B:
+ case ServiceState.RADIO_TECHNOLOGY_IS95A:
+ case ServiceState.RADIO_TECHNOLOGY_IS95B:
ret = "CDMA";
break;
- case DATA_ACCESS_CDMA_1xRTT:
+ case ServiceState.RADIO_TECHNOLOGY_1xRTT:
ret = "CDMA - 1xRTT";
break;
- case DATA_ACCESS_CDMA_EvDo_0:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_0:
ret = "CDMA - EvDo rev. 0";
break;
- case DATA_ACCESS_CDMA_EvDo_A:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_A:
ret = "CDMA - EvDo rev. A";
break;
- case DATA_ACCESS_CDMA_EvDo_B:
+ case ServiceState.RADIO_TECHNOLOGY_EVDO_B:
ret = "CDMA - EvDo rev. B";
break;
default:
if (DBG) {
- Log.e(LOG_TAG, "Wrong network. Can not return a string.");
+ slog("Wrong network. Can not return a string.");
}
break;
}
@@ -994,7 +901,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
return ret;
}
- private void fixTimeZone(String isoCountryCode) {
+ protected void fixTimeZone(String isoCountryCode) {
TimeZone zone = null;
// If the offset is (0, false) and the time zone property
// is set, use the time zone property rather than GMT.
@@ -1031,8 +938,8 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
}
- private void pollStateDone() {
- if (DBG) log("Poll ServiceState done: oldSS=[" + ss + "] newSS=[" + newSS + "]");
+ protected void pollStateDone() {
+ if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
boolean hasRegistered =
ss.getState() != ServiceState.STATE_IN_SERVICE
@@ -1043,15 +950,15 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
&& newSS.getState() != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionAttached =
- this.cdmaDataConnectionState != ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState == ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState != ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionDetached =
- this.cdmaDataConnectionState == ServiceState.STATE_IN_SERVICE
- && this.newCdmaDataConnectionState != ServiceState.STATE_IN_SERVICE;
+ mDataConnectionState == ServiceState.STATE_IN_SERVICE
+ && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
boolean hasCdmaDataConnectionChanged =
- cdmaDataConnectionState != newCdmaDataConnectionState;
+ mDataConnectionState != mNewDataConnectionState;
boolean hasNetworkTypeChanged = networkType != newNetworkType;
@@ -1065,10 +972,10 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
// Add an event log when connection state changes
if (ss.getState() != newSS.getState() ||
- cdmaDataConnectionState != newCdmaDataConnectionState) {
+ mDataConnectionState != mNewDataConnectionState) {
EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE,
- ss.getState(), cdmaDataConnectionState,
- newSS.getState(), newCdmaDataConnectionState);
+ ss.getState(), mDataConnectionState,
+ newSS.getState(), mNewDataConnectionState);
}
ServiceState tss;
@@ -1082,7 +989,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
cellLoc = newCellLoc;
newCellLoc = tcl;
- cdmaDataConnectionState = newCdmaDataConnectionState;
+ mDataConnectionState = mNewDataConnectionState;
networkType = newNetworkType;
// this new state has been applied - forget it until we get a new new state
newNetworkType = 0;
@@ -1095,7 +1002,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
if (hasRegistered) {
- networkAttachedRegistrants.notifyRegistrants();
+ mNetworkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
@@ -1129,9 +1036,9 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(
operatorNumeric.substring(0,3)));
} catch ( NumberFormatException ex){
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("pollStateDone: countryCodeForMcc error" + ex);
} catch ( StringIndexOutOfBoundsException ex) {
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("pollStateDone: countryCodeForMcc error" + ex);
}
phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
@@ -1150,11 +1057,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
if (hasCdmaDataConnectionAttached) {
- cdmaDataConnectionAttachedRegistrants.notifyRegistrants();
+ mAttachedRegistrants.notifyRegistrants();
}
if (hasCdmaDataConnectionDetached) {
- cdmaDataConnectionDetachedRegistrants.notifyRegistrants();
+ mDetachedRegistrants.notifyRegistrants();
}
if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) {
@@ -1162,11 +1069,11 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
if (hasRoamingOn) {
- roamingOnRegistrants.notifyRegistrants();
+ mRoamingOnRegistrants.notifyRegistrants();
}
if (hasRoamingOff) {
- roamingOffRegistrants.notifyRegistrants();
+ mRoamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
@@ -1213,7 +1120,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
* This code should probably be hoisted to the base class so
* the fix, when added, works for both.
*/
- private void
+ protected void
queueNextSignalStrengthPoll() {
if (dontPollSignalStrength || (cm.getRadioState().isGsm())) {
// The radio is telling us about signal strength changes
@@ -1234,7 +1141,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
* send signal-strength-changed notification if changed
* Called both for solicited and unsolicited signal strength updates
*/
- private void
+ protected void
onSignalStrengthResult(AsyncResult ar) {
SignalStrength oldSignalStrength = mSignalStrength;
@@ -1253,19 +1160,19 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
//log(String.format("onSignalStrengthResult cdmaDbm=%d cdmaEcio=%d evdoRssi=%d evdoEcio=%d evdoSnr=%d",
// cdmaDbm, cdmaEcio, evdoRssi, evdoEcio, evdoSnr));
mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio,
- evdoRssi, evdoEcio, evdoSnr, -1, -1, -1, -1, -1, false);
+ evdoRssi, evdoEcio, evdoSnr, false);
}
try {
phone.notifySignalStrength();
} catch (NullPointerException ex) {
- log("onSignalStrengthResult() Phone already destroyed: " + ex
+ loge("onSignalStrengthResult() Phone already destroyed: " + ex
+ "SignalStrength not notified");
}
}
- private int radioTechnologyToDataServiceState(int code) {
+ protected int radioTechnologyToDataServiceState(int code) {
int retVal = ServiceState.STATE_OUT_OF_SERVICE;
switch(code) {
case 0:
@@ -1279,17 +1186,18 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
case 7: // RADIO_TECHNOLOGY_EVDO_0
case 8: // RADIO_TECHNOLOGY_EVDO_A
case 12: // RADIO_TECHNOLOGY_EVDO_B
+ case 13: // RADIO_TECHNOLOGY_EHRPD
retVal = ServiceState.STATE_IN_SERVICE;
break;
default:
- Log.e(LOG_TAG, "Wrong radioTechnology code.");
+ loge("radioTechnologyToDataServiceState: Wrong radioTechnology code.");
break;
}
return(retVal);
}
/** code is registration state 0-5 from TS 27.007 7.2 */
- private int
+ protected int
regCodeToServiceState(int code) {
switch (code) {
case 0: // Not searching and not registered
@@ -1304,18 +1212,13 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
return ServiceState.STATE_IN_SERVICE;
default:
- Log.w(LOG_TAG, "unexpected service state " + code);
+ loge("regCodeToServiceState: unexpected service state " + code);
return ServiceState.STATE_OUT_OF_SERVICE;
}
}
- /**
- * @return The current CDMA data connection state. ServiceState.RADIO_TECHNOLOGY_1xRTT or
- * ServiceState.RADIO_TECHNOLOGY_EVDO is the same as "attached" and
- * ServiceState.RADIO_TECHNOLOGY_UNKNOWN is the same as detached.
- */
- /*package*/ int getCurrentCdmaDataConnectionState() {
- return cdmaDataConnectionState;
+ public int getCurrentDataConnectionState() {
+ return mDataConnectionState;
}
/**
@@ -1388,8 +1291,10 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
// tz is in number of quarter-hours
long start = SystemClock.elapsedRealtime();
- Log.i(LOG_TAG, "NITZ: " + nitz + "," + nitzReceiveTime +
+ if (DBG) {
+ log("NITZ: " + nitz + "," + nitzReceiveTime +
" start=" + start + " delay=" + (start - nitzReceiveTime));
+ }
try {
/* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
@@ -1486,7 +1391,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
String ignore = SystemProperties.get("gsm.ignore-nitz");
if (ignore != null && ignore.equals("yes")) {
- Log.i(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set");
+ if (DBG) log("NITZ: Not setting clock because gsm.ignore-nitz is set");
return;
}
@@ -1501,17 +1406,21 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (millisSinceNitzReceived < 0) {
// Sanity check: something is wrong
- Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
+ if (DBG) {
+ log("NITZ: not setting time, clock has rolled "
+ "backwards since NITZ time was received, "
+ nitz);
+ }
return;
}
if (millisSinceNitzReceived > Integer.MAX_VALUE) {
// If the time is this far off, something is wrong > 24 days!
- Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
+ if (DBG) {
+ log("NITZ: not setting time, processing has taken "
+ (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
+ " days");
+ }
return;
}
@@ -1531,14 +1440,18 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing)
|| (Math.abs(gained) > nitzUpdateDiff)) {
- Log.i(LOG_TAG, "NITZ: Auto updating time of day to " + c.getTime()
+ if (DBG) {
+ log("NITZ: Auto updating time of day to " + c.getTime()
+ " NITZ receive delay=" + millisSinceNitzReceived
+ "ms gained=" + gained + "ms from " + nitz);
+ }
setAndBroadcastNetworkSetTime(c.getTimeInMillis());
} else {
- Log.i(LOG_TAG, "NITZ: ignore, a previous update was "
+ if (DBG) {
+ log("NITZ: ignore, a previous update was "
+ timeSinceLastUpdate + "ms ago and gained=" + gained + "ms");
+ }
return;
}
}
@@ -1546,17 +1459,17 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
/**
* Update properties and save the time we did the update
*/
- Log.i(LOG_TAG, "NITZ: update nitz time property");
+ if (DBG) log("NITZ: update nitz time property");
SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
mSavedTime = c.getTimeInMillis();
mSavedAtTime = SystemClock.elapsedRealtime();
} finally {
long end = SystemClock.elapsedRealtime();
- Log.i(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
+ if (DBG) log("NITZ: end=" + end + " dur=" + (end - start));
mWakeLock.release();
}
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex);
+ loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex);
}
}
@@ -1614,8 +1527,9 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
if (Settings.System.getInt(cr, Settings.System.AUTO_TIME, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedTime
- + " mSavedAtTime=" + mSavedAtTime);
+ if (DBG) {
+ log("revertToNitzTime: mSavedTime=" + mSavedTime + " mSavedAtTime=" + mSavedAtTime);
+ }
if (mSavedTime != 0 && mSavedAtTime != 0) {
setAndBroadcastNetworkSetTime(mSavedTime
+ (SystemClock.elapsedRealtime() - mSavedAtTime));
@@ -1627,7 +1541,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
Settings.System.AUTO_TIME_ZONE, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
+ if (DBG) log("revertToNitzTimeZone: tz='" + mSavedTimeZone);
if (mSavedTimeZone != null) {
setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
}
@@ -1662,7 +1576,7 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
* @return true if phone is camping on a technology
* that could support voice and data simultaneously.
*/
- boolean isConcurrentVoiceAndData() {
+ public boolean isConcurrentVoiceAndDataAllowed() {
// Note: it needs to be confirmed which CDMA network types
// can support voice and data calls concurrently.
// For the time-being, the return value will be false.
@@ -1707,30 +1621,12 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
}
/**
- * process the pending request to turn radio off after data is disconnected
- *
- * return true if there is pending request to process; false otherwise.
- */
- public boolean processPendingRadioPowerOffAfterDataOff() {
- synchronized(this) {
- if (mPendingRadioPowerOffAfterDataOff) {
- if (DBG) log("Process pending request to turn radio off.");
- removeMessages(EVENT_SET_RADIO_POWER_OFF);
- hangupAndPowerOff();
- mPendingRadioPowerOffAfterDataOff = false;
- return true;
- }
- return false;
- }
- }
-
- /**
* Returns OTASP_UNKNOWN, OTASP_NEEDED or OTASP_NOT_NEEDED
*/
int getOtasp() {
int provisioningState;
if (mMin == null || (mMin.length() < 6)) {
- if (DBG) Log.d(LOG_TAG, "getOtasp: bad mMin='" + mMin + "'");
+ if (DBG) log("getOtasp: bad mMin='" + mMin + "'");
provisioningState = OTASP_UNKNOWN;
} else {
if ((mMin.equals(UNACTIVATED_MIN_VALUE)
@@ -1741,20 +1637,30 @@ final class CdmaServiceStateTracker extends ServiceStateTracker {
provisioningState = OTASP_NOT_NEEDED;
}
}
- if (DBG) Log.d(LOG_TAG, "getOtasp: state=" + provisioningState);
+ if (DBG) log("getOtasp: state=" + provisioningState);
return provisioningState;
}
@Override
- protected void log(String s) {
- Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s);
- }
-
- private void hangupAndPowerOff() {
+ protected void hangupAndPowerOff() {
// hang up all active voice calls
phone.mCT.ringingCall.hangupIfAlive();
phone.mCT.backgroundCall.hangupIfAlive();
phone.mCT.foregroundCall.hangupIfAlive();
cm.setRadioPower(false, null);
}
+
+ @Override
+ protected void log(String s) {
+ Log.d(LOG_TAG, "[CdmaSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[CdmaSST] " + s);
+ }
+
+ private static void slog(String s) {
+ Log.d(LOG_TAG, "[CdmaSST] " + s);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimCard.java b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
index 734badd..11f44d4 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
@@ -25,8 +25,8 @@ import com.android.internal.telephony.IccCard;
*/
public final class RuimCard extends IccCard {
- RuimCard(CDMAPhone phone) {
- super(phone, "CDMA", true);
+ RuimCard(CDMAPhone phone, String LOG_TAG, boolean dbg) {
+ super(phone, LOG_TAG, dbg);
mPhone.mCM.registerForRUIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mPhone.mCM.registerForRUIMReady(mHandler, EVENT_ICC_READY, null);
@@ -35,6 +35,7 @@ public final class RuimCard extends IccCard {
@Override
public void dispose() {
+ super.dispose();
//Unregister for all events
mPhone.mCM.unregisterForRUIMLockedOrAbsent(mHandler);
mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
@@ -43,7 +44,7 @@ public final class RuimCard extends IccCard {
@Override
public String getServiceProviderName () {
- return ((CDMAPhone)mPhone).mRuimRecords.getServiceProviderName();
+ return mPhone.mIccRecords.getServiceProviderName();
}
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
index 6e12f24..ce33066 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
@@ -32,7 +32,7 @@ public class RuimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager
public RuimPhoneBookInterfaceManager(CDMAPhone phone) {
super(phone);
- adnCache = phone.mRuimRecords.getAdnCache();
+ adnCache = phone.mIccRecords.getAdnCache();
//NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index 87b0c60..719eff3 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -87,18 +87,19 @@ public final class RuimRecords extends IccRecords {
p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
// NOTE the EVENT_SMS_ON_RUIM is not registered
- p.mCM.setOnIccRefresh(this, EVENT_RUIM_REFRESH, null);
+ p.mCM.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
// Start off by setting empty state
onRadioOffOrNotAvailable();
}
+ @Override
public void dispose() {
//Unregister for all events
phone.mCM.unregisterForRUIMReady(this);
phone.mCM.unregisterForOffOrNotAvailable( this);
- phone.mCM.unSetOnIccRefresh(this);
+ phone.mCM.unregisterForIccRefresh(this);
}
@Override
@@ -293,7 +294,7 @@ public final class RuimRecords extends IccRecords {
recordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
- ((CDMAPhone) phone).mRuimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
RuimCard.INTENT_VALUE_ICC_LOADED, null);
}
@@ -302,7 +303,7 @@ public final class RuimRecords extends IccRecords {
READY is sent before IMSI ready
*/
- ((CDMAPhone) phone).mRuimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
RuimCard.INTENT_VALUE_ICC_READY, null);
fetchRuimRecords();
@@ -324,8 +325,13 @@ public final class RuimRecords extends IccRecords {
// Further records that can be inserted are Operator/OEM dependent
}
+ /**
+ * {@inheritDoc}
+ *
+ * No Display rule for RUIMs yet.
+ */
@Override
- protected int getDisplayRule(String plmn) {
+ public int getDisplayRule(String plmn) {
// TODO together with spn
return 0;
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index cf06dab..7a45e15 100644..100755
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -34,6 +34,9 @@ import com.android.internal.telephony.SmsMessageBase.TextEncodingDetails;
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.BitwiseOutputStream;
+import android.content.res.Resources;
+
+
/**
* An object to encode and decode CDMA SMS bearer data.
@@ -582,7 +585,6 @@ public final class BearerData {
uData.payload = new byte[0];
uData.numFields = 0;
} else {
- uData.payload = uData.payload;
uData.numFields = uData.payload.length;
}
} else {
@@ -910,6 +912,16 @@ public final class BearerData {
return true;
}
+ private static String decodeUtf8(byte[] data, int offset, int numFields)
+ throws CodingException
+ {
+ try {
+ return new String(data, offset, numFields, "UTF-8");
+ } catch (java.io.UnsupportedEncodingException ex) {
+ throw new CodingException("UTF-8 decode failed: " + ex);
+ }
+ }
+
private static String decodeUtf16(byte[] data, int offset, int numFields)
throws CodingException
{
@@ -994,9 +1006,15 @@ public final class BearerData {
}
switch (userData.msgEncoding) {
case UserData.ENCODING_OCTET:
+ /*
+ * Octet decoding depends on the carrier service.
+ */
+ boolean decodingtypeUTF8 = Resources.getSystem()
+ .getBoolean(com.android.internal.R.bool.config_sms_utf8_support);
+
// Strip off any padding bytes, meaning any differences between the length of the
- // array and the target length specified by numFields. This is to avoid any confusion
- // by code elsewhere that only considers the payload array length.
+ // array and the target length specified by numFields. This is to avoid any
+ // confusion by code elsewhere that only considers the payload array length.
byte[] payload = new byte[userData.numFields];
int copyLen = userData.numFields < userData.payload.length
? userData.numFields : userData.payload.length;
@@ -1004,9 +1022,13 @@ public final class BearerData {
System.arraycopy(userData.payload, 0, payload, 0, copyLen);
userData.payload = payload;
- // There are many devices in the market that send 8bit text sms (latin encoded) as
- // octet encoded.
- userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
+ if (!decodingtypeUTF8) {
+ // There are many devices in the market that send 8bit text sms (latin encoded) as
+ // octet encoded.
+ userData.payloadStr = decodeLatin(userData.payload, offset, userData.numFields);
+ } else {
+ userData.payloadStr = decodeUtf8(userData.payload, offset, userData.numFields);
+ }
break;
case UserData.ENCODING_IA5:
case UserData.ENCODING_7BIT_ASCII:
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index c17197e..3ccc03d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -33,6 +33,7 @@ import android.telephony.CellLocation;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
+import com.android.internal.telephony.CallTracker;
import android.text.TextUtils;
import android.util.Log;
@@ -72,6 +73,7 @@ import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.UUSInfo;
import com.android.internal.telephony.test.SimulatedRadioControl;
import com.android.internal.telephony.IccVmNotSupportedException;
+import com.android.internal.telephony.ServiceStateTracker;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -100,9 +102,6 @@ public class GSMPhone extends PhoneBase {
// Instance Variables
GsmCallTracker mCT;
GsmServiceStateTracker mSST;
- GsmSMSDispatcher mSMS;
- SIMRecords mSIMRecords;
- SimCard mSimCard;
CatService mStkService;
ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
@@ -143,24 +142,23 @@ public class GSMPhone extends PhoneBase {
mSST = new GsmServiceStateTracker (this);
mSMS = new GsmSMSDispatcher(this);
mIccFileHandler = new SIMFileHandler(this);
- mSIMRecords = new SIMRecords(this);
- mDataConnection = new GsmDataConnectionTracker (this);
- mSimCard = new SimCard(this);
+ mIccRecords = new SIMRecords(this);
+ mDataConnectionTracker = new GsmDataConnectionTracker (this);
+ mIccCard = new SimCard(this);
if (!unitTestMode) {
mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
mSimSmsIntManager = new SimSmsInterfaceManager(this, mSMS);
mSubInfo = new PhoneSubInfo(this);
}
- mStkService = CatService.getInstance(mCM, mSIMRecords, mContext,
- (SIMFileHandler)mIccFileHandler, mSimCard);
+ mStkService = CatService.getInstance(mCM, mIccRecords, mContext, mIccFileHandler, mIccCard);
mCM.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
- mSIMRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
+ mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
mCM.registerForOn(this, EVENT_RADIO_ON, null);
mCM.setOnUSSD(this, EVENT_USSD, null);
mCM.setOnSuppServiceNotification(this, EVENT_SSN, null);
- mSST.registerForNetworkAttach(this, EVENT_REGISTERED_TO_NETWORK, null);
+ mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
if (false) {
try {
@@ -207,10 +205,10 @@ public class GSMPhone extends PhoneBase {
//Unregister from all former registered events
mCM.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
- mSIMRecords.unregisterForRecordsLoaded(this); //EVENT_SIM_RECORDS_LOADED
+ mIccRecords.unregisterForRecordsLoaded(this); //EVENT_SIM_RECORDS_LOADED
mCM.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
mCM.unregisterForOn(this); //EVENT_RADIO_ON
- mSST.unregisterForNetworkAttach(this); //EVENT_REGISTERED_TO_NETWORK
+ mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
mCM.unSetOnUSSD(this);
mCM.unSetOnSuppServiceNotification(this);
@@ -219,11 +217,11 @@ public class GSMPhone extends PhoneBase {
//Force all referenced classes to unregister their former registered events
mStkService.dispose();
mCT.dispose();
- mDataConnection.dispose();
+ mDataConnectionTracker.dispose();
mSST.dispose();
mIccFileHandler.dispose(); // instance of SimFileHandler
- mSIMRecords.dispose();
- mSimCard.dispose();
+ mIccRecords.dispose();
+ mIccCard.dispose();
mSimPhoneBookIntManager.dispose();
mSimSmsIntManager.dispose();
mSubInfo.dispose();
@@ -237,10 +235,10 @@ public class GSMPhone extends PhoneBase {
this.mSimSmsIntManager = null;
this.mSMS = null;
this.mSubInfo = null;
- this.mSIMRecords = null;
+ this.mIccRecords = null;
this.mIccFileHandler = null;
- this.mSimCard = null;
- this.mDataConnection = null;
+ this.mIccCard = null;
+ this.mDataConnectionTracker = null;
this.mCT = null;
this.mSST = null;
}
@@ -275,12 +273,12 @@ public class GSMPhone extends PhoneBase {
return mSST.mSignalStrength;
}
- public boolean getMessageWaitingIndicator() {
- return mSIMRecords.getVoiceMessageWaiting();
+ public CallTracker getCallTracker() {
+ return mCT;
}
- public boolean getCallForwardingIndicator() {
- return mSIMRecords.getVoiceCallForwardingFlag();
+ public ServiceStateTracker getServiceStateTracker() {
+ return mSST;
}
public List<? extends MmiCode>
@@ -301,11 +299,11 @@ public class GSMPhone extends PhoneBase {
// If we're out of service, open TCP sockets may still work
// but no data will flow
ret = DataState.DISCONNECTED;
- } else if (mDataConnection.isApnTypeEnabled(apnType) == false ||
- mDataConnection.isApnTypeActive(apnType) == false) {
+ } else if (mDataConnectionTracker.isApnTypeEnabled(apnType) == false ||
+ mDataConnectionTracker.isApnTypeActive(apnType) == false) {
ret = DataState.DISCONNECTED;
} else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
- switch (mDataConnection.getState()) {
+ switch (mDataConnectionTracker.getState(apnType)) {
case FAILED:
case IDLE:
ret = DataState.DISCONNECTED;
@@ -314,7 +312,7 @@ public class GSMPhone extends PhoneBase {
case CONNECTED:
case DISCONNECTING:
if ( mCT.state != Phone.State.IDLE
- && !mSST.isConcurrentVoiceAndData()) {
+ && !mSST.isConcurrentVoiceAndDataAllowed()) {
ret = DataState.SUSPENDED;
} else {
ret = DataState.CONNECTED;
@@ -336,7 +334,7 @@ public class GSMPhone extends PhoneBase {
DataActivityState ret = DataActivityState.NONE;
if (mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE) {
- switch (mDataConnection.getActivity()) {
+ switch (mDataConnectionTracker.getActivity()) {
case DATAIN:
ret = DataActivityState.DATAIN;
break;
@@ -404,7 +402,7 @@ public class GSMPhone extends PhoneBase {
mNotifier.notifySignalStrength(this);
}
- /*package*/ void
+ public void
notifyDataConnectionFailed(String reason, String apnType) {
mNotifier.notifyDataConnectionFailed(this, reason, apnType);
}
@@ -412,7 +410,7 @@ public class GSMPhone extends PhoneBase {
/*package*/ void
updateMessageWaitingIndicator(boolean mwi) {
// this also calls notifyMessageWaitingIndicator()
- mSIMRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
+ mIccRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
}
public void
@@ -813,7 +811,7 @@ public class GSMPhone extends PhoneBase {
public String getVoiceMailNumber() {
// Read from the SIM. If its null, try reading from the shared preference area.
- String number = mSIMRecords.getVoiceMailNumber();
+ String number = mIccRecords.getVoiceMailNumber();
if (TextUtils.isEmpty(number)) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
number = sp.getString(VM_NUMBER, null);
@@ -836,7 +834,7 @@ public class GSMPhone extends PhoneBase {
public String getVoiceMailAlphaTag() {
String ret;
- ret = mSIMRecords.getVoiceMailAlphaTag();
+ ret = mIccRecords.getVoiceMailAlphaTag();
if (ret == null || ret.length() == 0) {
return mContext.getText(
@@ -865,23 +863,19 @@ public class GSMPhone extends PhoneBase {
}
public String getSubscriberId() {
- return mSIMRecords.imsi;
- }
-
- public String getIccSerialNumber() {
- return mSIMRecords.iccid;
+ return mIccRecords.getIMSI();
}
public String getLine1Number() {
- return mSIMRecords.getMsisdnNumber();
+ return mIccRecords.getMsisdnNumber();
}
public String getLine1AlphaTag() {
- return mSIMRecords.getMsisdnAlphaTag();
+ return mIccRecords.getMsisdnAlphaTag();
}
public void setLine1Number(String alphaTag, String number, Message onComplete) {
- mSIMRecords.setMsisdnNumber(alphaTag, number, onComplete);
+ mIccRecords.setMsisdnNumber(alphaTag, number, onComplete);
}
public void setVoiceMailNumber(String alphaTag,
@@ -891,7 +885,7 @@ public class GSMPhone extends PhoneBase {
Message resp;
mVmNumber = voiceMailNumber;
resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
- mSIMRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
+ mIccRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
}
private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
@@ -981,15 +975,6 @@ public class GSMPhone extends PhoneBase {
mCM.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
}
- public boolean
- getIccRecordsLoaded() {
- return mSIMRecords.getRecordsLoaded();
- }
-
- public IccCard getIccCard() {
- return mSimCard;
- }
-
public void
getAvailableNetworks(Message response) {
mCM.getAvailableNetworks(response);
@@ -1062,10 +1047,6 @@ public class GSMPhone extends PhoneBase {
mCM.getDataCallList(response);
}
- public List<DataConnection> getCurrentDataConnectionList () {
- return mDataConnection.getAllDataConnections();
- }
-
public void updateServiceLocation() {
mSST.enableSingleLocationUpdate();
}
@@ -1079,11 +1060,11 @@ public class GSMPhone extends PhoneBase {
}
public boolean getDataRoamingEnabled() {
- return mDataConnection.getDataOnRoamingEnabled();
+ return mDataConnectionTracker.getDataOnRoamingEnabled();
}
public void setDataRoamingEnabled(boolean enable) {
- mDataConnection.setDataOnRoamingEnabled(enable);
+ mDataConnectionTracker.setDataOnRoamingEnabled(enable);
}
/**
@@ -1273,7 +1254,7 @@ public class GSMPhone extends PhoneBase {
case EVENT_SET_CALL_FORWARD_DONE:
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
- mSIMRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1);
+ mIccRecords.setVoiceCallForwardingFlag(1, msg.arg1 == 1);
}
onComplete = (Message) ar.userObj;
if (onComplete != null) {
@@ -1337,11 +1318,11 @@ public class GSMPhone extends PhoneBase {
* @return true for success; false otherwise.
*/
boolean updateCurrentCarrierInProvider() {
- if (mSIMRecords != null) {
+ if (mIccRecords != null) {
try {
Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
ContentValues map = new ContentValues();
- map.put(Telephony.Carriers.NUMERIC, mSIMRecords.getSIMOperatorNumeric());
+ map.put(Telephony.Carriers.NUMERIC, mIccRecords.getOperatorNumeric());
mContext.getContentResolver().insert(uri, map);
return true;
} catch (SQLException e) {
@@ -1406,11 +1387,11 @@ public class GSMPhone extends PhoneBase {
if (infos == null || infos.length == 0) {
// Assume the default is not active
// Set unconditional CFF in SIM to false
- mSIMRecords.setVoiceCallForwardingFlag(1, false);
+ mIccRecords.setVoiceCallForwardingFlag(1, false);
} else {
for (int i = 0, s = infos.length; i < s; i++) {
if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) {
- mSIMRecords.setVoiceCallForwardingFlag(1, (infos[i].status == 1));
+ mIccRecords.setVoiceCallForwardingFlag(1, (infos[i].status == 1));
// should only have the one
break;
}
@@ -1459,6 +1440,6 @@ public class GSMPhone extends PhoneBase {
}
public boolean isCspPlmnEnabled() {
- return mSIMRecords.isCspPlmnEnabled();
+ return mIccRecords.isCspPlmnEnabled();
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index 7dc2504..0870d5b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -374,11 +374,11 @@ public class GsmConnection extends Connection {
} else if (phone.getIccCard().getState() != SimCard.State.READY) {
return DisconnectCause.ICC_ERROR;
} else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
- if (phone.mSST.rs.isCsRestricted()) {
+ if (phone.mSST.mRestrictedState.isCsRestricted()) {
return DisconnectCause.CS_RESTRICTED;
- } else if (phone.mSST.rs.isCsEmergencyRestricted()) {
+ } else if (phone.mSST.mRestrictedState.isCsEmergencyRestricted()) {
return DisconnectCause.CS_RESTRICTED_EMERGENCY;
- } else if (phone.mSST.rs.isCsNormalRestricted()) {
+ } else if (phone.mSST.mRestrictedState.isCsNormalRestricted()) {
return DisconnectCause.CS_RESTRICTED_NORMAL;
} else {
return DisconnectCause.ERROR_UNSPECIFIED;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 4689b2d..9695344 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -19,10 +19,11 @@ package com.android.internal.telephony.gsm;
import android.os.Message;
import android.util.Log;
import android.util.Patterns;
+import android.text.TextUtils;
-import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
@@ -34,11 +35,11 @@ public class GsmDataConnection extends DataConnection {
private static final String LOG_TAG = "GSM";
//***** Instance Variables
- private ApnSetting apn;
-
+ protected int mProfileId = RILConstants.DATA_PROFILE_DEFAULT;
+ protected String mActiveApnType = Phone.APN_TYPE_DEFAULT;
//***** Constructor
- private GsmDataConnection(GSMPhone phone, String name, RetryManager rm) {
- super(phone, name, rm);
+ private GsmDataConnection(PhoneBase phone, String name, int id, RetryManager rm) {
+ super(phone, name, id, rm);
}
/**
@@ -49,15 +50,13 @@ public class GsmDataConnection extends DataConnection {
* @param rm the RetryManager
* @return GsmDataConnection that was created.
*/
- static GsmDataConnection makeDataConnection(GSMPhone phone, int id, RetryManager rm) {
+ static GsmDataConnection makeDataConnection(PhoneBase phone, int id, RetryManager rm) {
synchronized (mCountLock) {
mCount += 1;
}
- GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDataConnection-" + mCount, rm);
+ GsmDataConnection gsmDc = new GsmDataConnection(phone, "GsmDC-" + mCount, id, rm);
gsmDc.start();
if (DBG) gsmDc.log("Made " + gsmDc.getName());
- gsmDc.mId = id;
- gsmDc.mRetryMgr = rm;
return gsmDc;
}
@@ -71,13 +70,13 @@ public class GsmDataConnection extends DataConnection {
@Override
protected
void onConnect(ConnectionParams cp) {
- apn = cp.apn;
+ mApn = cp.apn;
- if (DBG) log("Connecting to carrier: '" + apn.carrier
- + "' APN: '" + apn.apn
- + "' proxy: '" + apn.proxy + "' port: '" + apn.port);
+ if (DBG) log("Connecting to carrier: '" + mApn.carrier
+ + "' APN: '" + mApn.apn
+ + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
- setHttpProxy (apn.proxy, apn.port);
+ setHttpProxy (mApn.proxy, mApn.port);
createTime = -1;
lastFailTime = -1;
@@ -87,35 +86,42 @@ public class GsmDataConnection extends DataConnection {
Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
msg.obj = cp;
- int authType = apn.authType;
+ int authType = mApn.authType;
if (authType == -1) {
- authType = (apn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
+ authType = (mApn.user != null) ? RILConstants.SETUP_DATA_AUTH_PAP_CHAP :
RILConstants.SETUP_DATA_AUTH_NONE;
}
String protocol;
if (phone.getServiceState().getRoaming()) {
- protocol = apn.roamingProtocol;
+ protocol = mApn.roamingProtocol;
} else {
- protocol = apn.protocol;
+ protocol = mApn.protocol;
}
phone.mCM.setupDataCall(
- Integer.toString(RILConstants.SETUP_DATA_TECH_GSM),
- Integer.toString(RILConstants.DATA_PROFILE_DEFAULT),
- apn.apn, apn.user, apn.password, Integer.toString(authType),
+ Integer.toString(getRadioTechnology(RILConstants.SETUP_DATA_TECH_GSM)),
+ Integer.toString(mProfileId),
+ mApn.apn, mApn.user, mApn.password,
+ Integer.toString(authType),
protocol, msg);
}
- @Override
- protected void clearSettings() {
- super.clearSettings();
- apn = null;
+ public void setProfileId(int profileId) {
+ mProfileId = profileId;
+ }
+
+ public int getProfileId() {
+ return mProfileId;
+ }
+
+ public void setActiveApnType(String apnType) {
+ mActiveApnType = apnType;
}
@Override
public String toString() {
- return "State=" + getCurrentState().getName() + " Apn=" + apn +
+ return "State=" + getCurrentState().getName() + " Apn=" + mApn +
" create=" + createTime + " lastFail=" + lastFailTime +
" lastFailCause=" + lastFailCause;
}
@@ -123,17 +129,18 @@ public class GsmDataConnection extends DataConnection {
@Override
protected boolean isDnsOk(String[] domainNameServers) {
if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
- && !((GSMPhone) phone).isDnsCheckDisabled()) {
+ && !phone.isDnsCheckDisabled()) {
// Work around a race condition where QMI does not fill in DNS:
// Deactivate PDP and let DataConnectionTracker retry.
// Do not apply the race condition workaround for MMS APN
// if Proxy is an IP-address.
// Otherwise, the default APN will not be restored anymore.
- if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
- || !isIpAddress(apn.mmsProxy)) {
+ if (!mApn.types[0].equals(Phone.APN_TYPE_MMS)
+ || !isIpAddress(mApn.mmsProxy)) {
log(String.format(
"isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s",
- apn.types[0], Phone.APN_TYPE_MMS, apn.mmsProxy, isIpAddress(apn.mmsProxy)));
+ mApn.types[0], Phone.APN_TYPE_MMS, mApn.mmsProxy,
+ isIpAddress(mApn.mmsProxy)));
return false;
}
}
@@ -145,27 +152,41 @@ public class GsmDataConnection extends DataConnection {
Log.d(LOG_TAG, "[" + getName() + "] " + s);
}
- public ApnSetting getApn() {
- return this.apn;
- }
-
private void setHttpProxy(String httpProxy, String httpPort) {
- if (httpProxy == null || httpProxy.length() == 0) {
- phone.setSystemProperty("net.gprs.http-proxy", null);
- return;
- }
- if (httpPort == null || httpPort.length() == 0) {
- httpPort = "8080"; // Default to port 8080
- }
+ if (DBG) log("set http proxy for"
+ + "' APN: '" + mActiveApnType
+ + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
+ if(TextUtils.equals(mActiveApnType, Phone.APN_TYPE_DEFAULT)) {
+ if (httpProxy == null || httpProxy.length() == 0) {
+ phone.setSystemProperty("net.gprs.http-proxy", null);
+ return;
+ }
+
+ if (httpPort == null || httpPort.length() == 0) {
+ httpPort = "8080"; // Default to port 8080
+ }
- phone.setSystemProperty("net.gprs.http-proxy",
- "http://" + httpProxy + ":" + httpPort + "/");
+ phone.setSystemProperty("net.gprs.http-proxy",
+ "http://" + httpProxy + ":" + httpPort + "/");
+ } else {
+ if (httpProxy == null || httpProxy.length() == 0) {
+ phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, null);
+ return;
+ }
+
+ if (httpPort == null || httpPort.length() == 0) {
+ httpPort = "8080"; // Default to port 8080
+ }
+
+ phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType,
+ "http://" + httpProxy + ":" + httpPort + "/");
+ }
}
private boolean isIpAddress(String address) {
if (address == null) return false;
- return Patterns.IP_ADDRESS.matcher(apn.mmsProxy).matches();
+ return Patterns.IP_ADDRESS.matcher(address).matches();
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index c57f2f1..f6485a4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -22,38 +22,54 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.database.ContentObserver;
import android.database.Cursor;
+import android.net.ConnectivityManager;
import android.net.ProxyProperties;
import android.net.TrafficStats;
import android.net.Uri;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.NetworkConfig;
import android.os.AsyncResult;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.provider.Telephony;
+import android.telephony.CellLocation;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
+import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
import android.util.EventLog;
import android.util.Log;
+import android.preference.PreferenceManager;
import com.android.internal.R;
+import com.android.internal.telephony.ApnContext;
import com.android.internal.telephony.ApnSetting;
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionAc;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.AsyncChannel;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
import java.util.HashMap;
/**
@@ -62,7 +78,6 @@ import java.util.HashMap;
public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected final String LOG_TAG = "GSM";
- private GSMPhone mGsmPhone;
/**
* Handles changes to the APN db.
*/
@@ -86,70 +101,63 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// call reRegisterNetwork, or pingTest succeeds.
private int mPdpResetCount = 0;
- /** Delay between APN attempts */
- protected static final int APN_DELAY_MILLIS = 5000;
+ // Recovery action taken in case of data stall
+ enum RecoveryAction {REREGISTER, RADIO_RESTART, RADIO_RESET};
+ private RecoveryAction mRecoveryAction = RecoveryAction.REREGISTER;
- //useful for debugging
- boolean mFailNextConnect = false;
-
- /**
- * allApns holds all apns for this sim spn, retrieved from
- * the Carrier DB.
- *
- * Create once after simcard info is loaded
- */
- private ArrayList<ApnSetting> mAllApns = null;
-
- /**
- * waitingApns holds all apns that are waiting to be connected
- *
- * It is a subset of allApns and has the same format
- */
- private ArrayList<ApnSetting> mWaitingApns = null;
- private int mWaitingApnsPermanentFailureCountDown = 0;
- private ApnSetting mPreferredApn = null;
-
- /** The DataConnection being setup */
- private GsmDataConnection mPendingDataConnection;
-
- /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
- private HashMap<String, Integer> mApnToDataConnectionId =
- new HashMap<String, Integer>();
-
- /** Is packet service restricted by network */
- private boolean mIsPsRestricted = false;
//***** Constants
private static final int POLL_PDP_MILLIS = 5 * 1000;
private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
+ private static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "type";
static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
static final String APN_ID = "apn_id";
private boolean canSetPreferApn = false;
+ private boolean mRadioAvailable = false;
+
+ @Override
+ protected void onActionIntentReconnectAlarm(Intent intent) {
+ if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
+
+ String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+ String type = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
+ ApnContext apnContext = mApnContexts.get(type);
+ if (apnContext != null) {
+ apnContext.setReason(reason);
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ }
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, apnContext));
+ }
+ }
/** Watches for changes to the APN db. */
private ApnChangeObserver mApnObserver;
//***** Constructor
- GsmDataConnectionTracker(GSMPhone p) {
+ public GsmDataConnectionTracker(PhoneBase p) {
super(p);
- mGsmPhone = p;
p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
- p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+ p.mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
p.mCM.registerForDataNetworkStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
- p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
- p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
- p.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
- p.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
- p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
- p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
- p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
- p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
+ p.getCallTracker().registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
+ p.getCallTracker().registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
+ p.getServiceStateTracker().registerForDataConnectionAttached(this,
+ EVENT_DATA_CONNECTION_ATTACHED, null);
+ p.getServiceStateTracker().registerForDataConnectionDetached(this,
+ EVENT_DATA_CONNECTION_DETACHED, null);
+ p.getServiceStateTracker().registerForRoamingOn(this, EVENT_ROAMING_ON, null);
+ p.getServiceStateTracker().registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+ p.getServiceStateTracker().registerForPsRestrictedEnabled(this,
+ EVENT_PS_RESTRICT_ENABLED, null);
+ p.getServiceStateTracker().registerForPsRestrictedDisabled(this,
+ EVENT_PS_RESTRICT_DISABLED, null);
mDataConnectionTracker = this;
mResolver = mPhone.getContext().getContentResolver();
@@ -158,35 +166,90 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
p.getContext().getContentResolver().registerContentObserver(
Telephony.Carriers.CONTENT_URI, true, mApnObserver);
- /** Create the default connection */
- createDataConnection(Phone.APN_TYPE_DEFAULT);
+ mApnContexts = new ConcurrentHashMap<String, ApnContext>();
+ initApnContextsAndDataConnection();
broadcastMessenger();
}
@Override
public void dispose() {
+ cleanUpAllConnections(false, null);
+
super.dispose();
//Unregister for all events
mPhone.mCM.unregisterForAvailable(this);
mPhone.mCM.unregisterForOffOrNotAvailable(this);
- mGsmPhone.mSIMRecords.unregisterForRecordsLoaded(this);
+ mPhone.mIccRecords.unregisterForRecordsLoaded(this);
mPhone.mCM.unregisterForDataNetworkStateChanged(this);
- mGsmPhone.mCT.unregisterForVoiceCallEnded(this);
- mGsmPhone.mCT.unregisterForVoiceCallStarted(this);
- mGsmPhone.mSST.unregisterForGprsAttached(this);
- mGsmPhone.mSST.unregisterForGprsDetached(this);
- mGsmPhone.mSST.unregisterForRoamingOn(this);
- mGsmPhone.mSST.unregisterForRoamingOff(this);
- mGsmPhone.mSST.unregisterForPsRestrictedEnabled(this);
- mGsmPhone.mSST.unregisterForPsRestrictedDisabled(this);
+ mPhone.getCallTracker().unregisterForVoiceCallEnded(this);
+ mPhone.getCallTracker().unregisterForVoiceCallStarted(this);
+ mPhone.getServiceStateTracker().unregisterForDataConnectionAttached(this);
+ mPhone.getServiceStateTracker().unregisterForDataConnectionDetached(this);
+ mPhone.getServiceStateTracker().unregisterForRoamingOn(this);
+ mPhone.getServiceStateTracker().unregisterForRoamingOff(this);
+ mPhone.getServiceStateTracker().unregisterForPsRestrictedEnabled(this);
+ mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
mPhone.getContext().getContentResolver().unregisterContentObserver(this.mApnObserver);
+ mApnContexts.clear();
destroyDataConnections();
}
@Override
+ public boolean isApnTypeActive(String type) {
+ ApnContext apnContext = mApnContexts.get(type);
+ if (apnContext == null) return false;
+
+ return (apnContext.getDataConnection() != null);
+ }
+
+ /**
+ * The only circumstances under which we report that data connectivity is not
+ * possible are
+ * <ul>
+ * <li>Data is disallowed (roaming, power state, voice call, etc).</li>
+ * <li>The current data state is {@code DISCONNECTED} for a reason other than
+ * having explicitly disabled connectivity. In other words, data is not available
+ * because the phone is out of coverage or some like reason.</li>
+ * </ul>
+ * @return {@code true} if data connectivity is possible, {@code false} otherwise.
+ * TODO - do per-apn notifications of availability using dependencyMet values.
+ */
+ @Override
+ protected boolean isDataPossible() {
+ boolean possible = (isDataAllowed()
+ && !(getAnyDataEnabled() && (getOverallState() == State.FAILED)));
+ if (!possible && DBG && isDataAllowed()) {
+ if (DBG) log("Data not possible. No coverage: dataState = " + getOverallState());
+ }
+ return possible;
+ }
+
+ @Override
+ protected boolean isDataPossible(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null) {
+ return false;
+ }
+ boolean apnContextIsEnabled = apnContext.isEnabled();
+ State apnContextState = apnContext.getState();
+ boolean apnTypePossible = !(apnContextIsEnabled &&
+ (apnContextState == State.FAILED));
+ boolean dataAllowed = isDataAllowed();
+ boolean possible = dataAllowed && apnTypePossible;
+
+ if (DBG) {
+ log(String.format("isDataPossible(%s): possible=%b isDataAllowed=%b " +
+ "apnTypePossible=%b apnContextisEnabled=%b apnContextState()=%s",
+ apnType, possible, dataAllowed, apnTypePossible,
+ apnContextIsEnabled, apnContextState));
+ }
+ return possible;
+ }
+
+ @Override
protected void finalize() {
if(DBG) log("finalize");
}
@@ -196,47 +259,262 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return INTENT_RECONNECT_ALARM;
}
+ private ApnContext addApnContext(String type) {
+ ApnContext apnContext = new ApnContext(type, LOG_TAG);
+ apnContext.setDependencyMet(false);
+ mApnContexts.put(type, apnContext);
+ return apnContext;
+ }
+
+ protected void initApnContextsAndDataConnection() {
+ boolean defaultEnabled = SystemProperties.getBoolean(DEFALUT_DATA_ON_BOOT_PROP, true);
+ // Load device network attributes from resources
+ String[] networkConfigStrings = mPhone.getContext().getResources().getStringArray(
+ com.android.internal.R.array.networkAttributes);
+ for (String networkConfigString : networkConfigStrings) {
+ NetworkConfig networkConfig = new NetworkConfig(networkConfigString);
+ ApnContext apnContext = null;
+
+ switch (networkConfig.type) {
+ case ConnectivityManager.TYPE_MOBILE:
+ apnContext = addApnContext(Phone.APN_TYPE_DEFAULT);
+ apnContext.setEnabled(defaultEnabled);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_MMS:
+ apnContext = addApnContext(Phone.APN_TYPE_MMS);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_SUPL:
+ apnContext = addApnContext(Phone.APN_TYPE_SUPL);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_DUN:
+ apnContext = addApnContext(Phone.APN_TYPE_DUN);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_HIPRI:
+ apnContext = addApnContext(Phone.APN_TYPE_HIPRI);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_FOTA:
+ apnContext = addApnContext(Phone.APN_TYPE_FOTA);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_IMS:
+ apnContext = addApnContext(Phone.APN_TYPE_IMS);
+ break;
+ case ConnectivityManager.TYPE_MOBILE_CBS:
+ apnContext = addApnContext(Phone.APN_TYPE_CBS);
+ break;
+ default:
+ // skip unknown types
+ continue;
+ }
+ if (apnContext != null) {
+ // set the prop, but also apply the newly set enabled and dependency values
+ onSetDependencyMet(apnContext.getApnType(), networkConfig.dependencyMet);
+ }
+ }
+ }
+
+ @Override
+ protected LinkProperties getLinkProperties(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext != null) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac != null) {
+ if (DBG) log("return link properites for " + apnType);
+ return dcac.getLinkPropertiesSync();
+ }
+ }
+ if (DBG) log("return new LinkProperties");
+ return new LinkProperties();
+ }
+
+ @Override
+ protected LinkCapabilities getLinkCapabilities(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext!=null) {
+ DataConnectionAc dataConnectionAc = apnContext.getDataConnectionAc();
+ if (dataConnectionAc != null) {
+ if (DBG) log("get active pdp is not null, return link Capabilities for " + apnType);
+ return dataConnectionAc.getLinkCapabilitiesSync();
+ }
+ }
+ if (DBG) log("return new LinkCapabilities");
+ return new LinkCapabilities();
+ }
+
+ @Override
+ // Return all active apn types
+ public String[] getActiveApnTypes() {
+ if (DBG) log("get all active apn types");
+ ArrayList<String> result = new ArrayList<String>();
+
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isReady()) {
+ result.add(apnContext.getApnType());
+ }
+ }
+
+ return (String[])result.toArray(new String[0]);
+ }
+
+ @Override
+ // Return active apn of specific apn type
+ public String getActiveApnString(String apnType) {
+ if (DBG) log( "get active apn string for type:" + apnType);
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext != null) {
+ ApnSetting apnSetting = apnContext.getApnSetting();
+ if (apnSetting != null) {
+ return apnSetting.apn;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isApnTypeEnabled(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null) {
+ return false;
+ }
+ return apnContext.isEnabled();
+ }
+
@Override
protected void setState(State s) {
- if (DBG) log ("setState: " + s);
- if (mState != s) {
- EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, mState.toString(), s.toString());
- mState = s;
+ if (DBG) log("setState should not be used in GSM" + s);
+ }
+
+ // Return state of specific apn type
+ @Override
+ public State getState(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext != null) {
+ return apnContext.getState();
+ }
+ return State.FAILED;
+ }
+
+ // Return state of overall
+ public State getOverallState() {
+ boolean isConnecting = false;
+ boolean isFailed = true; // All enabled Apns should be FAILED.
+ boolean isAnyEnabled = false;
+
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isEnabled()) {
+ isAnyEnabled = true;
+ switch (apnContext.getState()) {
+ case CONNECTED:
+ case DISCONNECTING:
+ if (DBG) log("overall state is CONNECTED");
+ return State.CONNECTED;
+ case CONNECTING:
+ case INITING:
+ isConnecting = true;
+ isFailed = false;
+ break;
+ case IDLE:
+ case SCANNING:
+ isFailed = false;
+ break;
+ }
+ }
+ }
+
+ if (!isAnyEnabled) { // Nothing enabled. return IDLE.
+ if (DBG) log( "overall state is IDLE");
+ return State.IDLE;
}
- if (mState == State.FAILED) {
- if (mWaitingApns != null)
- mWaitingApns.clear(); // when tear down the connection and set to IDLE
+ if (isConnecting) {
+ if (DBG) log( "overall state is CONNECTING");
+ return State.CONNECTING;
+ } else if (!isFailed) {
+ if (DBG) log( "overall state is IDLE");
+ return State.IDLE;
+ } else {
+ if (DBG) log( "overall state is FAILED");
+ return State.FAILED;
}
}
/**
- * The data connection is expected to be setup while device
- * 1. has sim card
- * 2. registered to gprs service
- * 3. user doesn't explicitly disable data service
- * 4. wifi is not on
+ * Ensure that we are connected to an APN of the specified type.
*
- * @return false while no data connection if all above requirements are met.
+ * @param type the APN type
+ * @return Success is indicated by {@code Phone.APN_ALREADY_ACTIVE} or
+ * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a
+ * broadcast will be sent by the ConnectivityManager when a
+ * connection to the APN has been established.
*/
@Override
- public boolean isDataConnectionAsDesired() {
- boolean roaming = mPhone.getServiceState().getRoaming();
+ public synchronized int enableApnType(String apnType) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null || !isApnTypeAvailable(apnType)) {
+ if (DBG) log("enableApnType: " + apnType + " is type not available");
+ return Phone.APN_TYPE_NOT_AVAILABLE;
+ }
- if (mGsmPhone.mSIMRecords.getRecordsLoaded() &&
- mGsmPhone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
- (!roaming || getDataOnRoamingEnabled()) &&
- !mIsWifiConnected &&
- !mIsPsRestricted ) {
- return (mState == State.CONNECTED);
+ // If already active, return
+ if (DBG) log("enableApnType: " + apnType + " mState(" + apnContext.getState() + ")");
+
+ if (apnContext.getState() == State.CONNECTED) {
+ if (DBG) log("enableApnType: return APN_ALREADY_ACTIVE");
+ return Phone.APN_ALREADY_ACTIVE;
+ }
+ setEnabled(apnTypeToId(apnType), true);
+ if (DBG) {
+ log("enableApnType: new apn request for type " + apnType +
+ " return APN_REQUEST_STARTED");
+ }
+ return Phone.APN_REQUEST_STARTED;
+ }
+
+ // A new APN has gone active and needs to send events to catch up with the
+ // current condition
+ private void notifyApnIdUpToCurrent(String reason, ApnContext apnContext, String type) {
+ switch (apnContext.getState()) {
+ case IDLE:
+ case INITING:
+ break;
+ case CONNECTING:
+ case SCANNING:
+ mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTING);
+ break;
+ case CONNECTED:
+ case DISCONNECTING:
+ mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTING);
+ mPhone.notifyDataConnection(reason, type, Phone.DataState.CONNECTED);
+ break;
+ }
+ }
+
+ @Override
+ public synchronized int disableApnType(String type) {
+ if (DBG) log("disableApnType:" + type);
+ ApnContext apnContext = mApnContexts.get(type);
+
+ if (apnContext != null) {
+ setEnabled(apnTypeToId(type), false);
+ if (apnContext.getState() != State.IDLE && apnContext.getState() != State.FAILED) {
+ if (DBG) log("diableApnType: return APN_REQUEST_STARTED");
+ return Phone.APN_REQUEST_STARTED;
+ } else {
+ if (DBG) log("disableApnType: return APN_ALREADY_INACTIVE");
+ return Phone.APN_ALREADY_INACTIVE;
+ }
+
+ } else {
+ if (DBG) {
+ log("disableApnType: no apn context was found, return APN_REQUEST_FAILED");
+ }
+ return Phone.APN_REQUEST_FAILED;
}
- return true;
}
@Override
protected boolean isApnTypeAvailable(String type) {
- if (type.equals(Phone.APN_TYPE_DUN)) {
- return (fetchDunApn() != null);
+ if (type.equals(Phone.APN_TYPE_DUN) && fetchDunApn() != null) {
+ return true;
}
if (mAllApns != null) {
@@ -249,41 +527,62 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return false;
}
+ /**
+ * Report on whether data connectivity is enabled for any APN.
+ * @return {@code false} if data connectivity has been explicitly disabled,
+ * {@code true} otherwise.
+ */
+ @Override
+ public synchronized boolean getAnyDataEnabled() {
+ if (!(mInternalDataEnabled && mDataEnabled)) return false;
+ for (ApnContext apnContext : mApnContexts.values()) {
+ // Make sure we dont have a context that going down
+ // and is explicitly disabled.
+ if (isDataAllowed(apnContext)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isDataAllowed(ApnContext apnContext) {
+ return apnContext.isReady() && isDataAllowed();
+ }
+
//****** Called from ServiceStateTracker
/**
* Invoked when ServiceStateTracker observes a transition from GPRS
* attach to detach.
*/
- protected void onGprsDetached() {
+ protected void onDataConnectionDetached() {
/*
* We presently believe it is unnecessary to tear down the PDP context
* when GPRS detaches, but we should stop the network polling.
*/
+ if (DBG) log ("onDataConnectionDetached: stop polling and notify detached");
stopNetStatPoll();
- notifyDataConnection(Phone.REASON_GPRS_DETACHED);
+ notifyDataConnection(Phone.REASON_DATA_DETACHED);
}
- private void onGprsAttached() {
- if (mState == State.CONNECTED) {
+ private void onDataConnectionAttached() {
+ if (DBG) log("onDataConnectionAttached");
+ if (getOverallState() == State.CONNECTED) {
+ if (DBG) log("onDataConnectionAttached: start polling notify attached");
startNetStatPoll();
- notifyDataConnection(Phone.REASON_GPRS_ATTACHED);
- } else {
- if (mState == State.FAILED) {
- cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
- mRetryMgr.resetRetryCount();
- }
- trySetupData(Phone.REASON_GPRS_ATTACHED);
+ notifyDataConnection(Phone.REASON_DATA_ATTACHED);
}
+
+ setupDataOnReadyApns(Phone.REASON_DATA_ATTACHED);
}
@Override
protected boolean isDataAllowed() {
- int gprsState = mGsmPhone.mSST.getCurrentGprsState();
- boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
+ int gprsState = mPhone.getServiceStateTracker().getCurrentDataConnectionState();
+ boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
boolean allowed =
(gprsState == ServiceState.STATE_IN_SERVICE || mAutoAttachOnCreation) &&
- mGsmPhone.mSIMRecords.getRecordsLoaded() &&
+ mPhone.mIccRecords.getRecordsLoaded() &&
mPhone.getState() == Phone.State.IDLE &&
mInternalDataEnabled &&
(!mPhone.getServiceState().getRoaming() || getDataOnRoamingEnabled()) &&
@@ -294,7 +593,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (!((gprsState == ServiceState.STATE_IN_SERVICE) || mAutoAttachOnCreation)) {
reason += " - gprs= " + gprsState;
}
- if (!mGsmPhone.mSIMRecords.getRecordsLoaded()) reason += " - SIM not loaded";
+ if (!mPhone.mIccRecords.getRecordsLoaded()) reason += " - SIM not loaded";
if (mPhone.getState() != Phone.State.IDLE) {
reason += " - PhoneState= " + mPhone.getState();
}
@@ -304,97 +603,246 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (mIsPsRestricted) reason += " - mIsPsRestricted= true";
if (!desiredPowerState) reason += " - desiredPowerState= false";
- log("Data not allowed due to" + reason);
+ if (DBG) log("isDataAllowed: not allowed due to" + reason);
}
return allowed;
}
- private boolean trySetupData(String reason) {
- if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
+ /**
+ * Release the apnContext
+ *
+ * @param apnContext
+ * @param tearDown
+ * @return none
+ */
+ private void releaseApnContext(ApnContext apnContext, boolean tearDown) {
+ if (apnContext == null) {
+ if (DBG) loge("releaseApnContext: apnContext null should not happen, ignore");
+ return;
+ }
+ DataConnection dc = apnContext.getDataConnection();
+ if (dc == null) {
+ if (DBG) loge("releaseApnContext: apnContext dc == null should not happen, ignore");
+ return;
+ }
+ if (tearDown) {
+ if (DBG) log("releaseApnContext: tearing down");
+ Message msg = obtainMessage(EVENT_DISCONNECT_DONE, apnContext);
+ apnContext.getDataConnection().tearDown(apnContext.getReason(), msg);
+ }
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
+ return;
+ }
+
+ private void setupDataOnReadyApns(String reason) {
+ // Only check for default APN state
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isReady()) {
+ if (apnContext.getState() == State.FAILED) {
+ cleanApnContextBeforeRestart(apnContext);
+ if (apnContext.getDataConnection() != null) {
+ apnContext.getDataConnection().resetRetryCount();
+ }
+ }
+ // Do not start ApnContext in SCANNING state
+ // FAILED state must be reset to IDLE by now
+ if (apnContext.getState() == State.IDLE) {
+ apnContext.setReason(reason);
+ trySetupData(apnContext);
+ }
+ }
+ }
+ }
+
+ private boolean trySetupData(String reason, String type) {
+ if (DBG) {
+ log("trySetupData: " + type + " due to " + (reason == null ? "(unspecified)" : reason)
+ + " isPsRestricted=" + mIsPsRestricted);
+ }
- log("[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
+ if (type == null) {
+ type = Phone.APN_TYPE_DEFAULT;
+ }
+
+ ApnContext apnContext = mApnContexts.get(type);
+
+ if (apnContext == null ){
+ if (DBG) log("trySetupData new apn context for type:" + type);
+ apnContext = new ApnContext(type, LOG_TAG);
+ mApnContexts.put(type, apnContext);
+ }
+ apnContext.setReason(reason);
+
+ return trySetupData(apnContext);
+ }
+
+ private boolean trySetupData(ApnContext apnContext) {
+ if (DBG) {
+ log("trySetupData for type:" + apnContext.getApnType() +
+ " due to " + apnContext.getReason());
+ log("trySetupData with mIsPsRestricted=" + mIsPsRestricted);
+ }
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
- setState(State.CONNECTED);
- notifyDataConnection(reason);
+ apnContext.setState(State.CONNECTED);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
- log("(fix?) We're on the simulator; assuming data is connected");
+ log("trySetupData: (fix?) We're on the simulator; assuming data is connected");
return true;
}
- int gprsState = mGsmPhone.mSST.getCurrentGprsState();
- boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
+ boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
- if (((mState == State.IDLE) || (mState == State.SCANNING)) &&
- isDataAllowed() && getAnyDataEnabled()) {
+ if ((apnContext.getState() == State.IDLE || apnContext.getState() == State.SCANNING) &&
+ isDataAllowed(apnContext) && getAnyDataEnabled()) {
- if (mState == State.IDLE) {
- mWaitingApns = buildWaitingApns(mRequestedApnType);
- mWaitingApnsPermanentFailureCountDown = mWaitingApns.size();
- if (mWaitingApns.isEmpty()) {
- if (DBG) log("No APN found");
- notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
- notifyOffApnsOfAvailability(reason, false);
+ if (apnContext.getState() == State.IDLE) {
+ ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
+ if (waitingApns.isEmpty()) {
+ if (DBG) log("trySetupData: No APN found");
+ notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
+ notifyOffApnsOfAvailability(apnContext.getReason(), false);
return false;
} else {
- log ("Create from allApns : " + apnListToString(mAllApns));
+ apnContext.setWaitingApns(waitingApns);
+ if (DBG) {
+ log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
+ }
}
}
if (DBG) {
- log ("Setup waitngApns : " + apnListToString(mWaitingApns));
+ log ("Setup watingApns : " + apnListToString(apnContext.getWaitingApns()));
}
- boolean retValue = setupData(reason);
- notifyOffApnsOfAvailability(reason, retValue);
+ // apnContext.setReason(apnContext.getReason());
+ boolean retValue = setupData(apnContext);
+ notifyOffApnsOfAvailability(apnContext.getReason(), retValue);
return retValue;
} else {
- notifyOffApnsOfAvailability(reason, false);
+ // TODO: check the condition.
+ if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)
+ && (apnContext.getState() == State.IDLE
+ || apnContext.getState() == State.SCANNING))
+ mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
+ notifyOffApnsOfAvailability(apnContext.getReason(), false);
return false;
}
}
+ @Override
+ // Disabled apn's still need avail/unavail notificiations - send them out
+ protected void notifyOffApnsOfAvailability(String reason, boolean availability) {
+ if (mAvailability == availability) return;
+ mAvailability = availability;
+
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (!apnContext.isReady()) {
+ if (DBG) log("notifyOffApnOfAvailability type:" + apnContext.getApnType());
+ mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
+ apnContext.getApnType(),
+ Phone.DataState.DISCONNECTED);
+ }
+ }
+ }
+
+ /**
+ * If tearDown is true, this only tears down a CONNECTED session. Presently,
+ * there is no mechanism for abandoning an INITING/CONNECTING session,
+ * but would likely involve cancelling pending async requests or
+ * setting a flag or new state to ignore them when they came in
+ * @param tearDown true if the underlying GsmDataConnection should be
+ * disconnected.
+ * @param reason reason for the clean up.
+ */
+ protected void cleanUpAllConnections(boolean tearDown, String reason) {
+ if (DBG) log("cleanUpAllConnections: tearDown=" + tearDown + " reason=" + reason);
+
+ for (ApnContext apnContext : mApnContexts.values()) {
+ apnContext.setReason(reason);
+ cleanUpConnection(tearDown, apnContext);
+ }
+
+ stopNetStatPoll();
+ // TODO: Do we need mRequestedApnType?
+ mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+ }
+
/**
* Cleanup all connections.
*
* TODO: Cleanup only a specified connection passed as a parameter.
+ * Also, make sure when you clean up a conn, if it is last apply
+ * logic as though it is cleanupAllConnections
*
* @param tearDown true if the underlying DataConnection should be disconnected.
* @param reason for the clean up.
*/
- private void cleanUpConnection(boolean tearDown, String reason) {
- if (DBG) log("Clean up connection due to " + reason);
- // Clear the reconnect alarm, if set.
- if (mReconnectIntent != null) {
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- am.cancel(mReconnectIntent);
- mReconnectIntent = null;
+ @Override
+ protected void onCleanUpAllConnections(String cause) {
+ cleanUpAllConnections(true, cause);
+ }
+
+ private void cleanUpConnection(boolean tearDown, ApnContext apnContext) {
+
+ if (apnContext == null) {
+ if (DBG) log("cleanUpConnection: apn context is null");
+ return;
}
- setState(State.DISCONNECTING);
+ if (DBG) {
+ log("cleanUpConnection: tearDown=" + tearDown + " reason=" + apnContext.getReason());
+ }
+ if (tearDown && cleanApnContextBeforeRestart(apnContext)) {
+ // if the request is tearDown and ApnContext does not hold an active connection,
+ // we're ok to return here.
+ return;
+ }
- boolean notificationDeferred = false;
- for (DataConnection conn : mDataConnections.values()) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac != null) {
if (tearDown) {
- if (DBG) log("cleanUpConnection: teardown, call conn.disconnect");
- conn.disconnect(obtainMessage(EVENT_DISCONNECT_DONE,
- conn.getDataConnectionId(), 0, reason));
- notificationDeferred = true;
+ apnContext.setState(State.DISCONNECTING);
+ releaseApnContext(apnContext, tearDown);
} else {
- if (DBG) log("cleanUpConnection: !tearDown, call conn.resetSynchronously");
- conn.resetSynchronously();
- notificationDeferred = false;
+ dcac.resetSync();
+ apnContext.setState(State.IDLE);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+ apnContext.setDataConnection(null);
+ apnContext.setDataConnectionAc(null);
}
}
- stopNetStatPoll();
+ }
+
+ /**
+ * @param APNContext to clean
+ * @return true if ApnContext is not connected anymore.
+ * false if ApnContext still holds a connection.
+ */
+ private boolean cleanApnContextBeforeRestart(ApnContext apnContext) {
+ if (apnContext == null) return true;
+
+ // Clear the reconnect alarm, if set.
+ if (apnContext.getReconnectIntent() != null) {
+ AlarmManager am =
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+ am.cancel(apnContext.getReconnectIntent());
+ apnContext.setReconnectIntent(null);
+ }
+
+ if (apnContext.getState() == State.IDLE || apnContext.getState() == State.DISCONNECTING) {
+ if (DBG) log("cleanUpConnection: state= " + apnContext.getState());
+ return true;
+ }
- if (!notificationDeferred) {
- if (DBG) log("cleanupConnection: !notificationDeferred");
- gotoIdleAndNotifyDataConnection(reason);
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ return true;
}
+ return false;
}
/**
@@ -439,162 +887,255 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
result.add(apn);
} while (cursor.moveToNext());
}
+ if (DBG) log("createApnList: X result=" + result);
return result;
}
private GsmDataConnection findFreeDataConnection() {
- for (DataConnection dc : mDataConnections.values()) {
- if (dc.isInactive()) {
- log("found free GsmDataConnection");
- return (GsmDataConnection) dc;
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ if (dcac.isInactiveSync()) {
+ log("findFreeDataConnection: found free GsmDataConnection");
+ return (GsmDataConnection) dcac.dataConnection;
}
}
- log("NO free GsmDataConnection");
+ log("findFreeDataConnection: NO free GsmDataConnection");
return null;
}
- private boolean setupData(String reason) {
+ protected GsmDataConnection findReadyDataConnection(ApnSetting apn) {
+ if (DBG)
+ log("findReadyDataConnection: apn string <" +
+ (apn!=null?(apn.toString()):"null") +">");
+ if (apn == null) {
+ return null;
+ }
+ for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ ApnSetting apnSetting = dcac.getApnSettingSync();
+ if (DBG) {
+ log("findReadyDataConnection: dc apn string <" +
+ (apnSetting != null ? (apnSetting.toString()) : "null") + ">");
+ }
+ if ((apnSetting != null) && TextUtils.equals(apnSetting.toString(), apn.toString())) {
+ return (GsmDataConnection) dcac.dataConnection;
+ }
+ }
+ return null;
+ }
+
+
+ private boolean setupData(ApnContext apnContext) {
+ if (DBG) log("setupData: apnContext=" + apnContext);
ApnSetting apn;
- GsmDataConnection gdc;
+ GsmDataConnection dc;
- apn = getNextApn();
- if (apn == null) return false;
- gdc = findFreeDataConnection();
- if (gdc == null) {
- if (DBG) log("setupData: No free GsmDataConnection found!");
+ int profileId = getApnProfileID(apnContext.getApnType());
+ apn = apnContext.getNextWaitingApn();
+ if (apn == null) {
+ if (DBG) log("setupData: return for no apn found!");
return false;
}
- mActiveApn = apn;
- mPendingDataConnection = gdc;
- Message msg = obtainMessage();
- msg.what = EVENT_DATA_SETUP_COMPLETE;
- msg.obj = reason;
- gdc.connect(msg, apn);
+ // First, check to see if ApnContext already has DC.
+ // This could happen if the retries are currently engaged.
+ dc = (GsmDataConnection)apnContext.getDataConnection();
- setState(State.INITING);
- notifyDataConnection(reason);
- return true;
- }
+ if (dc == null) {
- private boolean dataCallStatesHasCID (ArrayList<DataCallState> states, int cid) {
- for (int i = 0, s = states.size() ; i < s ; i++) {
- if (states.get(i).cid == cid) return true;
- }
- return false;
- }
+ dc = (GsmDataConnection) checkForConnectionForApnContext(apnContext);
- private boolean dataCallStatesHasActiveCID (ArrayList<DataCallState> states, int cid) {
- for (int i = 0, s = states.size() ; i < s ; i++) {
- if ((states.get(i).cid == cid) && (states.get(i).active != 0)) {
- return true;
+ if (dc == null) {
+ dc = findReadyDataConnection(apn);
+ }
+
+ if (dc == null) {
+ if (DBG) log("setupData: No ready GsmDataConnection found!");
+ // TODO: When allocating you are mapping type to id. If more than 1 free,
+ // then could findFreeDataConnection get the wrong one??
+ dc = findFreeDataConnection();
+ }
+
+ if (dc == null) {
+ dc = createDataConnection();
+ }
+
+ if (dc == null) {
+ if (DBG) log("setupData: No free GsmDataConnection found!");
+ return false;
+ }
+
+ DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId());
+ dc.setProfileId( profileId );
+ dc.setActiveApnType(apnContext.getApnType());
+ int refCount = dcac.getRefCountSync();
+ if (DBG) log("setupData: init dc and apnContext refCount=" + refCount);
+
+ // configure retry count if no other Apn is using the same connection.
+ if (refCount == 0) {
+ configureRetry(dc, apnContext.getApnType());
}
+ apnContext.setDataConnectionAc(mDataConnectionAsyncChannels.get(dc.getDataConnectionId()));
+ apnContext.setApnSetting(apn);
+ apnContext.setDataConnection(dc);
}
- return false;
+ Message msg = obtainMessage();
+ msg.what = EVENT_DATA_SETUP_COMPLETE;
+ msg.obj = apnContext;
+ dc.bringUp(msg, apn);
+
+ apnContext.setState(State.INITING);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+ if (DBG) log("setupData: initing!");
+ return true;
}
/**
* Handles changes to the APN database.
*/
private void onApnChanged() {
+ // TODO: How to handle when multiple APNs are active?
boolean isConnected;
- isConnected = (mState != State.IDLE && mState != State.FAILED);
+ ApnContext defaultApnContext = mApnContexts.get(Phone.APN_TYPE_DEFAULT);
+ isConnected = (defaultApnContext.getState() != State.IDLE
+ && defaultApnContext.getState() != State.FAILED);
- // The "current" may no longer be valid. MMS depends on this to send properly.
- mGsmPhone.updateCurrentCarrierInProvider();
+ if (mPhone instanceof GSMPhone) {
+ // The "current" may no longer be valid. MMS depends on this to send properly. TBD
+ ((GSMPhone)mPhone).updateCurrentCarrierInProvider();
+ }
// TODO: It'd be nice to only do this if the changed entrie(s)
// match the current operator.
+ if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
createAllApnList();
- if (mState != State.DISCONNECTING) {
- cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
- if (!isConnected) {
- // reset reconnect timer
- mRetryMgr.resetRetryCount();
- mReregisterOnReconnectFailure = false;
- trySetupData(Phone.REASON_APN_CHANGED);
- }
+ cleanUpAllConnections(isConnected, Phone.REASON_APN_CHANGED);
+ if (!isConnected) {
+ setupDataOnReadyApns(Phone.REASON_APN_CHANGED);
}
}
/**
- * @param explicitPoll if true, indicates that *we* polled for this
- * update while state == CONNECTED rather than having it delivered
- * via an unsolicited response (which could have happened at any
- * previous state
+ * @param ar is the result of RIL_REQUEST_DATA_CALL_LIST
+ * or RIL_UNSOL_DATA_CALL_LIST_CHANGED
*/
- private void onDataStateChanged (AsyncResult ar, boolean explicitPoll) {
+ private void onDataStateChanged (AsyncResult ar) {
ArrayList<DataCallState> dataCallStates;
+ if (DBG) log("onDataStateChanged(ar): E");
dataCallStates = (ArrayList<DataCallState>)(ar.result);
if (ar.exception != null) {
// This is probably "radio not available" or something
// of that sort. If so, the whole connection is going
// to come down soon anyway
+ if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
return;
}
- if (mState == State.CONNECTED) {
- // The way things are supposed to work, the PDP list
- // should not contain the CID after it disconnects.
- // However, the way things really work, sometimes the PDP
- // context is still listed with active = false, which
- // makes it hard to distinguish an activating context from
- // an activated-and-then deactivated one.
- if (!dataCallStatesHasCID(dataCallStates, mCidActive)) {
- // It looks like the PDP context has deactivated.
- // Tear everything down and try to reconnect.
+ // Create a hash map to store the dataCallState of each call id
+ // TODO: Depends on how frequent the DATA_CALL_LIST got updated,
+ // may cache response to reduce comparison.
+ HashMap<Integer, DataCallState> response;
+ response = new HashMap<Integer, DataCallState>();
+ if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
+ for (DataCallState dc : dataCallStates) {
+ response.put(dc.cid, dc);
+ if (DBG) log("onDataStateChanged(ar): " + dc.cid + ": " + dc.toString());
+ }
+
+ // For each connected apn, check if there is a matched active
+ // data call state, which has the same link properties.
+ if (DBG) log(" ApnContext size=" + mApnContexts.values().size());
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (DBG){
+ log("onDataStateChanged(ar): " + apnContext.toString());
+ if (apnContext.getDataConnection() != null) {
+ log("onDataStateChanged(ar): " + apnContext.getDataConnection().toString());
+ }
+ }
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) {
+ continue;
+ }
+ int connectionId = dcac.getCidSync();
+
+ if (apnContext.getState() == State.CONNECTED) {
+ // The way things are supposed to work, the PDP list
+ // should not contain the CID after it disconnects.
+ // However, the way things really work, sometimes the PDP
+ // context is still listed with active = false, which
+ // makes it hard to distinguish an activating context from
+ // an activated-and-then de-activated one.
+ if (response.containsKey(connectionId)) {
+ DataCallState newState = response.get(connectionId);
+ if (DBG) log("onDataStateChanged(ar): Found ConnId=" + connectionId
+ + " newState=" + newState.toString());
+ if (newState.active != 0) {
+ boolean resetConnection;
+ switch (dcac.updateLinkPropertiesDataCallStateSync(newState)) {
+ case NONE:
+ if (DBG) log("onDataStateChanged(ar): Found but no change, skip");
+ resetConnection = false;
+ break;
+ case CHANGED:
+ if (DBG) log("onDataStateChanged(ar): Found and changed, notify");
+ mPhone.notifyDataConnection(Phone.REASON_LINK_PROPERTIES_CHANGED,
+ apnContext.getApnType());
+ // Temporary hack, at this time a transition from CDMA -> Global
+ // fails so we'll hope for the best and not reset the connection.
+ // @see bug/4455071
+ if (SystemProperties.getBoolean("telephony.ignore-state-changes",
+ true)) {
+ log("onDataStateChanged(ar): STOPSHIP don't reset, continue");
+ resetConnection = false;
+ } else {
+ // Things changed so reset connection, when hack is removed
+ // this is the normal path.
+ log("onDataStateChanged(ar): changed so resetting connection");
+ resetConnection = true;
+ }
+ break;
+ case RESET:
+ default:
+ if (DBG) log("onDataStateChanged(ar): an error, reset connection");
+ resetConnection = true;
+ break;
+ }
+ if (resetConnection == false) continue;
+ }
+ }
- log("PDP connection has dropped. Reconnecting");
+ if (DBG) log("onDataStateChanged(ar): reset connection.");
// Add an event log when the network drops PDP
- GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
- EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
- loc != null ? loc.getCid() : -1,
+ int cid = getCellLocationId();
+ EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
TelephonyManager.getDefault().getNetworkType());
- cleanUpConnection(true, null);
- return;
- } else if (!dataCallStatesHasActiveCID(dataCallStates, mCidActive)) {
- // Here, we only consider this authoritative if we asked for the
- // PDP list. If it was an unsolicited response, we poll again
- // to make sure everyone agrees on the initial state.
-
- if (!explicitPoll) {
- // We think it disconnected but aren't sure...poll from our side
- mPhone.mCM.getPDPContextList(
- this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
- } else {
- log("PDP connection has dropped (active=false case). "
- + " Reconnecting");
-
- // Log the network drop on the event log.
- GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
- EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
- loc != null ? loc.getCid() : -1,
- TelephonyManager.getDefault().getNetworkType());
-
- cleanUpConnection(true, null);
- }
+ cleanUpConnection(true, apnContext);
}
}
+
+ if (DBG) log("onDataStateChanged(ar): X");
}
- private void notifyDefaultData(String reason) {
- setState(State.CONNECTED);
- notifyDataConnection(reason);
+ private void notifyDefaultData(ApnContext apnContext) {
+ if (DBG) {
+ log("notifyDefaultData: type=" + apnContext.getApnType()
+ + ", reason:" + apnContext.getReason());
+ }
+ apnContext.setState(State.CONNECTED);
+ // setState(State.CONNECTED);
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
startNetStatPoll();
// reset reconnect timer
- mRetryMgr.resetRetryCount();
- mReregisterOnReconnectFailure = false;
+ apnContext.getDataConnection().resetRetryCount();
}
- private void gotoIdleAndNotifyDataConnection(String reason) {
+ // TODO: For multiple Active APNs not exactly sure how to do this.
+ protected void gotoIdleAndNotifyDataConnection(String reason) {
if (DBG) log("gotoIdleAndNotifyDataConnection: reason=" + reason);
- setState(State.IDLE);
notifyDataConnection(reason);
mActiveApn = null;
}
@@ -608,28 +1149,60 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
private void doRecovery() {
- if (mState == State.CONNECTED) {
+ if (getOverallState() == State.CONNECTED) {
int maxPdpReset = Settings.Secure.getInt(mResolver,
Settings.Secure.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
DEFAULT_MAX_PDP_RESET_FAIL);
if (mPdpResetCount < maxPdpReset) {
mPdpResetCount++;
EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
- cleanUpConnection(true, Phone.REASON_PDP_RESET);
+ if (DBG) log("doRecovery() cleanup all connections mPdpResetCount < max");
+ cleanUpAllConnections(true, Phone.REASON_PDP_RESET);
} else {
mPdpResetCount = 0;
- EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
- mGsmPhone.mSST.reRegisterNetwork(null);
+ switch (mRecoveryAction) {
+ case REREGISTER:
+ EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, mSentSinceLastRecv);
+ if (DBG) log("doRecovery() re-register getting preferred network type");
+ mPhone.getServiceStateTracker().reRegisterNetwork(null);
+ mRecoveryAction = RecoveryAction.RADIO_RESTART;
+ break;
+ case RADIO_RESTART:
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, mSentSinceLastRecv);
+ if (DBG) log("restarting radio");
+ mRecoveryAction = RecoveryAction.RADIO_RESET;
+ restartRadio();
+ break;
+ case RADIO_RESET:
+ // This is in case radio restart has not recovered the data.
+ // It will set an additional "gsm.radioreset" property to tell
+ // RIL or system to take further action.
+ // The implementation of hard reset recovery action is up to OEM product.
+ // Once gsm.radioreset property is consumed, it is expected to set back
+ // to false by RIL.
+ EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, -1);
+ if (DBG) log("restarting radio with reset indication");
+ SystemProperties.set("gsm.radioreset", "true");
+ // give 1 sec so property change can be notified.
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {}
+ restartRadio();
+ break;
+ default:
+ throw new RuntimeException("doRecovery: Invalid mRecoveryAction " +
+ mRecoveryAction);
+ }
}
- // TODO: Add increasingly drastic recovery steps, eg,
- // reset the radio, reset the device.
+ } else {
+ if (DBG) log("doRecovery(): ignore, we're not connected");
}
}
@Override
protected void startNetStatPoll() {
- if (mState == State.CONNECTED && mNetStatPollEnabled == false) {
- log("[DataConnection] Start poll NetStat");
+ if (getOverallState() == State.CONNECTED && mNetStatPollEnabled == false) {
+ if (DBG) log("startNetStatPoll");
resetPollStats();
mNetStatPollEnabled = true;
mPollNetStat.run();
@@ -640,14 +1213,14 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void stopNetStatPoll() {
mNetStatPollEnabled = false;
removeCallbacks(mPollNetStat);
- log("[DataConnection] Stop poll NetStat");
+ if (DBG) log("stopNetStatPoll");
}
@Override
protected void restartRadio() {
- log("************TURN OFF RADIO**************");
- cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
- mGsmPhone.mSST.powerOffRadioSafely();
+ if (DBG) log("restartRadio: ************TURN OFF RADIO**************");
+ cleanUpAllConnections(true, Phone.REASON_RADIO_TURNED_OFF);
+ mPhone.getServiceStateTracker().powerOffRadioSafely(this);
/* Note: no need to call setRadioPower(true). Assuming the desired
* radio power state is still ON (as tracked by ServiceStateTracker),
* ServiceStateTracker will call setRadioPower when it receives the
@@ -672,10 +1245,30 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
preTxPkts = mTxPkts;
preRxPkts = mRxPkts;
- mTxPkts = TrafficStats.getMobileTxPackets();
- mRxPkts = TrafficStats.getMobileRxPackets();
+ long txSum = 0, rxSum = 0;
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.getState() == State.CONNECTED) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) continue;
- //log("rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+ LinkProperties linkProp = dcac.getLinkPropertiesSync();
+ if (linkProp == null) continue;
+
+ String iface = linkProp.getInterfaceName();
+
+ if (iface != null) {
+ long stats = TrafficStats.getTxPackets(iface);
+ if (stats > 0) txSum += stats;
+ stats = TrafficStats.getRxPackets(iface);
+ if (stats > 0) rxSum += stats;
+ }
+ }
+ }
+
+ mTxPkts = txSum;
+ mRxPkts = rxSum;
+
+ // log("tx " + mTxPkts + " rx " + mRxPkts);
if (mNetStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
sent = mTxPkts - preTxPkts;
@@ -685,6 +1278,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
mSentSinceLastRecv = 0;
newActivity = Activity.DATAINANDOUT;
mPdpResetCount = 0;
+ mRecoveryAction = RecoveryAction.REREGISTER;
} else if (sent > 0 && received == 0) {
if (mPhone.getState() == Phone.State.IDLE) {
mSentSinceLastRecv += sent;
@@ -696,6 +1290,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
mSentSinceLastRecv = 0;
newActivity = Activity.DATAIN;
mPdpResetCount = 0;
+ mRecoveryAction = RecoveryAction.REREGISTER;
} else if (sent == 0 && received == 0) {
newActivity = Activity.NONE;
} else {
@@ -726,8 +1321,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (mNoRecvPollCount < noRecvPollLimit) {
// It's possible the PDP context went down and we weren't notified.
// Start polling the context list in an attempt to recover.
- if (DBG) log("no DATAIN in a while; polling PDP");
- mPhone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+ if (DBG) log("Polling: no DATAIN in a while; polling PDP");
+ mPhone.mCM.getDataCallList(obtainMessage(EVENT_DATA_STATE_CHANGED));
mNoRecvPollCount++;
@@ -736,9 +1331,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
Settings.Secure.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS);
} else {
- if (DBG) log("Sent " + String.valueOf(mSentSinceLastRecv) +
+ if (DBG) log("Polling: Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received start recovery process");
- stopNetStatPoll();
+ mNoRecvPollCount = 0;
sendMessage(obtainMessage(EVENT_START_RECOVERY));
}
} else {
@@ -784,122 +1379,217 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return retry;
}
- private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
- if (mState == State.FAILED) {
- /** TODO: Retrieve retry manager from connection itself */
- if (!mRetryMgr.isRetryNeeded()) {
- if (!mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
- // if no more retries on a secondary APN attempt, tell the world and revert.
- notifyDataConnection(Phone.REASON_APN_FAILED);
- onEnableApn(apnTypeToId(mRequestedApnType), DISABLED);
+ private void reconnectAfterFail(FailCause lastFailCauseCode, ApnContext apnContext) {
+ if (apnContext == null) {
+ loge("reconnectAfterFail: apnContext == null, impossible");
+ return;
+ }
+ if ((apnContext.getState() == State.FAILED) &&
+ (apnContext.getDataConnection() != null)) {
+ if (!apnContext.getDataConnection().isRetryNeeded()) {
+ if (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT)) {
+ mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
return;
}
if (mReregisterOnReconnectFailure) {
- // We've re-registered once now just retry forever.
- mRetryMgr.retryForeverUsingLastTimeout();
+ // We've re-registerd once now just retry forever.
+ apnContext.getDataConnection().retryForeverUsingLastTimeout();
} else {
- // Try to re-register to the network.
- log("PDP activate failed, Reregistering to the network");
+ // Try to Re-register to the network.
+ if (DBG) log("reconnectAfterFail: activate failed, Reregistering to network");
mReregisterOnReconnectFailure = true;
- mGsmPhone.mSST.reRegisterNetwork(null);
- mRetryMgr.resetRetryCount();
+ mPhone.getServiceStateTracker().reRegisterNetwork(null);
+ apnContext.getDataConnection().resetRetryCount();
return;
}
}
- int nextReconnectDelay = mRetryMgr.getRetryTimer();
- log("PDP activate failed. Scheduling next attempt for "
- + (nextReconnectDelay / 1000) + "s");
-
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
- Intent intent = new Intent(INTENT_RECONNECT_ALARM);
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
- mReconnectIntent = PendingIntent.getBroadcast(
- mPhone.getContext(), 0, intent, 0);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
- SystemClock.elapsedRealtime() + nextReconnectDelay,
- mReconnectIntent);
-
- mRetryMgr.increaseRetryCount();
+ int nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
+ startAlarmForReconnect(nextReconnectDelay, apnContext);
+ apnContext.getDataConnection().increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
- log("NOT Posting GPRS Unavailable notification "
+ if (DBG) {
+ log("reconnectAfterFail: NOT Posting GPRS Unavailable notification "
+ "-- likely transient error");
+ }
} else {
- notifyNoData(lastFailCauseCode);
+ notifyNoData(lastFailCauseCode, apnContext);
}
}
}
- private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode) {
- setState(State.FAILED);
+ private void startAlarmForReconnect(int delay, ApnContext apnContext) {
+
+ if (DBG) {
+ log("Schedule alarm for reconnect: activate failed. Scheduling next attempt for "
+ + (delay / 1000) + "s");
+ }
+
+ AlarmManager am =
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+
+ // TODO : Register the receiver only once maybe in baseclass.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(INTENT_RECONNECT_ALARM + '.'+apnContext.getApnType());
+ mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
+ Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
+ intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
+ apnContext.setReconnectIntent(PendingIntent.getBroadcast (
+ mPhone.getContext(), 0, intent, 0));
+ am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delay, apnContext.getReconnectIntent());
+
+ }
+
+ private void notifyNoData(GsmDataConnection.FailCause lastFailCauseCode,
+ ApnContext apnContext) {
+ if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
+ apnContext.setState(State.FAILED);
+ if (lastFailCauseCode.isPermanentFail()
+ && (!apnContext.getApnType().equals(Phone.APN_TYPE_DEFAULT))) {
+ mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
+ }
}
private void onRecordsLoaded() {
+ if (DBG) log("onRecordsLoaded: createAllApnList");
createAllApnList();
- if (mState == State.FAILED) {
- cleanUpConnection(false, null);
+ if (mRadioAvailable) {
+ if (DBG) log("onRecordsLoaded: notifying data availability");
+ notifyDataAvailability(null);
}
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
+ setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
}
@Override
- protected void onEnableNewApn() {
- log("onEnableNewApn E");
- // change our retry manager to use the appropriate numbers for the new APN
- if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
- log("onEnableNewApn default type");
- mRetryMgr = mPendingDataConnection.getRetryMgr();
- mRetryMgr.resetRetryCount();
- } else if (mApnToDataConnectionId.get(mRequestedApnType) == null) {
- log("onEnableNewApn mRequestedApnType=" + mRequestedApnType +
- " missing, make a new connection");
- int id = createDataConnection(mRequestedApnType);
- mRetryMgr = mDataConnections.get(id).getRetryMgr();
- mRetryMgr.resetRetryCount();
+ protected void onSetDependencyMet(String apnType, boolean met) {
+ ApnContext apnContext = mApnContexts.get(apnType);
+ if (apnContext == null) {
+ loge("onSetDependencyMet: ApnContext not found in onSetDependencyMet(" +
+ apnType + ", " + met + ")");
+ return;
+ }
+ applyNewState(apnContext, apnContext.isEnabled(), met);
+ }
+
+ private void applyNewState(ApnContext apnContext, boolean enabled, boolean met) {
+ boolean cleanup = false;
+ boolean trySetup = false;
+ if (DBG) {
+ log("applyNewState(" + apnContext.getApnType() + ", " + enabled +
+ "(" + apnContext.isEnabled() + "), " + met + "(" +
+ apnContext.getDependencyMet() +"))");
+ }
+ if (apnContext.isReady()) {
+ if (enabled && met) return;
+ if (!enabled) {
+ apnContext.setReason(Phone.REASON_DATA_DISABLED);
+ } else {
+ apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_UNMET);
+ }
+ cleanup = true;
} else {
- log("oneEnableNewApn connection already exists, nothing to setup");
+ if (enabled && met) {
+ if (apnContext.isEnabled()) {
+ apnContext.setReason(Phone.REASON_DATA_DEPENDENCY_MET);
+ } else {
+ apnContext.setReason(Phone.REASON_DATA_ENABLED);
+ }
+ if (apnContext.getState() == State.FAILED) {
+ apnContext.setState(State.IDLE);
+ }
+ trySetup = true;
+ }
+ }
+ apnContext.setEnabled(enabled);
+ apnContext.setDependencyMet(met);
+ if (cleanup) cleanUpConnection(true, apnContext);
+ if (trySetup) trySetupData(apnContext);
+ }
+
+ private DataConnection checkForConnectionForApnContext(ApnContext apnContext) {
+ // Loop through all apnContexts looking for one with a conn that satisfies this apnType
+ String apnType = apnContext.getApnType();
+ for (ApnContext c : mApnContexts.values()) {
+ DataConnection conn = c.getDataConnection();
+ if (conn != null) {
+ ApnSetting apnSetting = c.getApnSetting();
+ if (apnSetting != null && apnSetting.canHandleType(apnType)) {
+ if (DBG) {
+ log("checkForConnectionForApnContext: apnContext=" + apnContext +
+ " found conn=" + conn);
+ }
+ return conn;
+ }
+ }
}
+ if (DBG) log("checkForConnectionForApnContext: apnContext=" + apnContext + " NO conn");
+ return null;
+ }
- // TODO: To support simultaneous PDP contexts, this should really only call
- // cleanUpConnection if it needs to free up a GsmDataConnection.
- cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
- log("onEnableNewApn X");
+ @Override
+ protected void onEnableApn(int apnId, int enabled) {
+ ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
+ if (apnContext == null) {
+ loge("onEnableApn(" + apnId + ", " + enabled + "): NO ApnContext");
+ return;
+ }
+ // TODO change our retry manager to use the appropriate numbers for the new APN
+ if (DBG) log("onEnableApn: apnContext=" + apnContext + " call applyNewState");
+ applyNewState(apnContext, enabled == ENABLED, apnContext.getDependencyMet());
}
@Override
+ // TODO: We shouldnt need this.
protected boolean onTrySetupData(String reason) {
- return trySetupData(reason);
+ if (DBG) log("onTrySetupData: reason=" + reason);
+ setupDataOnReadyApns(reason);
+ return true;
+ }
+
+ protected boolean onTrySetupData(ApnContext apnContext) {
+ if (DBG) log("onTrySetupData: apnContext=" + apnContext);
+ return trySetupData(apnContext);
}
@Override
protected void onRoamingOff() {
- trySetupData(Phone.REASON_ROAMING_OFF);
+ if (DBG) log("onRoamingOff");
+ setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
}
@Override
protected void onRoamingOn() {
if (getDataOnRoamingEnabled()) {
- trySetupData(Phone.REASON_ROAMING_ON);
+ if (DBG) log("onRoamingOn: setup data on roaming");
+ setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
} else {
- if (DBG) log("Tear down data connection on roaming.");
- cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+ if (DBG) log("onRoamingOn: Tear down data connection on roaming.");
+ cleanUpAllConnections(true, Phone.REASON_ROAMING_ON);
}
}
@Override
protected void onRadioAvailable() {
+ if (DBG) log("onRadioAvailable");
+ mRadioAvailable = true;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
- setState(State.CONNECTED);
+ // setState(State.CONNECTED);
notifyDataConnection(null);
- log("We're on the simulator; assuming data is connected");
+ log("onRadioAvailable: We're on the simulator; assuming data is connected");
}
- if (mState != State.IDLE) {
+ if (mPhone.mIccRecords.getRecordsLoaded()) {
+ notifyDataAvailability(null);
+ }
+
+ if (getOverallState() != State.IDLE) {
cleanUpConnection(true, null);
}
}
@@ -908,72 +1598,80 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onRadioOffOrNotAvailable() {
// Make sure our reconnect delay starts at the initial value
// next time the radio comes on
- mRetryMgr.resetRetryCount();
+
+ for (DataConnection dc : mDataConnections.values()) {
+ dc.resetRetryCount();
+ }
mReregisterOnReconnectFailure = false;
+ mRadioAvailable = false;
if (mPhone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
log("We're on the simulator; assuming radio off is meaningless");
} else {
- if (DBG) log("Radio is off and clean up all connection");
- // TODO: Should we reset mRequestedApnType to "default"?
- cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+ if (DBG) log("onRadioOffOrNotAvailable: is off and clean up all connections");
+ cleanUpAllConnections(false, Phone.REASON_RADIO_TURNED_OFF);
}
+ notifyDataAvailability(null);
}
@Override
protected void onDataSetupComplete(AsyncResult ar) {
- /** TODO: Which connection is completing should be a parameter */
- String reason = null;
- if (ar.userObj instanceof String) {
- reason = (String) ar.userObj;
+
+ ApnContext apnContext = null;
+
+ if(ar.userObj instanceof ApnContext){
+ apnContext = (ApnContext)ar.userObj;
+ } else {
+ throw new RuntimeException("onDataSetupComplete: No apnContext");
}
- if (ar.exception == null) {
- if(DBG) {
- log(String.format("onDataSetupComplete: success apn=%s", mWaitingApns.get(0).apn));
+ if (isDataSetupCompleteOk(ar)) {
+ DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ if (dcac == null) {
+ throw new RuntimeException("onDataSetupCompete: No dcac");
}
- // TODO: We should clear LinkProperties/Capabilities when torn down or disconnected
- mLinkProperties = getLinkProperties(mPendingDataConnection);
- mLinkCapabilities = getLinkCapabilities(mPendingDataConnection);
+ DataConnection dc = apnContext.getDataConnection();
- ApnSetting apn = mPendingDataConnection.getApn();
+ if (DBG) {
+ log(String.format("onDataSetupComplete: success apn=%s",
+ apnContext.getWaitingApns().get(0).apn));
+ }
+ ApnSetting apn = apnContext.getApnSetting();
if (apn.proxy != null && apn.proxy.length() != 0) {
try {
ProxyProperties proxy = new ProxyProperties(apn.proxy,
Integer.parseInt(apn.port), null);
- mLinkProperties.setHttpProxy(proxy);
+ dcac.setLinkPropertiesHttpProxySync(proxy);
} catch (NumberFormatException e) {
- loge("NumberFormatException making ProxyProperties (" + apn.port +
- "): " + e);
+ loge("onDataSetupComplete: NumberFormatException making ProxyProperties (" +
+ apn.port + "): " + e);
}
}
// everything is setup
- if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+ if(TextUtils.equals(apnContext.getApnType(),Phone.APN_TYPE_DEFAULT)) {
SystemProperties.set("gsm.defaultpdpcontext.active", "true");
- if (canSetPreferApn && mPreferredApn == null) {
- log("PREFERRED APN is null");
- mPreferredApn = mActiveApn;
- setPreferredApn(mPreferredApn.id);
- }
+ if (canSetPreferApn && mPreferredApn == null) {
+ if (DBG) log("onDataSetupComplete: PREFERED APN is null");
+ mPreferredApn = apnContext.getApnSetting();
+ if (mPreferredApn != null) {
+ setPreferredApn(mPreferredApn.id);
+ }
+ }
} else {
SystemProperties.set("gsm.defaultpdpcontext.active", "false");
}
- notifyDefaultData(reason);
-
- // TODO: For simultaneous PDP support, we need to build another
- // trigger another TRY_SETUP_DATA for the next APN type. (Note
- // that the existing connection may service that type, in which
- // case we should try the next type, etc.
+ notifyDefaultData(apnContext);
} else {
- GsmDataConnection.FailCause cause;
- cause = (GsmDataConnection.FailCause) (ar.result);
+ String apnString;
+ DataConnection.FailCause cause;
+
+ cause = (DataConnection.FailCause) (ar.result);
if (DBG) {
- String apnString;
try {
- apnString = mWaitingApns.get(0).apn;
+ apnString = apnContext.getWaitingApns().get(0).apn;
} catch (Exception e) {
apnString = "<unknown>";
}
@@ -981,35 +1679,45 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (cause.isEventLoggable()) {
// Log this failure to the Event Logs.
- GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation());
+ int cid = getCellLocationId();
EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
- cause.ordinal(), loc != null ? loc.getCid() : -1,
- TelephonyManager.getDefault().getNetworkType());
+ cause.ordinal(), cid, TelephonyManager.getDefault().getNetworkType());
}
// Count permanent failures and remove the APN we just tried
- mWaitingApnsPermanentFailureCountDown -= cause.isPermanentFail() ? 1 : 0;
- mWaitingApns.remove(0);
- if (DBG) log(String.format("onDataSetupComplete: mWaitingApns.size=%d" +
- " mWaitingApnsPermanenatFailureCountDown=%d",
- mWaitingApns.size(), mWaitingApnsPermanentFailureCountDown));
+ if (cause.isPermanentFail()) apnContext.decWaitingApnsPermFailCount();
+
+ apnContext.removeNextWaitingApn();
+ if (DBG) {
+ log(String.format("onDataSetupComplete: WaitingApns.size=%d" +
+ " WaitingApnsPermFailureCountDown=%d",
+ apnContext.getWaitingApns().size(),
+ apnContext.getWaitingApnsPermFailCount()));
+ }
// See if there are more APN's to try
- if (mWaitingApns.isEmpty()) {
- if (mWaitingApnsPermanentFailureCountDown == 0) {
- if (DBG) log("onDataSetupComplete: Permanent failures stop retrying");
- notifyNoData(cause);
- notifyDataConnection(Phone.REASON_APN_FAILED);
+ if (apnContext.getWaitingApns().isEmpty()) {
+ if (apnContext.getWaitingApnsPermFailCount() == 0) {
+ if (DBG) {
+ log("onDataSetupComplete: All APN's had permanent failures, stop retrying");
+ }
+ apnContext.setState(State.FAILED);
+ mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
+
+ releaseApnContext(apnContext, false);
+ if (DBG) {
+ log("onDataSetupComplete: permanent error apn=%s" + apnString );
+ }
} else {
if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
- startDelayedRetry(cause, reason);
+ startDelayedRetry(cause, apnContext);
}
} else {
if (DBG) log("onDataSetupComplete: Try next APN");
- setState(State.SCANNING);
+ apnContext.setState(State.SCANNING);
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel
- sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason), APN_DELAY_MILLIS);
+ startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
}
}
}
@@ -1019,43 +1727,53 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
*/
@Override
protected void onDisconnectDone(int connId, AsyncResult ar) {
- if(DBG) log("EVENT_DISCONNECT_DONE connId=" + connId);
- String reason = null;
- if (ar.userObj instanceof String) {
- reason = (String) ar.userObj;
+ ApnContext apnContext = null;
+
+ if(DBG) log("onDisconnectDone: EVENT_DISCONNECT_DONE connId=" + connId);
+ if (ar.userObj instanceof ApnContext) {
+ apnContext = (ApnContext) ar.userObj;
+ } else {
+ loge("Invalid ar in onDisconnectDone");
+ return;
}
- setState(State.IDLE);
- notifyDataConnection(reason);
- mActiveApn = null;
- if (retryAfterDisconnected(reason)) {
- trySetupData(reason);
+
+ apnContext.setState(State.IDLE);
+ apnContext.setApnSetting(null);
+
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+
+ // if all data connection are gone, check whether Airplane mode request was
+ // pending.
+ if (!isConnected()) {
+ if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
+ // Radio will be turned off. No need to retry data setup
+ return;
+ }
}
- }
- /**
- * Called when EVENT_RESET_DONE is received.
- */
- @Override
- protected void onResetDone(AsyncResult ar) {
- if (DBG) log("EVENT_RESET_DONE");
- String reason = null;
- if (ar.userObj instanceof String) {
- reason = (String) ar.userObj;
+ // If APN is still enabled, try to bring it back up automatically
+ if (apnContext.isReady() && retryAfterDisconnected(apnContext.getReason())) {
+ SystemProperties.set("gsm.defaultpdpcontext.active", "false"); // TODO - what the heck? This shoudld go
+ // Wait a bit before trying the next APN, so that
+ // we're not tying up the RIL command channel.
+ // This also helps in any external dependency to turn off the context.
+ startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
}
- gotoIdleAndNotifyDataConnection(reason);
}
protected void onPollPdp() {
- if (mState == State.CONNECTED) {
+ if (getOverallState() == State.CONNECTED) {
// only poll when connected
- mPhone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+ mPhone.mCM.getDataCallList(this.obtainMessage(EVENT_DATA_STATE_CHANGED));
sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
}
}
@Override
protected void onVoiceCallStarted() {
- if (mState == State.CONNECTED && ! mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+ if (DBG) log("onVoiceCallStarted");
+ if (isConnected() && ! mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
+ if (DBG) log("onVoiceCallStarted stop polling");
stopNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
}
@@ -1063,8 +1781,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
protected void onVoiceCallEnded() {
- if (mState == State.CONNECTED) {
- if (!mGsmPhone.mSST.isConcurrentVoiceAndData()) {
+ if (DBG) log("onVoiceCallEnded");
+ if (isConnected()) {
+ if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
startNetStatPoll();
notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
} else {
@@ -1073,16 +1792,40 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
} else {
// reset reconnect timer
- mRetryMgr.resetRetryCount();
- mReregisterOnReconnectFailure = false;
- // in case data setup was attempted when we were on a voice call
- trySetupData(Phone.REASON_VOICE_CALL_ENDED);
+ setupDataOnReadyApns(Phone.REASON_VOICE_CALL_ENDED);
}
}
@Override
- protected void onCleanUpConnection(boolean tearDown, String reason) {
- cleanUpConnection(tearDown, reason);
+ protected void onCleanUpConnection(boolean tearDown, int apnId, String reason) {
+ if (DBG) log("onCleanUpConnection");
+ ApnContext apnContext = mApnContexts.get(apnIdToType(apnId));
+ if (apnContext != null) {
+ apnContext.setReason(reason);
+ cleanUpConnection(tearDown, apnContext);
+ }
+ }
+
+ protected boolean isConnected() {
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.getState() == State.CONNECTED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void notifyDataConnection(String reason) {
+ if (DBG) log("notifyDataConnection: reason=" + reason);
+ for (ApnContext apnContext : mApnContexts.values()) {
+ if (apnContext.isReady()) {
+ if (DBG) log("notifyDataConnection: type:"+apnContext.getApnType());
+ mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
+ apnContext.getApnType());
+ }
+ }
+ notifyDataAvailability(reason);
}
/**
@@ -1091,10 +1834,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
*/
private void createAllApnList() {
mAllApns = new ArrayList<ApnSetting>();
- String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
-
+ String operator = mPhone.mIccRecords.getOperatorNumeric();
if (operator != null) {
String selection = "numeric = '" + operator + "'";
+ if (DBG) log("createAllApnList: selection=" + selection);
Cursor cursor = mPhone.getContext().getContentResolver().query(
Telephony.Carriers.CONTENT_URI, null, selection, null, null);
@@ -1108,73 +1851,75 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (mAllApns.isEmpty()) {
- if (DBG) log("No APN found for carrier: " + operator);
+ if (DBG) log("createAllApnList: No APN found for carrier: " + operator);
mPreferredApn = null;
- notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
+ // TODO: What is the right behaviour?
+ //notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
} else {
mPreferredApn = getPreferredApn();
- log("Get PreferredAPN");
if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
mPreferredApn = null;
setPreferredApn(-1);
}
+ if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
}
+ if (DBG) log("createAllApnList: X mAllApns=" + mAllApns);
}
/** Return the id for a new data connection */
- private int createDataConnection(String apnType) {
- log("createDataConnection(" + apnType + ") E");
+ private GsmDataConnection createDataConnection() {
+ if (DBG) log("createDataConnection E");
+
RetryManager rm = new RetryManager();
+ int id = mUniqueIdGenerator.getAndIncrement();
+ GsmDataConnection conn = GsmDataConnection.makeDataConnection(mPhone, id, rm);
+ mDataConnections.put(id, conn);
+ DataConnectionAc dcac = new DataConnectionAc(conn, LOG_TAG);
+ int status = dcac.fullyConnectSync(mPhone.getContext(), this, conn.getHandler());
+ if (status == AsyncChannel.STATUS_SUCCESSFUL) {
+ mDataConnectionAsyncChannels.put(dcac.dataConnection.getDataConnectionId(), dcac);
+ } else {
+ loge("createDataConnection: Could not connect to dcac.mDc=" + dcac.dataConnection +
+ " status=" + status);
+ }
+
+ if (DBG) log("createDataConnection() X id=" + id);
+ return conn;
+ }
+
+ private void configureRetry(DataConnection dc, String apnType) {
+ if ((dc == null) || (apnType == null)) return;
if (apnType.equals(Phone.APN_TYPE_DEFAULT)) {
- if (!rm.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
- if (!rm.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+ if (!dc.configureRetry(SystemProperties.get("ro.gsm.data_retry_config"))) {
+ if (!dc.configureRetry(DEFAULT_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple linear sequence.
- log("Could not configure using DEFAULT_DATA_RETRY_CONFIG="
- + DEFAULT_DATA_RETRY_CONFIG);
- rm.configure(20, 2000, 1000);
+ loge("createDataConnection: Could not configure using " +
+ "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
+ dc.configureRetry(20, 2000, 1000);
}
}
} else {
- if (!rm.configure(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
- if (!rm.configure(SECONDARY_DATA_RETRY_CONFIG)) {
+ if (!dc.configureRetry(SystemProperties.get("ro.gsm.2nd_data_retry_config"))) {
+ if (!dc.configureRetry(SECONDARY_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple sequence.
- log("Could note configure using SECONDARY_DATA_RETRY_CONFIG="
- + SECONDARY_DATA_RETRY_CONFIG);
- rm.configure("max_retries=3, 333, 333, 333");
+ loge("createDataConnection: Could note configure using " +
+ "SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
+ dc.configureRetry("max_retries=3, 333, 333, 333");
}
}
}
-
- int id = mUniqueIdGenerator.getAndIncrement();
- DataConnection conn = GsmDataConnection.makeDataConnection(mGsmPhone, id, rm);
- mDataConnections.put(id, conn);
- mApnToDataConnectionId.put(apnType, id);
-
- log("createDataConnection(" + apnType + ") X id=" + id);
- return id;
}
private void destroyDataConnections() {
if(mDataConnections != null) {
- log("destroyDataConnectionList clear mDataConnectionList");
+ if (DBG) log("destroyDataConnections: clear mDataConnectionList");
mDataConnections.clear();
} else {
- log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
+ if (DBG) log("destroyDataConnectionList mDataConnecitonList is empty, ignore");
}
}
- private ApnSetting fetchDunApn() {
- Context c = mPhone.getContext();
- String apnData = Settings.Secure.getString(c.getContentResolver(),
- Settings.Secure.TETHER_DUN_APN);
- ApnSetting dunSetting = ApnSetting.fromString(apnData);
- if (dunSetting != null) return dunSetting;
-
- apnData = c.getResources().getString(R.string.config_tether_apndata);
- return ApnSetting.fromString(apnData);
- }
-
/**
* Build a list of APNs to be used to create PDP's.
*
@@ -1187,53 +1932,44 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (requestedApnType.equals(Phone.APN_TYPE_DUN)) {
ApnSetting dun = fetchDunApn();
- if (dun != null) apnList.add(dun);
- return apnList;
+ if (dun != null) {
+ apnList.add(dun);
+ if (DBG) log("buildWaitingApns: X added APN_TYPE_DUN apnList=" + apnList);
+ return apnList;
+ }
}
- String operator = mGsmPhone.mSIMRecords.getSIMOperatorNumeric();
-
+ String operator = mPhone.mIccRecords.getOperatorNumeric();
if (requestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
if (canSetPreferApn && mPreferredApn != null) {
- log("Preferred APN:" + operator + ":"
+ if (DBG) {
+ log("buildWaitingApns: Preferred APN:" + operator + ":"
+ mPreferredApn.numeric + ":" + mPreferredApn);
+ }
if (mPreferredApn.numeric.equals(operator)) {
- log("Waiting APN set to preferred APN");
apnList.add(mPreferredApn);
+ if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
return apnList;
} else {
+ if (DBG) log("buildWaitingApns: no preferred APN");
setPreferredApn(-1);
mPreferredApn = null;
}
}
}
-
if (mAllApns != null) {
for (ApnSetting apn : mAllApns) {
if (apn.canHandleType(requestedApnType)) {
apnList.add(apn);
}
}
+ } else {
+ loge("mAllApns is empty!");
}
+ if (DBG) log("buildWaitingApns: X apnList=" + apnList);
return apnList;
}
- /**
- * Get next apn in waitingApns
- * @return the first apn found in waitingApns, null if none
- */
- private ApnSetting getNextApn() {
- ArrayList<ApnSetting> list = mWaitingApns;
- ApnSetting apn = null;
-
- if (list != null) {
- if (!list.isEmpty()) {
- apn = list.get(0);
- }
- }
- return apn;
- }
-
private String apnListToString (ArrayList<ApnSetting> apns) {
StringBuilder result = new StringBuilder();
for (int i = 0, size = apns.size(); i < size; i++) {
@@ -1244,9 +1980,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return result.toString();
}
- private void startDelayedRetry(GsmDataConnection.FailCause cause, String reason) {
- notifyNoData(cause);
- reconnectAfterFail(cause, reason);
+ private void startDelayedRetry(GsmDataConnection.FailCause cause, ApnContext apnContext) {
+ notifyNoData(cause, apnContext);
+ reconnectAfterFail(cause, apnContext);
}
private void setPreferredApn(int pos) {
@@ -1300,10 +2036,10 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
@Override
public void handleMessage (Message msg) {
- if (DBG) log("GSMDataConnTrack handleMessage "+msg);
+ if (DBG) log("handleMessage msg=" + msg);
- if (!mGsmPhone.mIsTheCurrentActivePhone) {
- log("Ignore GSM msgs since GSM phone is inactive");
+ if (!mPhone.mIsTheCurrentActivePhone || mIsDisposed) {
+ loge("handleMessage: Ignore GSM msgs since GSM phone is inactive");
return;
}
@@ -1312,20 +2048,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
onRecordsLoaded();
break;
- case EVENT_GPRS_DETACHED:
- onGprsDetached();
+ case EVENT_DATA_CONNECTION_DETACHED:
+ onDataConnectionDetached();
break;
- case EVENT_GPRS_ATTACHED:
- onGprsAttached();
+ case EVENT_DATA_CONNECTION_ATTACHED:
+ onDataConnectionAttached();
break;
case EVENT_DATA_STATE_CHANGED:
- onDataStateChanged((AsyncResult) msg.obj, false);
- break;
-
- case EVENT_GET_PDP_LIST_COMPLETE:
- onDataStateChanged((AsyncResult) msg.obj, true);
+ onDataStateChanged((AsyncResult) msg.obj);
break;
case EVENT_POLL_PDP:
@@ -1351,7 +2083,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* PDP context and notify us with PDP_CONTEXT_CHANGED.
* But we should stop the network polling and prevent reset PDP.
*/
- log("[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
+ if (DBG) log("EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
stopNetStatPoll();
mIsPsRestricted = true;
break;
@@ -1361,20 +2093,39 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* When PS restrict is removed, we need setup PDP connection if
* PDP connection is down.
*/
- log("[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
+ if (DBG) log("EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
mIsPsRestricted = false;
- if (mState == State.CONNECTED) {
+ if (isConnected()) {
startNetStatPoll();
} else {
+ // TODO: Should all PDN states be checked to fail?
if (mState == State.FAILED) {
- cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
- mRetryMgr.resetRetryCount();
+ cleanUpAllConnections(false, Phone.REASON_PS_RESTRICT_ENABLED);
+ resetAllRetryCounts();
mReregisterOnReconnectFailure = false;
}
- trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);
+ trySetupData(Phone.REASON_PS_RESTRICT_ENABLED, Phone.APN_TYPE_DEFAULT);
+ }
+ break;
+ case EVENT_TRY_SETUP_DATA:
+ if (msg.obj instanceof ApnContext) {
+ onTrySetupData((ApnContext)msg.obj);
+ } else if (msg.obj instanceof String) {
+ onTrySetupData((String)msg.obj);
+ } else {
+ loge("EVENT_TRY_SETUP request w/o apnContext or String");
}
break;
+ case EVENT_CLEAN_UP_CONNECTION:
+ boolean tearDown = (msg.arg1 == 0) ? false : true;
+ if (DBG) log("EVENT_CLEAN_UP_CONNECTION tearDown=" + tearDown);
+ if (msg.obj instanceof ApnContext) {
+ cleanUpConnection(tearDown, (ApnContext)msg.obj);
+ } else {
+ loge("EVENT_CLEAN_UP_CONNECTION request w/o apn context");
+ }
+ break;
default:
// handle the message in the super class DataConnectionTracker
super.handleMessage(msg);
@@ -1382,13 +2133,44 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
}
+ protected int getApnProfileID(String apnType) {
+ if (TextUtils.equals(apnType, Phone.APN_TYPE_IMS)) {
+ return RILConstants.DATA_PROFILE_IMS;
+ } else if (TextUtils.equals(apnType, Phone.APN_TYPE_FOTA)) {
+ return RILConstants.DATA_PROFILE_FOTA;
+ } else if (TextUtils.equals(apnType, Phone.APN_TYPE_CBS)) {
+ return RILConstants.DATA_PROFILE_CBS;
+ } else {
+ return RILConstants.DATA_PROFILE_DEFAULT;
+ }
+ }
+
+ private int getCellLocationId() {
+ int cid = -1;
+ CellLocation loc = mPhone.getCellLocation();
+
+ if (loc != null) {
+ if (loc instanceof GsmCellLocation) {
+ cid = ((GsmCellLocation)loc).getCid();
+ } else if (loc instanceof CdmaCellLocation) {
+ cid = ((CdmaCellLocation)loc).getBaseStationId();
+ }
+ }
+ return cid;
+ }
+
+ @Override
+ public boolean isAnyActiveDataConnections() {
+ return isConnected();
+ }
+
@Override
protected void log(String s) {
- Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+ Log.d(LOG_TAG, "[GsmDCT] "+ s);
}
@Override
protected void loge(String s) {
- Log.e(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+ Log.e(LOG_TAG, "[GsmDCT] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 2962e0f..680b3cd 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -765,7 +765,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
// invalid length
handlePasswordError(com.android.internal.R.string.invalidPin);
} else if (sc.equals(SC_PIN) &&
- phone.mSimCard.getState() == SimCard.State.PUK_REQUIRED ) {
+ phone.mIccCard.getState() == SimCard.State.PUK_REQUIRED ) {
// Sim is puk-locked
handlePasswordError(com.android.internal.R.string.needPuk);
} else {
@@ -885,7 +885,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
*/
if ((ar.exception == null) && (msg.arg1 == 1)) {
boolean cffEnabled = (msg.arg2 == 1);
- phone.mSIMRecords.setVoiceCallForwardingFlag(1, cffEnabled);
+ phone.mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
}
onSetComplete(ar);
@@ -1203,7 +1203,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
(info.serviceClass & serviceClassMask)
== CommandsInterface.SERVICE_CLASS_VOICE) {
boolean cffEnabled = (info.status == 1);
- phone.mSIMRecords.setVoiceCallForwardingFlag(1, cffEnabled);
+ phone.mIccRecords.setVoiceCallForwardingFlag(1, cffEnabled);
}
return TextUtils.replace(template, sources, destinations);
@@ -1228,7 +1228,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
sb.append(context.getText(com.android.internal.R.string.serviceDisabled));
// Set unconditional CFF in SIM to false
- phone.mSIMRecords.setVoiceCallForwardingFlag(1, false);
+ phone.mIccRecords.setVoiceCallForwardingFlag(1, false);
} else {
SpannableStringBuilder tb = new SpannableStringBuilder();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index f576b4e..21a12f1 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -99,7 +99,7 @@ final class GsmSMSDispatcher extends SMSDispatcher {
/** {@inheritDoc} */
@Override
- protected int dispatchMessage(SmsMessageBase smsb) {
+ public int dispatchMessage(SmsMessageBase smsb) {
// If sms is null, means there was a parsing error.
if (smsb == null) {
@@ -383,7 +383,7 @@ final class GsmSMSDispatcher extends SMSDispatcher {
/** {@inheritDoc} */
@Override
- protected void activateCellBroadcastSms(int activate, Message response) {
+ public void activateCellBroadcastSms(int activate, Message response) {
// Unless CBS is implemented for GSM, this point should be unreachable.
Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
response.recycle();
@@ -391,7 +391,7 @@ final class GsmSMSDispatcher extends SMSDispatcher {
/** {@inheritDoc} */
@Override
- protected void getCellBroadcastSmsConfig(Message response){
+ public void getCellBroadcastSmsConfig(Message response){
// Unless CBS is implemented for GSM, this point should be unreachable.
Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
response.recycle();
@@ -399,7 +399,7 @@ final class GsmSMSDispatcher extends SMSDispatcher {
/** {@inheritDoc} */
@Override
- protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+ public void setCellBroadcastConfig(int[] configValuesArray, Message response) {
// Unless CBS is implemented for GSM, this point should be unreachable.
Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
response.recycle();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index ac83808..dce9a17 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -23,6 +23,7 @@ import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RestrictedState;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
@@ -75,7 +76,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
GsmCellLocation cellLoc;
GsmCellLocation newCellLoc;
int mPreferredNetworkType;
- RestrictedState rs;
private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
@@ -85,7 +85,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
private int mNewReasonDataDenied = -1;
/**
- * Values correspond to ServiceStateTracker.DATA_ACCESS_ definitions.
+ * Values correspond to ServiceState.RADIO_TECHNOLOGY_ definitions.
*/
private int networkType = 0;
private int newNetworkType = 0;
@@ -107,11 +107,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
*/
private boolean mEmergencyOnly = false;
- private RegistrantList gprsAttachedRegistrants = new RegistrantList();
- private RegistrantList gprsDetachedRegistrants = new RegistrantList();
- private RegistrantList psRestrictEnabledRegistrants = new RegistrantList();
- private RegistrantList psRestrictDisabledRegistrants = new RegistrantList();
-
/**
* Sometimes we get the NITZ time before we know what country we
* are in. Keep the time zone information from the NITZ string so
@@ -169,8 +164,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
static final int PS_NOTIFICATION = 888; // Id to update and cancel PS restricted
static final int CS_NOTIFICATION = 999; // Id to update and cancel CS restricted
- static final int MAX_NUM_DATA_STATE_READS = 15;
-
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -206,7 +199,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
newSS = new ServiceState();
cellLoc = new GsmCellLocation();
newCellLoc = new GsmCellLocation();
- rs = new RestrictedState();
mSignalStrength = new SignalStrength();
PowerManager powerManager =
@@ -255,7 +247,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
cm.unregisterForVoiceNetworkStateChanged(this);
cm.unregisterForSIMReady(this);
- phone.mSIMRecords.unregisterForRecordsLoaded(this);
+ phone.mIccRecords.unregisterForRecordsLoaded(this);
cm.unSetOnSignalStrengthUpdate(this);
cm.unSetOnRestrictedStateChanged(this);
cm.unSetOnNITZTime(this);
@@ -264,7 +256,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
protected void finalize() {
- if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized");
+ if(DBG) log("finalize");
}
@Override
@@ -272,97 +264,6 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
return phone;
}
- /**
- * Registration point for transition into GPRS attached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForGprsAttached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- gprsAttachedRegistrants.add(r);
-
- if (gprsState == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForGprsAttached(Handler h) {
- gprsAttachedRegistrants.remove(h);
- }
-
- void registerForNetworkAttach(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- networkAttachedRegistrants.add(r);
-
- if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForNetworkAttach(Handler h) {
- networkAttachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into GPRS detached.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForGprsDetached(Handler h, int what, Object obj) {
- Registrant r = new Registrant(h, what, obj);
- gprsDetachedRegistrants.add(r);
-
- if (gprsState == ServiceState.STATE_OUT_OF_SERVICE) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForGprsDetached(Handler h) {
- gprsDetachedRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition into packet service restricted zone.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled ");
- Registrant r = new Registrant(h, what, obj);
- psRestrictEnabledRegistrants.add(r);
-
- if (rs.isPsRestricted()) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForPsRestrictedEnabled(Handler h) {
- psRestrictEnabledRegistrants.remove(h);
- }
-
- /**
- * Registration point for transition out of packet service restricted zone.
- * @param h handler to notify
- * @param what what code of message when delivered
- * @param obj placed in Message.obj
- */
- void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled ");
- Registrant r = new Registrant(h, what, obj);
- psRestrictDisabledRegistrants.add(r);
-
- if (rs.isPsRestricted()) {
- r.notifyRegistrant();
- }
- }
-
- void unregisterForPsRestrictedDisabled(Handler h) {
- psRestrictDisabledRegistrants.remove(h);
- }
-
public void handleMessage (Message msg) {
AsyncResult ar;
int[] ints;
@@ -380,7 +281,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
// it has been unlocked. At this stage, the radio is already
// powered on.
if (mNeedToRegForSimLoaded) {
- phone.mSIMRecords.registerForRecordsLoaded(this,
+ phone.mIccRecords.registerForRecordsLoaded(this,
EVENT_SIM_RECORDS_LOADED, null);
mNeedToRegForSimLoaded = false;
}
@@ -548,7 +449,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
// This is a notification from
// CommandsInterface.setOnRestrictedStateChanged
- Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_RESTRICTED_STATE_CHANGED");
+ if (DBG) log("EVENT_RESTRICTED_STATE_CHANGED");
ar = (AsyncResult) msg.obj;
@@ -556,7 +457,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
break;
default:
- Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+ super.handleMessage(msg);
break;
}
}
@@ -567,36 +468,14 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
&& cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
cm.setRadioPower(true, null);
} else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
- DataConnectionTracker dcTracker = phone.mDataConnection;
- if (! dcTracker.isDataConnectionAsDesired()) {
- EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
- dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0);
- }
// If it's on and available and we want it off gracefully
- powerOffRadioSafely();
+ DataConnectionTracker dcTracker = phone.mDataConnectionTracker;
+ powerOffRadioSafely(dcTracker);
} // Otherwise, we're in the desired state
}
@Override
- protected void powerOffRadioSafely() {
- // clean data connection
- DataConnectionTracker dcTracker = phone.mDataConnection;
- Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 1; // tearDown is true
- msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF;
- dcTracker.sendMessage(msg);
-
- // poll data state up to 15 times, with a 100ms delay
- // totaling 1.5 sec. Normal data disable action will finish in 100ms.
- for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
- if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED
- && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
- Log.d(LOG_TAG, "Data shutdown complete.");
- break;
- }
- SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
- }
-
+ protected void hangupAndPowerOff() {
// hang up all active voice calls
if (phone.isInCall()) {
phone.mCT.ringingCall.hangupIfAlive();
@@ -608,15 +487,15 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
protected void updateSpnDisplay() {
- int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric());
- String spn = phone.mSIMRecords.getServiceProviderName();
+ int rule = phone.mIccRecords.getDisplayRule(ss.getOperatorNumeric());
+ String spn = phone.mIccRecords.getServiceProviderName();
String plmn = ss.getOperatorAlphaLong();
// For emergency calls only, pass the EmergencyCallsOnly string via EXTRA_PLMN
if (mEmergencyOnly && cm.getRadioState().isOn()) {
plmn = Resources.getSystem().
getText(com.android.internal.R.string.emergency_calls_only).toString();
- Log.d(LOG_TAG, "updateSpnDisplay: emergency only and radio is on plmn='" + plmn + "'");
+ if (DBG) log("updateSpnDisplay: emergency only and radio is on plmn='" + plmn + "'");
}
if (rule != curSpnRule
@@ -627,10 +506,11 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
boolean showPlmn = !TextUtils.isEmpty(plmn) &&
(rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
- Log.d(LOG_TAG,
- String.format("updateSpnDisplay: changed sending intent" + " rule=" + rule +
+ if (DBG) {
+ log(String.format("updateSpnDisplay: changed sending intent" + " rule=" + rule +
" showPlmn='%b' plmn='%s' showSpn='%b' spn='%s'",
showPlmn, plmn, showSpn, spn));
+ }
Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
@@ -674,10 +554,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
return;
}
- if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
- err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
- Log.e(LOG_TAG,
- "RIL implementation has returned an error where it must succeed" +
+ if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
+ loge("RIL implementation has returned an error where it must succeed" +
ar.exception);
}
} else try {
@@ -706,7 +584,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
+ loge("error parsing RegistrationState: " + ex);
}
}
@@ -746,7 +624,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
mNewMaxDataCalls = Integer.parseInt(states[5]);
}
} catch (NumberFormatException ex) {
- Log.w(LOG_TAG, "error parsing GprsRegistrationState: " + ex);
+ loge("error parsing GprsRegistrationState: " + ex);
}
}
newGPRSState = regCodeToServiceState(regState);
@@ -771,8 +649,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "Exception while polling service state. "
- + "Probably malformed RIL response.", ex);
+ loge("Exception while polling service state. Probably malformed RIL response." + ex);
}
pollingContext[0]--;
@@ -835,7 +712,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
case RUIM_LOCKED_OR_ABSENT:
case NV_NOT_READY:
case NV_READY:
- Log.d(LOG_TAG, "Radio Technology Change ongoing, setting SS to off");
+ if (DBG) log("Radio Technology Change ongoing, setting SS to off");
newSS.setStateOff();
newCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
@@ -877,26 +754,26 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
String ret = "unknown";
switch (type) {
- case DATA_ACCESS_GPRS:
+ case ServiceState.RADIO_TECHNOLOGY_GPRS:
ret = "GPRS";
break;
- case DATA_ACCESS_EDGE:
+ case ServiceState.RADIO_TECHNOLOGY_EDGE:
ret = "EDGE";
break;
- case DATA_ACCESS_UMTS:
+ case ServiceState.RADIO_TECHNOLOGY_UMTS:
ret = "UMTS";
break;
- case DATA_ACCESS_HSDPA:
+ case ServiceState.RADIO_TECHNOLOGY_HSDPA:
ret = "HSDPA";
break;
- case DATA_ACCESS_HSUPA:
+ case ServiceState.RADIO_TECHNOLOGY_HSUPA:
ret = "HSUPA";
break;
- case DATA_ACCESS_HSPA:
+ case ServiceState.RADIO_TECHNOLOGY_HSPA:
ret = "HSPA";
break;
default:
- Log.e(LOG_TAG, "Wrong network type: " + Integer.toString(type));
+ sloge("Wrong network type: " + Integer.toString(type));
break;
}
@@ -905,7 +782,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
private void pollStateDone() {
if (DBG) {
- Log.d(LOG_TAG, "Poll ServiceState done: " +
+ log("Poll ServiceState done: " +
" oldSS=[" + ss + "] newSS=[" + newSS +
"] oldGprs=" + gprsState + " newData=" + newGPRSState +
" oldMaxDataCalls=" + mMaxDataCalls +
@@ -967,9 +844,10 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
if (loc != null) cid = loc.getCid();
EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED, cid, networkType, newNetworkType);
- Log.d(LOG_TAG,
- "RAT switched " + networkTypeToString(networkType) + " -> "
+ if (DBG) {
+ log("RAT switched " + networkTypeToString(networkType) + " -> "
+ networkTypeToString(newNetworkType) + " at cell " + cid);
+ }
}
gprsState = newGPRSState;
@@ -988,7 +866,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
if (hasRegistered) {
- networkAttachedRegistrants.notifyRegistrants();
+ mNetworkAttachedRegistrants.notifyRegistrants();
}
if (hasChanged) {
@@ -1010,9 +888,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
iso = MccTable.countryCodeForMcc(Integer.parseInt(
operatorNumeric.substring(0,3)));
} catch ( NumberFormatException ex){
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("countryCodeForMcc error" + ex);
} catch ( StringIndexOutOfBoundsException ex) {
- Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+ loge("countryCodeForMcc error" + ex);
}
phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, iso);
@@ -1065,23 +943,23 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
if (hasGprsAttached) {
- gprsAttachedRegistrants.notifyRegistrants();
+ mAttachedRegistrants.notifyRegistrants();
}
if (hasGprsDetached) {
- gprsDetachedRegistrants.notifyRegistrants();
+ mDetachedRegistrants.notifyRegistrants();
}
if (hasNetworkTypeChanged) {
- phone.notifyDataConnection();
+ phone.notifyDataConnection(Phone.REASON_NW_TYPE_CHANGED, Phone.APN_TYPE_ALL);
}
if (hasRoamingOn) {
- roamingOnRegistrants.notifyRegistrants();
+ mRoamingOnRegistrants.notifyRegistrants();
}
if (hasRoamingOff) {
- roamingOffRegistrants.notifyRegistrants();
+ mRoamingOffRegistrants.notifyRegistrants();
}
if (hasLocationChanged) {
@@ -1125,10 +1003,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
// Couldn't find a proper timezone. Perhaps the DST data is wrong.
guess = findTimeZone(offset, !dst, when);
}
- if (DBG) {
- Log.d(LOG_TAG, "getNitzTimeZone returning "
- + (guess == null ? guess : guess.getID()));
- }
+ if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID()));
return guess;
}
@@ -1199,7 +1074,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
lteRssnr = ints[10];
lteCqi = ints[11];
} else {
- Log.e(LOG_TAG, "Bogus signal strength response");
+ loge("Bogus signal strength response");
rssi = 99;
}
}
@@ -1226,10 +1101,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
* @param ar an int value of RIL_RESTRICTED_STATE_*
*/
private void onRestrictedStateChanged(AsyncResult ar) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "onRestrictedStateChanged");
RestrictedState newRs = new RestrictedState();
- Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at enter "+ rs);
+ if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState);
if (ar.exception == null) {
int[] ints = (int[])ar.result;
@@ -1247,13 +1121,13 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
(state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
}
- Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);
+ if (DBG) log("onRestrictedStateChanged: new rs "+ newRs);
- if (!rs.isPsRestricted() && newRs.isPsRestricted()) {
- psRestrictEnabledRegistrants.notifyRegistrants();
+ if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) {
+ mPsRestrictEnabledRegistrants.notifyRegistrants();
setNotification(PS_ENABLED);
- } else if (rs.isPsRestricted() && !newRs.isPsRestricted()) {
- psRestrictDisabledRegistrants.notifyRegistrants();
+ } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) {
+ mPsRestrictDisabledRegistrants.notifyRegistrants();
setNotification(PS_DISABLED);
}
@@ -1262,7 +1136,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
* there are 4 x 4 combinations in current and new restricted states
* and we only need to notify when state is changed.
*/
- if (rs.isCsRestricted()) {
+ if (mRestrictedState.isCsRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
@@ -1273,7 +1147,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
// remove emergency restriction
setNotification(CS_NORMAL_ENABLED);
}
- } else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) {
+ } else if (mRestrictedState.isCsEmergencyRestricted() &&
+ !mRestrictedState.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
@@ -1284,7 +1159,8 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
// remove emergency restriction and enable normal restriction
setNotification(CS_NORMAL_ENABLED);
}
- } else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) {
+ } else if (!mRestrictedState.isCsEmergencyRestricted() &&
+ mRestrictedState.isCsNormalRestricted()) {
if (!newRs.isCsRestricted()) {
// remove all restriction
setNotification(CS_DISABLED);
@@ -1308,9 +1184,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
}
}
- rs = newRs;
+ mRestrictedState = newRs;
}
- Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs);
+ log("onRestrictedStateChanged: X rs "+ mRestrictedState);
}
/** code is registration state 0-5 from TS 27.007 7.2 */
@@ -1334,7 +1210,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
return ServiceState.STATE_IN_SERVICE;
default:
- Log.w(LOG_TAG, "unexpected service state " + code);
+ loge("regCodeToServiceState: unexpected service state " + code);
return ServiceState.STATE_OUT_OF_SERVICE;
}
}
@@ -1401,12 +1277,16 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
return gprsState;
}
+ public int getCurrentDataConnectionState() {
+ return gprsState;
+ }
+
/**
* @return true if phone is camping on a technology (eg UMTS)
* that could support voice and data simultaneously.
*/
- boolean isConcurrentVoiceAndData() {
- return (networkType >= DATA_ACCESS_UMTS);
+ public boolean isConcurrentVoiceAndDataAllowed() {
+ return (networkType >= ServiceState.RADIO_TECHNOLOGY_UMTS);
}
/**
@@ -1450,8 +1330,9 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
// tz is in number of quarter-hours
long start = SystemClock.elapsedRealtime();
- Log.i(LOG_TAG, "NITZ: " + nitz + "," + nitzReceiveTime +
+ if (DBG) {log("NITZ: " + nitz + "," + nitzReceiveTime +
" start=" + start + " delay=" + (start - nitzReceiveTime));
+ }
try {
/* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
@@ -1548,7 +1429,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
String ignore = SystemProperties.get("gsm.ignore-nitz");
if (ignore != null && ignore.equals("yes")) {
- Log.i(LOG_TAG, "NITZ: Not setting clock because gsm.ignore-nitz is set");
+ log("NITZ: Not setting clock because gsm.ignore-nitz is set");
return;
}
@@ -1561,43 +1442,49 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
if (millisSinceNitzReceived < 0) {
// Sanity check: something is wrong
- Log.i(LOG_TAG, "NITZ: not setting time, clock has rolled "
+ if (DBG) {
+ log("NITZ: not setting time, clock has rolled "
+ "backwards since NITZ time was received, "
+ nitz);
+ }
return;
}
if (millisSinceNitzReceived > Integer.MAX_VALUE) {
// If the time is this far off, something is wrong > 24 days!
- Log.i(LOG_TAG, "NITZ: not setting time, processing has taken "
+ if (DBG) {
+ log("NITZ: not setting time, processing has taken "
+ (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
+ " days");
+ }
return;
}
// Note: with range checks above, cast to int is safe
c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
- Log.i(LOG_TAG, "NITZ: Setting time of day to " + c.getTime()
- + " NITZ receive delay(ms): " + millisSinceNitzReceived
- + " gained(ms): "
- + (c.getTimeInMillis() - System.currentTimeMillis())
- + " from " + nitz);
+ if (DBG) {
+ log("NITZ: Setting time of day to " + c.getTime()
+ + " NITZ receive delay(ms): " + millisSinceNitzReceived
+ + " gained(ms): "
+ + (c.getTimeInMillis() - System.currentTimeMillis())
+ + " from " + nitz);
+ }
setAndBroadcastNetworkSetTime(c.getTimeInMillis());
Log.i(LOG_TAG, "NITZ: after Setting time of day");
}
SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
saveNitzTime(c.getTimeInMillis());
- if (Config.LOGV) {
+ if (DBG) {
long end = SystemClock.elapsedRealtime();
- Log.v(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
+ log("NITZ: end=" + end + " dur=" + (end - start));
}
} finally {
mWakeLock.release();
}
} catch (RuntimeException ex) {
- Log.e(LOG_TAG, "NITZ: Parsing NITZ time " + nitz, ex);
+ loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex);
}
}
@@ -1663,8 +1550,10 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
Settings.System.AUTO_TIME, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ Time: mSavedTime=" + mSavedTime
+ if (DBG) {
+ log("Reverting to NITZ Time: mSavedTime=" + mSavedTime
+ " mSavedAtTime=" + mSavedAtTime);
+ }
if (mSavedTime != 0 && mSavedAtTime != 0) {
setAndBroadcastNetworkSetTime(mSavedTime
+ (SystemClock.elapsedRealtime() - mSavedAtTime));
@@ -1676,7 +1565,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
Settings.System.AUTO_TIME_ZONE, 0) == 0) {
return;
}
- Log.d(LOG_TAG, "Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
+ if (DBG) log("Reverting to NITZ TimeZone: tz='" + mSavedTimeZone);
if (mSavedTimeZone != null) {
setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
}
@@ -1689,7 +1578,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
*/
private void setNotification(int notifyType) {
- Log.d(LOG_TAG, "[DSAC DEB] " + "create notification " + notifyType);
+ if (DBG) log("setNotification: create notification " + notifyType);
Context context = phone.getContext();
mNotification = new Notification();
@@ -1726,7 +1615,7 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
break;
}
- Log.d(LOG_TAG, "[DSAC DEB] " + "put notification " + title + " / " +details);
+ if (DBG) log("setNotification: put notification " + title + " / " +details);
mNotification.tickerText = title;
mNotification.setLatestEventInfo(context, title, details,
mNotification.contentIntent);
@@ -1745,6 +1634,15 @@ final class GsmServiceStateTracker extends ServiceStateTracker {
@Override
protected void log(String s) {
- Log.d(LOG_TAG, "[GsmServiceStateTracker] " + s);
+ Log.d(LOG_TAG, "[GsmSST] " + s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Log.e(LOG_TAG, "[GsmSST] " + s);
+ }
+
+ private static void sloge(String s) {
+ Log.e(LOG_TAG, "[GsmSST] " + s);
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 3b133da..4cd9440 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -28,6 +28,7 @@ import android.util.Log;
import com.android.internal.telephony.AdnRecord;
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.IccFileHandler;
import com.android.internal.telephony.IccRecords;
@@ -35,6 +36,8 @@ import com.android.internal.telephony.IccUtils;
import com.android.internal.telephony.IccVmFixedException;
import com.android.internal.telephony.IccVmNotSupportedException;
import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
import java.util.ArrayList;
@@ -58,8 +61,8 @@ public final class SIMRecords extends IccRecords {
// ***** Cached SIM State; cleared on channel close
- String imsi;
- boolean callForwardingEnabled;
+ private String imsi;
+ private boolean callForwardingEnabled;
/**
@@ -165,7 +168,7 @@ public final class SIMRecords extends IccRecords {
// ***** Constructor
- SIMRecords(GSMPhone p) {
+ public SIMRecords(PhoneBase p) {
super(p);
adnCache = new AdnRecordCache(phone);
@@ -178,23 +181,29 @@ public final class SIMRecords extends IccRecords {
// recordsToLoad is set to 0 because no requests are made yet
recordsToLoad = 0;
-
- p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+ // SIMRecord is used by CDMA+LTE mode, and SIM_READY event
+ // will be subscribed by CdmaLteServiceStateTracker.
+ if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
+ p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+ }
p.mCM.registerForOffOrNotAvailable(
this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
- p.mCM.setOnIccRefresh(this, EVENT_SIM_REFRESH, null);
+ p.mCM.registerForIccRefresh(this, EVENT_SIM_REFRESH, null);
// Start off by setting empty state
onRadioOffOrNotAvailable();
}
+ @Override
public void dispose() {
//Unregister for all events
- phone.mCM.unregisterForSIMReady(this);
+ if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
+ phone.mCM.unregisterForSIMReady(this);
+ }
phone.mCM.unregisterForOffOrNotAvailable( this);
- phone.mCM.unSetOnIccRefresh(this);
+ phone.mCM.unregisterForIccRefresh(this);
}
protected void finalize() {
@@ -230,7 +239,10 @@ public final class SIMRecords extends IccRecords {
//***** Public Methods
- /** Returns null if SIM is not yet ready */
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public String getIMSI() {
return imsi;
}
@@ -364,7 +376,7 @@ public final class SIMRecords extends IccRecords {
countVoiceMessages = countWaiting;
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
try {
if (efMWIS != null) {
@@ -403,17 +415,25 @@ public final class SIMRecords extends IccRecords {
}
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public boolean getVoiceCallForwardingFlag() {
return callForwardingEnabled;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void setVoiceCallForwardingFlag(int line, boolean enable) {
if (line != 1) return; // only line 1 is supported
callForwardingEnabled = enable;
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
try {
if (mEfCfis != null) {
@@ -467,11 +487,17 @@ public final class SIMRecords extends IccRecords {
}
}
- /** Returns the 5 or 6 digit MCC/MNC of the operator that
- * provided the SIM card. Returns null of SIM is not yet ready
+ /**
+ * {@inheritDoc}
*/
- String getSIMOperatorNumeric() {
- if (imsi == null || mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
+ @Override
+ public String getOperatorNumeric() {
+ if (imsi == null) {
+ Log.d(LOG_TAG, "getOperatorNumeric: IMSI == null");
+ return null;
+ }
+ if (mncLength == UNINITIALIZED || mncLength == UNKNOWN) {
+ Log.d(LOG_TAG, "getSIMOperatorNumeric: bad mncLength");
return null;
}
@@ -518,7 +544,7 @@ public final class SIMRecords extends IccRecords {
imsi = null;
}
- Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxx");
+ Log.d(LOG_TAG, "IMSI: " + /* imsi.substring(0, 6) +*/ "xxxxxxx");
if (((mncLength == UNKNOWN) || (mncLength == 2)) &&
((imsi != null) && (imsi.length() >= 6))) {
@@ -547,7 +573,7 @@ public final class SIMRecords extends IccRecords {
// finally have both the imsi and the mncLength and can parse the imsi properly
MccTable.updateMccMncConfiguration(phone, imsi.substring(0, 3 + mncLength));
}
- ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_IMSI, null);
break;
@@ -702,7 +728,7 @@ public final class SIMRecords extends IccRecords {
countVoiceMessages = -1;
}
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
break;
case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
@@ -731,7 +757,7 @@ public final class SIMRecords extends IccRecords {
countVoiceMessages = 0;
}
- ((GSMPhone) phone).notifyMessageWaitingIndicator();
+ phone.notifyMessageWaitingIndicator();
}
break;
@@ -842,7 +868,7 @@ public final class SIMRecords extends IccRecords {
callForwardingEnabled =
((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
}
break;
@@ -1042,7 +1068,7 @@ public final class SIMRecords extends IccRecords {
// Refer TS 51.011 Section 10.3.46 for the content description
callForwardingEnabled = ((data[1] & 0x01) != 0);
- ((GSMPhone) phone).notifyCallForwardingIndicator();
+ phone.notifyCallForwardingIndicator();
break;
case EVENT_GET_CSP_CPHS_DONE:
@@ -1152,7 +1178,7 @@ public final class SIMRecords extends IccRecords {
System.arraycopy(ba, 1, pdu, 0, n - 1);
SmsMessage message = SmsMessage.createFromPdu(pdu);
- ((GSMPhone) phone).mSMS.dispatchMessage(message);
+ phone.mSMS.dispatchMessage(message);
}
}
@@ -1178,7 +1204,7 @@ public final class SIMRecords extends IccRecords {
System.arraycopy(ba, 1, pdu, 0, n - 1);
SmsMessage message = SmsMessage.createFromPdu(pdu);
- ((GSMPhone) phone).mSMS.dispatchMessage(message);
+ phone.mSMS.dispatchMessage(message);
// 3GPP TS 51.011 v5.0.0 (20011-12) 10.5.3
// 1 == "received by MS from network; message read"
@@ -1209,7 +1235,7 @@ public final class SIMRecords extends IccRecords {
protected void onAllRecordsLoaded() {
Log.d(LOG_TAG, "SIMRecords: record load complete");
- String operator = getSIMOperatorNumeric();
+ String operator = getOperatorNumeric();
// Some fields require more than one SIM record to set
@@ -1228,7 +1254,7 @@ public final class SIMRecords extends IccRecords {
recordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
- ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_LOADED, null);
}
@@ -1249,11 +1275,11 @@ public final class SIMRecords extends IccRecords {
}
}
- private void onSimReady() {
+ public void onSimReady() {
/* broadcast intent SIM_READY here so that we can make sure
READY is sent before IMSI ready
*/
- ((GSMPhone) phone).mSimCard.broadcastIccStateChangedIntent(
+ phone.mIccCard.broadcastIccStateChangedIntent(
SimCard.INTENT_VALUE_ICC_READY, null);
fetchSimRecords();
@@ -1350,7 +1376,8 @@ public final class SIMRecords extends IccRecords {
*
* If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
*/
- protected int getDisplayRule(String plmn) {
+ @Override
+ public int getDisplayRule(String plmn) {
int rule;
if (spn == null || spnDisplayCondition == -1) {
// EF_SPN was not found on the SIM, or not yet loaded. Just show ONS.
@@ -1377,7 +1404,7 @@ public final class SIMRecords extends IccRecords {
private boolean isOnMatchingPlmn(String plmn) {
if (plmn == null) return false;
- if (plmn.equals(getSIMOperatorNumeric())) {
+ if (plmn.equals(getOperatorNumeric())) {
return true;
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimCard.java b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
index 835cb29..643f709 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimCard.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
@@ -19,6 +19,10 @@ package com.android.internal.telephony.gsm;
import android.util.Log;
import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.TelephonyProperties;
+import android.os.SystemProperties;
/**
* {@hide}
@@ -34,17 +38,39 @@ public final class SimCard extends IccCard {
updateStateProperty();
}
+ /**
+ * We have the Sim card for LTE on CDMA phone
+ */
+ public SimCard(PhoneBase phone, String logTag, Boolean dbg) {
+ super(phone, logTag, dbg);
+ mPhone.mCM.registerForSIMLockedOrAbsent(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
+ mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+ mPhone.mCM.registerForSIMReady(mHandler, EVENT_ICC_READY, null);
+ updateStateProperty();
+
+ if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+ mPhone.mCM.registerForNVReady(mHandler, EVENT_ICC_READY, null);
+ mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_LOCKED_OR_ABSENT, null);
+ }
+ }
+
@Override
public void dispose() {
+ super.dispose();
//Unregister for all events
mPhone.mCM.unregisterForSIMLockedOrAbsent(mHandler);
mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
mPhone.mCM.unregisterForSIMReady(mHandler);
+
+ if(mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+ mPhone.mCM.unregisterForNVReady(mHandler);
+ mPhone.mCM.unregisterForIccStatusChanged(mHandler);
+ }
}
@Override
public String getServiceProviderName () {
- return ((GSMPhone)mPhone).mSIMRecords.getServiceProviderName();
+ return mPhone.mIccRecords.getServiceProviderName();
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
index feb508a..377f8f0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
@@ -32,7 +32,7 @@ public class SimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
public SimPhoneBookInterfaceManager(GSMPhone phone) {
super(phone);
- adnCache = phone.mSIMRecords.getAdnCache();
+ adnCache = phone.mIccRecords.getAdnCache();
//NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
index f2ece7f..5208ccd 100644
--- a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -326,6 +326,10 @@ class SipCommandInterface extends BaseCommands implements CommandsInterface {
public void reportStkServiceIsRunning(Message result) {
}
+ @Override
+ public void getCdmaSubscriptionSource(Message response) {
+ }
+
public void getGsmBroadcastConfig(Message response) {
}
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index d9bd7e8..80de9f3 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -1001,6 +1001,11 @@ public final class SimulatedCommands extends BaseCommands
resultSuccess(result, null);
}
+ @Override
+ public void getCdmaSubscriptionSource(Message result) {
+ unimplemented(result);
+ }
+
private boolean isSimLocked() {
if (mSimLockedState != SimLockState.NONE) {
return true;