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 17package com.android.connectivitymanagertest; 18 19import android.net.NetworkInfo.State; 20import android.util.Log; 21 22import java.util.List; 23import java.util.ArrayList; 24 25public 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 for (int i = 0; i < mStateDepository.size(); i++) { 81 if (mStateDepository.get(i) != mTransitionTarget) { 82 Log.v(LOG_TAG, "state changed."); 83 mReason = "Unexpected state change"; 84 return false; 85 } 86 } 87 } else if (mStateDepository.get(0) != mTransitionTarget) { 88 Log.v(LOG_TAG, mTransitionTarget + " is expected, but it is " + 89 mStateDepository.get(0)); 90 mReason = mTransitionTarget + " is expected, but it is " + mStateDepository.get(0); 91 return false; 92 } 93 return true; 94 } else if (mTransitionDirection == TO_CONNECTION) { 95 Log.v(LOG_TAG, "transition to CONNECTED"); 96 return transitToConnection(); 97 } else { 98 Log.v(LOG_TAG, "transition to DISCONNECTED"); 99 return transitToDisconnection(); 100 } 101 } 102 103 /* 104 * Verifies state transition from CONNECTED->...-> DISCONNECTED. 105 * 106 * returns false if initial state or target state is not correct, or if there is 107 * any transition from DISCONNECTING/DISCONNECTED -> CONNECTED. 108 */ 109 public boolean transitToDisconnection () { 110 mReason = "states: " + printStates(); 111 if (mStateDepository.get(0) != State.CONNECTED) { 112 mReason += " initial state should be CONNECTED, but it is " + 113 mStateDepository.get(0) + "."; 114 return false; 115 } 116 State lastState = mStateDepository.get(mStateDepository.size() - 1); 117 if ( lastState != mTransitionTarget) { 118 mReason += " the last state should be DISCONNECTED, but it is " + lastState; 119 return false; 120 } 121 for (int i = 1; i < mStateDepository.size() - 1; i++) { 122 State preState = mStateDepository.get(i-1); 123 State curState = mStateDepository.get(i); 124 if (preState == curState) { 125 continue; 126 } else if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) || 127 (curState == State.DISCONNECTED))) { 128 continue; 129 } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) { 130 continue; 131 } else { 132 mReason += " Transition state from " + preState.toString() + " to " + 133 curState.toString() + " is not valid."; 134 return false; 135 } 136 } 137 return true; 138 } 139 140 /* 141 * Verifies state transition from DISCONNECTED->...-> CONNECTED. 142 * 143 * returns false if initial state or target state is not correct, or if there is 144 * any transition from CONNECED -> DISCONNECTED. 145 */ 146 public boolean transitToConnection() { 147 mReason = "states: " + printStates(); 148 if (mStateDepository.get(0) != State.DISCONNECTED) { 149 mReason += " initial state should be DISCONNECTED, but it is " + 150 mStateDepository.get(0) + "."; 151 return false; 152 } 153 State lastState = mStateDepository.get(mStateDepository.size() - 1); 154 if ( lastState != mTransitionTarget) { 155 mReason += "The last state should be " + mTransitionTarget + ", but it is " + lastState; 156 return false; 157 } 158 for (int i = 1; i < mStateDepository.size(); i++) { 159 State preState = mStateDepository.get(i-1); 160 State curState = mStateDepository.get(i); 161 if (preState == curState) { 162 continue; 163 } 164 if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) || 165 (curState == State.CONNECTED))) { 166 continue; 167 } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) { 168 continue; 169 } else { 170 mReason += " Transition state from " + preState.toString() + " to " + 171 curState.toString() + " is not valid."; 172 return false; 173 } 174 } 175 return true; 176 } 177 178 public List<State> getTransitionStates() { 179 return mStateDepository; 180 } 181 182 // return state failure mReason 183 public String getReason() { 184 return mReason; 185 } 186 187 public String printStates() { 188 StringBuilder stateBuilder = new StringBuilder(""); 189 for (int i = 0; i < mStateDepository.size(); i++) { 190 stateBuilder.append(" ").append(mStateDepository.get(i).toString()).append("->"); 191 } 192 return stateBuilder.toString(); 193 } 194 195 @Override 196 public String toString() { 197 StringBuilder builder = new StringBuilder(" "); 198 builder.append("mTransitionDirection: ").append(Integer.toString(mTransitionDirection)). 199 append("; ").append("states:"). 200 append(printStates()).append("; "); 201 return builder.toString(); 202 } 203} 204