idlefw/hslaunch/src/hslaunch.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 15 Sep 2010 12:32:36 +0300
branchRCL_3
changeset 122 6cadd6867c17
parent 114 a5a39a295112
child 130 67f2ed48ad91
permissions -rw-r--r--
Revision: 201035 Kit: 201036

/*
 * Copyright (c) 2008 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: application class.                 
 *
 */

#include <e32property.h>
#include <e32debug.h>
#include "hslaunch.h"

// ========================= DECLARATIONS ==================================
_LIT( KHsExeName, "homescreen.exe" );
const TInt KSleepOnRetry = 250000; // 250ms
const TUid KPSCategoryUid = TUid::Uid( 0x200286E3 );
const TInt KPSCrashCountKey = 1;
_LIT_SECURITY_POLICY_C1( KPSReadPolicy, ECapabilityReadDeviceData );
_LIT_SECURITY_POLICY_C1( KPSWritePolicy, ECapabilityWriteDeviceData );

// ========================= LOCAL FUNCTIONS ==================================

void RunAppL()
    {
    // Construct active scheduler.
    CActiveScheduler* activeScheduler = new ( ELeave )CActiveScheduler();
    CleanupStack::PushL( activeScheduler );
    CActiveScheduler::Install( activeScheduler );        
    
    // Construct app.
    CHsLaunch* app = CHsLaunch::NewL();
    CleanupStack::PushL( app );        
    
    app->Activate();
    
    // Signal startup.
    RProcess::Rendezvous(KErrNone);
    
    // Start active scheduler.
    CActiveScheduler::Start();
    
    User::LeaveIfError( app->ApplicationReturnValue() );
    
    // Cleanup.
    CleanupStack::PopAndDestroy( app );
    CleanupStack::PopAndDestroy( activeScheduler );
    }

// -----------------------------------------------------------------------------
// E32Main
// entry-point
// -----------------------------------------------------------------------------
//
TInt E32Main()
    {            
    TInt error = KErrNone;
    
    __UHEAP_MARK;    
    
    // Construct cleanup stack.
    CTrapCleanup* cleanupstack = CTrapCleanup::New();
    if( !cleanupstack )
        {
        error  = KErrNoMemory;
        }
    
    // Call next phase of startup.
    if( !error )
        {
        TRAP( error, RunAppL() );
        }
    
    // Cleanup.
    delete cleanupstack;
    cleanupstack = NULL;
    
    __UHEAP_MARKEND;
    
    return error;
    }

// ========================= MEMBER FUNCTIONS ==================================

// -----------------------------------------------------------------------------
// CHsLaunch::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
CHsLaunch* CHsLaunch::NewL()
    {
    CHsLaunch* self = new ( ELeave ) CHsLaunch();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CHsLaunch::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CHsLaunch::ConstructL()
    {
    iShutdownMonitor = CHsShutdownMonitor::NewL( *this );
    iShutdownMonitor->StartMonitor();
    
    // Create property to pub/sub.    
    TInt error = RProperty::Define( KPSCrashCountKey,
                                    RProperty::EInt,
                                    KPSReadPolicy,
                                    KPSWritePolicy );    
    if( error == KErrNone )
        {
        // Init it to zero.
        error = RProperty::Set( KPSCategoryUid, KPSCrashCountKey, 0 );
        }                
    else if( error == KErrAlreadyExists )
        {
        error = KErrNone;        
        }        
    
    User::LeaveIfError( error );
    }

// -----------------------------------------------------------------------------
// CHsLaunch::CHsLaunch()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
CHsLaunch::CHsLaunch() :
        CActive( EPriorityStandard ),
        iApplicationReturnValue( KErrNone )
    {
    CActiveScheduler::Add( this );
    }

// -----------------------------------------------------------------------------
// CHsLaunch::~CHsLaunch()
// Destructor.
// -----------------------------------------------------------------------------
//
CHsLaunch::~CHsLaunch()
    {
    Cancel();
    
    delete iProcessMonitor;
    iProcessMonitor = NULL;
    
    delete iShutdownMonitor;
    iShutdownMonitor = NULL;
    }

// -----------------------------------------------------------------------------
// CHsLaunch::Activate()
// Set active object to be ran
// -----------------------------------------------------------------------------
//
void CHsLaunch::Activate()
    {   
    SetActive();
    TRequestStatus* tmp = &iStatus;
    User::RequestComplete( tmp, KErrNone );
    }

// -----------------------------------------------------------------------------
// CHsLaunch::ApplicationReturnValue()
// Get application return value
// -----------------------------------------------------------------------------
//
TInt CHsLaunch::ApplicationReturnValue()
    {
    return iApplicationReturnValue;
    }

// -----------------------------------------------------------------------------
// CHsLaunch::RunL
// -----------------------------------------------------------------------------
//
void CHsLaunch::RunL()
    {        
    // Create process
    RProcess process;
    TInt processError = KErrNone;    
    processError = process.Create( KHsExeName, KNullDesC );
    
    TInt monitorError = KErrNone;
    if( processError == KErrNone )
        {
        TRAP( monitorError, InitProcessMonitorL( process.Id() ) );
        }
    
    if( processError == KErrNone )
        {
        // Make sure process is started even if monitor startup
        // fails. This will assure that process is not left in
        // suspended state. Resume can not be called for
        // already running process (will cause KERN-EXEC 46).
        process.Resume();
        }
                     
    process.Close();
    
    if( processError != KErrNone ||
        monitorError != KErrNone )
        {
        /* Error in this method is critical and it might cause
         * endless active scheduler loop if no active objects are
         * not triggered. Therefore shutdown. This application
         * will be restarted by startup sw. */
        ShutdownApp( KErrGeneral );
        }
    }

// -----------------------------------------------------------------------------
// CHsLaunch::DoCancel()
// From CActive.
// -----------------------------------------------------------------------------
//
void CHsLaunch::DoCancel()
    {
    if( iProcessMonitor )
        {
        iProcessMonitor->Cancel();
        }
    
    if( iShutdownMonitor )
        {
        iShutdownMonitor->Cancel();
        }
    }      

// -----------------------------------------------------------------------------
// CHsLaunch::RunError()
// From CActive.
// -----------------------------------------------------------------------------
//
TInt CHsLaunch::RunError( TInt aError )
    {
    return aError;
    } 

// -----------------------------------------------------------------------------
// CHsLaunch::ProcessEndedL()
// From MHsProcessMonitorObserver
// -----------------------------------------------------------------------------
//
void CHsLaunch::ProcessEnded( const TExitType& aExitType,
                              const TInt aExitReason,
                              const TExitCategoryName& /*aExitCategory*/ )
    {    
    TInt crashCount = 0;
    TInt error = RProperty::Get( KPSCategoryUid,
                                 KPSCrashCountKey,
                                 crashCount );
    
    // increment crash count in cenrep if the process has panic'd or killed with
    // an error code
    if( aExitType == EExitPanic ||
        ( aExitType == EExitKill && aExitReason != KErrNone ) )
        {
        if( error == KErrNone )
            {
            crashCount++;
            error = RProperty::Set( KPSCategoryUid,
                                    KPSCrashCountKey,
                                    crashCount );                          
            }
        
        if( error == KErrNone )
            {      
            User::After( KSleepOnRetry ); 
            Activate();
            }
        else
            {           
            ShutdownApp( error );
            }
        }
    }

// -----------------------------------------------------------------------------
// CHsLaunch::ProcessMonitoringErrorL()
// From MHsProcessMonitorObserver
// -----------------------------------------------------------------------------
//
void CHsLaunch::ProcessMonitoringError( TInt aError )
    {
    /* Error in this method is critical and it might cause
     * endless active scheduler loop if no active objects are
     * not triggered. Therefore shutdown. This application
     * will be restarted by startup sw. */
    ShutdownApp( aError );
    }

// -----------------------------------------------------------------------------
// CHsLaunch::SystemShutdownEvent()
// From MHsShutdownMonitorObserver
// -----------------------------------------------------------------------------
//
void CHsLaunch::SystemShutdownEvent()
    {
    // Do not shut down app. Startup app would try to restart this app.
    // Just deactivate all active objects and wait for power off.
    if( IsActive() )
        {
        Cancel();
        }
    else
        {
        DoCancel();
        }    
    }

// -----------------------------------------------------------------------------
// CHsLaunch::InitProcessMonitorL()
// Initialize process monitor
// -----------------------------------------------------------------------------
//
void CHsLaunch::InitProcessMonitorL( const TInt aProcessId )
    {
    if( iProcessMonitor )
        {
        delete iProcessMonitor;
        iProcessMonitor = NULL;
        }
    iProcessMonitor = CHsProcessMonitor::NewL( aProcessId, *this );    
    User::LeaveIfError( iProcessMonitor->StartMonitor() );
    }

// -----------------------------------------------------------------------------
// CHsLaunch::ShutdownApp()
// Shut down application
// -----------------------------------------------------------------------------
//
void CHsLaunch::ShutdownApp( const TInt aApplicationReturnValue )
    {
    if( IsActive() )
        {
        Cancel();
        }
    else
        {
        DoCancel();
        }
    
    iApplicationReturnValue = aApplicationReturnValue;    
    CActiveScheduler::Stop();
    }

// End of File