10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2009 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Pair;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.text.TextUtils;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Random;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Retry manager allows a simple way to declare a series of
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * retry timeouts. After creating a RetryManager the configure
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * method is used to define the sequence. A simple linear series
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * may be initialized using configure with three integer parameters
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The other configure method allows a series to be declared using
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * a string.
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *<p>
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The format of the configuration string is a series of parameters
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * separated by a comma. There are two name value pair parameters plus a series
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * of delay times. The units of of these delay times is unspecified.
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The name value pairs which may be specified are:
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *<ul>
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *<li>max_retries=<value>
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *<li>default_randomizationTime=<value>
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *</ul>
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *<p>
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * max_retries is the number of times that incrementRetryCount
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * maybe called before isRetryNeeded will return false. if value
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * is infinite then isRetryNeeded will always return true.
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * default_randomizationTime will be used as the randomizationTime
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * for delay times which have no supplied randomizationTime. If
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * default_randomizationTime is not defined it defaults to 0.
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *<p>
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * The other parameters define The series of delay times and each
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * may have an optional randomization value separated from the
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * delay time by a colon.
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *<p>
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Examples:
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <ul>
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <li>3 retries with no randomization value which means its 0:
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <ul><li><code>"1000, 2000, 3000"</code></ul>
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <li>10 retries with a 500 default randomization value for each and
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the 4..10 retries all using 3000 as the delay:
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <ul><li><code>"max_retries=10, default_randomization=500, 1000, 2000, 3000"</code></ul>
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <li>4 retries with a 100 as the default randomization value for the first 2 values and
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * the other two having specified values of 500:
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <ul><li><code>"default_randomization=100, 1000, 2000, 4000:500, 5000:500"</code></ul>
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <li>Infinite number of retries with the first one at 1000, the second at 2000 all
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * others will be at 3000.
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * <ul><li><code>"max_retries=infinite,1000,2000,3000</code></ul>
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * </ul>
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide}
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class RetryManager {
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static public final String LOG_TAG = "GSM";
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static public final boolean DBG = true;
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static public final boolean VDBG = false;
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Retry record with times in milli-seconds
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static class RetryRec {
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        RetryRec(int delayTime, int randomizationTime) {
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mDelayTime = delayTime;
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRandomizationTime = randomizationTime;
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int mDelayTime;
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int mRandomizationTime;
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** The array of retry records */
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private ArrayList<RetryRec> mRetryArray = new ArrayList<RetryRec>();
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** When true isRetryNeeded() will always return true */
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mRetryForever;
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * The maximum number of retries to attempt before
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * isRetryNeeded returns false
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mMaxRetryCount;
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** The current number of retries */
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int mRetryCount;
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Random number generator */
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Random rng = new Random();
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private String mConfig;
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /** Constructor */
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public RetryManager() {
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (VDBG) log("constructor");
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public String toString() {
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String ret = "RetryManager: forever=" + mRetryForever + ", maxRetry=" + mMaxRetryCount +
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ", retry=" + mRetryCount + ",\n    " + mConfig;
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (RetryRec r : mRetryArray) {
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ret += "\n    " + r.mDelayTime + ":" + r.mRandomizationTime;
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ret;
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Configure for a simple linear sequence of times plus
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * a random value.
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param maxRetryCount is the maximum number of retries
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *        before isRetryNeeded returns false.
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param retryTime is a time that will be returned by getRetryTime.
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param randomizationTime a random value between 0 and
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *        randomizationTime will be added to retryTime. this
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *        parameter may be 0.
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return true if successful
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean configure(int maxRetryCount, int retryTime, int randomizationTime) {
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Pair<Boolean, Integer> value;
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (VDBG) log("configure: " + maxRetryCount + ", " + retryTime + "," + randomizationTime);
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!validateNonNegativeInt("maxRetryCount", maxRetryCount)) {
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!validateNonNegativeInt("retryTime", retryTime)) {
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!validateNonNegativeInt("randomizationTime", randomizationTime)) {
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mMaxRetryCount = maxRetryCount;
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        resetRetryCount();
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryArray.clear();
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryArray.add(new RetryRec(retryTime, randomizationTime));
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return true;
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Configure for using string which allow arbitrary
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * sequences of times. See class comments for the
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * string format.
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return true if successful
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean configure(String configStr) {
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Strip quotes if present.
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if ((configStr.startsWith("\"") && configStr.endsWith("\""))) {
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            configStr = configStr.substring(1, configStr.length()-1);
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (VDBG) log("configure: '" + configStr + "'");
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mConfig = configStr;
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!TextUtils.isEmpty(configStr)) {
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int defaultRandomization = 0;
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (VDBG) log("configure: not empty");
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mMaxRetryCount = 0;
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            resetRetryCount();
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRetryArray.clear();
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String strArray[] = configStr.split(",");
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 0; i < strArray.length; i++) {
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (VDBG) log("configure: strArray[" + i + "]='" + strArray[i] + "'");
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Pair<Boolean, Integer> value;
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                String splitStr[] = strArray[i].split("=", 2);
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                splitStr[0] = splitStr[0].trim();
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (VDBG) log("configure: splitStr[0]='" + splitStr[0] + "'");
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (splitStr.length > 1) {
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    splitStr[1] = splitStr[1].trim();
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (VDBG) log("configure: splitStr[1]='" + splitStr[1] + "'");
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (TextUtils.equals(splitStr[0], "default_randomization")) {
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        value = parseNonNegativeInt(splitStr[0], splitStr[1]);
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (!value.first) return false;
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        defaultRandomization = value.second;
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else if (TextUtils.equals(splitStr[0], "max_retries")) {
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (TextUtils.equals("infinite",splitStr[1])) {
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            mRetryForever = true;
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } else {
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            value = parseNonNegativeInt(splitStr[0], splitStr[1]);
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (!value.first) return false;
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            mMaxRetryCount = value.second;
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        Log.e(LOG_TAG, "Unrecognized configuration name value pair: "
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                        + strArray[i]);
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        return false;
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    /**
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                     * Assume a retry time with an optional randomization value
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                     * following a ":"
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                     */
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    splitStr = strArray[i].split(":", 2);
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    splitStr[0] = splitStr[0].trim();
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    RetryRec rr = new RetryRec(0, 0);
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    value = parseNonNegativeInt("delayTime", splitStr[0]);
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (!value.first) return false;
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    rr.mDelayTime = value.second;
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Check if optional randomization value present
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (splitStr.length > 1) {
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        splitStr[1] = splitStr[1].trim();
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (VDBG) log("configure: splitStr[1]='" + splitStr[1] + "'");
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        value = parseNonNegativeInt("randomizationTime", splitStr[1]);
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (!value.first) return false;
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        rr.mRandomizationTime = value.second;
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        rr.mRandomizationTime = defaultRandomization;
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mRetryArray.add(rr);
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (mRetryArray.size() > mMaxRetryCount) {
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mMaxRetryCount = mRetryArray.size();
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (VDBG) log("configure: setting mMaxRetryCount=" + mMaxRetryCount);
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (VDBG) log("configure: true");
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return true;
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (VDBG) log("configure: false it's empty");
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return false;
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Report whether data reconnection should be retried
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return {@code true} if the max retries has not been reached. {@code
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *         false} otherwise.
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isRetryNeeded() {
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean retVal = mRetryForever || (mRetryCount < mMaxRetryCount);
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("isRetryNeeded: " + retVal);
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return retVal;
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Return the timer that should be used to trigger the data reconnection
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int getRetryTimer() {
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int index;
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mRetryCount < mRetryArray.size()) {
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            index = mRetryCount;
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            index = mRetryArray.size() - 1;
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int retVal;
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if ((index >= 0) && (index < mRetryArray.size())) {
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            retVal = mRetryArray.get(index).mDelayTime + nextRandomizationTime(index);
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            retVal = 0;
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("getRetryTimer: " + retVal);
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return retVal;
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return retry count
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public int getRetryCount() {
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("getRetryCount: " + mRetryCount);
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mRetryCount;
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Increase the retry counter, does not change retry forever.
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void increaseRetryCount() {
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryCount++;
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mRetryCount > mMaxRetryCount) {
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRetryCount = mMaxRetryCount;
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("increaseRetryCount: " + mRetryCount);
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Set retry count to the specified value
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void setRetryCount(int count) {
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryCount = count;
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mRetryCount > mMaxRetryCount) {
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRetryCount = mMaxRetryCount;
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mRetryCount < 0) {
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mRetryCount = 0;
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("setRetryCount: " + mRetryCount);
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Set retry forever to the specified value
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void setRetryForever(boolean retryForever) {
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryForever = retryForever;
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("setRetryForever: " + mRetryForever);
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Clear the data-retry counter
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void resetRetryCount() {
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryCount = 0;
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("resetRetryCount: " + mRetryCount);
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Retry forever using last timeout time.
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void retryForeverUsingLastTimeout() {
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryCount = mMaxRetryCount;
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mRetryForever = true;
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("retryForeverUsingLastTimeout: " + mRetryForever + ", " + mRetryCount);
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return true if retrying forever
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public boolean isRetryForever() {
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG) log("isRetryForever: " + mRetryForever);
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return mRetryForever;
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Parse an integer validating the value is not negative.
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param name
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param stringValue
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return Pair.first == true if stringValue an integer >= 0
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Pair<Boolean, Integer> parseNonNegativeInt(String name, String stringValue) {
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int value;
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Pair<Boolean, Integer> retVal;
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            value = Integer.parseInt(stringValue);
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            retVal = new Pair<Boolean, Integer>(validateNonNegativeInt(name, value), value);
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (NumberFormatException e) {
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.e(LOG_TAG, name + " bad value: " + stringValue, e);
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            retVal = new Pair<Boolean, Integer>(false, 0);
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (VDBG) log("parseNonNetativeInt: " + name + ", " + stringValue + ", "
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    + retVal.first + ", " + retVal.second);
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return retVal;
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Validate an integer is >= 0 and logs an error if not
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param name
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param value
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return Pair.first
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean validateNonNegativeInt(String name, int value) {
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean retVal;
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (value < 0) {
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.e(LOG_TAG, name + " bad value: is < 0");
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            retVal = false;
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            retVal = true;
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (VDBG) log("validateNonNegative: " + name + ", " + value + ", " + retVal);
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return retVal;
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Return next random number for the index
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private int nextRandomizationTime(int index) {
3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int randomTime = mRetryArray.get(index).mRandomizationTime;
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (randomTime == 0) {
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return 0;
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return rng.nextInt(randomTime);
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void log(String s) {
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.d(LOG_TAG, "[RM] " + s);
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
411