callcontinuity/vcc/src/tvccstatecalling.cpp
changeset 0 a4daefaec16c
child 9 bddb6d4447db
equal deleted inserted replaced
-1:000000000000 0:a4daefaec16c
       
     1 /*
       
     2 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Implementation for the VCC Calling state
       
    15 *
       
    16 */
       
    17 
       
    18 #include "tvccstatecalling.h"
       
    19 #include "cvccperformer.h"
       
    20 #include "rubydebug.h"
       
    21 
       
    22 
       
    23 // -----------------------------------------------------------------------------
       
    24 // c'tor
       
    25 // -----------------------------------------------------------------------------
       
    26 //
       
    27 TVccStateCalling::TVccStateCalling()
       
    28 	{
       
    29 	RUBY_DEBUG_BLOCK( "TVccStateCalling::TVccStateCalling" );	
       
    30 	} 
       
    31 
       
    32 // -----------------------------------------------------------------------------
       
    33 // Name
       
    34 // -----------------------------------------------------------------------------
       
    35 //	
       
    36 TUint TVccStateCalling::Name() const
       
    37 	{
       
    38 	RUBY_DEBUG_BLOCK( "TVccStateCalling::Name" );
       
    39 	return KVccStateCalling;
       
    40 	}
       
    41 
       
    42 // -----------------------------------------------------------------------------
       
    43 // LinkState
       
    44 // -----------------------------------------------------------------------------
       
    45 //
       
    46 void TVccStateCalling::LinkState(TVccState& aReleasing, 
       
    47                                 TVccState& aInit, 
       
    48                                 TVccState& aFailing )
       
    49 	{
       
    50 	RUBY_DEBUG_BLOCK( "TVccStateCalling::LinkState" );
       
    51 	iReleasing = &aReleasing;
       
    52 	iInit = &aInit;	
       
    53 	iFailing = &aFailing;
       
    54 	}
       
    55 	
       
    56 // -----------------------------------------------------------------------------
       
    57 // HangUp
       
    58 // -----------------------------------------------------------------------------
       
    59 //
       
    60 TInt TVccStateCalling::HangUp(CVccPerformer& aContext, MCCPCall& aCall)
       
    61 	{
       
    62     RUBY_DEBUG_BLOCK( "TVccStateCalling::HangUp" );
       
    63     
       
    64 	TInt err = KErrNotFound;
       
    65 	
       
    66 	__ASSERT_DEBUG(&aCall == aContext.PrimaryCall(), User::Invariant());
       
    67 	
       
    68 	//must release old leg and put old observer back aCall is the
       
    69 	// same as returned in the iContext.PrimaryCall()
       
    70 	aCall.RemoveObserver(aContext);
       
    71 	
       
    72 	//add new observer because the original call will be released and events 
       
    73 	//must be suppressed and performer does not have to be on the path for this 
       
    74 	//call anymore.
       
    75 	TRAP_IGNORE(aCall.AddObserverL(*aContext.CallObserver()));
       
    76 	
       
    77 	//now hangup old leg and forget about it - CCE will take of it.
       
    78 	//The performer will not be aware of the old leg release events.
       
    79 	err = aCall.HangUp();
       
    80 	
       
    81 	//must release new call leg as well and suppress the events 	
       
    82 	//new leg idle event should come in the releasing-state and
       
    83 	//it will be suppressed.
       
    84 	__ASSERT_DEBUG(aContext.SecondaryCall() != NULL, User::Invariant());
       
    85 	aContext.SecondaryCall()->HangUp();
       
    86 	
       
    87 	//signal the performer for the "idle call", so it can stop the trigger
       
    88 	//move to the releasing state
       
    89 	aContext.SetState(*iReleasing);
       
    90 	
       
    91 	//stop trigger since call becomes not active
       
    92 	aContext.ActivateTrigger( EFalse );
       
    93 	
       
    94 	//notify UI about hangup, hangup rejects HO but it is not failure
       
    95 	//no need to show the "ho failed note"
       
    96 	TRAP_IGNORE( aContext.Notifier().NotifySubscriberL(EVccCsToPsHoSuccessful, KErrNone) );
       
    97 	
       
    98 	return err;
       
    99 	
       
   100 	}
       
   101 	
       
   102 // -----------------------------------------------------------------------------
       
   103 // CallStateChanged
       
   104 // -----------------------------------------------------------------------------
       
   105 //	
       
   106 void TVccStateCalling::CallStateChanged( CVccPerformer& aContext, 
       
   107                                 const MCCPCallObserver::TCCPCallState aState,
       
   108                                 MCCPCall* aCall )
       
   109 	{
       
   110 	RUBY_DEBUG_BLOCK( "TVccStateCalling::CallStateChanged" );
       
   111 	
       
   112 	__ASSERT_DEBUG( aContext.SecondaryCall() != NULL, User::Invariant());
       
   113     __ASSERT_DEBUG( aContext.PrimaryCall() != NULL, User::Invariant() );
       
   114     
       
   115 	if ( aState == MCCPCallObserver::ECCPStateConnected && 
       
   116          aContext.SecondaryCall() == aCall)
       
   117 		{
       
   118         RUBY_DEBUG0( "TVccStateCalling::CallStateChanged - swap the calls" );
       
   119         
       
   120 		aContext.SetCall(aContext.SecondaryCall());
       
   121 		TRAP_IGNORE( aContext.Notifier().NotifySubscriberL( EVccCsToPsHoInprogress, 
       
   122 		                                       KErrNone ) );
       
   123 		
       
   124 		//-> Set Next State - if the call is idle just destroy call object and 
       
   125 		//go to init-state
       
   126 		__ASSERT_DEBUG( aContext.SecondaryCall() != NULL, 
       
   127 		                User::Invariant());
       
   128 		
       
   129 		if ( aContext.SecondaryCall()->State() == 
       
   130 		     MCCPCallObserver::ECCPStateIdle)
       
   131 			{
       
   132             RUBY_DEBUG0( "TVccStateCalling::CallStateChanged -\
       
   133                          release the old leg" );
       
   134             
       
   135 			//delete the actuall call object and move to Init-state
       
   136             ReleaseCall( aContext, *aContext.SecondaryCall(), *iInit, 
       
   137                          KVccHoOk );
       
   138 			}
       
   139 		else
       
   140 			{
       
   141             RUBY_DEBUG0( "TVccStateCalling::CallStateChanged -\
       
   142                           set state to iReleasing" );
       
   143                     
       
   144 			//must wait for old leg to be released
       
   145 			aContext.SetState( *iReleasing );	
       
   146 			}				
       
   147         }
       
   148     else 
       
   149         {
       
   150         InspectChangedStates( aContext, 
       
   151                               aState, 
       
   152                               aCall, 
       
   153                               aContext.CallObserver(), 
       
   154                               &MCCPCallObserver::CallStateChanged );
       
   155         }
       
   156     }
       
   157 // -----------------------------------------------------------------------------
       
   158 // CallStateChangedWithInband
       
   159 // -----------------------------------------------------------------------------
       
   160 //  
       
   161 void TVccStateCalling::CallStateChangedWithInband( CVccPerformer& aContext, 
       
   162                                 const MCCPCallObserver::TCCPCallState aState,
       
   163                                 MCCPCall* aCall )
       
   164     {
       
   165     RUBY_DEBUG_BLOCK( "TVccStateCalling::CallStateChangedWithInband" );
       
   166     __ASSERT_DEBUG( aContext.SecondaryCall() != NULL, User::Invariant() );
       
   167     __ASSERT_DEBUG( aContext.PrimaryCall() != NULL, User::Invariant() );
       
   168     InspectChangedStates(aContext, 
       
   169                         aState, 
       
   170                         aCall, 
       
   171                         aContext.CallObserver(), 
       
   172                         &MCCPCallObserver::CallStateChangedWithInband);
       
   173 
       
   174     }
       
   175 
       
   176 // -----------------------------------------------------------------------------
       
   177 // From MCCPCallObserver
       
   178 // -----------------------------------------------------------------------------
       
   179 //
       
   180 void TVccStateCalling::ErrorOccurred( CVccPerformer& aContext, 
       
   181                                 const TCCPError aError,
       
   182                                 MCCPCall* aCall )
       
   183     {
       
   184     RUBY_DEBUG_BLOCK( "TVccStateCalling::ErrorOccurred" );
       
   185     RUBY_DEBUG1( "TVccStateCalling::ErrorOccurred - error: %d", aError );
       
   186     
       
   187     __ASSERT_DEBUG( aContext.CallObserver()!=NULL, User::Invariant() );
       
   188     __ASSERT_DEBUG(aContext.PrimaryCall()!=NULL, User::Invariant());
       
   189     __ASSERT_DEBUG(aCall != NULL, User::Invariant());
       
   190     
       
   191     if ( aCall == aContext.SecondaryCall() &&
       
   192          aContext.PrimaryCall()->State() == 
       
   193          MCCPCallObserver::ECCPStateConnected )
       
   194     	{
       
   195     	RUBY_DEBUG0( "TVccStateCalling::ErrorOccurred - set state to iFailing" );
       
   196     	        
       
   197     	aContext.SetState( *iFailing );
       
   198     	}
       
   199     else if( aCall == aContext.SecondaryCall() &&
       
   200             aContext.PrimaryCall()->State() != 
       
   201             MCCPCallObserver::ECCPStateConnected )
       
   202     	{
       
   203     //	RUBY_DEBUG0( "TVccStateCalling::ErrorOccurred - forward the error to CCE" );
       
   204     	//aContext.CallObserver()->ErrorOccurred( aError, 
       
   205     	  //                                      aContext.PrimaryCall() );
       
   206     	}
       
   207   		
       
   208     //Update PS key to notify handover failure
       
   209     TRAP_IGNORE( aContext.Notifier().NotifySubscriberL( EVccCsToPsHoFailure, 
       
   210                                                         aError ) );
       
   211     
       
   212     }
       
   213 
       
   214 // -----------------------------------------------------------------------------
       
   215 // From MCCPCallObserver
       
   216 // -----------------------------------------------------------------------------
       
   217 //
       
   218 void TVccStateCalling::CallEventOccurred(CVccPerformer& aContext, 
       
   219                                 const MCCPCallObserver::TCCPCallEvent aEvent,
       
   220                                 MCCPCall* aCall )
       
   221     {
       
   222     RUBY_DEBUG_BLOCK( "TVccStateCalling::CallEventOccurred" ); 
       
   223     
       
   224 	__ASSERT_DEBUG(aContext.CallObserver()!=NULL, User::Invariant());
       
   225 	__ASSERT_DEBUG(aCall != NULL, User::Invariant());
       
   226 	
       
   227 	//in successful HO case ECCPRemoteTerminated is also received when server
       
   228 	//disconnects the original leg
       
   229 	if ( aEvent == MCCPCallObserver::ECCPRemoteTerminated &&
       
   230 	     aCall == aContext.SecondaryCall()  &&
       
   231 	     aContext.PrimaryCall()->State() != MCCPCallObserver::ECCPStateConnected )
       
   232 		{
       
   233 		RUBY_DEBUG1( "TVccStateCalling::CallEventOccurred -\
       
   234 		             forward the call event to CCE: %d", aEvent );
       
   235 		        
       
   236 	 	aContext.CallObserver()->CallEventOccurred( aEvent, 
       
   237 	                                                aContext.PrimaryCall());
       
   238 	 	    
       
   239 		}
       
   240 	else if( aEvent == MCCPCallObserver::ECCPRemoteTerminated &&
       
   241          aCall == aContext.SecondaryCall()  &&
       
   242          aContext.PrimaryCall()->State() == MCCPCallObserver::ECCPStateConnected )
       
   243 	    {
       
   244 	    RUBY_DEBUG0( "TVccStateCalling::CallEventOccurred - set state to iFailing" );
       
   245 	            
       
   246 	    aContext.SetState( *iFailing );
       
   247 	    }
       
   248 	//if remote end holds the call HO is not allowed at this end either
       
   249 	else if( aEvent == MCCPCallObserver::ECCPRemoteHold )
       
   250 	    {
       
   251 	    //Trigger is informed that automatic HO is not allowed. 
       
   252 	    aContext.ActivateTrigger( EFalse );
       
   253 	    //for manual HO PS key needs to be updated
       
   254 	    aContext.AllowHo( EFalse );
       
   255 	    aContext.CallObserver()->CallEventOccurred( aEvent, 
       
   256 	                                                aContext.PrimaryCall());    
       
   257 	    }
       
   258 	else if( aEvent == MCCPCallObserver::ECCPRemoteResume )
       
   259 	    {
       
   260 	    //HO is allowed again
       
   261 	    aContext.ActivateTrigger( ETrue );
       
   262 	    //for manual HO PS key needs to be updated
       
   263 	    aContext.AllowHo( ETrue );
       
   264 	    aContext.CallObserver()->CallEventOccurred( aEvent, 
       
   265 	                                                aContext.PrimaryCall());                    
       
   266 	    }
       
   267 	}
       
   268 
       
   269 
       
   270 // -----------------------------------------------------------------------------
       
   271 // InspectChangedStates
       
   272 // -----------------------------------------------------------------------------
       
   273 //
       
   274 void TVccStateCalling::InspectChangedStates (CVccPerformer& aContext, 
       
   275                                 const MCCPCallObserver::TCCPCallState aState,
       
   276                                 MCCPCall* aCall,
       
   277                                 MCCPCallObserver* aCallee,
       
   278                                 void (MCCPCallObserver::*aCallback)
       
   279                                 (const MCCPCallObserver::TCCPCallState, MCCPCall*))
       
   280 
       
   281                                 
       
   282     {
       
   283     //Remote party has disconnected the call - the events might arrive
       
   284     //to the new leg first. The event must be issued on the old leg as
       
   285     //all previous events are suppressed.
       
   286     //
       
   287     if( (aState == MCCPCallObserver::ECCPStateDisconnecting ||
       
   288             aState == MCCPCallObserver::ECCPStateIdle) &&
       
   289             aCall == aContext.SecondaryCall() &&
       
   290             aContext.PrimaryCall()->State() != MCCPCallObserver::ECCPStateIdle &&
       
   291             aContext.PrimaryCall()->State() != MCCPCallObserver::ECCPStateConnected )
       
   292         {
       
   293         RUBY_DEBUG1( "TVccStateCalling::InspectChangedStates -\
       
   294                 forward the events on the old leg, suppress from new one: %d", aState );
       
   295         //remove progress bar from UI
       
   296         TRAP_IGNORE( aContext.Notifier().NotifySubscriberL( EVccCsToPsHoFailure, KErrGeneral ) );
       
   297         (aCallee->*aCallback)( aState, aContext.PrimaryCall());
       
   298         }
       
   299     //old leg is released in remote disconnect or other abnormal case, this should never
       
   300     //happen in the successfull HO case.
       
   301     
       
   302     else if( aState == MCCPCallObserver::ECCPStateIdle &&
       
   303                     aCall == aContext.PrimaryCall() )
       
   304         {       
       
   305         RUBY_DEBUG1( "TVccStateCalling::InspectChangedStates - shouldnt happen in normal HO case,\
       
   306                       MT disconnected the call, or some other abnormal case: %d", aState );
       
   307                 
       
   308         //remove progress bar from UI
       
   309         TRAP_IGNORE( aContext.Notifier().NotifySubscriberL( EVccCsToPsHoFailure, KErrGeneral ) );
       
   310         (aCallee->*aCallback)( aState, aContext.PrimaryCall() );
       
   311         aContext.SetState( *iInit );
       
   312         }
       
   313     }