1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.connectivitymanagertest; 18 19 import android.net.NetworkInfo.State; 20 import android.util.Log; 21 22 import java.util.List; 23 import java.util.ArrayList; 24 25 public class NetworkState { 26 public static final int TO_DISCONNECTION = 0; // transition to disconnection 27 public static final int TO_CONNECTION = 1; // transition to connection 28 public static final int DO_NOTHING = -1; // no state change 29 private final String LOG_TAG = "NetworkState"; 30 private List<State> mStateDepository; 31 private State mTransitionTarget; 32 private int mTransitionDirection; 33 private String mReason = null; // record mReason of state transition failure 34 35 public NetworkState() { 36 mStateDepository = new ArrayList<State>(); 37 mTransitionDirection = DO_NOTHING; 38 mTransitionTarget = State.UNKNOWN; 39 } 40 41 public NetworkState(State currentState) { 42 mStateDepository = new ArrayList<State>(); 43 mStateDepository.add(currentState); 44 mTransitionDirection = DO_NOTHING; 45 mTransitionTarget = State.UNKNOWN; 46 } 47 48 // Reinitialize the network state 49 public void resetNetworkState() { 50 mStateDepository.clear(); 51 mTransitionDirection = DO_NOTHING; 52 mTransitionTarget = State.UNKNOWN; 53 } 54 55 // set the transition criteria, transitionDir could be: 56 // DO_NOTHING, TO_CONNECTION, TO_DISCONNECTION 57 public void setStateTransitionCriteria(State initState, int transitionDir, State targetState) { 58 if (!mStateDepository.isEmpty()) { 59 mStateDepository.clear(); 60 } 61 mStateDepository.add(initState); 62 mTransitionDirection = transitionDir; 63 mTransitionTarget = targetState; 64 Log.v(LOG_TAG, "setStateTransitionCriteria: " + printStates()); 65 } 66 67 public void recordState(State currentState) { 68 mStateDepository.add(currentState); 69 } 70 71 // Verify state transition 72 public boolean validateStateTransition() { 73 Log.v(LOG_TAG, "print state depository: " + printStates()); 74 if (mTransitionDirection == DO_NOTHING) { 75 if (mStateDepository.isEmpty()) { 76 Log.v(LOG_TAG, "no state is recorded"); 77 mReason = "no state is recorded."; 78 return false; 79 } else if (mStateDepository.size() > 1) { 80 Log.v(LOG_TAG, "no broadcast is expected, " + 81 "instead broadcast is probably received"); 82 mReason = "no broadcast is expected, instead broadcast is probably received"; 83 return false; 84 } else if (mStateDepository.get(0) != mTransitionTarget) { 85 Log.v(LOG_TAG, mTransitionTarget + " is expected, but it is " + 86 mStateDepository.get(0)); 87 mReason = mTransitionTarget + " is expected, but it is " + mStateDepository.get(0); 88 return false; 89 } 90 return true; 91 } else if (mTransitionDirection == TO_CONNECTION) { 92 Log.v(LOG_TAG, "transition to CONNECTED"); 93 return transitToConnection(); 94 } else { 95 Log.v(LOG_TAG, "transition to DISCONNECTED"); 96 return transitToDisconnection(); 97 } 98 } 99 100 /* 101 * Transition from CONNECTED -> DISCONNECTED: 102 * CONNECTED->DISCONNECTING->DISCONNECTED 103 * return false if any state transition is not valid and save a message in mReason 104 */ 105 public boolean transitToDisconnection () { 106 mReason = "states: " + printStates(); 107 if (mStateDepository.get(0) != State.CONNECTED) { 108 mReason += " initial state should be CONNECTED, but it is " + 109 mStateDepository.get(0) + "."; 110 return false; 111 } 112 State lastState = mStateDepository.get(mStateDepository.size() - 1); 113 if ( lastState != mTransitionTarget) { 114 mReason += " the last state should be DISCONNECTED, but it is " + lastState; 115 return false; 116 } 117 for (int i = 1; i < mStateDepository.size() - 1; i++) { 118 State preState = mStateDepository.get(i-1); 119 State curState = mStateDepository.get(i); 120 if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) || 121 (curState == State.DISCONNECTED))) { 122 continue; 123 } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) { 124 continue; 125 } else if ((preState == State.DISCONNECTED) && (curState == State.DISCONNECTED)) { 126 continue; 127 } else { 128 mReason += " Transition state from " + preState.toString() + " to " + 129 curState.toString() + " is not valid."; 130 return false; 131 } 132 } 133 return true; 134 } 135 136 // DISCONNECTED->CONNECTING->CONNECTED 137 public boolean transitToConnection() { 138 mReason = "states: " + printStates(); 139 if (mStateDepository.get(0) != State.DISCONNECTED) { 140 mReason += " initial state should be DISCONNECTED, but it is " + 141 mStateDepository.get(0) + "."; 142 return false; 143 } 144 State lastState = mStateDepository.get(mStateDepository.size() - 1); 145 if ( lastState != mTransitionTarget) { 146 mReason += "The last state should be " + mTransitionTarget + ", but it is " + lastState; 147 return false; 148 } 149 for (int i = 1; i < mStateDepository.size(); i++) { 150 State preState = mStateDepository.get(i-1); 151 State curState = mStateDepository.get(i); 152 if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) || 153 (curState == State.CONNECTED) || (curState == State.DISCONNECTED))) { 154 continue; 155 } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) { 156 continue; 157 } else if ((preState == State.CONNECTED) && (curState == State.CONNECTED)) { 158 continue; 159 } else { 160 mReason += " Transition state from " + preState.toString() + " to " + 161 curState.toString() + " is not valid."; 162 return false; 163 } 164 } 165 return true; 166 } 167 168 public List<State> getTransitionStates() { 169 return mStateDepository; 170 } 171 172 // return state failure mReason 173 public String getReason() { 174 return mReason; 175 } 176 177 public String printStates() { 178 StringBuilder stateBuilder = new StringBuilder(""); 179 for (int i = 0; i < mStateDepository.size(); i++) { 180 stateBuilder.append(" ").append(mStateDepository.get(i).toString()).append("->"); 181 } 182 return stateBuilder.toString(); 183 } 184 185 @Override 186 public String toString() { 187 StringBuilder builder = new StringBuilder(" "); 188 builder.append("mTransitionDirection: ").append(Integer.toString(mTransitionDirection)). 189 append("; ").append("states:"). 190 append(printStates()).append("; "); 191 return builder.toString(); 192 } 193 } 194