--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/callcontinuity/vcchotrigger/src/vcccchmonitor.cpp Mon Jan 18 20:12:36 2010 +0200
@@ -0,0 +1,433 @@
+/*
+* Copyright (c) 2008-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of the CCH monitor.
+*
+*/
+
+
+
+#include <cch.h>
+#include "vcccchmonitor.h"
+#include "vccsettingsreader.h"
+#include "rubydebug.h"
+
+// ---------------------------------------------------------------------------
+// Symbian OS static constructor
+// ---------------------------------------------------------------------------
+//
+CVccCchMonitor* CVccCchMonitor::NewL( MVccCchObserver& aObserver )
+ {
+ RUBY_DEBUG_BLOCKL( "CVccCchMonitor::NewL" );
+
+ CVccCchMonitor* self = new ( ELeave ) CVccCchMonitor( aObserver );
+
+ CleanupStack::PushL( self );
+
+ self->ConstructL();
+
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// C++ destructor
+// ---------------------------------------------------------------------------
+//
+CVccCchMonitor::~CVccCchMonitor()
+ {
+ RUBY_DEBUG0( "CVccCchMonitor::~CVccCchMonitor START" );
+
+ // If we have reserved the used service, free it before disabling.
+ // Do not mind the return values, just keep going.
+
+ if ( iCchService )
+ {
+ if ( iServiceReserved )
+ {
+ RUBY_DEBUG0( " -Free and disable service" );
+
+ (void) iCchService->Free( ECCHVoIPSub );
+ (void) iCchService->Disable( ECCHVoIPSub );
+
+ // We did disabled here.
+ iDisableService = EFalse;
+ }
+
+ // If we enabled the service, we must disable it also
+ // ( even if it was not reserved for us).
+ // Do not mind the return value, just keep going.
+
+ if ( iDisableService )
+ {
+ RUBY_DEBUG0( " -Disable service" );
+ (void) iCchService->Disable( ECCHVoIPSub );
+ }
+
+ // Remove observer
+ iCchService->RemoveObserver();
+
+ // We DO NOT OWN the service, DO NOT DELETE IT
+ iCchService = NULL;
+ }
+
+ // Free the CCH itself
+ delete iCch;
+ RUBY_DEBUG0( "CVccCchMonitor::~CVccCchMonitor STOP" );
+ }
+
+// ---------------------------------------------------------------------------
+// Symbian OS 2nd phase constructor
+// ---------------------------------------------------------------------------
+//
+void CVccCchMonitor::ConstructL()
+ {
+ RUBY_DEBUG_BLOCKL( "CVccCchMonitor::ConstructL" );
+
+ // First we create the CCH object and get the VoIP id
+ // which is VCC enabled.
+ //
+ // If we don't get the VoIP id we leave since
+ // without the VoIP id we cannot get the right VoIP service.
+ //
+ // If everything goes well, we try to enable the service.
+ // All errors etc. are received thru the CCH observer interface.
+ //
+
+ // Initialize some own flags.
+
+ // Do not notify our observer (yet).
+ iNotifyObserver = EFalse;
+
+ // Do not disable service when we exit.
+ iDisableService = EFalse;
+
+ // Intitial CCH state.
+ iCurrentCchState = ECCHUninitialized;
+
+ // No errors so far.
+ iLastCchError = KErrNone;
+
+ // And service is not available (yet).
+ iCurrentStatus = MVccCchObserver::EServiceUnavailable;
+
+
+ // Create CCH
+ iCch = CCch::NewL();
+
+ // We do not have the service yet.
+ iCchService = NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// C++ constructor
+// ---------------------------------------------------------------------------
+//
+CVccCchMonitor::CVccCchMonitor( MVccCchObserver& aObserver )
+ : iObserver( aObserver )
+ {
+ RUBY_DEBUG_BLOCK( "CVccCchMonitor::CVccCchMonitor" );
+ }
+
+// ---------------------------------------------------------------------------
+// Enable the VoIP service and start monitoring the state of the CCH.
+// ---------------------------------------------------------------------------
+//
+void CVccCchMonitor::EnableServiceL()
+ {
+ RUBY_DEBUG_BLOCK( "CVccCchMonitor::EnableServiceL" );
+
+ // CCH must be created.
+ __ASSERT_DEBUG( iCch, User::Leave( KErrArgument ) );
+
+ // Get the Voip service id. Get it always to if the SP
+ // settings are chagned, we get updated values.
+
+ iServiceId = VccSettingsReader::VoIPServiceIdL();
+
+ if ( iServiceId == KErrNotFound )
+ {
+ RUBY_DEBUG1( " -VoIP service id (%d) not found - LEAVE", iServiceId );
+ User::Leave( KErrNotFound );
+ }
+
+ // Get the service if not already available
+
+ if ( !iCchService )
+ {
+
+ // Get the service. The ownership is not transfered
+ iCchService = iCch->GetService( iServiceId );
+
+ RUBY_DEBUG1( " -CCH service fetched, addr = %x (LEAVE if NULL)",
+ iCchService );
+
+ // CCH cannot find the service if it returns NULL
+ if ( !iCchService )
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ // We got the service.
+ // Set us as observer to get notifications.
+
+ iCchService->SetObserver( *this );
+ }
+
+
+ // Start sending notifications to our observer.
+ iNotifyObserver = ETrue;
+
+ // And then enable the VoIP service.
+ DoEnableServiceL();
+ }
+
+// ---------------------------------------------------------------------------
+// Disable the service, this means that
+// we stop sending notifications to our observer.
+// The service is not disabled, we just do not notify our obsserver.
+// The service is disabled when we exit.
+// ---------------------------------------------------------------------------
+//
+void CVccCchMonitor::DisableService()
+ {
+ RUBY_DEBUG_BLOCK( "CVccCchMonitor::DisableService" );
+
+ // We do not disable the service.
+ // It can be done here but if we start and stop it
+ // many times within a short period of time,
+ // it does not make sense.
+ //
+ // Service is released (and disabled if needed)
+ // when we exit (see destructor).
+ // So here just flag to stop sending notifications to
+ // our observer.
+ iCchService = NULL;
+ iNotifyObserver = EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// From MCchServiceStatusObserver
+// Handles CCH service or error status changes.
+// ---------------------------------------------------------------------------
+//
+void CVccCchMonitor::ServiceStatusChanged(
+ TInt aServiceId,
+ TCCHSubserviceType aType,
+ const TCchServiceStatus& aServiceStatus )
+ {
+ RUBY_DEBUG_BLOCK( "CVccCchMonitor::ServiceStatusChanged" );
+
+ // The CCH sends notifications to all
+ // so service id and the type must be checked.
+
+ if ( !( aServiceId == iServiceId && aType == ECCHVoIPSub ) )
+ {
+ return;
+ }
+
+ // Get the state and the error.
+ iCurrentCchState = aServiceStatus.State();
+ iLastCchError = aServiceStatus.Error();
+
+ RUBY_DEBUG2( " -State = %d, error = %d", iCurrentCchState, iLastCchError );
+
+
+ // If we are observing, notify our observer.
+ if ( iNotifyObserver == EFalse )
+ {
+ return;
+ }
+ else
+ {
+ NotifyObserver();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Send notifications to our observer.
+// ---------------------------------------------------------------------------
+//
+void CVccCchMonitor::NotifyObserver()
+ {
+ RUBY_DEBUG_BLOCK( "CVccCchMonitor::NotifyObserver" );
+
+
+ // This method should be called only when
+ // the state of the cch service is updated
+ // to iCurrentCchState member variable.
+
+ // If CCH state != enabled or there is an error, service is not working
+ //
+ // Note that the service stays enabled until someone disables it.
+
+ if ( ( iCurrentCchState != ECCHEnabled ) ||
+ ( iLastCchError != KErrNone ) )
+ {
+ RUBY_DEBUG0( " -Service unavailable" );
+ iCurrentStatus = MVccCchObserver::EServiceUnavailable;
+ }
+ else
+ {
+ RUBY_DEBUG0( " -Service available" );
+ iCurrentStatus = MVccCchObserver::EServiceAvailable;
+ }
+
+ iObserver.CchServiceStatusChanged( iCurrentStatus );
+ }
+
+// ---------------------------------------------------------------------------
+// Enable the CCH service we are using (ECCHVoIPSub).
+// ---------------------------------------------------------------------------
+//
+void CVccCchMonitor::DoEnableServiceL()
+ {
+ RUBY_DEBUG_BLOCK( "CVccCchMonitor::DoEnableServiceL" );
+
+ // Enable the service
+ //
+ // Depending of the current state of the CCH service:
+ //
+ // Do nothing if
+ // - ECCHConnecting
+ //
+ //
+ // Try to enable if
+ // - ECCHDisconnecting
+ // - ECCHDisabled
+ // - ECCHUninitialized
+ //
+ // Notify our observer if
+ // - ECCHEnabled
+
+
+ // Check the state of the service.
+ // The state is got from the status object of the service.
+
+
+ TCchServiceStatus serviceStatus;
+ TInt errorValue( KErrNone );
+
+ // Get the status.
+ errorValue = iCchService->GetStatus( ECCHVoIPSub, serviceStatus );
+
+ RUBY_DEBUG2( " -GetStatus returned = %d, service status = %d",
+ errorValue, serviceStatus.State() );
+
+
+ // If we can't get the status, leave
+
+ if ( errorValue != KErrNone )
+ {
+ RUBY_DEBUG0( " -GetStatus returned error, can't enable - LEAVE" );
+
+ User::Leave( errorValue );
+ }
+
+
+ // Okay, get the state and error (from status).
+ iCurrentCchState = serviceStatus.State();
+ iLastCchError = serviceStatus.Error();
+
+ RUBY_DEBUG1( " -Service state = %d", iCurrentCchState );
+
+
+ switch( iCurrentCchState )
+ {
+ case ECCHUninitialized:
+ // Fall-through intended here
+ case ECCHDisabled:
+ // Fall-through intended here
+ case ECCHDisconnecting:
+ {
+ RUBY_DEBUG0( " -Try to enable service, LEAVE if error" );
+
+ // Enable, leave if errors,
+ User::LeaveIfError( iCchService->Enable( ECCHVoIPSub ) );
+
+ // Service should be enabled in a while,
+ // we must disable it upon exiting since it was not enabled
+ // (we are one who enabled it so must disable it).
+
+ iDisableService = ETrue;
+ break;
+ }
+
+ case ECCHConnecting:
+ {
+ // Service is connecting (by someone else
+ // or we have been called more than twice).
+ // We should get the notification when it is enabled
+ // and ready for the use.
+ // Do nothing.
+ break;
+ }
+
+ case ECCHEnabled:
+ {
+ RUBY_DEBUG0( " -Service is already enabled - do nothing" );
+
+ // Enabled already. We can notify our observer
+ // with the status of the service.
+
+ NotifyObserver();
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+
+ } // End of switch
+
+
+ // So good so far...
+ // Check if we can reserve (if not done already)
+ // the service for us.
+ // This prevents someone to disable it during a call
+
+ if ( !iServiceReserved )
+ {
+ TBool isReserved( EFalse );
+
+ iCchService->IsReserved( ECCHVoIPSub, isReserved );
+
+ if ( !isReserved )
+ {
+ RUBY_DEBUG0( " -Try to reserve the service for us" );
+
+ // It is free. Try to reserve it.
+
+ if ( iCchService->Reserve( ECCHVoIPSub ) == KErrNone )
+ {
+ RUBY_DEBUG0( " -Service reserved for us" );
+ iServiceReserved = ETrue;
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Return the current status of the service availability
+// ---------------------------------------------------------------------------
+//
+MVccCchObserver::TServiceStatus CVccCchMonitor::ServiceStatus() const
+ {
+ RUBY_DEBUG_BLOCK( "CVccCchMonitor::ServiceStatus" );
+
+ RUBY_DEBUG1( " -Status = %d", iCurrentStatus );
+
+ return iCurrentStatus;
+ }