keepalive/flextimer/server/src/flextimersession.cpp
changeset 32 5c4486441ae6
equal deleted inserted replaced
31:c16e04725da3 32:5c4486441ae6
       
     1 /*
       
     2  * Copyright (c) 2010 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 CFlexTimerSession class.
       
    15  *
       
    16  */
       
    17 /*
       
    18  * %version: 1 %
       
    19  */
       
    20 
       
    21 // System include files
       
    22 #include <e32def.h>
       
    23 #include <e32cmn.h>
       
    24 #include <hal.h>
       
    25 
       
    26 // User include files go here:
       
    27 #include "flextimercommon.h"
       
    28 #include "flextimersession.h"
       
    29 #include "mflextimerservice.h"
       
    30 #include "OstTraceDefinitions.h"
       
    31 #ifdef OST_TRACE_COMPILER_IN_USE
       
    32 #include "flextimersessionTraces.h"
       
    33 #endif
       
    34 
       
    35 // Constants
       
    36 
       
    37 // ======== MEMBER FUNCTIONS ========
       
    38 
       
    39 // --------------------------------------------------------------------------
       
    40 // Constructor
       
    41 // --------------------------------------------------------------------------
       
    42 //
       
    43 CFlexTimerSession::CFlexTimerSession( MFlexTimerService* aFlexTimerService )
       
    44 :   iService( aFlexTimerService ),
       
    45     iTimerWinSize( 0 ),
       
    46     iUseDefaultWin( ETrue )
       
    47     {
       
    48     OstTrace1( TRACE_INTERNAL,
       
    49                CFLEXTIMERSESSION,
       
    50                "CFlexTimerSession::CFlexTimerSession; this=%x",
       
    51                ( TUint )this );
       
    52     }
       
    53 
       
    54 // --------------------------------------------------------------------------
       
    55 // Destructor
       
    56 // --------------------------------------------------------------------------
       
    57 //
       
    58 CFlexTimerSession::~CFlexTimerSession()
       
    59     {
       
    60     OstTrace1( TRACE_INTERNAL,
       
    61                CFLEXTIMERSESSIOND,
       
    62                "CFlexTimerSession::~CFlexTimerSession; this=%x",
       
    63                ( TUint )this );
       
    64     }
       
    65 
       
    66 // --------------------------------------------------------------------------
       
    67 // Function called from CFlexTimerService::RunL for messages targeted to
       
    68 // this session
       
    69 // --------------------------------------------------------------------------
       
    70 //
       
    71 void CFlexTimerSession::ServiceL( const RMessage2& aMessage )
       
    72     {
       
    73     TInt msgType( aMessage.Function() );
       
    74 
       
    75     OstTraceExt2( TRACE_INTERNAL,
       
    76                   CFLEXTIMERSESSION_MSG,
       
    77                   "CFlexTimerSession::ServiceL; this=%x; msgType=%d",
       
    78                   ( TInt )this,
       
    79                   msgType );
       
    80 
       
    81     // Check message type and pass it to correct handler. Handler either 
       
    82     // stores the message or completes it immediately.
       
    83     switch ( msgType )
       
    84         {
       
    85         case EFlexTimerServCancelRequest:
       
    86             CancelTimer( aMessage );
       
    87             break;
       
    88         case EFlexTimerServAtRequest:
       
    89             NewAtTimer( aMessage );
       
    90             break;
       
    91         case EFlexTimerServAtUTCRequest:
       
    92             NewAtUtcTimer( aMessage );
       
    93             break;
       
    94         case EFlexTimerServAfterRequest:
       
    95             NewAfterTimer( aMessage );
       
    96             break;
       
    97         case EFlexTimerServAfterTicksRequest:
       
    98             NewAfterTicksTimer( aMessage );
       
    99             break;
       
   100         case EFlexTimerServConfigureRequest:
       
   101             ConfigureParameters( aMessage );
       
   102             break;
       
   103         default:
       
   104             OstTrace1(
       
   105                     TRACE_INTERNAL,
       
   106                     CFLEXTIMERSESSION_ERROR,
       
   107                     "CFlexTimerSession::ServiceL: Unknown message; this=%x",
       
   108                     ( TUint )this );
       
   109             aMessage.Complete( KErrNotSupported );
       
   110         }
       
   111     }
       
   112 
       
   113 // --------------------------------------------------------------------------
       
   114 // Timeout handler for triggering timers
       
   115 // --------------------------------------------------------------------------
       
   116 //
       
   117 void CFlexTimerSession::Timeout() const
       
   118     {
       
   119     // Check for the validity of pending timeout request
       
   120     if ( !iPendingTimeoutMsg.IsNull() )
       
   121         {
       
   122         OstTraceExt2( TRACE_INTERNAL,
       
   123                       CFLEXTIMERSESSION_TIMEOUT,
       
   124                       "CFlexTimerSession::Timeout; this=%x; msg=%x",
       
   125                       ( TUint )this,
       
   126                       ( TUint )iPendingTimeoutMsg.Handle() );
       
   127         // Complete message, this sets message pointer to NULL
       
   128         iPendingTimeoutMsg.Complete( KErrNone );
       
   129         }
       
   130     else
       
   131         {
       
   132         // No valid message pointer, nothing we can do here
       
   133         OstTrace1( TRACE_INTERNAL,
       
   134                    CFLEXTIMERSESSION_TIMEOUT_ERROR,
       
   135                    "CFlexTimerSession::Timeout: No Pending message; this=%x",
       
   136                    ( TUint )this );
       
   137         }
       
   138     }
       
   139 
       
   140 // --------------------------------------------------------------------------
       
   141 // Function for aborting At-timer
       
   142 // --------------------------------------------------------------------------
       
   143 //
       
   144 void CFlexTimerSession::Abort( TInt aReason ) const
       
   145     {
       
   146     // Check for the validity of pending timeout request
       
   147     if ( !iPendingTimeoutMsg.IsNull() )
       
   148         {
       
   149         OstTraceExt2( TRACE_INTERNAL,
       
   150                       CFLEXTIMERSESSION_ABORT,
       
   151                       "CFlexTimerSession::Abort; this=%x; msg=%x",
       
   152                       ( TUint )this,
       
   153                       ( TUint )iPendingTimeoutMsg.Handle() );
       
   154         // Complete message, this sets message pointer to NULL
       
   155         iPendingTimeoutMsg.Complete( aReason );
       
   156         }
       
   157     else
       
   158         {
       
   159         // No valid message pointer, nothing we can do here
       
   160         OstTrace1(
       
   161                 TRACE_INTERNAL,
       
   162                 CFLEXTIMERSESSION_ABORT_ERROR,
       
   163                 "CFlexTimerSession::Abort: No Pending message; this=%x",
       
   164                 ( TUint )this );
       
   165 
       
   166         }
       
   167     }
       
   168 
       
   169 // --------------------------------------------------------------------------
       
   170 // Handler function for starting At() -timer
       
   171 // --------------------------------------------------------------------------
       
   172 //
       
   173 void CFlexTimerSession::NewAtTimer( const RMessage2& aMessage )
       
   174     {
       
   175 
       
   176     // Check that we do not have a pending timer request
       
   177     if ( !iPendingTimeoutMsg.IsNull() )
       
   178         {
       
   179         OstTraceExt2( TRACE_INTERNAL,
       
   180                       CFLEXTIMERSESSION_ATPANIC,
       
   181                       "CFlexTimerSession::NewAtTimer: Already pending; "
       
   182                       "this=%x; msg=%x",
       
   183                       ( TUint )this,
       
   184                       ( TUint )iPendingTimeoutMsg.Handle() );
       
   185 
       
   186         aMessage.Panic( KRFlexTimerPanicCat,
       
   187                         EFlexTimerServerErrorPendingTimer );
       
   188         return;
       
   189         }
       
   190 
       
   191     // Get interval from current time to the requested timestamp
       
   192     TTime refTime;
       
   193     refTime.HomeTime();
       
   194     TTimeIntervalMicroSeconds interval;
       
   195     GetIntervalToMsgTime( aMessage, refTime, interval );
       
   196 
       
   197     OstTraceExt2( TRACE_INTERNAL,
       
   198                   CFLEXTIMERSESSION_ATTIMER,
       
   199                   "CFlexTimerSession::NewAtTimer; this=%x; interval=%lld",
       
   200                   ( TUint )this,
       
   201                   interval.Int64() );
       
   202 
       
   203     // Add the timer to engine
       
   204     DoAddTimer( aMessage, interval, ETrue );
       
   205 
       
   206     }
       
   207 
       
   208 // --------------------------------------------------------------------------
       
   209 // Handler function for starting AtUTC() -timer
       
   210 // --------------------------------------------------------------------------
       
   211 //
       
   212 void CFlexTimerSession::NewAtUtcTimer( const RMessage2& aMessage )
       
   213     {
       
   214 
       
   215     // Check that we do not have a pending timer request
       
   216     if ( !iPendingTimeoutMsg.IsNull() )
       
   217         {
       
   218         OstTraceExt2( TRACE_INTERNAL,
       
   219                       CFLEXTIMERSESSION_ATUTCPANIC,
       
   220                       "CFlexTimerSession::NewAtUtcTimer: Already pending; "
       
   221                       "this=%x; msg=%x",
       
   222                       ( TUint )this,
       
   223                       ( TUint )iPendingTimeoutMsg.Handle() );
       
   224 
       
   225         aMessage.Panic( KRFlexTimerPanicCat,
       
   226                         EFlexTimerServerErrorPendingTimer );
       
   227         return;
       
   228         }
       
   229 
       
   230     TTime refTime;
       
   231     refTime.UniversalTime();
       
   232     TTimeIntervalMicroSeconds interval;
       
   233     GetIntervalToMsgTime( aMessage, refTime, interval );
       
   234     
       
   235     OstTraceExt2( 
       
   236             TRACE_INTERNAL,
       
   237             CFLEXTIMERSESSION_ATUTCTIMER,
       
   238             "CFlexTimerSession::NewAtUtcTimer; this=%x; interval=%lld",
       
   239             ( TUint )this,
       
   240             interval.Int64() );
       
   241 
       
   242     // Add the timer to engine
       
   243     DoAddTimer( aMessage, interval, ETrue );
       
   244 
       
   245     }
       
   246 
       
   247 // --------------------------------------------------------------------------
       
   248 // Handler function for starting After()-timer
       
   249 // --------------------------------------------------------------------------
       
   250 //
       
   251 void CFlexTimerSession::NewAfterTimer( const RMessage2& aMessage )
       
   252     {
       
   253 
       
   254     // Check that we do not have a pending timer request
       
   255     if ( !iPendingTimeoutMsg.IsNull() )
       
   256         {
       
   257         OstTraceExt2( TRACE_INTERNAL,
       
   258                       CFLEXTIMERSESSION_AFTERPANIC,
       
   259                       "CFlexTimerSession::NewAfterTimer: Already pending; "
       
   260                       "this=%x; msg=%x",
       
   261                       ( TUint )this,
       
   262                       ( TUint )iPendingTimeoutMsg.Handle() );
       
   263 
       
   264         aMessage.Panic( KRFlexTimerPanicCat,
       
   265                         EFlexTimerServerErrorPendingTimer );
       
   266         return;
       
   267         }
       
   268 
       
   269     TInt64 timeStamp = MAKE_TINT64( aMessage.Int1(), aMessage.Int0() );
       
   270     TTimeIntervalMicroSeconds interval( timeStamp );
       
   271 
       
   272     OstTraceExt2(
       
   273             TRACE_INTERNAL,
       
   274             CFLEXTIMERSESSION_AFTERTIMER,
       
   275             "CFlexTimerSession::NewAfterTimer; this=%x; interval=%llu",
       
   276             ( TUint )this,
       
   277             interval.Int64() );
       
   278 
       
   279     // Add the timer to engine, request cancellation if the secure time
       
   280     // is not available
       
   281     DoAddTimer( aMessage, interval, EFalse );
       
   282     }
       
   283 
       
   284 // --------------------------------------------------------------------------
       
   285 // Handler function for starting AfterTicks()-timer
       
   286 // --------------------------------------------------------------------------
       
   287 //
       
   288 void CFlexTimerSession::NewAfterTicksTimer( const RMessage2& aMessage )
       
   289     {
       
   290 
       
   291     // Check that we do not have a pending timer request
       
   292     if ( !iPendingTimeoutMsg.IsNull() )
       
   293         {
       
   294         OstTraceExt2(
       
   295                 TRACE_INTERNAL,
       
   296                 CFLEXTIMERSESSION_AFTERTICKSPANIC,
       
   297                 "CFlexTimerSession::NewAfterTicksTimer: Already pending; "
       
   298                 "this=%x; msg=%x",
       
   299                 ( TUint )this,
       
   300                 ( TUint )iPendingTimeoutMsg.Handle() );
       
   301 
       
   302         aMessage.Panic( KRFlexTimerPanicCat,
       
   303                         EFlexTimerServerErrorPendingTimer );
       
   304         return;
       
   305         }
       
   306 
       
   307     // Get the tick period from HAL and convert ticks to microseconds
       
   308     TInt tickUs;
       
   309     HAL::Get( HAL::ESystemTickPeriod, tickUs );
       
   310 
       
   311     TTimeIntervalMicroSeconds interval =
       
   312             static_cast<TInt64> ( aMessage.Int0() ) * tickUs;
       
   313 
       
   314     OstTraceExt2(
       
   315             TRACE_INTERNAL,
       
   316             CFLEXTIMERSESSION_AFTERTICKSTIMER,
       
   317             "CFlexTimerSession::NewAfterTicksTimer; this=%x; interval=%llu",
       
   318             ( TUint )this,
       
   319             interval.Int64() );
       
   320 
       
   321     // Add the timer to engine
       
   322     DoAddTimer( aMessage, interval, EFalse );
       
   323     }
       
   324 
       
   325 // --------------------------------------------------------------------------
       
   326 // Handler function for cancelling running timer
       
   327 // --------------------------------------------------------------------------
       
   328 //
       
   329 void CFlexTimerSession::CancelTimer( const RMessage2& aMessage )
       
   330     {
       
   331     TInt ret;
       
   332     // Check that we have a pending timer request
       
   333     if ( iPendingTimeoutMsg.IsNull() )
       
   334         {
       
   335         OstTrace1(
       
   336                 TRACE_INTERNAL,
       
   337                 CFLEXTIMERSESSION_CANCELERROR,
       
   338                 "CFlexTimerSession::CancelTimer: no pending msg; this=%x",
       
   339                 ( TUint )this );
       
   340         ret = KErrNotFound;
       
   341         }
       
   342     else
       
   343         {
       
   344         ret = iService->CancelTimer( this );
       
   345         OstTraceExt2( TRACE_INTERNAL,
       
   346                       CFLEXTIMERSESSION_CANCEL,
       
   347                       "CFlexTimerSession::CancelTimer; this=%x; ret=%d",
       
   348                       ( TUint )this,
       
   349                       ret );
       
   350 
       
   351         // Complete pending message, this sets message pointer to NULL
       
   352         iPendingTimeoutMsg.Complete( KErrCancel );
       
   353         }
       
   354 
       
   355     // Complete cancel message
       
   356     aMessage.Complete( ret );
       
   357     }
       
   358 
       
   359 // --------------------------------------------------------------------------
       
   360 // Handler function for configuring timer parameters
       
   361 // --------------------------------------------------------------------------
       
   362 //
       
   363 void CFlexTimerSession::ConfigureParameters( const RMessage2& aMessage )
       
   364     {
       
   365     TInt ret( KErrNone );
       
   366 
       
   367     // Configuration is not allowed when there is a pending message
       
   368     if ( !iPendingTimeoutMsg.IsNull() )
       
   369         {
       
   370         OstTrace1( TRACE_INTERNAL,
       
   371                    CFLEXTIMERSESSION_CONFIGERROR,
       
   372                    "CFlexTimerSession::ConfigureParameters: Timer pending; "
       
   373                    "this=%x",
       
   374                    ( TUint )this );
       
   375         ret = KErrInUse;
       
   376         }
       
   377     else
       
   378         {
       
   379         TInt paramType( aMessage.Int0() );
       
   380         OstTraceExt2( TRACE_INTERNAL,
       
   381                       CFLEXTIMERSESSION_CONFIG,
       
   382                       "CFlexTimerSession::ConfigureParameters; this=%x; "
       
   383                       "paramType=%d",
       
   384                       ( TUint )this,
       
   385                       paramType );
       
   386 
       
   387         switch ( paramType )
       
   388             {
       
   389             case EConfigureRequestWindowSize:
       
   390                 {
       
   391                 TInt winLo = aMessage.Int1();
       
   392                 TInt winHi = aMessage.Int2();
       
   393 
       
   394                 iTimerWinSize = MAKE_TINT64( winHi, winLo );
       
   395                 iUseDefaultWin = EFalse;
       
   396 
       
   397                 OstTraceExt1( TRACE_INTERNAL,
       
   398                               CFLEXTIMERSESSION_CONFIGWIN,
       
   399                               "CFlexTimerSession::ConfigureParameters; "
       
   400                               "iTimerWinSize=%lld",
       
   401                               iTimerWinSize.Int64() );
       
   402                 
       
   403                 if ( iTimerWinSize.Int64() < 0 ||
       
   404                     iTimerWinSize.Int64() > KFlexTimerMaxTimerLength )
       
   405                     {
       
   406                     aMessage.Panic( KRFlexTimerPanicCat,
       
   407                         EFlexTimerServerIllegalTimerValue );
       
   408                     // Return after panicing the client -- completing the
       
   409                     // message afterwards panics the server with USER 70.
       
   410                     return;
       
   411                     }
       
   412                 break;
       
   413                 }
       
   414             default:
       
   415                 OstTrace0( TRACE_INTERNAL,
       
   416                            CFLEXTIMERSESSION_CONFIGUNKNOWN,
       
   417                            "CFlexTimerSession::ConfigureParameters: "
       
   418                            "ERROR - Invalid parameter type" );
       
   419                 ret = KErrNotSupported;
       
   420                 break;
       
   421             }
       
   422         }
       
   423     aMessage.Complete( ret );
       
   424     }
       
   425 
       
   426 // --------------------------------------------------------------------------
       
   427 // Function for adding timer to engine and handling its return value
       
   428 // --------------------------------------------------------------------------
       
   429 //
       
   430 void CFlexTimerSession::DoAddTimer( const RMessage2& aMessage,
       
   431                                     TTimeIntervalMicroSeconds& aWinEnd,
       
   432                                     TBool aRequestAbort )
       
   433     {
       
   434     OstTraceExt4( TRACE_INTERNAL,
       
   435                CFLEXTIMERSESSION_ADDTIMER,
       
   436                "CFlexTimerSession::DoAddTimer; this=%x; msg=%x; aWinEnd=%llu;"
       
   437                " aRequestAbort=%d",
       
   438                ( TUint )this,
       
   439                ( TUint )aMessage.Handle(),
       
   440                aWinEnd.Int64(),
       
   441                aRequestAbort );  
       
   442     
       
   443     // Check that the timer has valid values.
       
   444     if ( aWinEnd.Int64() < 0 || aWinEnd.Int64() > KFlexTimerMaxTimerLength)
       
   445         {
       
   446         OstTraceExt4( TRACE_INTERNAL, 
       
   447                       CFLEXTIMERSESSION_DOADDTIMER, 
       
   448                       "CFlexTimerSession::DoAddTimer;Invalid parameters "
       
   449                       "- panicing client;this=%x;aMessage=%x;aWinEnd=%llu;"
       
   450                       "aRequestAbort=%d", 
       
   451                       ( TUint )this, 
       
   452                       ( TUint )aMessage.Handle(), 
       
   453                       aWinEnd.Int64(),
       
   454                       aRequestAbort );
       
   455         aMessage.Panic( KRFlexTimerPanicCat,
       
   456                         EFlexTimerServerIllegalTimerValue );
       
   457         return;
       
   458         }
       
   459     
       
   460     TTimeIntervalMicroSeconds winStart;
       
   461     TTimeIntervalMicroSeconds window = iTimerWinSize;
       
   462     
       
   463     if ( iUseDefaultWin )
       
   464         {
       
   465         window = static_cast<TInt64> ( static_cast<TReal64> ( aWinEnd.Int64() )
       
   466             * KDefaultWindowMultiplier );
       
   467         }
       
   468 
       
   469     winStart = aWinEnd.Int64() - window.Int64();
       
   470 
       
   471     // Store pending message. Not completed until timer expires.
       
   472     // Note that in case of zero or negative timer value, message can
       
   473     // be completed through Timeout() even before AddTimer returns. This
       
   474     // implementation saves some checks and timer stopping/starting in engine.
       
   475     iPendingTimeoutMsg = aMessage;
       
   476 
       
   477     // Add timer to engine
       
   478     TInt ret = iService->AddTimer( winStart, aWinEnd, aRequestAbort, this );
       
   479 
       
   480     if ( KErrNone != ret )
       
   481         {
       
   482         // Failed, pass error code to client side
       
   483         OstTraceExt2( TRACE_INTERNAL,
       
   484                    CFLEXTIMERSESSION_ADDERROR,
       
   485                    "CFlexTimerSession::DoAddTimer: Error; this=%x, ret=%d",
       
   486                    ( TUint )this,
       
   487                    ret );
       
   488         // Complete pending message, this sets message pointer to NULL
       
   489         iPendingTimeoutMsg.Complete( ret );
       
   490         }
       
   491     }
       
   492 
       
   493 // --------------------------------------------------------------------------
       
   494 // From CSession2
       
   495 // Function for handling unintentional termination of the client
       
   496 // --------------------------------------------------------------------------
       
   497 //
       
   498 void CFlexTimerSession::Disconnect( const RMessage2 &aMessage )
       
   499     {
       
   500     // The client of this session has died.
       
   501     
       
   502     // Remove timer from engine.
       
   503     iService->CancelTimer( this );
       
   504 
       
   505     // Disconnect() must end with a call to the base class implementation, 
       
   506     // which will delete the session object and complete the disconnect 
       
   507     // message.
       
   508     CSession2::Disconnect( aMessage );
       
   509     }