// Copyright (c) 2005-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:
// cwatcherssastartupmgr.cpp
//
#include "cwatcherssastartupmgr.h"
#include <ecom/ecom.h>
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include "cwatcher.h"
#endif
static void CleanUpEComInfoArray(TAny* aInfoArray);
/**
Factory function to create a new instance of the CWatcherSSAStartupMgr
SSA start-up manager.
The SSA start-up manager registers with the Domain Manager for the
domain KAppServicesDomain3 of the KDmHierarchyIdStartup.
@return
A new CWatcherSSAStartupMgr object.
*/
CWatcherSSAStartupMgr* CWatcherSSAStartupMgr::NewL()
{
#ifndef SYMBIAN_SYSTEM_STATE_MANAGEMENT
CWatcherSSAStartupMgr* self = new (ELeave) CWatcherSSAStartupMgr(KDmHierarchyIdStartup, KAppServicesDomain3);
#else
CWatcherSSAStartupMgr* self = new (ELeave) CWatcherSSAStartupMgr(KDmHierarchyIdStartup, KSM2AppServicesDomain3);
#endif
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
/**
Constructor of CWatcherSSAStartupMgr
@param aHierarchyId
The Id of the domain hierarchy to connect to
@param aDomainId
The Id of the domain to connect to
*/
CWatcherSSAStartupMgr::CWatcherSSAStartupMgr(TDmHierarchyId aHierarchyId, TDmDomainId aDomainId)
: CDmDomain(aHierarchyId,aDomainId), iCurrentStartupState(EStartupStateUndefined)
{
}
/**
Destructor
*/
CWatcherSSAStartupMgr::~CWatcherSSAStartupMgr()
{
Cancel();
iWatcherList.ResetAndDestroy();
delete iLog,
iFs.Close();
REComSession::FinalClose();
}
/**
Second-stage constructor.
This method indicates how the CWatcherSSAStartupMgr interacts with the
Domain manager to keep aware of the startup state change.
*/
void CWatcherSSAStartupMgr::ConstructL()
{
// Get ready to log in \logs\watcher\watcher.txt
User::LeaveIfError(iFs.Connect());
iLog = CWatcherLog::NewL(iFs);
// Connect to the Domain Manager
TRAPD( err, CDmDomain::ConstructL() );
if( err != KErrNone )
{
// The connection to the Domain Manager cannot be established,
// we perform a full initialisation
iLog->Printf(_L("CWatcherSSAStartupMgr::InitialiseL(): cannot connect to the Domain Manager, performing full init."));
PerformFullInitL();
iCurrentStartupState = EStartupStateNonCritical;
return;
}
// Get the start-up state from the Domain Manager.
TDmDomainState state = GetState();
// Either something wrong with the Domain Manager or final state is reached
if( state <= EStartupStateUndefined || state >= EStartupStateNonCritical )
{
// We perform a full initialisation
iLog->Printf(_L("CWatcherSSAStartupMgr::InitialiseL(): wrong state, performing full init."));
PerformFullInitL();
iCurrentStartupState = EStartupStateNonCritical;
return;
}
// Perform the initialisation for this state
TBool notFinished = ProcessSSAEventL((TStartupStateIdentifier)state);
if( notFinished )
{
// Still need to get the state from Domain Manager.
RequestTransitionNotification();
}
}
/**
Executed when the startup state change is done, it does the same thing
as the method InitialiseL().
*/
void CWatcherSSAStartupMgr::RunL()
{
// Leave if our previous request to be notified a state change has
// returned an error and let RunError handle this.
User::LeaveIfError(iStatus.Int());
// Get the start-up state from the Domain Manager.
TDmDomainState state = GetState();
//If the state is EStartupStateUndefined there must be something wrong.
if( state == EStartupStateUndefined )
{
AcknowledgeLastState(KErrBadHandle);
User::Leave(KErrBadHandle); //RunError will handle this.
}
// Perform the initialisation for this state
TBool notFinished = ProcessSSAEventL((TStartupStateIdentifier)state);
// Tell domain manager that we have processed the last state change
AcknowledgeLastState(KErrNone);
if( notFinished )
{
RequestTransitionNotification();
}
}
/**
Handle the error if RunL leaves. Here, we just do a full initialisation.
@param aError
Error code generated by the RunL(), not used here.
@return
KErrNone to avoid CActiveScheduler to panic.
*/
TInt CWatcherSSAStartupMgr::RunError(TInt /*aError*/)
{
iLog->Printf(_L("CWatcherSSAStartupMgr::RunL() leaves, do a full initialisation"));
TRAP_IGNORE(DoRunErrorL());
return KErrNone;
}
/**
Leaving method trapped by RunError
If RunError has been called that means RunL has left.
Because watcher.exe is started in the critical-dynamic state it is quite
likely the critical init has been done already (in ConstructL) when RunL
is called so we just want to do the non-critical part of the init.
We check our internal state for confirmation and run the non-critical init.
If our internal state is EStartupStateCriticalDynamic or before we
perform a full init.
*/
void CWatcherSSAStartupMgr::DoRunErrorL()
{
if ( iCurrentStartupState > EStartupStateCriticalDynamic )
{
PerformNonCriticalInitL();
}
else
{
PerformFullInitL();
}
}
/**
Perform the initialisation for a particular state.
@param aKnownState
The startup state passed into the MStartupStateObserver objects
@return
Whether or not a transition notification should be requested
*/
TBool CWatcherSSAStartupMgr::ProcessSSAEventL(TStartupStateIdentifier aKnownState)
{
TBool notFinished = ETrue;
if ( aKnownState != iCurrentStartupState )
{
//if we have not performed critical dynamic initialisation and receive a
//notification for it or a state that comes after
if(iCurrentStartupState<EStartupStateCriticalDynamic &&
aKnownState >= EStartupStateCriticalDynamic)
{
PerformCriticalInitL();
iCurrentStartupState = EStartupStateCriticalDynamic;
}
//if we have not performed non-critical initialisation and receive a notification
//for it or a state that comes after
if(iCurrentStartupState<EStartupStateNonCritical &&
aKnownState >= EStartupStateNonCritical)
{
PerformNonCriticalInitL();
notFinished = EFalse;
iCurrentStartupState = EStartupStateNonCritical;
}
}
return notFinished;
}
/**
Perform a full initialisation = start all the watchers
*/
void CWatcherSSAStartupMgr::PerformFullInitL()
{
// Watchers for the critical-dynamic state:
PerformCriticalInitL();
// Watchers for the non-critical state:
PerformNonCriticalInitL();
}
/**
Perform initialisation for the 'critical-dynamic' start-up state
*/
void CWatcherSSAStartupMgr::PerformCriticalInitL()
{
StartWatchersL(KUidEComWatcher); // Legacy watchers
StartWatchersL(KUidMsgCriticalWatchers);
}
/**
Perform initialisation for the 'non-critical' start-up state
*/
void CWatcherSSAStartupMgr::PerformNonCriticalInitL()
{
StartWatchersL(KUidMsgNonCriticalWatchers);
}
/**
Starts all the watchers implementing the specified ECom interface
@param aEComInterface
The ECom interface of the watchers to be started
*/
void CWatcherSSAStartupMgr::StartWatchersL(TUid aEComInterface)
{
RImplInfoPtrArray watcherInfoArray;
TCleanupItem cleanup(CleanUpEComInfoArray, &watcherInfoArray);
CleanupStack::PushL(cleanup);
TEComResolverParams eComResolverParams;
// Get the list of active watcher implementations.
// (list only watcher implementations that are ROM, as it would be
// insecure to load RAM implementations)
REComSession::ListImplementationsL( aEComInterface, eComResolverParams,
KRomOnlyResolverUid, watcherInfoArray);
const TInt count = watcherInfoArray.Count();
#ifdef __WINS__
_LIT(KLaunchingWatcher, "Launching ECOM watcher %S");
#endif
for( TInt ii=0; ii < count; ++ii )
{
CImplementationInformation* info = watcherInfoArray[ii];
// Log details of the watcher
const TDesC& name = info->DisplayName();
#ifdef __WINS__
iLog->Printf(KLaunchingWatcher, &name);
#endif
// Create the watcher launcher
CWatcherLauncher* launcher = CWatcherLauncher::NewL(name,
info->ImplementationUid(),
iFs,
*iLog);
CleanupStack::PushL(launcher);
iWatcherList.AppendL(launcher);
CleanupStack::Pop(launcher);
}
CleanupStack::PopAndDestroy(&watcherInfoArray);
}
// CleanupEComArray function is used for cleanup support
// of locally declared arrays.
void CleanUpEComInfoArray(TAny* aInfoArray)
{
RImplInfoPtrArray* infoArray = (static_cast<RImplInfoPtrArray*>(aInfoArray));
infoArray->ResetAndDestroy();
infoArray->Close();
}