/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* src/com/vodafone360/people/VODAFONE.LICENSE.txt or
* http://github.com/360/360-Engine-for-Android
* See the License for the specific language governing permissions and
* limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each file and
* include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the fields
* enclosed by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved.
* Use is subject to license terms.
*/
package com.vodafone360.people.service.agent;
import java.security.InvalidParameterException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
import com.vodafone360.people.Intents;
import com.vodafone360.people.MainApplication;
import com.vodafone360.people.engine.EngineManager;
import com.vodafone360.people.service.PersistSettings;
import com.vodafone360.people.service.RemoteService;
import com.vodafone360.people.service.ServiceStatus;
import com.vodafone360.people.service.PersistSettings.InternetAvail;
import com.vodafone360.people.service.interfaces.IConnectionManagerInterface;
import com.vodafone360.people.service.interfaces.IWorkerThreadControl;
import com.vodafone360.people.utils.LogUtils;
/**
* The network Agent monitors the connectivity status of the device and makes
* decisions about the communication strategy. The Agent has the following
* states {connected | disconnected}, with changes reported to various listeners
* in the service.
*/
public class NetworkAgent {
/** Roaming notification is on */
public static final int ROAMING_DIALOG_GLOBAL_ON = 0;
/** Roaming notification is off */
public static final int ROAMING_DIALOG_GLOBAL_OFF = 1;
private static final int TYPE_WIFI = 1;
private static AgentState mAgentState = AgentState.UNKNOWN;
private ConnectivityManager mConnectivityManager;
private ContentResolver mContentResolver;
private static AgentDisconnectReason sDisconnectReason = AgentDisconnectReason.UNKNOWN;
private SettingsContentObserver mDataRoamingSettingObserver;
private boolean mInternetConnected;
private boolean mDataRoaming;
private boolean mBackgroundData;
private boolean mIsRoaming;
private boolean mIsInBackground;
private boolean mNetworkWorking = true;
// dateTime value in milliseconds
private Long mDisableRoamingNotificationUntil = null;
private IWorkerThreadControl mWorkerThreadControl;
private IConnectionManagerInterface mConnectionMgrIf;
private Context mContext;
/**
* 2G Voice call started string
*/
private static final String VOICE_CALL_STARTED_2G_STRING = "2GVoiceCallStarted";
/**
* 2G Voice call finished string.
*/
private static final String VOICE_CALL_ENDED_2G_STRING = "2GVoiceCallEnded";
/**
* To hold network info
*/
private NetworkInfo mNetworkInfo = null;
/**
* Resume contact sync if 2G call has finished.
*/
private boolean mIsResumeSync = false;
public enum AgentState {
CONNECTED,
DISCONNECTED,
UNKNOWN
};
private boolean mWifiNetworkAvailable;
private boolean mMobileNetworkAvailable;
/**
* Reasons for Service Agent changing state to disconnected
*/
public enum AgentDisconnectReason {
AGENT_IS_CONNECTED, // Sanity check
NO_INTERNET_CONNECTION,
NO_WORKING_NETWORK,
DATA_SETTING_SET_TO_MANUAL_CONNECTION,
DATA_ROAMING_DISABLED,
BACKGROUND_CONNECTION_DISABLED,
// WIFI_INACTIVE,
UNKNOWN
}
public enum StatesOfService {
IS_CONNECTED_TO_INTERNET,
IS_NETWORK_WORKING,
IS_ROAMING,
IS_ROAMING_ALLOWED,
IS_INBACKGROUND,
IS_BG_CONNECTION_ALLOWED,
IS_WIFI_ACTIVE
};
/**
* Listens for changes made to People client's status. The NetworkAgent is
* specifically interested in changes to the data settings (e.g. data
* disabled, only in home network or roaming).
*/
private class SettingsContentObserver extends ContentObserver {
private String mSettingName;
private SettingsContentObserver(String settingName) {
super(new Handler());
mSettingName = settingName;
}
/**
* Start content observer.
*/
private void start() {
if (mContentResolver != null) {
mContentResolver.registerContentObserver(Settings.Secure.getUriFor(mSettingName),
true, this);
}
}
/**
* De-activate content observer.
*/
private void close() {
if (mContentResolver != null) {
mContentResolver.unregisterContentObserver(this);
}
}
@Override
public void onChange(boolean selfChange) {
onDataSettingChanged(mSettingName);
}
public boolean getBooleanValue() {
if (mContentResolver != null) {
try {
return (Settings.Secure.getInt(mContentResolver, mSettingName) != 0);
} catch (SettingNotFoundException e) {
LogUtils.logE("NetworkAgent.SettingsContentObserver.getBooleanValue() "
+ "SettingNotFoundException", e);
return false;
}
}
return false;
}
}
/**
* The constructor.
*
* @param context Android context.
* @param workerThreadControl Handle to kick the worker thread.
* @param connMgrIf Handler to signal the connection manager.
* @throws InvalidParameterException Context is NULL.
* @throws InvalidParameterException IWorkerThreadControl is NULL.
* @throws InvalidParameterException IConnectionManagerInterface is NULL.
*/
public NetworkAgent(Context context, IWorkerThreadControl workerThreadControl,
IConnectionManagerInterface connMgrIf) {
if (context == null) {
throw new InvalidParameterException("NetworkAgent() Context canot be NULL");
}
if (workerThreadControl == null) {
throw new InvalidParameterException("NetworkAgent() IWorkerThreadControl canot be NULL");
}
if (connMgrIf == null) {
throw new InvalidParameterException(
"NetworkAgent() IConnectionManagerInterface canot be NULL");
}
mContext = context;
mWorkerThreadControl = workerThreadControl;
mConnectionMgrIf = connMgrIf;
mContentResolver = context.getContentResolver();
mConnectivityManager = (ConnectivityManager)context
.getSystemService(Context.CONNECTIVITY_SERVICE);
mDataRoamingSettingObserver = new SettingsContentObserver(Settings.Secure.DATA_ROAMING);
}
/**
* Create NetworkAgent and start observers of device connectivity state.
*
* @throws InvalidParameterException DataRoamingSettingObserver is NULL.
* @throws InvalidParameterException Context is NULL.
* @throws InvalidParameterException ConnectivityManager is NULL.
*/
public void onCreate() {
if (mDataRoamingSettingObserver == null) {
throw new InvalidParameterException(
"NetworkAgent.onCreate() DataRoamingSettingObserver canot be NULL");
}
if (mContext == null) {
throw new InvalidParameterException("NetworkAgent.onCreate() Context canot be NULL");
}
if (mConnectivityManager == null) {
throw new InvalidParameterException(
"NetworkAgent.onCreate() ConnectivityManager canot be NULL");
}
mDataRoamingSettingObserver.start();
mDataRoaming = mDataRoamingSettingObserver.getBooleanValue();
mContext.registerReceiver(mBackgroundDataBroadcastReceiver, new IntentFilter(
ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED));
mContext.registerReceiver(mInternetConnectivityReceiver, new IntentFilter(
ConnectivityManager.CONNECTIVITY_ACTION));
mContext.registerReceiver(mServiceStateRoamingReceiver, new IntentFilter(
"android.intent.action.SERVICE_STATE"));
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
if (info != null) {
mInternetConnected = (info.getState() == NetworkInfo.State.CONNECTED);
mWifiNetworkAvailable = (info.getType() == TYPE_WIFI);
mIsRoaming = info.isRoaming();
}
mBackgroundData = mConnectivityManager.getBackgroundDataSetting();
onConnectionStateChanged();
}
/**
* Destroy NetworkAgent and un-register observers.
*
* @throws InvalidParameterException Context is NULL.
* @throws InvalidParameterException DataRoamingSettingObserver is NULL.
*/
public void onDestroy() {
if (mContext == null) {
throw new InvalidParameterException("NetworkAgent.onCreate() Context canot be NULL");
}
if (mDataRoamingSettingObserver == null) {
throw new InvalidParameterException(
"NetworkAgent.onDestroy() DataRoamingSettingObserver canot be NULL");
}
mContext.unregisterReceiver(mInternetConnectivityReceiver);
mContext.unregisterReceiver(mBackgroundDataBroadcastReceiver);
mContext.unregisterReceiver(mServiceStateRoamingReceiver);
mDataRoamingSettingObserver.close();
mDataRoamingSettingObserver = null;
}
/**
* Receive notification from
* ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED
*/
private final BroadcastReceiver mBackgroundDataBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
LogUtils
.logV("NetworkAgent.broadcastReceiver.onReceive() ACTION_BACKGROUND_DATA_SETTING_CHANGED");
synchronized (NetworkAgent.this) {
if (mConnectivityManager != null) {
mBackgroundData = mConnectivityManager.getBackgroundDataSetting();
onConnectionStateChanged();
}
}
}
};
/**
* Receive notification from ConnectivityManager.CONNECTIVITY_ACTION
*/
private final BroadcastReceiver mInternetConnectivityReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
LogUtils.logV("NetworkAgent.broadcastReceiver.onReceive() CONNECTIVITY_ACTION");
synchronized (NetworkAgent.this) {
NetworkInfo info = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
mNetworkInfo = info;
boolean noConnectivity = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (info != null) {
// Check network type
if (info.getType() == TYPE_WIFI) {
mWifiNetworkAvailable = (info.getState() == NetworkInfo.State.CONNECTED);
} else {
mMobileNetworkAvailable = (info.getState() == NetworkInfo.State.CONNECTED);
}
} else {
LogUtils.logW("NetworkAgent.broadcastReceiver.onReceive() EXTRA_NETWORK_INFO not found.");
}
if (noConnectivity) {
LogUtils.logV("NetworkAgent.broadcastReceiver.onReceive() EXTRA_NO_CONNECTIVITY found!");
mInternetConnected = false;
} else {
mInternetConnected = mWifiNetworkAvailable || mMobileNetworkAvailable;
}
LogUtils.logV("NetworkAgent.broadcastReceiver.onReceive() mInternetConnected = " + mInternetConnected +
", mWifiNetworkAvailable = " + mWifiNetworkAvailable +
", mMobileNetworkAvailable = " + mMobileNetworkAvailable);
onConnectionStateChanged();
}
}
};
/**
* Receive notification from android.intent.action.SERVICE_STATE
*/
private final BroadcastReceiver mServiceStateRoamingReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
LogUtils.logV("NetworkAgent.broadcastReceiver.onReceive() SERVICE_STATE");
synchronized (NetworkAgent.this) {
// //ConnectivityManager provides wrong information about
// roaming
// NetworkInfo info =
// mConnectivityManager.getActiveNetworkInfo();
// if (info != null) {
// mIsRoaming = info.isRoaming();
// }
LogUtils.logV("NetworkAgent.broadcastReceiver.onReceive() Extras are: "
+ intent.getExtras());
Bundle bu = intent.getExtras();
// int state = bu.getInt("state");
boolean roam = bu.getBoolean("roaming");
mIsRoaming = roam;
onConnectionStateChanged();
LogUtils.logV("NetworkAgent.broadcastReceiver.onReceive() Network Roaming = "
+ mIsRoaming);
LogUtils.logV("NetworkAgent.broadcastReceiver.onReceive() WiFi active = "
+ mWifiNetworkAvailable);
}
processRoaming(null);
}
};
/**
* Notify interested parties of changes in Internet setting.
*
* @param val updated InternetAvail value.
*/
public void notifyDataSettingChanged(InternetAvail val) {
processRoaming(val);
onConnectionStateChanged();
}
/**
* Displaying notification to the user about roaming
*
* @param InternetAvail value.
*/
private void processRoaming(InternetAvail val) {
InternetAvail internetAvail;
if (val != null) {
internetAvail = val;
} else {
internetAvail = getInternetAvailSetting();
}
Intent intent = new Intent();
if (mContext != null
&& mIsRoaming
&& (internetAvail == InternetAvail.ALWAYS_CONNECT)
&& (mDisableRoamingNotificationUntil == null || mDisableRoamingNotificationUntil < System
.currentTimeMillis())) {
LogUtils.logV("NetworkAgent.processRoaming() "
+ "Displaying notification - DisplayRoaming[" + mIsRoaming + "]");
intent.setAction(Intents.ROAMING_ON);
} else {
/*
* We are not roaming then we should remove notification, if no
* notification were before nothing happens
*/
LogUtils.logV("NetworkAgent.processRoaming() Removing notification - "
+ " DisplayRoaming[" + mIsRoaming + "]");
intent.setAction(Intents.ROAMING_OFF);
}
mContext.sendBroadcast(intent);
}
private InternetAvail getInternetAvailSetting() {
if (mContext != null) {
PersistSettings setting = ((MainApplication)((RemoteService)mContext).getApplication())
.getDatabase().fetchOption(PersistSettings.Option.INTERNETAVAIL);
if (setting != null) {
return setting.getInternetAvail();
}
}
return null;
}
public int getRoamingNotificationType() {
int type;
if (mDataRoaming) {
type = ROAMING_DIALOG_GLOBAL_ON;
} else {
type = ROAMING_DIALOG_GLOBAL_OFF;
}
return type;
}
/**
* Get current device roaming setting.
*
* @return current device roaming setting.
*/
public boolean getRoamingDeviceSetting() {
return mDataRoaming;
}
public void setShowRoamingNotificationAgain(boolean showAgain) {
LogUtils.logV("NetworkAgent.setShowRoamingNotificationAgain() " + "showAgain[" + showAgain
+ "]");
if (showAgain) {
mDisableRoamingNotificationUntil = null;
} else {
mDisableRoamingNotificationUntil = System.currentTimeMillis() + DateUtils.DAY_IN_MILLIS;
if (mContext != null) {
LogUtils.logV("NetworkAgent.setShowRoamingNotificationAgain() "
+ "Next notification on ["
+ DateUtils.formatDateTime(mContext, mDisableRoamingNotificationUntil,
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR) + "]");
}
}
processRoaming(null);
}
/**
* Received when user modifies one of the system settings
*/
private synchronized void onDataSettingChanged(String settingName) {
LogUtils.logV("NetworkAgent.onDataSettingChanged() settingName[" + settingName + "]"
+ " has changed");
if (settingName.equals(Settings.Secure.DATA_ROAMING)) {
if (mDataRoamingSettingObserver != null) {
mDataRoaming = mDataRoamingSettingObserver.getBooleanValue();
onConnectionStateChanged();
}
}
}
/**
* Contains the main logic that determines the agent state for network
* access
*/
private void onConnectionStateChanged() {
if (mContext != null) {
MainApplication app = (MainApplication)((RemoteService)mContext).getApplication();
if ((app.getInternetAvail() == InternetAvail.MANUAL_CONNECT)) {
LogUtils.logV("NetworkAgent.onConnectionStateChanged()"
+ " Internet allowed only in manual mode");
sDisconnectReason = AgentDisconnectReason.DATA_SETTING_SET_TO_MANUAL_CONNECTION;
setNewState(AgentState.DISCONNECTED);
return;
}
}
if (!mNetworkWorking) {
LogUtils.logV("NetworkAgent.onConnectionStateChanged() Network is not working");
sDisconnectReason = AgentDisconnectReason.NO_WORKING_NETWORK;
setNewState(AgentState.DISCONNECTED);
return;
}
if (mIsRoaming && !mDataRoaming && !mWifiNetworkAvailable) {
LogUtils.logV("NetworkAgent.onConnectionStateChanged() "
+ "Connect while roaming not allowed");
sDisconnectReason = AgentDisconnectReason.DATA_ROAMING_DISABLED;
setNewState(AgentState.DISCONNECTED);
return;
}
if (mIsInBackground && !mBackgroundData) {
LogUtils.logV("NetworkAgent.onConnectionStateChanged() Background connection not allowed");
sDisconnectReason = AgentDisconnectReason.BACKGROUND_CONNECTION_DISABLED;
setNewState(AgentState.DISCONNECTED);
return;
}
if (!mInternetConnected) {
LogUtils.logV("NetworkAgent.onConnectionStateChanged() No internet connection");
sDisconnectReason = AgentDisconnectReason.NO_INTERNET_CONNECTION;
// If 2g call is started, notify contact sync engine to pause.
if (mNetworkInfo != null &&
VOICE_CALL_STARTED_2G_STRING.equals(mNetworkInfo.getReason())) {
EngineManager.getInstance().getContactSyncEngine().pauseSync();
}
setNewState(AgentState.DISCONNECTED);
return;
}
// If 2g voice call is finished, set resume state
if (mNetworkInfo != null &&
VOICE_CALL_ENDED_2G_STRING.equals(mNetworkInfo.getReason())) {
mIsResumeSync = true;
}
if (mWifiNetworkAvailable) {
LogUtils.logV("NetworkAgent.onConnectionStateChanged() WIFI connected");
} else {
LogUtils.logV("NetworkAgent.onConnectionStateChanged() Cellular connected");
}
LogUtils.logV("NetworkAgent.onConnectionStateChanged() Connection available");
setNewState(AgentState.CONNECTED);
}
public static AgentState getAgentState() {
LogUtils.logV("NetworkAgent.getAgentState() mAgentState[" + mAgentState.name() + "]");
return mAgentState;
}
public static ServiceStatus getServiceStatusfromDisconnectReason() {
if (sDisconnectReason != null)
switch (sDisconnectReason)
{
case AGENT_IS_CONNECTED:
return ServiceStatus.SUCCESS;
case NO_WORKING_NETWORK:
return ServiceStatus.ERROR_NO_INTERNET;
case NO_INTERNET_CONNECTION:
return ServiceStatus.ERROR_NO_INTERNET;
case DATA_ROAMING_DISABLED:
return ServiceStatus.ERROR_ROAMING_INTERNET_NOT_ALLOWED;
case DATA_SETTING_SET_TO_MANUAL_CONNECTION:
return ServiceStatus.ERROR_NO_AUTO_CONNECT;
case BACKGROUND_CONNECTION_DISABLED:
// TODO: define appropriate ServiceStatus
return ServiceStatus.ERROR_COMMS;
}
return ServiceStatus.ERROR_COMMS;
}
private void setNewState(AgentState newState) {
if (newState == mAgentState) {
return;
}
LogUtils.logI("NetworkAgent.setNewState(): " + mAgentState + " -> " + newState);
mAgentState = newState;
if (newState == AgentState.CONNECTED) {
sDisconnectReason = AgentDisconnectReason.AGENT_IS_CONNECTED;
onConnected();
} else if (newState == AgentState.DISCONNECTED) {
onDisconnected();
}
}
private void onConnected() {
checkActiveNetworkState();
if (mWorkerThreadControl != null) {
mWorkerThreadControl.kickWorkerThread();
}
if (mConnectionMgrIf != null) {
mConnectionMgrIf.signalConnectionManager(true);
}
// If resume sync is set, signal contact sync engine to resume sync.
if (mIsResumeSync) {
EngineManager.getInstance().getContactSyncEngine().resumeSync();
mIsResumeSync = false;
}
}
private void onDisconnected() {
// AA:need to kick it to make engines run and set the
if (mWorkerThreadControl != null) {
mWorkerThreadControl.kickWorkerThread();
}
if (mConnectionMgrIf != null) {
mConnectionMgrIf.signalConnectionManager(false);
}
}
private void checkActiveNetworkState() {
if (mConnectivityManager != null) {
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if (mNetworkInfo == null) {
LogUtils.logW("NetworkAgent.checkActiveNetworkInfoy() "
+ "mConnectivityManager.getActiveNetworkInfo() Returned null");
return;
} else {
if (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
LogUtils.logV("NetworkAgent.checkActiveNetworkInfoy() WIFI network");
// TODO: Do something
} else if (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
LogUtils.logV("NetworkAgent.checkActiveNetworkInfoy() MOBILE and ROAMING");
// TODO: Do something
// Only works when you are registering with network
switch (mNetworkInfo.getSubtype()) {
case TelephonyManager.NETWORK_TYPE_EDGE:
LogUtils
.logV("NetworkAgent.checkActiveNetworkInfoy() MOBILE EDGE network");
// TODO: Do something
break;
case TelephonyManager.NETWORK_TYPE_GPRS:
LogUtils
.logV("NetworkAgent.checkActiveNetworkInfoy() MOBILE GPRS network");
// TODO: Do something
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
LogUtils
.logV("NetworkAgent.checkActiveNetworkInfoy() MOBILE UMTS network");
// TODO: Do something
break;
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
LogUtils
.logV("NetworkAgent.checkActiveNetworkInfoy() MOBILE UNKNOWN network");
// TODO: Do something
break;
default:
// Do nothing.
break;
}
;
}
}
} else {
LogUtils.logW("NetworkAgent.checkActiveNetworkInfoy() mConnectivityManager is null");
}
}
public void setNetworkAgentState(NetworkAgentState state) {
LogUtils.logD("NetworkAgent.setNetworkAgentState() state[" + state + "]");
// TODO: make assignments if any changes
boolean changes[] = state.getChanges();
if (changes[StatesOfService.IS_CONNECTED_TO_INTERNET.ordinal()])
mInternetConnected = state.isInternetConnected();
if (changes[StatesOfService.IS_NETWORK_WORKING.ordinal()])
mNetworkWorking = state.isNetworkWorking();
if (changes[StatesOfService.IS_ROAMING_ALLOWED.ordinal()])
mDataRoaming = state.isRoamingAllowed();
if (changes[StatesOfService.IS_INBACKGROUND.ordinal()])
mIsInBackground = state.isInBackGround();
if (changes[StatesOfService.IS_BG_CONNECTION_ALLOWED.ordinal()])
mBackgroundData = state.isBackDataAllowed();
if (changes[StatesOfService.IS_WIFI_ACTIVE.ordinal()])
mWifiNetworkAvailable = state.isWifiActive();
if (changes[StatesOfService.IS_ROAMING.ordinal()]) {// special case for
// roaming
mIsRoaming = state.isRoaming();
// This method sets the mAgentState, and mDisconnectReason as well
// by calling setNewState();
onConnectionStateChanged();
processRoaming(null);
} else
// This method sets the mAgentState, and mDisconnectReason as well
// by calling setNewState();
onConnectionStateChanged();
}
public NetworkAgentState getNetworkAgentState() {
NetworkAgentState state = new NetworkAgentState();
state.setRoaming(mIsRoaming);
state.setRoamingAllowed(mDataRoaming);
state.setBackgroundDataAllowed(mBackgroundData);
state.setInBackGround(mIsInBackground);
state.setInternetConnected(mInternetConnected);
state.setNetworkWorking(mNetworkWorking);
state.setWifiActive(mWifiNetworkAvailable);
state.setDisconnectReason(sDisconnectReason);
state.setAgentState(mAgentState);
LogUtils.logD("NetworkAgent.getNetworkAgentState() state[" + state + "]");
return state;
}
// /////////////////////////////
// FOR TESTING PURPOSES ONLY //
// /////////////////////////////
/**
* Forces the AgentState to a specific value.
*
* @param newState the state to set Note: to be used only for test purposes
*/
public static void setAgentState(AgentState newState) {
mAgentState = newState;
}
}