Move retrying into DC.
This is the first step in refactoring for bug 4772191.
Bug: 4772191
Change-Id: Id54a20ab192783c63939158670faaf531a527640
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..4afeefc
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,55 @@
+This package contains classes used to manage a DataConnection.
+
+A criticial aspect of this class is that most objects in this
+package run on the same thread except DataConnectionTracker
+This makes processing efficient as it minimizes context
+switching and it eliminates issues with multi-threading.
+
+This can be done because all actions are either asynchronous
+or are known to be non-blocking and fast. At this time only
+DcTesterDeactivateAll takes specific advantage of this
+single threading knowledge by using Dcc#mDcListAll so be
+very careful when making changes that break this assumption.
+
+A related change was in DataConnectionAc I added code that
+checks to see if the caller is on a different thread. If
+it is then the AsyncChannel#sendMessageSynchronously is
+used. If the caller is on the same thread then a getter
+is used. This allows the DCAC to be used from any thread
+and was required to fix a bug when Dcc called
+PhoneBase#notifyDataConnection which calls DCT#getLinkProperties
+and DCT#getLinkCapabilities which call Dcc all on the same
+thread. Without this change there was a dead lock when
+sendMessageSynchronously blocks.
+
+
+Testing:
+
+There are three Intents that can be sent for testing pruproses:
+
+The first two cause bringUp and retry requests to fail and the first
+causes all DC's to fail the second causes a specific DC to fail:
+
+ adb shell am broadcast -a com.android.internal.telephony.dataconnection.action_fail_bringup --ei counter 2 --ei fail_cause -3
+ adb shell am broadcast -a com.android.internal.telephony.dataconnection.DC-1.action_fail_bringup --ei counter 2 --ei fail_cause -3
+
+The other causes all DC's to get torn down, simulating a temporary network outage:
+
+ adb shell am broadcast -a com.android.internal.telephony.dataconnection.action_deactivate_all
+
+To simplify testing we also have detach and attach simulations below where {x} is gsm, cdma or sip
+
+ adb shell am broadcast -a com.android.internal.telephony.{x}.action_detached
+ adb shell am broadcast -a com.android.internal.telephony.{x}.action_attached
+
+
+Additionally, you on DEGUGGABLE builds (userdebug, eng) you can replace the retry configuration
+by setting the SystemProperty: test.data_retry_config for instance:
+
+ adb shell setprop test.data_retry_config "5000,5000,5000"
+
+Which changes the retry to 3 retires at 5 second intervals. This can be added to
+/data/local.prop, don't forget to "adb shell chmod 0600 /data/local.prop":
+ $ cat local.prop.test.data_retry_config
+ test.data_retry_config=5000,5000,5000,5000
+
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 0ea8035..27b0d68 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -705,7 +705,7 @@
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
- * ar.result contains a List of DataCallState
+ * ar.result contains a List of DataCallResponse
* @deprecated Do not use.
*/
@Deprecated
@@ -716,7 +716,7 @@
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
- * ar.result contains a List of DataCallState
+ * ar.result contains a List of DataCallResponse
*/
void getDataCallList(Message result);
@@ -1471,8 +1471,8 @@
/**
* Setup a packet data connection On successful completion, the result
- * message will return a {@link DataCallState} object containing the connection
- * information.
+ * message will return a {@link com.android.internal.telephony.dataconnection.DataCallResponse}
+ * object containing the connection information.
*
* @param radioTechnology
* indicates whether to setup connection on radio technology CDMA
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 13c99ea..d67884d 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -101,6 +101,8 @@
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_LOST_DATA_CONNECTION = "lostDataConnection";
+ static final String REASON_CONNECTED = "connected";
// Used for band mode selection methods
static final int BM_UNSPECIFIED = 0; // selected by baseband automatically
diff --git a/src/java/com/android/internal/telephony/PhoneBase.java b/src/java/com/android/internal/telephony/PhoneBase.java
index 145cbea..04ec3ea 100644
--- a/src/java/com/android/internal/telephony/PhoneBase.java
+++ b/src/java/com/android/internal/telephony/PhoneBase.java
@@ -65,6 +65,8 @@
public abstract class PhoneBase extends Handler implements Phone {
private static final String LOG_TAG = "PhoneBase";
+ protected static final boolean DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
// Key used to read and write the saved network selection numeric value
public static final String NETWORK_SELECTION_KEY = "network_selection_key";
// Key used to read and write the saved network selection operator name
@@ -136,11 +138,42 @@
new AtomicReference<UiccCardApplication>();
public SMSDispatcher mSMS;
+ private TelephonyTester mTelephonyTester;
+ private final String mName;
+ private final String mActionDetached;
+ private final String mActionAttached;
+
+ @Override
+ public String getPhoneName() {
+ return mName;
+ }
+
+ /**
+ * Return the ActionDetached string. When this action is received by components
+ * they are to simulate detaching from the network.
+ *
+ * @return com.android.internal.telephony.{mName}.action_detached
+ * {mName} is GSM, CDMA ...
+ */
+ public String getActionDetached() {
+ return mActionDetached;
+ }
+
+ /**
+ * Return the ActionAttached string. When this action is received by components
+ * they are to simulate attaching to the network.
+ *
+ * @return com.android.internal.telephony.{mName}.action_detached
+ * {mName} is GSM, CDMA ...
+ */
+ public String getActionAttached() {
+ return mActionAttached;
+ }
+
/**
* Set a system property, unless we're in unit test mode
*/
- public void
- setSystemProperty(String property, String value) {
+ public void setSystemProperty(String property, String value) {
if(getUnitTestMode()) {
return;
}
@@ -198,8 +231,8 @@
* unless unit testing.
* @param ci the CommandsInterface
*/
- protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) {
- this(notifier, context, ci, false);
+ protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci) {
+ this(name, notifier, context, ci, false);
}
/**
@@ -212,12 +245,19 @@
* @param unitTestMode when true, prevents notifications
* of state change events
*/
- protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
+ protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
boolean unitTestMode) {
+ mName = name;
mNotifier = notifier;
mContext = context;
mLooper = Looper.myLooper();
mCi = ci;
+ mActionDetached = this.getClass().getPackage().getName() + ".action_detached";
+ mActionAttached = this.getClass().getPackage().getName() + ".action_attached";
+
+ if (DEBUGGABLE) {
+ mTelephonyTester = new TelephonyTester(this);
+ }
setPropertiesByCarrier();
@@ -272,6 +312,10 @@
mSmsStorageMonitor.dispose();
mSmsUsageMonitor.dispose();
mUiccController.unregisterForIccChanged(this);
+
+ if (mTelephonyTester != null) {
+ mTelephonyTester.dispose();
+ }
}
}
@@ -920,9 +964,6 @@
}
@Override
- public abstract String getPhoneName();
-
- @Override
public abstract int getPhoneType();
/** @hide */
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index d54d1ec..3885dbe 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -59,7 +59,8 @@
import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
import com.android.internal.telephony.cdma.CdmaInformationRecords;
import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
-import com.android.internal.telephony.dataconnection.DataConnectionBase;
+import com.android.internal.telephony.dataconnection.DcFailCause;
+import com.android.internal.telephony.dataconnection.DataCallResponse;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
@@ -3230,8 +3231,8 @@
return response;
}
- private DataCallState getDataCallState(Parcel p, int version) {
- DataCallState dataCall = new DataCallState();
+ private DataCallResponse getDataCallResponse(Parcel p, int version) {
+ DataCallResponse dataCall = new DataCallResponse();
dataCall.version = version;
if (version < 5) {
@@ -3249,9 +3250,9 @@
dataCall.active = p.readInt();
dataCall.type = p.readString();
dataCall.ifname = p.readString();
- if ((dataCall.status == DataConnectionBase.FailCause.NONE.getErrorCode()) &&
+ if ((dataCall.status == DcFailCause.NONE.getErrorCode()) &&
TextUtils.isEmpty(dataCall.ifname)) {
- throw new RuntimeException("getDataCallState, no ifname");
+ throw new RuntimeException("getDataCallResponse, no ifname");
}
String addresses = p.readString();
if (!TextUtils.isEmpty(addresses)) {
@@ -3271,15 +3272,15 @@
private Object
responseDataCallList(Parcel p) {
- ArrayList<DataCallState> response;
+ ArrayList<DataCallResponse> response;
int ver = p.readInt();
int num = p.readInt();
riljLog("responseDataCallList ver=" + ver + " num=" + num);
- response = new ArrayList<DataCallState>(num);
+ response = new ArrayList<DataCallResponse>(num);
for (int i = 0; i < num; i++) {
- response.add(getDataCallState(p, ver));
+ response.add(getDataCallResponse(p, ver));
}
return response;
@@ -3291,10 +3292,10 @@
int num = p.readInt();
if (RILJ_LOGV) riljLog("responseSetupDataCall ver=" + ver + " num=" + num);
- DataCallState dataCall;
+ DataCallResponse dataCall;
if (ver < 5) {
- dataCall = new DataCallState();
+ dataCall = new DataCallResponse();
dataCall.version = ver;
dataCall.cid = Integer.parseInt(p.readString());
dataCall.ifname = p.readString();
@@ -3326,7 +3327,7 @@
"RIL_REQUEST_SETUP_DATA_CALL response expecting 1 RIL_Data_Call_response_v5"
+ " got " + num);
}
- dataCall = getDataCallState(p, ver);
+ dataCall = getDataCallResponse(p, ver);
}
return dataCall;
diff --git a/src/java/com/android/internal/telephony/RetryManager.java b/src/java/com/android/internal/telephony/RetryManager.java
index c0222e9..ad073b7 100644
--- a/src/java/com/android/internal/telephony/RetryManager.java
+++ b/src/java/com/android/internal/telephony/RetryManager.java
@@ -74,7 +74,7 @@
*/
public class RetryManager {
static public final String LOG_TAG = "RetryManager";
- static public final boolean DBG = true;
+ static public final boolean DBG = false;
static public final boolean VDBG = false;
/**
@@ -102,6 +102,8 @@
*/
private int mMaxRetryCount;
+ private int mCurMaxRetryCount;
+
/** The current number of retries */
private int mRetryCount;
@@ -117,11 +119,13 @@
@Override
public String toString() {
- String ret = "RetryManager: forever=" + mRetryForever + ", maxRetry=" + mMaxRetryCount +
- ", retry=" + mRetryCount + ",\n " + mConfig;
+ String ret = "RetryManager: { forever=" + mRetryForever + " maxRetry=" + mMaxRetryCount
+ + " curMaxRetry=" + mCurMaxRetryCount + " retry=" + mRetryCount
+ + " config={" + mConfig + "} retryArray={";
for (RetryRec r : mRetryArray) {
- ret += "\n " + r.mDelayTime + ":" + r.mRandomizationTime;
+ ret += r.mDelayTime + ":" + r.mRandomizationTime + " ";
}
+ ret += "}}";
return ret;
}
@@ -155,6 +159,8 @@
}
mMaxRetryCount = maxRetryCount;
+ mCurMaxRetryCount = mMaxRetryCount;
+
resetRetryCount();
mRetryArray.clear();
mRetryArray.add(new RetryRec(retryTime, randomizationTime));
@@ -242,6 +248,7 @@
mMaxRetryCount = mRetryArray.size();
if (VDBG) log("configure: setting mMaxRetryCount=" + mMaxRetryCount);
}
+ mCurMaxRetryCount = mMaxRetryCount;
if (VDBG) log("configure: true");
return true;
} else {
@@ -257,7 +264,7 @@
* false} otherwise.
*/
public boolean isRetryNeeded() {
- boolean retVal = mRetryForever || (mRetryCount < mMaxRetryCount);
+ boolean retVal = mRetryForever || (mRetryCount < mCurMaxRetryCount);
if (DBG) log("isRetryNeeded: " + retVal);
return retVal;
}
@@ -297,8 +304,8 @@
*/
public void increaseRetryCount() {
mRetryCount++;
- if (mRetryCount > mMaxRetryCount) {
- mRetryCount = mMaxRetryCount;
+ if (mRetryCount > mCurMaxRetryCount) {
+ mRetryCount = mCurMaxRetryCount;
}
if (DBG) log("increaseRetryCount: " + mRetryCount);
}
@@ -308,8 +315,8 @@
*/
public void setRetryCount(int count) {
mRetryCount = count;
- if (mRetryCount > mMaxRetryCount) {
- mRetryCount = mMaxRetryCount;
+ if (mRetryCount > mCurMaxRetryCount) {
+ mRetryCount = mCurMaxRetryCount;
}
if (mRetryCount < 0) {
@@ -320,6 +327,33 @@
}
/**
+ * Set current maximum retry count to the specified value
+ */
+ public void setCurMaxRetryCount(int count) {
+ mCurMaxRetryCount = count;
+
+ // Make sure it's not negative
+ if (mCurMaxRetryCount < 0) {
+ mCurMaxRetryCount = 0;
+ }
+
+ // Make sure mRetryCount is within range
+ setRetryCount(mRetryCount);
+
+ if (DBG) log("setCurMaxRetryCount: " + mCurMaxRetryCount);
+ }
+
+ /**
+ * Restore CurMaxRetryCount
+ */
+ public void restoreCurMaxRetryCount() {
+ mCurMaxRetryCount = mMaxRetryCount;
+
+ // Make sure mRetryCount is within range
+ setRetryCount(mRetryCount);
+ }
+
+ /**
* Set retry forever to the specified value
*/
public void setRetryForever(boolean retryForever) {
@@ -339,7 +373,7 @@
* Retry forever using last timeout time.
*/
public void retryForeverUsingLastTimeout() {
- mRetryCount = mMaxRetryCount;
+ mRetryCount = mCurMaxRetryCount;
mRetryForever = true;
if (DBG) log("retryForeverUsingLastTimeout: " + mRetryForever + ", " + mRetryCount);
}
diff --git a/src/java/com/android/internal/telephony/TelephonyTester.java b/src/java/com/android/internal/telephony/TelephonyTester.java
new file mode 100644
index 0000000..eafd248
--- /dev/null
+++ b/src/java/com/android/internal/telephony/TelephonyTester.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.PhoneBase;
+
+/**
+ * Telephony tester receives the following intents where {name} is the phone name
+ *
+ * adb shell am broadcast -a com.android.internal.telephony.{name}.action_detached
+ * adb shell am broadcast -a com.android.internal.telephony.{name}.action_attached
+ */
+public class TelephonyTester {
+ private static final String LOG_TAG = "TelephonyTester";
+ private static final boolean DBG = true;
+ private static final boolean DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+ private PhoneBase mPhone;
+
+ // The static intent receiver one for all instances and we assume this
+ // is running on the same thread as Dcc.
+ protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (DBG) log("sIntentReceiver.onReceive: action=" + action);
+ if (action.equals(mPhone.getActionDetached())) {
+ log("simulate detaching");
+ mPhone.getServiceStateTracker().mDetachedRegistrants.notifyRegistrants();
+ } else if (action.equals(mPhone.getActionAttached())) {
+ log("simulate attaching");
+ mPhone.getServiceStateTracker().mAttachedRegistrants.notifyRegistrants();
+ } else {
+ if (DBG) log("onReceive: unknown action=" + action);
+ }
+ }
+ };
+
+ TelephonyTester(PhoneBase phone) {
+ mPhone = phone;
+
+ if (DEBUGGABLE) {
+ IntentFilter filter = new IntentFilter();
+
+ filter.addAction(mPhone.getActionDetached());
+ log("register for intent action=" + mPhone.getActionDetached());
+
+ filter.addAction(mPhone.getActionAttached());
+ log("register for intent action=" + mPhone.getActionAttached());
+
+ phone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone.getHandler());
+ }
+ }
+
+ void dispose() {
+ mPhone.getContext().unregisterReceiver(mIntentReceiver);
+ }
+
+ private static void log(String s) {
+ Rlog.d(LOG_TAG, s);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 988f36a..3fefa9b 100644
--- a/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -139,6 +139,7 @@
}
break;
+ case RETRYING:
case CONNECTING:
case SCANNING:
ret = PhoneConstants.DataState.CONNECTING;
diff --git a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
index b304e81..139bf2a 100755
--- a/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/src/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -138,14 +138,14 @@
// Constructors
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
- super(notifier, context, ci, false);
+ super("CDMA", notifier, context, ci, false);
initSstIcc();
init(context, notifier);
}
public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
- super(notifier, context, ci, unitTestMode);
+ super("CDMA", notifier, context, ci, unitTestMode);
initSstIcc();
init(context, notifier);
}
@@ -286,11 +286,6 @@
}
@Override
- public String getPhoneName() {
- return "CDMA";
- }
-
- @Override
public int getPhoneType() {
return PhoneConstants.PHONE_TYPE_CDMA;
}
@@ -690,6 +685,7 @@
}
break;
+ case RETRYING:
case CONNECTING:
case SCANNING:
ret = PhoneConstants.DataState.CONNECTING;
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
index a7c4af5..a4c322d 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
@@ -16,6 +16,7 @@
package com.android.internal.telephony.dataconnection;
+import android.app.PendingIntent;
import android.telephony.Rlog;
import com.android.internal.telephony.DctConstants;
@@ -34,7 +35,7 @@
public final String LOG_TAG;
- protected static final boolean DBG = true;
+ protected static final boolean DBG = false;
private final String mApnType;
@@ -47,13 +48,11 @@
private ApnSetting mApnSetting;
- DataConnectionBase mDataConnection;
-
DataConnectionAc mDataConnectionAc;
String mReason;
- int mRetryCount;
+ PendingIntent mReconnectAlarmIntent;
/**
* user/app requested connection on this APN
@@ -69,7 +68,6 @@
mApnType = apnType;
mState = DctConstants.State.IDLE;
setReason(Phone.REASON_DATA_ENABLED);
- setRetryCount(0);
mDataEnabled = new AtomicBoolean(false);
mDependencyMet = new AtomicBoolean(true);
mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0);
@@ -80,19 +78,7 @@
return mApnType;
}
- public synchronized DataConnectionBase getDataConnection() {
- return mDataConnection;
- }
-
- public synchronized void setDataConnection(DataConnectionBase dc) {
- if (DBG) {
- log("setDataConnection: old dc=" + mDataConnection + " new dc=" + dc + " this=" + this);
- }
- mDataConnection = dc;
- }
-
-
- public synchronized DataConnectionAc getDataConnectionAc() {
+ public synchronized DataConnectionAc getDcAc() {
return mDataConnectionAc;
}
@@ -101,20 +87,29 @@
log("setDataConnectionAc: old dcac=" + mDataConnectionAc + " new dcac=" + dcac
+ " this=" + this);
}
- if ((dcac == null) && (mDataConnectionAc != null) &&
- (mDataConnectionAc.dataConnection != null)) {
+ if ((dcac == null) && (mDataConnectionAc != null)) {
// TODO: This tearDown should be done by caller, but for now we'll do it
if (DBG) log("setDataConnection: call tearDown");
- mDataConnectionAc.dataConnection.tearDown(this, "", null);
+ mDataConnectionAc.tearDown(this, "", null);
}
mDataConnectionAc = dcac;
}
+ public synchronized PendingIntent getReconnectIntent() {
+ return mReconnectAlarmIntent;
+ }
+
+ public synchronized void setReconnectIntent(PendingIntent intent) {
+ mReconnectAlarmIntent = intent;
+ }
+
public synchronized ApnSetting getApnSetting() {
+ log("getApnSetting: apnSetting=" + mApnSetting);
return mApnSetting;
}
public synchronized void setApnSetting(ApnSetting apnSetting) {
+ log("setApnSetting: apnSetting=" + apnSetting);
mApnSetting = apnSetting;
}
@@ -188,25 +183,17 @@
return mReason;
}
- public synchronized void setRetryCount(int retryCount) {
- if (DBG) {
- log("setRetryCount: " + retryCount);
- }
- mRetryCount = retryCount;
- DataConnectionBase dc = mDataConnection;
- if (dc != null) {
- dc.setRetryCount(retryCount);
- }
- }
-
- public synchronized int getRetryCount() {
- return mRetryCount;
- }
-
public boolean isReady() {
return mDataEnabled.get() && mDependencyMet.get();
}
+ public boolean isConnectable() {
+ return isReady() && ((mState == DctConstants.State.IDLE)
+ || (mState == DctConstants.State.SCANNING)
+ || (mState == DctConstants.State.RETRYING)
+ || (mState == DctConstants.State.FAILED));
+ }
+
public void setEnabled(boolean enabled) {
if (DBG) {
log("set enabled as " + enabled + ", current state is " + mDataEnabled.get());
@@ -232,12 +219,9 @@
@Override
public String toString() {
// We don't print mDataConnection because its recursive.
- return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns=" + mWaitingApns +
- " mWaitingApnsPermanentFailureCountDown=" + mWaitingApnsPermanentFailureCountDown +
- " mApnSetting=" + mApnSetting +
- " mDataConnection=" + ((mDataConnection != null)
- ? mDataConnection.toStringSimple() : "null") +
- " mReason=" + mReason + " mRetryCount=" + mRetryCount +
+ return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns={" + mWaitingApns +
+ "} mWaitingApnsPermanentFailureCountDown=" + mWaitingApnsPermanentFailureCountDown +
+ " mApnSetting={" + mApnSetting + "} mReason=" + mReason +
" mDataEnabled=" + mDataEnabled + " mDependencyMet=" + mDependencyMet + "}";
}
diff --git a/src/java/com/android/internal/telephony/DataCallState.java b/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java
similarity index 94%
rename from src/java/com/android/internal/telephony/DataCallState.java
rename to src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java
index 12ebc1a..ca9624c 100644
--- a/src/java/com/android/internal/telephony/DataCallState.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataCallResponse.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package com.android.internal.telephony.dataconnection;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -24,7 +24,7 @@
import android.os.SystemProperties;
import android.telephony.Rlog;
-import com.android.internal.telephony.dataconnection.DataConnectionBase.FailCause;
+import com.android.internal.telephony.dataconnection.DcFailCause;
import java.net.Inet4Address;
import java.net.InetAddress;
@@ -32,11 +32,10 @@
/**
* This is RIL_Data_Call_Response_v5 from ril.h
- * TODO: Rename to DataCallResponse.
*/
-public class DataCallState {
+public class DataCallResponse {
private final boolean DBG = true;
- private final String LOG_TAG = "DataCallState";
+ private final String LOG_TAG = "DataCallResponse";
public int version = 0;
public int status = 0;
@@ -60,10 +59,10 @@
ERR_Stale,
ERR_RilError;
- public FailCause mFailCause;
+ public DcFailCause mFailCause;
SetupResult() {
- mFailCause = FailCause.fromInt(0);
+ mFailCause = DcFailCause.fromInt(0);
}
@Override
@@ -75,7 +74,7 @@
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
- sb.append("DataCallState: {")
+ sb.append("DataCallResponse: {")
.append("version=").append(version)
.append(" status=").append(status)
.append(" retry=").append(suggestedRetryTime)
@@ -116,7 +115,7 @@
else
linkProperties.clear();
- if (status == FailCause.NONE.getErrorCode()) {
+ if (status == DcFailCause.NONE.getErrorCode()) {
String propertyPrefix = "net." + ifname + ".";
try {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 0858931..e70f418 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -16,30 +16,200 @@
package com.android.internal.telephony.dataconnection;
-import android.os.Message;
-import android.telephony.Rlog;
-import android.util.Patterns;
-import android.text.TextUtils;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.DctConstants;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RetryManager;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import android.app.PendingIntent;
+import android.net.LinkCapabilities;
+import android.net.LinkProperties;
+import android.net.ProxyProperties;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.text.TextUtils;
+import android.telephony.Rlog;
+import android.telephony.TelephonyManager;
+import android.util.Patterns;
+import android.util.TimeUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* {@hide}
+ *
+ * DataConnection StateMachine.
+ *
+ * This a class for representing a single data connection, with instances of this
+ * class representing a connection via the cellular network. There may be multiple
+ * data connections and all of them are managed by the <code>DataConnectionTracker</code>.
+ *
+ * A recent change is to move retry handling into this class, with that change the
+ * old retry manager is now used internally rather than exposed to the DCT. Also,
+ * bringUp now has an initialRetry which is used limit the number of retries
+ * during the initial bring up of the connection. After the connection becomes active
+ * the current max retry is restored to the configured value.
+ *
+ * NOTE: All DataConnection objects must be running on the same looper, which is the default
+ * as the coordinator has members which are used without synchronization.
*/
-public class DataConnection extends DataConnectionBase {
+public final class DataConnection extends StateMachine {
+ private static final boolean DBG = true;
+ private static final boolean VDBG = true;
+ private static final boolean DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
- //***** Instance Variables
- protected int mProfileId = RILConstants.DATA_PROFILE_DEFAULT;
- //***** Constructor
- private DataConnection(PhoneBase phone, String name, int id, RetryManager rm,
- DataConnectionTrackerBase dct) {
- super(phone, name, id, rm, dct);
+ /** Retry configuration: A doubling of retry times from 5secs to 30minutes */
+ private static final String DEFAULT_DATA_RETRY_CONFIG = "default_randomization=2000,"
+ + "5000,10000,20000,40000,80000:5000,160000:5000,"
+ + "320000:5000,640000:5000,1280000:5000,1800000:5000";
+
+ /** Retry configuration for secondary networks: 4 tries in 20 sec */
+ private static final String SECONDARY_DATA_RETRY_CONFIG =
+ "max_retries=3, 5000, 5000, 5000";
+
+ // The data connection controller
+ private DcController mDcController;
+
+ // The Tester for failing all bringup's
+ private DcTesterFailBringUpAll mDcTesterFailBringUpAll;
+
+ private static AtomicInteger mInstanceNumber = new AtomicInteger(0);
+ private AsyncChannel mAc;
+
+ // Utilities for the DataConnection
+ private DcRetryAlarmController mDcRetryAlarmController;
+
+ // The DCT that's talking to us, we only support one!
+ private DataConnectionTrackerBase mDct = null;
+
+ /**
+ * Used internally for saving connecting parameters.
+ */
+ static class ConnectionParams {
+ int mTag;
+ ApnContext mApnContext;
+ int mInitialMaxRetry;
+ int mProfileId;
+ Message mOnCompletedMsg;
+
+ ConnectionParams(ApnContext apnContext, int initialMaxRetry, int profileId,
+ Message onCompletedMsg) {
+ mApnContext = apnContext;
+ mInitialMaxRetry = initialMaxRetry;
+ mProfileId = profileId;
+ mOnCompletedMsg = onCompletedMsg;
+ }
+
+ @Override
+ public String toString() {
+ return "{mTag=" + mTag + " mApnContext=" + mApnContext
+ + " mInitialMaxRetry=" + mInitialMaxRetry + " mProfileId=" + mProfileId
+ + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}";
+ }
+ }
+
+ /**
+ * Used internally for saving disconnecting parameters.
+ */
+ static class DisconnectParams {
+ int mTag;
+ ApnContext mApnContext;
+ String mReason;
+ Message mOnCompletedMsg;
+
+ DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) {
+ mApnContext = apnContext;
+ mReason = reason;
+ mOnCompletedMsg = onCompletedMsg;
+ }
+
+ @Override
+ public String toString() {
+ return "{mTag=" + mTag + " mApnContext=" + mApnContext
+ + " mReason=" + mReason
+ + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}";
+ }
+ }
+
+ private ApnSetting mApnSetting;
+ private ConnectionParams mConnectionParams;
+ private DisconnectParams mDisconnectParams;
+ private DcFailCause mDcFailCause;
+
+ private PhoneBase mPhone;
+ private LinkProperties mLinkProperties = new LinkProperties();
+ private LinkCapabilities mLinkCapabilities = new LinkCapabilities();
+ private long mCreateTime;
+ private long mLastFailTime;
+ private DcFailCause mLastFailCause;
+ private static final String NULL_IP = "0.0.0.0";
+ private Object mUserData;
+
+ //***** Package visible variables
+ int mTag;
+ int mCid;
+ List<ApnContext> mApnContexts = null;
+ PendingIntent mReconnectIntent = null;
+ RetryManager mRetryManager = new RetryManager();
+
+
+ // ***** Event codes for driving the state machine, package visible for Dcc
+ static final int BASE = Protocol.BASE_DATA_CONNECTION;
+ static final int EVENT_CONNECT = BASE + 0;
+ static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1;
+ static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2;
+ static final int EVENT_DEACTIVATE_DONE = BASE + 3;
+ static final int EVENT_DISCONNECT = BASE + 4;
+ static final int EVENT_RIL_CONNECTED = BASE + 5;
+ static final int EVENT_DISCONNECT_ALL = BASE + 6;
+ static final int EVENT_DATA_STATE_CHANGED = BASE + 7;
+ static final int EVENT_TEAR_DOWN_NOW = BASE + 8;
+ static final int EVENT_LOST_CONNECTION = BASE + 9;
+ static final int EVENT_RETRY_CONNECTION = BASE + 10;
+
+ private static final int CMD_TO_STRING_COUNT = EVENT_RETRY_CONNECTION - BASE + 1;
+ private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
+ static {
+ sCmdToString[EVENT_CONNECT - BASE] = "EVENT_CONNECT";
+ sCmdToString[EVENT_SETUP_DATA_CONNECTION_DONE - BASE] =
+ "EVENT_SETUP_DATA_CONNECTION_DONE";
+ sCmdToString[EVENT_GET_LAST_FAIL_DONE - BASE] = "EVENT_GET_LAST_FAIL_DONE";
+ sCmdToString[EVENT_DEACTIVATE_DONE - BASE] = "EVENT_DEACTIVATE_DONE";
+ sCmdToString[EVENT_DISCONNECT - BASE] = "EVENT_DISCONNECT";
+ sCmdToString[EVENT_RIL_CONNECTED - BASE] = "EVENT_RIL_CONNECTED";
+ sCmdToString[EVENT_DISCONNECT_ALL - BASE] = "EVENT_DISCONNECT_ALL";
+ sCmdToString[EVENT_DATA_STATE_CHANGED - BASE] = "EVENT_DATA_STATE_CHANGED";
+ sCmdToString[EVENT_TEAR_DOWN_NOW - BASE] = "EVENT_TEAR_DOWN_NOW";
+ sCmdToString[EVENT_LOST_CONNECTION - BASE] = "EVENT_LOST_CONNECTION";
+ sCmdToString[EVENT_RETRY_CONNECTION - BASE] = "EVENT_RETRY_CONNECTION";
+ }
+ // Convert cmd to string or null if unknown
+ static String cmdToString(int cmd) {
+ String value;
+ cmd -= BASE;
+ if ((cmd >= 0) && (cmd < sCmdToString.length)) {
+ value = sCmdToString[cmd];
+ } else {
+ value = DataConnectionAc.cmdToString(cmd + BASE);
+ }
+ if (value == null) {
+ value = "0x" + Integer.toHexString(cmd + BASE);
+ }
+ return value;
}
/**
@@ -47,16 +217,166 @@
*
* @param phone the Phone
* @param id the connection id
- * @param rm the RetryManager
* @return DataConnection that was created.
*/
- static DataConnection makeDataConnection(PhoneBase phone, int id, RetryManager rm,
- DataConnectionTrackerBase dct) {
- DataConnection gsmDc = new DataConnection(phone,
- "DC-" + mCount.incrementAndGet(), id, rm, dct);
- gsmDc.start();
- if (DBG) gsmDc.log("Made " + gsmDc.getName());
- return gsmDc;
+ static DataConnection makeDataConnection(PhoneBase phone, int id,
+ DataConnectionTrackerBase dct, DcTesterFailBringUpAll failBringUpAll,
+ DcController dcc) {
+ DataConnection dc = new DataConnection(phone,
+ "DC-" + mInstanceNumber.incrementAndGet(), id, dct, failBringUpAll, dcc);
+ dc.start();
+ if (DBG) dc.log("Made " + dc.getName());
+ return dc;
+ }
+
+ void dispose() {
+ log("dispose: call quiteNow()");
+ quitNow();
+ }
+
+ /* Getter functions */
+
+ LinkCapabilities getCopyLinkCapabilities() {
+ return new LinkCapabilities(mLinkCapabilities);
+ }
+
+ LinkProperties getCopyLinkProperties() {
+ return new LinkProperties(mLinkProperties);
+ }
+
+ boolean getIsInactive() {
+ return getCurrentState() == mInactiveState;
+ }
+
+ int getCid() {
+ return mCid;
+ }
+
+ ApnSetting getApnSetting() {
+ return mApnSetting;
+ }
+
+ void setLinkPropertiesHttpProxy(ProxyProperties proxy) {
+ mLinkProperties.setHttpProxy(proxy);
+ }
+
+ static class UpdateLinkPropertyResult {
+ public DataCallResponse.SetupResult setupResult = DataCallResponse.SetupResult.SUCCESS;
+ public LinkProperties oldLp;
+ public LinkProperties newLp;
+ public UpdateLinkPropertyResult(LinkProperties curLp) {
+ oldLp = curLp;
+ newLp = curLp;
+ }
+ }
+
+ UpdateLinkPropertyResult updateLinkProperty(DataCallResponse newState) {
+ UpdateLinkPropertyResult result = new UpdateLinkPropertyResult(mLinkProperties);
+
+ if (newState == null) return result;
+
+ DataCallResponse.SetupResult setupResult;
+ result.newLp = new LinkProperties();
+
+ // set link properties based on data call response
+ result.setupResult = setLinkProperties(newState, result.newLp);
+ if (result.setupResult != DataCallResponse.SetupResult.SUCCESS) {
+ if (DBG) log("updateLinkProperty failed : " + result.setupResult);
+ return result;
+ }
+ // copy HTTP proxy as it is not part DataCallResponse.
+ result.newLp.setHttpProxy(mLinkProperties.getHttpProxy());
+
+ if (DBG && (! result.oldLp.equals(result.newLp))) {
+ log("updateLinkProperty old LP=" + result.oldLp);
+ log("updateLinkProperty new LP=" + result.newLp);
+ }
+ mLinkProperties = result.newLp;
+
+ return result;
+ }
+
+ //***** Constructor (NOTE: uses dcc.getHandler() as its Handler)
+ private DataConnection(PhoneBase phone, String name, int id,
+ DataConnectionTrackerBase dct, DcTesterFailBringUpAll failBringUpAll,
+ DcController dcc) {
+ super(name, dcc.getHandler());
+ setLogRecSize(300);
+ setLogOnlyTransitions(true);
+ if (DBG) log("DataConnection constructor E");
+
+ mPhone = phone;
+ mDct = dct;
+ mDcTesterFailBringUpAll = failBringUpAll;
+ mDcController = dcc;
+ mId = id;
+ mCid = -1;
+ mDcRetryAlarmController = new DcRetryAlarmController(mPhone, this);
+
+ addState(mDefaultState);
+ addState(mInactiveState, mDefaultState);
+ addState(mActivatingState, mDefaultState);
+ addState(mRetryingState, mDefaultState);
+ addState(mActiveState, mDefaultState);
+ addState(mDisconnectingState, mDefaultState);
+ addState(mDisconnectingErrorCreatingConnection, mDefaultState);
+ setInitialState(mInactiveState);
+
+ mApnContexts = new ArrayList<ApnContext>();
+ if (DBG) log("DataConnection constructor X");
+ }
+
+ private String getRetryConfig(boolean forDefault) {
+ int nt = mPhone.getServiceState().getNetworkType();
+
+ if (DEBUGGABLE) {
+ String config = SystemProperties.get("test.data_retry_config");
+ if (! TextUtils.isEmpty(config)) {
+ return config;
+ }
+ }
+
+ if ((nt == TelephonyManager.NETWORK_TYPE_CDMA) ||
+ (nt == TelephonyManager.NETWORK_TYPE_1xRTT) ||
+ (nt == TelephonyManager.NETWORK_TYPE_EVDO_0) ||
+ (nt == TelephonyManager.NETWORK_TYPE_EVDO_A) ||
+ (nt == TelephonyManager.NETWORK_TYPE_EVDO_B) ||
+ (nt == TelephonyManager.NETWORK_TYPE_EHRPD)) {
+ // CDMA variant
+ return SystemProperties.get("ro.cdma.data_retry_config");
+ } else {
+ // Use GSM variant for all others.
+ if (forDefault) {
+ return SystemProperties.get("ro.gsm.data_retry_config");
+ } else {
+ return SystemProperties.get("ro.gsm.2nd_data_retry_config");
+ }
+ }
+ }
+
+ private void configureRetry(boolean forDefault) {
+ String retryConfig = getRetryConfig(forDefault);
+
+ if (!mRetryManager.configure(retryConfig)) {
+ if (forDefault) {
+ if (!mRetryManager.configure(DEFAULT_DATA_RETRY_CONFIG)) {
+ // Should never happen, log an error and default to a simple linear sequence.
+ loge("configureRetry: Could not configure using " +
+ "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
+ mRetryManager.configure(5, 2000, 1000);
+ }
+ } else {
+ if (!mRetryManager.configure(SECONDARY_DATA_RETRY_CONFIG)) {
+ // Should never happen, log an error and default to a simple sequence.
+ loge("configureRetry: Could note configure using " +
+ "SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
+ mRetryManager.configure(5, 2000, 1000);
+ }
+ }
+ }
+ if (DBG) {
+ log("configureRetry: forDefault=" + forDefault + " mRetryManager=" + mRetryManager);
+ }
}
/**
@@ -66,68 +386,296 @@
*
* @param cp is the connection parameters
*/
- @Override
- protected
- void onConnect(ConnectionParams cp) {
- mApn = cp.mApnContext.getApnSetting();
+ private void onConnect(ConnectionParams cp) {
+ if (DBG) log("onConnect: carrier='" + mApnSetting.carrier
+ + "' APN='" + mApnSetting.apn
+ + "' proxy='" + mApnSetting.proxy + "' port='" + mApnSetting.port + "'");
- if (DBG) log("onConnect: carrier='" + mApn.carrier
- + "' APN='" + mApn.apn
- + "' proxy='" + mApn.proxy + "' port='" + mApn.port + "'");
+ // Check if we should fake an error.
+ if (mDcTesterFailBringUpAll.getDcFailBringUp().mCounter > 0) {
+ DataCallResponse response = new DataCallResponse();
+ response.version = mPhone.mCi.getRilVersion();
+ response.status = mDcTesterFailBringUpAll.getDcFailBringUp().mFailCause.getErrorCode();
+ response.cid = 0;
+ response.active = 0;
+ response.type = "";
+ response.ifname = "";
+ response.addresses = new String[0];
+ response.dnses = new String[0];
+ response.gateways = new String[0];
+ response.suggestedRetryTime =
+ mDcTesterFailBringUpAll.getDcFailBringUp().mSuggestedRetryTime;
+
+ Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
+ AsyncResult.forMessage(msg, response, null);
+ sendMessage(msg);
+ if (DBG) {
+ log("onConnect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp()
+ + " send error response=" + response);
+ }
+ mDcTesterFailBringUpAll.getDcFailBringUp().mCounter -= 1;
+ return;
+ }
mCreateTime = -1;
mLastFailTime = -1;
- mLastFailCause = FailCause.NONE;
+ mLastFailCause = DcFailCause.NONE;
// msg.obj will be returned in AsyncResult.userObj;
Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
msg.obj = cp;
- int authType = mApn.authType;
+ int authType = mApnSetting.authType;
if (authType == -1) {
- authType = TextUtils.isEmpty(mApn.user) ? RILConstants.SETUP_DATA_AUTH_NONE
+ authType = TextUtils.isEmpty(mApnSetting.user) ? RILConstants.SETUP_DATA_AUTH_NONE
: RILConstants.SETUP_DATA_AUTH_PAP_CHAP;
}
String protocol;
if (mPhone.getServiceState().getRoaming()) {
- protocol = mApn.roamingProtocol;
+ protocol = mApnSetting.roamingProtocol;
} else {
- protocol = mApn.protocol;
+ protocol = mApnSetting.protocol;
}
mPhone.mCi.setupDataCall(
Integer.toString(getRilRadioTechnology()),
- Integer.toString(mProfileId),
- mApn.apn, mApn.user, mApn.password,
+ Integer.toString(cp.mProfileId),
+ mApnSetting.apn, mApnSetting.user, mApnSetting.password,
Integer.toString(authType),
protocol, msg);
}
- public void setProfileId(int profileId) {
- mProfileId = profileId;
+ /**
+ * TearDown the data connection when the deactivation is complete a Message with
+ * msg.what == EVENT_DEACTIVATE_DONE and msg.obj == AsyncResult with AsyncResult.obj
+ * containing the parameter o.
+ *
+ * @param o is the object returned in the AsyncResult.obj.
+ */
+ private void tearDownData(Object o) {
+ int discReason = RILConstants.DEACTIVATE_REASON_NONE;
+ if ((o != null) && (o instanceof DisconnectParams)) {
+ DisconnectParams dp = (DisconnectParams)o;
+
+ if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)) {
+ discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;
+ } else if (TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) {
+ discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET;
+ }
+ }
+ if (mPhone.mCi.getRadioState().isOn()) {
+ if (DBG) log("tearDownData radio is on, call deactivateDataCall");
+ mPhone.mCi.deactivateDataCall(mCid, discReason,
+ obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, o));
+ } else {
+ if (DBG) log("tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately");
+ AsyncResult ar = new AsyncResult(o, null, null);
+ sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, ar));
+ }
}
- public int getProfileId() {
- return mProfileId;
+ private void notifyAllWithEvent(ApnContext alreadySent, int event, String reason) {
+ for (ApnContext apnContext : mApnContexts) {
+ if (apnContext == alreadySent) continue;
+ if (reason != null) apnContext.setReason(reason);
+ Message msg = mDct.obtainMessage(event, apnContext);
+ AsyncResult.forMessage(msg);
+ msg.sendToTarget();
+ }
}
- /** Doesn't print mApnList of ApnContext's which would be recursive */
- @Override
- public String toStringSimple() {
- return getName() + ": State=" + getCurrentState().getName() +
- " apnSetting=" + mApn + " RefCount=" + mApnList.size() +
- " cid=" + mCid + " create=" + mCreateTime + " lastFail=" + mLastFailTime +
- " lastFailCause=" + mLastFailCause;
+ private void notifyAllOfConnected(String reason) {
+ notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason);
}
- @Override
- public String toString() {
- return "{" + toStringSimple() + " mApnList=" + mApnList + "}";
+ private void notifyAllOfDisconnectDcRetrying(String reason) {
+ notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DC_RETRYING, reason);
+ }
+ private void notifyAllDisconnectCompleted(DcFailCause cause) {
+ notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DONE, cause.toString());
}
- @Override
- protected boolean isDnsOk(String[] domainNameServers) {
+
+ /**
+ * Send the connectionCompletedMsg.
+ *
+ * @param cp is the ConnectionParams
+ * @param cause and if no error the cause is DcFailCause.NONE
+ * @param sendAll is true if all contexts are to be notified
+ */
+ private void notifyConnectCompleted(ConnectionParams cp, DcFailCause cause, boolean sendAll) {
+ ApnContext alreadySent = null;
+
+ if (cp != null && cp.mOnCompletedMsg != null) {
+ // Get the completed message but only use it once
+ Message connectionCompletedMsg = cp.mOnCompletedMsg;
+ cp.mOnCompletedMsg = null;
+ if (connectionCompletedMsg.obj instanceof ApnContext) {
+ alreadySent = (ApnContext)connectionCompletedMsg.obj;
+ }
+
+ long timeStamp = System.currentTimeMillis();
+ connectionCompletedMsg.arg1 = mCid;
+
+ if (cause == DcFailCause.NONE) {
+ mCreateTime = timeStamp;
+ AsyncResult.forMessage(connectionCompletedMsg);
+ } else {
+ mLastFailCause = cause;
+ mLastFailTime = timeStamp;
+
+ // Return message with a Throwable exception to signify an error.
+ if (cause == null) cause = DcFailCause.UNKNOWN;
+ AsyncResult.forMessage(connectionCompletedMsg, cause,
+ new Throwable(cause.toString()));
+ }
+ if (DBG) {
+ log("notifyConnectCompleted at " + timeStamp + " cause=" + cause
+ + " connectionCompletedMsg=" + msgToString(connectionCompletedMsg));
+ }
+
+ connectionCompletedMsg.sendToTarget();
+ }
+ if (sendAll) {
+ notifyAllWithEvent(alreadySent, DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR,
+ cause.toString());
+ }
+ }
+
+ /**
+ * Send ar.userObj if its a message, which is should be back to originator.
+ *
+ * @param dp is the DisconnectParams.
+ */
+ private void notifyDisconnectCompleted(DisconnectParams dp, boolean sendAll) {
+ if (VDBG) log("NotifyDisconnectCompleted");
+
+ ApnContext alreadySent = null;
+ String reason = null;
+
+ if (dp != null && dp.mOnCompletedMsg != null) {
+ // Get the completed message but only use it once
+ Message msg = dp.mOnCompletedMsg;
+ dp.mOnCompletedMsg = null;
+ if (msg.obj instanceof ApnContext) {
+ alreadySent = (ApnContext)msg.obj;
+ }
+ reason = dp.mReason;
+ 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 (sendAll) {
+ if (reason == null) {
+ reason = DcFailCause.UNKNOWN.toString();
+ }
+ notifyAllWithEvent(alreadySent, DctConstants.EVENT_DISCONNECT_DONE, reason);
+ }
+ if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
+ }
+
+ private int getRilRadioTechnology() {
+ int rilRadioTechnology;
+ if (mApnSetting.bearer > 0) {
+ rilRadioTechnology = mApnSetting.bearer + 2;
+ } else {
+ rilRadioTechnology = mPhone.getServiceState().getRilDataRadioTechnology() + 2;
+ }
+ return rilRadioTechnology;
+ }
+
+ /*
+ * **************************************************************************
+ * 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;
+ }
+
+ /*
+ * **************************************************************************
+ * End members owned by DataConnectionTracker
+ * **************************************************************************
+ */
+
+ /**
+ * Clear all settings called when entering mInactiveState.
+ */
+ private void clearSettings() {
+ if (DBG) log("clearSettings");
+
+ mCreateTime = -1;
+ mLastFailTime = -1;
+ mLastFailCause = DcFailCause.NONE;
+ mCid = -1;
+
+ mLinkProperties = new LinkProperties();
+ mApnContexts.clear();
+ mApnSetting = null;
+ mDcFailCause = null;
+ }
+
+ /**
+ * Process setup completion.
+ *
+ * @param ar is the result
+ * @return SetupResult.
+ */
+ private DataCallResponse.SetupResult onSetupConnectionCompleted(AsyncResult ar) {
+ DataCallResponse response = (DataCallResponse) ar.result;
+ ConnectionParams cp = (ConnectionParams) ar.userObj;
+ DataCallResponse.SetupResult result;
+
+ if (cp.mTag != mTag) {
+ if (DBG) {
+ log("onSetupConnectionCompleted stale cp.tag=" + cp.mTag + ", mtag=" + mTag);
+ }
+ result = DataCallResponse.SetupResult.ERR_Stale;
+ } else if (ar.exception != null) {
+ if (DBG) {
+ log("onSetupConnectionCompleted failed, ar.exception=" + ar.exception +
+ " response=" + response);
+ }
+
+ if (ar.exception instanceof CommandException
+ && ((CommandException) (ar.exception)).getCommandError()
+ == CommandException.Error.RADIO_NOT_AVAILABLE) {
+ result = DataCallResponse.SetupResult.ERR_BadCommand;
+ result.mFailCause = DcFailCause.RADIO_NOT_AVAILABLE;
+ } else if ((response == null) || (response.version < 4)) {
+ result = DataCallResponse.SetupResult.ERR_GetLastErrorFromRil;
+ } else {
+ result = DataCallResponse.SetupResult.ERR_RilError;
+ result.mFailCause = DcFailCause.fromInt(response.status);
+ }
+ } else if (response.status != 0) {
+ result = DataCallResponse.SetupResult.ERR_RilError;
+ result.mFailCause = DcFailCause.fromInt(response.status);
+ } else {
+ if (DBG) log("onSetupConnectionCompleted received DataCallResponse: " + response);
+ mCid = response.cid;
+ result = updateLinkProperty(response).setupResult;
+ }
+
+ return result;
+ }
+
+ private boolean isDnsOk(String[] domainNameServers) {
if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1])
&& !mPhone.isDnsCheckDisabled()) {
// Work around a race condition where QMI does not fill in DNS:
@@ -135,33 +683,966 @@
// 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 (!mApn.types[0].equals(PhoneConstants.APN_TYPE_MMS)
- || !isIpAddress(mApn.mmsProxy)) {
+ if (!mApnSetting.types[0].equals(PhoneConstants.APN_TYPE_MMS)
+ || !isIpAddress(mApnSetting.mmsProxy)) {
log(String.format(
"isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s",
- mApn.types[0], PhoneConstants.APN_TYPE_MMS, mApn.mmsProxy,
- isIpAddress(mApn.mmsProxy)));
+ mApnSetting.types[0], PhoneConstants.APN_TYPE_MMS, mApnSetting.mmsProxy,
+ isIpAddress(mApnSetting.mmsProxy)));
return false;
}
}
return true;
}
- @Override
- protected void log(String s) {
- Rlog.d(getName(), s);
- }
-
private boolean isIpAddress(String address) {
if (address == null) return false;
return Patterns.IP_ADDRESS.matcher(address).matches();
}
+ private DataCallResponse.SetupResult setLinkProperties(DataCallResponse 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);
+ }
+
+ /**
+ * The parent state for all other states.
+ */
+ private class DcDefaultState extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("DcDefaultState: enter");
+
+ // Add ourselves to the list of data connections
+ mDcController.addDc(DataConnection.this);
+ }
+ @Override
+ public void exit() {
+ if (DBG) log("DcDefaultState: exit");
+
+
+ if (mAc != null) {
+ mAc.disconnected();
+ mAc = null;
+ }
+ mDcRetryAlarmController.dispose();
+ mDcRetryAlarmController = null;
+ mApnContexts = null;
+ mReconnectIntent = null;
+ mDct = null;
+ mApnSetting = null;
+ mPhone = null;
+ mLinkProperties = null;
+ mLinkCapabilities = null;
+ mLastFailCause = null;
+ mUserData = null;
+
+ // Remove ourselves from the DC lists
+ mDcController.removeDc(DataConnection.this);
+
+ mDcController = null;
+ mDcTesterFailBringUpAll = null;
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ boolean retVal = HANDLED;
+ AsyncResult ar;
+
+ if (VDBG) {
+ log("DcDefault msg=" + getWhatToString(msg.what)
+ + " RefCount=" + mApnContexts.size());
+ }
+ switch (msg.what) {
+ 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_DISCONNECTED: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECTED");
+ quit();
+ break;
+ }
+ case DataConnectionAc.REQ_IS_INACTIVE: {
+ boolean val = getIsInactive();
+ if (VDBG) log("REQ_IS_INACTIVE isInactive=" + val);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_IS_INACTIVE, val ? 1 : 0);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_CID: {
+ int cid = getCid();
+ if (VDBG) log("REQ_GET_CID cid=" + cid);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_CID, cid);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_APNSETTING: {
+ ApnSetting apnSetting = getApnSetting();
+ if (VDBG) log("REQ_GET_APNSETTING mApnSetting=" + apnSetting);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNSETTING, apnSetting);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_PROPERTIES: {
+ LinkProperties lp = getCopyLinkProperties();
+ 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);
+ setLinkPropertiesHttpProxy(proxy);
+ mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_LINK_PROPERTIES_HTTP_PROXY);
+ break;
+ }
+ case DataConnectionAc.REQ_GET_LINK_CAPABILITIES: {
+ LinkCapabilities lc = getCopyLinkCapabilities();
+ 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");
+ transitionTo(mInactiveState);
+ break;
+ case EVENT_CONNECT:
+ if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
+ ConnectionParams cp = (ConnectionParams) msg.obj;
+ notifyConnectCompleted(cp, DcFailCause.UNKNOWN, false);
+ break;
+
+ case EVENT_DISCONNECT:
+ if (DBG) {
+ log("DcDefaultState deferring msg.what=EVENT_DISCONNECT RefCount="
+ + mApnContexts.size());
+ }
+ deferMessage(msg);
+ break;
+
+ case EVENT_DISCONNECT_ALL:
+ if (DBG) {
+ log("DcDefaultState deferring msg.what=EVENT_DISCONNECT_ALL RefCount="
+ + mApnContexts.size());
+ }
+ deferMessage(msg);
+ break;
+
+ case EVENT_TEAR_DOWN_NOW:
+ if (DBG) log("DcDefaultState EVENT_TEAR_DOWN_NOW");
+ mPhone.mCi.deactivateDataCall(mCid, 0, null);
+ break;
+
+ case EVENT_LOST_CONNECTION:
+ if (DBG) {
+ String s = "DcDefaultState ignore EVENT_LOST_CONNECTION"
+ + " tag=" + msg.arg1 + ":mTag=" + mTag;
+ logAndAddLogRec(s);
+ }
+ break;
+
+ case EVENT_RETRY_CONNECTION:
+ if (DBG) {
+ String s = "DcDefaultState ignore EVENT_RETRY_CONNECTION"
+ + " tag=" + msg.arg1 + ":mTag=" + mTag;
+ logAndAddLogRec(s);
+ }
+ break;
+
+ default:
+ if (DBG) {
+ log("DcDefaultState: shouldn't happen but ignore msg.what="
+ + getWhatToString(msg.what));
+ }
+ break;
+ }
+
+ return retVal;
+ }
+ }
+ private DcDefaultState mDefaultState = new DcDefaultState();
+
+ /**
+ * The state machine is inactive and expects a EVENT_CONNECT.
+ */
+ private class DcInactiveState extends State {
+ // Inform all contexts we've failed connecting
+ public void setEnterNotificationParams(ConnectionParams cp, DcFailCause cause) {
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
+ mConnectionParams = cp;
+ mDisconnectParams = null;
+ mDcFailCause = cause;
+ }
+
+ // Inform all contexts we've failed disconnected
+ public void setEnterNotificationParams(DisconnectParams dp) {
+ if (VDBG) log("DcInactiveState: setEnterNoticationParams dp");
+ mConnectionParams = null;
+ mDisconnectParams = dp;
+ mDcFailCause = DcFailCause.NONE;
+ }
+
+ // Inform all contexts of the failure cause
+ public void setEnterNotificationParams(DcFailCause cause) {
+ mConnectionParams = null;
+ mDisconnectParams = null;
+ mDcFailCause = cause;
+ }
+
+ // We won't be informing anyone
+ public void setEnterNotificationParams() {
+ mConnectionParams = null;
+ mDisconnectParams = null;
+ mDcFailCause = null;
+ }
+
+ @Override
+ public void enter() {
+ mTag += 1;
+ if (DBG) log("DcInactiveState: enter() mTag=" + mTag);
+
+ if (mConnectionParams != null) {
+ if (DBG) {
+ log("DcInactiveState: enter notifyConnectCompleted +ALL failCause="
+ + mDcFailCause);
+ }
+ notifyConnectCompleted(mConnectionParams, mDcFailCause, true);
+ }
+ if (mDisconnectParams != null) {
+ if (DBG) {
+ log("DcInactiveState: enter notifyDisconnectCompleted +ALL failCause="
+ + mDcFailCause);
+ }
+ notifyDisconnectCompleted(mDisconnectParams, true);
+ }
+ if (mDisconnectParams == null && mConnectionParams == null && mDcFailCause != null) {
+ if (DBG) {
+ log("DcInactiveState: enter notifyAllDisconnectCompleted failCause="
+ + mDcFailCause);
+ }
+ notifyAllDisconnectCompleted(mDcFailCause);
+ }
+
+ // Remove ourselves from cid mapping, before clearSettings
+ mDcController.removeActiveDcByCid(DataConnection.this);
+
+ clearSettings();
+ }
+
+ @Override
+ public void exit() {
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case DataConnectionAc.REQ_RESET:
+ if (DBG) {
+ log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
+ }
+ retVal = HANDLED;
+ break;
+
+ case EVENT_CONNECT:
+ mConnectionParams = (ConnectionParams) msg.obj;
+ mConnectionParams.mTag = mTag;
+
+ ApnContext apnContext = mConnectionParams.mApnContext;
+ mApnSetting = apnContext.getApnSetting();
+ mApnContexts.add(apnContext);
+ configureRetry(mApnSetting.canHandleType(PhoneConstants.APN_TYPE_DEFAULT));
+ mRetryManager.setRetryCount(0);
+ mRetryManager.setCurMaxRetryCount(mConnectionParams.mInitialMaxRetry);
+
+ if (DBG) {
+ log("DcInactiveState msg.what=EVENT_CONNECT"
+ + " RefCount=" + mApnContexts.size()
+ + " mApnList=" + mApnContexts
+ + " mConnectionParams=" + mConnectionParams);
+ }
+
+ onConnect(mConnectionParams);
+ transitionTo(mActivatingState);
+ retVal = HANDLED;
+ break;
+
+ case EVENT_DISCONNECT:
+ if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT");
+ notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
+ retVal = HANDLED;
+ break;
+
+ case EVENT_DISCONNECT_ALL:
+ if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT_ALL");
+ notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
+ retVal = HANDLED;
+ break;
+
+ default:
+ if (VDBG) {
+ log("DcInactiveState nothandled msg.what=" + getWhatToString(msg.what));
+ }
+ retVal = NOT_HANDLED;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcInactiveState mInactiveState = new DcInactiveState();
+
+ /**
+ * The state machine is retrying and expects a EVENT_RETRY_CONNECTION.
+ */
+ private class DcRetryingState extends State {
+ @Override
+ public void enter() {
+ if (DBG) {
+ log("DcRetryingState: enter() mTag=" + mTag
+ + ", call notifyAllOfDisconnectDcRetrying lostConnection");
+ }
+
+ notifyAllOfDisconnectDcRetrying(Phone.REASON_LOST_DATA_CONNECTION);
+
+ // Remove ourselves from cid mapping
+ mDcController.removeActiveDcByCid(DataConnection.this);
+ mCid = -1;
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case EVENT_RETRY_CONNECTION: {
+ if (msg.arg1 == mTag) {
+ mRetryManager.increaseRetryCount();
+ if (DBG) {
+ log("DcRetryingState EVENT_RETRY_CONNECTION"
+ + " RetryCount=" + mRetryManager.getRetryCount()
+ + " mConnectionParams=" + mConnectionParams);
+ }
+ onConnect(mConnectionParams);
+ transitionTo(mActivatingState);
+ } else {
+ if (DBG) {
+ log("DcRetryingState stale EVENT_RETRY_CONNECTION"
+ + " tag:" + msg.arg1 + " != mTag:" + mTag);
+ }
+ }
+ retVal = HANDLED;
+ break;
+ }
+ case DataConnectionAc.REQ_RESET: {
+ if (DBG) {
+ log("DcRetryingState: msg.what=RSP_RESET, ignore we're already reset");
+ }
+ mInactiveState.setEnterNotificationParams(mConnectionParams,
+ DcFailCause.RESET_BY_FRAMEWORK);
+ transitionTo(mInactiveState);
+ retVal = HANDLED;
+ break;
+ }
+ case EVENT_CONNECT: {
+ if (DBG) {
+ ConnectionParams cp = (ConnectionParams) msg.obj;
+ log("DcRetryingState msg.what=EVENT_CONNECT "
+ + "RefCount=" + mApnContexts.size() + " cp=" + cp
+ + " mConnectionParams=" + mConnectionParams);
+ }
+ // Enter inactive state and skip notification as
+ // it will be assumed this EVENT_CONNECT failed.
+ mInactiveState.setEnterNotificationParams();
+ deferMessage(msg);
+ transitionTo(mInactiveState);
+ retVal = HANDLED;
+ break;
+ }
+ case EVENT_DISCONNECT: {
+ DisconnectParams dp = (DisconnectParams) msg.obj;
+
+ if (mApnContexts.remove(dp.mApnContext) && mApnContexts.size() == 0) {
+ if (DBG) {
+ log("DcRetryingState msg.what=EVENT_DISCONNECT " + " RefCount="
+ + mApnContexts.size() + " dp=" + dp);
+ }
+ mInactiveState.setEnterNotificationParams(dp);
+ transitionTo(mInactiveState);
+ } else {
+ if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT");
+ notifyDisconnectCompleted(dp, false);
+ }
+ retVal = HANDLED;
+ break;
+ }
+ case EVENT_DISCONNECT_ALL: {
+ if (DBG) {
+ log("DcRetryingState msg.what=EVENT_DISCONNECT/DISCONNECT_ALL "
+ + "RefCount=" + mApnContexts.size());
+ }
+ mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
+ deferMessage(msg);
+ transitionTo(mInactiveState);
+ retVal = HANDLED;
+ break;
+ }
+ default: {
+ if (VDBG) {
+ log("DcRetryingState nothandled msg.what=" + getWhatToString(msg.what));
+ }
+ retVal = NOT_HANDLED;
+ break;
+ }
+ }
+ return retVal;
+ }
+ }
+ private DcRetryingState mRetryingState = new DcRetryingState();
+
+ /**
+ * The state machine is activating a connection.
+ */
+ private class DcActivatingState extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ boolean retVal;
+ AsyncResult ar;
+ ConnectionParams cp;
+
+ if (DBG) log("DcActivatingState: msg=" + msgToString(msg));
+ switch (msg.what) {
+ case EVENT_CONNECT:
+ deferMessage(msg);
+ retVal = HANDLED;
+ break;
+
+ case EVENT_SETUP_DATA_CONNECTION_DONE:
+ ar = (AsyncResult) msg.obj;
+ cp = (ConnectionParams) ar.userObj;
+
+ DataCallResponse.SetupResult result = onSetupConnectionCompleted(ar);
+ if (result != DataCallResponse.SetupResult.ERR_Stale) {
+ if (mConnectionParams != cp) {
+ loge("DcActivatingState: WEIRD mConnectionsParams:"+ mConnectionParams
+ + " != cp:" + cp);
+ }
+ }
+ if (DBG) log("DcActivatingState onSetupConnectionCompleted result=" + result);
+ switch (result) {
+ case SUCCESS:
+ // All is well
+ mDcFailCause = DcFailCause.NONE;
+ transitionTo(mActiveState);
+ break;
+ case ERR_BadCommand:
+ // Vendor ril rejected the command and didn't connect.
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+ transitionTo(mInactiveState);
+ break;
+ case ERR_UnacceptableParameter:
+ // The addresses given from the RIL are bad
+ tearDownData(cp);
+ transitionTo(mDisconnectingErrorCreatingConnection);
+ break;
+ case ERR_GetLastErrorFromRil:
+ // Request failed and this is an old RIL
+ mPhone.mCi.getLastDataCallFailCause(
+ obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp));
+ break;
+ case ERR_RilError:
+ int delay = mDcRetryAlarmController.getSuggestedRetryTime(
+ DataConnection.this, ar);
+ if (delay >= 0) {
+ mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION,
+ mTag, delay);
+ transitionTo(mRetryingState);
+ } else {
+ mInactiveState.setEnterNotificationParams(cp, result.mFailCause);
+ transitionTo(mInactiveState);
+ }
+ break;
+ case ERR_Stale:
+ loge("DcActivatingState: stale EVENT_SETUP_DATA_CONNECTION_DONE"
+ + " tag:" + cp.mTag + " != mTag:" + mTag);
+ break;
+ default:
+ throw new RuntimeException("Unknown SetupResult, should not happen");
+ }
+ retVal = HANDLED;
+ break;
+
+ case EVENT_GET_LAST_FAIL_DONE:
+ ar = (AsyncResult) msg.obj;
+ cp = (ConnectionParams) ar.userObj;
+ if (cp.mTag == mTag) {
+ if (mConnectionParams != cp) {
+ loge("DcActivatingState: WEIRD mConnectionsParams:" + mConnectionParams
+ + " != cp:" + cp);
+ }
+
+ DcFailCause cause = DcFailCause.UNKNOWN;
+
+ if (DBG) {
+ log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE"
+ + " RefCount=" + mApnContexts.size());
+ }
+ if (ar.exception == null) {
+ int rilFailCause = ((int[]) (ar.result))[0];
+ cause = DcFailCause.fromInt(rilFailCause);
+ }
+ mDcFailCause = cause;
+
+ int retryDelay = mRetryManager.getRetryTimer();
+ if (mRetryManager.isRetryNeeded()) {
+ mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, mTag,
+ retryDelay);
+ transitionTo(mRetryingState);
+ } else {
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams(cp, cause);
+ transitionTo(mInactiveState);
+ }
+ } else {
+ loge("DcActivatingState: stale EVENT_GET_LAST_FAIL_DONE"
+ + " tag:" + cp.mTag + " != mTag:" + mTag);
+ }
+
+ retVal = HANDLED;
+ break;
+
+ default:
+ if (VDBG) {
+ log("DcActivatingState not handled msg.what=" +
+ getWhatToString(msg.what) + " RefCount=" + mApnContexts.size());
+ }
+ retVal = NOT_HANDLED;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcActivatingState mActivatingState = new DcActivatingState();
+
+ /**
+ * The state machine is connected, expecting an EVENT_DISCONNECT.
+ */
+ private class DcActiveState extends State {
+ @Override public void enter() {
+ if (DBG) log("DcActiveState: enter dc=" + DataConnection.this);
+
+ if (mRetryManager.getRetryCount() != 0) {
+ log("DcActiveState: connected after retrying call notifyAllOfConnected");
+ mRetryManager.setRetryCount(0);
+ }
+ // If we were retrying there maybe more than one, otherwise they'll only be one.
+ notifyAllOfConnected(Phone.REASON_CONNECTED);
+
+ // If the EVENT_CONNECT set the current max retry restore it here
+ // if it didn't then this is effectively a NOP.
+ mRetryManager.restoreCurMaxRetryCount();
+ mDcController.addActiveDcByCid(DataConnection.this);
+ }
+
+ @Override
+ public void exit() {
+ if (DBG) log("DcActiveState: exit dc=" + this);
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case EVENT_CONNECT: {
+ ConnectionParams cp = (ConnectionParams) msg.obj;
+ if (mApnContexts.contains(cp.mApnContext)) {
+ log("DcActiveState ERROR already added apnContext=" + cp.mApnContext
+ + " to this DC=" + this);
+ } else {
+ mApnContexts.add(cp.mApnContext);
+ if (DBG) {
+ log("DcActiveState msg.what=EVENT_CONNECT RefCount="
+ + mApnContexts.size());
+ }
+ }
+ notifyConnectCompleted(cp, DcFailCause.NONE, false);
+ retVal = HANDLED;
+ break;
+ }
+ case EVENT_DISCONNECT: {
+ DisconnectParams dp = (DisconnectParams) msg.obj;
+ if (mApnContexts.contains(dp.mApnContext)) {
+ if (DBG) {
+ log("DcActiveState msg.what=EVENT_DISCONNECT RefCount="
+ + mApnContexts.size());
+ }
+
+ if (mApnContexts.size() == 1) {
+ mApnContexts.clear();
+ mDisconnectParams = dp;
+ mConnectionParams = null;
+ dp.mTag = mTag;
+ tearDownData(dp);
+ transitionTo(mDisconnectingState);
+ } else {
+ mApnContexts.remove(dp.mApnContext);
+ notifyDisconnectCompleted(dp, false);
+ }
+ } else {
+ log("DcActiveState ERROR no such apnContext=" + dp.mApnContext
+ + " in this DC=" + this);
+ notifyDisconnectCompleted(dp, false);
+ }
+ retVal = HANDLED;
+ break;
+ }
+ case EVENT_DISCONNECT_ALL: {
+ if (DBG) {
+ log("DcActiveState msg.what=EVENT_DISCONNECT_ALL RefCount="
+ + mApnContexts.size() + " clearing apn contexts");
+ }
+ mApnContexts.clear();
+ DisconnectParams dp = (DisconnectParams) msg.obj;
+ mDisconnectParams = dp;
+ mConnectionParams = null;
+ dp.mTag = mTag;
+ tearDownData(dp);
+ transitionTo(mDisconnectingState);
+ retVal = HANDLED;
+ break;
+ }
+ case EVENT_LOST_CONNECTION: {
+ if (mRetryManager.isRetryNeeded()) {
+ // We're going to retry
+ int delayMillis = mRetryManager.getRetryTimer();
+ if (DBG) {
+ log("DcActiveState EVENT_LOST_CONNECTION startRetryAlarm"
+ + " mTag=" + mTag + " delay=" + delayMillis + "ms");
+ }
+ mDcRetryAlarmController.startRetryAlarm(EVENT_RETRY_CONNECTION, mTag,
+ delayMillis);
+ transitionTo(mRetryingState);
+ } else {
+ mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION);
+ transitionTo(mInactiveState);
+ }
+ retVal = HANDLED;
+ break;
+ }
+ default:
+ if (VDBG) {
+ log("DcActiveState not handled msg.what=" + getWhatToString(msg.what));
+ }
+ retVal = NOT_HANDLED;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcActiveState mActiveState = new DcActiveState();
+
+ /**
+ * The state machine is disconnecting.
+ */
+ 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 = "
+ + mApnContexts.size());
+ deferMessage(msg);
+ retVal = HANDLED;
+ break;
+
+ case EVENT_DEACTIVATE_DONE:
+ if (DBG) log("DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount="
+ + mApnContexts.size());
+ AsyncResult ar = (AsyncResult) msg.obj;
+ DisconnectParams dp = (DisconnectParams) ar.userObj;
+ if (dp.mTag == mTag) {
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams((DisconnectParams) ar.userObj);
+ transitionTo(mInactiveState);
+ } else {
+ if (DBG) log("DcDisconnectState stale EVENT_DEACTIVATE_DONE"
+ + " dp.tag=" + dp.mTag + " mTag=" + mTag);
+ }
+ retVal = HANDLED;
+ break;
+
+ default:
+ if (VDBG) {
+ log("DcDisconnectingState not handled msg.what="
+ + getWhatToString(msg.what));
+ }
+ retVal = NOT_HANDLED;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();
+
+ /**
+ * The state machine is disconnecting after an creating a connection.
+ */
+ private class DcDisconnectionErrorCreatingConnection extends State {
+ @Override
+ public boolean processMessage(Message msg) {
+ boolean retVal;
+
+ switch (msg.what) {
+ case EVENT_DEACTIVATE_DONE:
+ AsyncResult ar = (AsyncResult) msg.obj;
+ ConnectionParams cp = (ConnectionParams) ar.userObj;
+ if (cp.mTag == mTag) {
+ if (DBG) {
+ log("DcDisconnectionErrorCreatingConnection" +
+ " msg.what=EVENT_DEACTIVATE_DONE");
+ }
+
+ // Transition to inactive but send notifications after
+ // we've entered the mInactive state.
+ mInactiveState.setEnterNotificationParams(cp,
+ DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER);
+ transitionTo(mInactiveState);
+ } else {
+ if (DBG) {
+ log("DcDisconnectionErrorCreatingConnection stale EVENT_DEACTIVATE_DONE"
+ + " dp.tag=" + cp.mTag + ", mTag=" + mTag);
+ }
+ }
+ retVal = HANDLED;
+ break;
+
+ default:
+ if (VDBG) {
+ log("DcDisconnectionErrorCreatingConnection not handled msg.what="
+ + getWhatToString(msg.what));
+ }
+ retVal = NOT_HANDLED;
+ break;
+ }
+ return retVal;
+ }
+ }
+ private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection =
+ new DcDisconnectionErrorCreatingConnection();
+
+ // ******* "public" interface
+
+ /**
+ * Used for testing purposes.
+ */
+ /* package */ void tearDownNow() {
+ if (DBG) log("tearDownNow()");
+ sendMessage(obtainMessage(EVENT_TEAR_DOWN_NOW));
+ }
+
+ /**
+ * @return the string for msg.what as our info.
+ */
+ @Override
+ protected String getWhatToString(int what) {
+ return cmdToString(what);
+ }
+
+ private static String msgToString(Message msg) {
+ String retVal;
+ if (msg == null) {
+ retVal = "null";
+ } else {
+ StringBuilder b = new StringBuilder();
+
+ b.append("{what=");
+ b.append(cmdToString(msg.what));
+
+ b.append(" when=");
+ TimeUtils.formatDuration(msg.getWhen() - SystemClock.uptimeMillis(), b);
+
+ if (msg.arg1 != 0) {
+ b.append(" arg1=");
+ b.append(msg.arg1);
+ }
+
+ if (msg.arg2 != 0) {
+ b.append(" arg2=");
+ b.append(msg.arg2);
+ }
+
+ if (msg.obj != null) {
+ b.append(" obj=");
+ b.append(msg.obj);
+ }
+
+ b.append(" target=");
+ b.append(msg.getTarget());
+
+ b.append(" replyTo=");
+ b.append(msg.replyTo);
+
+ b.append("}");
+
+ retVal = b.toString();
+ }
+ return retVal;
+ }
+
+ static void slog(String s) {
+ Rlog.d("DC", s);
+ }
+
+ /**
+ * Log with debug
+ *
+ * @param s is string log
+ */
+ @Override
+ protected void log(String s) {
+ Rlog.d(getName(), s);
+ }
+
+ /**
+ * Log with debug attribute
+ *
+ * @param s is string log
+ */
+ @Override
+ protected void logd(String s) {
+ Rlog.d(getName(), s);
+ }
+
+ /**
+ * Log with verbose attribute
+ *
+ * @param s is string log
+ */
+ @Override
+ protected void logv(String s) {
+ Rlog.v(getName(), s);
+ }
+
+ /**
+ * Log with info attribute
+ *
+ * @param s is string log
+ */
+ @Override
+ protected void logi(String s) {
+ Rlog.i(getName(), s);
+ }
+
+ /**
+ * Log with warning attribute
+ *
+ * @param s is string log
+ */
+ @Override
+ protected void logw(String s) {
+ Rlog.w(getName(), s);
+ }
+
+ /**
+ * Log with error attribute
+ *
+ * @param s is string log
+ */
+ @Override
+ protected void loge(String s) {
+ Rlog.e(getName(), s);
+ }
+
+ /**
+ * Log with error attribute
+ *
+ * @param s is string log
+ * @param e is a Throwable which logs additional information.
+ */
+ @Override
+ protected void loge(String s, Throwable e) {
+ Rlog.e(getName(), s, e);
+ }
+
+ /** Doesn't print mApnList of ApnContext's which would be recursive */
+ public String toStringSimple() {
+ return getName() + ": State=" + getCurrentState().getName()
+ + " mApnSetting=" + mApnSetting + " RefCount=" + mApnContexts.size()
+ + " mCid=" + mCid + " mCreateTime=" + mCreateTime
+ + " mLastastFailTime=" + mLastFailTime
+ + " mLastFailCause=" + mLastFailCause
+ + " mTag=" + mTag
+ + " mRetryManager=" + mRetryManager
+ + " mLinkProperties=" + mLinkProperties
+ + " mLinkCapabilities=" + mLinkCapabilities;
+ }
+
+ @Override
+ public String toString() {
+ return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}";
+ }
+
+ /**
+ * Dump the current state.
+ *
+ * @param fd
+ * @param pw
+ * @param args
+ */
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("DataConnection extends:");
+ pw.print("DataConnection ");
super.dump(fd, pw, args);
- pw.println(" mProfileId=" + mProfileId);
+ pw.println(" mApnContexts.size=" + mApnContexts.size());
+ pw.println(" mApnContexts=" + mApnContexts);
+ pw.flush();
+ pw.println(" mDataConnectionTracker=" + mDct);
+ pw.println(" mApnSetting=" + mApnSetting);
+ pw.println(" mTag=" + mTag);
+ pw.println(" mCid=" + mCid);
+ pw.println(" mRetryManager=" + mRetryManager);
+ pw.println(" mConnectionParams=" + mConnectionParams);
+ pw.println(" mDisconnectParams=" + mDisconnectParams);
+ pw.println(" mDcFailCause=" + mDcFailCause);
+ pw.flush();
+ pw.println(" mPhone=" + mPhone);
+ pw.flush();
+ pw.println(" mLinkProperties=" + mLinkProperties);
+ pw.flush();
+ pw.println(" mLinkCapabilities=" + mLinkCapabilities);
+ pw.println(" mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime));
+ pw.println(" mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime));
+ pw.println(" mLastFailCause=" + mLastFailCause);
+ pw.flush();
+ pw.println(" mUserData=" + mUserData);
+ pw.println(" mInstanceNumber=" + mInstanceNumber);
+ pw.println(" mAc=" + mAc);
+ pw.println(" mDcRetryAlarmController=" + mDcRetryAlarmController);
+ pw.flush();
}
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnectionAc.java b/src/java/com/android/internal/telephony/dataconnection/DataConnectionAc.java
index 245223b..7b1e596 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnectionAc.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnectionAc.java
@@ -16,20 +16,16 @@
package com.android.internal.telephony.dataconnection;
-import com.android.internal.telephony.DataCallState;
-import com.android.internal.telephony.dataconnection.DataConnectionBase.UpdateLinkPropertyResult;
+import com.android.internal.telephony.dataconnection.DataConnection.ConnectionParams;
+import com.android.internal.telephony.dataconnection.DataConnection.DisconnectParams;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
-import android.app.PendingIntent;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.net.ProxyProperties;
import android.os.Message;
-import java.util.ArrayList;
-import java.util.Collection;
-
/**
* AsyncChannel to a DataConnection
*/
@@ -37,7 +33,8 @@
private static final boolean DBG = false;
private String mLogTag;
- public DataConnectionBase dataConnection;
+ private DataConnection mDc;
+ private long mDcThreadId;
public static final int BASE = Protocol.BASE_DATA_CONNECTION_AC;
@@ -59,25 +56,10 @@
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 + 12;
+ public static final int RSP_RESET = 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;
-
- public static final int REQ_GET_APNCONTEXT_LIST = BASE + 18;
- public static final int RSP_GET_APNCONTEXT_LIST = BASE + 19;
-
- public static final int REQ_SET_RECONNECT_INTENT = BASE + 20;
- public static final int RSP_SET_RECONNECT_INTENT = BASE + 21;
-
- public static final int REQ_GET_RECONNECT_INTENT = BASE + 22;
- public static final int RSP_GET_RECONNECT_INTENT = BASE + 23;
-
- private static final int CMD_TO_STRING_COUNT = RSP_GET_RECONNECT_INTENT - BASE + 1;
+ private static final int CMD_TO_STRING_COUNT = RSP_RESET - BASE + 1;
private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
static {
sCmdToString[REQ_IS_INACTIVE - BASE] = "REQ_IS_INACTIVE";
@@ -94,21 +76,11 @@
"RSP_SET_LINK_PROPERTIES_HTTP_PROXY";
sCmdToString[REQ_GET_LINK_CAPABILITIES - BASE] = "REQ_GET_LINK_CAPABILITIES";
sCmdToString[RSP_GET_LINK_CAPABILITIES - BASE] = "RSP_GET_LINK_CAPABILITIES";
- sCmdToString[REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE - BASE] =
- "REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE";
- sCmdToString[RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE - BASE] =
- "RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE";
sCmdToString[REQ_RESET - BASE] = "REQ_RESET";
sCmdToString[RSP_RESET - BASE] = "RSP_RESET";
- sCmdToString[REQ_GET_REFCOUNT - BASE] = "REQ_GET_REFCOUNT";
- sCmdToString[RSP_GET_REFCOUNT - BASE] = "RSP_GET_REFCOUNT";
- sCmdToString[REQ_GET_APNCONTEXT_LIST - BASE] = "REQ_GET_APNCONTEXT_LIST";
- sCmdToString[RSP_GET_APNCONTEXT_LIST - BASE] = "RSP_GET_APNCONTEXT_LIST";
- sCmdToString[REQ_SET_RECONNECT_INTENT - BASE] = "REQ_SET_RECONNECT_INTENT";
- sCmdToString[RSP_SET_RECONNECT_INTENT - BASE] = "RSP_SET_RECONNECT_INTENT";
- sCmdToString[REQ_GET_RECONNECT_INTENT - BASE] = "REQ_GET_RECONNECT_INTENT";
- sCmdToString[RSP_GET_RECONNECT_INTENT - BASE] = "RSP_GET_RECONNECT_INTENT";
}
+
+ // Convert cmd to string or null if unknown
protected static String cmdToString(int cmd) {
cmd -= BASE;
if ((cmd >= 0) && (cmd < sCmdToString.length)) {
@@ -138,8 +110,9 @@
}
}
- public DataConnectionAc(DataConnectionBase dc, String logTag) {
- dataConnection = dc;
+ public DataConnectionAc(DataConnection dc, String logTag) {
+ mDc = dc;
+ mDcThreadId = mDc.getHandler().getLooper().getThread().getId();
mLogTag = logTag;
}
@@ -164,16 +137,23 @@
}
/**
- * @return true if the state machine is in the inactive state.
+ * @return true if the state machine is in the inactive state
+ * and can be used for a new connection.
*/
public boolean isInactiveSync() {
- Message response = sendMessageSynchronously(REQ_IS_INACTIVE);
- if ((response != null) && (response.what == RSP_IS_INACTIVE)) {
- return rspIsInactive(response);
+ boolean value;
+ if (isCallerOnDifferentThread()) {
+ Message response = sendMessageSynchronously(REQ_IS_INACTIVE);
+ if ((response != null) && (response.what == RSP_IS_INACTIVE)) {
+ value = rspIsInactive(response);
+ } else {
+ log("rspIsInactive error response=" + response);
+ value = false;
+ }
} else {
- log("rspIsInactive error response=" + response);
- return false;
+ value = mDc.getIsInactive();
}
+ return value;
}
/**
@@ -201,47 +181,19 @@
* @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);
+ int value;
+ if (isCallerOnDifferentThread()) {
+ Message response = sendMessageSynchronously(REQ_GET_CID);
+ if ((response != null) && (response.what == RSP_GET_CID)) {
+ value = rspCid(response);
+ } else {
+ log("rspCid error response=" + response);
+ value = -1;
+ }
} else {
- log("rspCid error response=" + response);
- return -1;
+ value = mDc.getCid();
}
- }
-
- /**
- * 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;
- }
+ return value;
}
/**
@@ -271,13 +223,19 @@
* @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);
+ ApnSetting value;
+ if (isCallerOnDifferentThread()) {
+ Message response = sendMessageSynchronously(REQ_GET_APNSETTING);
+ if ((response != null) && (response.what == RSP_GET_APNSETTING)) {
+ value = rspApnSetting(response);
+ } else {
+ log("getApnSetting error response=" + response);
+ value = null;
+ }
} else {
- log("getApnSetting error response=" + response);
- return null;
+ value = mDc.getApnSetting();
}
+ return value;
}
/**
@@ -307,13 +265,19 @@
* @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);
+ LinkProperties value;
+ if (isCallerOnDifferentThread()) {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_PROPERTIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_PROPERTIES)) {
+ value = rspLinkProperties(response);
+ } else {
+ log("getLinkProperties error response=" + response);
+ value = null;
+ }
} else {
- log("getLinkProperties error response=" + response);
- return null;
+ value = mDc.getCopyLinkProperties();
}
+ return value;
}
/**
@@ -329,44 +293,16 @@
* 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");
+ if (isCallerOnDifferentThread()) {
+ 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);
+ }
} 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 UpdateLinkPropertyResult rspUpdateLinkPropertiesDataCallState(Message response) {
- UpdateLinkPropertyResult retVal = (UpdateLinkPropertyResult)response.obj;
- if (DBG) log("rspUpdateLinkPropertiesState: retVal=" + retVal);
- return retVal;
- }
-
- /**
- * Update link properties in the data connection
- *
- * @return the removed and added addresses.
- */
- public UpdateLinkPropertyResult 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 new UpdateLinkPropertyResult(new LinkProperties());
+ mDc.setLinkPropertiesHttpProxy(proxy);
}
}
@@ -397,13 +333,18 @@
* @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);
+ LinkCapabilities value;
+ if (isCallerOnDifferentThread()) {
+ Message response = sendMessageSynchronously(REQ_GET_LINK_CAPABILITIES);
+ if ((response != null) && (response.what == RSP_GET_LINK_CAPABILITIES)) {
+ value = rspLinkCapabilities(response);
+ } else {
+ value = null;
+ }
} else {
- log("getLinkCapabilities error response=" + response);
- return null;
+ value = mDc.getCopyLinkCapabilities();
}
+ return value;
}
/**
@@ -416,118 +357,73 @@
}
/**
- * Reset the connection and wait for it to complete.
+ * 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 apnContext is the Access Point Name to bring up a connection to
+ * @param initialMaxRetry the number of retires for initial bringup.
+ * @param profileId for the conneciton
+ * @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 resetSync() {
- Message response = sendMessageSynchronously(REQ_RESET);
- if ((response != null) && (response.what == RSP_RESET)) {
- if (DBG) log("restSync ok");
- } else {
- log("restSync error response=" + response);
+ public void bringUp(ApnContext apnContext, int initialMaxRetry, int profileId,
+ Message onCompletedMsg) {
+ if (DBG) {
+ log("bringUp: apnContext=" + apnContext + " initialMaxRetry=" + initialMaxRetry
+ + " onCompletedMsg=" + onCompletedMsg);
}
+ sendMessage(DataConnection.EVENT_CONNECT,
+ new ConnectionParams(apnContext, initialMaxRetry, profileId, onCompletedMsg));
}
/**
- * Request the ApnContext List associated with DC.
- * Response RSP_GET_APNCONTEXT_LIST when complete.
- */
- public void reqGetApnList(ApnContext apnContext) {
- Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
- if (DBG) log("reqGetApnList");
- }
-
- /**
- * Retrieve Collection of ApnContext from the response message.
+ * Tear down the connection through the apn on the network.
*
- * @param response sent from DC in response to REQ_GET_APNCONTEXT_LIST.
- * @return Collection of ApnContext
+ * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
+ * With AsyncResult.userObj set to the original msg.obj.
*/
- public Collection<ApnContext> rspApnList(Message response) {
- Collection<ApnContext> retVal = (Collection<ApnContext>)response.obj;
- if (retVal == null) retVal = new ArrayList<ApnContext>();
- return retVal;
- }
-
- /**
- * Retrieve collection of ApnContext currently associated with
- * the DataConnectionA synchronously.
- *
- * @return Collection of ApnContext
- */
- public Collection<ApnContext> getApnListSync() {
- Message response = sendMessageSynchronously(REQ_GET_APNCONTEXT_LIST);
- if ((response != null) && (response.what == RSP_GET_APNCONTEXT_LIST)) {
- if (DBG) log("getApnList ok");
- return rspApnList(response);
- } else {
- log("getApnList error response=" + response);
- // return dummy list with no entry
- return new ArrayList<ApnContext>();
+ public void tearDown(ApnContext apnContext, String reason, Message onCompletedMsg) {
+ if (DBG) {
+ log("tearDown: apnContext=" + apnContext
+ + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg);
}
+ sendMessage(DataConnection.EVENT_DISCONNECT,
+ new DisconnectParams(apnContext, reason, onCompletedMsg));
}
/**
- * Request to set Pending ReconnectIntent to DC.
- * Response RSP_SET_RECONNECT_INTENT when complete.
- */
- public void reqSetReconnectIntent(PendingIntent intent) {
- Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
- if (DBG) log("reqSetReconnectIntent");
- }
-
- /**
- * Set pending reconnect intent to DC synchronously.
+ * Tear down the connection through the apn on the network. Ignores refcount and
+ * and always tears down.
*
- * @param intent to set.
+ * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
+ * With AsyncResult.userObj set to the original msg.obj.
*/
- public void setReconnectIntentSync(PendingIntent intent) {
- Message response = sendMessageSynchronously(REQ_SET_RECONNECT_INTENT, intent);
- if ((response != null) && (response.what == RSP_SET_RECONNECT_INTENT)) {
- if (DBG) log("setReconnectIntent ok");
- } else {
- log("setReconnectIntent error response=" + response);
- }
+ public void tearDownAll(String reason, Message onCompletedMsg) {
+ if (DBG) log("tearDownAll: reason=" + reason + " onCompletedMsg=" + onCompletedMsg);
+ sendMessage(DataConnection.EVENT_DISCONNECT_ALL,
+ new DisconnectParams(null, reason, onCompletedMsg));
}
/**
- * Request to get Pending ReconnectIntent to DC.
- * Response RSP_GET_RECONNECT_INTENT when complete.
+ * @return connection id
*/
- public void reqGetReconnectIntent() {
- Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
- if (DBG) log("reqGetReconnectIntent");
- }
-
- /**
- * Retrieve reconnect intent from response message from DC.
- *
- * @param response which contains the reconnect intent.
- * @return PendingIntent from the response.
- */
- public PendingIntent rspReconnectIntent(Message response) {
- PendingIntent retVal = (PendingIntent) response.obj;
- return retVal;
- }
-
- /**
- * Retrieve reconnect intent currently set in DC synchronously.
- *
- * @return PendingIntent reconnect intent current ly set in DC
- */
- public PendingIntent getReconnectIntentSync() {
- Message response = sendMessageSynchronously(REQ_GET_RECONNECT_INTENT);
- if ((response != null) && (response.what == RSP_GET_RECONNECT_INTENT)) {
- if (DBG) log("getReconnectIntent ok");
- return rspReconnectIntent(response);
- } else {
- log("getReconnectIntent error response=" + response);
- return null;
- }
+ public int getDataConnectionIdSync() {
+ // Safe because this is owned by the caller.
+ return mDc.getDataConnectionId();
}
@Override
public String toString() {
- return dataConnection.getName();
+ return mDc.getName();
+ }
+
+ private boolean isCallerOnDifferentThread() {
+ long curThreadId = Thread.currentThread().getId();
+ boolean value = mDcThreadId != curThreadId;
+ if (DBG) log("isCallerOnDifferentThread: " + value);
+ return value;
}
private void log(String s) {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnectionBase.java b/src/java/com/android/internal/telephony/dataconnection/DataConnectionBase.java
deleted file mode 100644
index f0d1e09..0000000
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnectionBase.java
+++ /dev/null
@@ -1,1520 +0,0 @@
-/*
- * 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.dataconnection;
-
-
-import com.android.internal.telephony.CommandException;
-import com.android.internal.telephony.DataCallState;
-import com.android.internal.telephony.DctConstants;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneBase;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.RetryManager;
-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.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.LinkCapabilities;
-import android.net.LinkProperties;
-import android.net.ProxyProperties;
-import android.os.AsyncResult;
-import android.os.Message;
-import android.os.SystemProperties;
-import android.text.TextUtils;
-import android.telephony.Rlog;
-import android.util.TimeUtils;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * {@hide}
- *
- * DataConnectionBase StateMachine.
- *
- * This is an abstract base class for representing a single data connection.
- * Instances of this class such represent a connection via the cellular network.
- * There may be multiple data connections and all of them are managed by the
- * <code>DataConnectionTracker</code>.
- *
- * Instances are asynchronous state machines and have two primary entry points
- * <code>connect()</code> and <code>disconnect</code>. The message a parameter will be returned
- * hen the operation completes. The <code>msg.obj</code> will contain an AsyncResult
- * object and <code>AsyncResult.userObj</code> is the original <code>msg.obj</code>. if successful
- * with the <code>AsyncResult.result == null</code> and <code>AsyncResult.exception == null</code>.
- * If an error <code>AsyncResult.result = FailCause</code> and
- * <code>AsyncResult.exception = new Exception()</code>.
- *
- * The other public methods are provided for debugging.
- */
-public abstract class DataConnectionBase extends StateMachine {
- protected static final String LOG_TAG = "DCBase";
- protected static final boolean DBG = true;
- protected static final boolean VDBG = true;
- protected static final boolean DBG_FAILURE = SystemProperties.getInt("ro.debuggable", 0) == 1;
-
- protected static AtomicInteger mCount = new AtomicInteger(0);
- protected AsyncChannel mAc;
-
- protected List<ApnContext> mApnList = null;
- PendingIntent mReconnectIntent = null;
-
- private DataConnectionTrackerBase mDataConnectionTracker = null;
-
- /**
- * Used internally for saving connecting parameters.
- */
- protected static class ConnectionParams {
- ConnectionParams(ApnContext apnContext, Message onCompletedMsg) {
- mApnContext = apnContext;
- mOnCompletedMsg = onCompletedMsg;
- }
-
- int mTheTag;
- ApnContext mApnContext;
- Message mOnCompletedMsg;
- }
-
- /**
- * Used internally for saving disconnecting parameters.
- */
- protected static class DisconnectParams {
- DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) {
- mApnContext = apnContext;
- mReason = reason;
- mOnCompletedMsg = onCompletedMsg;
- }
-
- int mTheTag;
- ApnContext mApnContext;
- String mReason;
- Message mOnCompletedMsg;
- }
-
- /**
- * Returned as the reason for a connection failure as defined
- * by RIL_DataCallFailCause in ril.h and some local errors.
- */
- public enum FailCause {
- NONE(0),
-
- // This series of errors as specified by the standards
- // specified in ril.h
- OPERATOR_BARRED(0x08),
- INSUFFICIENT_RESOURCES(0x1A),
- MISSING_UNKNOWN_APN(0x1B),
- UNKNOWN_PDP_ADDRESS_TYPE(0x1C),
- USER_AUTHENTICATION(0x1D),
- ACTIVATION_REJECT_GGSN(0x1E),
- ACTIVATION_REJECT_UNSPECIFIED(0x1F),
- SERVICE_OPTION_NOT_SUPPORTED(0x20),
- SERVICE_OPTION_NOT_SUBSCRIBED(0x21),
- SERVICE_OPTION_OUT_OF_ORDER(0x22),
- NSAPI_IN_USE(0x23),
- ONLY_IPV4_ALLOWED(0x32),
- ONLY_IPV6_ALLOWED(0x33),
- ONLY_SINGLE_BEARER_ALLOWED(0x34),
- PROTOCOL_ERRORS(0x6F),
-
- // Local errors generated by Vendor RIL
- // specified in ril.h
- REGISTRATION_FAIL(-1),
- GPRS_REGISTRATION_FAIL(-2),
- SIGNAL_LOST(-3),
- PREF_RADIO_TECH_CHANGED(-4),
- RADIO_POWER_OFF(-5),
- TETHERED_CALL_ACTIVE(-6),
- ERROR_UNSPECIFIED(0xFFFF),
-
- // Errors generated by the Framework
- // specified here
- UNKNOWN(0x10000),
- RADIO_NOT_AVAILABLE(0x10001),
- UNACCEPTABLE_NETWORK_PARAMETER(0x10002),
- CONNECTION_TO_DATACONNECTIONAC_BROKEN(0x10003);
-
- private final int mErrorCode;
- private static final HashMap<Integer, FailCause> sErrorCodeToFailCauseMap;
- static {
- sErrorCodeToFailCauseMap = new HashMap<Integer, FailCause>();
- for (FailCause fc : values()) {
- sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
- }
- }
-
- FailCause(int errorCode) {
- mErrorCode = errorCode;
- }
-
- public int getErrorCode() {
- return mErrorCode;
- }
-
- public boolean isPermanentFail() {
- return (this == OPERATOR_BARRED) || (this == MISSING_UNKNOWN_APN) ||
- (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
- (this == ACTIVATION_REJECT_GGSN) || (this == SERVICE_OPTION_NOT_SUPPORTED) ||
- (this == SERVICE_OPTION_NOT_SUBSCRIBED) || (this == NSAPI_IN_USE) ||
- (this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
- (this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
- (this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE);
- }
-
- public boolean isEventLoggable() {
- return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
- (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
- (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
- (this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
- (this == SERVICE_OPTION_NOT_SUPPORTED) ||
- (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
- (this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
- (this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
- (this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE) ||
- (this == UNACCEPTABLE_NETWORK_PARAMETER);
- }
-
- public static FailCause fromInt(int errorCode) {
- FailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
- if (fc == null) {
- fc = UNKNOWN;
- }
- return fc;
- }
- }
-
- /**
- * Static logging for DataConnection
- */
- private static void sDcLog(String s) {
- Rlog.d(LOG_TAG, "[DC] " + s);
- }
-
- // Debugging INTENT with are two targets, com.android.internal.telephony.DC which
- // is for all DataConnections and com.android.internal.telephony.<NameDC-X> where
- // NameDc-X is a particular DC such as GsmDC-1.
- protected static final String INTENT_BASE = DataConnectionBase.class.getPackage().getName();
- protected static String sActionFailBringUp;
- protected String mActionFailBringUp;
-
- // The FailBringUp class
- public static class FailBringUp {
- protected static final String ACTION_FAIL_BRINGUP = "action_fail_bringup";
-
- // counter with its --ei option name and default value
- public static final String COUNTER = "counter";
- public static final int DEFAULT_COUNTER = 1;
- public int counter;
-
- // failCause with its --ei option name and default value
- public static final String FAIL_CAUSE = "fail_cause";
- public static final FailCause DEFAULT_FAIL_CAUSE = FailCause.ERROR_UNSPECIFIED;
- public FailCause failCause;
-
- // suggestedRetryTime with its --ei option name and default value
- public static final String SUGGESTED_RETRY_TIME = "suggested_retry_time";
- public static final int DEFAULT_SUGGESTED_RETRY_TIME = -1;
- public int suggestedRetryTime;
-
- // Get the Extra Intent parameters
- public void getEiParameters(Intent intent, String s) {
- if (DBG) sDcLog(s + ".getEiParameters: action=" + intent.getAction());
- counter = intent.getIntExtra(FailBringUp.COUNTER,
- FailBringUp.DEFAULT_COUNTER);
- failCause = FailCause.fromInt(
- intent.getIntExtra(FailBringUp.FAIL_CAUSE,
- FailBringUp.DEFAULT_FAIL_CAUSE.getErrorCode()));
- suggestedRetryTime =
- intent.getIntExtra(FailBringUp.SUGGESTED_RETRY_TIME,
- FailBringUp.DEFAULT_SUGGESTED_RETRY_TIME);
- if (DBG) {
- sDcLog(s + ".getEiParameters: " + this);
- }
- }
-
- @Override
- public String toString() {
- return "{counter=" + counter +
- " failCause=" + failCause +
- " suggestedRetryTime=" + suggestedRetryTime + "}";
-
- }
- }
-
- // This is the static FailBringUp used to cause all DC's to "fail" a bringUp.
- // Here is an example that sets counter to 2 and cause to -3 for all instances:
- //
- // adb shell am broadcast \
- // -a com.android.internal.telephony.DC.action_fail_bringup \
- // --ei counter 2 --ei fail_cause -3
- //
- // Also you can add a suggested retry time if desired:
- // --ei suggested_retry_time 5000
- protected static FailBringUp sFailBringUp = new FailBringUp();
-
- // The static intent receiver one for all instances.
- protected static BroadcastReceiver sIntentReceiver = new BroadcastReceiver ()
- {
- @Override
- public void onReceive(Context context, Intent intent)
- {
- String action = intent.getAction();
- if (DBG) sDcLog("sIntentReceiver.onReceive: action=" + action);
- if (action.equals(sActionFailBringUp)) {
- sFailBringUp.getEiParameters(intent, "sFailBringUp");
- } else {
- if (DBG) sDcLog("onReceive: unknown action=" + action);
- }
- }
- };
-
- // This is the per instance FailBringUP used to cause one DC to "fail" a bringUp.
- // Here is an example that sets counter to 2 and cause to -3 for GsmDC-2:
- //
- // adb shell am broadcast \
- // -a com.android.internal.telephony.GsmDC-2.action_fail_bringup \
- // --ei counter 2 --ei fail_cause -3
- //
- // Also you can add a suggested retry time if desired:
- // --ei suggested_retry_time 5000
- protected FailBringUp mFailBringUp = new FailBringUp();
-
- protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
- {
- @Override
- public void onReceive(Context context, Intent intent)
- {
- String action = intent.getAction();
- if (DBG) log("mIntentReceiver.onReceive: action=" + action);
- if (DBG_FAILURE && action.equals(mActionFailBringUp)) {
- mFailBringUp.getEiParameters(intent, "mFailBringUp");
- } else {
- if (DBG) log("onReceive: unknown action=" + action);
- }
- }
- };
-
- /**
- * Do the on connect or fake it if an error
- */
- protected void doOnConnect(ConnectionParams cp) {
- // Check if we should fake an error.
- if (sFailBringUp.counter > 0) {
- DataCallState response = new DataCallState();
- response.version = mPhone.mCi.getRilVersion();
- response.status = sFailBringUp.failCause.getErrorCode();
- response.cid = 0;
- response.active = 0;
- response.type = "";
- response.ifname = "";
- response.addresses = new String[0];
- response.dnses = new String[0];
- response.gateways = new String[0];
- response.suggestedRetryTime = sFailBringUp.suggestedRetryTime;
-
- Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
- AsyncResult.forMessage(msg, response, null);
- sendMessage(msg);
- if (DBG) {
- log("doOnConnect: sFailBringUp.counter=" + sFailBringUp.counter +
- " send error response=" + response);
- }
- sFailBringUp.counter -= 1;
- return;
- }
- if (mFailBringUp.counter > 0) {
- DataCallState response = new DataCallState();
- response.version = mPhone.mCi.getRilVersion();
- response.status = mFailBringUp.failCause.getErrorCode();
- response.cid = 0;
- response.active = 0;
- response.type = "";
- response.ifname = "";
- response.addresses = new String[0];
- response.dnses = new String[0];
- response.gateways = new String[0];
- response.suggestedRetryTime = mFailBringUp.suggestedRetryTime;
-
- Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp);
- AsyncResult.forMessage(msg, response, null);
- sendMessage(msg);
- if (DBG) {
- log("doOnConnect: mFailBringUp.counter=" + mFailBringUp.counter +
- " send error response=" + response);
- }
- mFailBringUp.counter -= 1;
- return;
- }
-
- // Else do the normal onConnection
- onConnect(cp);
- }
-
- public static class CallSetupException extends Exception {
- private int mRetryOverride = -1;
-
- CallSetupException (int retryOverride) {
- mRetryOverride = retryOverride;
- }
-
- public int getRetryOverride() {
- return mRetryOverride;
- }
- }
-
- // ***** Event codes for driving the state machine
- 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;
- protected static final int EVENT_DISCONNECT_ALL = BASE + 6;
-
- private static final int CMD_TO_STRING_COUNT = EVENT_DISCONNECT_ALL - BASE + 1;
- private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
- static {
- sCmdToString[EVENT_CONNECT - BASE] = "EVENT_CONNECT";
- sCmdToString[EVENT_SETUP_DATA_CONNECTION_DONE - BASE] =
- "EVENT_SETUP_DATA_CONNECTION_DONE";
- sCmdToString[EVENT_GET_LAST_FAIL_DONE - BASE] = "EVENT_GET_LAST_FAIL_DONE";
- sCmdToString[EVENT_DEACTIVATE_DONE - BASE] = "EVENT_DEACTIVATE_DONE";
- sCmdToString[EVENT_DISCONNECT - BASE] = "EVENT_DISCONNECT";
- sCmdToString[EVENT_RIL_CONNECTED - BASE] = "EVENT_RIL_CONNECTED";
- sCmdToString[EVENT_DISCONNECT_ALL - BASE] = "EVENT_DISCONNECT_ALL";
- }
- protected static String cmdToString(int cmd) {
- cmd -= BASE;
- if ((cmd >= 0) && (cmd < sCmdToString.length)) {
- return sCmdToString[cmd];
- } else {
- return null;
- }
- }
-
- //***** Tag IDs for EventLog
- protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
-
- //***** Member Variables
- protected ApnSetting mApn;
- protected int mTag;
- protected PhoneBase mPhone;
- protected int mRilVersion = -1;
- protected int mCid;
- protected LinkProperties mLinkProperties = new LinkProperties();
- protected LinkCapabilities mCapabilities = new LinkCapabilities();
- protected long mCreateTime;
- protected long mLastFailTime;
- protected FailCause mLastFailCause;
- protected int mRetryOverride = -1;
- protected static final String NULL_IP = "0.0.0.0";
- Object mUserData;
-
- //***** Abstract methods
- @Override
- public abstract String toString();
-
- // A Non recursive toString
- public String toStringSimple() {
- return toString();
- }
-
- protected abstract void onConnect(ConnectionParams cp);
-
- protected abstract boolean isDnsOk(String[] domainNameServers);
-
- //***** Constructor
- protected DataConnectionBase(PhoneBase phone, String name, int id, RetryManager rm,
- DataConnectionTrackerBase dct) {
- super(name);
- setLogRecSize(300);
- setLogOnlyTransitions(true);
- if (DBG) log("DataConnectionBase constructor E");
- mPhone = phone;
- mDataConnectionTracker = dct;
- mId = id;
- mRetryMgr = rm;
- mCid = -1;
-
- if (DBG_FAILURE) {
- IntentFilter filter;
-
- synchronized (DataConnectionBase.class) {
- // Register the static Intent receiver once
- if (sActionFailBringUp == null) {
- sActionFailBringUp = INTENT_BASE + ".DC." +
- FailBringUp.ACTION_FAIL_BRINGUP;
-
- filter = new IntentFilter();
- filter.addAction(sActionFailBringUp);
- phone.getContext().registerReceiver(sIntentReceiver, filter, null, phone);
- log("DataConnectionBase: register sActionFailBringUp=" + sActionFailBringUp);
- }
- }
-
- // Register the per instance Intent receiver
- mActionFailBringUp = INTENT_BASE + "." + getName() + "." +
- FailBringUp.ACTION_FAIL_BRINGUP;
- filter = new IntentFilter();
- filter.addAction(mActionFailBringUp);
- phone.getContext().registerReceiver(mIntentReceiver, filter, null, phone);
- log("DataConnectionBase: register mActionFailBringUp=" + mActionFailBringUp);
- }
-
- addState(mDefaultState);
- addState(mInactiveState, mDefaultState);
- addState(mActivatingState, mDefaultState);
- addState(mActiveState, mDefaultState);
- addState(mDisconnectingState, mDefaultState);
- addState(mDisconnectingErrorCreatingConnection, mDefaultState);
- setInitialState(mInactiveState);
-
- mApnList = new ArrayList<ApnContext>();
- if (DBG) log("DataConnectionBase constructor X");
- }
-
- /**
- * Shut down this instance and its state machine.
- */
- private void shutDown() {
- if (DBG) log("shutDown");
-
- if (mAc != null) {
- mAc.disconnected();
- mAc = null;
- }
- mApnList = null;
- mReconnectIntent = null;
- mDataConnectionTracker = null;
- mApn = null;
- mPhone = null;
- mLinkProperties = null;
- mCapabilities = null;
- mLastFailCause = null;
- mUserData = null;
- }
-
- /**
- * TearDown the data connection.
- *
- * @param o will be returned in AsyncResult.userObj
- * and is either a DisconnectParams or ConnectionParams.
- */
- private void tearDownData(Object o) {
- int discReason = RILConstants.DEACTIVATE_REASON_NONE;
- if ((o != null) && (o instanceof DisconnectParams)) {
- DisconnectParams dp = (DisconnectParams)o;
- Message m = dp.mOnCompletedMsg;
- if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)) {
- discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF;
- } else if (TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) {
- discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET;
- }
- }
- if (mPhone.mCi.getRadioState().isOn()) {
- if (DBG) log("tearDownData radio is on, call deactivateDataCall");
- mPhone.mCi.deactivateDataCall(mCid, discReason, obtainMessage(EVENT_DEACTIVATE_DONE, o));
- } else {
- if (DBG) log("tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately");
- AsyncResult ar = new AsyncResult(o, null, null);
- sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, ar));
- }
- }
-
- /**
- * Send the connectionCompletedMsg.
- *
- * @param cp is the ConnectionParams
- * @param cause
- */
- private void notifyConnectCompleted(ConnectionParams cp, FailCause cause) {
- Message connectionCompletedMsg = cp.mOnCompletedMsg;
- if (connectionCompletedMsg == null) {
- return;
- }
-
- long timeStamp = System.currentTimeMillis();
- connectionCompletedMsg.arg1 = mCid;
-
- if (cause == FailCause.NONE) {
- mCreateTime = timeStamp;
- AsyncResult.forMessage(connectionCompletedMsg);
- } else {
- mLastFailCause = cause;
- mLastFailTime = timeStamp;
- AsyncResult.forMessage(connectionCompletedMsg, cause,
- new CallSetupException(mRetryOverride));
- }
- if (DBG) log("notifyConnectionCompleted at " + timeStamp + " cause=" + cause);
-
- connectionCompletedMsg.sendToTarget();
- }
-
- /**
- * Send ar.userObj if its a message, which is should be back to originator.
- *
- * @param dp is the DisconnectParams.
- */
- private void notifyDisconnectCompleted(DisconnectParams dp, boolean sendAll) {
- if (VDBG) log("NotifyDisconnectCompleted");
-
- ApnContext alreadySent = null;
- String reason = null;
-
- if (dp.mOnCompletedMsg != null) {
- // Get ApnContext, but only valid on GSM devices this is a string on CDMA devices.
- Message msg = dp.mOnCompletedMsg;
- if (msg.obj instanceof ApnContext) {
- alreadySent = (ApnContext)msg.obj;
- }
- reason = dp.mReason;
- 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 (sendAll) {
- for (ApnContext a : mApnList) {
- if (a == alreadySent) continue;
- if (reason != null) a.setReason(reason);
- Message msg = mDataConnectionTracker.obtainMessage(
- DctConstants.EVENT_DISCONNECT_DONE, a);
- AsyncResult.forMessage(msg);
- msg.sendToTarget();
- }
- }
-
- if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp);
- }
-
- protected int getRilRadioTechnology() {
- int rilRadioTechnology;
- if (mApn.bearer > 0) {
- rilRadioTechnology = mApn.bearer + 2;
- } else {
- rilRadioTechnology = mPhone.getServiceState().getRilDataRadioTechnology() + 2;
- }
- return rilRadioTechnology;
- }
-
- /*
- * **************************************************************************
- * Begin Members and methods owned by DataConnectionTracker but stored
- * in a DataConnectionBase because there is one per connection.
- * **************************************************************************
- */
-
- /*
- * The id is owned by DataConnectionTracker.
- */
- private int mId;
-
- /**
- * Get the DataConnection ID
- */
- public int getDataConnectionId() {
- return mId;
- }
-
- /*
- * 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();
- }
-
- /**
- * set retry manager retryCount
- */
- public void setRetryCount(int retryCount) {
- if (DBG) log("setRetryCount: " + retryCount);
- mRetryMgr.setRetryCount(retryCount);
- }
-
- /**
- * @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");
-
- mCreateTime = -1;
- mLastFailTime = -1;
- mLastFailCause = FailCause.NONE;
- mRetryOverride = -1;
- mCid = -1;
-
- mLinkProperties = new LinkProperties();
- mApnList.clear();
- mApn = null;
- }
-
- /**
- * Process setup completion.
- *
- * @param ar is the result
- * @return SetupResult.
- */
- private DataCallState.SetupResult onSetupConnectionCompleted(AsyncResult ar) {
- DataCallState response = (DataCallState) ar.result;
- ConnectionParams cp = (ConnectionParams) ar.userObj;
- DataCallState.SetupResult result;
-
- if (ar.exception != null) {
- if (DBG) {
- log("onSetupConnectionCompleted failed, ar.exception=" + ar.exception +
- " response=" + response);
- }
-
- if (ar.exception instanceof CommandException
- && ((CommandException) (ar.exception)).getCommandError()
- == CommandException.Error.RADIO_NOT_AVAILABLE) {
- result = DataCallState.SetupResult.ERR_BadCommand;
- result.mFailCause = FailCause.RADIO_NOT_AVAILABLE;
- } else if ((response == null) || (response.version < 4)) {
- result = DataCallState.SetupResult.ERR_GetLastErrorFromRil;
- } else {
- result = DataCallState.SetupResult.ERR_RilError;
- result.mFailCause = FailCause.fromInt(response.status);
- }
- } else if (cp.mTheTag != mTag) {
- if (DBG) {
- log("BUG: onSetupConnectionCompleted is stale cp.tag=" + cp.mTheTag + ", mtag=" + mTag);
- }
- result = DataCallState.SetupResult.ERR_Stale;
- } else if (response.status != 0) {
- result = DataCallState.SetupResult.ERR_RilError;
- result.mFailCause = FailCause.fromInt(response.status);
- } else {
- if (DBG) log("onSetupConnectionCompleted received DataCallState: " + response);
- mCid = response.cid;
- result = updateLinkProperty(response).setupResult;
- }
-
- return result;
- }
-
- private int getSuggestedRetryTime(AsyncResult ar) {
- int retry = -1;
- if (ar.exception == null) {
- DataCallState response = (DataCallState) ar.result;
- retry = response.suggestedRetryTime;
- }
- return retry;
- }
-
- 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);
- }
-
- public static class UpdateLinkPropertyResult {
- public DataCallState.SetupResult setupResult = DataCallState.SetupResult.SUCCESS;
- public LinkProperties oldLp;
- public LinkProperties newLp;
- public UpdateLinkPropertyResult(LinkProperties curLp) {
- oldLp = curLp;
- newLp = curLp;
- }
- }
-
- private UpdateLinkPropertyResult updateLinkProperty(DataCallState newState) {
- UpdateLinkPropertyResult result = new UpdateLinkPropertyResult(mLinkProperties);
-
- if (newState == null) return result;
-
- DataCallState.SetupResult setupResult;
- result.newLp = new LinkProperties();
-
- // set link properties based on data call response
- result.setupResult = setLinkProperties(newState, result.newLp);
- if (result.setupResult != DataCallState.SetupResult.SUCCESS) {
- if (DBG) log("updateLinkProperty failed : " + result.setupResult);
- return result;
- }
- // copy HTTP proxy as it is not part DataCallState.
- result.newLp.setHttpProxy(mLinkProperties.getHttpProxy());
-
- if (DBG && (! result.oldLp.equals(result.newLp))) {
- log("updateLinkProperty old LP=" + result.oldLp);
- log("updateLinkProperty new LP=" + result.newLp);
- }
- mLinkProperties = result.newLp;
-
- return result;
- }
-
- /**
- * The parent state for all other states.
- */
- private class DcDefaultState extends State {
- @Override
- public void enter() {
- mPhone.mCi.registerForRilConnected(getHandler(), EVENT_RIL_CONNECTED, null);
- }
- @Override
- public void exit() {
- mPhone.mCi.unregisterForRilConnected(getHandler());
- shutDown();
- }
- @Override
- public boolean processMessage(Message msg) {
- boolean retVal = HANDLED;
- AsyncResult ar;
-
- if (VDBG) {
- log("DcDefault msg=0x" + Integer.toHexString(msg.what)
- + " RefCount=" + mApnList.size());
- }
- switch (msg.what) {
- 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_DISCONNECTED: {
- if (VDBG) log("CMD_CHANNEL_DISCONNECTED");
- quit();
- 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=" + mCid);
- mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_CID, mCid);
- 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;
- UpdateLinkPropertyResult result =
- updateLinkProperty(newState);
- if (VDBG) {
- log("REQ_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE result="
- + result + " newState=" + newState);
- }
- mAc.replyToMessage(msg,
- DataConnectionAc.RSP_UPDATE_LINK_PROPERTIES_DATA_CALL_STATE,
- result);
- 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");
- mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
- transitionTo(mInactiveState);
- break;
- case DataConnectionAc.REQ_GET_REFCOUNT: {
- if (VDBG) log("REQ_GET_REFCOUNT RefCount=" + mApnList.size());
- mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_REFCOUNT, mApnList.size());
- break;
- }
- case DataConnectionAc.REQ_GET_APNCONTEXT_LIST: {
- if (VDBG) log("REQ_GET_APNCONTEXT_LIST num in list=" + mApnList.size());
- mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_APNCONTEXT_LIST,
- new ArrayList<ApnContext>(mApnList));
- break;
- }
- case DataConnectionAc.REQ_SET_RECONNECT_INTENT: {
- PendingIntent intent = (PendingIntent) msg.obj;
- if (VDBG) log("REQ_SET_RECONNECT_INTENT");
- mReconnectIntent = intent;
- mAc.replyToMessage(msg, DataConnectionAc.RSP_SET_RECONNECT_INTENT);
- break;
- }
- case DataConnectionAc.REQ_GET_RECONNECT_INTENT: {
- if (VDBG) log("REQ_GET_RECONNECT_INTENT");
- mAc.replyToMessage(msg, DataConnectionAc.RSP_GET_RECONNECT_INTENT,
- mReconnectIntent);
- break;
- }
- case EVENT_CONNECT:
- if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected");
- ConnectionParams cp = (ConnectionParams) msg.obj;
- notifyConnectCompleted(cp, FailCause.UNKNOWN);
- break;
-
- case EVENT_DISCONNECT:
- if (DBG) {
- log("DcDefaultState deferring msg.what=EVENT_DISCONNECT RefCount="
- + mApnList.size());
- }
- deferMessage(msg);
- break;
-
- case EVENT_DISCONNECT_ALL:
- if (DBG) {
- log("DcDefaultState deferring msg.what=EVENT_DISCONNECT_ALL RefCount="
- + mApnList.size());
- }
- deferMessage(msg);
- 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=0x" +
- Integer.toHexString(msg.what));
- }
- break;
- }
-
- return retVal;
- }
- }
- private DcDefaultState mDefaultState = new DcDefaultState();
-
- /**
- * The state machine is inactive and expects a EVENT_CONNECT.
- */
- private class DcInactiveState extends State {
- private ConnectionParams mConnectionParams = null;
- private FailCause mFailCause = null;
- private DisconnectParams mDisconnectParams = null;
-
- public void setEnterNotificationParams(ConnectionParams cp, FailCause cause,
- int retryOverride) {
- if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
- mConnectionParams = cp;
- mFailCause = cause;
- mRetryOverride = retryOverride;
- }
-
- public void setEnterNotificationParams(DisconnectParams dp) {
- if (VDBG) log("DcInactiveState: setEnterNoticationParams dp");
- mDisconnectParams = dp;
- }
-
- @Override
- public void enter() {
- mTag += 1;
-
- /**
- * Now that we've transitioned to Inactive state we
- * can send notifications. Previously we sent the
- * notifications in the processMessage handler but
- * that caused a race condition because the synchronous
- * call to isInactive.
- */
- if ((mConnectionParams != null) && (mFailCause != null)) {
- if (VDBG) log("DcInactiveState: enter notifyConnectCompleted");
- notifyConnectCompleted(mConnectionParams, mFailCause);
- }
- if (mDisconnectParams != null) {
- if (VDBG) log("DcInactiveState: enter notifyDisconnectCompleted");
- notifyDisconnectCompleted(mDisconnectParams, true);
- }
- clearSettings();
- }
-
- @Override
- public void exit() {
- // clear notifications
- mConnectionParams = null;
- mFailCause = null;
- mDisconnectParams = null;
- }
-
- @Override
- public boolean processMessage(Message msg) {
- boolean retVal;
-
- switch (msg.what) {
- case DataConnectionAc.REQ_RESET:
- if (DBG) {
- log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset");
- }
- mAc.replyToMessage(msg, DataConnectionAc.RSP_RESET);
- retVal = HANDLED;
- break;
-
- case EVENT_CONNECT:
- ConnectionParams cp = (ConnectionParams) msg.obj;
- mApnList.add(cp.mApnContext);
- cp.mTheTag = mTag;
- if (DBG) {
- log("DcInactiveState msg.what=EVENT_CONNECT " + "RefCount="
- + mApnList.size());
- }
- doOnConnect(cp);
- transitionTo(mActivatingState);
- retVal = HANDLED;
- break;
-
- case EVENT_DISCONNECT:
- if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT");
- notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
- retVal = HANDLED;
- break;
-
- case EVENT_DISCONNECT_ALL:
- if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT_ALL");
- notifyDisconnectCompleted((DisconnectParams)msg.obj, false);
- retVal = HANDLED;
- break;
-
- default:
- if (VDBG) {
- log("DcInactiveState nothandled msg.what=0x" +
- Integer.toHexString(msg.what));
- }
- retVal = NOT_HANDLED;
- break;
- }
- return retVal;
- }
- }
- private DcInactiveState mInactiveState = new DcInactiveState();
-
- /**
- * The state machine is activating a connection.
- */
- private class DcActivatingState extends State {
- @Override
- public boolean processMessage(Message msg) {
- boolean retVal;
- AsyncResult ar;
- ConnectionParams cp;
-
- switch (msg.what) {
- case EVENT_CONNECT:
- if (DBG) {
- log("DcActivatingState deferring msg.what=EVENT_CONNECT RefCount="
- + mApnList.size());
- }
- deferMessage(msg);
- retVal = HANDLED;
- break;
-
- case EVENT_SETUP_DATA_CONNECTION_DONE:
- if (DBG) {
- log("DcActivatingState msg.what=EVENT_SETUP_DATA_CONNECTION_DONE"
- + " RefCount=" + mApnList.size());
- }
-
- ar = (AsyncResult) msg.obj;
- cp = (ConnectionParams) ar.userObj;
-
- DataCallState.SetupResult result = onSetupConnectionCompleted(ar);
- if (DBG) log("DcActivatingState onSetupConnectionCompleted result=" + result);
- switch (result) {
- case SUCCESS:
- // All is well
- mActiveState.setEnterNotificationParams(cp, FailCause.NONE);
- transitionTo(mActiveState);
- break;
- case ERR_BadCommand:
- // Vendor ril rejected the command and didn't connect.
- // Transition to inactive but send notifications after
- // we've entered the mInactive state.
- mInactiveState.setEnterNotificationParams(cp, result.mFailCause, -1);
- transitionTo(mInactiveState);
- break;
- case ERR_UnacceptableParameter:
- // The addresses given from the RIL are bad
- tearDownData(cp);
- transitionTo(mDisconnectingErrorCreatingConnection);
- break;
- case ERR_GetLastErrorFromRil:
- // Request failed and this is an old RIL
- mPhone.mCi.getLastDataCallFailCause(
- obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp));
- break;
- case ERR_RilError:
- // Request failed and mFailCause has the reason
- mInactiveState.setEnterNotificationParams(cp, result.mFailCause,
- getSuggestedRetryTime(ar));
- transitionTo(mInactiveState);
- break;
- case ERR_Stale:
- // Request is stale, ignore.
- break;
- default:
- throw new RuntimeException("Unknown SetupResult, should not happen");
- }
- retVal = HANDLED;
- break;
-
- case EVENT_GET_LAST_FAIL_DONE:
- ar = (AsyncResult) msg.obj;
- cp = (ConnectionParams) ar.userObj;
- FailCause cause = FailCause.UNKNOWN;
-
- if (cp.mTheTag == mTag) {
- if (DBG) {
- log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE"
- + " RefCount=" + mApnList.size());
- }
- if (ar.exception == null) {
- int rilFailCause = ((int[]) (ar.result))[0];
- cause = FailCause.fromInt(rilFailCause);
- }
- // Transition to inactive but send notifications after
- // we've entered the mInactive state.
- mInactiveState.setEnterNotificationParams(cp, cause, -1);
- transitionTo(mInactiveState);
- } else {
- if (DBG) {
- log("DcActivatingState EVENT_GET_LAST_FAIL_DONE is stale cp.tag="
- + cp.mTheTag + ", mTag=" + mTag + " RefCount=" + mApnList.size());
- }
- }
-
- retVal = HANDLED;
- break;
-
- default:
- if (VDBG) {
- log("DcActivatingState not handled msg.what=0x" +
- Integer.toHexString(msg.what) + " RefCount=" + mApnList.size());
- }
- retVal = NOT_HANDLED;
- break;
- }
- return retVal;
- }
- }
- private DcActivatingState mActivatingState = new DcActivatingState();
-
- /**
- * The state machine is connected, expecting an EVENT_DISCONNECT.
- */
- private class DcActiveState extends State {
- private ConnectionParams mConnectionParams = null;
- private FailCause mFailCause = null;
-
- public void setEnterNotificationParams(ConnectionParams cp, FailCause cause) {
- if (VDBG) log("DcInactiveState: setEnterNoticationParams cp,cause");
- mConnectionParams = cp;
- mFailCause = cause;
- }
-
- @Override public void enter() {
- /**
- * Now that we've transitioned to Active state we
- * can send notifications. Previously we sent the
- * notifications in the processMessage handler but
- * that caused a race condition because the synchronous
- * call to isActive.
- */
- if ((mConnectionParams != null) && (mFailCause != null)) {
- if (VDBG) log("DcActiveState: enter notifyConnectCompleted");
- notifyConnectCompleted(mConnectionParams, mFailCause);
- }
- }
-
- @Override
- public void exit() {
- // clear notifications
- mConnectionParams = null;
- mFailCause = null;
- }
-
- @Override
- public boolean processMessage(Message msg) {
- boolean retVal;
-
- switch (msg.what) {
- case EVENT_CONNECT: {
- ConnectionParams cp = (ConnectionParams) msg.obj;
- if (mApnList.contains(cp.mApnContext)) {
- log("DcActiveState ERROR already added apnContext=" + cp.mApnContext
- + " to this DC=" + this);
- } else {
- mApnList.add(cp.mApnContext);
- if (DBG) {
- log("DcActiveState msg.what=EVENT_CONNECT RefCount=" + mApnList.size());
- }
- }
- notifyConnectCompleted(cp, FailCause.NONE);
- retVal = HANDLED;
- break;
- }
- case EVENT_DISCONNECT: {
- DisconnectParams dp = (DisconnectParams) msg.obj;
- if (mApnList.contains(dp.mApnContext)) {
- if (DBG) {
- log("DcActiveState msg.what=EVENT_DISCONNECT RefCount="
- + mApnList.size());
- }
-
- if (mApnList.size() == 1) {
- mApnList.clear();
- dp.mTheTag = mTag;
- tearDownData(dp);
- transitionTo(mDisconnectingState);
- } else {
- mApnList.remove(dp.mApnContext);
- notifyDisconnectCompleted(dp, false);
- }
- } else {
- log("DcActiveState ERROR no such apnContext=" + dp.mApnContext
- + " in this DC=" + this);
- notifyDisconnectCompleted(dp, false);
- }
- retVal = HANDLED;
- break;
- }
- case EVENT_DISCONNECT_ALL: {
- if (DBG) {
- log("DcActiveState msg.what=EVENT_DISCONNECT_ALL RefCount="
- + mApnList.size() + " clearing apn contexts");
- }
- mApnList.clear();
- DisconnectParams dp = (DisconnectParams) msg.obj;
- dp.mTheTag = mTag;
- tearDownData(dp);
- transitionTo(mDisconnectingState);
- retVal = HANDLED;
- break;
- }
- default:
- if (VDBG) {
- log("DcActiveState not handled msg.what=0x" +
- Integer.toHexString(msg.what));
- }
- retVal = NOT_HANDLED;
- break;
- }
- return retVal;
- }
- }
- private DcActiveState mActiveState = new DcActiveState();
-
- /**
- * The state machine is disconnecting.
- */
- 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 = "
- + mApnList.size());
- deferMessage(msg);
- retVal = HANDLED;
- break;
-
- case EVENT_DEACTIVATE_DONE:
- if (DBG) log("DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount="
- + mApnList.size());
- AsyncResult ar = (AsyncResult) msg.obj;
- DisconnectParams dp = (DisconnectParams) ar.userObj;
- if (dp.mTheTag == mTag) {
- // Transition to inactive but send notifications after
- // we've entered the mInactive state.
- mInactiveState.setEnterNotificationParams((DisconnectParams) ar.userObj);
- transitionTo(mInactiveState);
- } else {
- if (DBG) log("DcDisconnectState EVENT_DEACTIVATE_DONE stale dp.tag="
- + dp.mTheTag + " mTag=" + mTag);
- }
- retVal = HANDLED;
- break;
-
- default:
- if (VDBG) {
- log("DcDisconnectingState not handled msg.what=0x" +
- Integer.toHexString(msg.what));
- }
- retVal = NOT_HANDLED;
- break;
- }
- return retVal;
- }
- }
- private DcDisconnectingState mDisconnectingState = new DcDisconnectingState();
-
- /**
- * The state machine is disconnecting after an creating a connection.
- */
- private class DcDisconnectionErrorCreatingConnection extends State {
- @Override
- public boolean processMessage(Message msg) {
- boolean retVal;
-
- switch (msg.what) {
- case EVENT_DEACTIVATE_DONE:
- AsyncResult ar = (AsyncResult) msg.obj;
- ConnectionParams cp = (ConnectionParams) ar.userObj;
- if (cp.mTheTag == mTag) {
- if (DBG) {
- log("DcDisconnectionErrorCreatingConnection" +
- " msg.what=EVENT_DEACTIVATE_DONE");
- }
-
- // Transition to inactive but send notifications after
- // we've entered the mInactive state.
- mInactiveState.setEnterNotificationParams(cp,
- FailCause.UNACCEPTABLE_NETWORK_PARAMETER, -1);
- transitionTo(mInactiveState);
- } else {
- if (DBG) {
- log("DcDisconnectionErrorCreatingConnection EVENT_DEACTIVATE_DONE" +
- " stale dp.tag=" + cp.mTheTag + ", mTag=" + mTag);
- }
- }
- retVal = HANDLED;
- break;
-
- default:
- if (VDBG) {
- log("DcDisconnectionErrorCreatingConnection not handled msg.what=0x"
- + Integer.toHexString(msg.what));
- }
- retVal = NOT_HANDLED;
- break;
- }
- return retVal;
- }
- }
- private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection =
- new DcDisconnectionErrorCreatingConnection();
-
- // ******* public interface
-
- /**
- * 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 apnContext is the Access Point Name to bring up a connection to
- * @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 bringUp(ApnContext apnContext, Message onCompletedMsg) {
- if (DBG) log("bringUp: apnContext=" + apnContext + " onCompletedMsg=" + onCompletedMsg);
- sendMessage(obtainMessage(EVENT_CONNECT, new ConnectionParams(apnContext, onCompletedMsg)));
- }
-
- /**
- * 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 tearDown(ApnContext apnContext, String reason, Message onCompletedMsg) {
- if (DBG) {
- log("tearDown: apnContext=" + apnContext
- + " reason=" + reason + " onCompletedMsg=" + onCompletedMsg);
- }
- sendMessage(obtainMessage(EVENT_DISCONNECT,
- new DisconnectParams(apnContext, reason, onCompletedMsg)));
- }
-
- /**
- * Tear down the connection through the apn on the network. Ignores refcount and
- * and always tears down.
- *
- * @param onCompletedMsg is sent with its msg.obj as an AsyncResult object.
- * With AsyncResult.userObj set to the original msg.obj.
- */
- public void tearDownAll(String reason, Message onCompletedMsg) {
- if (DBG) log("tearDownAll: reason=" + reason + " onCompletedMsg=" + onCompletedMsg);
- sendMessage(obtainMessage(EVENT_DISCONNECT_ALL,
- new DisconnectParams(null, reason, onCompletedMsg)));
- }
-
- /**
- * @return the string for msg.what as our info.
- */
- @Override
- protected String getWhatToString(int what) {
- String info = null;
- info = cmdToString(what);
- if (info == null) {
- info = DataConnectionAc.cmdToString(what);
- }
- return info;
- }
-
- /**
- * Dump the current state.
- *
- * @param fd
- * @param pw
- * @param args
- */
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.print("DataConnectionBase ");
- super.dump(fd, pw, args);
- pw.println(" mApnContexts.size=" + mApnList.size());
- pw.println(" mApnContexts=" + mApnList);
- pw.flush();
- pw.println(" mDataConnectionTracker=" + mDataConnectionTracker);
- pw.println(" mApn=" + mApn);
- pw.println(" mTag=" + mTag);
- pw.flush();
- pw.println(" mPhone=" + mPhone);
- pw.println(" mRilVersion=" + mRilVersion);
- pw.println(" mCid=" + mCid);
- pw.flush();
- pw.println(" mLinkProperties=" + mLinkProperties);
- pw.flush();
- pw.println(" mCapabilities=" + mCapabilities);
- pw.println(" mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime));
- pw.println(" mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime));
- pw.println(" mLastFailCause=" + mLastFailCause);
- pw.flush();
- pw.println(" mRetryOverride=" + mRetryOverride);
- pw.println(" mUserData=" + mUserData);
- if (mRetryMgr != null) pw.println(" " + mRetryMgr);
- pw.flush();
- }
-}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnectionTracker.java b/src/java/com/android/internal/telephony/dataconnection/DataConnectionTracker.java
index d9a7bf4..2730706 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnectionTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnectionTracker.java
@@ -27,10 +27,8 @@
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
-import android.net.LinkAddress;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
-import android.net.LinkProperties.CompareResult;
import android.net.NetworkConfig;
import android.net.NetworkUtils;
import android.net.ProxyProperties;
@@ -52,20 +50,11 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneBase;
-import com.android.internal.telephony.dataconnection.ApnContext;
-import com.android.internal.telephony.dataconnection.ApnSetting;
-import com.android.internal.telephony.DataCallState;
-import com.android.internal.telephony.dataconnection.DataConnectionBase;
-import com.android.internal.telephony.dataconnection.DataConnectionBase.FailCause;
-import com.android.internal.telephony.dataconnection.DataConnectionBase.UpdateLinkPropertyResult;
-import com.android.internal.telephony.dataconnection.DataConnectionAc;
-import com.android.internal.telephony.dataconnection.DataConnectionTrackerBase;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.EventLogTags;
import com.android.internal.telephony.gsm.GSMPhone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
-import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.AsyncChannel;
@@ -73,9 +62,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
/**
* {@hide}
@@ -104,69 +91,17 @@
//***** Constants
+ // Used by puppetmaster/*/radio_stress.py
+ private static final String PUPPET_MASTER_RADIO_STRESS_TEST = "gsm.defaultpdpcontext.active";
+
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 = "reconnect_alarm_extra_type";
- private static final String INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT =
- "reconnect_alaram_extra_retry_count";
-
- private static final String INTENT_DATA_STALL_ALARM =
- "com.android.internal.telephony.gprs-data-stall";
-
static final Uri PREFERAPN_NO_UPDATE_URI =
Uri.parse("content://telephony/carriers/preferapn_no_update");
static final String APN_ID = "apn_id";
+
private boolean mCanSetPreferApn = false;
- @Override
- protected void onActionIntentReconnectAlarm(Intent intent) {
- String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- String apnType = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
- int retryCount = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT, 0);
-
- ApnContext apnContext = mApnContexts.get(apnType);
-
- if (DBG) {
- log("onActionIntentReconnectAlarm: mState=" + mState + " reason=" + reason +
- " retryCount=" + retryCount +
- " apnType=" + apnType + " apnContext=" + apnContext +
- " mDataConnectionAsyncChannels=" + mDataConnectionAsyncChannels);
- }
-
- if ((apnContext != null) && (apnContext.isEnabled())) {
- apnContext.setReason(reason);
- apnContext.setRetryCount(retryCount);
- DctConstants.State apnContextState = apnContext.getState();
- if (DBG) {
- log("onActionIntentReconnectAlarm: apnContext state=" + apnContextState);
- }
- if ((apnContextState == DctConstants.State.FAILED)
- || (apnContextState == DctConstants.State.IDLE)) {
- if (DBG) {
- log("onActionIntentReconnectAlarm: state is FAILED|IDLE, disassociate");
- }
- apnContext.setDataConnectionAc(null);
- apnContext.setDataConnection(null);
- apnContext.setState(DctConstants.State.IDLE);
- } else {
- if (DBG) log("onActionIntentReconnectAlarm: keep associated");
- }
- // TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA???
- sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
-
- DataConnectionAc dcac = apnContext.getDataConnectionAc();
- if (dcac != null) {
- Collection<ApnContext> apnList = dcac.getApnListSync();
- log("onActionIntentReconnectAlarm: dcac.getApnListSync()=" + apnList);
- // Alarm had expired. Clear pending intent recorded on the DataConnection.
- // TODO: Maybe store in apnContext????
- dcac.setReconnectIntentSync(null);
- }
- }
- }
-
/** Watches for changes to the APN db. */
private ApnChangeObserver mApnObserver;
@@ -239,7 +174,7 @@
ApnContext apnContext = mApnContexts.get(type);
if (apnContext == null) return false;
- return (apnContext.getDataConnection() != null);
+ return (apnContext.getDcAc() != null);
}
@Override
@@ -255,7 +190,7 @@
boolean dataAllowed = isDataAllowed();
boolean possible = dataAllowed && apnTypePossible;
- if (DBG) {
+ if (VDBG) {
log(String.format("isDataPossible(%s): possible=%b isDataAllowed=%b " +
"apnTypePossible=%b apnContextisEnabled=%b apnContextState()=%s",
apnType, possible, dataAllowed, apnTypePossible,
@@ -269,16 +204,6 @@
if(DBG) log("finalize");
}
- @Override
- protected String getActionIntentReconnectAlarm() {
- return INTENT_RECONNECT_ALARM;
- }
-
- @Override
- protected String getActionIntentDataStallAlarm() {
- return INTENT_DATA_STALL_ALARM;
- }
-
private ApnContext addApnContext(String type) {
ApnContext apnContext = new ApnContext(type, LOG_TAG);
apnContext.setDependencyMet(false);
@@ -343,7 +268,7 @@
public LinkProperties getLinkProperties(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext != null) {
- DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ DataConnectionAc dcac = apnContext.getDcAc();
if (dcac != null) {
if (DBG) log("return link properites for " + apnType);
return dcac.getLinkPropertiesSync();
@@ -357,7 +282,7 @@
public LinkCapabilities getLinkCapabilities(String apnType) {
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext!=null) {
- DataConnectionAc dataConnectionAc = apnContext.getDataConnectionAc();
+ DataConnectionAc dataConnectionAc = apnContext.getDcAc();
if (dataConnectionAc != null) {
if (DBG) log("get active pdp is not null, return link Capabilities for " + apnType);
return dataConnectionAc.getLinkCapabilitiesSync();
@@ -385,7 +310,7 @@
@Override
// Return active apn of specific apn type
public String getActiveApnString(String apnType) {
- if (DBG) log( "get active apn string for type:" + apnType);
+ if (VDBG) log( "get active apn string for type:" + apnType);
ApnContext apnContext = mApnContexts.get(apnType);
if (apnContext != null) {
ApnSetting apnSetting = apnContext.getApnSetting();
@@ -435,6 +360,7 @@
case DISCONNECTING:
if (DBG) log("overall state is CONNECTED");
return DctConstants.State.CONNECTED;
+ case RETRYING:
case CONNECTING:
isConnecting = true;
isFailed = false;
@@ -529,8 +455,8 @@
return true;
}
- if (mAllApns != null) {
- for (ApnSetting apn : mAllApns) {
+ if (mAllApnSettings != null) {
+ for (ApnSetting apn : mAllApnSettings) {
if (apn.canHandleType(type)) {
return true;
}
@@ -591,7 +517,7 @@
notifyOffApnsOfAvailability(Phone.REASON_DATA_ATTACHED);
}
mAutoAttachOnCreation = true;
- setupDataOnReadyApns(Phone.REASON_DATA_ATTACHED);
+ setupDataOnConnectableApns(Phone.REASON_DATA_ATTACHED);
}
@Override
@@ -637,49 +563,15 @@
return allowed;
}
- private void setupDataOnReadyApns(String reason) {
- // Stop reconnect alarms on all data connections pending
- // retry. Reset ApnContext state to IDLE.
- for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
- if (dcac.getReconnectIntentSync() != null) {
- cancelReconnectAlarm(dcac);
- }
- // update retry config for existing calls to match up
- // ones for the new RAT.
- if (dcac.dataConnection != null) {
- Collection<ApnContext> apns = dcac.getApnListSync();
-
- boolean hasDefault = false;
- for (ApnContext apnContext : apns) {
- if (apnContext.getApnType().equals(PhoneConstants.APN_TYPE_DEFAULT)) {
- hasDefault = true;
- break;
- }
- }
- configureRetry(dcac.dataConnection, hasDefault, 0);
- }
- }
-
- // Be sure retry counts for Apncontexts and DC's are sync'd.
- // When DCT/ApnContexts are refactored and we cleanup retrying
- // this won't be needed.
- resetAllRetryCounts();
-
- // Only check for default APN state
+ private void setupDataOnConnectableApns(String reason) {
for (ApnContext apnContext : mApnContexts.values()) {
if (apnContext.getState() == DctConstants.State.FAILED) {
- // By this time, alarms for all failed Apns
- // should be stopped if any.
- // Make sure to set the state back to IDLE
- // so that setup data can happen.
apnContext.setState(DctConstants.State.IDLE);
}
- if (apnContext.isReady()) {
- if (apnContext.getState() == DctConstants.State.IDLE ||
- apnContext.getState() == DctConstants.State.SCANNING) {
- apnContext.setReason(reason);
- trySetupData(apnContext);
- }
+ if (apnContext.isConnectable()) {
+ log("setupDataOnConnectableApns: isConnectable() call trySetupData");
+ apnContext.setReason(reason);
+ trySetupData(apnContext);
}
}
}
@@ -725,21 +617,24 @@
boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
- if ((apnContext.getState() == DctConstants.State.IDLE ||
- apnContext.getState() == DctConstants.State.SCANNING) &&
+ if (apnContext.isConnectable() &&
isDataAllowed(apnContext) && getAnyDataEnabled() && !isEmergency()) {
-
+ if (apnContext.getState() == DctConstants.State.FAILED) {
+ if (DBG) log("trySetupData: make a FAILED ApnContext IDLE so its reusable");
+ apnContext.setState(DctConstants.State.IDLE);
+ }
if (apnContext.getState() == DctConstants.State.IDLE) {
ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());
if (waitingApns.isEmpty()) {
- notifyNoData(DataConnectionBase.FailCause.MISSING_UNKNOWN_APN, apnContext);
+ notifyNoData(DcFailCause.MISSING_UNKNOWN_APN, apnContext);
notifyOffApnsOfAvailability(apnContext.getReason());
if (DBG) log("trySetupData: X No APN found retValue=false");
return false;
} else {
apnContext.setWaitingApns(waitingApns);
if (DBG) {
- log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
+ log ("trySetupData: Create from mAllApnSettings : "
+ + apnListToString(mAllApnSettings));
}
}
}
@@ -748,18 +643,16 @@
log("trySetupData: call setupData, waitingApns : "
+ apnListToString(apnContext.getWaitingApns()));
}
- // apnContext.setReason(apnContext.getReason());
boolean retValue = setupData(apnContext);
notifyOffApnsOfAvailability(apnContext.getReason());
if (DBG) log("trySetupData: X retValue=" + retValue);
return retValue;
} else {
- // TODO: check the condition.
if (!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_DEFAULT)
- && (apnContext.getState() == DctConstants.State.IDLE
- || apnContext.getState() == DctConstants.State.SCANNING))
+ && apnContext.isConnectable()) {
mPhone.notifyDataConnectionFailed(apnContext.getReason(), apnContext.getApnType());
+ }
notifyOffApnsOfAvailability(apnContext.getReason());
if (DBG) log ("trySetupData: X apnContext not 'ready' retValue=false");
return false;
@@ -771,12 +664,12 @@
protected void notifyOffApnsOfAvailability(String reason) {
for (ApnContext apnContext : mApnContexts.values()) {
if (!apnContext.isReady()) {
- if (DBG) log("notifyOffApnOfAvailability type:" + apnContext.getApnType());
+ if (VDBG) log("notifyOffApnOfAvailability type:" + apnContext.getApnType());
mPhone.notifyDataConnection(reason != null ? reason : apnContext.getReason(),
apnContext.getApnType(),
PhoneConstants.DataState.DISCONNECTED);
} else {
- if (DBG) {
+ if (VDBG) {
log("notifyOffApnsOfAvailability skipped apn due to isReady==true: " +
apnContext.toString());
}
@@ -830,7 +723,7 @@
return;
}
- DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ DataConnectionAc dcac = apnContext.getDcAc();
if (DBG) {
log("cleanUpConnection: E tearDown=" + tearDown + " reason=" + apnContext.getReason() +
" apnContext=" + apnContext);
@@ -841,7 +734,6 @@
// If apnContext is not enabled anymore, break the linkage to the DCAC/DC.
apnContext.setState(DctConstants.State.IDLE);
if (!apnContext.isReady()) {
- apnContext.setDataConnection(null);
apnContext.setDataConnectionAc(null);
}
} else {
@@ -866,9 +758,9 @@
}
Message msg = obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, apnContext);
if (disconnectAll) {
- apnContext.getDataConnection().tearDownAll(apnContext.getReason(), msg);
+ apnContext.getDcAc().tearDownAll(apnContext.getReason(), msg);
} else {
- apnContext.getDataConnection()
+ apnContext.getDcAc()
.tearDown(apnContext, apnContext.getReason(), msg);
}
apnContext.setState(DctConstants.State.DISCONNECTING);
@@ -883,42 +775,38 @@
}
} else {
// force clean up the data connection.
- if (dcac != null) dcac.resetSync();
+ if (dcac != null) dcac.reqReset();
apnContext.setState(DctConstants.State.IDLE);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
- apnContext.setDataConnection(null);
apnContext.setDataConnectionAc(null);
}
- // make sure reconnection alarm is cleaned up if there is no ApnContext
+ // Make sure reconnection alarm is cleaned up if there is no ApnContext
// associated to the connection.
if (dcac != null) {
- Collection<ApnContext> apnList = dcac.getApnListSync();
- if (apnList.isEmpty()) {
- cancelReconnectAlarm(dcac);
- }
+ cancelReconnectAlarm(apnContext);
}
if (DBG) {
log("cleanUpConnection: X tearDown=" + tearDown + " reason=" + apnContext.getReason() +
- " apnContext=" + apnContext + " dc=" + apnContext.getDataConnection());
+ " apnContext=" + apnContext + " dcac=" + apnContext.getDcAc());
}
}
/**
- * Cancels the alarm associated with DCAC.
+ * Cancels the alarm associated with apnContext.
*
- * @param dcac on which the alarm should be stopped.
+ * @param apnContext on which the alarm should be stopped.
*/
- private void cancelReconnectAlarm(DataConnectionAc dcac) {
- if (dcac == null) return;
+ private void cancelReconnectAlarm(ApnContext apnContext) {
+ if (apnContext == null) return;
- PendingIntent intent = dcac.getReconnectIntentSync();
+ PendingIntent intent = apnContext.getReconnectIntent();
if (intent != null) {
AlarmManager am =
(AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
am.cancel(intent);
- dcac.setReconnectIntentSync(null);
+ apnContext.setReconnectIntent(null);
}
}
@@ -1054,9 +942,9 @@
}
private boolean dataConnectionNotInUse(DataConnectionAc dcac) {
- if (DBG) log("dataConnectionNotInUse: check if dcac is inuse dc=" + dcac.dataConnection);
+ if (DBG) log("dataConnectionNotInUse: check if dcac is inuse dcac=" + dcac);
for (ApnContext apnContext : mApnContexts.values()) {
- if (apnContext.getDataConnectionAc() == dcac) {
+ if (apnContext.getDcAc() == dcac) {
if (DBG) log("dataConnectionNotInUse: in use by apnContext=" + apnContext);
return false;
}
@@ -1065,20 +953,19 @@
// Probably move retry handling into DataConnections and reduce complexity
// of DCT.
if (DBG) log("dataConnectionNotInUse: tearDownAll");
- dcac.dataConnection.tearDownAll("No connection", null);
+ dcac.tearDownAll("No connection", null);
if (DBG) log("dataConnectionNotInUse: not in use return true");
return true;
}
- private DataConnection findFreeDataConnection() {
- for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ private DataConnectionAc findFreeDataConnection() {
+ for (DataConnectionAc dcac : mDataConnectionAcHashMap.values()) {
if (dcac.isInactiveSync() && dataConnectionNotInUse(dcac)) {
- DataConnectionBase dc = dcac.dataConnection;
if (DBG) {
log("findFreeDataConnection: found free DataConnection=" +
- " dcac=" + dcac + " dc=" + dc);
+ " dcac=" + dcac);
}
- return (DataConnection) dc;
+ return dcac;
}
}
log("findFreeDataConnection: NO free DataConnection");
@@ -1087,66 +974,48 @@
private boolean setupData(ApnContext apnContext) {
if (DBG) log("setupData: apnContext=" + apnContext);
- ApnSetting apn;
- DataConnection dc;
+ ApnSetting apnSetting;
+ DataConnectionAc dcac;
int profileId = getApnProfileID(apnContext.getApnType());
- apn = apnContext.getNextWaitingApn();
- if (apn == null) {
+ apnSetting = apnContext.getNextWaitingApn();
+ if (apnSetting == null) {
if (DBG) log("setupData: return for no apn found!");
return false;
}
+ dcac = checkForCompatibleConnectedApnContext(apnContext);
+ if (dcac != null) {
+ // Get the dcacApnSetting for the connection we want to share.
+ ApnSetting dcacApnSetting = dcac.getApnSettingSync();
+ if (dcacApnSetting != null) {
+ // Setting is good, so use it.
+ apnSetting = dcacApnSetting;
+ }
+ }
+ if (dcac == null) {
+ dcac = findFreeDataConnection();
- dc = (DataConnection) checkForConnectionForApnContext(apnContext);
-
- if (dc == null) {
- // 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 (dcac == null) {
+ dcac = createDataConnection();
}
- if (dc == null) {
- if (DBG) log("setupData: No free DataConnection found!");
+ if (dcac == null) {
+ if (DBG) log("setupData: No free DataConnection and couldn't create one, WEIRD");
return false;
}
- } else {
- apn = mDataConnectionAsyncChannels.get(dc.getDataConnectionId()).getApnSettingSync();
}
+ if (DBG) log("setupData: dcac=" + dcac + " apnSetting=" + apnSetting);
- DataConnectionAc dcac = mDataConnectionAsyncChannels.get(dc.getDataConnectionId());
- dc.setProfileId( profileId ); // assumed no connection sharing on profiled types
-
- 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, apn.canHandleType(PhoneConstants.APN_TYPE_DEFAULT),
- apnContext.getRetryCount());
- }
apnContext.setDataConnectionAc(dcac);
- apnContext.setDataConnection(dc);
-
- apnContext.setApnSetting(apn);
+ apnContext.setApnSetting(apnSetting);
apnContext.setState(DctConstants.State.CONNECTING);
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
- // If reconnect alarm is active on this DataConnection, wait for the alarm being
- // fired so that we don't disrupt data retry pattern engaged.
- if (apnContext.getDataConnectionAc().getReconnectIntentSync() != null) {
- if (DBG) log("setupData: data reconnection pending");
- apnContext.setState(DctConstants.State.FAILED);
- mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
- return true;
- }
Message msg = obtainMessage();
msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;
msg.obj = apnContext;
- dc.bringUp(apnContext, msg);
+ dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, msg);
if (DBG) log("setupData: initing!");
return true;
@@ -1171,7 +1040,7 @@
createAllApnList();
cleanUpAllConnections(!isDisconnected, Phone.REASON_APN_CHANGED);
if (isDisconnected) {
- setupDataOnReadyApns(Phone.REASON_APN_CHANGED);
+ setupDataOnConnectableApns(Phone.REASON_APN_CHANGED);
}
}
@@ -1180,7 +1049,7 @@
* @return DataConnectionAc associated with specified cid.
*/
private DataConnectionAc findDataConnectionAcByCid(int cid) {
- for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ for (DataConnectionAc dcac : mDataConnectionAcHashMap.values()) {
if (dcac.getCidSync() == cid) {
return dcac;
}
@@ -1189,52 +1058,14 @@
}
/**
- * @param dcacs Collection of DataConnectionAc reported from RIL.
- * @return List of ApnContext which is connected, but is not present in
- * data connection list reported from RIL.
- */
- private List<ApnContext> findApnContextToClean(Collection<DataConnectionAc> dcacs) {
- if (dcacs == null) return null;
-
- if (DBG) log("findApnContextToClean(ar): E dcacs=" + dcacs);
-
- ArrayList<ApnContext> list = new ArrayList<ApnContext>();
- for (ApnContext apnContext : mApnContexts.values()) {
- if (apnContext.getState() == DctConstants.State.CONNECTED) {
- boolean found = false;
- for (DataConnectionAc dcac : dcacs) {
- if (dcac == apnContext.getDataConnectionAc()) {
- // ApnContext holds the ref to dcac present in data call list.
- found = true;
- break;
- }
- }
- if (!found) {
- // ApnContext does not have dcac reported in data call list.
- // Fetch all the ApnContexts that map to this dcac.
- if (DBG) log("findApnContextToClean(ar): Connected apn not found in the list (" +
- apnContext.toString() + ")");
- if (apnContext.getDataConnectionAc() != null) {
- list.addAll(apnContext.getDataConnectionAc().getApnListSync());
- } else {
- list.add(apnContext);
- }
- }
- }
- }
- if (DBG) log("findApnContextToClean(ar): X list=" + list);
- return list;
- }
-
- /**
* @param ar is the result of RIL_REQUEST_DATA_CALL_LIST
* or RIL_UNSOL_DATA_CALL_LIST_CHANGED
*/
private void onDataStateChanged (AsyncResult ar) {
- ArrayList<DataCallState> dataCallStates;
+ ArrayList<DataCallResponse> dataCallStates;
if (DBG) log("onDataStateChanged(ar): E");
- dataCallStates = (ArrayList<DataCallState>)(ar.result);
+ dataCallStates = (ArrayList<DataCallResponse>)(ar.result);
if (ar.exception != null) {
// This is probably "radio not available" or something
@@ -1243,117 +1074,24 @@
if (DBG) log("onDataStateChanged(ar): exception; likely radio not available, ignore");
return;
}
- if (DBG) log("onDataStateChanged(ar): DataCallState size=" + dataCallStates.size());
-
- boolean isAnyDataCallDormant = false;
- boolean isAnyDataCallActive = false;
+ if (DBG) log("onDataStateChanged(ar): DataCallResponse size=" + dataCallStates.size());
// Create a hash map to store the dataCallState of each DataConnectionAc
- HashMap<DataCallState, DataConnectionAc> dataCallStateToDcac;
- dataCallStateToDcac = new HashMap<DataCallState, DataConnectionAc>();
- for (DataCallState dataCallState : dataCallStates) {
+ HashMap<DataCallResponse, DataConnectionAc> dataCallStateToDcac;
+ dataCallStateToDcac = new HashMap<DataCallResponse, DataConnectionAc>();
+ for (DataCallResponse dataCallState : dataCallStates) {
DataConnectionAc dcac = findDataConnectionAcByCid(dataCallState.cid);
if (dcac != null) dataCallStateToDcac.put(dataCallState, dcac);
}
- // A list of apns to cleanup, those that aren't in the list we know we have to cleanup
- List<ApnContext> apnsToCleanup = findApnContextToClean(dataCallStateToDcac.values());
-
- // Find which connections have changed state and send a notification or cleanup
- for (DataCallState newState : dataCallStates) {
- DataConnectionAc dcac = dataCallStateToDcac.get(newState);
-
- if (dcac == null) {
- loge("onDataStateChanged(ar): No associated DataConnection ignore");
- continue;
- }
-
+ // Check if we should start or stop polling, by looking
+ // for dormant and active connections.
+ boolean isAnyDataCallDormant = false;
+ boolean isAnyDataCallActive = false;
+ for (DataCallResponse newState : dataCallStates) {
if (newState.active == DATA_CONNECTION_ACTIVE_PH_LINK_UP) isAnyDataCallActive = true;
if (newState.active == DATA_CONNECTION_ACTIVE_PH_LINK_DOWN) isAnyDataCallDormant = true;
-
- // The list of apn's associated with this DataConnection
- Collection<ApnContext> apns = dcac.getApnListSync();
-
- // Find which ApnContexts of this DC are in the "Connected/Connecting" state.
- ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
- for (ApnContext apnContext : apns) {
- if (apnContext.getState() == DctConstants.State.CONNECTED ||
- apnContext.getState() == DctConstants.State.CONNECTING) {
- connectedApns.add(apnContext);
- }
- }
- if (connectedApns.size() == 0) {
- if (DBG) log("onDataStateChanged(ar): no connected apns");
- } else {
- // Determine if the connection/apnContext should be cleaned up
- // or just a notification should be sent out.
- if (DBG) log("onDataStateChanged(ar): Found ConnId=" + newState.cid
- + " newState=" + newState.toString());
- if (newState.active == 0) {
- if (DBG) {
- log("onDataStateChanged(ar): inactive, cleanup apns=" + connectedApns);
- }
- apnsToCleanup.addAll(connectedApns);
- } else {
- // Its active so update the DataConnections link properties
- UpdateLinkPropertyResult result =
- dcac.updateLinkPropertiesDataCallStateSync(newState);
- if (result.oldLp.equals(result.newLp)) {
- if (DBG) log("onDataStateChanged(ar): no change");
- } else {
- if (result.oldLp.isIdenticalInterfaceName(result.newLp)) {
- if (! result.oldLp.isIdenticalDnses(result.newLp) ||
- ! result.oldLp.isIdenticalRoutes(result.newLp) ||
- ! result.oldLp.isIdenticalHttpProxy(result.newLp) ||
- ! result.oldLp.isIdenticalAddresses(result.newLp)) {
- // If the same address type was removed and added we need to cleanup
- CompareResult<LinkAddress> car =
- result.oldLp.compareAddresses(result.newLp);
- if (DBG) {
- log("onDataStateChanged: oldLp=" + result.oldLp +
- " newLp=" + result.newLp + " car=" + car);
- }
- boolean needToClean = false;
- for (LinkAddress added : car.added) {
- for (LinkAddress removed : car.removed) {
- if (NetworkUtils.addressTypeMatches(removed.getAddress(),
- added.getAddress())) {
- needToClean = true;
- break;
- }
- }
- }
- if (needToClean) {
- if (DBG) {
- log("onDataStateChanged(ar): addr change, cleanup apns=" +
- connectedApns + " oldLp=" + result.oldLp +
- " newLp=" + result.newLp);
- }
- apnsToCleanup.addAll(connectedApns);
- } else {
- if (DBG) log("onDataStateChanged(ar): simple change");
- for (ApnContext apnContext : connectedApns) {
- mPhone.notifyDataConnection(
- PhoneConstants.REASON_LINK_PROPERTIES_CHANGED,
- apnContext.getApnType());
- }
- }
- } else {
- if (DBG) {
- log("onDataStateChanged(ar): no changes");
- }
- }
- } else {
- if (DBG) {
- log("onDataStateChanged(ar): interface change, cleanup apns="
- + connectedApns);
- }
- apnsToCleanup.addAll(connectedApns);
- }
- }
- }
- }
}
if (isAnyDataCallDormant && !isAnyDataCallActive) {
@@ -1376,20 +1114,6 @@
}
if (isAnyDataCallActive) startNetStatPoll();
}
- mPhone.notifyDataActivity();
-
- if (apnsToCleanup.size() != 0) {
- // Add an event log when the network drops PDP
- int cid = getCellLocationId();
- EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP, cid,
- TelephonyManager.getDefault().getNetworkType());
- }
-
- // Cleanup those dropped connections
- if (DBG) log("onDataStateChange(ar): apnsToCleanup=" + apnsToCleanup);
- for (ApnContext apnContext : apnsToCleanup) {
- cleanUpConnection(true, apnContext);
- }
if (DBG) log("onDataStateChanged(ar): X");
}
@@ -1404,8 +1128,6 @@
mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
startNetStatPoll();
startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
- // reset reconnect timer
- apnContext.setRetryCount(0);
}
// TODO: For multiple Active APNs not exactly sure how to do this.
@@ -1434,15 +1156,6 @@
}
/**
- * Returns true if the last fail cause is something that
- * seems like it deserves an error notification.
- * Transient errors are ignored
- */
- private boolean shouldPostNotification(DataConnection.FailCause cause) {
- return (cause != DataConnection.FailCause.UNKNOWN);
- }
-
- /**
* Return true if data connection need to be setup after disconnected due to
* reason.
*
@@ -1458,107 +1171,42 @@
return retry;
}
- private void reconnectAfterFail(FailCause lastFailCauseCode,
- ApnContext apnContext, int retryOverride) {
- if (apnContext == null) {
- loge("reconnectAfterFail: apnContext == null, impossible");
- return;
- }
- if (DBG) {
- log("reconnectAfterFail: lastFailCause=" + lastFailCauseCode +
- " retryOverride=" + retryOverride + " apnContext=" + apnContext);
- }
- if ((apnContext.getState() == DctConstants.State.FAILED) &&
- (apnContext.getDataConnection() != null)) {
- if (!apnContext.getDataConnection().isRetryNeeded()) {
- if (!apnContext.getApnType().equals(PhoneConstants.APN_TYPE_DEFAULT)) {
- mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
- return;
- }
- if (mReregisterOnReconnectFailure) {
- // We've re-registerd once now just retry forever.
- apnContext.getDataConnection().retryForeverUsingLastTimeout();
- } else {
- // Try to Re-register to the network.
- if (DBG) log("reconnectAfterFail: activate failed, Reregistering to network");
- mReregisterOnReconnectFailure = true;
- mPhone.getServiceStateTracker().reRegisterNetwork(null);
- apnContext.setRetryCount(0);
- return;
- }
- }
-
- // If retry needs to be backed off for specific case (determined by RIL/Modem)
- // use the specified timer instead of pre-configured retry pattern.
- int nextReconnectDelay = retryOverride;
- if (nextReconnectDelay < 0) {
- nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
- apnContext.getDataConnection().increaseRetryCount();
- if (DBG) {
- log("reconnectAfterFail: increaseRetryCount=" +
- apnContext.getDataConnection().getRetryCount() +
- " nextReconnectDelay=" + nextReconnectDelay);
- }
- }
- startAlarmForReconnect(nextReconnectDelay, apnContext);
-
- if (!shouldPostNotification(lastFailCauseCode)) {
- if (DBG) {
- log("reconnectAfterFail: NOT Posting GPRS Unavailable notification "
- + "-- likely transient error");
- }
- } else {
- apnContext.setState(DctConstants.State.FAILED);
- notifyNoData(lastFailCauseCode, apnContext);
- }
- }
- }
-
private void startAlarmForReconnect(int delay, ApnContext apnContext) {
+ DataConnectionAc dcac = apnContext.getDcAc();
- DataConnectionAc dcac = apnContext.getDataConnectionAc();
-
- if ((dcac == null) || (dcac.dataConnection == null)) {
+ if (dcac == null) {
// should not happen, but just in case.
loge("startAlarmForReconnect: null dcac or dc.");
return;
}
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
-
Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' +
- dcac.dataConnection.getDataConnectionId());
+ dcac.getDataConnectionIdSync());
String reason = apnContext.getReason();
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
String apnType = apnContext.getApnType();
intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnType);
- // TODO: Until a real fix is created, which probably entails pushing
- // retires into the DC itself, this fix gets the retry count and
- // puts it in the reconnect alarm. When the reconnect alarm fires
- // onActionIntentReconnectAlarm is called which will use the value saved
- // here and save it in the ApnContext and send the EVENT_CONNECT message
- // which invokes setupData. Then setupData will use the value in the ApnContext
- // and to tell the DC to set the retry count in the retry manager.
- int retryCount = dcac.dataConnection.getRetryCount();
- intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT, retryCount);
+ PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
+ intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ apnContext.setReconnectIntent(alarmIntent);
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delay, alarmIntent);
+ }
- if (DBG) {
- log("startAlarmForReconnect: next attempt in " + (delay / 1000) + "s" +
- " reason='" + reason + "' apnType=" + apnType +
- " retryCount=" + retryCount);
- }
+ private void startAlarmForRestartTrySetup(int delay, ApnContext apnContext) {
+ Intent intent = new Intent(INTENT_RESTART_TRYSETUP_ALARM);
+ String apnType = apnContext.getApnType();
+ intent.putExtra(INTENT_RESTART_TRYSETUP_ALARM_EXTRA_TYPE, apnType);
PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
- dcac.setReconnectIntentSync(alarmIntent);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ apnContext.setReconnectIntent(alarmIntent);
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + delay, alarmIntent);
-
}
- private void notifyNoData(DataConnectionBase.FailCause lastFailCauseCode,
+ private void notifyNoData(DcFailCause lastFailCauseCode,
ApnContext apnContext) {
if (DBG) log( "notifyNoData: type=" + apnContext.getApnType());
if (lastFailCauseCode.isPermanentFail()
@@ -1574,7 +1222,7 @@
if (DBG) log("onRecordsLoaded: notifying data availability");
notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
}
- setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
+ setupDataOnConnectableApns(Phone.REASON_SIM_LOADED);
}
@Override
@@ -1631,62 +1279,75 @@
if (trySetup) trySetupData(apnContext);
}
- private DataConnectionBase checkForConnectionForApnContext(ApnContext apnContext) {
- // Loop through all apnContexts looking for one with a conn that satisfies this apnType
+ private DataConnectionAc checkForCompatibleConnectedApnContext(ApnContext apnContext) {
String apnType = apnContext.getApnType();
ApnSetting dunSetting = null;
if (PhoneConstants.APN_TYPE_DUN.equals(apnType)) {
dunSetting = fetchDunApn();
}
+ if (DBG) {
+ log("checkForCompatibleConnectedApnContext: apnContext=" + apnContext );
+ }
- DataConnectionBase potential = null;
- for (ApnContext c : mApnContexts.values()) {
- DataConnectionBase conn = c.getDataConnection();
- if (conn != null) {
- ApnSetting apnSetting = c.getApnSetting();
+ DataConnectionAc potentialDcac = null;
+ ApnContext potentialApnCtx = null;
+ for (ApnContext curApnCtx : mApnContexts.values()) {
+ DataConnectionAc curDcac = curApnCtx.getDcAc();
+ if (curDcac != null) {
+ ApnSetting apnSetting = curApnCtx.getApnSetting();
if (dunSetting != null) {
if (dunSetting.equals(apnSetting)) {
- switch (c.getState()) {
+ switch (curApnCtx.getState()) {
case CONNECTED:
if (DBG) {
- log("checkForConnectionForApnContext: apnContext=" +
- apnContext + " found conn=" + conn);
+ log("checkForCompatibleConnectedApnContext:"
+ + " found dun conn=" + curDcac
+ + " curApnCtx=" + curApnCtx);
}
- return conn;
+ return curDcac;
+ case RETRYING:
case CONNECTING:
- potential = conn;
+ potentialDcac = curDcac;
+ potentialApnCtx = curApnCtx;
default:
// Not connected, potential unchanged
break;
}
}
} else if (apnSetting != null && apnSetting.canHandleType(apnType)) {
- switch (c.getState()) {
+ switch (curApnCtx.getState()) {
case CONNECTED:
if (DBG) {
- log("checkForConnectionForApnContext: apnContext=" + apnContext +
- " found conn=" + conn);
+ log("checkForCompatibleConnectedApnContext:"
+ + " found canHandle conn=" + curDcac
+ + " curApnCtx=" + curApnCtx);
}
- return conn;
+ return curDcac;
+ case RETRYING:
case CONNECTING:
- potential = conn;
+ potentialDcac = curDcac;
+ potentialApnCtx = curApnCtx;
default:
// Not connected, potential unchanged
break;
}
}
+ } else {
+ if (VDBG) {
+ log("checkForCompatibleConnectedApnContext: not conn curApnCtx=" + curApnCtx);
+ }
}
}
- if (potential != null) {
+ if (potentialDcac != null) {
if (DBG) {
- log("checkForConnectionForApnContext: apnContext=" + apnContext +
- " found conn=" + potential);
+ log("checkForCompatibleConnectedApnContext: found potential conn=" + potentialDcac
+ + " curApnCtx=" + potentialApnCtx);
}
- return potential;
+ return potentialDcac;
}
- if (DBG) log("checkForConnectionForApnContext: apnContext=" + apnContext + " NO conn");
+ if (DBG) log("checkForCompatibleConnectedApnContext: NO conn apnContext=" + apnContext);
return null;
}
@@ -1706,7 +1367,7 @@
// TODO: We shouldnt need this.
protected boolean onTrySetupData(String reason) {
if (DBG) log("onTrySetupData: reason=" + reason);
- setupDataOnReadyApns(reason);
+ setupDataOnConnectableApns(reason);
return true;
}
@@ -1723,7 +1384,7 @@
if (getDataOnRoamingEnabled() == false) {
notifyOffApnsOfAvailability(Phone.REASON_ROAMING_OFF);
- setupDataOnReadyApns(Phone.REASON_ROAMING_OFF);
+ setupDataOnConnectableApns(Phone.REASON_ROAMING_OFF);
} else {
notifyDataConnection(Phone.REASON_ROAMING_OFF);
}
@@ -1735,7 +1396,7 @@
if (getDataOnRoamingEnabled()) {
if (DBG) log("onRoamingOn: setup data on roaming");
- setupDataOnReadyApns(Phone.REASON_ROAMING_ON);
+ setupDataOnConnectableApns(Phone.REASON_ROAMING_ON);
notifyDataConnection(Phone.REASON_ROAMING_ON);
} else {
if (DBG) log("onRoamingOn: Tear down data connection on roaming.");
@@ -1771,7 +1432,6 @@
// Make sure our reconnect delay starts at the initial value
// next time the radio comes on
- resetAllRetryCounts();
mReregisterOnReconnectFailure = false;
if (mPhone.getSimulatedRadioControl() != null) {
@@ -1785,10 +1445,14 @@
notifyOffApnsOfAvailability(null);
}
+ /**
+ * A SETUP (aka bringUp) has completed, possibly with an error. If
+ * there is an error this method will call {@link #onDataSetupCompleteError}.
+ */
@Override
protected void onDataSetupComplete(AsyncResult ar) {
- DataConnectionBase.FailCause cause = DataConnectionBase.FailCause.UNKNOWN;
+ DcFailCause cause = DcFailCause.UNKNOWN;
boolean handleError = false;
ApnContext apnContext = null;
@@ -1799,14 +1463,14 @@
}
if (ar.exception == null) {
- DataConnectionAc dcac = apnContext.getDataConnectionAc();
+ DataConnectionAc dcac = apnContext.getDcAc();
if (RADIO_TESTS) {
// Note: To change radio.test.onDSC.null.dcac from command line you need to
// adb root and adb remount and from the command line you can only change the
// value to 1 once. To change it a second time you can reboot or execute
// adb shell stop and then adb shell start. The command line to set the value is:
- // adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "insert into system (name,value) values ('radio.test.onDSC.null.dcac', '1');"
+ // adb shell sqlite3 /data/data/com.android.providers.settings/databases/settings.db "insert into system (name,value) values ('radio.test.onDSC.null.dcac', '1');"
ContentResolver cr = mPhone.getContext().getContentResolver();
String radioTestProperty = "radio.test.onDSC.null.dcac";
if (Settings.System.getInt(cr, radioTestProperty, 0) == 1) {
@@ -1821,10 +1485,9 @@
}
if (dcac == null) {
log("onDataSetupComplete: no connection to DC, handle as error");
- cause = DataConnectionBase.FailCause.CONNECTION_TO_DATACONNECTIONAC_BROKEN;
+ cause = DcFailCause.CONNECTION_TO_DATACONNECTIONAC_BROKEN;
handleError = true;
} else {
- DataConnectionBase dc = apnContext.getDataConnection();
ApnSetting apn = apnContext.getApnSetting();
if (DBG) {
log("onDataSetupComplete: success apn=" + (apn == null ? "unknown" : apn.apn));
@@ -1844,7 +1507,7 @@
// everything is setup
if(TextUtils.equals(apnContext.getApnType(),PhoneConstants.APN_TYPE_DEFAULT)) {
- SystemProperties.set("gsm.defaultpdpcontext.active", "true");
+ SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "true");
if (mCanSetPreferApn && mPreferredApn == null) {
if (DBG) log("onDataSetupComplete: PREFERED APN is null");
mPreferredApn = apn;
@@ -1853,12 +1516,12 @@
}
}
} else {
- SystemProperties.set("gsm.defaultpdpcontext.active", "false");
+ SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "false");
}
notifyDefaultData(apnContext);
}
} else {
- cause = (DataConnectionBase.FailCause) (ar.result);
+ cause = (DcFailCause) (ar.result);
if (DBG) {
ApnSetting apn = apnContext.getApnSetting();
log(String.format("onDataSetupComplete: error apn=%s cause=%s",
@@ -1885,38 +1548,50 @@
}
if (handleError) {
- // See if there are more APN's to try
- if (apnContext.getWaitingApns().isEmpty()) {
- if (apnContext.getWaitingApnsPermFailCount() == 0) {
- if (DBG) {
- log("onDataSetupComplete: All APN's had permanent failures, stop retrying");
- }
- apnContext.setState(DctConstants.State.FAILED);
- mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
+ onDataSetupCompleteError(ar);
+ }
+ }
- apnContext.setDataConnection(null);
- apnContext.setDataConnectionAc(null);
- } else {
- if (DBG) log("onDataSetupComplete: Not all permanent failures, retry");
- // check to see if retry should be overridden for this failure.
- int retryOverride = -1;
- if (ar.exception instanceof DataConnectionBase.CallSetupException) {
- retryOverride =
- ((DataConnectionBase.CallSetupException)ar.exception).getRetryOverride();
- }
- if (retryOverride == RILConstants.MAX_INT) {
- if (DBG) log("No retry is suggested.");
- } else {
- startDelayedRetry(cause, apnContext, retryOverride);
- }
+ /**
+ * Error has occurred during the SETUP {aka bringUP} request and the DCT
+ * should either try the next waiting APN or start over from the
+ * beginning if the list is empty. Between each SETUP request there will
+ * be a delay defined by {@link #APN_DELAY_MILLIS}.
+ */
+ @Override
+ protected void onDataSetupCompleteError(AsyncResult ar) {
+ String reason = "";
+ ApnContext apnContext = null;
+
+ if(ar.userObj instanceof ApnContext){
+ apnContext = (ApnContext)ar.userObj;
+ } else {
+ throw new RuntimeException("onDataSetupCompleteError: No apnContext");
+ }
+
+ // See if there are more APN's to try
+ if (apnContext.getWaitingApns().isEmpty()) {
+ apnContext.setState(DctConstants.State.FAILED);
+ mPhone.notifyDataConnection(Phone.REASON_APN_FAILED, apnContext.getApnType());
+
+ apnContext.setDataConnectionAc(null);
+
+ if (apnContext.getWaitingApnsPermFailCount() == 0) {
+ if (DBG) {
+ log("onDataSetupComplete: All APN's had permanent failures, stop retrying");
}
} else {
- if (DBG) log("onDataSetupComplete: Try next APN");
- apnContext.setState(DctConstants.State.SCANNING);
- // Wait a bit before trying the next APN, so that
- // we're not tying up the RIL command channel
- startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
+ if (DBG) {
+ log("onDataSetupComplete: Not all APN's had permanent failures, retry");
+ }
+ startAlarmForRestartTrySetup(APN_DELAY_MILLIS, apnContext);
}
+ } else {
+ if (DBG) log("onDataSetupComplete: Try next APN");
+ apnContext.setState(DctConstants.State.SCANNING);
+ // Wait a bit before trying the next APN, so that
+ // we're not tying up the RIL command channel
+ startAlarmForReconnect(APN_DELAY_MILLIS, apnContext);
}
}
@@ -1945,7 +1620,6 @@
if (mPhone.getServiceStateTracker().processPendingRadioPowerOffAfterDataOff()) {
// Radio will be turned off. No need to retry data setup
apnContext.setApnSetting(null);
- apnContext.setDataConnection(null);
apnContext.setDataConnectionAc(null);
return;
}
@@ -1953,18 +1627,38 @@
// 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
+ SystemProperties.set(PUPPET_MASTER_RADIO_STRESS_TEST, "false");
// 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);
} else {
apnContext.setApnSetting(null);
- apnContext.setDataConnection(null);
apnContext.setDataConnectionAc(null);
}
}
+ /**
+ * Called when EVENT_DISCONNECT_DC_RETRYING is received.
+ */
+ @Override
+ protected void onDisconnectDcRetrying(int connId, AsyncResult ar) {
+ // We could just do this in DC!!!
+ ApnContext apnContext = null;
+
+ if (ar.userObj instanceof ApnContext) {
+ apnContext = (ApnContext) ar.userObj;
+ } else {
+ loge("onDisconnectDcRetrying: Invalid ar in onDisconnectDone, ignore");
+ return;
+ }
+
+ apnContext.setState(DctConstants.State.RETRYING);
+ if(DBG) log("onDisconnectDcRetrying: apnContext=" + apnContext);
+
+ mPhone.notifyDataConnection(apnContext.getReason(), apnContext.getApnType());
+ }
+
protected void onPollPdp() {
if (getOverallState() == DctConstants.State.CONNECTED) {
// only poll when connected
@@ -1998,7 +1692,7 @@
}
}
// reset reconnect timer
- setupDataOnReadyApns(Phone.REASON_VOICE_CALL_ENDED);
+ setupDataOnConnectableApns(Phone.REASON_VOICE_CALL_ENDED);
}
@Override
@@ -2014,7 +1708,7 @@
@Override
protected boolean isConnected() {
for (ApnContext apnContext : mApnContexts.values()) {
- if (apnContext.getState() ==DctConstants.State.CONNECTED) {
+ if (apnContext.getState() == DctConstants.State.CONNECTED) {
// At least one context is connected, return true
return true;
}
@@ -2053,7 +1747,7 @@
* Data Connections and setup the preferredApn.
*/
private void createAllApnList() {
- mAllApns = new ArrayList<ApnSetting>();
+ mAllApnSettings = new ArrayList<ApnSetting>();
IccRecords r = mIccRecords.get();
String operator = (r != null) ? r.getOperatorNumeric() : "";
if (operator != null) {
@@ -2068,16 +1762,16 @@
if (cursor != null) {
if (cursor.getCount() > 0) {
- mAllApns = createApnList(cursor);
+ mAllApnSettings = createApnList(cursor);
}
cursor.close();
}
}
- if (mAllApns.isEmpty()) {
+ if (mAllApnSettings.isEmpty()) {
if (DBG) log("createAllApnList: No APN found for carrier: " + operator);
mPreferredApn = null;
- // TODO: What is the right behaviour?
+ // TODO: What is the right behavior?
//notifyNoData(DataConnection.FailCause.MISSING_UNKNOWN_APN);
} else {
mPreferredApn = getPreferredApn();
@@ -2087,60 +1781,33 @@
}
if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
}
- if (DBG) log("createAllApnList: X mAllApns=" + mAllApns);
+ if (DBG) log("createAllApnList: X mAllApnSettings=" + mAllApnSettings);
}
- /** Return the id for a new data connection */
- private DataConnection createDataConnection() {
+ /** Return the DC AsyncChannel for the new data connection */
+ private DataConnectionAc createDataConnection() {
if (DBG) log("createDataConnection E");
- RetryManager rm = new RetryManager();
int id = mUniqueIdGenerator.getAndIncrement();
- DataConnection conn = DataConnection.makeDataConnection(mPhone, id, rm, this);
+ DataConnection conn = DataConnection.makeDataConnection(mPhone, id,
+ this, mDcTesterFailBringUpAll, mDcc);
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);
+ mDataConnectionAcHashMap.put(dcac.getDataConnectionIdSync(), dcac);
} else {
- loge("createDataConnection: Could not connect to dcac.mDc=" + dcac.dataConnection +
- " status=" + status);
+ loge("createDataConnection: Could not connect to dcac=" + dcac + " status=" + status);
}
// install reconnect intent filter for this data connection.
IntentFilter filter = new IntentFilter();
filter.addAction(INTENT_RECONNECT_ALARM + '.' + id);
+ filter.addAction(INTENT_RESTART_TRYSETUP_ALARM);
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
if (DBG) log("createDataConnection() X id=" + id + " dc=" + conn);
- return conn;
- }
-
- private void configureRetry(DataConnectionBase dc, boolean forDefault, int retryCount) {
- if (DBG) {
- log("configureRetry: forDefault=" + forDefault + " retryCount=" + retryCount +
- " dc=" + dc);
- }
- if (dc == null) return;
-
- if (!dc.configureRetry(getReryConfig(forDefault))) {
- if (forDefault) {
- if (!dc.configureRetry(DEFAULT_DATA_RETRY_CONFIG)) {
- // Should never happen, log an error and default to a simple linear sequence.
- loge("configureRetry: Could not configure using " +
- "DEFAULT_DATA_RETRY_CONFIG=" + DEFAULT_DATA_RETRY_CONFIG);
- dc.configureRetry(20, 2000, 1000);
- }
- } else {
- if (!dc.configureRetry(SECONDARY_DATA_RETRY_CONFIG)) {
- // Should never happen, log an error and default to a simple sequence.
- loge("configureRetry: Could note configure using " +
- "SECONDARY_DATA_RETRY_CONFIG=" + SECONDARY_DATA_RETRY_CONFIG);
- dc.configureRetry("max_retries=3, 333, 333, 333");
- }
- }
- }
- dc.setRetryCount(retryCount);
+ return dcac;
}
private void destroyDataConnections() {
@@ -2219,9 +1886,9 @@
mPreferredApn = null;
}
}
- if (mAllApns != null) {
- if (DBG) log("buildWaitingApns: mAllApns=" + mAllApns);
- for (ApnSetting apn : mAllApns) {
+ if (mAllApnSettings != null) {
+ if (DBG) log("buildWaitingApns: mAllApnSettings=" + mAllApnSettings);
+ for (ApnSetting apn : mAllApnSettings) {
if (DBG) log("buildWaitingApns: apn=" + apn);
if (apn.canHandleType(requestedApnType)) {
if (apn.bearer == 0 || apn.bearer == radioTech) {
@@ -2241,7 +1908,7 @@
}
}
} else {
- loge("mAllApns is empty!");
+ loge("mAllApnSettings is empty!");
}
if (DBG) log("buildWaitingApns: X apnList=" + apnList);
return apnList;
@@ -2257,13 +1924,6 @@
return result.toString();
}
- private void startDelayedRetry(DataConnection.FailCause cause,
- ApnContext apnContext, int retryOverride) {
- apnContext.setState(DctConstants.State.FAILED);
- notifyNoData(cause, apnContext);
- reconnectAfterFail(cause, apnContext, retryOverride);
- }
-
private void setPreferredApn(int pos) {
if (!mCanSetPreferApn) {
log("setPreferredApn: X !canSEtPreferApn");
@@ -2283,8 +1943,8 @@
}
private ApnSetting getPreferredApn() {
- if (mAllApns.isEmpty()) {
- log("getPreferredApn: X not found mAllApns.isEmpty");
+ if (mAllApnSettings.isEmpty()) {
+ log("getPreferredApn: X not found mAllApnSettings.isEmpty");
return null;
}
@@ -2304,7 +1964,7 @@
int pos;
cursor.moveToFirst();
pos = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID));
- for(ApnSetting p:mAllApns) {
+ for(ApnSetting p : mAllApnSettings) {
log("getPreferredApn: apnSetting=" + p);
if (p.id == pos && p.canHandleType(mRequestedApnType)) {
log("getPreferredApn: X found apnSetting" + p);
@@ -2385,14 +2045,14 @@
startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
} else {
// TODO: Should all PDN states be checked to fail?
- if (mState ==DctConstants.State.FAILED) {
+ if (mState == DctConstants.State.FAILED) {
cleanUpAllConnections(false, Phone.REASON_PS_RESTRICT_ENABLED);
- resetAllRetryCounts();
mReregisterOnReconnectFailure = false;
}
trySetupData(Phone.REASON_PS_RESTRICT_ENABLED, PhoneConstants.APN_TYPE_DEFAULT);
}
break;
+
case DctConstants.EVENT_TRY_SETUP_DATA:
if (msg.obj instanceof ApnContext) {
onTrySetupData((ApnContext)msg.obj);
@@ -2409,9 +2069,11 @@
if (msg.obj instanceof ApnContext) {
cleanUpConnection(tearDown, (ApnContext)msg.obj);
} else {
- loge("EVENT_CLEAN_UP_CONNECTION request w/o apn context");
+ loge("EVENT_CLEAN_UP_CONNECTION request w/o apn context, call super");
+ super.handleMessage(msg);
}
break;
+
default:
// handle the message in the super class DataConnectionTracker
super.handleMessage(msg);
@@ -2471,12 +2133,12 @@
@Override
protected void log(String s) {
- Rlog.d(LOG_TAG, "[GsmDCT] "+ s);
+ Rlog.d(LOG_TAG, s);
}
@Override
protected void loge(String s) {
- Rlog.e(LOG_TAG, "[GsmDCT] " + s);
+ Rlog.e(LOG_TAG, s);
}
@Override
@@ -2487,6 +2149,6 @@
pw.println(" canSetPreferApn=" + mCanSetPreferApn);
pw.println(" mApnObserver=" + mApnObserver);
pw.println(" getOverallState=" + getOverallState());
- pw.println(" mDataConnectionAsyncChannels=%s\n" + mDataConnectionAsyncChannels);
+ pw.println(" mDataConnectionAsyncChannels=%s\n" + mDataConnectionAcHashMap);
}
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnectionTrackerBase.java b/src/java/com/android/internal/telephony/dataconnection/DataConnectionTrackerBase.java
index 66eb400..b302930 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnectionTrackerBase.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnectionTrackerBase.java
@@ -33,6 +33,7 @@
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Message;
import android.os.Messenger;
import android.os.SystemClock;
@@ -70,7 +71,8 @@
*/
public abstract class DataConnectionTrackerBase extends Handler {
protected static final boolean DBG = true;
- protected static final boolean VDBG = false;
+ protected static final boolean VDBG = false; // STOPSHIP if true
+ protected static final boolean VDBG_STALL = true; // STOPSHIP if true
protected static final boolean RADIO_TESTS = false;
/**
@@ -86,6 +88,8 @@
protected static final int APN_DELAY_MILLIS =
SystemProperties.getInt("persist.radio.apn_delay", 5000);
+ AlarmManager mAlarmManager;
+
protected Object mDataEnabledLock = new Object();
// responds to the setInternalDataEnabled call - used internally to turn off data
@@ -155,17 +159,27 @@
protected String RADIO_RESET_PROPERTY = "gsm.radioreset";
-
- // TODO: See if we can remove INTENT_RECONNECT_ALARM
- // having to have different values for GSM and
- // CDMA. If so we can then remove the need for
- // getActionIntentReconnectAlarm.
+ protected static final String INTENT_RECONNECT_ALARM =
+ "com.android.internal.telephony.data-reconnect";
+ protected static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "reconnect_alarm_extra_type";
protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON =
- "reconnect_alarm_extra_reason";
+ "reconnect_alarm_extra_reason";
+
+ protected static final String INTENT_RESTART_TRYSETUP_ALARM =
+ "com.android.internal.telephony.data-restart-trysetup";
+ protected static final String INTENT_RESTART_TRYSETUP_ALARM_EXTRA_TYPE =
+ "restart_trysetup_alarm_extra_type";
+
+ protected static final String INTENT_DATA_STALL_ALARM =
+ "com.android.internal.telephony.data-stall";
+
protected static final String DEFALUT_DATA_ON_BOOT_PROP = "net.def_data_on_boot";
+ protected DcTesterFailBringUpAll mDcTesterFailBringUpAll;
+ protected DcController mDcc;
+
// member variables
protected PhoneBase mPhone;
protected UiccController mUiccController;
@@ -210,11 +224,11 @@
protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0);
/** The data connections. */
- protected HashMap<Integer, DataConnectionBase> mDataConnections =
- new HashMap<Integer, DataConnectionBase>();
+ protected HashMap<Integer, DataConnection> mDataConnections =
+ new HashMap<Integer, DataConnection>();
/** The data connection async channels */
- protected HashMap<Integer, DataConnectionAc> mDataConnectionAsyncChannels =
+ protected HashMap<Integer, DataConnectionAc> mDataConnectionAcHashMap =
new HashMap<Integer, DataConnectionAc>();
/** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */
@@ -229,7 +243,7 @@
protected ApnSetting mActiveApn;
/** allApns holds all apns */
- protected ArrayList<ApnSetting> mAllApns = null;
+ protected ArrayList<ApnSetting> mAllApnSettings = null;
/** preferred apn */
protected ApnSetting mPreferredApn = null;
@@ -259,10 +273,13 @@
stopNetStatPoll();
startNetStatPoll();
restartDataStallAlarm();
- } else if (action.startsWith(getActionIntentReconnectAlarm())) {
+ } else if (action.startsWith(INTENT_RECONNECT_ALARM)) {
if (DBG) log("Reconnect alarm. Previous state was " + mState);
onActionIntentReconnectAlarm(intent);
- } else if (action.equals(getActionIntentDataStallAlarm())) {
+ } else if (action.startsWith(INTENT_RESTART_TRYSETUP_ALARM)) {
+ if (DBG) log("Restart trySetup alarm");
+ onActionIntentRestartTrySetupAlarm(intent);
+ } else if (action.equals(INTENT_DATA_STALL_ALARM)) {
onActionIntentDataStallAlarm(intent);
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
final android.net.NetworkInfo networkInfo = (NetworkInfo)
@@ -284,7 +301,6 @@
}
};
- private final DataRoamingSettingObserver mDataRoamingSettingObserver;
private Runnable mPollNetStat = new Runnable()
{
@Override
@@ -307,32 +323,52 @@
};
private class DataRoamingSettingObserver extends ContentObserver {
- public DataRoamingSettingObserver(Handler handler) {
+
+ public DataRoamingSettingObserver(Handler handler, Context context) {
super(handler);
+ mResolver = context.getContentResolver();
}
- public void register(Context context) {
- final ContentResolver resolver = context.getContentResolver();
- resolver.registerContentObserver(
+ public void register() {
+ mResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.DATA_ROAMING), false, this);
}
- public void unregister(Context context) {
- final ContentResolver resolver = context.getContentResolver();
- resolver.unregisterContentObserver(this);
+ public void unregister() {
+ mResolver.unregisterContentObserver(this);
}
@Override
public void onChange(boolean selfChange) {
// already running on mPhone handler thread
- handleDataOnRoamingChange();
+ if (mPhone.getServiceState().getRoaming()) {
+ sendMessage(obtainMessage(DctConstants.EVENT_ROAMING_ON));
+ }
}
}
+ private final DataRoamingSettingObserver mDataRoamingSettingObserver;
+
+ /**
+ * The Initial MaxRetry sent to a DataConnection as a parameter
+ * to DataConnectionAc.bringUp. This value can be defined at compile
+ * time using the SystemProperty Settings.Global.DCT_INITIAL_MAX_RETRY
+ * and at runtime using gservices to change Settings.Global.DCT_INITIAL_MAX_RETRY.
+ */
+ private static final int DEFAULT_MDC_INITIAL_RETRY = 1;
+ protected int getInitialMaxRetry() {
+ // Get default value from system property or use DEFAULT_MDC_INITIAL_RETRY
+ int value = SystemProperties.getInt(
+ Settings.Global.MDC_INITIAL_MAX_RETRY, DEFAULT_MDC_INITIAL_RETRY);
+
+ // Check if its been overridden
+ return Settings.Global.getInt(mResolver,
+ Settings.Global.MDC_INITIAL_MAX_RETRY, value);
+ }
/**
- * Maintian the sum of transmit and receive packets.
+ * Maintain the sum of transmit and receive packets.
*
- * The packet counts are initizlied and reset to -1 and
+ * The packet counts are initialized and reset to -1 and
* remain -1 until they can be updated.
*/
public class TxRxSum {
@@ -371,18 +407,47 @@
protected void onActionIntentReconnectAlarm(Intent intent) {
String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
- if (mState == DctConstants.State.FAILED) {
- Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 0; // tearDown is false
- msg.arg2 = 0;
- msg.obj = reason;
- sendMessage(msg);
+ String apnType = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE);
+
+ ApnContext apnContext = mApnContexts.get(apnType);
+
+ if (DBG) {
+ log("onActionIntentReconnectAlarm: mState=" + mState + " reason=" + reason +
+ " apnType=" + apnType + " apnContext=" + apnContext +
+ " mDataConnectionAsyncChannels=" + mDataConnectionAcHashMap);
}
- sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA));
+
+ if ((apnContext != null) && (apnContext.isEnabled())) {
+ apnContext.setReason(reason);
+ DctConstants.State apnContextState = apnContext.getState();
+ if (DBG) {
+ log("onActionIntentReconnectAlarm: apnContext state=" + apnContextState);
+ }
+ if ((apnContextState == DctConstants.State.FAILED)
+ || (apnContextState == DctConstants.State.IDLE)) {
+ if (DBG) {
+ log("onActionIntentReconnectAlarm: state is FAILED|IDLE, disassociate");
+ }
+ apnContext.setDataConnectionAc(null);
+ apnContext.setState(DctConstants.State.IDLE);
+ } else {
+ if (DBG) log("onActionIntentReconnectAlarm: keep associated");
+ }
+ // TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA???
+ sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
+
+ apnContext.setReconnectIntent(null);
+ }
+ }
+
+ protected void onActionIntentRestartTrySetupAlarm(Intent intent) {
+ String apnType = intent.getStringExtra(INTENT_RESTART_TRYSETUP_ALARM_EXTRA_TYPE);
+ ApnContext apnContext = mApnContexts.get(apnType);
+ sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
}
protected void onActionIntentDataStallAlarm(Intent intent) {
- if (VDBG) log("onActionIntentDataStallAlarm: action=" + intent.getAction());
+ if (VDBG_STALL) log("onActionIntentDataStallAlarm: action=" + intent.getAction());
Message msg = obtainMessage(DctConstants.EVENT_DATA_STALL_ALARM,
intent.getAction());
msg.arg1 = intent.getIntExtra(DATA_STALL_ALARM_TAG_EXTRA, 0);
@@ -396,22 +461,24 @@
super();
if (DBG) log("DCT.constructor");
mPhone = phone;
+ mResolver = mPhone.getContext().getContentResolver();
mUiccController = UiccController.getInstance();
mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null);
+ mAlarmManager =
+ (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+
IntentFilter filter = new IntentFilter();
- filter.addAction(getActionIntentReconnectAlarm());
+ filter.addAction(INTENT_RECONNECT_ALARM);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- filter.addAction(getActionIntentDataStallAlarm());
+ filter.addAction(INTENT_DATA_STALL_ALARM);
mUserDataEnabled = Settings.Global.getInt(
mPhone.getContext().getContentResolver(), Settings.Global.MOBILE_DATA, 1) == 1;
- // TODO: Why is this registering the phone as the receiver of the intent
- // and not its own handler?
mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
// This preference tells us 1) initial condition for "dataEnabled",
@@ -426,23 +493,29 @@
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false);
- // watch for changes to Settings.Global.DATA_ROAMING
- mDataRoamingSettingObserver = new DataRoamingSettingObserver(mPhone);
- mDataRoamingSettingObserver.register(mPhone.getContext());
+ // Watch for changes to Settings.Global.DATA_ROAMING
+ mDataRoamingSettingObserver = new DataRoamingSettingObserver(mPhone, mPhone.getContext());
+ mDataRoamingSettingObserver.register();
- mResolver = mPhone.getContext().getContentResolver();
+ HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread");
+ dcHandlerThread.start();
+ Handler dcHandler = new Handler(dcHandlerThread.getLooper());
+ mDcc = DcController.makeDcc(mPhone, this, dcHandler);
+ mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler);
}
public void dispose() {
if (DBG) log("DCT.dispose");
- for (DataConnectionAc dcac : mDataConnectionAsyncChannels.values()) {
+ for (DataConnectionAc dcac : mDataConnectionAcHashMap.values()) {
dcac.disconnect();
}
- mDataConnectionAsyncChannels.clear();
+ mDataConnectionAcHashMap.clear();
mIsDisposed = true;
mPhone.getContext().unregisterReceiver(mIntentReceiver);
- mDataRoamingSettingObserver.unregister(mPhone.getContext());
mUiccController.unregisterForIccChanged(this);
+ mDataRoamingSettingObserver.unregister();
+ mDcc.dispose();
+ mDcTesterFailBringUpAll.dispose();
}
protected void broadcastMessenger() {
@@ -529,18 +602,7 @@
}
}
- private void handleDataOnRoamingChange() {
- if (mPhone.getServiceState().getRoaming()) {
- if (getDataOnRoamingEnabled()) {
- resetAllRetryCounts();
- }
- sendMessage(obtainMessage(DctConstants.EVENT_ROAMING_ON));
- }
- }
-
// abstract methods
- protected abstract String getActionIntentReconnectAlarm();
- protected abstract String getActionIntentDataStallAlarm();
protected abstract void restartRadio();
protected abstract void log(String s);
protected abstract void loge(String s);
@@ -556,7 +618,9 @@
protected abstract void onRadioAvailable();
protected abstract void onRadioOffOrNotAvailable();
protected abstract void onDataSetupComplete(AsyncResult ar);
+ protected abstract void onDataSetupCompleteError(AsyncResult ar);
protected abstract void onDisconnectDone(int connId, AsyncResult ar);
+ protected abstract void onDisconnectDcRetrying(int connId, AsyncResult ar);
protected abstract void onVoiceCallStarted();
protected abstract void onVoiceCallEnded();
protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason);
@@ -570,7 +634,7 @@
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
log("DISCONNECTED_CONNECTED: msg=" + msg);
DataConnectionAc dcac = (DataConnectionAc) msg.obj;
- mDataConnectionAsyncChannels.remove(dcac.dataConnection.getDataConnectionId());
+ mDataConnectionAcHashMap.remove(dcac.getDataConnectionIdSync());
dcac.disconnected();
break;
}
@@ -591,9 +655,6 @@
break;
case DctConstants.EVENT_ROAMING_OFF:
- if (getDataOnRoamingEnabled() == false) {
- resetAllRetryCounts();
- }
onRoamingOff();
break;
@@ -614,11 +675,20 @@
onDataSetupComplete((AsyncResult) msg.obj);
break;
+ case DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR:
+ onDataSetupCompleteError((AsyncResult) msg.obj);
+ break;
+
case DctConstants.EVENT_DISCONNECT_DONE:
log("DataConnectoinTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg);
onDisconnectDone(msg.arg1, (AsyncResult) msg.obj);
break;
+ case DctConstants.EVENT_DISCONNECT_DC_RETRYING:
+ log("DataConnectoinTracker.handleMessage: EVENT_DISCONNECT_DC_RETRYING msg=" + msg);
+ onDisconnectDcRetrying(msg.arg1, (AsyncResult) msg.obj);
+ break;
+
case DctConstants.EVENT_VOICE_CALL_STARTED:
onVoiceCallStarted();
break;
@@ -669,10 +739,10 @@
onSetPolicyDataEnabled(enabled);
break;
}
- case DctConstants.EVENT_ICC_CHANGED:
+ case DctConstants.EVENT_ICC_CHANGED: {
onUpdateIcc();
break;
-
+ }
default:
Rlog.e("DATA", "Unidentified event msg=" + msg);
break;
@@ -754,8 +824,7 @@
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
- // TODO - remove this cdma-only hack and support multiple DCs.
- DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
+ DataConnectionAc dcac = mDataConnectionAcHashMap.get(0);
return dcac.getLinkPropertiesSync();
} else {
return new LinkProperties();
@@ -765,8 +834,7 @@
public LinkCapabilities getLinkCapabilities(String apnType) {
int id = apnTypeToId(apnType);
if (isApnIdEnabled(id)) {
- // TODO - remove this cdma-only hack and support multiple DCs.
- DataConnectionAc dcac = mDataConnectionAsyncChannels.get(0);
+ DataConnectionAc dcac = mDataConnectionAcHashMap.get(0);
return dcac.getLinkCapabilitiesSync();
} else {
return new LinkCapabilities();
@@ -789,6 +857,7 @@
switch (mState) {
case IDLE:
break;
+ case RETRYING:
case CONNECTING:
case SCANNING:
mPhone.notifyDataConnection(reason, apnIdToType(apnId),
@@ -802,7 +871,7 @@
PhoneConstants.DataState.CONNECTED);
break;
default:
- // Ingore
+ // Ignore
break;
}
}
@@ -1021,7 +1090,6 @@
mInternalDataEnabled = enabled;
if (enabled) {
log("onSetInternalDataEnabled: changed to enabled, try to setup data call");
- resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
log("onSetInternalDataEnabled: changed to disabled, cleanUpAllConnections");
@@ -1055,7 +1123,6 @@
}
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
- resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
@@ -1075,7 +1142,6 @@
sPolicyDataEnabled = enabled;
if (prevEnabled != getAnyDataEnabled()) {
if (!prevEnabled) {
- resetAllRetryCounts();
onTrySetupData(Phone.REASON_DATA_ENABLED);
} else {
onCleanUpAllConnections(Phone.REASON_DATA_DISABLED);
@@ -1106,15 +1172,6 @@
}
}
- protected void resetAllRetryCounts() {
- for (ApnContext ac : mApnContexts.values()) {
- ac.setRetryCount(0);
- }
- for (DataConnectionBase dc : mDataConnections.values()) {
- dc.resetRetryCount();
- }
- }
-
protected void resetPollStats() {
mTxPkts = -1;
mRxPkts = -1;
@@ -1198,13 +1255,13 @@
public int getRecoveryAction() {
int action = Settings.System.getInt(mPhone.getContext().getContentResolver(),
"radio.data.stall.recovery.action", RecoveryAction.GET_DATA_CALL_LIST);
- if (VDBG) log("getRecoveryAction: " + action);
+ if (VDBG_STALL) log("getRecoveryAction: " + action);
return action;
}
public void putRecoveryAction(int action) {
Settings.System.putInt(mPhone.getContext().getContentResolver(),
"radio.data.stall.recovery.action", action);
- if (VDBG) log("putRecoveryAction: " + action);
+ if (VDBG_STALL) log("putRecoveryAction: " + action);
}
protected boolean isConnected() {
@@ -1274,7 +1331,7 @@
TxRxSum preTxRxSum = new TxRxSum(mDataStallTxRxSum);
mDataStallTxRxSum.updateTxRxSum();
- if (VDBG) {
+ if (VDBG_STALL) {
log("updateDataStallInfo: mDataStallTxRxSum=" + mDataStallTxRxSum +
" preTxRxSum=" + preTxRxSum);
}
@@ -1289,7 +1346,7 @@
}
}
if ( sent > 0 && received > 0 ) {
- if (VDBG) log("updateDataStallInfo: IN/OUT");
+ if (VDBG_STALL) log("updateDataStallInfo: IN/OUT");
mSentSinceLastRecv = 0;
putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST);
} else if (sent > 0 && received == 0) {
@@ -1303,11 +1360,11 @@
" mSentSinceLastRecv=" + mSentSinceLastRecv);
}
} else if (sent == 0 && received > 0) {
- if (VDBG) log("updateDataStallInfo: IN");
+ if (VDBG_STALL) log("updateDataStallInfo: IN");
mSentSinceLastRecv = 0;
putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST);
} else {
- if (VDBG) log("updateDataStallInfo: NONE");
+ if (VDBG_STALL) log("updateDataStallInfo: NONE");
}
}
@@ -1332,7 +1389,7 @@
suspectedStall = DATA_STALL_SUSPECTED;
sendMessage(obtainMessage(DctConstants.EVENT_DO_RECOVERY));
} else {
- if (VDBG) {
+ if (VDBG_STALL) {
log("onDataStallAlarm: tag=" + tag + " Sent " + String.valueOf(mSentSinceLastRecv) +
" pkts since last received, < watchdogTrigger=" + hangWatchdogTrigger);
}
@@ -1358,33 +1415,31 @@
}
mDataStallAlarmTag += 1;
- if (VDBG) {
+ if (VDBG_STALL) {
log("startDataStallAlarm: tag=" + mDataStallAlarmTag +
" delay=" + (delayInMs / 1000) + "s");
}
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
-
- Intent intent = new Intent(getActionIntentDataStallAlarm());
+ Intent intent = new Intent(INTENT_DATA_STALL_ALARM);
intent.putExtra(DATA_STALL_ALARM_TAG_EXTRA, mDataStallAlarmTag);
mDataStallAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
- am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + delayInMs, mDataStallAlarmIntent);
+ } else {
+ if (VDBG_STALL) {
+ log("startDataStallAlarm: NOT started, no connection tag=" + mDataStallAlarmTag);
+ }
}
}
protected void stopDataStallAlarm() {
- AlarmManager am =
- (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
-
- if (VDBG) {
+ if (VDBG_STALL) {
log("stopDataStallAlarm: current tag=" + mDataStallAlarmTag +
" mDataStallAlarmIntent=" + mDataStallAlarmIntent);
}
mDataStallAlarmTag += 1;
if (mDataStallAlarmIntent != null) {
- am.cancel(mDataStallAlarmIntent);
+ mAlarmManager.cancel(mDataStallAlarmIntent);
mDataStallAlarmIntent = null;
}
}
@@ -1396,13 +1451,23 @@
int nextAction = getRecoveryAction();
if (RecoveryAction.isAggressiveRecovery(nextAction)) {
- if (DBG) log("data stall recovery action is pending. not resetting the alarm.");
+ if (DBG) log("restartDataStallAlarm: action is pending. not resetting the alarm.");
return;
}
+ if (VDBG_STALL) log("restartDataStallAlarm: stop then start.");
stopDataStallAlarm();
startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
}
+ void sendCleanUpConnection(boolean tearDown, ApnContext apnContext) {
+ if (DBG)log("sendCleanUpConnection: tearDown=" + tearDown + " apnContext=" + apnContext);
+ Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = tearDown ? 1 : 0;
+ msg.arg2 = 0;
+ msg.obj = apnContext;
+ sendMessage(msg);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("DataConnectionTrackerBase:");
pw.println(" RADIO_TESTS=" + RADIO_TESTS);
@@ -1436,25 +1501,43 @@
pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator);
pw.flush();
pw.println(" ***************************************");
- Set<Entry<Integer, DataConnectionBase> > mDcSet = mDataConnections.entrySet();
- pw.println(" mDataConnections: count=" + mDcSet.size());
- for (Entry<Integer, DataConnectionBase> entry : mDcSet) {
- pw.printf(" *** mDataConnection[%d] \n", entry.getKey());
- entry.getValue().dump(fd, pw, args);
+ DcController dcc = mDcc;
+ if (dcc != null) {
+ dcc.dump(fd, pw, args);
+ } else {
+ pw.println(" mDcc=null");
+ }
+ pw.println(" ***************************************");
+ HashMap<Integer, DataConnection> dcs = mDataConnections;
+ if (dcs != null) {
+ Set<Entry<Integer, DataConnection> > mDcSet = mDataConnections.entrySet();
+ pw.println(" mDataConnections: count=" + mDcSet.size());
+ for (Entry<Integer, DataConnection> entry : mDcSet) {
+ pw.printf(" *** mDataConnection[%d] \n", entry.getKey());
+ entry.getValue().dump(fd, pw, args);
+ }
+ } else {
+ pw.println("mDataConnections=null");
}
pw.println(" ***************************************");
pw.flush();
- Set<Entry<String, Integer>> mApnToDcIdSet = mApnToDataConnectionId.entrySet();
- pw.println(" mApnToDataConnectonId size=" + mApnToDcIdSet.size());
- for (Entry<String, Integer> entry : mApnToDcIdSet) {
- pw.printf(" mApnToDataConnectonId[%s]=%d\n", entry.getKey(), entry.getValue());
+ HashMap<String, Integer> apnToDcId = mApnToDataConnectionId;
+ if (apnToDcId != null) {
+ Set<Entry<String, Integer>> apnToDcIdSet = apnToDcId.entrySet();
+ pw.println(" mApnToDataConnectonId size=" + apnToDcIdSet.size());
+ for (Entry<String, Integer> entry : apnToDcIdSet) {
+ pw.printf(" mApnToDataConnectonId[%s]=%d\n", entry.getKey(), entry.getValue());
+ }
+ } else {
+ pw.println("mApnToDataConnectionId=null");
}
pw.println(" ***************************************");
pw.flush();
- if (mApnContexts != null) {
- Set<Entry<String, ApnContext>> mApnContextsSet = mApnContexts.entrySet();
- pw.println(" mApnContexts size=" + mApnContextsSet.size());
- for (Entry<String, ApnContext> entry : mApnContextsSet) {
+ ConcurrentHashMap<String, ApnContext> apnCtxs = mApnContexts;
+ if (apnCtxs != null) {
+ Set<Entry<String, ApnContext>> apnCtxsSet = apnCtxs.entrySet();
+ pw.println(" mApnContexts size=" + apnCtxsSet.size());
+ for (Entry<String, ApnContext> entry : apnCtxsSet) {
entry.getValue().dump(fd, pw, args);
}
pw.println(" ***************************************");
@@ -1463,14 +1546,15 @@
}
pw.flush();
pw.println(" mActiveApn=" + mActiveApn);
- if (mAllApns != null) {
- pw.println(" mAllApns size=" + mAllApns.size());
- for (int i=0; i < mAllApns.size(); i++) {
- pw.printf(" mAllApns[%d]: %s\n", i, mAllApns.get(i));
+ ArrayList<ApnSetting> apnSettings = mAllApnSettings;
+ if (apnSettings != null) {
+ pw.println(" mAllApnSettings size=" + apnSettings.size());
+ for (int i=0; i < apnSettings.size(); i++) {
+ pw.printf(" mAllApnSettings[%d]: %s\n", i, apnSettings.get(i));
}
pw.flush();
} else {
- pw.println(" mAllApns=null");
+ pw.println(" mAllApnSettings=null");
}
pw.println(" mPreferredApn=" + mPreferredApn);
pw.println(" mIsPsRestricted=" + mIsPsRestricted);
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcController.java b/src/java/com/android/internal/telephony/dataconnection/DcController.java
new file mode 100644
index 0000000..8ffd54c
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/DcController.java
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2013 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.dataconnection;
+
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.net.LinkProperties.CompareResult;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.telephony.Rlog;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.dataconnection.DataConnection.UpdateLinkPropertyResult;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Data Connection Controller which is a package visible class and controls
+ * multiple data connections. For instance listening for unsolicited messages
+ * and then demultiplexing them to the appropriate DC.
+ */
+class DcController extends StateMachine {
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+ protected static final boolean DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+ private PhoneBase mPhone;
+ private DataConnectionTrackerBase mDct;
+ private DcTesterDeactivateAll mDcTesterDeactivateAll;
+
+ // package as its used by Testing code
+ ArrayList<DataConnection> mDcListAll = new ArrayList<DataConnection>();
+ private HashMap<Integer, DataConnection> mDcListActiveByCid =
+ new HashMap<Integer, DataConnection>();
+
+ /**
+ * Constants for the data connection activity:
+ * physical link down/up
+ *
+ * TODO: Move to RILConstants.java
+ */
+ static final int DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE = 0;
+ static final int DATA_CONNECTION_ACTIVE_PH_LINK_DORMANT = 1;
+ static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2;
+
+ private DccDefaultState mDccDefaultState = new DccDefaultState();
+
+ /**
+ * Constructor.
+ *
+ * @param name to be used for the Controller
+ * @param phone the phone associated with Dcc and Dct
+ * @param dct the DataConnectionTracker associated with Dcc
+ * @param handler defines the thread/looper to be used with Dcc
+ */
+ private DcController(String name, PhoneBase phone, DataConnectionTrackerBase dct,
+ Handler handler) {
+ super(name, handler);
+ setLogRecSize(300);
+ log("E ctor");
+ mPhone = phone;
+ mDct = dct;
+ addState(mDccDefaultState);
+ setInitialState(mDccDefaultState);
+ log("X ctor");
+ }
+
+ static DcController makeDcc(PhoneBase phone, DataConnectionTrackerBase dct, Handler handler) {
+ DcController dcc = new DcController("Dcc", phone, dct, handler);
+ dcc.start();
+ return dcc;
+ }
+
+ void dispose() {
+ log("dispose: call quiteNow()");
+ quitNow();
+ }
+
+ void addDc(DataConnection dc) {
+ mDcListAll.add(dc);
+ }
+
+ void removeDc(DataConnection dc) {
+ mDcListActiveByCid.remove(dc.mCid);
+ mDcListAll.remove(dc);
+ }
+
+ void addActiveDcByCid(DataConnection dc) {
+ if (DBG && dc.mCid < 0) {
+ log("addActiveDcByCid dc.mCid < 0 dc=" + dc);
+ }
+ mDcListActiveByCid.put(dc.mCid, dc);
+ }
+
+ void removeActiveDcByCid(DataConnection dc) {
+ DataConnection removedDc = mDcListActiveByCid.remove(dc.mCid);
+ if (DBG && removedDc == null) {
+ log("removeActiveDcByCid removedDc=null dc=" + dc);
+ }
+ }
+
+ private class DccDefaultState extends State {
+ @Override
+ public void enter() {
+ mPhone.mCi.registerForRilConnected(getHandler(),
+ DataConnection.EVENT_RIL_CONNECTED, null);
+ mPhone.mCi.registerForDataNetworkStateChanged(getHandler(),
+ DataConnection.EVENT_DATA_STATE_CHANGED, null);
+ if (DEBUGGABLE) {
+ mDcTesterDeactivateAll =
+ new DcTesterDeactivateAll(mPhone, DcController.this, getHandler());
+ }
+ }
+
+ @Override
+ public void exit() {
+ if (mPhone != null) {
+ mPhone.mCi.unregisterForRilConnected(getHandler());
+ mPhone.mCi.unregisterForDataNetworkStateChanged(getHandler());
+ }
+ if (mDcTesterDeactivateAll != null) {
+ mDcTesterDeactivateAll.dispose();
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ AsyncResult ar;
+
+ switch (msg.what) {
+ case DataConnection.EVENT_RIL_CONNECTED:
+ ar = (AsyncResult)msg.obj;
+ if (ar.exception == null) {
+ if (DBG) {
+ log("DccDefaultState: msg.what=EVENT_RIL_CONNECTED mRilVersion=" +
+ ar.result);
+ }
+ } else {
+ log("DccDefaultState: Unexpected exception on EVENT_RIL_CONNECTED");
+ }
+ break;
+
+ case DataConnection.EVENT_DATA_STATE_CHANGED:
+ ar = (AsyncResult)msg.obj;
+ if (ar.exception == null) {
+ onDataStateChanged((ArrayList<DataCallResponse>)ar.result);
+ } else {
+ log("DccDefaultState: EVENT_DATA_STATE_CHANGED:" +
+ " exception; likely radio not available, ignore");
+ }
+ break;
+ }
+ return HANDLED;
+ }
+
+ /**
+ * Process the new list of "known" Data Calls
+ * @param dcsList as sent by RIL_UNSOL_DATA_CALL_LIST_CHANGED
+ */
+ private void onDataStateChanged(ArrayList<DataCallResponse> dcsList) {
+ if (DBG) {
+ lr("onDataStateChanged: dcsList=" + dcsList
+ + " mDcListActiveByCid=" + mDcListActiveByCid);
+ }
+ if (VDBG) {
+ log("onDataStateChanged: mDcListAll=" + mDcListAll);
+ }
+
+ // Create hashmap of cid to DataCallResponse
+ HashMap<Integer, DataCallResponse> dataCallResponseListByCid =
+ new HashMap<Integer, DataCallResponse>();
+ for (DataCallResponse dcs : dcsList) {
+ dataCallResponseListByCid.put(dcs.cid, dcs);
+ }
+
+ // Add a DC that is active but not in the
+ // dcsList to the list of DC's to retry
+ ArrayList<DataConnection> dcsToRetry = new ArrayList<DataConnection>();
+ for (DataConnection dc : mDcListActiveByCid.values()) {
+ if (dataCallResponseListByCid.get(dc.mCid) == null) {
+ if (DBG) log("onDataStateChanged: add to retry dc=" + dc);
+ dcsToRetry.add(dc);
+ }
+ }
+ if (DBG) log("onDataStateChanged: dcsToRetry=" + dcsToRetry);
+
+ // Find which connections have changed state and send a notification or cleanup
+ // and any that are in active need to be retried.
+ ArrayList<ApnContext> apnsToCleanup = new ArrayList<ApnContext>();
+
+ for (DataCallResponse newState : dcsList) {
+ DataConnection dc = mDcListActiveByCid.get(newState.cid);
+ if (dc == null) {
+ // UNSOL_DATA_CALL_LIST_CHANGED arrived before SETUP_DATA_CALL completed.
+ loge("onDataStateChanged: no associated DC yet, ignore");
+ continue;
+ }
+
+ if (dc.mApnContexts.size() == 0) {
+ if (DBG) loge("onDataStateChanged: no connected apns, ignore");
+ } else {
+ // Determine if the connection/apnContext should be cleaned up
+ // or just a notification should be sent out.
+ if (DBG) log("onDataStateChanged: Found ConnId=" + newState.cid
+ + " newState=" + newState.toString());
+ if (newState.active == DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE) {
+ if (DBG) log("onDataStateChanged: inactive, add to retry list");
+ dcsToRetry.add(dc);
+ } else {
+ // Its active so update the DataConnections link properties
+ UpdateLinkPropertyResult result = dc.updateLinkProperty(newState);
+ if (result.oldLp.equals(result.newLp)) {
+ if (DBG) log("onDataStateChanged: no change");
+ } else {
+ if (result.oldLp.isIdenticalInterfaceName(result.newLp)) {
+ if (! result.oldLp.isIdenticalDnses(result.newLp) ||
+ ! result.oldLp.isIdenticalRoutes(result.newLp) ||
+ ! result.oldLp.isIdenticalHttpProxy(result.newLp) ||
+ ! result.oldLp.isIdenticalAddresses(result.newLp)) {
+ // If the same address type was removed and
+ // added we need to cleanup
+ CompareResult<LinkAddress> car =
+ result.oldLp.compareAddresses(result.newLp);
+ if (DBG) {
+ log("onDataStateChanged: oldLp=" + result.oldLp +
+ " newLp=" + result.newLp + " car=" + car);
+ }
+ boolean needToClean = false;
+ for (LinkAddress added : car.added) {
+ for (LinkAddress removed : car.removed) {
+ if (NetworkUtils.addressTypeMatches(
+ removed.getAddress(),
+ added.getAddress())) {
+ needToClean = true;
+ break;
+ }
+ }
+ }
+ if (needToClean) {
+ if (DBG) {
+ log("onDataStateChanged: addr change," +
+ " cleanup apns=" + dc.mApnContexts +
+ " oldLp=" + result.oldLp +
+ " newLp=" + result.newLp);
+ }
+ apnsToCleanup.addAll(dc.mApnContexts);
+ } else {
+ if (DBG) log("onDataStateChanged: simple change");
+ for (ApnContext apnContext : dc.mApnContexts) {
+ mPhone.notifyDataConnection(
+ PhoneConstants.REASON_LINK_PROPERTIES_CHANGED,
+ apnContext.getApnType());
+ }
+ }
+ } else {
+ if (DBG) {
+ log("onDataStateChanged: no changes");
+ }
+ }
+ } else {
+ apnsToCleanup.addAll(dc.mApnContexts);
+ if (DBG) {
+ log("onDataStateChanged: interface change, cleanup apns="
+ + dc.mApnContexts);
+ }
+ }
+ }
+ }
+ }
+ }
+ mPhone.notifyDataActivity();
+
+ if (DBG) {
+ lr("onDataStateChanged: dcsToRetry=" + dcsToRetry
+ + " apnsToCleanup=" + apnsToCleanup);
+ }
+
+ // Cleanup connections that have changed
+ for (ApnContext apnContext : apnsToCleanup) {
+ mDct.sendCleanUpConnection(true, apnContext);
+ }
+
+ // Retry connections that have disappeared
+ for (DataConnection dc : dcsToRetry) {
+ if (DBG) log("onDataStateChanged: send EVENT_LOST_CONNECTION dc.mTag=" + dc.mTag);
+ dc.sendMessage(DataConnection.EVENT_LOST_CONNECTION, dc.mTag);
+ }
+
+ if (DBG) log("onDataStateChanged: X");
+ }
+ }
+
+ /**
+ * lr is short name for logAndAddLogRec
+ * @param s
+ */
+ private void lr(String s) {
+ logAndAddLogRec(s);
+ }
+
+ @Override
+ protected void log(String s) {
+ Rlog.d(getName(), s);
+ }
+
+ @Override
+ protected void loge(String s) {
+ Rlog.e(getName(), s);
+ }
+
+ /**
+ * @return the string for msg.what as our info.
+ */
+ @Override
+ protected String getWhatToString(int what) {
+ String info = null;
+ info = DataConnection.cmdToString(what);
+ if (info == null) {
+ info = DataConnectionAc.cmdToString(what);
+ }
+ return info;
+ }
+
+ @Override
+ public String toString() {
+ return "mDcListAll=" + mDcListAll + " mDcListActiveByCid=" + mDcListActiveByCid;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ super.dump(fd, pw, args);
+ pw.println(" mPhone=" + mPhone);
+ pw.println(" mDcListAll=" + mDcListAll);
+ pw.println(" mDcListActiveByCid=" + mDcListActiveByCid);
+ }
+}
\ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcFailBringUp.java b/src/java/com/android/internal/telephony/dataconnection/DcFailBringUp.java
new file mode 100644
index 0000000..c891817
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/DcFailBringUp.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2013 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.dataconnection;
+
+import android.content.Intent;
+import android.telephony.Rlog;
+
+/**
+ * A package visible class for supporting testing failing bringUp commands. This
+ * saves the parameters from a action_fail_bringup intent. See
+ * {@link DataConnection#doOnConnect} and {@see DcTesterFailBringUpAll} for more info.
+ */
+class DcFailBringUp {
+ private static final String LOG_TAG = "DcFailBringUp";
+ private static final boolean DBG = true;
+
+ static final String INTENT_BASE = DataConnection.class.getPackage().getName();
+
+ static final String ACTION_FAIL_BRINGUP = "action_fail_bringup";
+
+ // counter with its --ei option name and default value
+ static final String COUNTER = "counter";
+ static final int DEFAULT_COUNTER = 1;
+ int mCounter;
+
+ // failCause with its --ei option name and default value
+ static final String FAIL_CAUSE = "fail_cause";
+ static final DcFailCause DEFAULT_FAIL_CAUSE = DcFailCause.ERROR_UNSPECIFIED;
+ DcFailCause mFailCause;
+
+ // suggestedRetryTime with its --ei option name and default value
+ static final String SUGGESTED_RETRY_TIME = "suggested_retry_time";
+ static final int DEFAULT_SUGGESTED_RETRY_TIME = -1;
+ int mSuggestedRetryTime;
+
+ // Get the Extra Intent parameters
+ void saveParameters(Intent intent, String s) {
+ if (DBG) log(s + ".saveParameters: action=" + intent.getAction());
+ mCounter = intent.getIntExtra(COUNTER, DEFAULT_COUNTER);
+ mFailCause = DcFailCause.fromInt(
+ intent.getIntExtra(FAIL_CAUSE, DEFAULT_FAIL_CAUSE.getErrorCode()));
+ mSuggestedRetryTime =
+ intent.getIntExtra(SUGGESTED_RETRY_TIME, DEFAULT_SUGGESTED_RETRY_TIME);
+ if (DBG) {
+ log(s + ".saveParameters: " + this);
+ }
+ }
+
+ void saveParameters(int counter, int failCause, int suggestedRetryTime) {
+ mCounter = counter;
+ mFailCause = DcFailCause.fromInt(failCause);
+ mSuggestedRetryTime = suggestedRetryTime;
+ }
+
+ @Override
+ public String toString() {
+ return "{mCounter=" + mCounter +
+ " mFailCause=" + mFailCause +
+ " mSuggestedRetryTime=" + mSuggestedRetryTime + "}";
+
+ }
+
+ private static void log(String s) {
+ Rlog.d(LOG_TAG, s);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcFailCause.java b/src/java/com/android/internal/telephony/dataconnection/DcFailCause.java
new file mode 100644
index 0000000..a535e09
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/DcFailCause.java
@@ -0,0 +1,111 @@
+/*
+ * 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.dataconnection;
+
+import java.util.HashMap;
+
+/**
+ * Returned as the reason for a connection failure as defined
+ * by RIL_DataCallFailCause in ril.h and some local errors.
+ */
+public enum DcFailCause {
+ NONE(0),
+
+ // This series of errors as specified by the standards
+ // specified in ril.h
+ OPERATOR_BARRED(0x08),
+ INSUFFICIENT_RESOURCES(0x1A),
+ MISSING_UNKNOWN_APN(0x1B),
+ UNKNOWN_PDP_ADDRESS_TYPE(0x1C),
+ USER_AUTHENTICATION(0x1D),
+ ACTIVATION_REJECT_GGSN(0x1E),
+ ACTIVATION_REJECT_UNSPECIFIED(0x1F),
+ SERVICE_OPTION_NOT_SUPPORTED(0x20),
+ SERVICE_OPTION_NOT_SUBSCRIBED(0x21),
+ SERVICE_OPTION_OUT_OF_ORDER(0x22),
+ NSAPI_IN_USE(0x23),
+ ONLY_IPV4_ALLOWED(0x32),
+ ONLY_IPV6_ALLOWED(0x33),
+ ONLY_SINGLE_BEARER_ALLOWED(0x34),
+ PROTOCOL_ERRORS(0x6F),
+
+ // Local errors generated by Vendor RIL
+ // specified in ril.h
+ REGISTRATION_FAIL(-1),
+ GPRS_REGISTRATION_FAIL(-2),
+ SIGNAL_LOST(-3),
+ PREF_RADIO_TECH_CHANGED(-4),
+ RADIO_POWER_OFF(-5),
+ TETHERED_CALL_ACTIVE(-6),
+ ERROR_UNSPECIFIED(0xFFFF),
+
+ // Errors generated by the Framework
+ // specified here
+ UNKNOWN(0x10000),
+ RADIO_NOT_AVAILABLE(0x10001),
+ UNACCEPTABLE_NETWORK_PARAMETER(0x10002),
+ CONNECTION_TO_DATACONNECTIONAC_BROKEN(0x10003),
+ LOST_CONNECTION(0x10004),
+ RESET_BY_FRAMEWORK(0x10005);
+
+ private final int mErrorCode;
+ private static final HashMap<Integer, DcFailCause> sErrorCodeToFailCauseMap;
+ static {
+ sErrorCodeToFailCauseMap = new HashMap<Integer, DcFailCause>();
+ for (DcFailCause fc : values()) {
+ sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
+ }
+ }
+
+ DcFailCause(int errorCode) {
+ mErrorCode = errorCode;
+ }
+
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+
+ public boolean isPermanentFail() {
+ return (this == OPERATOR_BARRED) || (this == MISSING_UNKNOWN_APN) ||
+ (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
+ (this == ACTIVATION_REJECT_GGSN) || (this == SERVICE_OPTION_NOT_SUPPORTED) ||
+ (this == SERVICE_OPTION_NOT_SUBSCRIBED) || (this == NSAPI_IN_USE) ||
+ (this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
+ (this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
+ (this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE);
+ }
+
+ public boolean isEventLoggable() {
+ return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
+ (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
+ (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
+ (this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
+ (this == SERVICE_OPTION_NOT_SUPPORTED) ||
+ (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
+ (this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
+ (this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
+ (this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE) ||
+ (this == UNACCEPTABLE_NETWORK_PARAMETER);
+ }
+
+ public static DcFailCause fromInt(int errorCode) {
+ DcFailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
+ if (fc == null) {
+ fc = UNKNOWN;
+ }
+ return fc;
+ }
+}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcRetryAlarmController.java b/src/java/com/android/internal/telephony/dataconnection/DcRetryAlarmController.java
new file mode 100644
index 0000000..be5d300
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/DcRetryAlarmController.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 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.dataconnection;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncResult;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.telephony.Rlog;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.RILConstants;
+
+/**
+ * The Data Connection Retry Alarm Controller.
+ */
+public class DcRetryAlarmController {
+ private String mLogTag = "DcRac";
+ private static final boolean DBG = true;
+ protected static final boolean DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+ private PhoneBase mPhone;
+ private DataConnection mDc;
+ private AlarmManager mAlarmManager;
+
+ // The Intent action for retrying and its two extra's
+ private String mActionRetry;
+ private static final String INTENT_RETRY_ALARM_WHAT = "what";
+ private static final String INTENT_RETRY_ALARM_TAG = "tag";
+
+ private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (TextUtils.isEmpty(action)) {
+ // Our mActionXxxx's could be null when disposed this could match an empty action.
+ log("onReceive: ignore empty action='" + action + "'");
+ return;
+ }
+ if (TextUtils.equals(action, mActionRetry)) {
+ if (!intent.hasExtra(INTENT_RETRY_ALARM_WHAT)) {
+ throw new RuntimeException(mActionRetry + " has no INTENT_RETRY_ALRAM_WHAT");
+ }
+ if (!intent.hasExtra(INTENT_RETRY_ALARM_TAG)) {
+ throw new RuntimeException(mActionRetry + " has no INTENT_RETRY_ALRAM_TAG");
+ }
+ int what = intent.getIntExtra(INTENT_RETRY_ALARM_WHAT, Integer.MAX_VALUE);
+ int tag = intent.getIntExtra(INTENT_RETRY_ALARM_TAG, Integer.MAX_VALUE);
+ if (DBG) {
+ log("onReceive: action=" + action
+ + " sendMessage(what:" + mDc.getWhatToString(what)
+ + ", tag:" + tag + ")");
+ }
+ mDc.sendMessage(mDc.obtainMessage(what, tag, 0));
+ } else {
+ if (DBG) log("onReceive: unknown action=" + action);
+ }
+ }
+ };
+
+ DcRetryAlarmController(PhoneBase phone, DataConnection dc) {
+ mLogTag = dc.getName();
+ mPhone = phone;
+ mDc = dc;
+ mAlarmManager = (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
+ mActionRetry = mDc.getClass().getCanonicalName() + "." + mDc.getName() + ".action_retry";
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(mActionRetry);
+ log("DcRetryAlarmController: register for intent action=" + mActionRetry);
+
+ mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mDc.getHandler());
+ }
+
+ /**
+ * Dispose of resources when shutting down
+ */
+ void dispose() {
+ if (DBG) log("dispose");
+ mPhone.getContext().unregisterReceiver(mIntentReceiver);
+ mPhone = null;
+ mDc = null;
+ mAlarmManager = null;
+ mActionRetry = null;
+ }
+
+ /**
+ * Using dc.mRetryManager and the result of the SETUP_DATA_CALL determine
+ * the retry delay.
+ *
+ * @param dc is the DataConnection
+ * @param ar is the result from SETUP_DATA_CALL
+ * @return < 0 if no retry is needed otherwise the delay to the next SETUP_DATA_CALL
+ */
+ int getSuggestedRetryTime(DataConnection dc, AsyncResult ar) {
+ int retryDelay;
+
+ DataCallResponse response = (DataCallResponse) ar.result;
+ retryDelay = response.suggestedRetryTime;
+ if (retryDelay == RILConstants.MAX_INT) {
+ if (DBG) log("getSuggestedRetryTime: suggestedRetryTime is MAX_INT, retry NOT needed");
+ retryDelay = -1;
+ } else if (retryDelay >= 0) {
+ if (DBG) log("getSuggestedRetryTime: suggestedRetryTime is >= 0 use it");
+ } else if (dc.mRetryManager.isRetryNeeded()) {
+ retryDelay = dc.mRetryManager.getRetryTimer();
+ if (retryDelay < 0) {
+ retryDelay = 0;
+ }
+ if (DBG) log("getSuggestedRetryTime: retry is needed");
+ } else {
+ if (DBG) log("getSuggestedRetryTime: retry is NOT needed");
+ retryDelay = -1;
+ }
+
+ if (DBG) {
+ log("getSuggestedRetryTime: " + retryDelay + " response=" + response + " dc=" + dc);
+ }
+ return retryDelay;
+ }
+
+ public void startRetryAlarm(int what, int tag, int delay) {
+ Intent intent = new Intent(mActionRetry);
+ intent.putExtra(INTENT_RETRY_ALARM_WHAT, what);
+ intent.putExtra(INTENT_RETRY_ALARM_TAG, tag);
+
+ if (DBG) {
+ log("startRetryAlarm: next attempt in " + (delay / 1000) + "s" +
+ " what=" + what + " tag=" + tag);
+ }
+
+ PendingIntent retryIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
+ intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delay, retryIntent);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(mLogTag).append(" [dcRac] ");
+ sb.append(" mPhone=").append(mPhone);
+ sb.append(" mDc=").append(mDc);
+ sb.append(" mAlaramManager=").append(mAlarmManager);
+ sb.append(" mActionRetry=").append(mActionRetry);
+ return sb.toString();
+ }
+
+ private void log(String s) {
+ Rlog.d(mLogTag, "[dcRac] " + s);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTesterDeactivateAll.java b/src/java/com/android/internal/telephony/dataconnection/DcTesterDeactivateAll.java
new file mode 100644
index 0000000..87f9d93
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTesterDeactivateAll.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013 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.dataconnection;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.PhoneBase;
+
+/**
+ * To bring down all DC's send the following intent:
+ *
+ * adb shell am broadcast -a com.android.internal.telephony.dataconnection.action_deactivate_all
+ */
+public class DcTesterDeactivateAll {
+ private static final String LOG_TAG = "DcTesterDeacativeAll";
+ private static final boolean DBG = true;
+ private static final boolean DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+ private PhoneBase mPhone;
+ private DcController mDcc;
+
+ public static String sActionDcTesterDeactivateAll =
+ "com.android.internal.telephony.dataconnection.action_deactivate_all";
+
+
+ // The static intent receiver one for all instances and we assume this
+ // is running on the same thread as Dcc.
+ protected BroadcastReceiver sIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (DBG) log("sIntentReceiver.onReceive: action=" + action);
+ if (action.equals(sActionDcTesterDeactivateAll)
+ || action.equals(mPhone.getActionDetached())) {
+ log("Send DEACTIVATE to all Dcc's");
+ if (mDcc != null) {
+ for (DataConnection dc : mDcc.mDcListAll) {
+ dc.tearDownNow();
+ }
+ } else {
+ if (DBG) log("onReceive: mDcc is null, ignoring");
+ }
+ } else {
+ if (DBG) log("onReceive: unknown action=" + action);
+ }
+ }
+ };
+
+ DcTesterDeactivateAll(PhoneBase phone, DcController dcc, Handler handler) {
+ mPhone = phone;
+ mDcc = dcc;
+
+ if (DEBUGGABLE) {
+ IntentFilter filter = new IntentFilter();
+
+ filter.addAction(sActionDcTesterDeactivateAll);
+ log("register for intent action=" + sActionDcTesterDeactivateAll);
+
+ filter.addAction(mPhone.getActionDetached());
+ log("register for intent action=" + mPhone.getActionDetached());
+
+ phone.getContext().registerReceiver(sIntentReceiver, filter, null, handler);
+ }
+ }
+
+ void dispose() {
+ mPhone.getContext().unregisterReceiver(sIntentReceiver);
+ }
+
+ private static void log(String s) {
+ Rlog.d(LOG_TAG, s);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTesterFailBringUpAll.java b/src/java/com/android/internal/telephony/dataconnection/DcTesterFailBringUpAll.java
new file mode 100644
index 0000000..0c86e1c
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTesterFailBringUpAll.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 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.dataconnection;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.telephony.Rlog;
+
+import com.android.internal.telephony.PhoneBase;
+
+/**
+ * A package level call that causes all DataConnection bringUp calls to fail a specific
+ * number of times. Here is an example that sets counter to 2 and cause to -3 for all instances:
+ * adb shell am broadcast -a com.android.internal.telephony.dataconnection.action_fail_bringup \
+ * --ei counter 2 --ei fail_cause -3
+ *
+ * Also you can add a suggested retry time if desired:
+ * --ei suggested_retry_time 5000
+ *
+ * There is also a per DC command implemented in {@link DcRetryAlarmController#mFailBringUp} the intent is
+ * the same as above except the action has a "DC-x" before the action_fail_bringup so for
+ * DC-1 the action action is:
+ * adb shell am broadcast \
+ * -a com.android.internal.telephony.dataconnection.DC-1.action_fail_bringup \
+ * --ei counter 2 --ei fail_cause -3
+ *
+ * The fail_cause is one of {@link DcFailCause}
+ */
+public class DcTesterFailBringUpAll {
+ private static final String LOG_TAG = "DcTesterFailBrinupAll";
+ private static final boolean DBG = true;
+ private static final boolean DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
+
+ private PhoneBase mPhone;
+
+ private String mActionFailBringUp = DcFailBringUp.INTENT_BASE + "."
+ + DcFailBringUp.ACTION_FAIL_BRINGUP;
+
+ // The saved FailBringUp data from the intent
+ private DcFailBringUp mFailBringUp = new DcFailBringUp();
+
+ // The static intent receiver one for all instances.
+ private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (DBG) log("sIntentReceiver.onReceive: action=" + action);
+ if (action.equals(mActionFailBringUp)) {
+ mFailBringUp.saveParameters(intent, "sFailBringUp");
+ } else if (action.equals(mPhone.getActionDetached())) {
+ // Counter is MAX, bringUp/retry will always fail
+ log("simulate detaching");
+ mFailBringUp.saveParameters(Integer.MAX_VALUE,
+ DcFailCause.LOST_CONNECTION.getErrorCode(),
+ DcFailBringUp.DEFAULT_SUGGESTED_RETRY_TIME);
+ } else if (action.equals(mPhone.getActionAttached())) {
+ // Counter is 0 next bringUp/retry will succeed
+ log("simulate attaching");
+ mFailBringUp.saveParameters(0, DcFailCause.NONE.getErrorCode(),
+ DcFailBringUp.DEFAULT_SUGGESTED_RETRY_TIME);
+ } else {
+ if (DBG) log("onReceive: unknown action=" + action);
+ }
+ }
+ };
+
+ DcTesterFailBringUpAll(PhoneBase phone, Handler handler) {
+ mPhone = phone;
+ if (DEBUGGABLE) {
+ IntentFilter filter = new IntentFilter();
+
+ filter.addAction(mActionFailBringUp);
+ log("register for intent action=" + mActionFailBringUp);
+
+ filter.addAction(mPhone.getActionDetached());
+ log("register for intent action=" + mPhone.getActionDetached());
+
+ filter.addAction(mPhone.getActionAttached());
+ log("register for intent action=" + mPhone.getActionAttached());
+
+ phone.getContext().registerReceiver(mIntentReceiver, filter, null, handler);
+ }
+ }
+
+ void dispose() {
+ mPhone.getContext().unregisterReceiver(mIntentReceiver);
+ }
+
+ DcFailBringUp getDcFailBringUp() {
+ return mFailBringUp;
+ }
+
+ private void log(String s) {
+ Rlog.d(LOG_TAG, s);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/gsm/GSMPhone.java b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
index 32e5a80..23967e8 100644
--- a/src/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -132,7 +132,7 @@
public
GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
- super(notifier, context, ci, unitTestMode);
+ super("GSM", notifier, context, ci, unitTestMode);
if (ci instanceof SimulatedRadioControl) {
mSimulatedRadioControl = (SimulatedRadioControl) ci;
@@ -258,11 +258,6 @@
}
@Override
- public String getPhoneName() {
- return "GSM";
- }
-
- @Override
public int getPhoneType() {
return PhoneConstants.PHONE_TYPE_GSM;
}
@@ -320,6 +315,7 @@
}
break;
+ case RETRYING:
case CONNECTING:
case SCANNING:
ret = PhoneConstants.DataState.CONNECTING;
diff --git a/src/java/com/android/internal/telephony/sip/SipConnectionBase.java b/src/java/com/android/internal/telephony/sip/SipConnectionBase.java
index 19d217f..c3f39de 100644
--- a/src/java/com/android/internal/telephony/sip/SipConnectionBase.java
+++ b/src/java/com/android/internal/telephony/sip/SipConnectionBase.java
@@ -29,7 +29,7 @@
abstract class SipConnectionBase extends Connection {
private static final String LOG_TAG = "SipConnBase";
private static final boolean DBG = true;
- private static final boolean VDBG = true; // STOPSHIP if true
+ private static final boolean VDBG = false; // STOPSHIP if true
private String mPostDialString; // outgoing calls only
private int mNextPostDialChar; // index into postDialString
diff --git a/src/java/com/android/internal/telephony/sip/SipPhone.java b/src/java/com/android/internal/telephony/sip/SipPhone.java
index 764c7ef..878fe3f 100644
--- a/src/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhone.java
@@ -49,7 +49,7 @@
public class SipPhone extends SipPhoneBase {
private static final String LOG_TAG = "SipPhone";
private static final boolean DBG = true;
- private static final boolean VDBG = true; // STOPSHIP if true
+ private static final boolean VDBG = false; // STOPSHIP if true
private static final int TIMEOUT_MAKE_CALL = 15; // in seconds
private static final int TIMEOUT_ANSWER_CALL = 8; // in seconds
private static final int TIMEOUT_HOLD_CALL = 15; // in seconds
@@ -63,7 +63,7 @@
private SipProfile mProfile;
SipPhone (Context context, PhoneNotifier notifier, SipProfile profile) {
- super(context, notifier);
+ super("SIP:" + profile.getUriString(), context, notifier);
if (DBG) log("new SipPhone: " + profile.getUriString());
mRingingCall = new SipCall();
@@ -81,11 +81,6 @@
return mProfile.getUriString().equals(that.mProfile.getUriString());
}
- @Override
- public String getPhoneName() {
- return "SIP:" + getUriString(mProfile);
- }
-
public String getSipUri() {
return mProfile.getUriString();
}
diff --git a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
index 49ca7c6..b749542 100755
--- a/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -33,7 +33,7 @@
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
-import com.android.internal.telephony.dataconnection.DataConnectionBase;
+import com.android.internal.telephony.dataconnection.DataConnection;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.IccPhoneBookInterfaceManager;
import com.android.internal.telephony.IccSmsInterfaceManager;
@@ -56,8 +56,8 @@
private RegistrantList mRingbackRegistrants = new RegistrantList();
private PhoneConstants.State mState = PhoneConstants.State.IDLE;
- public SipPhoneBase(Context context, PhoneNotifier notifier) {
- super(notifier, context, new SipCommandInterface(context), false);
+ public SipPhoneBase(String name, Context context, PhoneNotifier notifier) {
+ super(name, notifier, context, new SipCommandInterface(context), false);
}
@Override
@@ -424,7 +424,7 @@
public void getDataCallList(Message response) {
}
- public List<DataConnectionBase> getCurrentDataConnectionList () {
+ public List<DataConnection> getCurrentDataConnectionList () {
return null;
}
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index 883e11c..23c09ee 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -25,10 +25,10 @@
import com.android.internal.telephony.BaseCommands;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
-import com.android.internal.telephony.DataCallState;
+import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.dataconnection.DataCallResponse;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.UUSInfo;
-import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
import com.android.internal.telephony.gsm.CallFailCause;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import com.android.internal.telephony.gsm.SuppServiceNotification;
@@ -478,11 +478,11 @@
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* ar.userObject contains the original value of result.obj
- * ar.result contains a List of DataCallState
+ * ar.result contains a List of DataCallResponse
*/
@Override
public void getDataCallList(Message result) {
- resultSuccess(result, new ArrayList<DataCallState>(0));
+ resultSuccess(result, new ArrayList<DataCallResponse>(0));
}
/**