// Copyright (c) 2008-2010 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://#include <ssm/ssmstates.hrh>#include <ssm/ssmstatetransition.h>#include <ssm/ssmstatepolicy.h>#include <ssm/ssmuiproviderdll.h>#include "ssmserverpanic.h"#include "ssmserver.h"#include "ssmsession.h"#include "ssmclisrv.h"#include "clesessionproxy.h"#include "ssmstatepolicyresolver.h"#include "ssmstatetransitionengine.h"#include "ssmstatepolicyresolverproxy.h"#include "ssmstatetransitionrequest.h"#include "ssmstatepolicyframe.h"#include "ssmswppolicyresolver.h"#include "ssmswprequesthandler.h"#include "ssmdebug.h"// ------------------- Policy Server Security Setup ----------------------const TUint KRangeCount = 3;const TInt KRanges[KRangeCount] = { 0, // op-code 0 not used KSsmFirstUsedOpCode, //range: KFirstUsedSsmOpCode...(EEndOfSsmOpCodes-1) inclusive EEndOfSsmOpCodes };/** Specifies the appropriate action for each range in KRanges. The nth element of KElementsIndex specifies the appropriate action for the nth range in KRanges. */const TUint8 KElementsIndex[KRangeCount] = { CPolicyServer::ENotSupported, CPolicyServer::EAlwaysPass, //All request will be accepted and passed on to policy DLL for security checks CPolicyServer::ENotSupported, };/** Setup a security policy that always allows connection requests for all requests. */const CPolicyServer::TPolicy KSsmServerPolicy = { CPolicyServer::EAlwaysPass, // Always allow connection requests KRangeCount, KRanges, KElementsIndex, NULL };// ------------------- SsmServer Implementation ----------------------/** EPriorityHigh to make sure the server is always scheduled before other AO such as CSsmStateTransitionEngine. */CSsmServer::CSsmServer() : CPolicyServer(EPriorityHigh, KSsmServerPolicy) { }/** */CSsmServer::~CSsmServer() { const TInt ignore = User::SetCritical(User::ENotCritical); delete iStateTransitionEngine; delete iSwpRequestHandler; delete iSwpResolver; if(NULL != iSwpCleSession) { iSwpCleSession->ReleaseCle(); } if(iSsmUiSpecific) { iSsmUiSpecific->Release(); } } //lint !e529 not subsequently referenced/** */CSsmServer* CSsmServer::NewLC() { return CSsmServer::NewLC(ESsmStartup, EDoValidateCommandLists); }/** */CSsmServer* CSsmServer::NewLC(TUint16 aInitialState) { return CSsmServer::NewLC(aInitialState, EDoValidateCommandLists); }/** */CSsmServer* CSsmServer::NewLC(TUint16 aInitialState, TValidation aSetting) { CSsmServer* server = new(ELeave) CSsmServer(); CleanupStack::PushL(server); server->ConstructL(aInitialState, aSetting); server->StartL(KSsmServerName); return server; }#ifdef TEST_SSM_SERVER/** Factory method used by automated tests to avoid clash with production server name. */CSsmServer* CSsmServer::NewLC(const TDesC& aServerName, TUint16 aInitialState) { CSsmServer* server = new(ELeave) CSsmServer(); CleanupStack::PushL(server); server->ConstructL(aInitialState, ENoCommandListValidation); server->StartL(aServerName); return server; }#endif //TEST_SSM_SERVER/** */void CSsmServer::ConstructL(TUint16 aInitialState, TValidation aSetting) { __ASSERT_ALWAYS( KErrNone == User::SetCritical(User::ESystemCritical), PanicNow(KPanicSysStateMgr,ESsmServerError1)); __ASSERT_ALWAYS( KErrNone == User::RenameThread(KSsmServerName), PanicNow(KPanicSysStateMgr,ESsmServerError2)); iSsmUiSpecific = CSsmUiSpecific::InstanceL(); //Reserve memory for critical operation especially when phone memory will be full TInt err = iSsmUiSpecific->ReservePhoneMemorySpace(); DEBUGPRINT2(_L("CSsmUiSpecific::ReservePhoneMemorySpace returned with = %d"), err); // --- Instantiate the "System State" handling classes --- // Create a state policy resolver and load the initial policy CSsmStatePolicyResolver* stateResolver = CSsmStatePolicyResolver::NewLC(); const TSsmState initalState = TSsmState(aInitialState, KSsmAnySubState); stateResolver->GetStatePolicyL(initalState); CCleSessionProxy* stateCleSession = CCleSessionProxy::NewL(); CleanupStack::PushL(stateCleSession); // Create the state transition engine and let it take ownership of stateResolver and stateCleSession iStateTransitionEngine = CSsmStateTransitionEngine::NewL(stateResolver, stateCleSession); CleanupStack::Pop(2, stateResolver); // Configure engine iStateTransitionEngine->PerformCommandListValidation(EDoValidateCommandLists==aSetting); // --- Instantiate the SWP handling classes --- iSwpResolver = CSsmSwpPolicyResolver::NewL(); iSwpCleSession = CCleSessionProxy::NewL(); // Thought: Perhaps the CleSessionProxy should be a CLE session factory, thus allowing a separate session to be created for each engine // Create the swp request handler and wire it up to the proxies iSwpRequestHandler = CSsmSwpRequestHandler::NewL(); iSwpRequestHandler->SetSwpPolicyResolverProxy(iSwpResolver); iSwpRequestHandler->SetCleSessionProxy(iSwpCleSession); iSwpRequestHandler->PerformCommandListValidation(EDoValidateCommandLists==aSetting); //Request initial actions const TSsmStateTransition doStartup(initalState, 0); iStateTransitionEngine->SubmitL(doStartup); }/** */CSession2* CSsmServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const { // Check we're the right version TVersion version(KSsmServMajorVersionNumber,KSsmServMinorVersionNumber,KSsmServBuildVersionNumber); if (!User::QueryVersionSupported(version,aVersion)) { User::Leave(KErrNotSupported); } // version supported, go ahead return CSsmSession::NewL(); }/** */void CSsmServer::RequestStateTransitionL(const TSsmState& aState, TInt aReason, const RMessage2& aMessage) { __ASSERT_DEBUG(iStateTransitionEngine, PanicNow(KPanicSysStateMgr,ESsmServerError3)); const TSsmStateTransition request(aState, aReason); const MSsmStatePolicy::TResponse response = iStateTransitionEngine->TransitionAllowed(request, aMessage); switch(response) { case MSsmStatePolicy::EDefinitelyAllowed: case MSsmStatePolicy::ECurrentRemainReplaceQueued: { // A leave here will complete the client-request with KErrNoMemory iStateTransitionEngine->SubmitL(request, aMessage); break; } case MSsmStatePolicy::EReplaceCurrentClearQueue: { iStateTransitionEngine->Cancel(NULL); iStateTransitionEngine->SubmitL(request, aMessage); break; } case MSsmStatePolicy::ENotAllowed: default: { aMessage.Complete(KErrNotSupported); break; } } }/** Cancel any transition job that is accepted but not yet started. */void CSsmServer::RequestStateTransitionCancel(CSession2* aSession) { iStateTransitionEngine->Cancel(aSession); }/** Initiate processing of the request for a system wide property change */void CSsmServer::RequestSwpChangeL(const TSsmSwp& aSwp, const RMessage2& aMessage) { iSwpRequestHandler->SubmitRequestL(aSwp, aMessage); }/** Cancel processing of pending and running system wide property change requests */void CSsmServer::RequestSwpChangeCancel(CSession2* aSession) { iSwpRequestHandler->Cancel(aSession); }/** Register the policy file name for this swp This also marks the actual existence of the swp */void CSsmServer::RequestRegisterSwpMappingL(TUint aSwpKey, const TDesC& aFilename) { iSwpResolver->RegisterSwpMappingL(aSwpKey, aFilename); } //lint !e1746 Suppress parameter 'aSwpKey' could be made const reference/** * Used only for testing purposes * DeRegister the policy file name for this swp */#ifdef _DEBUGvoid CSsmServer::RequestDeRegisterSwpMappingL(TUint aSwpKey, const TDesC& aFilename) { iSwpResolver->DeRegisterSwpMappingL(aSwpKey, aFilename); }#endif/** * Used only for testing purposes * Cleanup Transition Engine after the test is over */#ifdef _DEBUGvoid CSsmServer::DoCleanupStateTransitionEngine() { iStateTransitionEngine->CleanupTransitionEngine(); }#endif/** * Used only for testing purposes * Cleanup Request Handler after the test is over */#ifdef _DEBUGvoid CSsmServer::DoCleanupSwpRequestHandler() { iSwpRequestHandler->CleanupSwpTransitionScheduler(); }#endif