callcontinuity/vcchotrigger/src/vcccchmonitor.cpp
branchRCL_3
changeset 22 d38647835c2e
parent 0 a4daefaec16c
equal deleted inserted replaced
21:f742655b05bf 22:d38647835c2e
       
     1 /*
       
     2 * Copyright (c) 2008-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 of the CCH monitor.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <cch.h>
       
    21 #include "vcccchmonitor.h"
       
    22 #include "vccsettingsreader.h"
       
    23 #include "rubydebug.h"
       
    24 
       
    25 // ---------------------------------------------------------------------------
       
    26 // Symbian OS static constructor
       
    27 // ---------------------------------------------------------------------------
       
    28 //
       
    29 CVccCchMonitor* CVccCchMonitor::NewL( MVccCchObserver& aObserver )
       
    30     {
       
    31     RUBY_DEBUG_BLOCKL( "CVccCchMonitor::NewL" );
       
    32 
       
    33     CVccCchMonitor* self = new ( ELeave ) CVccCchMonitor( aObserver );
       
    34 
       
    35     CleanupStack::PushL( self );
       
    36 
       
    37     self->ConstructL();
       
    38 
       
    39     CleanupStack::Pop( self );
       
    40 
       
    41     return self;
       
    42     }
       
    43 
       
    44 // ---------------------------------------------------------------------------
       
    45 // C++ destructor
       
    46 // ---------------------------------------------------------------------------
       
    47 //
       
    48 CVccCchMonitor::~CVccCchMonitor()
       
    49     {
       
    50     RUBY_DEBUG0( "CVccCchMonitor::~CVccCchMonitor START" );
       
    51 
       
    52     // If we have reserved the used service, free it before disabling.
       
    53     // Do not mind the return values, just keep going.
       
    54 
       
    55     if ( iCchService )
       
    56         {
       
    57         if ( iServiceReserved )
       
    58             {
       
    59             RUBY_DEBUG0( " -Free and disable service" );
       
    60 
       
    61             (void) iCchService->Free( ECCHVoIPSub );
       
    62             (void) iCchService->Disable( ECCHVoIPSub );
       
    63 
       
    64             // We did disabled here.
       
    65             iDisableService = EFalse;
       
    66             }
       
    67 
       
    68         // If we enabled the service, we must disable it also
       
    69         // ( even if it was not reserved for us).
       
    70         // Do not mind the return value, just keep going.
       
    71 
       
    72         if ( iDisableService )
       
    73             {
       
    74             RUBY_DEBUG0( " -Disable service" );
       
    75             (void) iCchService->Disable( ECCHVoIPSub );
       
    76             }
       
    77 
       
    78         // Remove observer
       
    79         iCchService->RemoveObserver();
       
    80 
       
    81         // We DO NOT OWN the service, DO NOT DELETE IT
       
    82         iCchService = NULL;
       
    83         }
       
    84 
       
    85     // Free the CCH itself
       
    86     delete iCch;
       
    87     RUBY_DEBUG0( "CVccCchMonitor::~CVccCchMonitor STOP" );
       
    88     }
       
    89 
       
    90 // ---------------------------------------------------------------------------
       
    91 // Symbian OS 2nd phase constructor
       
    92 // ---------------------------------------------------------------------------
       
    93 //
       
    94 void CVccCchMonitor::ConstructL()
       
    95     {
       
    96     RUBY_DEBUG_BLOCKL( "CVccCchMonitor::ConstructL" );
       
    97 
       
    98     // First we create the CCH object and get the VoIP id
       
    99     // which is VCC enabled.
       
   100     //
       
   101     // If we don't get the VoIP id we leave since
       
   102     // without the VoIP id we cannot get the right VoIP service.
       
   103     //
       
   104     // If everything goes well, we try to enable the service.
       
   105     // All errors etc. are received thru the CCH observer interface.
       
   106     //
       
   107 
       
   108     // Initialize some own flags.
       
   109 
       
   110     // Do not notify our observer (yet).
       
   111     iNotifyObserver = EFalse;
       
   112 
       
   113     // Do not disable service when we exit.
       
   114     iDisableService = EFalse;
       
   115 
       
   116     // Intitial CCH state.
       
   117     iCurrentCchState = ECCHUninitialized;
       
   118 
       
   119     // No errors so far.
       
   120     iLastCchError = KErrNone;
       
   121 
       
   122     // And service is not available (yet).
       
   123     iCurrentStatus = MVccCchObserver::EServiceUnavailable;
       
   124 
       
   125 
       
   126     // Create CCH
       
   127     iCch = CCch::NewL();
       
   128 
       
   129     // We do not have the service yet.
       
   130     iCchService = NULL;
       
   131     }
       
   132 
       
   133 // ---------------------------------------------------------------------------
       
   134 // C++ constructor
       
   135 // ---------------------------------------------------------------------------
       
   136 //
       
   137 CVccCchMonitor::CVccCchMonitor( MVccCchObserver& aObserver )
       
   138     : iObserver( aObserver )
       
   139     {
       
   140     RUBY_DEBUG_BLOCK( "CVccCchMonitor::CVccCchMonitor" );
       
   141     }
       
   142 
       
   143 // ---------------------------------------------------------------------------
       
   144 // Enable the VoIP service and start monitoring the state of the CCH.
       
   145 // ---------------------------------------------------------------------------
       
   146 //
       
   147 void CVccCchMonitor::EnableServiceL()
       
   148     {
       
   149     RUBY_DEBUG_BLOCK( "CVccCchMonitor::EnableServiceL" );
       
   150 
       
   151     // CCH must be created.
       
   152     __ASSERT_DEBUG( iCch, User::Leave( KErrArgument ) );
       
   153 
       
   154     // Get the Voip service id. Get it always to if the SP
       
   155     // settings are chagned, we get updated values.
       
   156 
       
   157     iServiceId = VccSettingsReader::VoIPServiceIdL();
       
   158 
       
   159     if ( iServiceId == KErrNotFound )
       
   160         {
       
   161         RUBY_DEBUG1( " -VoIP service id (%d) not found - LEAVE", iServiceId );
       
   162         User::Leave( KErrNotFound );
       
   163         }
       
   164 
       
   165     // Get the service if not already available
       
   166 
       
   167     if ( !iCchService )
       
   168         {
       
   169 
       
   170         // Get the service. The ownership is not transfered
       
   171         iCchService = iCch->GetService( iServiceId );
       
   172 
       
   173         RUBY_DEBUG1( " -CCH service fetched, addr = %x (LEAVE if NULL)",
       
   174                 iCchService );
       
   175 
       
   176         // CCH cannot find the service if it returns NULL
       
   177         if ( !iCchService )
       
   178             {
       
   179             User::Leave( KErrNotFound );
       
   180             }
       
   181 
       
   182         // We got the service.
       
   183         // Set us as observer to get notifications.
       
   184 
       
   185         iCchService->SetObserver( *this );
       
   186         }
       
   187 
       
   188 
       
   189     // Start sending notifications to our observer.
       
   190     iNotifyObserver = ETrue;
       
   191 
       
   192     // And then enable the VoIP service.
       
   193     DoEnableServiceL();
       
   194     }
       
   195 
       
   196 // ---------------------------------------------------------------------------
       
   197 // Disable the service, this means that
       
   198 // we stop sending notifications to our observer.
       
   199 // The service is not disabled, we just do not notify our obsserver.
       
   200 // The service is disabled when we exit.
       
   201 // ---------------------------------------------------------------------------
       
   202 //
       
   203 void CVccCchMonitor::DisableService()
       
   204     {
       
   205     RUBY_DEBUG_BLOCK( "CVccCchMonitor::DisableService" );
       
   206 
       
   207     // We do not disable the service.
       
   208     // It can be done here but if we start and stop it
       
   209     // many times within a short period of time,
       
   210     // it does not make sense.
       
   211     //
       
   212     // Service is released (and disabled if needed)
       
   213     // when we exit (see destructor).
       
   214     // So here just flag to stop sending notifications to
       
   215     // our observer.
       
   216     iCchService = NULL;
       
   217     iNotifyObserver = EFalse;
       
   218     }
       
   219 
       
   220 // ---------------------------------------------------------------------------
       
   221 // From MCchServiceStatusObserver
       
   222 // Handles CCH service or error status changes.
       
   223 // ---------------------------------------------------------------------------
       
   224 //
       
   225 void CVccCchMonitor::ServiceStatusChanged(
       
   226         TInt aServiceId,
       
   227         TCCHSubserviceType aType,
       
   228         const TCchServiceStatus& aServiceStatus )
       
   229     {
       
   230     RUBY_DEBUG_BLOCK( "CVccCchMonitor::ServiceStatusChanged" );
       
   231 
       
   232     // The CCH sends notifications to all
       
   233     // so service id and the type must be checked.
       
   234 
       
   235     if ( !( aServiceId == iServiceId && aType == ECCHVoIPSub ) )
       
   236         {
       
   237         return;
       
   238         }
       
   239 
       
   240     // Get the state and the error.
       
   241     iCurrentCchState = aServiceStatus.State();
       
   242     iLastCchError = aServiceStatus.Error();
       
   243 
       
   244     RUBY_DEBUG2( " -State = %d, error = %d", iCurrentCchState, iLastCchError );
       
   245 
       
   246 
       
   247     // If we are observing, notify our observer.
       
   248     if ( iNotifyObserver == EFalse )
       
   249         {
       
   250         return;
       
   251         }
       
   252     else
       
   253         {
       
   254         NotifyObserver();
       
   255         }
       
   256     }
       
   257 
       
   258 // ---------------------------------------------------------------------------
       
   259 // Send notifications to our observer.
       
   260 // ---------------------------------------------------------------------------
       
   261 //
       
   262 void CVccCchMonitor::NotifyObserver()
       
   263     {
       
   264     RUBY_DEBUG_BLOCK( "CVccCchMonitor::NotifyObserver" );
       
   265 
       
   266 
       
   267     // This method should be called only when
       
   268     // the state of the cch service is updated
       
   269     // to iCurrentCchState member variable.
       
   270 
       
   271     // If CCH state != enabled or there is an error, service is not working
       
   272     //
       
   273     // Note that the service stays enabled until someone disables it.
       
   274 
       
   275     if ( ( iCurrentCchState != ECCHEnabled ) ||
       
   276         ( iLastCchError != KErrNone ) )
       
   277         {
       
   278         RUBY_DEBUG0( " -Service unavailable" );
       
   279         iCurrentStatus = MVccCchObserver::EServiceUnavailable;
       
   280         }
       
   281     else
       
   282         {
       
   283         RUBY_DEBUG0( " -Service available" );
       
   284         iCurrentStatus = MVccCchObserver::EServiceAvailable;
       
   285         }
       
   286 
       
   287     iObserver.CchServiceStatusChanged( iCurrentStatus );
       
   288     }
       
   289 
       
   290 // ---------------------------------------------------------------------------
       
   291 // Enable the CCH service we are using (ECCHVoIPSub).
       
   292 // ---------------------------------------------------------------------------
       
   293 //
       
   294 void CVccCchMonitor::DoEnableServiceL()
       
   295     {
       
   296     RUBY_DEBUG_BLOCK( "CVccCchMonitor::DoEnableServiceL" );
       
   297 
       
   298     // Enable the service
       
   299     //
       
   300     // Depending of the current state of the CCH service:
       
   301     //
       
   302     // Do nothing if
       
   303     // - ECCHConnecting
       
   304     //
       
   305     //
       
   306     // Try to enable if
       
   307     // - ECCHDisconnecting
       
   308     // - ECCHDisabled
       
   309     // - ECCHUninitialized
       
   310     //
       
   311     // Notify our observer if
       
   312     // - ECCHEnabled
       
   313 
       
   314 
       
   315     // Check the state of the service.
       
   316     // The state is got from the status object of the service.
       
   317 
       
   318 
       
   319     TCchServiceStatus serviceStatus;
       
   320     TInt errorValue( KErrNone );
       
   321 
       
   322     // Get the status.
       
   323     errorValue = iCchService->GetStatus( ECCHVoIPSub, serviceStatus );
       
   324 
       
   325     RUBY_DEBUG2( " -GetStatus returned = %d, service status = %d",
       
   326             errorValue, serviceStatus.State() );
       
   327 
       
   328 
       
   329     // If we can't get the status, leave
       
   330 
       
   331     if ( errorValue != KErrNone )
       
   332         {
       
   333         RUBY_DEBUG0( " -GetStatus returned error, can't enable - LEAVE" );
       
   334 
       
   335         User::Leave( errorValue );
       
   336         }
       
   337 
       
   338 
       
   339     // Okay, get the state and error (from status).
       
   340     iCurrentCchState = serviceStatus.State();
       
   341     iLastCchError = serviceStatus.Error();
       
   342 
       
   343     RUBY_DEBUG1( " -Service state = %d", iCurrentCchState );
       
   344 
       
   345 
       
   346     switch( iCurrentCchState )
       
   347         {
       
   348         case ECCHUninitialized:
       
   349         // Fall-through intended here
       
   350         case ECCHDisabled:
       
   351         // Fall-through intended here
       
   352         case ECCHDisconnecting:
       
   353             {
       
   354             RUBY_DEBUG0( " -Try to enable service, LEAVE if error" );
       
   355 
       
   356             // Enable, leave if errors,
       
   357             User::LeaveIfError( iCchService->Enable( ECCHVoIPSub ) );
       
   358 
       
   359             // Service should be enabled in a while,
       
   360             // we must disable it upon exiting since it was not enabled
       
   361             // (we are one who enabled it so must disable it).
       
   362 
       
   363             iDisableService = ETrue;
       
   364             break;
       
   365             }
       
   366 
       
   367         case ECCHConnecting:
       
   368             {
       
   369             // Service is connecting (by someone else
       
   370             // or we have been called more than twice).
       
   371             // We should get the notification when it is enabled
       
   372             // and ready for the use.
       
   373             // Do nothing.
       
   374             break;
       
   375             }
       
   376 
       
   377         case ECCHEnabled:
       
   378             {
       
   379             RUBY_DEBUG0( " -Service is already enabled - do nothing" );
       
   380 
       
   381             // Enabled already. We can notify our observer
       
   382             // with the status of the service.
       
   383 
       
   384             NotifyObserver();
       
   385             break;
       
   386             }
       
   387 
       
   388         default:
       
   389             {
       
   390             break;
       
   391             }
       
   392 
       
   393         } // End of switch
       
   394 
       
   395 
       
   396     // So good so far...
       
   397     // Check if we can reserve (if not done already)
       
   398     // the service for us.
       
   399     // This prevents someone to disable it during a call
       
   400 
       
   401     if ( !iServiceReserved )
       
   402         {
       
   403         TBool isReserved( EFalse );
       
   404 
       
   405         iCchService->IsReserved( ECCHVoIPSub, isReserved );
       
   406 
       
   407         if ( !isReserved )
       
   408             {
       
   409             RUBY_DEBUG0( " -Try to reserve the service for us" );
       
   410 
       
   411             // It is free. Try to reserve it.
       
   412 
       
   413             if ( iCchService->Reserve( ECCHVoIPSub ) == KErrNone )
       
   414                 {
       
   415                 RUBY_DEBUG0( " -Service reserved for us" );
       
   416                 iServiceReserved = ETrue;
       
   417                 }
       
   418             }
       
   419         }
       
   420     }
       
   421 
       
   422 // ---------------------------------------------------------------------------
       
   423 // Return the current status of the service availability
       
   424 // ---------------------------------------------------------------------------
       
   425 //
       
   426 MVccCchObserver::TServiceStatus CVccCchMonitor::ServiceStatus() const
       
   427     {
       
   428     RUBY_DEBUG_BLOCK( "CVccCchMonitor::ServiceStatus" );
       
   429 
       
   430     RUBY_DEBUG1( " -Status = %d", iCurrentStatus );
       
   431 
       
   432     return iCurrentStatus;
       
   433     }