mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-10 23:57:25 -05:00
Resolves threading issue in ChannelState.
Resolves issue in tuner controller where controller was not releasing sourced tuner channels, preventing re-tuning to other frequencies. Resolves issue with channel timeout on MPT1327 monitored traffic channels
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
* Copyright (C) 2014-2016 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -22,16 +22,9 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import module.Module;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.ICallEventProvider;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import audio.metadata.IMetadataProvider;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataReset;
|
||||
@@ -41,38 +34,13 @@ import audio.squelch.SquelchState;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import module.Module;
|
||||
import module.decode.config.DecodeConfiguration;
|
||||
import module.decode.event.CallEvent;
|
||||
import module.decode.event.ICallEventProvider;
|
||||
import module.decode.state.DecoderStateEvent.Event;
|
||||
import sample.Listener;
|
||||
|
||||
/**
|
||||
* Channel state tracks the overall state of all processing modules and decoders
|
||||
* configured for the channel and provides squelch control events.
|
||||
*
|
||||
* Primary channel state provides a state machine for tracking decode events
|
||||
* during a voice or data call through it's life cycle of CALL/DATA, FADE, END,
|
||||
* and then back to an IDLE state. This class also provides squelch control
|
||||
* to support any audio processing.
|
||||
*
|
||||
* State Descriptions:
|
||||
* IDLE No voice or data call activity
|
||||
* CALL/DATA A voice or data call has started, or is continuing
|
||||
* CONTROL Control channel
|
||||
* FADE The phase after a voice or data call when either an explicit
|
||||
* call end has been received, or when no new signalling updates
|
||||
* have been received, and the fade timer has expired. This phase
|
||||
* allows for gui updates to signal to the user that the call is
|
||||
* ended, while continuing to display the call details for the user
|
||||
* END The phase after the voice or data call FADE, when the call is
|
||||
* now over, and the gui should be reset to IDLE.
|
||||
*
|
||||
* When a call is started, invoke mTimerService.startFadeTimer() to start the
|
||||
* call fade monitoring timer process that will automatically signal a call end
|
||||
* once no more call signalling has been detected after the fade timeout has
|
||||
* occurred, by invoking the fade() method.
|
||||
*
|
||||
* When a call ends, invoke the mTimerService.stopFadeTimer() and then invoke
|
||||
* the mTimerService.startResetTimer(). Once the reset timeout occurs,
|
||||
* the reset() method will be called, allowing the channel state to perform
|
||||
* any reset actions, like clearing status and id labels on any view panels.
|
||||
*/
|
||||
public class ChannelState extends Module implements ICallEventProvider,
|
||||
IChangedAttributeProvider, IDecoderStateEventListener,
|
||||
IDecoderStateEventProvider, IMetadataProvider, ISquelchStateProvider
|
||||
@@ -84,8 +52,6 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
public static final long RESET_TIMEOUT_DELAY = 2000;
|
||||
|
||||
private State mState = State.IDLE;
|
||||
private long mTrafficChannelTimeout =
|
||||
DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS;
|
||||
|
||||
private Listener<CallEvent> mCallEventListener;
|
||||
private Listener<ChangedAttribute> mChangedAttributeListener;
|
||||
@@ -98,12 +64,15 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
private boolean mSquelchLocked = false;
|
||||
private boolean mSelected = false;
|
||||
|
||||
private long mStandardChannelFadeTimeout = FADE_TIMEOUT_DELAY;
|
||||
private long mTrafficChannelFadeTimeout =
|
||||
DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS * 1000;
|
||||
private long mFadeTimeout;
|
||||
private long mResetTimeout;
|
||||
private long mEndTimeout;
|
||||
|
||||
private StateMonitor mStateMonitor = new StateMonitor();
|
||||
private AtomicBoolean mMonitoring = new AtomicBoolean();
|
||||
private ScheduledFuture<?> mRunningMonitor;
|
||||
private ScheduledFuture<?> mStateMonitorFuture;
|
||||
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ChannelType mChannelType;
|
||||
@@ -111,15 +80,48 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
private TrafficChannelStatusListener mTrafficChannelStatusListener;
|
||||
private CallEvent mTrafficChannelCallEvent;
|
||||
|
||||
/**
|
||||
* Channel state tracks the overall state of all processing modules and decoders
|
||||
* configured for the channel and provides squelch control events.
|
||||
*
|
||||
* Uses a state enumeration that defines allowable channel state transitions in
|
||||
* order to track a call or data decode event from start to finish. Uses a
|
||||
* timer to monitor for inactivity and to provide a FADE period that indicates
|
||||
* to the user that the activity has stopped while continuing to provide details
|
||||
* about the call, before the state is reset to IDLE.
|
||||
*
|
||||
* Since this class is multi-threaded between decoder events and the internal
|
||||
* timer that monitors for inactivity, this class uses the mState object for
|
||||
* thread synchronization.
|
||||
*
|
||||
* State Descriptions:
|
||||
* IDLE Normal state. No voice or data call activity
|
||||
* CALL/DATA/ENCRYPTED/CONTROL
|
||||
* Decoding states.
|
||||
* FADE The phase after a voice or data call when either an explicit
|
||||
* call end has been received, or when no new signalling updates
|
||||
* have been received, and the fade timer has expired. This phase
|
||||
* allows for gui updates to signal to the user that the call is
|
||||
* ended, while continuing to display the call details for the user
|
||||
* TEARDOWN Indicates a traffic channel that will be torn down for reuse.
|
||||
*/
|
||||
public ChannelState( ThreadPoolManager manager, ChannelType channelType )
|
||||
{
|
||||
mThreadPoolManager = manager;
|
||||
mChannelType = channelType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this channel state and prepares it for reuse.
|
||||
*/
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
broadcast( new DecoderStateEvent( this, Event.RESET, State.IDLE ) );
|
||||
broadcast( new MetadataReset() );
|
||||
|
||||
mState = State.IDLE;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,6 +133,7 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
public void stop()
|
||||
{
|
||||
mSquelchLocked = false;
|
||||
stopMonitor();
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
@@ -145,9 +148,34 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
mStateMonitor = null;
|
||||
}
|
||||
|
||||
private boolean isStandardChannel()
|
||||
{
|
||||
return mChannelType == ChannelType.STANDARD;
|
||||
}
|
||||
|
||||
private boolean isTrafficChannel()
|
||||
{
|
||||
return mChannelType == ChannelType.TRAFFIC;
|
||||
}
|
||||
|
||||
public void setStandardChannelTimeout( long milliseconds )
|
||||
{
|
||||
mStandardChannelFadeTimeout = milliseconds;
|
||||
|
||||
if( mChannelType == ChannelType.STANDARD )
|
||||
{
|
||||
mFadeTimeout = mStandardChannelFadeTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTrafficChannelTimeout( long milliseconds )
|
||||
{
|
||||
mTrafficChannelTimeout = milliseconds;
|
||||
mTrafficChannelFadeTimeout = milliseconds;
|
||||
|
||||
if( mChannelType == ChannelType.TRAFFIC )
|
||||
{
|
||||
mFadeTimeout = mTrafficChannelFadeTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSelected( boolean selected )
|
||||
@@ -165,14 +193,6 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
return mState;
|
||||
}
|
||||
|
||||
private boolean isIdleOrEndingState()
|
||||
{
|
||||
return mState == State.FADE ||
|
||||
mState == State.END ||
|
||||
mState == State.IDLE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Starts the state monitor running when we're not in IDLE state. Calls to
|
||||
* start an already started monitor are ignored.
|
||||
@@ -181,12 +201,12 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
{
|
||||
if( mMonitoring.compareAndSet( false, true ) )
|
||||
{
|
||||
if( mRunningMonitor == null && mStateMonitor != null )
|
||||
if( mStateMonitorFuture == null && mStateMonitor != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
mRunningMonitor = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.DECODER, mStateMonitor, 20, TimeUnit.MILLISECONDS );
|
||||
mStateMonitorFuture = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.DECODER, mStateMonitor, 20, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
catch( RejectedExecutionException ree )
|
||||
{
|
||||
@@ -210,12 +230,17 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
{
|
||||
if( mMonitoring.compareAndSet( true, false ) )
|
||||
{
|
||||
if( mRunningMonitor != null )
|
||||
if( mStateMonitorFuture != null )
|
||||
{
|
||||
mThreadPoolManager.cancel( mRunningMonitor );
|
||||
boolean success = mThreadPoolManager.cancel( mStateMonitorFuture );
|
||||
|
||||
if( !success )
|
||||
{
|
||||
mLog.error("Couldn't stop monitoring scheduled future" );
|
||||
}
|
||||
}
|
||||
|
||||
mRunningMonitor = null;
|
||||
mStateMonitorFuture = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,20 +249,13 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
*/
|
||||
private void updateFadeTimeout()
|
||||
{
|
||||
/* Standard channel uses the FADE_TIMEOUT_DELAY and traffic channels
|
||||
* use the TRAFFIC_FADE_TIMEOUT_DELAY. Some traffic channels (e.g. MPT)
|
||||
* don't have signaling on the traffic channel that can be used to
|
||||
* update the fade timeout, so we set the timeout value larger to ensure
|
||||
* the channel doesn't fade before the end of the call. */
|
||||
long current = System.currentTimeMillis();
|
||||
|
||||
long timeout = current +
|
||||
( mChannelType == ChannelType.STANDARD ? FADE_TIMEOUT_DELAY :
|
||||
mTrafficChannelTimeout );
|
||||
|
||||
if( timeout > mFadeTimeout )
|
||||
if( isTrafficChannel() )
|
||||
{
|
||||
mFadeTimeout = timeout;
|
||||
mFadeTimeout = System.currentTimeMillis() + mTrafficChannelFadeTimeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
mFadeTimeout = System.currentTimeMillis() + mStandardChannelFadeTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,13 +264,13 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
*/
|
||||
private void updateResetTimeout()
|
||||
{
|
||||
if( mChannelType == ChannelType.TRAFFIC )
|
||||
if( isTrafficChannel() )
|
||||
{
|
||||
mResetTimeout = System.currentTimeMillis();
|
||||
mEndTimeout = System.currentTimeMillis();
|
||||
}
|
||||
else
|
||||
{
|
||||
mResetTimeout = System.currentTimeMillis() + RESET_TIMEOUT_DELAY;
|
||||
mEndTimeout = System.currentTimeMillis() + RESET_TIMEOUT_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,134 +312,129 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
*/
|
||||
protected void setState( State state )
|
||||
{
|
||||
if( mState == state )
|
||||
synchronized( mState )
|
||||
{
|
||||
switch( state )
|
||||
if( state == mState )
|
||||
{
|
||||
case CALL:
|
||||
case CONTROL:
|
||||
case DATA:
|
||||
case ENCRYPTED:
|
||||
if( State.CALL_STATES.contains( state ) )
|
||||
{
|
||||
updateFadeTimeout();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( mState.canChangeTo( state ) )
|
||||
{
|
||||
switch( state )
|
||||
else if( state != mState && mState.canChangeTo( state ) )
|
||||
{
|
||||
case CONTROL:
|
||||
//Don't allow traffic channels to be control channels,
|
||||
//otherwise they won't get call tear down
|
||||
if( mChannelType != ChannelType.TRAFFIC )
|
||||
{
|
||||
switch( state )
|
||||
{
|
||||
case CONTROL:
|
||||
//Don't allow traffic channels to be control channels,
|
||||
//otherwise they can't transition to call tear down
|
||||
if( isStandardChannel() )
|
||||
{
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
updateFadeTimeout();
|
||||
startMonitor();
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
}
|
||||
break;
|
||||
case DATA:
|
||||
case ENCRYPTED:
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
updateFadeTimeout();
|
||||
startMonitor();
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
}
|
||||
break;
|
||||
case DATA:
|
||||
case ENCRYPTED:
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
updateFadeTimeout();
|
||||
startMonitor();
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
break;
|
||||
case CALL:
|
||||
broadcast( SquelchState.UNSQUELCH );
|
||||
updateFadeTimeout();
|
||||
startMonitor();
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
break;
|
||||
case FADE:
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
updateResetTimeout();
|
||||
startMonitor();
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
break;
|
||||
case END:
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
broadcast( new DecoderStateEvent( this, Event.RESET, State.IDLE ) );
|
||||
broadcast( new MetadataReset() );
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
break;
|
||||
case IDLE:
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
stopMonitor();
|
||||
|
||||
if( mChannelType == ChannelType.TRAFFIC )
|
||||
{
|
||||
if( mTrafficChannelStatusListener != null )
|
||||
{
|
||||
mTrafficChannelStatusListener.callEnd();
|
||||
mTrafficChannelStatusListener = null;
|
||||
}
|
||||
|
||||
if( mTrafficChannelCallEvent != null )
|
||||
{
|
||||
mTrafficChannelCallEvent.end();
|
||||
|
||||
broadcast( mTrafficChannelCallEvent );
|
||||
mTrafficChannelCallEvent = null;
|
||||
}
|
||||
}
|
||||
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
case CALL:
|
||||
broadcast( SquelchState.UNSQUELCH );
|
||||
updateFadeTimeout();
|
||||
startMonitor();
|
||||
mState = state;
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
break;
|
||||
case FADE:
|
||||
processFadeState();
|
||||
break;
|
||||
case IDLE:
|
||||
processIdleState();
|
||||
break;
|
||||
case TEARDOWN:
|
||||
processTeardownState();
|
||||
break;
|
||||
case RESET:
|
||||
mState = State.IDLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if( mState == State.ENCRYPTED && state == State.CALL )
|
||||
{
|
||||
updateFadeTimeout();
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.debug( "Can't change from [" + mState + "] to [" + state + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the state and processes related actions
|
||||
*/
|
||||
private void processFadeState()
|
||||
{
|
||||
updateResetTimeout();
|
||||
mState = State.FADE;
|
||||
startMonitor();
|
||||
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
}
|
||||
|
||||
private void processIdleState()
|
||||
{
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
|
||||
if( mState == State.FADE )
|
||||
{
|
||||
broadcast( new DecoderStateEvent( this, Event.RESET, State.IDLE ) );
|
||||
broadcast( new MetadataReset() );
|
||||
}
|
||||
|
||||
stopMonitor();
|
||||
mState = State.IDLE;
|
||||
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
}
|
||||
|
||||
private void processTeardownState()
|
||||
{
|
||||
broadcast( SquelchState.SQUELCH );
|
||||
|
||||
stopMonitor();
|
||||
|
||||
mState = State.TEARDOWN;
|
||||
|
||||
broadcast( ChangedAttribute.CHANNEL_STATE );
|
||||
|
||||
if( mTrafficChannelCallEvent != null )
|
||||
{
|
||||
mTrafficChannelCallEvent.end();
|
||||
|
||||
broadcast( mTrafficChannelCallEvent );
|
||||
mTrafficChannelCallEvent = null;
|
||||
}
|
||||
|
||||
if( mTrafficChannelStatusListener != null )
|
||||
{
|
||||
mTrafficChannelStatusListener.callEnd();
|
||||
mTrafficChannelStatusListener = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.debug( "Can't change from [" + mState + "] to [" + state + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
public class StateMonitor implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
if( getState() == State.FADE )
|
||||
{
|
||||
if( mResetTimeout <= System.currentTimeMillis() )
|
||||
{
|
||||
setState( State.END );
|
||||
}
|
||||
}
|
||||
else if( getState() == State.END )
|
||||
{
|
||||
setState( State.IDLE );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mFadeTimeout <= System.currentTimeMillis() )
|
||||
{
|
||||
setState( State.FADE );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Exception thrown while state monitor is running " +
|
||||
"- state [" + getState() +
|
||||
"] current [" + System.currentTimeMillis() +
|
||||
"] mResetTimeout [" + mResetTimeout +
|
||||
"] mFadeTimeout [" + mFadeTimeout +
|
||||
"]", e );
|
||||
}
|
||||
mLog.error( "Traffic channel status listener was null - couldn't "
|
||||
+ "teardown the channel");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,35 +628,95 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
broadcast( SquelchState.UNSQUELCH );
|
||||
mSquelchLocked = true;
|
||||
break;
|
||||
case CHANGE_CALL_TIMEOUT:
|
||||
if( event instanceof ChangeChannelTimeoutEvent )
|
||||
{
|
||||
ChangeChannelTimeoutEvent timeout = (ChangeChannelTimeoutEvent)event;
|
||||
|
||||
if( timeout.getChannelType() == ChannelType.STANDARD )
|
||||
{
|
||||
setStandardChannelTimeout( timeout.getCallTimeout() );
|
||||
}
|
||||
else
|
||||
{
|
||||
setTrafficChannelTimeout( timeout.getCallTimeout() );
|
||||
}
|
||||
}
|
||||
case CONTINUATION:
|
||||
if( isIdleOrEndingState() )
|
||||
{
|
||||
setState( event.getState() );
|
||||
}
|
||||
else
|
||||
{
|
||||
updateFadeTimeout();
|
||||
}
|
||||
break;
|
||||
case DECODE:
|
||||
if( getState() == State.IDLE )
|
||||
case START:
|
||||
if( State.CALL_STATES.contains( event.getState() ) )
|
||||
{
|
||||
setState( event.getState() );
|
||||
}
|
||||
break;
|
||||
case END:
|
||||
setState( State.FADE );
|
||||
if( isTrafficChannel() )
|
||||
{
|
||||
setState( State.TEARDOWN );
|
||||
}
|
||||
else
|
||||
{
|
||||
setState( State.FADE );
|
||||
}
|
||||
break;
|
||||
case RESET:
|
||||
/* Channel State does not respond to reset events */
|
||||
break;
|
||||
case START:
|
||||
setState( event.getState() );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitors decoder state events to automatically transition the channel
|
||||
* state to IDLE (standard channel) or to TEARDOWN (traffic channel) when
|
||||
* decoding stops or the monitored channel returns to a no signal state.
|
||||
*
|
||||
* Provides a FADE transition state to allow for momentary decoding dropouts
|
||||
* and to allow the user access to call details for a fade period upon
|
||||
* call end.
|
||||
*/
|
||||
public class StateMonitor implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized( mState )
|
||||
{
|
||||
if( State.CALL_STATES.contains( mState ) &&
|
||||
mFadeTimeout <= System.currentTimeMillis() )
|
||||
{
|
||||
mState = State.FADE;
|
||||
processFadeState();
|
||||
}
|
||||
else if( mState == State.FADE &&
|
||||
mEndTimeout <= System.currentTimeMillis() )
|
||||
{
|
||||
if( isTrafficChannel() )
|
||||
{
|
||||
processTeardownState();
|
||||
}
|
||||
else
|
||||
{
|
||||
processIdleState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
mLog.error( "Exception thrown while state monitor is running " +
|
||||
"- state [" + getState() +
|
||||
"] current [" + System.currentTimeMillis() +
|
||||
"] mResetTimeout [" + mEndTimeout +
|
||||
"] mFadeTimeout [" + mFadeTimeout +
|
||||
"]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user