diff -r 7fdc9a71d314 -r 8ad140f3dd41 hti/HtiFramework/src/HtiDispatcher.cpp --- /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 + +//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( KServiceArrayGranularity ); + + iMemoryObservers = new (ELeave) + RPointerArray( 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( 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 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; + }