133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang/*
233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Copyright (C) 2011 The Android Open Source Project
333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *
433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Licensed under the Apache License, Version 2.0 (the "License");
533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * you may not use this file except in compliance with the License.
633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * You may obtain a copy of the License at
733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *
833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *      http://www.apache.org/licenses/LICENSE-2.0
933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *
1033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Unless required by applicable law or agreed to in writing, software
1133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * distributed under the License is distributed on an "AS IS" BASIS,
1233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * See the License for the specific language governing permissions and
1433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * limitations under the License.
1533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang */
1633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
1733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangpackage com.android.bandwidthtest;
1833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
1933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.NetworkInfo.State;
2033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.util.Log;
2133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
2233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport java.util.List;
2333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport java.util.ArrayList;
2433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
2533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang/**
2633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Data structure to keep track of the network state transitions.
2733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang */
2833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangpublic class NetworkState {
2933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
3033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Desired direction of state transition.
3133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
3233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public enum StateTransitionDirection {
3333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        TO_DISCONNECTION, TO_CONNECTION, DO_NOTHING
3433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
3533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private final String LOG_TAG = "NetworkState";
3633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private List<State> mStateDepository;
3733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private State mTransitionTarget;
3833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private StateTransitionDirection mTransitionDirection;
3933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private String mReason = null;         // record mReason of state transition failure
4033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
4133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public NetworkState() {
4233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mStateDepository = new ArrayList<State>();
4333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionDirection = StateTransitionDirection.DO_NOTHING;
4433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionTarget = State.UNKNOWN;
4533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
4633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
4733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public NetworkState(State currentState) {
4833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mStateDepository = new ArrayList<State>();
4933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mStateDepository.add(currentState);
5033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionDirection = StateTransitionDirection.DO_NOTHING;
5133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionTarget = State.UNKNOWN;
5233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
5333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
5433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
5533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Reinitialize the network state
5633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
5733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void resetNetworkState() {
5833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mStateDepository.clear();
5933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionDirection = StateTransitionDirection.DO_NOTHING;
6033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionTarget = State.UNKNOWN;
6133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
6233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
6333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
6433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Set the transition criteria
6533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param initState initial {@link State}
6633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param transitionDir explicit {@link StateTransitionDirection}
6733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param targetState desired {@link State}
6833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
6933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void setStateTransitionCriteria(State initState, StateTransitionDirection transitionDir,
7033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            State targetState) {
7133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (!mStateDepository.isEmpty()) {
7233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mStateDepository.clear();
7333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
7433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mStateDepository.add(initState);
7533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionDirection = transitionDir;
7633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mTransitionTarget = targetState;
7733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "setStateTransitionCriteria: " + printStates());
7833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
7933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
8033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
8133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Record the current state of the network
8233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param currentState  the current {@link State}
8333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
8433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void recordState(State currentState) {
8533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mStateDepository.add(currentState);
8633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
8733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
8833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
8933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Verify the state transition
9033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if the requested transition completed successfully.
9133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
9233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean validateStateTransition() {
9333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, String.format("Print state depository: %s", printStates()));
9433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        switch (mTransitionDirection) {
9533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            case DO_NOTHING:
9633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "No direction requested, verifying network states");
9733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return validateNetworkStates();
9833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            case TO_CONNECTION:
9933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Transition to CONNECTED");
10033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return validateNetworkConnection();
10133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            case TO_DISCONNECTION:
10233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Transition to DISCONNECTED");
10333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return validateNetworkDisconnection();
10433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            default:
10533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.e(LOG_TAG, "Invalid transition direction.");
10633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return false;
10733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
10833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
10933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
11033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
11133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Verify that network states are valid
11233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return false if any of the states are invalid
11333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
11433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private boolean validateNetworkStates() {
11533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mStateDepository.isEmpty()) {
11633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "no state is recorded");
11733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mReason = "no state is recorded.";
11833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
11933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        } else if (mStateDepository.size() > 1) {
12033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "no broadcast is expected, instead broadcast is probably received");
12133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mReason = "no broadcast is expected, instead broadcast is probably received";
12233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
12333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        } else if (mStateDepository.get(0) != mTransitionTarget) {
12433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, String.format("%s is expected, but it is %s",
12533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mTransitionTarget.toString(),
12633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mStateDepository.get(0).toString()));
12733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mReason = String.format("%s is expected, but it is %s",
12833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mTransitionTarget.toString(),
12933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mStateDepository.get(0).toString());
13033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
13133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
13233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return true;
13333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
13433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
13533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
13633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Verify the network state to disconnection
13733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return false if any of the state transitions were not valid
13833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
13933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private boolean validateNetworkDisconnection() {
14033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Transition from CONNECTED -> DISCONNECTED: CONNECTED->DISCONNECTING->DISCONNECTED
14133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        StringBuffer str = new StringBuffer ("States: ");
14233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        str.append(printStates());
14333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mStateDepository.get(0) != State.CONNECTED) {
14433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            str.append(String.format(" Initial state should be CONNECTED, but it is %s.",
14533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mStateDepository.get(0)));
14633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mReason = str.toString();
14733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
14833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
14933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        State lastState = mStateDepository.get(mStateDepository.size() - 1);
15033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if ( lastState != mTransitionTarget) {
15133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            str.append(String.format(" Last state should be DISCONNECTED, but it is %s",
15233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    lastState));
15333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mReason = str.toString();
15433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
15533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
15633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (int i = 1; i < mStateDepository.size() - 1; i++) {
15733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            State preState = mStateDepository.get(i-1);
15833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            State curState = mStateDepository.get(i);
15933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) ||
16033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    (curState == State.DISCONNECTED))) {
16133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                continue;
16233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) {
16333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                continue;
16433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if ((preState == State.DISCONNECTED) && (curState == State.DISCONNECTED)) {
16533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                continue;
16633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else {
16733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                str.append(String.format(" Transition state from %s to %s is not valid",
16833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        preState.toString(), curState.toString()));
16933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mReason = str.toString();
17033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return false;
17133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
17233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
17333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mReason = str.toString();
17433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return true;
17533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
17633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
17733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
17833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Verify the network state to connection
17933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return false if any of the state transitions were not valid
18033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
18133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private boolean validateNetworkConnection() {
18233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        StringBuffer str = new StringBuffer("States ");
18333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        str.append(printStates());
18433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mStateDepository.get(0) != State.DISCONNECTED) {
18533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            str.append(String.format(" Initial state should be DISCONNECTED, but it is %s.",
18633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mStateDepository.get(0)));
18733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mReason = str.toString();
18833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
18933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
19033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        State lastState = mStateDepository.get(mStateDepository.size() - 1);
19133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if ( lastState != mTransitionTarget) {
19233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            str.append(String.format(" Last state should be %s, but it is %s", mTransitionTarget,
19333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    lastState));
19433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mReason = str.toString();
19533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
19633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
19733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (int i = 1; i < mStateDepository.size(); i++) {
19833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            State preState = mStateDepository.get(i-1);
19933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            State curState = mStateDepository.get(i);
20033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) ||
20133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    (curState == State.CONNECTED) || (curState == State.DISCONNECTED))) {
20233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                continue;
20333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) {
20433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                continue;
20533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if ((preState == State.CONNECTED) && (curState == State.CONNECTED)) {
20633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                continue;
20733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else {
20833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                str.append(String.format(" Transition state from %s to %s is not valid.",
20933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        preState.toString(), curState.toString()));
21033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mReason = str.toString();
21133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return false;
21233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
21333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
21433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mReason = str.toString();
21533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return true;
21633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
21733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
21833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
21933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Fetch the different network state transitions
22033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return {@link List} of {@link State}
22133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
22233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public List<State> getTransitionStates() {
22333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mStateDepository;
22433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
22533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
22633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
22733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Fetch the reason for network state transition failure
22833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return the {@link String} for the failure
22933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
23033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public String getFailureReason() {
23133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mReason;
23233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
23333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
23433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
23533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Print the network state
23633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return {@link String} representation of the network state
23733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
23833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public String printStates() {
23933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        StringBuilder stateBuilder = new StringBuilder();
24033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (int i = 0; i < mStateDepository.size(); i++) {
24133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            stateBuilder.append(" ").append(mStateDepository.get(i).toString()).append("->");
24233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
24333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return stateBuilder.toString();
24433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
24533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
24633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
24733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * {@inheritDoc}
24833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
24933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    @Override
25033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public String toString() {
25133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        StringBuilder builder = new StringBuilder();
25233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        builder.append("mTransitionDirection: ").append(mTransitionDirection.toString()).
25333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        append("; ").append("states:").
25433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        append(printStates()).append("; ");
25533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return builder.toString();
25633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
25733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang}
258