hti/HtiFramework/src/HtiFramework.cpp
changeset 0 a03f92240627
child 9 8a14024f954a
child 13 33016869e0dd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hti/HtiFramework/src/HtiFramework.cpp	Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,556 @@
+/*
+* 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
+*               CHtiFramework class.
+*
+*/
+
+
+// INCLUDE FILES
+#include "HtiFramework.h"
+#include "HtiLogging.h"
+#include <badesca.h>
+#include <e32std.h>
+#include <f32file.h>
+#include <HtiCfg.h>
+#include <HtiStartupWaitInterface.h>
+
+// CONSTANTS
+_LIT( KHtiFrameworkMatchPattern, "HtiFramework*" );
+_LIT( KHtiMainThreadName,        "HtiMain" );
+_LIT( KHtiWatchDogExeName,       "HtiWatchDog.exe" );
+_LIT( KHtiWatchDogMatchPattern,  "HtiWatchDog*" );
+_LIT( KHtiAdminStartParameter,   "admin" );
+_LIT( KEComServerMatchPattern,   "EComServer*" );
+_LIT( KHtiStartupWaitDllName,    "HtiStartupWait.dll" );
+
+// config file parameters
+_LIT( KCfgFilePath,         "\\");
+_LIT( KHtiCfgFileName,      "hti.cfg" );
+_LIT8( KCommPlugin,         "CommPlugin" );
+_LIT8( KMaxMsgSize,         "MaxMsgSize" );
+_LIT8( KMaxQueueSize,       "MaxQueueSize" );
+_LIT8( KMaxHeapSize,        "MaxHeapSize" );
+_LIT8( KPriority,           "Priority" );
+_LIT8( KShowConsole,        "ShowConsole" );
+_LIT8( KMaxWaitTime,        "MaxWaitTime" );
+_LIT8( KStartUpDelay,       "StartUpDelay" );
+_LIT8( KEnableHtiWatchDog,  "EnableHtiWatchDog" );
+_LIT8( KEnableHtiAutoStart, "EnableHtiAutoStart" );
+_LIT8( KShowErrorDialogs,   "ShowErrorDialogs" );
+
+const static TInt KDefaultMaxWaitTime  = 90; // seconds
+const static TInt KDefaultStartUpDelay = 5;  // seconds
+const static TInt KHtiDefaultPriority = 3;
+const static TInt KHtiWatchDogEnabledDefault = 0;
+const static TInt KHtiConsoleEnabledDefault = 0;
+const static TInt KHtiAutoStartEnabledDefault = 0;
+const static TInt KHtiShowErrorDialogsDefault = 1;
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::CHtiFramework
+// Constructor
+// -----------------------------------------------------------------------------
+CHtiFramework::CHtiFramework():
+    iCfg( NULL ),
+    iDispatcher( NULL ),
+    iOriginalHeap( NULL )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::ConstructL
+// Second phase constructor
+// -----------------------------------------------------------------------------
+void CHtiFramework::ConstructL()
+    {
+    HTI_LOG_FUNC_IN("CHtiFramework::ConstructL");
+
+    if ( IsHtiRunning() )
+        {
+        HTI_LOG_TEXT( "HTI already running - not starting second instance" );
+        User::Leave( KErrAlreadyExists );
+        }
+
+    TInt priority = KHtiDefaultPriority;
+    TInt enableHtiWatchDog = KHtiWatchDogEnabledDefault;
+    TInt showConsole = KHtiConsoleEnabledDefault;
+    TInt enableHtiAutoStart = KHtiAutoStartEnabledDefault;
+    TInt showErrorDialogs = KHtiShowErrorDialogsDefault;
+
+    TRAPD( err, iCfg = CHtiCfg::NewL() );
+    if ( err == KErrNone )
+        {
+        HTI_LOG_TEXT( "CHtiCfg constructed" );
+        TRAP( err, iCfg->LoadCfgL( KCfgFilePath, KHtiCfgFileName ) );
+        if ( err == KErrNone )
+            {
+            HTI_LOG_TEXT( "Cfg file loaded" );
+
+            TBuf8<64> commPlugin( KNullDesC8 );
+            TRAPD( paramErr, commPlugin = iCfg->GetParameterL( KCommPlugin ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KCommPlugin );
+                }
+
+            TInt maxMsgSize = 0;
+            TRAP( paramErr, maxMsgSize = iCfg->GetParameterIntL( KMaxMsgSize ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KMaxMsgSize );
+                }
+
+            TInt maxQueueSize = 0;
+            TRAP( paramErr, maxQueueSize = iCfg->GetParameterIntL( KMaxQueueSize ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KMaxQueueSize );
+                }
+
+            TInt maxHeapSize = 0;
+            TRAP( paramErr, maxHeapSize = iCfg->GetParameterIntL( KMaxHeapSize ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KMaxHeapSize );
+                }
+            else
+                {
+                //create new heap and switch heaps
+                RHeap* newHeap = UserHeap::ChunkHeap( NULL, //local
+                                                      KMinHeapSize, //min size
+                                                      maxHeapSize //max size
+                                                     );
+                if ( newHeap )
+                    {
+                    HTI_LOG_TEXT( "SwitchHeap" );
+                    iOriginalHeap = User::SwitchHeap( newHeap );
+                    HTI_LOG_ALLOC_HEAP_MEM();
+                    }
+                else
+                    {
+                    HTI_LOG_TEXT( "Failed create new heap" );
+                    User::Leave( KErrNoMemory );
+                    }
+                }
+
+            TRAP( paramErr, priority = iCfg->GetParameterIntL( KPriority ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KPriority );
+                }
+
+            TRAP( paramErr, showConsole = iCfg->GetParameterIntL( KShowConsole ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KShowConsole );
+                }
+
+            TInt maxWaitTime = KDefaultMaxWaitTime;
+            TRAP( paramErr, maxWaitTime = iCfg->GetParameterIntL( KMaxWaitTime ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KMaxWaitTime );
+                }
+
+            TInt startUpDelay = KDefaultStartUpDelay;
+            TRAP( paramErr, startUpDelay = iCfg->GetParameterIntL( KStartUpDelay ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KStartUpDelay );
+                }
+
+            TRAP( paramErr, enableHtiWatchDog = iCfg->GetParameterIntL( KEnableHtiWatchDog ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KEnableHtiWatchDog );
+                }
+
+            TRAP( paramErr, enableHtiAutoStart = iCfg->GetParameterIntL( KEnableHtiAutoStart ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KEnableHtiAutoStart );
+                }
+
+            TRAP( paramErr, showErrorDialogs = iCfg->GetParameterIntL( KShowErrorDialogs ) );
+            if ( paramErr != KErrNone )
+                {
+                HTI_LOG_TEXT( "The following parameter not defined in cfg, using default value:" );
+                HTI_LOG_DES( KShowErrorDialogs );
+                }
+
+            if ( !IsStartAcceptedL( enableHtiAutoStart ) )
+                {
+                User::Leave( KErrAbort );
+                }
+
+            WaitNormalState( maxWaitTime, startUpDelay );
+            iDispatcher = CHtiDispatcher::NewL( commPlugin, maxMsgSize,
+                    maxQueueSize, showConsole != 0, showErrorDialogs != 0 );
+            }
+        }
+
+
+    // cfg file was not found or it could not be opened
+    if ( err )
+        {
+        HTI_LOG_TEXT( "Error loading cfg file, use default values" );
+
+        if ( !IsStartAcceptedL( enableHtiAutoStart ) )
+            {
+            User::Leave( KErrAbort );
+            }
+
+        WaitNormalState( KDefaultMaxWaitTime, KDefaultStartUpDelay );
+
+        //create with default values
+        iDispatcher = CHtiDispatcher::NewL(
+            KNullDesC8, 0, 0, showConsole != 0, showErrorDialogs != 0 );
+        }
+
+    HTI_LOG_FORMAT( "Priority setting = %d", priority );
+    // Set HTI priority
+    switch ( priority )
+        {
+        case 1:
+            RProcess().SetPriority( EPriorityBackground ); // 250
+            break;
+        case 2:
+            RProcess().SetPriority( EPriorityForeground ); // 350
+            break;
+        // case 3: goes to default
+        case 4:
+            RThread().SetPriority( EPriorityAbsoluteHigh ); // 500
+            break;
+        default:
+            RProcess().SetPriority( EPriorityHigh );        // 450
+            break;
+        }
+
+    // start hti watchdog, if it is enabled in config file
+    if ( enableHtiWatchDog != 0 ) StartHtiWatchDogL();
+
+    HTI_LOG_FORMAT( "Process priority %d", RProcess().Priority() );
+    HTI_LOG_FORMAT( "Thread priority %d", RThread().Priority() );
+    HTI_LOG_FUNC_OUT("CHtiFramework::ConstructL");
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::~CHtiFramework
+// Destructor.
+// -----------------------------------------------------------------------------
+CHtiFramework::~CHtiFramework()
+    {
+    HTI_LOG_FUNC_IN("~CHTIServer");
+    delete iDispatcher;
+
+    HTI_LOG_ALLOC_HEAP_MEM();
+    //switch before deleting iCfg
+    //'cause iCfg was allocated in the original heap
+    if ( iOriginalHeap )
+        {
+        User::SwitchHeap( iOriginalHeap );
+        }
+
+    delete iCfg;
+    HTI_LOG_FUNC_OUT("~CHTIServer");
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+CHtiFramework* CHtiFramework::NewL()
+    {
+    CHtiFramework* obj = new ( ELeave ) CHtiFramework;
+    CleanupStack::PushL( obj );
+    obj->ConstructL();
+    CleanupStack::Pop();
+    return obj;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::StartL
+// The method that gets the show going.
+// -----------------------------------------------------------------------------
+TInt CHtiFramework::StartL()
+    {
+    HTI_LOG_FUNC_IN( "CHtiFramework::StartL" );
+
+    CConsoleBase* console = iDispatcher->GetConsole();
+    if ( console )
+        {
+        console->Printf( _L( "HTI up and running.\n" ) );
+        }
+
+    // start scheduler
+    CActiveScheduler::Start();
+
+    HTI_LOG_FUNC_OUT( "CHtiFramework::StartL" );
+    return KErrNone;
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::StartHtiWatchDogL
+// Launches the HTI Watchdog process if necessary.
+// -----------------------------------------------------------------------------
+void CHtiFramework::StartHtiWatchDogL()
+    {
+    HTI_LOG_FUNC_IN( "CHtiFramework::StartHtiWatchDogL" );
+
+    TFullName processName;
+    TFindProcess finder( KHtiWatchDogMatchPattern );
+    TInt err = finder.Next( processName );
+    if ( err == KErrNone )
+        {
+        // ok, already running
+        HTI_LOG_TEXT( "HtiWatchDog already running" );
+        }
+    else
+        {
+        // start watchdog
+        HTI_LOG_TEXT( "Starting HtiWatchDog..." );
+        RProcess watchDogProcess;
+        err = watchDogProcess.Create( KHtiWatchDogExeName, KNullDesC );
+        if ( err == KErrNone )
+            {
+            watchDogProcess.Resume();
+            watchDogProcess.Close();
+            HTI_LOG_TEXT( "HtiWatchDog up and running" );
+            }
+        else
+            {
+            HTI_LOG_FORMAT( "Could not start HtiWatchDog, err: %d", err );
+            User::Leave( err );
+            }
+        }
+    HTI_LOG_FUNC_OUT( "CHtiFramework::StartHtiWatchDogL" );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::WaitNormalState
+// Delays HTI startup until device reaches normal state.
+// -----------------------------------------------------------------------------
+void CHtiFramework::WaitNormalState( TInt aMaxWaitTime, TInt aStartUpDelay )
+    {
+    HTI_LOG_FUNC_IN("CHtiFramework::WaitNormalState");
+    // First make sure that EComServer is running before continuing
+    TFullName processName;
+    TFindProcess finder( KEComServerMatchPattern );
+    while ( finder.Next( processName ) != KErrNone )
+        {
+        HTI_LOG_TEXT( "HTI waiting for EComServer startup" );
+        finder.Find( KEComServerMatchPattern );
+        User::After( 1000000 ); // wait 1 second
+        }
+    HTI_LOG_TEXT( "EComServer process found - HTI startup continuing" );
+
+    if ( aMaxWaitTime > 0 )
+        {
+        TInt err = KErrNone;
+        RFs fs;
+        err = fs.Connect();
+        if ( err == KErrNone )
+            {
+            RLibrary library;
+            err = library.Load( KHtiStartupWaitDllName );
+            HTI_LOG_FORMAT( "StartupWait library load returned %d", err );
+            if ( err == KErrNone &&
+                 library.Type()[1] == KHtiStartupWaitInterfaceUid )
+                {
+                HTI_LOG_TEXT( "StartupWait DLL found" );
+                TLibraryFunction entry = library.Lookup( 1 );
+                if ( entry != NULL )
+                    {
+                    MHtiStartupWaitInterface* startupWait =
+                        ( MHtiStartupWaitInterface* ) entry();
+                    err = startupWait->WaitForStartup( aMaxWaitTime );
+                    HTI_LOG_FORMAT( "StartupWait returned %d", err );
+                    delete startupWait;
+                    startupWait = NULL;
+                    }
+                }
+            library.Close();
+            }
+        }
+
+    HTI_LOG_FORMAT( "HTI Starting after %d seconds", aStartUpDelay );
+    User::After( aStartUpDelay * 1000 * 1000 );
+
+    HTI_LOG_FUNC_OUT( "CHtiFramework::WaitNormalState" );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::IsHtiRunning
+// Checks whether HTI Framework process is already running.
+// -----------------------------------------------------------------------------
+TBool CHtiFramework::IsHtiRunning()
+    {
+    HTI_LOG_FUNC_IN( "CHtiFramework::IsHtiRunning" );
+    TInt htiInstanceCount = 0;
+    TBool isRunning = EFalse;
+    TFullName processName;
+    TFindProcess finder( KHtiFrameworkMatchPattern );
+    TInt err = finder.Next( processName );
+    while ( err == KErrNone && processName.Length() > 0 )
+        {
+        HTI_LOG_FORMAT( "Found process %S", &processName );
+        RProcess process;
+        err = process.Open( finder );
+        if ( err == KErrNone )
+            {
+            if ( process.ExitType() == EExitPending )
+                {
+                HTI_LOG_TEXT( "Process is running" );
+                htiInstanceCount++;
+                }
+            process.Close();
+            }
+        err = finder.Next( processName );
+        }
+    if ( htiInstanceCount > 1 )
+        {
+        isRunning = ETrue;
+        }
+    HTI_LOG_FUNC_OUT( "CHtiFramework::IsHtiRunning" );
+    return isRunning;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHtiFramework::IsStartAccepted
+// Checks whether HTI Framework should start or not. If automatic startup is
+// disabled HTI should start only when started by HtiAdmin.
+// -----------------------------------------------------------------------------
+TBool CHtiFramework::IsStartAcceptedL( TBool aIsAutoStartEnabled )
+    {
+    HTI_LOG_FUNC_IN( "CHtiFramework::IsStartAccepted" );
+    TBool isStartAccepted = EFalse;
+
+    if ( aIsAutoStartEnabled )
+        {
+        // If auto start is enabled, no additional checks needed. OK to start.
+        isStartAccepted = ETrue;
+        }
+
+    else
+        {
+        // If we have "admin" parameter given from command line, start is
+        // requested by HtiAdmin or HtiWatchDog and we are OK to start -
+        // otherwise this is an auto start and we deny it.
+        TInt cmdLen = User::CommandLineLength();
+        HBufC* cmdLine = HBufC::NewL( cmdLen );
+        TPtr ptrCmdLine = cmdLine->Des();
+        User::CommandLine( ptrCmdLine );
+        TLex parser( *cmdLine );
+        parser.SkipCharacters();
+        if ( parser.MarkedToken().Compare( KHtiAdminStartParameter ) == 0  )
+            {
+            isStartAccepted = ETrue;
+            }
+        delete cmdLine;
+        cmdLine = NULL;
+        }
+
+    HTI_LOG_FORMAT( "HTI start accepted = %d", isStartAccepted );
+    HTI_LOG_FUNC_OUT( "CHtiFramework::IsStartAccepted" );
+    return isStartAccepted;
+    }
+
+
+// ============================ LOCAL FUNCTIONS ===============================
+
+LOCAL_C TInt StartL()
+    {
+    User::__DbgMarkStart( RHeap::EUser );
+
+    User::RenameThread( KHtiMainThreadName );
+
+    TInt error;
+    CHtiFramework* server = NULL;
+    TRAP( error, server = CHtiFramework::NewL() );
+
+    if ( error == KErrNone )
+        {
+        CleanupStack::PushL( server );
+        TRAP( error, server->StartL() );
+
+        if ( error )
+            {
+            HTI_LOG_FORMAT( "Leave happened in StartL(): %d", error );
+            }
+
+        CleanupStack::PopAndDestroy();
+        }
+    else
+        {
+        HTI_LOG_FORMAT( "Leave when constructing: %d", error );
+        }
+
+    User::__DbgMarkEnd( RHeap::EUser, 0 );
+    HTI_LOG_TEXT( "NO memory leaks: past __UHEAP_MARKEND" );
+    return error;
+    }
+
+
+GLDEF_C TInt E32Main()
+    {
+    __UHEAP_MARK;
+    HTI_LOG_ALLOC_HEAP_MEM();
+
+    _LIT( KHTIServer, "CHtiFramework" );
+    CTrapCleanup* cleanup = CTrapCleanup::New();
+    CActiveScheduler *scheduler = new ( ELeave ) CActiveScheduler;
+    CActiveScheduler::Install( scheduler );
+
+    TRAPD( error, StartL() );
+
+    delete scheduler;
+    delete cleanup;
+    __UHEAP_MARKEND;
+    HTI_LOG_ALLOC_HEAP_MEM();
+
+    __ASSERT_ALWAYS( !error, User::Panic( KHTIServer, error ) );
+    return KErrNone;
+    }