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 * Transition from CONNECTED -> DISCONNECTED: 105 * CONNECTED->DISCONNECTING->DISCONNECTED 106 * return false if any state transition is not valid and save a message in mReason 107 */ 108 public boolean transitToDisconnection () { 109 mReason = "states: " + printStates(); 110 if (mStateDepository.get(0) != State.CONNECTED) { 111 mReason += " initial state should be CONNECTED, but it is " + 112 mStateDepository.get(0) + "."; 113 return false; 114 } 115 State lastState = mStateDepository.get(mStateDepository.size() - 1); 116 if ( lastState != mTransitionTarget) { 117 mReason += " the last state should be DISCONNECTED, but it is " + lastState; 118 return false; 119 } 120 for (int i = 1; i < mStateDepository.size() - 1; i++) { 121 State preState = mStateDepository.get(i-1); 122 State curState = mStateDepository.get(i); 123 if ((preState == State.CONNECTED) && ((curState == State.DISCONNECTING) || 124 (curState == State.DISCONNECTED))) { 125 continue; 126 } else if ((preState == State.DISCONNECTING) && (curState == State.DISCONNECTED)) { 127 continue; 128 } else if ((preState == State.DISCONNECTED) && (curState == State.DISCONNECTED)) { 129 continue; 130 } else { 131 mReason += " Transition state from " + preState.toString() + " to " + 132 curState.toString() + " is not valid."; 133 return false; 134 } 135 } 136 return true; 137 } 138 139 // DISCONNECTED->CONNECTING->CONNECTED 140 public boolean transitToConnection() { 141 mReason = "states: " + printStates(); 142 if (mStateDepository.get(0) != State.DISCONNECTED) { 143 mReason += " initial state should be DISCONNECTED, but it is " + 144 mStateDepository.get(0) + "."; 145 return false; 146 } 147 State lastState = mStateDepository.get(mStateDepository.size() - 1); 148 if ( lastState != mTransitionTarget) { 149 mReason += "The last state should be " + mTransitionTarget + ", but it is " + lastState; 150 return false; 151 } 152 for (int i = 1; i < mStateDepository.size(); i++) { 153 State preState = mStateDepository.get(i-1); 154 State curState = mStateDepository.get(i); 155 if ((preState == State.DISCONNECTED) && ((curState == State.CONNECTING) || 156 (curState == State.CONNECTED) || (curState == State.DISCONNECTED))) { 157 continue; 158 } else if ((preState == State.CONNECTING) && (curState == State.CONNECTED)) { 159 continue; 160 } else if ((preState == State.CONNECTED) && (curState == State.CONNECTED)) { 161 continue; 162 } else { 163 mReason += " Transition state from " + preState.toString() + " to " + 164 curState.toString() + " is not valid."; 165 return false; 166 } 167 } 168 return true; 169 } 170 171 public List<State> getTransitionStates() { 172 return mStateDepository; 173 } 174 175 // return state failure mReason 176 public String getReason() { 177 return mReason; 178 } 179 180 public String printStates() { 181 StringBuilder stateBuilder = new StringBuilder(""); 182 for (int i = 0; i < mStateDepository.size(); i++) { 183 stateBuilder.append(" ").append(mStateDepository.get(i).toString()).append("->"); 184 } 185 return stateBuilder.toString(); 186 } 187 188 @Override 189 public String toString() { 190 StringBuilder builder = new StringBuilder(" "); 191 builder.append("mTransitionDirection: ").append(Integer.toString(mTransitionDirection)). 192 append("; ").append("states:"). 193 append(printStates()).append("; "); 194 return builder.toString(); 195 } 196} 197