--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hti/HtiFramework/src/HtiDispatcher.cpp Wed Oct 13 16:17:58 2010 +0300
@@ -0,0 +1,1334 @@
+/*
+* Copyright (c) 2009 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: This file contains the implementations of the CHTIDispatcher
+* class.
+*
+*/
+
+
+#include "HtiDispatcher.h"
+#include "HtiMessage.h"
+#include "HtiMessageQueue.h"
+#include "HtiLogging.h"
+#include "HtiCommAdapter.h"
+#include "HtiServicePluginInterface.h"
+#include "HtiCommPluginInterface.h"
+#include "HtiSecurityManager.h"
+#include "HtiVersion.h"
+
+#include <e32debug.h>
+
+//active objects priorities
+const static TInt KHtiIdlePriority = 2;
+
+const static TInt KDefaultMaxQueueSize = 4 * 1024 * 1024; // 4 MB
+
+//HTI system service commands
+enum THtiCommand
+ {
+ EHtiAuthentication = 0x01,
+ EHtiVersion = 0x02,
+ EHtiServiceList = 0x03,
+ EHtiStop = 0x04,
+ EHtiReboot = 0x05,
+ EHtiFormat = 0x06,
+ EHtiReset = 0x07,
+ EHtiShowConsole = 0x08,
+ EHtiHideConsole = 0x09,
+ EHtiInstanceId = 0x0A,
+ EHtiDebugPrint = 0x0B,
+ EHtiRestartServices= 0x0C,
+ EHtiError = 0xFF
+ };
+
+//HTI error messages
+const static TInt KMaxErrMessageLength = KErrorDescriptionMaxLength + 10;
+
+//error descriptions
+_LIT8( KHtiSystemCmdErrDescr, "Unknown HTI command" );
+_LIT8( KErrDescrDispatchOut, "Failed to dispatch message" );
+_LIT8( KErrDescrWrap, "Failed to wrap message" );
+_LIT8( KErrDescrDispatchOutError, "Failed to dispatch error message" );
+_LIT8( KErrDescrInvalidParameter, "Invalid command parameter" );
+_LIT8( KErrDescrNotInRom, "Command supported only if HTI is running from ROM" );
+
+const static TChar KSpChar = ' ';
+const static TChar KNewLineChar = '\n';
+const static TInt KHtiServiceNameLength = 124;
+const static TInt KHtiServiceListRecordLength = KHtiServiceNameLength + 4;
+
+_LIT( KHtiWatchDogMatchPattern, "HtiWatchDog*" );
+_LIT( KHtiDeviceRebootExeOS, "HtiDeviceRebootOS.exe" );
+_LIT( KHtiDeviceRebootExeUI, "HtiDeviceRebootUI.exe" );
+_LIT( KHtiRestartExeName, "HtiRestart.exe");
+
+_LIT( KParamNormalRfs, "rfsnormal" );
+_LIT( KParamDeepRfs, "rfsdeep" );
+
+TDesC8* THtiSystemProtocolHelper::ErrorMessageL( TInt aHtiErrorCode,
+ const TUid aTargetServiceUid )
+ {
+ HBufC8* msg = HBufC8::NewL( KMaxErrMessageLength );
+ msg->Des().Append( EHtiError ); //one byte
+ msg->Des().Append( aHtiErrorCode ); //one byte
+ msg->Des().AppendFill( 0x00, 4 ); //missed service error code
+ //append uid as TInt32 by copying 4 bytes through pointer
+ msg->Des().Append( ( TUint8* )( &( aTargetServiceUid.iUid ) ), 4 );
+ return msg;
+ }
+
+TDesC8* THtiSystemProtocolHelper::ErrorMessageL( TInt aHtiErrorCode,
+ const TUid aTargetServiceUid,
+ TInt aErrorCode,
+ const TDesC8& aErrorDescription )
+ {
+ HBufC8* msg = HBufC8::NewL( KMaxErrMessageLength );
+ msg->Des().Append( EHtiError ); //one byte
+ msg->Des().Append( aHtiErrorCode ); //one byte
+ msg->Des().Append( ( TUint8* ) ( &aErrorCode ), 4 ); //4 bytes
+ //append uid as TInt32 by copying 4 bytes through pointer
+ msg->Des().Append( ( TUint8* )( &( aTargetServiceUid.iUid ) ), 4 );
+ msg->Des().Append( aErrorDescription );
+ return msg;
+ }
+
+TDesC8* THtiSystemProtocolHelper::AuthMessageL( const TDesC8& aToken )
+ {
+ HBufC8* msg = HBufC8::NewL( aToken.Length() + 1 );
+ msg->Des().Append( EHtiAuthentication );
+ msg->Des().Append( aToken );
+ return msg;
+ }
+
+/*************************************************************************
+* CHtiDispatcher implementation
+*
+**************************************************************************/
+CHtiDispatcher::CHtiDispatcher( TInt aMaxQueueMemorySize,
+ TInt aReconnectDelay, TBool aShowErrorDialogs ):
+ iIdleActive( EFalse ),
+ iMaxQueueMemorySize( aMaxQueueMemorySize > 0 ?
+ aMaxQueueMemorySize : KDefaultMaxQueueSize ),
+ iToReboot( EFalse ),
+ iRfsMode( ERfsUnknown ),
+ iConsole( NULL ),
+ iIdleOverCommAdapter( EFalse ),
+ iHtiInstanceId( 0 ),
+ iShowErrorDialogs( aShowErrorDialogs ),
+ iReconnectDelay(aReconnectDelay),
+ iRebootReason(-1)
+ {
+ HTI_LOG_FORMAT( "MaxQueueMemorySize %d", iMaxQueueMemorySize );
+ iQueueSizeLowThresold = ( iMaxQueueMemorySize / 2 ) / 2;
+ iQueueSizeHighThresold = ( iMaxQueueMemorySize / 2 ) * 4 / 5;
+ HTI_LOG_FORMAT( "QueueSizeThresholds low : %d", iQueueSizeLowThresold );
+ HTI_LOG_FORMAT( "QueueSizeThresholds high: %d", iQueueSizeHighThresold );
+ }
+
+void CHtiDispatcher::ConstructL( const TDesC8& aCommPlugin,
+ TInt aMaxMsgSize,
+ TBool aShowConsole )
+ {
+ HTI_LOG_FUNC_IN( "CHTIDispatcher::ConstructL()" );
+#ifdef __ENABLE_LOGGING__
+ DebugListPlugins();
+#endif
+
+ if ( aShowConsole )
+ {
+ // Create the HTI console
+ iConsole = Console::NewL( _L( "HtiFramework" ),
+ TSize( KConsFullScreen, KConsFullScreen ) );
+ iConsole->Printf( _L( "HTI Framework\n" ) );
+ iConsole->Printf( _L( "=============\n\n" ) );
+ iConsole->Printf( _L( "Version %u.%u\n" ),
+ KHtiVersionMajor, KHtiVersionMinor );
+ iConsole->Printf( _L( "Starting up...\n" ) );
+ }
+
+ //create queues
+ iIncomingQueue = CHtiMessageQueue::NewL();
+ iOutgoingQueue = CHtiMessageQueue::NewL();
+
+ //security manager init
+ iSecurityManager = CHtiSecurityManager::NewL();
+
+ //plugins array
+ iLoadedServices = new (ELeave)
+ RArray<TServiceItem>( KServiceArrayGranularity );
+
+ iMemoryObservers = new (ELeave)
+ RPointerArray<MHtiMemoryObserver>( KServiceArrayGranularity );
+
+ //try to load default plugin if specified can't be found
+ if ( aCommPlugin.Length() == 0 )
+ {
+ HTI_LOG_TEXT( "load default comm plugin" );
+ iCommPlugin = CHTICommPluginInterface::NewL();
+ }
+ else
+ {
+ HTI_LOG_TEXT( "load Comm plugin" );
+ HTI_LOG_DES( aCommPlugin );
+ iCommPlugin = CHTICommPluginInterface::NewL( aCommPlugin );
+ }
+
+ if ( iConsole )
+ {
+ iConsole->Printf( _L( "Communication plugin loaded.\n" ) );
+ }
+
+ iListener = CHtiCommAdapter::NewL( iCommPlugin, this, aMaxMsgSize );
+ iSender = CHtiCommAdapter::NewL( iCommPlugin, this, aMaxMsgSize );
+
+ //!!!!!!!!!!!!! -=IMPORTANT=- !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // idle should be created (added to AS) AFTER comm adapters
+ //!!!!!!!!!!!!! -=IMPORTANT=- !!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ //create CIdle object
+ iIdle = CIdle::NewL( KHtiIdlePriority );
+
+ // start listening for incoming messages
+ Reset();
+
+ HTI_LOG_FUNC_OUT( "CHTIDispatcher::ConstructL()" );
+ }
+
+CHtiDispatcher::~CHtiDispatcher()
+ {
+ HTI_LOG_FUNC_IN( "CHTIDispatcher::~CHTIDispatcher" );
+
+ if ( iIdle )
+ {
+ iIdle->Cancel();
+ delete iIdle;
+ }
+
+ UnloadAllServices();
+
+ if ( iLoadedServices )
+ {
+ iLoadedServices->Close();
+ delete iLoadedServices;
+ }
+
+ if ( iMemoryObservers )
+ {
+ iMemoryObservers->Close();
+ delete iMemoryObservers;
+ }
+
+ delete iIncomingQueue;
+ delete iOutgoingQueue;
+
+ delete iListener;
+ delete iSender;
+
+ delete iCommPlugin;
+
+ REComSession::FinalClose();
+
+ delete iSecurityManager;
+
+ if ( iRfsMode == ERfsNormal || iRfsMode == ERfsDeep )
+ {
+ HTI_LOG_FORMAT( "Activating Restore Factory Settings %d", iRfsMode );
+ RestoreFactorySettings();
+ }
+
+ if ( iToReboot )
+ {
+ HTI_LOG_TEXT( "Reboot now" );
+ Reboot();
+ }
+
+ delete iConsole;
+
+ HTI_LOG_FUNC_OUT( "CHTIDispatcher::~CHTIDispatcher" );
+ }
+
+
+CHtiDispatcher* CHtiDispatcher::NewLC( const TDesC8& aCommPlugin,
+ TInt aMaxMsgSize,
+ TInt aMaxQueueMemory,
+ TInt aReconnectDelay,
+ TBool aShowConsole,
+ TBool aShowErrorDialogs )
+ {
+ CHtiDispatcher* obj = new (ELeave) CHtiDispatcher(
+ aMaxQueueMemory, aReconnectDelay,aShowErrorDialogs );
+ CleanupStack::PushL( obj );
+ obj->ConstructL( aCommPlugin, aMaxMsgSize, aShowConsole );
+ return obj;
+ }
+
+CHtiDispatcher* CHtiDispatcher::NewL( const TDesC8& aCommPlugin,
+ TInt aMaxMsgSize,
+ TInt aMaxQueueMemory,
+ TInt aReconnectDelay,
+ TBool aShowConsole,
+ TBool aShowErrorDialogs )
+ {
+ CHtiDispatcher* obj = NewLC( aCommPlugin, aMaxMsgSize, aMaxQueueMemory,
+ aReconnectDelay,aShowConsole, aShowErrorDialogs );
+ CleanupStack::Pop();
+ return obj;
+ }
+
+CConsoleBase* CHtiDispatcher::GetConsole()
+ {
+ return iConsole;
+ }
+
+TBool CHtiDispatcher::GetShowErrorDialogs()
+ {
+ return iShowErrorDialogs;
+ }
+
+void CHtiDispatcher::CheckPriorities()
+ {
+ // If incoming queue reaches some high limit then lower its priority
+ // below idle object priority.
+ // Make opposite when incoming queue size reaches some low limit
+ if ( iIncomingQueue->QueueSize() > iQueueSizeHighThresold )
+ {
+ if ( !( iListener->IsActive() || iIdleOverCommAdapter ) )
+ {
+ HTI_LOG_TEXT( "Set listener priority low" );
+ iListener->Deque();
+ CActiveScheduler::Add( iListener );
+ iIdleOverCommAdapter = ETrue;
+ }
+ }
+ }
+
+void CHtiDispatcher::DispatchIncomingMessage( CHtiMessage* aMessage )
+ {
+ HTI_LOG_FUNC_IN( "DispatchIncomingMessage" );
+
+ iIncomingQueue->Add( *aMessage );
+
+ //start CIdle if needed
+ Start();
+ CheckPriorities();
+
+ HTI_LOG_FUNC_OUT( "DispatchIncomingMessage" );
+ }
+
+TInt CHtiDispatcher::DispatchOutgoingMessage( TDesC8* aMessage,
+ const TUid aTargetServiceUid,
+ TBool aWrappedFlag,
+ THtiMessagePriority aPriority )
+ {
+ HTI_LOG_FUNC_IN( "DispatchOutgoingMessage" );
+ HTI_LOG_TEXT( "Construct HTI message" );
+
+ //send only if enough memory
+ TInt returnErr = KErrNone;
+ if ( aMessage->Size() <= GetFreeMemory() )
+ {
+ //call here wrapping
+ CHtiMessage* msg = NULL;
+ if ( aWrappedFlag )
+ {
+ TDesC8* wrapped = NULL;
+ TRAP( returnErr, wrapped = iSecurityManager->WrapL( *aMessage ) );
+ if ( returnErr == KErrNone )
+ {
+ TRAP( returnErr,
+ msg = CHtiMessage::NewL( wrapped, aTargetServiceUid,
+ aWrappedFlag, aPriority ) );
+ if ( returnErr != KErrNone )
+ {
+ UrgentReboot( returnErr, KErrDescrDispatchOut );
+ }
+ //wrapped message is kept, original is deleted
+ delete aMessage;
+ }
+ else
+ {
+ UrgentReboot( returnErr, KErrDescrWrap );
+ }
+ }
+ else
+ {
+ TRAP( returnErr, msg = CHtiMessage::NewL( aMessage,
+ aTargetServiceUid, aWrappedFlag, aPriority ) );
+
+ if ( returnErr != KErrNone )
+ {
+ UrgentReboot( returnErr, KErrDescrDispatchOut );
+ }
+ }
+
+ // put in a queue
+ if ( msg )
+ iOutgoingQueue->Add( *msg );
+
+ //start CIdle if needed
+ Start();
+ }
+ else
+ {
+ returnErr = KErrNoMemory;
+ }
+
+ HTI_LOG_FUNC_OUT( "DispatchOutgoingMessage" );
+ return returnErr;
+ }
+
+TInt CHtiDispatcher::DispatchOutgoingErrorMessage( TInt aErrorCode,
+ const TDesC8& aErrorDescription,
+ const TUid aTargetServiceUid )
+ {
+ HTI_LOG_FUNC_IN( "DispatchError" );
+
+ if ( aTargetServiceUid == TUid::Null() )
+ {
+ return KErrArgument;
+ }
+
+ HTI_LOG_FORMAT( "ErrorCode %d", aErrorCode );
+ TInt err = KErrNone;
+ TDesC8* msg = NULL;
+ TRAP( err, msg = THtiSystemProtocolHelper::ErrorMessageL(
+ EHtiErrServiceError,
+ aTargetServiceUid,
+ aErrorCode,
+ aErrorDescription ) );
+
+ if ( err != KErrNone )
+ {
+ UrgentReboot( err, KErrDescrDispatchOutError );
+ }
+
+ err = DispatchOutgoingMessage( msg, KHtiSystemServiceUid,
+ EFalse, EHtiPriorityDefault );
+
+ if ( err == KErrNoMemory )
+ {
+ delete msg;
+ }
+
+ HTI_LOG_FUNC_OUT( "DispatchError" );
+ return err;
+ }
+
+TInt CHtiDispatcher::DispatchOutgoingErrorMessage( THtiError aHtiErroreCode,
+ TInt aLeaveCode,
+ const TUid aTargetServiceUid )
+ {
+ HTI_LOG_FORMAT( "leaveCode %d", aLeaveCode );
+ TInt err = KErrNone;
+ TDesC8* msg = NULL;
+
+ TRAP( err, msg = THtiSystemProtocolHelper::ErrorMessageL(
+ aHtiErroreCode,
+ aTargetServiceUid,
+ aLeaveCode,
+ KNullDesC8 ) );
+
+ if ( err != KErrNone )
+ {
+ UrgentReboot( err, KErrDescrDispatchOutError );
+ }
+
+ err = DispatchOutgoingMessage( msg, KHtiSystemServiceUid,
+ EFalse, EHtiPriorityDefault );
+
+ if ( err == KErrNoMemory )
+ {
+ delete msg;
+ }
+
+ return err;
+ }
+
+TInt CHtiDispatcher::DispatchOutgoingErrorMessage( THtiError aHtiErrorCode,
+ const TUid aTargetServiceUid )
+ {
+ HTI_LOG_FORMAT( "HtiErrorCode %d", aHtiErrorCode );
+ TInt err = KErrNone;
+ TDesC8* msg = NULL;
+
+ TRAP( err, msg = THtiSystemProtocolHelper::ErrorMessageL( aHtiErrorCode,
+ aTargetServiceUid ) );
+
+ if ( err != KErrNone )
+ {
+ UrgentReboot( err, KErrDescrDispatchOutError );
+ }
+
+ err = DispatchOutgoingMessage( msg, KHtiSystemServiceUid,
+ EFalse, EHtiPriorityDefault );
+
+ if ( err == KErrNoMemory )
+ {
+ delete msg;
+ }
+
+ return err;
+ }
+
+TInt CHtiDispatcher::DispatchOutgoingMessage(TDesC8* aMessage,
+ const TUid aTargetServiceUid)
+ {
+ return DispatchOutgoingMessage( aMessage, aTargetServiceUid,
+ EFalse, EHtiPriorityDefault );
+ }
+
+void CHtiDispatcher::AddMemoryObserver( MHtiMemoryObserver* anObserver )
+ {
+ if ( iMemoryObservers->FindInAddressOrder( anObserver ) == KErrNotFound )
+ {
+ iMemoryObservers->InsertInAddressOrder( anObserver );
+ }
+ }
+
+void CHtiDispatcher::RemoveMemoryObserver( MHtiMemoryObserver* anObserver )
+ {
+ TInt removeIndex = iMemoryObservers->FindInAddressOrder( anObserver );
+ if ( removeIndex != KErrNotFound )
+ {
+ iMemoryObservers->Remove( removeIndex );
+ }
+ }
+
+void CHtiDispatcher::DoMemoryNotification()
+ {
+ if ( iMemoryObservers->Count() > 0 )
+ {
+ TInt memory = GetFreeMemory();
+ for ( TInt i = 0; i < iMemoryObservers->Count(); ++i )
+ {
+ ( *iMemoryObservers )[i]->NotifyMemoryChange( memory );
+ }
+ }
+ }
+
+TInt CHtiDispatcher::GetFreeMemory()
+ {
+ return iMaxQueueMemorySize
+ - iIncomingQueue->QueueSize()
+ - iOutgoingQueue->QueueSize();
+ }
+
+void CHtiDispatcher::Start()
+ {
+ if ( !( iIdle->IsActive() || iIdleActive ) )
+ {
+ HTI_LOG_TEXT( "Start CIdle" );
+ iIdleActive = ETrue;
+ iIdle->Start( TCallBack( DispatchCallback, this ) );
+ }
+ }
+
+void CHtiDispatcher::Notify( TInt anError )
+ {
+ HTI_LOG_FORMAT( "CHtiDispatcher::Notify: %d", anError );
+ anError = anError;
+ //start CIdle to check for messages
+ Start();
+ }
+
+TInt CHtiDispatcher::DoDispatch()
+ {
+ HTI_LOG_FUNC_IN( "DoDispatch" );
+
+ TBool isFailed = ETrue;
+
+ //dispatch
+ CHtiMessage* msg = NULL;
+
+ //Process message from the queues
+ if ( !iSender->IsActive() )
+ {
+ msg = iOutgoingQueue->Remove();
+ if ( msg )
+ {
+ //process outgoing
+ iSender->SendMessage( msg );
+ isFailed = EFalse;
+ }
+
+ //after some messages removed do memory notification
+ DoMemoryNotification();
+ }
+
+ iIncomingQueue->StartServiceIteration();
+ TBool msgProcessed = EFalse;
+ while ( ( msg = iIncomingQueue->GetNext() ) != NULL && !msgProcessed )
+ {
+ //processing of incoming HTI message
+ HTI_LOG_TEXT( "incoming msg" );
+
+ //1. find service
+ HTI_LOG_TEXT( "service uid" );
+ TUid cmd = msg->DestinationServiceUid();
+ THtiMessagePriority msgPriority = ( msg->Priority() && KPriorityMask ) ?
+ EHtiPriorityControl:
+ EHtiPriorityData;
+ HTI_LOG_FORMAT( "UID: %d", cmd.iUid );
+
+ //check if it's a system message
+ if ( cmd == KHtiSystemServiceUid )
+ {
+ TPtrC8 body = msg->Body();
+ TRAPD( err, HandleSystemMessageL( body ) );
+ if ( err != KErrNone )
+ {
+ //do nothing
+ HTI_LOG_FORMAT( "Failed handle HTI service, err %d", err );
+ }
+ msgProcessed = ETrue;
+ }
+ else
+ {
+ if ( iSecurityManager->IsContextEstablashed() )
+ {
+ CHTIServicePluginInterface* service = GetService( cmd );
+ if ( service )
+ {
+ //2. call service
+ if ( !service->IsBusy() )
+ {
+ TInt err;
+ if ( msg->IsWrapped() )
+ {
+ TDesC8* unwrapped = NULL;
+ TRAP( err,
+ unwrapped = iSecurityManager->UnwrapL(
+ msg->Body() ) );
+ if ( err == KErrNone && unwrapped )
+ {
+ TRAP( err, service->ProcessMessageL(
+ *unwrapped,
+ msgPriority ) );
+
+ delete unwrapped;
+ }
+ else
+ {
+ HTI_LOG_FORMAT( "ERROR: Unwrap %d", err );
+ DispatchOutgoingErrorMessage( EHtiErrUnwrap,
+ err, cmd );
+ err = KErrNone;
+ }
+ }
+ else
+ {
+ TPtrC8 body = msg->Body();
+ TRAP( err, service->ProcessMessageL( body,
+ msgPriority ) );
+ }
+
+ if ( err != KErrNone )
+ {
+ HTI_LOG_FORMAT( "ERROR: Service Error %d", err );
+ DispatchOutgoingErrorMessage( EHtiErrServiceError,
+ err, cmd );
+ }
+
+ msgProcessed = ETrue;
+ }
+ else
+ {
+ HTI_LOG_TEXT( "service is busy" );
+ }
+ }
+ else
+ {
+ //send error message ServiceNotFound
+ HTI_LOG_TEXT( "ERROR: service not found" );
+ DispatchOutgoingErrorMessage( EHtiErrServiceNotFound, cmd );
+ msgProcessed = ETrue;
+ }
+ }
+ else
+ {
+ //not authorized acces
+ HTI_LOG_TEXT( "ERROR: not authorized acces" );
+ DispatchOutgoingErrorMessage( EHtiErrNotAuthorized, cmd );
+ msgProcessed = ETrue;
+ }
+ }
+ if ( msgProcessed )
+ {
+ //remove msg from dispatcher
+ if ( iIncomingQueue->Remove( msg ) )
+ {
+ delete msg;
+ }
+
+ isFailed = EFalse;
+ }
+ }
+
+ HTI_LOG_FORMAT( "IQ:%d", iIncomingQueue->QueueSize() );
+ HTI_LOG_FORMAT( "OQ:%d", iOutgoingQueue->QueueSize() );
+
+ HTI_LOG_FREE_MEM();
+ HTI_LOG_ALLOC_HEAP_MEM();
+
+ //if queues are empty & listener stopped - stop all
+ if ( iIncomingQueue->IsEmpty() && iOutgoingQueue->IsEmpty() &&
+ !iListener->IsActive() )
+ {
+ CActiveScheduler::Stop();
+ }
+
+ if ( iIncomingQueue->QueueSize() < iQueueSizeLowThresold && iIdleOverCommAdapter )
+ {
+ HTI_LOG_TEXT( "set listener priority high" );
+ iIdle->Deque();
+ CActiveScheduler::Add( iIdle );
+ iIdleOverCommAdapter = EFalse;
+ }
+
+ if ( isFailed )
+ {
+ HTI_LOG_TEXT( "dispatch failed, stop CIdle" );
+ //stop iIdle if there are long outgoing requests
+ iIdleActive = EFalse;
+ }
+ else
+ {
+ iIdleActive = !iIncomingQueue->IsEmpty() || !iOutgoingQueue->IsEmpty();
+ }
+
+ HTI_LOG_FUNC_OUT( "DoDispatch" );
+ return iIdleActive;
+ }
+
+CHTIServicePluginInterface* CHtiDispatcher::GetService(
+ const TUid aServiceUid )
+ {
+ CHTIServicePluginInterface* result = NULL;
+ for ( TInt i = 0; i < iLoadedServices->Count(); ++i )
+ {
+ if ( aServiceUid == (*iLoadedServices)[i].iServiceUid )
+ return (*iLoadedServices)[i].iService;
+ }
+
+ HTI_LOG_FORMAT( "Load service: %d", aServiceUid.iUid );
+
+ TRAPD( err, result = CHTIServicePluginInterface::NewL(
+ MapServicePluginUid( aServiceUid ) ) );
+ if ( err == KErrNone )
+ {
+ //set dispatcher
+ result->SetDispatcher( this );
+ //call InitL()
+ TRAP( err, result->InitL() );
+ if ( err != KErrNone )
+ {
+ HTI_LOG_TEXT( "Failed at InitL()" );
+ delete result;
+ result = NULL;
+ }
+ else
+ {
+ //add service to the array
+ TServiceItem serviceItem;
+ serviceItem.iServiceUid = aServiceUid;
+ serviceItem.iService = result;
+
+ if ( iLoadedServices->Append( serviceItem ) != KErrNone )
+ {
+ HTI_LOG_TEXT( "Failed to load service" );
+ delete result;
+ result = NULL;
+ }
+ }
+ }
+ else
+ {
+ result = NULL;
+ HTI_LOG_FORMAT( "Failed to load service %d", err );
+ }
+
+ return result;
+ }
+
+void CHtiDispatcher::UnloadAllServices()
+ {
+ if ( iLoadedServices )
+ {
+ for ( TInt i=0; i < iLoadedServices->Count(); ++i )
+ {
+ delete (*iLoadedServices)[i].iService;
+ }
+ iLoadedServices->Reset();
+ }
+ if ( iMemoryObservers )
+ {
+ iMemoryObservers->Reset();
+ }
+ }
+
+TInt CHtiDispatcher::DispatchCallback( TAny* aObj )
+ {
+ return ( reinterpret_cast<CHtiDispatcher*>( aObj ) )->DoDispatch();
+ }
+
+void CHtiDispatcher::Reset()
+ {
+ UnloadAllServices();
+ iIncomingQueue->RemoveAll();
+ iOutgoingQueue->RemoveAll();
+ iSecurityManager->ResetSecurityContext();
+
+ iListener->Reset();
+ iSender->Reset();
+
+ iListener->ReceiveMessage();
+ }
+
+void CHtiDispatcher::HandleSystemMessageL( const TDesC8& aMessage )
+ {
+ HTI_LOG_FUNC_IN( "HandleSystemMessage" );
+
+ if ( aMessage.Length() > 0 )
+ {
+ HTI_LOG_FORMAT( "cmd %d", aMessage[0] );
+ if ( aMessage[0] == EHtiAuthentication )
+ {
+ //pass token to security manager
+ TPtrC8 token = aMessage.Mid( 1 );//token start at the second byte
+
+ TDesC8* replyToken = iSecurityManager->SetSecurityContext( token );
+ CleanupStack::PushL( replyToken );
+ //prepare reply message
+ TDesC8* reply = THtiSystemProtocolHelper::AuthMessageL(
+ *replyToken );
+
+ CleanupStack::PushL( reply );
+
+ User::LeaveIfError( DispatchOutgoingMessage(
+ reply,
+ KHtiSystemServiceUid ) );
+
+ CleanupStack::Pop(); //reply
+ CleanupStack::PopAndDestroy(); //replyToken
+ }
+ else if ( iSecurityManager->IsContextEstablashed() )
+ {
+ switch ( aMessage[0] )
+ {
+ case EHtiServiceList:
+ {
+ TDesC8* list = ServicePluginsListL();
+ CleanupStack::PushL( list );
+ User::LeaveIfError( DispatchOutgoingMessage( list,
+ KHtiSystemServiceUid ) );
+ CleanupStack::Pop();
+ }
+ break;
+
+ case EHtiVersion:
+ {
+ HBufC8* msg = HBufC8::NewLC( 2 );
+ msg->Des().Append( KHtiVersionMajor );
+ msg->Des().Append( KHtiVersionMinor );
+ User::LeaveIfError(
+ DispatchOutgoingMessage( msg, KHtiSystemServiceUid ) );
+ CleanupStack::Pop(); // msg
+ }
+ break;
+
+ case EHtiInstanceId:
+ {
+ if ( iHtiInstanceId == 0 )
+ {
+ CreateInstanceId();
+ }
+ HBufC8* msg = HBufC8::NewLC( sizeof( TUint32 ) );
+ msg->Des().Append( ( TUint8* ) ( &iHtiInstanceId ), sizeof( TUint32 ) );
+ User::LeaveIfError(
+ DispatchOutgoingMessage( msg, KHtiSystemServiceUid ) );
+ CleanupStack::Pop(); // msg
+ if ( iConsole )
+ {
+ iConsole->Printf( _L( "Instance ID = %u\n" ), iHtiInstanceId );
+ }
+ }
+ break;
+
+ case EHtiReboot:
+ {
+ if(aMessage.Length() == 2)
+ {
+ iRebootReason = aMessage[1];
+ }
+ else if(aMessage.Length() == 1)
+ {
+ iRebootReason = -1;
+ }
+ else
+ {
+ User::LeaveIfError(DispatchOutgoingErrorMessage( KErrArgument,
+ KErrDescrInvalidParameter,
+ KHtiSystemServiceUid ) );
+ break;
+ }
+ ShutdownAndRebootDeviceL();
+ }
+ break;
+
+ case EHtiStop:
+ {
+ HTI_LOG_TEXT( "STOP" );
+ //stop all requests
+ //cancel just incoming request
+ //after all outgoing messages sent system will go down
+ iListener->Cancel();
+
+ // kill the watchdog, so HTI stays stopped
+ KillHtiWatchDogL();
+ }
+ break;
+
+ case EHtiRestartServices:
+ {
+ HTI_LOG_TEXT("RESTARTSERVISE");
+ if(aMessage.Length() != 1 && aMessage.Length() != 5)
+ {
+ User::LeaveIfError(DispatchOutgoingErrorMessage( KErrArgument,
+ KErrDescrInvalidParameter,
+ KHtiSystemServiceUid ) );
+ break;
+ }
+
+ //stop all requests
+ //cancel just incoming request
+ //after all outgoing messages sent system will go down
+ iListener->Cancel();
+
+ // kill the watchdog, so HTI stays stopped
+ KillHtiWatchDogL();
+
+ TUint milliseconds = 0;
+ if(aMessage.Length() == 5)
+ {
+ milliseconds = aMessage[1] + ( aMessage[2] << 8 )
+ + ( aMessage[3] << 16 )
+ + ( aMessage[4] << 24 );
+ }
+
+ TBuf<20> buf;
+ buf.Format(_L("%d"), milliseconds * 1000);
+
+ RProcess htiProcess;
+ User::LeaveIfError( htiProcess.Create(
+ KHtiRestartExeName, buf ) );
+ htiProcess.Resume();
+ htiProcess.Close();
+ break;
+ }
+ case EHtiReset:
+ {
+ HTI_LOG_TEXT( "RESET" );
+ Reset();
+ }
+ break;
+
+ case EHtiFormat:
+ {
+ HTI_LOG_TEXT( "RESET FACTORY SETTINGS" );
+ if ( aMessage.Length() == 2 )
+ {
+ //set the flag to do rfs
+ iRfsMode = ( TRfsType ) aMessage[1];
+ }
+ if ( iRfsMode != ERfsNormal && iRfsMode != ERfsDeep )
+ {
+ iRfsMode = ERfsUnknown;
+ User::LeaveIfError(
+ DispatchOutgoingErrorMessage( KErrArgument,
+ KErrDescrInvalidParameter,
+ KHtiSystemServiceUid ) );
+ }
+ else
+ {
+ RProcess thisProcess;
+ // ERfsDeep is supported only if HTI running from ROM
+ if ( iRfsMode == ERfsNormal ||
+ IsFileInRom( thisProcess.FileName() ) )
+ {
+ //stop
+ iListener->Cancel();
+ }
+ else
+ {
+ iRfsMode = ERfsUnknown;
+ User::LeaveIfError(
+ DispatchOutgoingErrorMessage( KErrNotSupported,
+ KErrDescrNotInRom,
+ KHtiSystemServiceUid ) );
+ }
+ }
+ }
+ break;
+
+ case EHtiShowConsole:
+ {
+ HTI_LOG_TEXT( "SHOW CONSOLE" );
+ if ( !iConsole )
+ {
+ iConsole = Console::NewL( _L( "HtiFramework" ),
+ TSize( KConsFullScreen,
+ KConsFullScreen ) );
+ iConsole->Printf( _L( "HTI Framework\n" ) );
+ iConsole->Printf( _L( "=============\n\n" ) );
+ }
+
+ HBufC8* msg = HBufC8::NewLC( 1 );
+ msg->Des().Append( 0 );
+ User::LeaveIfError(
+ DispatchOutgoingMessage( msg, KHtiSystemServiceUid ) );
+ CleanupStack::Pop(); // msg
+ }
+ break;
+
+ case EHtiHideConsole:
+ {
+ HTI_LOG_TEXT( "HIDE CONSOLE" );
+ delete iConsole;
+ iConsole = NULL;
+
+ HBufC8* msg = HBufC8::NewLC( 1 );
+ msg->Des().Append( 0 );
+ User::LeaveIfError(
+ DispatchOutgoingMessage( msg, KHtiSystemServiceUid ) );
+ CleanupStack::Pop(); // msg
+ }
+ break;
+
+ case EHtiDebugPrint:
+ {
+ if ( aMessage.Length() > 1 )
+ {
+ RDebug::RawPrint( aMessage.Mid( 1 ) );
+ }
+ HBufC8* msg = HBufC8::NewLC( 1 );
+ msg->Des().Append( 0 );
+ User::LeaveIfError(
+ DispatchOutgoingMessage( msg, KHtiSystemServiceUid ) );
+ CleanupStack::Pop(); // msg
+ }
+ break;
+
+ default:
+ {
+ //unknown command
+ HTI_LOG_TEXT( "Error: Unknown HTI system command:" );
+ DispatchOutgoingErrorMessage( KErrArgument,
+ KHtiSystemCmdErrDescr,
+ KHtiSystemServiceUid );
+ }
+ }
+ }
+ else
+ {
+ HTI_LOG_TEXT( "ERROR: not authorized acces" );
+ DispatchOutgoingErrorMessage( EHtiErrNotAuthorized );
+ }
+ }
+ else
+ {
+ HTI_LOG_TEXT( "Error: empty command" );
+ DispatchOutgoingErrorMessage( KErrArgument,
+ KHtiSystemCmdErrDescr,
+ KHtiSystemServiceUid );
+ }
+ HTI_LOG_FUNC_OUT( "HandleSystemMessage" );
+ }
+
+void CHtiDispatcher::UrgentReboot( TInt aReason, const TDesC8& aReasonDescr )
+ {
+ HTI_LOG_FORMAT( "UrgentReboot: %d", aReason );
+ HTI_LOG_DES( aReasonDescr );
+ aReason = aReason;
+ aReasonDescr.Size();
+ //empty queues
+ delete iIncomingQueue;
+ iIncomingQueue = NULL;
+ delete iOutgoingQueue;
+ iOutgoingQueue = NULL;
+ //stop
+ iListener->Cancel();
+ //reboot
+ Reboot();
+ }
+
+void CHtiDispatcher::Reboot()
+ {
+ if ( iConsole )
+ {
+ iConsole->Printf( _L( "Reboot requested.\n" ) );
+ }
+ TInt err = KErrNone;
+ RProcess rebootProcess;
+ // First try the UI layer rebooter
+ if(iRebootReason == -1)
+ {
+ err = rebootProcess.Create( KHtiDeviceRebootExeUI, KNullDesC );
+ }
+ else
+ {
+ TBuf<8> reasonNumber;
+ reasonNumber.Num(iRebootReason);
+ err = rebootProcess.Create( KHtiDeviceRebootExeUI, reasonNumber );
+ }
+ if ( err != KErrNone )
+ {
+ HTI_LOG_FORMAT( "UI layer rebooter failed with %d", err );
+ // Try if there is OS layer rebooter present
+ err = rebootProcess.Create( KHtiDeviceRebootExeOS, KNullDesC );
+ }
+ if ( err == KErrNone )
+ {
+ rebootProcess.Resume();
+ rebootProcess.Close();
+ }
+ else
+ {
+ HTI_LOG_FORMAT( "Reboot err %d", err );
+ if ( iConsole )
+ {
+ iConsole->Printf( _L( "Reboot error %d.\n" ), err );
+ User::After( 3000000 ); // to let the console display a while
+ }
+ // Can't send any error message here - communications have been stopped
+ }
+ }
+
+void CHtiDispatcher::RestoreFactorySettings()
+ {
+ HTI_LOG_FUNC_IN( "CHtiDispatcher::RestoreFactorySettings" );
+ if ( iConsole )
+ {
+ iConsole->Printf( _L( "RFS requested, type %d.\n" ), iRfsMode );
+ }
+ TInt err = KErrNone;
+ RProcess rebootProcess;
+ if ( iRfsMode == ERfsNormal )
+ {
+ err = rebootProcess.Create( KHtiDeviceRebootExeUI, KParamNormalRfs );
+ }
+ else if ( iRfsMode == ERfsDeep )
+ {
+ err = rebootProcess.Create( KHtiDeviceRebootExeUI, KParamDeepRfs );
+ }
+
+
+ if ( err == KErrNone )
+ {
+ rebootProcess.Resume();
+ rebootProcess.Close();
+ }
+ else
+ {
+ HTI_LOG_FORMAT( "RFS err %d", err );
+ if ( iConsole )
+ {
+ iConsole->Printf( _L( "RFS error %d.\n" ), err );
+ User::After( 3000000 ); // to let the console display a while
+ }
+ // Can't send any error message here - communications have been stopped
+ }
+ HTI_LOG_FUNC_OUT( "CHtiDispatcher::RestoreFactorySettings" );
+ }
+
+TBool CHtiDispatcher::IsFileInRom( const TDesC& aFileName )
+ {
+ HTI_LOG_FUNC_IN( "CHtiDispatcher::IsFileInRom" );
+ HTI_LOG_DES( aFileName );
+ TBool isInRom = EFalse;
+ _LIT( KDriveZ, "z:" );
+ if ( aFileName.FindF( KDriveZ ) == 0 )
+ {
+ isInRom = ETrue;
+ }
+
+ HTI_LOG_FORMAT( "IsFileInRom returning %d", isInRom );
+ HTI_LOG_FUNC_OUT( "CHtiDispatcher::IsFileInRom" );
+ return isInRom;
+ }
+
+void CleanupRArray( TAny* object )
+ {
+ ( ( RImplInfoPtrArray* ) object )->ResetAndDestroy();
+ }
+
+TDesC8* CHtiDispatcher::ServicePluginsListL()
+ {
+ RImplInfoPtrArray aImplInfoArray;
+ CleanupStack::PushL( TCleanupItem( CleanupRArray, &aImplInfoArray ) );
+
+ REComSession::ListImplementationsL(
+ KHTIServiceInterfaceUid,
+ aImplInfoArray );
+
+ //alloc memory for the list
+ TInt maxMemory = aImplInfoArray.Count() * KHtiServiceListRecordLength;
+ HBufC8* list = HBufC8::NewLC( maxMemory );
+
+ for ( TInt i = 0; i < aImplInfoArray.Count(); ++i )
+ {
+ //add uid
+ TUid uid = MapServicePluginUid(
+ aImplInfoArray[i]->ImplementationUid() );
+
+ list->Des().Append( ( TUint8* )( &( uid.iUid ) ), 4 );
+
+ //add display name, converted to 8-bit text
+ TBuf8<KHtiServiceNameLength> serviceName8;
+ serviceName8.Copy(
+ aImplInfoArray[i]->DisplayName().Left( KHtiServiceNameLength ) );
+
+ list->Des().Append( serviceName8 );
+ list->Des().AppendFill( 0,
+ KHtiServiceNameLength - serviceName8.Length() );
+ }
+
+ CleanupStack::Pop();//list
+ CleanupStack::PopAndDestroy();//aImplInfoArray
+
+ return list;
+ }
+
+void CHtiDispatcher::KillHtiWatchDogL()
+ {
+ HTI_LOG_FUNC_IN( "CHtiDispatcher::KillHtiWatchDogL" );
+
+ TFullName processName;
+ TFindProcess finder( KHtiWatchDogMatchPattern );
+ TInt err = finder.Next( processName );
+ if ( err == KErrNone )
+ {
+ HTI_LOG_TEXT( "HTI watchdog process found. Trying to open and kill it..." );
+ RProcess prs;
+ User::LeaveIfError( prs.Open( finder ) );
+ prs.Kill( 1 );
+ prs.Close();
+ HTI_LOG_TEXT( "HTI watchdog killed" );
+ }
+
+ HTI_LOG_FUNC_OUT( "CHtiDispatcher::KillHtiWatchDogL" );
+ }
+
+
+#ifdef __ENABLE_LOGGING__
+void CHtiDispatcher::DebugListPlugins()
+ {
+ HTI_LOG_FUNC_IN( "ListPlugins" );
+ RImplInfoPtrArray aImplInfoArray;
+ HTI_LOG_TEXT( "COMM PLUGINS" );
+ REComSession::ListImplementationsL( KHTICommInterfaceUid, aImplInfoArray );
+ HTI_LOG_FORMAT( "Num of implementations: %d", aImplInfoArray.Count() );
+ TInt i;
+ for ( i = 0; i < aImplInfoArray.Count(); ++i )
+ {
+ HTI_LOG_FORMAT( "uid: %d", aImplInfoArray[i]->ImplementationUid().iUid );
+ HTI_LOG_DES( aImplInfoArray[i]->DataType() );
+ HTI_LOG_DES( aImplInfoArray[i]->DisplayName() );
+ }
+ aImplInfoArray.ResetAndDestroy();
+
+ HTI_LOG_TEXT( "SERVICE PLUGINS" );
+ REComSession::ListImplementationsL( KHTIServiceInterfaceUid, aImplInfoArray );
+ HTI_LOG_FORMAT( "Num of implementations: %d", aImplInfoArray.Count() );
+ for ( i = 0; i < aImplInfoArray.Count(); ++i )
+ {
+ HTI_LOG_FORMAT( "uid: %d", aImplInfoArray[i]->ImplementationUid().iUid );
+ HTI_LOG_DES( aImplInfoArray[i]->DataType() );
+ HTI_LOG_DES( aImplInfoArray[i]->DisplayName() );
+
+ }
+ aImplInfoArray.ResetAndDestroy();
+ HTI_LOG_FUNC_OUT( "ListPlugins" );
+ }
+#endif
+
+void CHtiDispatcher::ShutdownAndRebootDeviceL()
+ {
+ HTI_LOG_TEXT( "REBOOT" );
+ //stop
+ iListener->Cancel();
+ //and set flag to reboot
+ iToReboot = ETrue;
+ }
+
+void CHtiDispatcher::CreateInstanceId()
+ {
+ iHtiInstanceId = User::FastCounter();
+ HTI_LOG_FORMAT( "Generated instance ID %u", iHtiInstanceId );
+ }
+
+TUid CHtiDispatcher::MapServicePluginUid( const TUid aUid )
+ {
+ TUid mappedUid = TUid::Uid( aUid.iUid );
+ switch ( aUid.iUid )
+ {
+ case 0x10210CCD:
+ mappedUid.iUid = 0x200212C4;
+ break;
+ case 0x10210CCF:
+ mappedUid.iUid = 0x200212C6;
+ break;
+ case 0x10210CD1:
+ mappedUid.iUid = 0x200212C8;
+ break;
+ case 0x10210CD3:
+ mappedUid.iUid = 0x200212CA;
+ break;
+ case 0x200212C4:
+ mappedUid.iUid = 0x10210CCD;
+ break;
+ case 0x200212C6:
+ mappedUid.iUid = 0x10210CCF;
+ break;
+ case 0x200212C8:
+ mappedUid.iUid = 0x10210CD1;
+ break;
+ case 0x200212CA:
+ mappedUid.iUid = 0x10210CD3;
+ break;
+ default:
+ break;
+ }
+ return mappedUid;
+ }
+
+TBool CHtiDispatcher::CommReconnect()
+ {
+ if(iReconnectDelay == 0)
+ {
+ return EFalse;
+ }
+
+ //Delay
+ HTI_LOG_FORMAT( "Reconnect deley : %d seconds", iReconnectDelay);
+ User::After(iReconnectDelay * 1000 * 1000);
+
+ //Reconnect
+ iIncomingQueue->RemoveAll();
+ iOutgoingQueue->RemoveAll();
+
+ iListener->Reset();
+ iSender->Reset();
+ iListener->ReceiveMessage();
+
+ return ETrue;
+ }