// Copyright (c) 1999-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:
//

#include <apgtask.h>
#include <apgwgnam.h>

#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include "vwsinternal.h"
#include "vwsdefpartner.h"
#endif //SYMBIAN_ENABLE_SPLIT_HEADERS

#include "VWSERVER.H"
#include "VWSSESSN.H"
#include "VWSEVENT.H"
#include "VWSWEVNT.H"
#include "VWSADDOB.H"
#include "VWSPRIV.H"
#include "VWSDEBUG.H"
#include "vwspatchdata.h"


#include <barsc2.h>
#include <barsread2.h>
#include <f32file.h> 
#include <u32hal.h>

//
// Constants.
//

const TInt KVwsSystemDefaultViewArrayGranularity=2;
const TInt KDefaultClientRequestTimeOutDuration=1000000;
const TInt KDefaultServerEventTimeOutDuration=10000000;

_LIT(KPriorityFilename,"Z:\\resource\\apps\\PrioritySet.rsc");


const TUint8 KPolicyElementSID = 0;
const TUint8 KPolicyPowerMgmt = 1;

const TInt KEiksrvsSid=0x10003a4a;

const TUint KRangeCount = 5; 

const TInt KVwsServerRanges[KRangeCount] = 
	{	
	EFirstUnrestrictedOpcodeInVws,
	EFirstOpcodeNeedingCustomCheckInVws,
	EFirstOpcodeNeedingSecureIdInVws,	
	EFirstOpCodeNeedingPowerMgmt,
	EVwsFirstUnusedOpcode,
	};

const TUint8 KElementsIndex[KRangeCount] =
	{
	CPolicyServer::EAlwaysPass,		//Always passing no capability required [EFirstUnrestrictedOpcodeInVws-(EFirstOpcodeNeedingCustomCheckInVws-1)]
	CPolicyServer::ECustomCheck,	//Requires Custom check	[EFirstOpcodeNeedingCustomCheckInVws-(EFirstOpcodeNeedingSecureIdInVws-1)]
	KPolicyElementSID,				//Requires SID to be of Eiksrvs ie.0x10003a4a  [EFirstOpcodeNeedingSecureIdInVws-(EFirstOpCodeNeedingPowerMgmt-1)]
	KPolicyPowerMgmt,				//Requires PowerMgmt capability [EFirstOpCodeNeedingPowerMgmt-(EVwsFirstUnusedOpcode-1)]
	CPolicyServer::ENotSupported,	//Not Supported		
	};

const CPolicyServer::TPolicyElement KPolicyElements[] = 
	{
	{_INIT_SECURITY_POLICY_S0(KEiksrvsSid), CPolicyServer::EFailClient}, 
	{_INIT_SECURITY_POLICY_C1(ECapabilityPowerMgmt), CPolicyServer::EFailClient} 
	};

const CPolicyServer::TPolicy KVwsServerPolicy =
	{
	CPolicyServer::EAlwaysPass, 
	KRangeCount,
	KVwsServerRanges,
	KElementsIndex, 	 
	KPolicyElements 	
	};
 	
//
// CVwsServer.
//

#ifdef __DO_LOGGING__
CVwsServer::CVwsServer(TInt aPriority,MVwsAppStarter& aAppStarter)
	: CPolicyServer(aPriority,KVwsServerPolicy),
	  iAppStarter(aAppStarter),
	  iSystemDefaultViewIdArray(KVwsSystemDefaultViewArrayGranularity),
	  iClientRequestTimeOut(KDefaultClientRequestTimeOutDuration),
	  iServerEventTimeOut(KDefaultServerEventTimeOutDuration),
	  iForegroundChangeWhileEventsOutstanding(EFalse),
	  iIsServerEventTimeOutDisabled(0),	
	  iNoActivationRequests(0),
	  iEnableServerBlankScreen(ETrue),
	  iEnableBoostAppPriorityBeforePanic(KVwsBoostAppPriorityBeforePanic)
	{
	}
#else
CVwsServer::CVwsServer(TInt aPriority,MVwsAppStarter& aAppStarter)
	: CPolicyServer(aPriority,KVwsServerPolicy),
	  iAppStarter(aAppStarter),
	  iSystemDefaultViewIdArray(KVwsSystemDefaultViewArrayGranularity),
	  iClientRequestTimeOut(KDefaultClientRequestTimeOutDuration),
	  iServerEventTimeOut(KDefaultServerEventTimeOutDuration),
	  iForegroundChangeWhileEventsOutstanding(EFalse),
	  iIsServerEventTimeOutDisabled(0),
	  iEnableServerBlankScreen(ETrue),
	  iEnableBoostAppPriorityBeforePanic(KVwsBoostAppPriorityBeforePanic)
	{
	}
#endif

EXPORT_C CVwsServer* CVwsServer::NewL(MVwsAppStarter& aAppStarter)
	{
	CVwsServer *pS=new CVwsServer(CActive::EPriorityStandard,aAppStarter);
	__ASSERT_ALWAYS(pS!=NULL,PanicServer(EVwsServerCreate));

	pS->ConstructL();

	pS->StartL(KViewServerName);
	return pS;
	}

CSession2* CVwsServer::NewSessionL(const TVersion &aVersion,const RMessage2& aMessage) const
	{
	// Check version supported.
	TVersion version(KVwsMajorVersionNumber,KVwsMinorVersionNumber,KVwsBuildVersionNumber);
	if (!User::QueryVersionSupported(version,aVersion))
		{
		User::Leave(KErrNotSupported);
		}

	RThread thread;
	User::LeaveIfError(aMessage.Client(thread));
	const TThreadId threadId(thread.Id());
	thread.Close();
	return CVwsSession::NewL(threadId,CONST_CAST(CVwsServer&,*this));
	}


EXPORT_C CVwsServer::~CVwsServer()
	{
	delete iWServSessionHandler;

	delete iEventQueue;
#ifdef __DO_LOGGING__
	CVwsLog::ShutdownLog();
#endif
	}

void CVwsServer::ConstructL()
	{
	// required for handling intercepting window
	iWServSessionHandler=CVwsWServSessionHandler::NewL(*this);

#ifdef __DO_LOGGING__
	iEventQueue=new(ELeave) CVwsEventQueue(_L("Server Queue"));
	CVwsLog::StartLogL();
#else
	iEventQueue=new(ELeave) CVwsEventQueue;
#endif
	RFs fs;
	iPrioritySet=CActive::EPriorityStandard;
	CleanupClosePushL(fs);
	if(fs.Connect()==KErrNone)
		{
		CResourceFile* file=NULL;
		TRAPD(err, file=CResourceFile::NewL(fs, KPriorityFilename, 0, 0));
		if(err == KErrNone)
			{
			CleanupStack::PushL(file);
			RResourceReader reader;
			reader.OpenL(file, 2);
			CleanupClosePushL(reader);
			iPrioritySet=reader.ReadUint32L();
			CleanupStack::PopAndDestroy(&reader);
			CleanupStack::PopAndDestroy(file);
			}
		fs.Close();
		}
	
	CleanupStack::PopAndDestroy(&fs);


	
		
		
#ifdef __WINS__
	// KVwsBoostAppPriorityBeforePanic is a Rom patchable constant, so need an emulator equivalent
	// if WINS then read value from epoc.ini requires licencees to set property in epoc.ini. 
	// Usage: In epoc.ini patchdata_viewsrv_dll_KVwsBoostAppPriorityBeforePanic 1
						
	TInt valueOfKVwsBoostAppPriorityBeforePanic = 0;
	if (UserSvr::HalFunction(EHalGroupEmulator,EEmulatorHalIntProperty,(TAny*)"patchdata_viesrv_dll_KVwsBoostAppPriorityBeforePanic",&valueOfKVwsBoostAppPriorityBeforePanic) == KErrNone)
		{
		iEnableBoostAppPriorityBeforePanic = valueOfKVwsBoostAppPriorityBeforePanic;
		}
#endif
	
	if (iEnableBoostAppPriorityBeforePanic)
		{
		CVwsStartupAware* startupAware = new(ELeave)CVwsStartupAware(*this);
		TInt err = startupAware->Start();
		if (err != KErrNone)
			{
			HandleInitializationFinished();
			delete startupAware;
			}
		}
 	}

CVwsStartupAware::CVwsStartupAware(CVwsServer& aServer)
	:CActive(CActive::EPriorityStandard),iServer(aServer)
	{
	CActiveScheduler::Add(this); 
	}
	
CVwsStartupAware::~CVwsStartupAware()
	{
	Cancel();
	iStateAwareSession.Close();
	}

TInt CVwsStartupAware::Start()
	{
	TInt err = iStateAwareSession.Connect(KSM2UiServicesDomain3);
	if(iStateAwareSession.State().MainState() != ESsmNormal && err == KErrNone)
		{
		iStateAwareSession.RequestStateNotification(iStatus);
		SetActive();
		}
	return err;
	}

void CVwsStartupAware::RunL()
	{
	if (iStatus == KErrNone)
		{
		if (iStateAwareSession.State().MainState() == ESsmNormal)
			{
		iServer.HandleInitializationFinished(); //Bootup is complete now, allowing Viewsrv 11 panics to occur here onwards
			delete this;
			}
		else
			{
			iStateAwareSession.AcknowledgeAndRequestStateNotification(KErrNone, iStatus);
			SetActive();
			}
		}
	}

void CVwsStartupAware::DoCancel()
	{
	iStateAwareSession.RequestStateNotificationCancel();
	}

void CVwsServer::PanicClient(TInt aPanic) const
	{
	 _LIT(KVwsSrvPanic, "ViewSrv");
 	 User::Panic(KVwsSrvPanic,aPanic); 
	}

void CVwsServer::SetSystemDefaultViewL(TInt aMode,const TVwsViewId& aViewId)
	{
	__ASSERT_DEBUG(aMode>=0,PanicClient(EVwsInvalidScreenMode));
	const TInt count = iSystemDefaultViewIdArray.Count();

	if ((aMode>count) || (aMode<0))
		{
		PanicClient(EVwsInvalidScreenMode);	
		}
	else if (aMode < count)
		{
		iSystemDefaultViewIdArray.At(aMode) = aViewId;
		}
	else if (aMode == count) 
		{
		iSystemDefaultViewIdArray.AppendL(aViewId);
		}
	}

void CVwsServer::SetClientRequestTimeOut(const TTimeIntervalMicroSeconds32& aDuration)
	{
	iClientRequestTimeOut=aDuration;
	}

void CVwsServer::SetServerEventTimeOut(const TTimeIntervalMicroSeconds32& aDuration)
	{
	iServerEventTimeOut=aDuration;
	}

void CVwsServer::EnableServerEventTimeOut(TBool aEnable)
	{
	if (!aEnable)
		{
		iIsServerEventTimeOutDisabled++;
		}
	else if (iIsServerEventTimeOutDisabled)
		{
		iIsServerEventTimeOutDisabled--;
		}
	}

void CVwsServer::EnableServerBlankScreen(TBool aEnable)
	{
	iEnableServerBlankScreen = aEnable;	
	}

void CVwsServer::GetSystemDefaultView(TVwsViewId& aViewId)
	{
	TInt mode=iWServSessionHandler->GetScreenMode();
	aViewId = (mode>=0 && mode<iSystemDefaultViewIdArray.Count()) ? iSystemDefaultViewIdArray[mode] : KNullViewId;
	}

TInt CVwsServer::ScreenMode()
	{
	return iWServSessionHandler->GetScreenMode();
	}

TBool CVwsServer::IsSystemDefaultView(const TVwsViewId& aViewId)
	{
	TBool ret=EFalse;

	const TInt numViews=iSystemDefaultViewIdArray.Count();
	for (TInt ii=0;ii<numViews;ii++)
		{
		if (iSystemDefaultViewIdArray[ii] == aViewId)
			{
			return ETrue;
			}
		}

	return ret;
	}

/**
 * Activates the view identified by aViewId. Immediately takes ownership of the message aClientMessage.
 */
void CVwsServer::ActivateViewL(const TVwsViewId& aViewId,CVwsClientMessage* aClientMessage,const RMessage2& aMessage,const TThreadId& aClientThreadId,TVwsCompleteRequest aCompleteRequest)
	{
	TVwsViewId viewId=aViewId;
	if (viewId==KNullViewId)
		{
		GetSystemDefaultView(viewId);
		}
	CleanupStack::PushL(aClientMessage);
	CVwsThreadWatcher* threadWatcher=new(ELeave) CVwsThreadWatcher();
	CleanupStack::PushL(threadWatcher);
	CVwsEventTimer* eventTimer=CVwsEventTimer::NewLC(iClientRequestTimeOut,iServerEventTimeOut);
	RThread threadOfClientInitiatingViewSwitch;
	User::LeaveIfError(aMessage.Client(threadOfClientInitiatingViewSwitch));
	CleanupClosePushL(threadOfClientInitiatingViewSwitch);	
	CVwsServerEvent* activationEvent=new(ELeave) CVwsServerEvent_Activate(*this,CVwsServerEvent::ENormal,*iEventQueue,viewId,aClientMessage,aMessage,aClientThreadId,aCompleteRequest,threadWatcher,eventTimer,threadOfClientInitiatingViewSwitch);
	CleanupStack::Pop(4, aClientMessage); // the CVwsServerEvent_Activate object is now the owner of aClientMessage, threadWatcher, eventTimer and threadOfClientInitiatingViewSwitch
	iEventQueue->ProcessEventL(activationEvent);
#ifdef __DO_LOGGING__
	iNoActivationRequests++;
	LOG3(CVwsLog::ELoud,_L("Cumulative activation requests since server start - %d"),iNoActivationRequests);
#endif
	}

void CVwsServer::ActivateViewL(const TVwsViewId& aViewId,CVwsClientMessage* aClientMessage,const RMessage2& aMessage,const CVwsSession& aSession,TVwsCompleteRequest aCompleteRequest)
	{
	ActivateViewL(aViewId,aClientMessage,aMessage,aSession.ClientThreadId(),aCompleteRequest);
	}

TVwsViewId CVwsServer::ActiveView()
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->HasActiveView())
			{
			return thisSession->ActiveView();
			}
		}

	return KNullViewId;
	}

void CVwsServer::SetActiveView(const TThreadId& aThreadId,const TVwsViewId& aViewId)
	{
#ifdef _DEBUG
	TVwsViewId activeView=ActiveView();

	if (activeView != KNullViewId)
		{
		LOG6(CVwsLog::EQuiet,_L("Changing active view to \"%x,%x\" [previously \"%x,%x\"]"),aViewId.iAppUid.iUid,aViewId.iViewUid.iUid,activeView.iAppUid.iUid,activeView.iViewUid.iUid);
		}
	else
		{
		LOG4(CVwsLog::EQuiet,_L("Changing active view to \"%x,%x\" [no view previously active]"),aViewId.iAppUid.iUid,aViewId.iViewUid.iUid);
		}
#endif

	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->ClientThreadId()==aThreadId)
			{
			thisSession->SetActiveView(aViewId);
			}
		else if (thisSession->HasActiveView())
			{
			thisSession->ClearActiveView();
			}
		}
	}

void CVwsServer::ClearActiveView()
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->HasActiveView())
			{
			thisSession->ClearActiveView();
			break;
			}
		}
	}

void CVwsServer::SetViewAdditionObserver(MVwsViewAdditionObserver* aViewAdditionObserver)
	{
	ASSERT((iViewAdditionObserver==NULL) || (aViewAdditionObserver==NULL));
	iViewAdditionObserver=aViewAdditionObserver;
	}

void CVwsServer::HandleScreenDeviceChangedL()
	{
	LOG2(CVwsLog::ENormal,_L("Received screen device changed notification from WServ, creating event to handle it"));
	CVwsThreadWatcher* threadWatcher=new(ELeave) CVwsThreadWatcher();
	CleanupStack::PushL(threadWatcher);
	CVwsEventTimer* eventTimer=CVwsEventTimer::NewLC(iClientRequestTimeOut,iServerEventTimeOut);
	CVwsServerEvent* screenDeviceChangedEvent=new(ELeave) CVwsServerEvent_ScreenDeviceChanged(*this,*iEventQueue,threadWatcher,eventTimer);
	CleanupStack::Pop(2); // threadWatcher, eventTimer - _ScreenDeviceChanged event is now the owner.
	iEventQueue->ProcessEventL(screenDeviceChangedEvent);
	}

TInt CVwsServer::StartApp(const TUid& aAppUid,TThreadId& aThreadId)
	{
	LOG3(CVwsLog::ENormal,_L("Attempting to start app \"%x\""),aAppUid.iUid);
	TRAPD(err,iAppStarter.StartAppL(aAppUid,aThreadId));
	return err;
	}

TInt CVwsServer::CheckViewExists(const TThreadId& aThreadId,const TVwsViewId& aViewId)
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->ClientThreadId()==aThreadId)
			{
			return thisSession->CheckViewExists(aViewId);
			}
		}

	return KErrNotFound;
	}

CVwsSession* CVwsServer::ActiveViewSession()
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->HasActiveView())
			{
			return thisSession;
			}
		}

	return NULL;
	}

CVwsSession* CVwsServer::SessionByUid(const TUid& aAppUid)
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->AppUid()==aAppUid && !thisSession->Protected())
			{
			return thisSession;
			}
		}

	return NULL;
	}

CVwsSession* CVwsServer::SessionByThreadIdAndAppUid(const TThreadId& aThreadId,const TUid& aAppUid)
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->ClientThreadId()==aThreadId && thisSession->AppUid()==aAppUid)
			{
			return thisSession;
			}
		}

	return NULL;
	}

CVwsSession* CVwsServer::SessionByThreadId(const TThreadId& aThreadId)
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->ClientThreadId()==aThreadId)
			{
			return thisSession;
			}
		}

	return NULL;
	}

TBool CVwsServer::IsViewActive(const TVwsViewId& aViewId)
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);

		if (thisSession->HasActiveView())
			{
			return thisSession->IsViewActive(aViewId);
			}
		}

	return EFalse;
	}

void CVwsServer::RequestDeactivateActiveViewL(const RMessage2& aMessage,const CVwsSession& aSession,TVwsCompleteRequest aCompleteRequest)
	{
	LOG2(CVwsLog::ENormal,_L("Received deactivate active view request, creating event to handle it"));
	CVwsEventTimer* eventTimer=CVwsEventTimer::NewLC(iClientRequestTimeOut,iServerEventTimeOut);
	CVwsServerEvent* deactivateActiveViewEvent=new(ELeave) CVwsServerEvent_DeactivateActiveView(*this,*iEventQueue,aMessage,aSession.ClientThreadId(),aCompleteRequest,eventTimer);
	CleanupStack::Pop(); //  eventTimer - _DeactivateActiveView event is now the owner.
	iEventQueue->ProcessEventL(deactivateActiveViewEvent);
	}

void CVwsServer::RequestAppStartL(const RMessage2& aMessage,const TUid& aAppToStart)
	{
	LOG2(CVwsLog::ENormal,_L("Received start app request, creating event to handle it"));
	CVwsThreadWatcher* threadWatcher=new(ELeave) CVwsThreadWatcher();
	CleanupStack::PushL(threadWatcher);
	CVwsServerEvent* appStartEvent=new(ELeave) CVwsServerEvent_AppStart(*this,*iEventQueue,aMessage,aAppToStart,threadWatcher);
	CleanupStack::Pop();	// threadWatcher
	iEventQueue->ProcessEventL(appStartEvent);
	}

void CVwsServer::HandleDeactivation(const TVwsViewId& aDeactivatedViewId, const TVwsViewId& aActivatedViewId)
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);
		TRAP_IGNORE(thisSession->HandleDeactivationL(aDeactivatedViewId,aActivatedViewId));
		}
	}

void CVwsServer::HandleActivation(const TVwsViewId& aActivatedViewId, const TVwsViewId& aViewIdToBeDeactivated)
	{
	for (iSessionIter.SetToFirst();iSessionIter;iSessionIter++)
		{
		CSession2* baseSession=iSessionIter;
		CVwsSession* thisSession=STATIC_CAST(CVwsSession*,baseSession);
		TRAP_IGNORE(thisSession->HandleActivationL(aActivatedViewId,aViewIdToBeDeactivated));
		}
	}

void CVwsServer::MakeInterceptingWindowVisible()
	{
	if (iEnableServerBlankScreen)
		{
		iWServSessionHandler->DisplayWindow();
		}
	}

void CVwsServer::MakeInterceptingWindowInvisible()
	{
	if (iEnableServerBlankScreen)
		{
		iWServSessionHandler->HideWindow();
		}
	}

void CVwsServer::MakeInterceptingWindowVisibleAndUpdateScreen()
	{
	if (iEnableServerBlankScreen)
		{
		iWServSessionHandler->UpdateScreenAndDisplayWindow();
		}
	}

void CVwsServer::HandleSessionViewAddition(const TVwsViewId& aViewId, const TThreadId& aNewViewClientThreadId)
	{
	if (iViewAdditionObserver)
		{
		iViewAdditionObserver->HandleViewAdded(aViewId, aNewViewClientThreadId);
		}
	}

void CVwsServer::HandleSessionRemoval(const TThreadId& aThreadId)
	{
	iEventQueue->HandleSessionRemoval(aThreadId);
	}

/* Check that the thread that has keyboard focus also has the active view.
 * Activate a new view if not.
 */
void CVwsServer::CrossCheckForegroundTask()
	{
	//Get the focused window group;
	RWsSession& wsSession=iWServSessionHandler->WsSession();
	TInt fgAppWgId=wsSession.GetFocusWindowGroup();
	if (fgAppWgId)
		{
		CVwsSession* activeSession=ActiveViewSession();
		TThreadId fgAppThreadId;
		//Get the thread that owns this Window group.
		if (wsSession.GetWindowGroupClientThreadId(fgAppWgId,fgAppThreadId)==KErrNotFound)
			{
			fgAppThreadId=TThreadId(0);
			}
		if (!(activeSession && activeSession->ClientThreadId()==fgAppThreadId) && SessionByThreadId(fgAppThreadId))
			{
			LOG2(CVwsLog::ELoud,_L("Foreground app cross-check failed - notifying foreground app that it needs to activate a view"));
			if(iCrossCheckUid!=KNullUid)
				{
				// We can't do anything about the leave here, so trap and ignore it
				TRAP_IGNORE(SendCrossCheckToLauncherL(wsSession, fgAppWgId, ActiveView()));
				}
			else
				{
				TWsEvent event;
				event.SetType(EEventUser);
				*(TApaSystemEvent*)(event.EventData())=EApaSystemEventBroughtToForeground;
				event.SetTimeNow();
				wsSession.SendEventToWindowGroup(fgAppWgId,event);
				}
			}
		}
	}

void CVwsServer::HandleLastServerEventOnQueue()
	{
	MakeInterceptingWindowInvisible();
	if (iForegroundChangeWhileEventsOutstanding)
		{
		iForegroundChangeWhileEventsOutstanding=EFalse;
		CrossCheckForegroundTask();
		}
	}

void CVwsServer::HandleForegroundTaskChange()
	{
	if (iEventQueue->Count()>0)
		{
		iForegroundChangeWhileEventsOutstanding=ETrue;
		}
	else
		{
		CrossCheckForegroundTask();
		}
	}

 void CVwsServer::KickStartEventQ()
     {
     iEventQueue->KickStart();          
     }

CPolicyServer::TCustomResult CVwsServer::CustomSecurityCheckL(const RMessage2& aMsg, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
//aAction is not set because default value to it is already set(CPolicyServer::EFailClient)
//aMissing is not set because it is not needed as we aren't overriding CheckFailedL
	{
	CPolicyServer::TCustomResult returnValue = CPolicyServer::EFail;	

	// Check that the client either has SID of Eiksrvs or WriteDeviceData capability
	if(aMsg.SecureId()==KEiksrvsSid || aMsg.HasCapability(ECapabilityWriteDeviceData))
		{
		returnValue = CPolicyServer::EPass;
		}
	
	return(returnValue);
	}
void CVwsServer::GetPriorityForActiveObjectL(TInt& aPriority)
	{
	aPriority=iPrioritySet;
	}

struct TCrossCheckParam
	{
	TVwsViewId	iActiveView;
	TInt		iFgAppWgId;
	};

void CVwsServer::SetCrossCheckUid(const RMessage2& aMessage)
	{
	iCrossCheckUid.iUid=aMessage.Int0();
	}

TUid CVwsServer::CrossCheckUid() const
	{
	return iCrossCheckUid;
	}

void CVwsServer::SendCrossCheckToLauncherL(RWsSession& aWsSession, TInt aFgAppWgId, const TVwsViewId& aActiveView)
	{
	TInt launcherWgId = 0;
	const TInt KPriority = -1;
	TInt wgCount = aWsSession.NumWindowGroups(KPriority);
	if (wgCount)
		{
		CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(aWsSession);
		CArrayFixFlat<TInt>* wgIdArray = new(ELeave) CArrayFixFlat<TInt>(wgCount);
		CleanupStack::PushL(wgIdArray);
		User::LeaveIfError(aWsSession.WindowGroupList(KPriority, wgIdArray));
		const TInt KCount = wgIdArray->Count();
		for (TInt i = 0; i < KCount; ++i)
			{
			const TInt wgId = (*wgIdArray)[i];
			wgName->ConstructFromWgIdL(wgId);
			if (wgName->AppUid() == iCrossCheckUid)
				{
				launcherWgId = wgId;
				break;
				}
			}
		CleanupStack::PopAndDestroy(2, wgName);		// wgIdArray, wgName
		}

	if (launcherWgId)
		{
		TWsEvent wsEvent;
		wsEvent.SetType(EEventUser + 256);	// Change this later
		wsEvent.SetTimeNow();
		TCrossCheckParam* param = reinterpret_cast<TCrossCheckParam*>(wsEvent.EventData());
		param->iActiveView = aActiveView;
		param->iFgAppWgId = aFgAppWgId;
		aWsSession.SendEventToWindowGroup(launcherWgId, wsEvent);
		}	
	};
	
void CVwsServer::SetWindowBackgroundColor(const RMessage2& aMessage)
	{
	TRgb color;
	color.SetInternal(aMessage.Int0());
	iWServSessionHandler->SetWindowBackgroundColor(color);
	}
	
// Gets the active viewid of the foreground application
void CVwsServer::GetCurrentActiveViewId(TVwsViewId& aActiveViewId)
	{
	aActiveViewId = ActiveView();
	}

// Tells if the application whose view is getting activated is in foreground or background
TBool CVwsServer::IsAppInForeground()
	{
	TBool isAppInForeground = EFalse;
	RWsSession& wsSession = iWServSessionHandler->WsSession();
	TInt fgAppWgId = wsSession.GetFocusWindowGroup();
	if (fgAppWgId)
		{
		CVwsSession* activeSession = ActiveViewSession();
		TThreadId fgAppThreadId;
		// Get the thread that owns this Window group.
		// GetWindowGroupClientThreadId() either returns KErrNone or KErrNotFound error code
		if (wsSession.GetWindowGroupClientThreadId(fgAppWgId,fgAppThreadId) == KErrNotFound)
			{
			fgAppThreadId = TThreadId(0);
			}

		if (!(activeSession && (activeSession->ClientThreadId() == fgAppThreadId)) && SessionByThreadId(fgAppThreadId))
			{
			isAppInForeground = ETrue;
			}
		}
	return isAppInForeground;
	}
	
TBool CVwsServer::InitializationFinished() const
	{
	return iInitializationFinished;
	}
	
TInt CVwsServer::IsPriorityBoostBeforePanicEnabled()const
	{
	return iEnableBoostAppPriorityBeforePanic;
	}

void CVwsServer::HandleInitializationFinished()
 	{
 	iInitializationFinished = ETrue;
 	}

void CVwsServer::BoostPriority(CVwsSession* aClient)
	{
	if (!aClient)
		{
		return;
		}
	if (!IsPriorityBoostBeforePanicEnabled())
		{
		return;
		}
		
	RThread starved;
	if (starved.Open(aClient->ClientThreadId()) != KErrNone)
		{
		return;
		}
		
	if (starved.ProcessPriority() < EPriorityForeground)
		{
		RProcess owningProcess;
		TInt err = starved.Process(owningProcess);
		if (err != KErrNone)
			{
			starved.Close();
			return;
			}
		owningProcess.SetPriority(EPriorityForeground);
		owningProcess.Close();
		}
	
	starved.Close();
	}

