--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/keepalive/flextimer/server/src/flextimersession.cpp Mon May 24 20:51:35 2010 +0300
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2010 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 CFlexTimerSession class.
+ *
+ */
+/*
+ * %version: 1 %
+ */
+
+// System include files
+#include <e32def.h>
+#include <e32cmn.h>
+#include <hal.h>
+
+// User include files go here:
+#include "flextimercommon.h"
+#include "flextimersession.h"
+#include "mflextimerservice.h"
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "flextimersessionTraces.h"
+#endif
+
+// Constants
+
+// ======== MEMBER FUNCTIONS ========
+
+// --------------------------------------------------------------------------
+// Constructor
+// --------------------------------------------------------------------------
+//
+CFlexTimerSession::CFlexTimerSession( MFlexTimerService* aFlexTimerService )
+: iService( aFlexTimerService ),
+ iTimerWinSize( 0 ),
+ iUseDefaultWin( ETrue )
+ {
+ OstTrace1( TRACE_INTERNAL,
+ CFLEXTIMERSESSION,
+ "CFlexTimerSession::CFlexTimerSession; this=%x",
+ ( TUint )this );
+ }
+
+// --------------------------------------------------------------------------
+// Destructor
+// --------------------------------------------------------------------------
+//
+CFlexTimerSession::~CFlexTimerSession()
+ {
+ OstTrace1( TRACE_INTERNAL,
+ CFLEXTIMERSESSIOND,
+ "CFlexTimerSession::~CFlexTimerSession; this=%x",
+ ( TUint )this );
+ }
+
+// --------------------------------------------------------------------------
+// Function called from CFlexTimerService::RunL for messages targeted to
+// this session
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::ServiceL( const RMessage2& aMessage )
+ {
+ TInt msgType( aMessage.Function() );
+
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_MSG,
+ "CFlexTimerSession::ServiceL; this=%x; msgType=%d",
+ ( TInt )this,
+ msgType );
+
+ // Check message type and pass it to correct handler. Handler either
+ // stores the message or completes it immediately.
+ switch ( msgType )
+ {
+ case EFlexTimerServCancelRequest:
+ CancelTimer( aMessage );
+ break;
+ case EFlexTimerServAtRequest:
+ NewAtTimer( aMessage );
+ break;
+ case EFlexTimerServAtUTCRequest:
+ NewAtUtcTimer( aMessage );
+ break;
+ case EFlexTimerServAfterRequest:
+ NewAfterTimer( aMessage );
+ break;
+ case EFlexTimerServAfterTicksRequest:
+ NewAfterTicksTimer( aMessage );
+ break;
+ case EFlexTimerServConfigureRequest:
+ ConfigureParameters( aMessage );
+ break;
+ default:
+ OstTrace1(
+ TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ERROR,
+ "CFlexTimerSession::ServiceL: Unknown message; this=%x",
+ ( TUint )this );
+ aMessage.Complete( KErrNotSupported );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Timeout handler for triggering timers
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::Timeout() const
+ {
+ // Check for the validity of pending timeout request
+ if ( !iPendingTimeoutMsg.IsNull() )
+ {
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_TIMEOUT,
+ "CFlexTimerSession::Timeout; this=%x; msg=%x",
+ ( TUint )this,
+ ( TUint )iPendingTimeoutMsg.Handle() );
+ // Complete message, this sets message pointer to NULL
+ iPendingTimeoutMsg.Complete( KErrNone );
+ }
+ else
+ {
+ // No valid message pointer, nothing we can do here
+ OstTrace1( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_TIMEOUT_ERROR,
+ "CFlexTimerSession::Timeout: No Pending message; this=%x",
+ ( TUint )this );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Function for aborting At-timer
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::Abort( TInt aReason ) const
+ {
+ // Check for the validity of pending timeout request
+ if ( !iPendingTimeoutMsg.IsNull() )
+ {
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ABORT,
+ "CFlexTimerSession::Abort; this=%x; msg=%x",
+ ( TUint )this,
+ ( TUint )iPendingTimeoutMsg.Handle() );
+ // Complete message, this sets message pointer to NULL
+ iPendingTimeoutMsg.Complete( aReason );
+ }
+ else
+ {
+ // No valid message pointer, nothing we can do here
+ OstTrace1(
+ TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ABORT_ERROR,
+ "CFlexTimerSession::Abort: No Pending message; this=%x",
+ ( TUint )this );
+
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handler function for starting At() -timer
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::NewAtTimer( const RMessage2& aMessage )
+ {
+
+ // Check that we do not have a pending timer request
+ if ( !iPendingTimeoutMsg.IsNull() )
+ {
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ATPANIC,
+ "CFlexTimerSession::NewAtTimer: Already pending; "
+ "this=%x; msg=%x",
+ ( TUint )this,
+ ( TUint )iPendingTimeoutMsg.Handle() );
+
+ aMessage.Panic( KRFlexTimerPanicCat,
+ EFlexTimerServerErrorPendingTimer );
+ return;
+ }
+
+ // Get interval from current time to the requested timestamp
+ TTime refTime;
+ refTime.HomeTime();
+ TTimeIntervalMicroSeconds interval;
+ GetIntervalToMsgTime( aMessage, refTime, interval );
+
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ATTIMER,
+ "CFlexTimerSession::NewAtTimer; this=%x; interval=%lld",
+ ( TUint )this,
+ interval.Int64() );
+
+ // Add the timer to engine
+ DoAddTimer( aMessage, interval, ETrue );
+
+ }
+
+// --------------------------------------------------------------------------
+// Handler function for starting AtUTC() -timer
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::NewAtUtcTimer( const RMessage2& aMessage )
+ {
+
+ // Check that we do not have a pending timer request
+ if ( !iPendingTimeoutMsg.IsNull() )
+ {
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ATUTCPANIC,
+ "CFlexTimerSession::NewAtUtcTimer: Already pending; "
+ "this=%x; msg=%x",
+ ( TUint )this,
+ ( TUint )iPendingTimeoutMsg.Handle() );
+
+ aMessage.Panic( KRFlexTimerPanicCat,
+ EFlexTimerServerErrorPendingTimer );
+ return;
+ }
+
+ TTime refTime;
+ refTime.UniversalTime();
+ TTimeIntervalMicroSeconds interval;
+ GetIntervalToMsgTime( aMessage, refTime, interval );
+
+ OstTraceExt2(
+ TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ATUTCTIMER,
+ "CFlexTimerSession::NewAtUtcTimer; this=%x; interval=%lld",
+ ( TUint )this,
+ interval.Int64() );
+
+ // Add the timer to engine
+ DoAddTimer( aMessage, interval, ETrue );
+
+ }
+
+// --------------------------------------------------------------------------
+// Handler function for starting After()-timer
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::NewAfterTimer( const RMessage2& aMessage )
+ {
+
+ // Check that we do not have a pending timer request
+ if ( !iPendingTimeoutMsg.IsNull() )
+ {
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_AFTERPANIC,
+ "CFlexTimerSession::NewAfterTimer: Already pending; "
+ "this=%x; msg=%x",
+ ( TUint )this,
+ ( TUint )iPendingTimeoutMsg.Handle() );
+
+ aMessage.Panic( KRFlexTimerPanicCat,
+ EFlexTimerServerErrorPendingTimer );
+ return;
+ }
+
+ TInt64 timeStamp = MAKE_TINT64( aMessage.Int1(), aMessage.Int0() );
+ TTimeIntervalMicroSeconds interval( timeStamp );
+
+ OstTraceExt2(
+ TRACE_INTERNAL,
+ CFLEXTIMERSESSION_AFTERTIMER,
+ "CFlexTimerSession::NewAfterTimer; this=%x; interval=%llu",
+ ( TUint )this,
+ interval.Int64() );
+
+ // Add the timer to engine, request cancellation if the secure time
+ // is not available
+ DoAddTimer( aMessage, interval, EFalse );
+ }
+
+// --------------------------------------------------------------------------
+// Handler function for starting AfterTicks()-timer
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::NewAfterTicksTimer( const RMessage2& aMessage )
+ {
+
+ // Check that we do not have a pending timer request
+ if ( !iPendingTimeoutMsg.IsNull() )
+ {
+ OstTraceExt2(
+ TRACE_INTERNAL,
+ CFLEXTIMERSESSION_AFTERTICKSPANIC,
+ "CFlexTimerSession::NewAfterTicksTimer: Already pending; "
+ "this=%x; msg=%x",
+ ( TUint )this,
+ ( TUint )iPendingTimeoutMsg.Handle() );
+
+ aMessage.Panic( KRFlexTimerPanicCat,
+ EFlexTimerServerErrorPendingTimer );
+ return;
+ }
+
+ // Get the tick period from HAL and convert ticks to microseconds
+ TInt tickUs;
+ HAL::Get( HAL::ESystemTickPeriod, tickUs );
+
+ TTimeIntervalMicroSeconds interval =
+ static_cast<TInt64> ( aMessage.Int0() ) * tickUs;
+
+ OstTraceExt2(
+ TRACE_INTERNAL,
+ CFLEXTIMERSESSION_AFTERTICKSTIMER,
+ "CFlexTimerSession::NewAfterTicksTimer; this=%x; interval=%llu",
+ ( TUint )this,
+ interval.Int64() );
+
+ // Add the timer to engine
+ DoAddTimer( aMessage, interval, EFalse );
+ }
+
+// --------------------------------------------------------------------------
+// Handler function for cancelling running timer
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::CancelTimer( const RMessage2& aMessage )
+ {
+ TInt ret;
+ // Check that we have a pending timer request
+ if ( iPendingTimeoutMsg.IsNull() )
+ {
+ OstTrace1(
+ TRACE_INTERNAL,
+ CFLEXTIMERSESSION_CANCELERROR,
+ "CFlexTimerSession::CancelTimer: no pending msg; this=%x",
+ ( TUint )this );
+ ret = KErrNotFound;
+ }
+ else
+ {
+ ret = iService->CancelTimer( this );
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_CANCEL,
+ "CFlexTimerSession::CancelTimer; this=%x; ret=%d",
+ ( TUint )this,
+ ret );
+
+ // Complete pending message, this sets message pointer to NULL
+ iPendingTimeoutMsg.Complete( KErrCancel );
+ }
+
+ // Complete cancel message
+ aMessage.Complete( ret );
+ }
+
+// --------------------------------------------------------------------------
+// Handler function for configuring timer parameters
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::ConfigureParameters( const RMessage2& aMessage )
+ {
+ TInt ret( KErrNone );
+
+ // Configuration is not allowed when there is a pending message
+ if ( !iPendingTimeoutMsg.IsNull() )
+ {
+ OstTrace1( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_CONFIGERROR,
+ "CFlexTimerSession::ConfigureParameters: Timer pending; "
+ "this=%x",
+ ( TUint )this );
+ ret = KErrInUse;
+ }
+ else
+ {
+ TInt paramType( aMessage.Int0() );
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_CONFIG,
+ "CFlexTimerSession::ConfigureParameters; this=%x; "
+ "paramType=%d",
+ ( TUint )this,
+ paramType );
+
+ switch ( paramType )
+ {
+ case EConfigureRequestWindowSize:
+ {
+ TInt winLo = aMessage.Int1();
+ TInt winHi = aMessage.Int2();
+
+ iTimerWinSize = MAKE_TINT64( winHi, winLo );
+ iUseDefaultWin = EFalse;
+
+ OstTraceExt1( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_CONFIGWIN,
+ "CFlexTimerSession::ConfigureParameters; "
+ "iTimerWinSize=%lld",
+ iTimerWinSize.Int64() );
+
+ if ( iTimerWinSize.Int64() < 0 ||
+ iTimerWinSize.Int64() > KFlexTimerMaxTimerLength )
+ {
+ aMessage.Panic( KRFlexTimerPanicCat,
+ EFlexTimerServerIllegalTimerValue );
+ // Return after panicing the client -- completing the
+ // message afterwards panics the server with USER 70.
+ return;
+ }
+ break;
+ }
+ default:
+ OstTrace0( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_CONFIGUNKNOWN,
+ "CFlexTimerSession::ConfigureParameters: "
+ "ERROR - Invalid parameter type" );
+ ret = KErrNotSupported;
+ break;
+ }
+ }
+ aMessage.Complete( ret );
+ }
+
+// --------------------------------------------------------------------------
+// Function for adding timer to engine and handling its return value
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::DoAddTimer( const RMessage2& aMessage,
+ TTimeIntervalMicroSeconds& aWinEnd,
+ TBool aRequestAbort )
+ {
+ OstTraceExt4( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ADDTIMER,
+ "CFlexTimerSession::DoAddTimer; this=%x; msg=%x; aWinEnd=%llu;"
+ " aRequestAbort=%d",
+ ( TUint )this,
+ ( TUint )aMessage.Handle(),
+ aWinEnd.Int64(),
+ aRequestAbort );
+
+ // Check that the timer has valid values.
+ if ( aWinEnd.Int64() < 0 || aWinEnd.Int64() > KFlexTimerMaxTimerLength)
+ {
+ OstTraceExt4( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_DOADDTIMER,
+ "CFlexTimerSession::DoAddTimer;Invalid parameters "
+ "- panicing client;this=%x;aMessage=%x;aWinEnd=%llu;"
+ "aRequestAbort=%d",
+ ( TUint )this,
+ ( TUint )aMessage.Handle(),
+ aWinEnd.Int64(),
+ aRequestAbort );
+ aMessage.Panic( KRFlexTimerPanicCat,
+ EFlexTimerServerIllegalTimerValue );
+ return;
+ }
+
+ TTimeIntervalMicroSeconds winStart;
+ TTimeIntervalMicroSeconds window = iTimerWinSize;
+
+ if ( iUseDefaultWin )
+ {
+ window = static_cast<TInt64> ( static_cast<TReal64> ( aWinEnd.Int64() )
+ * KDefaultWindowMultiplier );
+ }
+
+ winStart = aWinEnd.Int64() - window.Int64();
+
+ // Store pending message. Not completed until timer expires.
+ // Note that in case of zero or negative timer value, message can
+ // be completed through Timeout() even before AddTimer returns. This
+ // implementation saves some checks and timer stopping/starting in engine.
+ iPendingTimeoutMsg = aMessage;
+
+ // Add timer to engine
+ TInt ret = iService->AddTimer( winStart, aWinEnd, aRequestAbort, this );
+
+ if ( KErrNone != ret )
+ {
+ // Failed, pass error code to client side
+ OstTraceExt2( TRACE_INTERNAL,
+ CFLEXTIMERSESSION_ADDERROR,
+ "CFlexTimerSession::DoAddTimer: Error; this=%x, ret=%d",
+ ( TUint )this,
+ ret );
+ // Complete pending message, this sets message pointer to NULL
+ iPendingTimeoutMsg.Complete( ret );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// From CSession2
+// Function for handling unintentional termination of the client
+// --------------------------------------------------------------------------
+//
+void CFlexTimerSession::Disconnect( const RMessage2 &aMessage )
+ {
+ // The client of this session has died.
+
+ // Remove timer from engine.
+ iService->CancelTimer( this );
+
+ // Disconnect() must end with a call to the base class implementation,
+ // which will delete the session object and complete the disconnect
+ // message.
+ CSession2::Disconnect( aMessage );
+ }