Add configurable data-retry.

Add RetryManager and change GsmDataConnectionTracker and
CdmaDataConnectionTracker to use it.

Add TelephonyUtilsTest which tests RetryManager.
This commit is contained in:
Wink Saville
2009-08-08 18:05:24 -07:00
parent e4ebbd29f7
commit 3918e13b24
6 changed files with 642 additions and 51 deletions

View File

@@ -96,10 +96,11 @@ public abstract class DataConnectionTracker extends Handler {
public static final int EVENT_CLEAN_UP_CONNECTION = 34;
//***** Constants
protected static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
/** Cap out with 30 min retry interval. */
protected static final int RECONNECT_DELAY_MAX_MILLIS = 30 * 60 * 1000;
/** Retry configuration: A doubling of retry times from 5secs to 30minutes */
protected 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";
/** Slow poll when attempting connection recovery. */
protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;

View File

@@ -0,0 +1,383 @@
/**
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony;
import android.util.Log;
import android.util.Pair;
import android.text.TextUtils;
import java.util.Random;
import java.util.ArrayList;
/**
* Retry manager allows a simple way to declare a series of
* retires timeouts. After creating a RetryManager the configure
* method is used to define the sequence. A simple linear series
* may be initialized using configure with three integer parameters
* The other configure method allows a series to be declared using
* a string.
*<p>
* The format of the configuration string is a series of parameters
* separated by a comma. There are two name value pair parameters plus a series
* of delay times. The units of of these delay times is unspecified.
* The name value pairs which may be specified are:
*<ul>
*<li>max_retries=<value>
*<li>default_randomizationTime=<value>
*</ul>
*<p>
* max_retries is the number of times that incrementRetryCount
* maybe called before isRetryNeeded will return false.
*
* default_randomizationTime will be used as the randomizationTime
* for delay times which have no supplied randomizationTime. If
* default_randomizationTime is not defined it defaults to 0.
*<p>
* The other parameters define The series of delay times and each
* may have an optional randomization value separated from the
* delay time by a colon.
*<p>
* Examples:
* <ul>
* <li>3 retires with no randomization value which means its 0:
* <ul><li><code>"1000, 2000, 3000"</code></ul>
*
* <li>10 retires with a 500 default randomization value for each and
* the 4..10 retries all using 3000 as the delay:
* <ul><li><code>"max_retries=10, default_randomization=500, 1000, 2000, 3000"</code></ul>
*
* <li>4 retires with a 100ms default randomization value for the first 2 values and
* the other two having specified values of 500ms:
* <ul><li><code>"default_randomization=100, 1000, 2000, 4000:500, 5000:500"</code></ul>
* </ul>
*
* {@hide}
*/
public class RetryManager {
static public final String LOG_TAG = "RetryManager";
static public final boolean DBG = false;
static public final int RETRYIES_NOT_STARTED = 0;
static public final int RETRYIES_ON_GOING = 1;
static public final int RETRYIES_COMPLETED = 2;
/**
* Retry record with times in milli-seconds
*/
private static class RetryRec {
RetryRec(int delayTime, int randomizationTime) {
mDelayTime = delayTime;
mRandomizationTime = randomizationTime;
}
int mDelayTime;
int mRandomizationTime;
}
/** The array of retry records */
private ArrayList<RetryRec> mRetryArray = new ArrayList<RetryRec>();
/** When true isRetryNeeded() will always return true */
private boolean mRetryForever;
/**
* The maximum number of retries to attempt before
* isRetryNeeded returns false
*/
private int mMaxRetryCount;
/** The current number of retires */
private int mRetryCount;
/** Random number generator */
private Random rng = new Random();
/** Constructor */
public RetryManager() {
if (DBG) log("constructor");
}
/**
* Configure for a simple linear sequence of times plus
* a random value.
*
* @param maxRetryCount is the maximum number of retries
* before isRetryNeeded returns false.
* @param retryTime is a time that will be returned by getRetryTime.
* @param randomizationTime a random value between 0 and
* randomizationTime will be added to retryTime. this
* parameter may be 0.
* @return true if successfull
*/
public boolean configure(int maxRetryCount, int retryTime, int randomizationTime) {
Pair<Boolean, Integer> value;
if (DBG) log("configure: " + maxRetryCount + ", " + retryTime + "," + randomizationTime);
if (!validateNonNegativeInt("maxRetryCount", maxRetryCount)) {
return false;
}
if (!validateNonNegativeInt("retryTime", retryTime)) {
return false;
}
if (!validateNonNegativeInt("randomizationTime", randomizationTime)) {
return false;
}
mMaxRetryCount = maxRetryCount;
resetRetryCount();
mRetryArray.clear();
mRetryArray.add(new RetryRec(retryTime, randomizationTime));
return true;
}
/**
* Configure for using string which allow arbitary
* sequences of times. See class comments for the
* string format.
*
* @return true if successfull
*/
public boolean configure(String configStr) {
if (DBG) log("configure: '" + configStr + "'");
if (!TextUtils.isEmpty(configStr)) {
int defaultRandomization = 0;
if (DBG) log("configure: not empty");
mMaxRetryCount = 0;
resetRetryCount();
mRetryArray.clear();
String strArray[] = configStr.split(",");
for (int i = 0; i < strArray.length; i++) {
if (DBG) log("configure: strArray[" + i + "]='" + strArray[i] + "'");
Pair<Boolean, Integer> value;
String splitStr[] = strArray[i].split("=", 2);
splitStr[0] = splitStr[0].trim();
if (DBG) log("configure: splitStr[0]='" + splitStr[0] + "'");
if (splitStr.length > 1) {
splitStr[1] = splitStr[1].trim();
if (DBG) log("configure: splitStr[1]='" + splitStr[1] + "'");
if (TextUtils.equals(splitStr[0], "default_randomization")) {
value = parseNonNegativeInt(splitStr[0], splitStr[1]);
if (!value.first) return false;
defaultRandomization = value.second;
} else if (TextUtils.equals(splitStr[0], "max_retries")) {
value = parseNonNegativeInt(splitStr[0], splitStr[1]);
if (!value.first) return false;
mMaxRetryCount = value.second;
} else {
Log.e(LOG_TAG, "Unrecognized configuration name value pair: "
+ strArray[i]);
return false;
}
} else {
/**
* Assume a retry time with an optional randomization value
* following a ":"
*/
splitStr = strArray[i].split(":", 2);
splitStr[0] = splitStr[0].trim();
RetryRec rr = new RetryRec(0, 0);
value = parseNonNegativeInt("delayTime", splitStr[0]);
if (!value.first) return false;
rr.mDelayTime = value.second;
// Check if optional randomization value present
if (splitStr.length > 1) {
splitStr[1] = splitStr[1].trim();
if (DBG) log("configure: splitStr[1]='" + splitStr[1] + "'");
value = parseNonNegativeInt("randomizationTime", splitStr[1]);
if (!value.first) return false;
rr.mRandomizationTime = value.second;
} else {
rr.mRandomizationTime = defaultRandomization;
}
mRetryArray.add(rr);
}
}
if (mRetryArray.size() > mMaxRetryCount) {
mMaxRetryCount = mRetryArray.size();
if (DBG) log("configure: setting mMaxRetryCount=" + mMaxRetryCount);
}
if (DBG) log("configure: true");
return true;
} else {
if (DBG) log("configure: false it's empty");
return false;
}
}
/**
* Report whether data reconnection should be retried
*
* @return {@code true} if the max retires has not been reached. {@code
* false} otherwise.
*/
public boolean isRetryNeeded() {
boolean retVal = mRetryForever || (mRetryCount < mMaxRetryCount);
if (DBG) log("isRetryNeeded: " + retVal);
return retVal;
}
/**
* Return the timer that should be used to trigger the data reconnection
*/
public int getRetryTimer() {
int index;
if (mRetryCount < mRetryArray.size()) {
index = mRetryCount;
} else {
index = mRetryArray.size() - 1;
}
int retVal;
if ((index >= 0) && (index < mRetryArray.size())) {
retVal = mRetryArray.get(index).mDelayTime + nextRandomizationTime(index);
} else {
retVal = 0;
}
if (DBG) log("getRetryTimer: " + retVal);
return retVal;
}
/**
* @return retry count
*/
public int getRetryCount() {
if (DBG) log("getRetryCount: " + mRetryCount);
return mRetryCount;
}
/**
* Increase the retry counter, does not change retry forever.
*/
public void increaseRetryCount() {
mRetryCount++;
if (mRetryCount > mMaxRetryCount) {
mRetryCount = mMaxRetryCount;
}
if (DBG) log("increseRetryCount: " + mRetryCount);
}
/**
* Set retry count to the specified value
* and turns off retrying forever.
*/
public void setRetryCount(int count) {
mRetryCount = count;
if (mRetryCount > mMaxRetryCount) {
mRetryCount = mMaxRetryCount;
}
if (mRetryCount < 0) {
mRetryCount = 0;
}
mRetryForever = false;
if (DBG) log("setRetryCount: " + mRetryCount);
}
/**
* Reset network re-registration indicator and clear the data-retry counter
* and turns off retrying forever.
*/
public void resetRetryCount() {
mRetryCount = 0;
mRetryForever = false;
if (DBG) log("resetRetryCount: " + mRetryCount);
}
/**
* Retry forever using last timeout time.
*/
public void retryForeverUsingLastTimeout() {
mRetryCount = mMaxRetryCount;
mRetryForever = true;
if (DBG) log("retryForeverUsingLastTimeout: " + mRetryForever + ", " + mRetryCount);
}
/**
* @return true if retrying forever
*/
public boolean isRetryForever() {
if (DBG) log("isRetryForever: " + mRetryForever);
return mRetryForever;
}
/**
* Parse an integer validating the value is not negative.
*
* @param name
* @param stringValue
* @return Pair.first == true if stringValue an integer >= 0
*/
private Pair<Boolean, Integer> parseNonNegativeInt(String name, String stringValue) {
int value;
Pair<Boolean, Integer> retVal;
try {
value = Integer.parseInt(stringValue);
retVal = new Pair<Boolean, Integer>(validateNonNegativeInt(name, value), value);
} catch (NumberFormatException e) {
Log.e(LOG_TAG, name + " bad value: " + stringValue, e);
retVal = new Pair<Boolean, Integer>(false, 0);
}
if (DBG) log("parseNonNetativeInt: " + name + ", " + stringValue + ", "
+ retVal.first + ", " + retVal.second);
return retVal;
}
/**
* Validate an integer is >= 0 and logs an error if not
*
* @param name
* @param value
* @return Pair.first
*/
private boolean validateNonNegativeInt(String name, int value) {
boolean retVal;
if (value < 0) {
Log.e(LOG_TAG, name + " bad value: is < 0");
retVal = false;
} else {
retVal = true;
}
if (DBG) log("validateNonNegative: " + name + ", " + value + ", " + retVal);
return retVal;
}
/**
* Return next random number for the index
*/
private int nextRandomizationTime(int index) {
int randomTime = mRetryArray.get(index).mRandomizationTime;
if (randomTime == 0) {
return 0;
} else {
return rng.nextInt(randomTime);
}
}
private void log(String s) {
Log.d(LOG_TAG, s);
}
}

View File

@@ -31,6 +31,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.preference.PreferenceManager;
import android.provider.Checkin;
import android.telephony.ServiceState;
@@ -45,6 +46,7 @@ import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyEventLog;
@@ -61,8 +63,6 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
// Indicates baseband will not auto-attach
private boolean noAutoAttach = false;
long nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
private boolean mReregisterOnReconnectFailure = false;
private boolean mIsScreenOn = true;
//useful for debugging
@@ -76,6 +76,9 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
/** Currently active CdmaDataConnection */
private CdmaDataConnection mActiveDataConnection;
/** Manage the behavior of data retry after failure */
private final RetryManager mRetryMgr = new RetryManager();
/** Defined cdma connection profiles */
private static final int EXTERNAL_NETWORK_DEFAULT_ID = 0;
private static final int EXTERNAL_NETWORK_NUM_TYPES = 1;
@@ -183,10 +186,19 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID] =
!sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false);
noAutoAttach = !dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
if (!mRetryMgr.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple linear sequence.
Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+ DEFAULT_DATA_RETRY_CONFIG);
mRetryMgr.configure(20, 2000, 1000);
}
}
}
public void dispose() {
//Unregister from all events
// Unregister from all events
phone.mCM.unregisterForAvailable(this);
phone.mCM.unregisterForOffOrNotAvailable(this);
mCdmaPhone.mRuimRecords.unregisterForRecordsLoaded(this);
@@ -459,9 +471,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
setState(State.CONNECTED);
phone.notifyDataConnection(reason);
startNetStatPoll();
// reset reconnect timer
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mReregisterOnReconnectFailure = false;
mRetryMgr.resetRetryCount();
}
private void resetPollStats() {
@@ -617,21 +627,13 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
if (state == State.FAILED) {
if (nextReconnectDelay > RECONNECT_DELAY_MAX_MILLIS) {
if (mReregisterOnReconnectFailure) {
// We have already tried to re-register to the network.
// This might be a problem with the data network.
nextReconnectDelay = RECONNECT_DELAY_MAX_MILLIS;
} else {
// Try to Re-register to the network.
Log.d(LOG_TAG, "PDP activate failed, Reregistering to the network");
mReregisterOnReconnectFailure = true;
mCdmaPhone.mSST.reRegisterNetwork(null);
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
return;
}
}
/**
* For now With CDMA we never try to reconnect on
* error and instead just continue to retry
* at the last time until the state is changed.
* TODO: Make this configurable?
*/
int nextReconnectDelay = mRetryMgr.getRetryTimer();
Log.d(LOG_TAG, "Data Connection activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s");
@@ -645,8 +647,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
SystemClock.elapsedRealtime() + nextReconnectDelay,
mReconnectIntent);
// double it for next time
nextReconnectDelay *= 2;
mRetryMgr.increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
Log.d(LOG_TAG,"NOT Posting Data Connection Unavailable notification "
@@ -723,10 +724,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
* @override com.android.internal.telephony.DataConnectionTracker
*/
protected void onRadioOffOrNotAvailable() {
// Make sure our reconnect delay starts at the initial value
// next time the radio comes on
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mReregisterOnReconnectFailure = false;
mRetryMgr.resetRetryCount();
if (phone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
@@ -802,9 +800,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
resetPollStats();
}
} else {
// reset reconnect timer
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mReregisterOnReconnectFailure = false;
mRetryMgr.resetRetryCount();
// in case data setup was attempted when we were on a voice call
trySetupData(Phone.REASON_VOICE_CALL_ENDED);
}
@@ -840,7 +836,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker {
} else {
if (state == State.FAILED) {
cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
int bsid = (loc != null) ? loc.getBaseStationId() : -1;

View File

@@ -52,6 +52,7 @@ import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.TelephonyEventLog;
import com.android.internal.telephony.DataConnection.FailCause;
@@ -85,7 +86,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
INetStatService netstat;
// Indicates baseband will not auto-attach
private boolean noAutoAttach = false;
long nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
private boolean mReregisterOnReconnectFailure = false;
private ContentResolver mResolver;
@@ -95,6 +96,11 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private int mPdpResetCount = 0;
private boolean mIsScreenOn = true;
private final RetryManager mRetryMgr = new RetryManager();
/** Delay between APN attempts */
protected static final int APN_DELAY_MILLIS = 5000;
//useful for debugging
boolean failNextConnect = false;
@@ -247,6 +253,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
if (!mRetryMgr.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
// Should never happen, log an error and default to a simple linear sequence.
Log.e(LOG_TAG, "Could not configure using DEFAULT_DATA_RETRY_CONFIG="
+ DEFAULT_DATA_RETRY_CONFIG);
mRetryMgr.configure(20, 2000, 1000);
}
}
}
public void dispose() {
@@ -558,7 +573,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} else {
if (state == State.FAILED) {
cleanUpConnection(false, Phone.REASON_GPRS_ATTACHED);
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
}
trySetupData(Phone.REASON_GPRS_ATTACHED);
}
@@ -808,7 +823,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
cleanUpConnection(isConnected, Phone.REASON_APN_CHANGED);
if (!isConnected) {
// reset reconnect timer
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
mReregisterOnReconnectFailure = false;
trySetupData(Phone.REASON_APN_CHANGED);
}
@@ -889,7 +904,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
phone.notifyDataConnection(reason);
startNetStatPoll();
// reset reconnect timer
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
mReregisterOnReconnectFailure = false;
}
@@ -1175,20 +1190,21 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
if (state == State.FAILED) {
if (nextReconnectDelay > RECONNECT_DELAY_MAX_MILLIS) {
if (!mRetryMgr.isRetryNeeded()) {
if (mReregisterOnReconnectFailure) {
// We have already tried to re-register to the network.
// This might be a problem with the data network.
nextReconnectDelay = RECONNECT_DELAY_MAX_MILLIS;
// We've re-registerd once now just retry forever.
mRetryMgr.retryForeverUsingLastTimeout();
} else {
// Try to Re-register to the network.
// Try to re-register to the network.
Log.d(LOG_TAG, "PDP activate failed, Reregistering to the network");
mReregisterOnReconnectFailure = true;
mGsmPhone.mSST.reRegisterNetwork(null);
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
return;
}
}
int nextReconnectDelay = mRetryMgr.getRetryTimer();
Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for "
+ (nextReconnectDelay / 1000) + "s");
@@ -1202,8 +1218,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
SystemClock.elapsedRealtime() + nextReconnectDelay,
mReconnectIntent);
// double it for next time
nextReconnectDelay *= 2;
mRetryMgr.increaseRetryCount();
if (!shouldPostNotification(lastFailCauseCode)) {
Log.d(LOG_TAG,"NOT Posting GPRS Unavailable notification "
@@ -1276,7 +1291,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
protected void onRadioOffOrNotAvailable() {
// Make sure our reconnect delay starts at the initial value
// next time the radio comes on
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
mReregisterOnReconnectFailure = false;
if (phone.getSimulatedRadioControl() != null) {
@@ -1361,8 +1376,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
setState(State.SCANNING);
// Wait a bit before trying the next APN, so that
// we're not tying up the RIL command channel
sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason),
RECONNECT_DELAY_INITIAL_MILLIS);
sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason), APN_DELAY_MILLIS);
}
}
}
@@ -1407,7 +1421,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
} else {
// reset reconnect timer
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
mReregisterOnReconnectFailure = false;
// in case data setup was attempted when we were on a voice call
trySetupData(Phone.REASON_VOICE_CALL_ENDED);
@@ -1684,7 +1698,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
} else {
if (state == State.FAILED) {
cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
mRetryMgr.resetRetryCount();
mReregisterOnReconnectFailure = false;
}
trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);

View File

@@ -47,6 +47,7 @@ public class TelephonyTests {
suite.addTestSuite(SimUtilsTest.class);
suite.addTestSuite(SimPhoneBookTest.class);
suite.addTestSuite(SimSmsTest.class);
suite.addTestSuite(TelephonyUtilsTest.class);
return suite;
}

View File

@@ -0,0 +1,196 @@
/**
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony;
import com.android.internal.telephony.RetryManager;
import junit.framework.TestCase;
import android.test.suitebuilder.annotation.SmallTest;
public class TelephonyUtilsTest extends TestCase {
/**
* After first creating the RetryManager
* isRetryNeeded should be false and the time 0
*/
@SmallTest
public void testRetryManagerEmpty() throws Exception {
RetryManager rm = new RetryManager();
assertEquals(0, rm.getRetryCount());
assertFalse(rm.isRetryForever());
assertFalse(rm.isRetryNeeded());
assertEquals(0, rm.getRetryCount());
assertEquals(0, rm.getRetryTimer());
rm.increaseRetryCount();
assertFalse(rm.isRetryForever());
assertFalse(rm.isRetryNeeded());
assertEquals(0, rm.getRetryCount());
assertEquals(0, rm.getRetryTimer());
rm.setRetryCount(123);
assertFalse(rm.isRetryForever());
assertFalse(rm.isRetryNeeded());
assertEquals(0, rm.getRetryCount());
assertEquals(0, rm.getRetryTimer());
rm.retryForeverUsingLastTimeout();
assertTrue(rm.isRetryForever());
assertTrue(rm.isRetryNeeded());
assertEquals(0, rm.getRetryCount());
assertEquals(0, rm.getRetryTimer());
rm.setRetryCount(2);
assertFalse(rm.isRetryForever());
assertFalse(rm.isRetryNeeded());
assertEquals(0, rm.getRetryCount());
assertEquals(0, rm.getRetryTimer());
}
/**
* A simple test and that randomization is doing something.
*/
@SmallTest
public void testRetryManagerSimplest() throws Exception {
RetryManager rm = new RetryManager();
assertTrue(rm.configure(1, 500, 10));
int loops = 10;
int count = 0;
for (int i = 0; i < loops; i++) {
assertTrue(rm.isRetryNeeded());
int time = rm.getRetryTimer();
assertTrue((time >= 500) && (time < 600));
if (time == 500) {
count++;
}
}
assertFalse(count == loops);
rm.increaseRetryCount();
assertFalse(rm.isRetryNeeded());
rm.setRetryCount(0);
assertTrue(rm.isRetryNeeded());
}
/**
* Test multiple values using simple configuration.
*/
@SmallTest
public void testRetryManagerSimple() throws Exception {
RetryManager rm = new RetryManager();
assertTrue(rm.configure(3, 1000, 0));
assertTrue(rm.isRetryNeeded());
assertEquals(1000, rm.getRetryTimer());
assertEquals(rm.getRetryTimer(), 1000);
rm.increaseRetryCount();
assertTrue(rm.isRetryNeeded());
assertEquals(1000, rm.getRetryTimer());
rm.increaseRetryCount();
assertTrue(rm.isRetryNeeded());
assertEquals(1000, rm.getRetryTimer());
rm.increaseRetryCount();
assertFalse(rm.isRetryNeeded());
assertEquals(1000, rm.getRetryTimer());
}
/**
* Test string configuration, simplest
*/
@SmallTest
public void testRetryManageSimpleString() throws Exception {
RetryManager rm = new RetryManager();
assertTrue(rm.configure("101"));
assertTrue(rm.isRetryNeeded());
assertEquals(101, rm.getRetryTimer());
rm.increaseRetryCount();
assertFalse(rm.isRetryNeeded());
}
/**
* Test string configuration using all options.
*/
@SmallTest
public void testRetryManageString() throws Exception {
RetryManager rm = new RetryManager();
int time;
assertTrue(rm.configure("max_retries=4,"
+ "default_randomization=100,1000, 2000 :200 , 3000"));
assertTrue(rm.isRetryNeeded());
time = rm.getRetryTimer();
assertTrue((time >= 1000) && (time < 1100));
rm.increaseRetryCount();
assertTrue(rm.isRetryNeeded());
time = rm.getRetryTimer();
assertTrue((time >= 2000) && (time < 2200));
rm.increaseRetryCount();
assertTrue(rm.isRetryNeeded());
time = rm.getRetryTimer();
assertTrue((time >= 3000) && (time < 3100));
rm.increaseRetryCount();
assertTrue(rm.isRetryNeeded());
time = rm.getRetryTimer();
assertTrue((time >= 3000) && (time < 3100));
rm.increaseRetryCount();
assertFalse(rm.isRetryNeeded());
}
/**
* Test string configuration using all options.
*/
@SmallTest
public void testRetryManageForever() throws Exception {
RetryManager rm = new RetryManager();
int time;
assertTrue(rm.configure("1000, 2000, 3000"));
assertTrue(rm.isRetryNeeded());
assertFalse(rm.isRetryForever());
assertEquals(0, rm.getRetryCount());
assertEquals(1000, rm.getRetryTimer());
rm.retryForeverUsingLastTimeout();
rm.increaseRetryCount();
rm.increaseRetryCount();
rm.increaseRetryCount();
assertTrue(rm.isRetryNeeded());
assertTrue(rm.isRetryForever());
assertEquals(3, rm.getRetryCount());
assertEquals(3000, rm.getRetryTimer());
rm.setRetryCount(1);
assertTrue(rm.isRetryNeeded());
assertFalse(rm.isRetryForever());
assertEquals(1, rm.getRetryCount());
assertEquals(2000, rm.getRetryTimer());
rm.retryForeverUsingLastTimeout();
assertTrue(rm.isRetryNeeded());
assertTrue(rm.isRetryForever());
rm.resetRetryCount();
assertTrue(rm.isRetryNeeded());
assertFalse(rm.isRetryForever());
assertEquals(0, rm.getRetryCount());
assertEquals(1000, rm.getRetryTimer());
}
}