/*
Copyright (c) 2004 - 2017 Qualcomm Technologies International, Ltd.
*/
/*!
@file
@ingroup sink_app
@brief
state machine helper functions used for state changes etc - provide single
state change points etc for the sink device application
*/
#include "sink_statemanager.h"
#include "sink_led_manager.h"
#include "sink_buttonmanager.h"
#include "sink_pio.h"
#include "sink_audio.h"
#include "sink_scan.h"
#include "sink_slc.h"
#include "sink_inquiry.h"
#include "sink_devicemanager.h"
#include "sink_powermanager.h"
#include "sink_speech_recognition.h"
#include "psu.h"
#include "sink_audio_routing.h"
#include "sink_auth.h"
#include "sink_ba.h"
#include "sink_dormant.h"
#include "sink_main_task.h"
#include "sink_wired.h"
#include "sink_bredr.h"
#include "sink_private_data.h"
#include "sink_callmanager.h"
#include "sink_ble.h"
#include "sink_fm.h"
#ifdef ENABLE_FAST_PAIR
#include "sink_fast_pair.h"
#endif
#include "sink_hfp_data.h"
#include "sink_display.h"
#ifdef ENABLE_AVRCP
#include "sink_avrcp.h"
#endif
#ifdef ENABLE_SUBWOOFER
#include "sink_swat.h"
#include <bdaddr.h>
#endif
#include <stdlib.h>
#include <boot.h>
#include <ahi.h>
#ifdef DEBUG_STATES
#define SM_DEBUG(x) DEBUG(x)
/*
NB: When adding a new extended state, it must be put at
the end of the array
+ Should follow the same order as in sink_extended_state_t
(see sink_extendedstates.h)
+ needs consistency with "values" in global XML config file
*/
const char* const gHSExtendedStateStrings [ SINK_NUM_EXTENDED_STATES ] =
{
"Limbo",
"Connectable",
"ConnDiscoverableToSource", /* Connectable/Discoverable Ext states */
"ConnDiscoverableToPeer",
"ConnectedToSource", /* Connected Ext states */
"ConnectedToPeer",
"ConnectedToSourceAndPeer",
"OutgoingCallEstablish",
"IncomingCallEstablish",
"ActiveCallSCO",
"TestMode",
"ThreeWayCallWaiting",
"ThreeWayCallOnHold",
"ThreeWayMulticall",
"IncomingCallOnHold",
"ActiveCallNoSCO",
"deviceA2DPStreaming",
"LowBattery",
"Config Mode",
"Default Pattern / No Pattern found"
/* ADD EXTENDED STATE HERE */
} ;
#else
#define SM_DEBUG(x)
#endif
typedef enum
{
GOODBYE_DORMANT,
GOODBYE_POWER_OFF
} sinkGoodbyeState;
/****************************************************************************
VARIABLES
*/
/*the device state variable - accessed only from below fns*/
static sinkState gTheSinkState ;
/* The device extended state variable - accessed only from below fns */
static sink_extended_state_t pTheSinkExtendedState ; /* Keeps track of the current extended state */
static sinkLimboReason gTheSinkLimboReason ;
/****************************************************************************
FUNCTIONS
*/
static void stateManagerSetState ( sinkState pNewState ) ;
static void stateManagerSetExtendedState ( sink_extended_state_t pNewExtendedState ) ;
static void stateManagerResetPIOs ( void ) ;
static sink_extended_state_t stateManagerFindExtendedStateFromState( sinkState pState );
static bool stateManagerIsStateSameExtendedState( sinkState pState1, sink_extended_state_t* pNewExtendedState );
static sink_extended_state_t getConnDiscovExtendedStates(void);
static sink_extended_state_t getConnectedExtendedStates(void);
static bool checkSecondSlc(void);
#define isPowerDownPioConfigured() PioIsPioConfigured(PIO_POWER_ON)
#define isMutePioConfigured() PioIsPioConfigured(PIO_AMP_MUTE)
/****************************************************************************
NAME
stateManagerSetState
DESCRIPTION
helper function to Set the current device state
provides a single state change point and passes the information
on to the managers requiring state based responses
RETURNS
void
*/
static void stateManagerSetState ( sinkState pNewState )
{
SM_DEBUG(("SM:[%s]->[%s][%d]\n",gHSExtendedStateStrings[stateManagerGetState()] , gHSExtendedStateStrings[pNewState] , pNewState ));
if ( pNewState < SINK_NUM_STATES )
{
/* Needed to set the new extended state if it has changed */
sink_extended_state_t newExtendedState;
/* Indicate the machine state immediately to the AHI
and display whenever the state is updated*/
if (pNewState != gTheSinkState)
{
AhiTestReportStateMachineState(1, pNewState);
/* this should be called before the state is updated */
displayUpdateAppState(pNewState);
}
else
{
/*State already indicated, need not resend the same*/
}
if ( !stateManagerIsStateSameExtendedState(pNewState, &newExtendedState) )
{
/* Indicate the LED pattern based on extended state */
stateManagerSetExtendedState(newExtendedState);
/* send message to reduce stack usage */
MessageSend(&theSink.task, EventSysLEDIndicateState, 0);
}
gTheSinkState = pNewState ;
#ifdef ENABLE_FAST_PAIR
if(gTheSinkState != deviceConnDiscoverable)
sinkFastPairSetDiscoverabilityStatus(no_discoverability);
#endif
}
else
{
SM_DEBUG(("SM: ? [%s] [%x]\n",gHSExtendedStateStrings[ pNewState] , pNewState)) ;
}
}
/****************************************************************************
NAME
stateManagerGetState
DESCRIPTION
helper function to get the current device state
RETURNS
the Devie State information
*/
sinkState stateManagerGetState ( void )
{
return gTheSinkState ;
}
/****************************************************************************
NAME
stateManagerSetExtendedState
DESCRIPTION
helper function to Set the current device extended state
RETURNS
*/
static void stateManagerSetExtendedState (sink_extended_state_t pNewExtendedState)
{
pTheSinkExtendedState = pNewExtendedState;
}
/****************************************************************************
NAME
stateManagerGetExtendedState
DESCRIPTION
helper function to get the current device extended state
RETURNS
the Devie Extended State information
*/
sink_extended_state_t stateManagerGetExtendedState ( void )
{
return pTheSinkExtendedState;
}
/****************************************************************************
NAME
updateExtendedState
DESCRIPTION
Updating the extended state and indicate the LED state.
RETURNS
void
*/
void updateExtendedState ( sinkState pNewState )
{
if ((pNewState == deviceConnected) || (pNewState == deviceConnDiscoverable))
{
/* Needed to set the new extended state if it has changed */
sink_extended_state_t newExtendedState;
/* Extended states are verified instead of application states because although this can be the same
* Application state, the extended state might be different and then needs to be displayed
*/
if ( !stateManagerIsStateSameExtendedState(pNewState, &newExtendedState) )
{
/* LED state to indicate */
stateManagerSetExtendedState(newExtendedState);
/* send message to reduce stack usage */
MessageSend(&theSink.task, EventSysLEDIndicateState, 0);
}
}
}
/****************************************************************************
NAME
checkSecondSlc
DESCRIPTION
This function to be called to check the second incoming connection (SLC)
comes from either AG/Peer to update the extended state as both AG and Peer
connected(i.e. sink_ext_state_connectedToSourceAndPeer)
RETURNS
TRUE if any one of the AG/Peer already connected. Else returns FALSE.
*/
static bool checkSecondSlc(void)
{
return ((deviceManagerIsOnlyAgSourceConnected() && (stateManagerGetExtendedState()
== sink_ext_state_connectedToAG))
|| (deviceManagerIsPeerConnected() && (stateManagerGetExtendedState()
== sink_ext_state_connectedToPeer)));
}
/****************************************************************************
NAME
getConnDicovExtendedStates
DESCRIPTION
Get the extended states of connectable/discoverable device state (sinkState)
RETURNS
The corresponding extended state of connectable/discoverable device state
*/
static sink_extended_state_t getConnDiscovExtendedStates(void)
{
sink_extended_state_t conndisc_ext_state = sink_ext_state_Default;
if (sinkInquiryIsInqSessionNormal())
{
conndisc_ext_state = sink_ext_state_connDiscoverableToSource;
}
else if (sinkInquiryIsInqSessionPeer())
{ /* For clarity, though no need to check */
conndisc_ext_state = sink_ext_state_connDiscoverableToPeer;
}
return conndisc_ext_state;
}
/****************************************************************************
NAME
getConnectedExtendedStates
<