--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/appfw/viewserver/server/VWSEVENT.CPP Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,1204 @@
+// 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:
+//
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "vwsinternal.h"
+#include "vwsdefpartner.h"
+#endif //SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "VWSEVENT.H"
+#include "VWSERVER.H"
+#include "VWSDEBUG.H"
+#include "VWSPRIV.H"
+#include "vwspatchdata.h"
+
+#include <u32hal.h>
+
+
+
+//
+// class CVwsThreadWatcher
+//
+
+CVwsThreadWatcher::~CVwsThreadWatcher()
+ {
+ Cancel();
+ iThread.Close();
+ }
+
+CVwsThreadWatcher::CVwsThreadWatcher()
+ : CActive(EPriorityStandard)
+ {
+ }
+
+TInt CVwsThreadWatcher::StartWatching(const TThreadId& aThreadId, const TCallBack& aCallBack)
+ {
+ iCallBack=aCallBack;
+ if(aThreadId!=iThread.Id())
+ {
+ if(IsAdded())
+ {
+ Deque();
+ iThread.Close();
+ }
+ TInt err=iThread.Open(aThreadId);
+ if (err==KErrNone)
+ {
+ CActiveScheduler::Add(this);
+ iThread.Logon(iStatus);
+ SetActive();
+ }
+ return err;
+ }
+ return KErrNone;
+ }
+
+void CVwsThreadWatcher::DoCancel()
+ {
+ iThread.LogonCancel(iStatus);
+ }
+
+void CVwsThreadWatcher::RunL()
+ {
+ iCallBack.CallBack();
+ }
+
+
+//
+// CVwsEventTimer.
+//
+
+CVwsEventTimer::~CVwsEventTimer()
+ {
+ delete iPeriodic;
+ }
+
+CVwsEventTimer* CVwsEventTimer::NewLC(const TTimeIntervalMicroSeconds32& aClientRequestTimeOut, const TTimeIntervalMicroSeconds32& aServerEventTimeOut)
+ { // static
+ CVwsEventTimer* self = new(ELeave) CVwsEventTimer(aClientRequestTimeOut, aServerEventTimeOut);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+CVwsEventTimer::CVwsEventTimer(const TTimeIntervalMicroSeconds32& aClientRequestTimeOut, const TTimeIntervalMicroSeconds32& aServerEventTimeOut)
+ : iClientRequestTimeOut(aClientRequestTimeOut),
+ iServerEventTimeOut(aServerEventTimeOut),
+ iTimeOutState(EUndefined),
+ iScreenDeviceChangeEvent(EFalse)
+ {}
+
+void CVwsEventTimer::ConstructL()
+ {
+ iPeriodic=CPeriodic::NewL(0);
+ }
+
+void CVwsEventTimer::Start(MVwsEventTimerObserver* aObserver,const TBool& aScreenDeviceChangeEvent)
+ {
+ iObserver=aObserver;
+
+ if (iPeriodic->IsActive())
+ {
+ iPeriodic->Cancel();
+ }
+
+ TTimeIntervalMicroSeconds32 firstDelay(0);
+ iTimeOutState=EUndefined;
+
+ if (iClientRequestTimeOut < iServerEventTimeOut)
+ {
+ iTimeOutState=EClientRequestTimeOut;
+ firstDelay=iClientRequestTimeOut;
+ }
+ else
+ {
+ iTimeOutState=EServerEventTimeOut;
+ firstDelay=iServerEventTimeOut;
+ }
+
+ TTimeIntervalMicroSeconds32 delay(firstDelay);
+ iPeriodic->Start(delay,delay,TCallBack(TimerCallBack,this));
+ iScreenDeviceChangeEvent = aScreenDeviceChangeEvent;
+
+ }
+
+TInt CVwsEventTimer::TimerCallBack(TAny* aSelf)
+ { // static
+ REINTERPRET_CAST(CVwsEventTimer*,aSelf)->DoTimerCallBack();
+ return 0;
+ }
+
+void CVwsEventTimer::DoTimerCallBack()
+ {
+ if (iPeriodic != NULL && iPeriodic->IsActive())
+ {
+ iPeriodic->Cancel();
+ }
+ if (iScreenDeviceChangeEvent && iObserver)
+ {
+ iObserver->HandleTimeOut(iTimeOutState);
+ }
+ else
+ {
+ if (iObserver)
+ {
+ iObserver->HandleTimeOut(iTimeOutState);
+ }
+ if (iTimeOutState == EClientRequestTimeOut || iTimeOutState == EIntermediateEventTimeOut)
+ {
+ TTimeIntervalMicroSeconds32 delay;
+ if (iTimeOutState == EClientRequestTimeOut)
+ {
+ //Normal delay is given before considering boosting the priority of an application
+ delay = iServerEventTimeOut.Int()-iClientRequestTimeOut.Int();
+ iTimeOutState = EIntermediateEventTimeOut;
+ }
+ else
+ {
+ //Delay of KTimeoutValueForPreemptedProcess is given after boosting priority of an application
+ TUint8 patchableConst = KTimeoutValueForPreemptedProcess;
+ #ifdef __WINS__
+ // For the emulator allow the constant to be patched via epoc.ini
+ UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty,
+ (TAny*)"KTimeoutValueForPreemptedProcess", &patchableConst); // read emulator property (if present)
+ #endif
+ delay = patchableConst;
+ iTimeOutState = EServerEventTimeOut;
+ }
+
+ iPeriodic->Start(delay,delay,TCallBack(TimerCallBack,this));
+ }
+ }
+ }
+
+//
+// CVwsServerEvent.
+//
+
+CVwsServerEvent::CVwsServerEvent(CVwsServer& aServer,TType aType,CVwsEventQueue& aQueue)
+ :CVwsEvent(aType,aQueue),iServer(aServer)
+ {
+ }
+
+CVwsServerEvent::~CVwsServerEvent()
+ {
+ if (iObserved)
+ {
+ iObserved->NullifyObserver();
+ }
+ }
+
+
+void CVwsServerEvent::HandleLastOnQueue()
+ {
+ iServer.HandleLastServerEventOnQueue();
+ }
+
+
+//
+// CVwsServerEvent_Activate.
+//
+
+CVwsServerEvent_Activate::CVwsServerEvent_Activate(CVwsServer& aServer,TType aType,CVwsEventQueue& aQueue,const TVwsViewId& aViewIdToActivate,CVwsClientMessage* aClientMessage,const RMessage2& aMessage,const TThreadId& aClientThreadId,TVwsCompleteRequest aCompleteRequest,CVwsThreadWatcher* aThreadWatcher,CVwsEventTimer* aEventTimer,const RThread& aThreadOfClientInitiatingViewSwitch)
+ : CVwsServerEvent(aServer,aType,aQueue),
+ iViewIdToActivate(aViewIdToActivate),
+ iClientMessage(aClientMessage),
+ iNewViewClientThreadId(0),
+ iCompleteRequest(aCompleteRequest),
+ iClientThreadId(aClientThreadId),
+ iMessage(aMessage),
+ iThreadWatcher(aThreadWatcher),
+ iEventTimer(aEventTimer),
+ iThreadOfClientInitiatingViewSwitch(aThreadOfClientInitiatingViewSwitch)
+ {
+ }
+
+CVwsServerEvent_Activate::~CVwsServerEvent_Activate()
+ {
+ delete iClientMessage;
+ delete iThreadWatcher;
+ delete iEventTimer;
+ iThreadOfClientInitiatingViewSwitch.Close();
+ }
+
+void CVwsServerEvent_Activate::HandleTimeOut(CVwsEventTimer::TTimeOut aTimeOut)
+ {
+ if (aTimeOut==CVwsEventTimer::EServerEventTimeOut && iServer.IsServerEventTimeOutEnabled())
+ {
+ if (iState==EActivationRequested)
+ {
+ LOG3(CVwsLog::ENormal,_L("PANIC CLIENT \"%x\" for timing out activation view event - activation request was not completed"),iViewIdToActivate.iAppUid.iUid);
+ if (TUint(iNewViewClientThreadId)!=0)
+ {
+ CVwsSession* newViewSession=iServer.SessionByThreadId(iNewViewClientThreadId);
+ if (newViewSession)
+ {
+ if (iServer.IsPriorityBoostBeforePanicEnabled())
+ {
+ if (iServer.InitializationFinished())
+ {
+ newViewSession->PanicClient(EVwsViewActivationEventTimeOut);
+ }
+ }
+ else
+ {
+ newViewSession->PanicClient(EVwsViewActivationEventTimeOut);
+ }
+ }
+ }
+ }
+ else if (iState==EDeactivationRequested)
+ {
+ LOG3(CVwsLog::ENormal,_L("PANIC CLIENT \"%x\" for timing out activation view event - deactivation request was not completed"),iServer.ActiveView().iAppUid.iUid);
+ CVwsSession* sessionWithActiveView=iServer.ActiveViewSession();
+ if (sessionWithActiveView)
+ {
+ if (iServer.IsPriorityBoostBeforePanicEnabled())
+ {
+ if (iServer.InitializationFinished())
+ {
+ sessionWithActiveView->PanicClient(EVwsViewDeactivationEventTimeOut);
+ }
+ }
+ else
+ {
+ sessionWithActiveView->PanicClient(EVwsViewDeactivationEventTimeOut);
+ }
+ }
+ }
+ else
+ {
+ LOG4(CVwsLog::EQuiet,_L("Aborting activation of view \"%x,%x\" - server event processing timed-out"),iViewIdToActivate.iAppUid.iUid,iViewIdToActivate.iViewUid.iUid);
+ Complete(KErrCancel);
+ }
+ }
+ else if (aTimeOut==CVwsEventTimer::EClientRequestTimeOut)
+ {
+ LOG2(CVwsLog::ELoud,_L("Activation event timer has passed client request time-out"));
+ if (iCompleteRequest==ECompleteRequest && iServer.SessionByThreadId(iClientThreadId)!=NULL)
+ {
+ LOG2(CVwsLog::ELoud,_L("Client request timed-out - silently completing request"));
+ iCompleteRequest=EDoNotCompleteRequest;
+ iMessage.Complete(KErrNone);
+ }
+ }
+ else if (aTimeOut==CVwsEventTimer::EIntermediateEventTimeOut)
+ {
+ if (iState==EActivationRequested)
+ {
+ iServer.BoostPriority(iServer.SessionByThreadId(iNewViewClientThreadId));
+ }
+ else if (iState==EDeactivationRequested)
+ {
+ iServer.BoostPriority(iServer.ActiveViewSession());
+ }
+ }
+
+ }
+
+void CVwsServerEvent_Activate::ProcessEventL()
+ {
+LOG4(CVwsLog::ELoud,_L("Starting to process activation of \"%x,%x\""),iViewIdToActivate.iAppUid.iUid,iViewIdToActivate.iViewUid.iUid);
+
+ RequestActivateNewView();
+ }
+
+#ifdef _DEBUG
+void CVwsServerEvent_Activate::RequestCompleted(TRequestType aType,TInt aError,const RMessage2&)
+#else
+void CVwsServerEvent_Activate::RequestCompleted(TRequestType /*aType*/,TInt aError,const RMessage2&)
+#endif // _DEBUG
+ {
+ switch (iState)
+ {
+ case EPending:
+ ASSERT(EFalse);
+ break;
+ case EActivationRequested:
+ ASSERT(aType==MVwsSessionObserver::EActivation);
+ LOG5(CVwsLog::ELoud,_L("Session request complete [activation event state: EActivationRequested; view to activate: \"%x,%x\", error: %d]"),iViewIdToActivate.iAppUid.iUid,iViewIdToActivate.iViewUid.iUid,aError);
+ if (aError)
+ {
+ if (aError==KErrViewWrongMode)
+ {
+ RequestActivateSystemDefaultView();
+ }
+ else
+ {
+ Complete(aError);
+ }
+ }
+ else
+ {
+ TVwsViewId viewToDeactivate(iServer.ActiveView());
+ // When an application whose view has to be activated is in background, the currently active view will not be deactivated.
+ // Note: Switching between different views of the same application must be followed by deactivation of old view
+ if ((iMessage.Int3() && !(iServer.IsAppInForeground())) && (viewToDeactivate.iAppUid != iViewIdToActivate.iAppUid))
+ {
+ LOG4(CVwsLog::ELoud,_L("\"%x,%x\", is activated at the background, so foreground view will not be deactivated"),iViewIdToActivate.iAppUid.iUid,iViewIdToActivate.iViewUid.iUid);
+ Complete(KErrNone);
+ }
+ else
+ {
+ RequestDeactivateOldView();
+ }
+ }
+ break;
+ case ESystemDefaultActivationRequested:
+ ASSERT(aType==MVwsSessionObserver::EActivation);
+ if (aError)
+ {
+ LOG3(CVwsLog::EQuiet,_L("Failed to activate system default view, error: %d"),aError);
+ RequestActivateSystemDefaultView();
+ }
+ else
+ {
+ RequestDeactivateOldView();
+ }
+ break;
+ case EDeactivationRequested:
+ ASSERT(aType==MVwsSessionObserver::EDeactivation);
+ LOG5(CVwsLog::ELoud,_L("Session request complete [activation event state: EDeactivationRequested; view to activate: \"%x,%x\", error: %d]"),iViewIdToActivate.iAppUid.iUid,iViewIdToActivate.iViewUid.iUid,aError);
+ iServer.HandleDeactivation(iServer.ActiveView(),iViewIdToActivate);
+ Complete(KErrNone);
+ break;
+ default:
+ case EAppStartRequested:
+ ASSERT(EFalse);
+ }
+
+// Disable unused parameter warning under release builds
+#pragma warning (disable: 4100)
+ }
+#pragma warning (default: 4100)
+
+void CVwsServerEvent_Activate::NowObserving(CVwsSessionEvent* aObserved)
+ {
+ if(iObserved)
+ {
+ iObserved->NullifyObserver();
+ }
+ iObserved = aObserved;
+ }
+
+void CVwsServerEvent_Activate::NullifyObserved()
+ {
+ iObserved = NULL;
+ }
+
+void CVwsServerEvent_Activate::HandleViewAdded(const TVwsViewId& aViewId, const TThreadId& aNewViewClientThreadId)
+ {
+ ASSERT(iState==EAppStartRequested);
+ if (aViewId.iAppUid==iViewIdToActivate.iAppUid
+ &&aViewId.iAppUid==aViewId.iViewUid)
+ {
+ iViewIdToActivate = aViewId;
+ }
+ if (aViewId==iViewIdToActivate)
+ {
+ iServer.SetViewAdditionObserver(NULL);
+
+ // set iNewViewClientThreadId to indicate that the new view should come from the session specified if possible
+ iNewViewClientThreadId = aNewViewClientThreadId;
+ RequestActivateNewView();
+ }
+ }
+
+void CVwsServerEvent_Activate::RequestActivateNewView()
+ {
+ CVwsSession* sessionWithNewView=iServer.SessionByThreadIdAndAppUid(iClientThreadId,iViewIdToActivate.iAppUid);
+
+ // iNewViewClientThreadId may have been set by the caller to indicate a preference between
+ // sessions with the same App Uid
+ if (sessionWithNewView==NULL && iNewViewClientThreadId!=TThreadId(0))
+ {
+ sessionWithNewView=iServer.SessionByThreadIdAndAppUid(iNewViewClientThreadId,iViewIdToActivate.iAppUid);
+ }
+
+ if (sessionWithNewView==NULL)
+ {
+ sessionWithNewView=iServer.SessionByUid(iViewIdToActivate.iAppUid);
+ }
+
+ if (sessionWithNewView==NULL || (sessionWithNewView && sessionWithNewView->IsExiting()))
+ {
+ RequestAppStart();
+ }
+ else
+ {
+ iNewViewClientThreadId=sessionWithNewView->ClientThreadId();
+ DoRequestActivateNewView(*sessionWithNewView);
+ }
+ }
+
+void CVwsServerEvent_Activate::RequestActivateSystemDefaultView()
+ {
+ iServer.GetSystemDefaultView(iViewIdToActivate);
+ CVwsSession* sessionWithSystemDefaultView=iServer.SessionByUid(iViewIdToActivate.iAppUid);
+ // need an empty client message
+ CVwsClientMessage* emptyClientMessage=CVwsClientMessage::New();
+ if (emptyClientMessage==NULL)
+ {
+ Complete(KErrNoMemory);
+ }
+
+ if (sessionWithSystemDefaultView)
+ {
+ iNewViewClientThreadId=sessionWithSystemDefaultView->ClientThreadId();
+ RequestClientActivation(*sessionWithSystemDefaultView,emptyClientMessage,ESystemDefaultActivationRequested);
+ }
+ else if (iThreadWatcher==NULL)
+ {
+ // app died
+ StopActivationProfile();
+ ASSERT(iState!=EAppStartRequested); // Already asked to start app once.
+ StartAppStartProfile();
+ iServer.SetViewAdditionObserver(this);
+ TThreadId appThreadId;
+ iClientMessage = emptyClientMessage;
+ TInt err=iServer.StartApp(iViewIdToActivate.iAppUid,appThreadId);
+ if (err)
+ {
+ LOG3(CVwsLog::EQuiet,_L("App start FAILED with %d"),err);
+ Complete(err);
+ }
+ else
+ {
+ iState=EAppStartRequested;
+ }
+ }
+ else
+ {
+ delete emptyClientMessage;
+ }
+ }
+
+void CVwsServerEvent_Activate::RequestAppStart()
+ {
+ ASSERT(iState!=EAppStartRequested); // Already asked to start app once.
+ StartAppStartProfile();
+ iServer.SetViewAdditionObserver(this);
+ TThreadId appThreadId;
+ TInt err=iServer.StartApp(iViewIdToActivate.iAppUid,appThreadId);
+ if (err)
+ {
+ LOG3(CVwsLog::EQuiet,_L("App start FAILED with %d"),err);
+ Complete(err);
+ }
+ else
+ {
+ iState=EAppStartRequested;
+ err=iThreadWatcher->StartWatching(appThreadId,TCallBack(&AppThreadWatcherCallBack,this));
+ if (err)
+ {
+ LOG3(CVwsLog::EQuiet,_L("App start FAILED with %d"),err);
+ Complete(err);
+ }
+ }
+ }
+
+TInt CVwsServerEvent_Activate::AppThreadWatcherCallBack(TAny* aPtr)
+ // static
+ {
+ LOG2(CVwsLog::EQuiet,_L("App start FAILED with app client thread death"));
+ REINTERPRET_CAST(CVwsServerEvent_Activate*,aPtr)->Complete(KErrCancel);
+ return 0;
+ }
+
+TInt CVwsServerEvent_Activate::RequestClientActivation(CVwsSession& aSession,CVwsClientMessage* aClientMessage,TState aNewState)
+ {
+ TRAPD(error,
+ aSession.RequestClientActivationL(*this,iViewIdToActivate,iServer.ActiveView(),aClientMessage,iThreadOfClientInitiatingViewSwitch));
+ if (error)
+ {
+ LOG3(CVwsLog::ELoud,_L("RequestClientActivationL FAILED with %d - unable to activate new view"),error);
+ if(aSession.IsLeaveAfterOwnershipTaken())
+ {
+ aSession.ResetLeaveAfterOwnershipTaken();
+ iClientMessage=NULL;
+ }
+ Complete(error);
+ }
+ else
+ {
+ iClientMessage=NULL; // The session is now the owner of the custom message buf.
+ iState=aNewState;
+ }
+ return error;
+ }
+
+void CVwsServerEvent_Activate::CustomCrossCheck(CVwsSession& aSessionWithNewView)
+ {
+ if (iClientMessage->iMessageId == KUidCustomCrossCheck && iClientMessage->iMessage == NULL)
+ {
+ iClientMessage->iMessageId = KNullUid;
+ TVwsViewId viewId;
+ if (aSessionWithNewView.GetTopView(viewId) == KErrNone)
+ {
+#ifdef _DEBUG
+ if (iViewIdToActivate != viewId)
+ {
+ LOG4(CVwsLog::ELoud,_L("Cross check to \"%x,%x\""), viewId.iAppUid.iUid, viewId.iViewUid.iUid);
+ }
+#endif //_DEBUG
+ iViewIdToActivate = viewId;
+ iClientMessage->iMessageId = KNullUid;
+ }
+ }
+ }
+
+void CVwsServerEvent_Activate::DoRequestActivateNewView(CVwsSession& aSessionWithNewView)
+ {
+ StopAppStartProfile();
+ delete iThreadWatcher;
+ iThreadWatcher=NULL;
+
+ iEventTimer->Start(this,EFalse);
+
+ if (iClientMessage)
+ {
+ CustomCrossCheck(aSessionWithNewView);
+ }
+
+ if (iServer.CheckViewExists(aSessionWithNewView.ClientThreadId(),iViewIdToActivate)==KErrNotFound)
+ {
+ LOG4(CVwsLog::EQuiet,_L("Aborting activation - view \"%x,%x\" not found"),iViewIdToActivate.iAppUid.iUid,iViewIdToActivate.iViewUid.iUid);
+ Complete(KErrNotFound);
+ return;
+ }
+
+ StartActivationProfile();
+ RequestClientActivation(aSessionWithNewView,iClientMessage,EActivationRequested);
+ }
+
+void CVwsServerEvent_Activate::RequestDeactivateOldView()
+ {
+ StopActivationProfile();
+ TVwsViewId viewToDeactivate(iServer.ActiveView());
+ CVwsSession* sessionWithOldView=iServer.ActiveViewSession();
+ CVwsSession* sessionWithNewView=iServer.SessionByThreadIdAndAppUid(iClientThreadId,iViewIdToActivate.iAppUid);
+
+ //If the client that is requesting view activation is same as the client which has the new active view, ie, reactivation of same view,
+ //then the session with new active view is taken.
+ if (sessionWithNewView==NULL && iNewViewClientThreadId!=TThreadId(0))
+ {
+ sessionWithNewView=iServer.SessionByThreadIdAndAppUid(iNewViewClientThreadId,iViewIdToActivate.iAppUid);
+ }
+
+ if (sessionWithNewView==NULL)
+ {
+ sessionWithNewView=iServer.SessionByUid(iViewIdToActivate.iAppUid);
+ }
+
+ if (viewToDeactivate.iAppUid.iUid && (viewToDeactivate != iViewIdToActivate || sessionWithOldView != sessionWithNewView))
+ {
+ if (sessionWithOldView==NULL)
+ { // Session with old view has disconnected, so abort deactivation.
+ LOG4(CVwsLog::ELoud,_L("Aborting deactivation of view \"%x,%x\" - client disconnected"),viewToDeactivate.iAppUid.iUid,viewToDeactivate.iViewUid.iUid);
+ Complete(KErrNone);
+ }
+ else
+ {
+ TBool differentInstanceOfSameApp = EFalse;
+ if (viewToDeactivate.iAppUid == iViewIdToActivate.iAppUid && sessionWithOldView != sessionWithNewView)
+ differentInstanceOfSameApp = ETrue;
+ TRAPD(err,sessionWithOldView->RequestClientDeactivationL(*this,viewToDeactivate,iViewIdToActivate, differentInstanceOfSameApp));
+ if (err)
+ {
+ LOG3(CVwsLog::ELoud,_L("RequestClientDeactivationL FAILED with %d - unable to deactivate currently active view"),err);
+ Complete(err);
+ }
+ else
+ {
+ iState=EDeactivationRequested;
+ }
+ }
+ }
+ else
+ {
+ // No view to deactivate, so complete.
+ LOG2(CVwsLog::ELoud,_L("Aborting deactivation - no view to deactivate"));
+ Complete(KErrNone);
+ }
+ }
+
+void CVwsServerEvent_Activate::Complete(TInt aError)
+ {
+ LOG5(CVwsLog::ELoud,_L("Completing activation of \"%x,%x\" with %d"),iViewIdToActivate.iAppUid,iViewIdToActivate.iViewUid,aError);
+ if (aError==KErrNone && TUint(iNewViewClientThreadId)!=0)
+ {
+ iServer.HandleActivation(iViewIdToActivate,iServer.ActiveView());
+ TVwsViewId viewToDeactivate(iServer.ActiveView());
+ // The active active viewid will be set in the server when
+ // 1. Application whose view is getting activated is in foreground
+ // 2. Switching between different views of the same application
+ if(iServer.IsAppInForeground() || (iViewIdToActivate.iAppUid == viewToDeactivate.iAppUid))
+ {
+ iServer.SetActiveView(iNewViewClientThreadId,iViewIdToActivate);
+ }
+ }
+ iServer.SetViewAdditionObserver(NULL);
+ if ((iCompleteRequest==ECompleteRequest) && (iServer.SessionByThreadId(iClientThreadId)!=NULL))
+ {
+ if(!iMessage.IsNull())
+ {
+ iMessage.Complete(aError);
+ }
+ }
+#ifdef __DO_LOGGING__
+ else if (iCompleteRequest==ECompleteRequest)
+ {
+ LOG2(CVwsLog::ELoud,_L("Client requesting activation not current - completing activation will not complete message handle"));
+ }
+#endif
+ ReportEventProcessed();
+ }
+
+void CVwsServerEvent_Activate::HandleSessionRemoval(const TThreadId& aClientThreadId)
+ {
+ TThreadId threadId(aClientThreadId);
+ TBool iCancel=EFalse;
+ if (iState==EDeactivationRequested)
+ {
+ CVwsSession* sessionWithActiveView=iServer.ActiveViewSession();
+ if (sessionWithActiveView && threadId==sessionWithActiveView->ClientThreadId())
+ {
+ LOG2(CVwsLog::ELoud,_L("Client with active view removed while session deactivation request outstanding"));
+ iCancel=ETrue;
+ }
+#ifdef __DO_LOGGING__
+ else if (threadId==iNewViewClientThreadId)
+ {
+ LOG2(CVwsLog::ELoud,_L("Client with new view removed while session deactivation request outstanding - waiting for deactivation to complete"));
+ }
+#endif
+ }
+ else if (threadId==iNewViewClientThreadId)
+ {
+ LOG2(CVwsLog::ELoud,_L("Client with new view removed"));
+ iCancel=ETrue;
+ }
+ if (iCancel)
+ {
+ LOG2(CVwsLog::ELoud,_L("Client removal means activation event will not complete normally - activation cancelled"));
+ Complete(KErrCancel);
+ }
+ }
+
+void CVwsServerEvent_Activate::StartAppStartProfile()
+ {
+ ASSERT(iWhichProfile==ENone);
+ iWhichProfile=EAppStart;
+ }
+
+void CVwsServerEvent_Activate::StopAppStartProfile()
+ {
+ if (iWhichProfile==EAppStart)
+ {
+ iWhichProfile=ENone;
+ }
+ }
+
+void CVwsServerEvent_Activate::StartActivationProfile()
+ {
+ ASSERT(iWhichProfile==ENone);
+ iWhichProfile=EActivation;
+ }
+
+void CVwsServerEvent_Activate::StopActivationProfile()
+ {
+ if (iWhichProfile==EActivation)
+ {
+ iWhichProfile=ENone;
+ }
+ }
+
+
+//
+// CVwsServerEvent_ScreenDeviceChanged.
+//
+
+CVwsServerEvent_ScreenDeviceChanged::CVwsServerEvent_ScreenDeviceChanged(CVwsServer& aServer,CVwsEventQueue& aQueue,CVwsThreadWatcher* aThreadWatcher,CVwsEventTimer* aEventTimer)
+ : CVwsServerEvent_Activate(aServer,CVwsServerEvent::ERejectPairs,aQueue,KNullViewId,NULL,RMessage2(),0,EDoNotCompleteRequest,aThreadWatcher,aEventTimer,RThread()),
+ iThreadWatcher(aThreadWatcher) ,iEventTimer(aEventTimer)
+ {
+ }
+
+CVwsServerEvent_ScreenDeviceChanged::~CVwsServerEvent_ScreenDeviceChanged()
+ {
+ }
+
+void CVwsServerEvent_ScreenDeviceChanged::ProcessEventL()
+ {
+ LOG2(CVwsLog::ELoud,_L("Started processing of screen device changed event"));
+ if(iServer.ActiveViewSession()!=NULL)
+ {
+ TThreadId activeClientThread = iServer.ActiveViewSession()->ClientThreadId();
+ TRAPD(err,iThreadWatcher->StartWatching(activeClientThread,TCallBack(&AppThreadWatcherCallBack,this)));
+ iEventTimer->Start(this,ETrue);
+ if (err)
+ {
+ Complete(err);
+ }
+ }
+ TVwsViewId activeView(iServer.ActiveView());
+ if (activeView.iAppUid.iUid)
+ {
+ RequestChangeNotification();
+ }
+ else
+ {
+ LOG2(CVwsLog::ELoud,_L("No active view, so ignoring screen device changed event"));
+ Complete(KErrNone);
+ }
+ }
+TInt CVwsServerEvent_ScreenDeviceChanged::AppThreadWatcherCallBack(TAny* aPtr)
+ // static
+ {
+ LOG2(CVwsLog::ELoud,_L("Client thread died while processing Screendevice change event"));
+ REINTERPRET_CAST(CVwsServerEvent_ScreenDeviceChanged*,aPtr)->Complete(KErrCancel);
+ return 0;
+ }
+
+void CVwsServerEvent_ScreenDeviceChanged::RequestCompleted(TRequestType aType,TInt aError,const RMessage2& aMessage)
+ {
+ switch (iScreenDeviceNotificationState)
+ {
+ case EPending:
+ ASSERT(EFalse);
+ break;
+ case EScreenDeviceChangeNotificationRequested:
+ {
+ ASSERT(aType==EScreenDeviceChangeNotification);
+ TRAPD(err,RequestActivationAsRequiredL(aMessage));
+ if (err)
+ {
+ LOG3(CVwsLog::ELoud,_L("CVwsClientMessage::NewL FAILED with %d, unable to activate view in responce to screen device changed event"),err);
+ RequestActivateSystemDefaultView();
+ }
+ }
+ break;
+ case EViewActivationRequested:
+ case EDefaultSystemViewActivationRequested:
+ CVwsServerEvent_Activate::RequestCompleted(aType,aError,aMessage);
+ break;
+ default:
+ ASSERT(EFalse);
+ }
+
+// Disable unused parameter warning under release builds
+#pragma warning (disable: 4100)
+ }
+#pragma warning (default: 4100)
+
+void CVwsServerEvent_ScreenDeviceChanged::NowObserving(CVwsSessionEvent* aObserved)
+ {
+ if(iObserved)
+ {
+ iObserved->NullifyObserver();
+ }
+ iObserved = aObserved;
+ }
+
+void CVwsServerEvent_ScreenDeviceChanged::NullifyObserved()
+ {
+ iObserved = NULL;
+ }
+
+void CVwsServerEvent_ScreenDeviceChanged::RequestChangeNotification()
+ {
+ const TVwsViewId activeView(iServer.ActiveView());
+ CVwsSession* sessionWithActiveView=iServer.ActiveViewSession();
+ ASSERT(sessionWithActiveView); // Session with active view MUST be found.
+ TRAPD(err,sessionWithActiveView->RequestScreenDeviceChangeNotificationL(*this,activeView));
+ if (err)
+ {
+ LOG3(CVwsLog::ELoud,_L("RequestScreenDeviceChangeNotificationL FAILED with %d, unable to notify screen device changed"),err);
+ iScreenDeviceNotificationState=EDefaultSystemViewActivationRequested;
+ RequestActivateSystemDefaultView();
+ }
+ else
+ {
+ iScreenDeviceNotificationState=EScreenDeviceChangeNotificationRequested;
+ }
+ }
+
+void CVwsServerEvent_ScreenDeviceChanged::RequestActivationAsRequiredL(const RMessage2& aMessage)
+ {
+ TVwsViewIdAndMessageBuf viewToActivateBuf;
+ aMessage.ReadL(2,viewToActivateBuf);
+ TVwsViewIdAndMessage viewToActivate(viewToActivateBuf());
+ iViewIdToActivate=viewToActivate.iViewId;
+ if (iViewIdToActivate==TVwsViewId())
+ { // Null view id, so ignore.
+ Complete(KErrNone);
+ }
+ else if (iServer.IsViewActive(iViewIdToActivate))
+ {
+ LOG4(CVwsLog::ELoud,_L("View \"%x,%x\" already active - aborting activation"),iViewIdToActivate.iAppUid.iUid,iViewIdToActivate.iViewUid.iUid);
+ Complete(KErrNone);
+ }
+ else
+ {
+ iClientMessage=CVwsClientMessage::NewL(viewToActivate.iCustomMessageId,viewToActivate.iCustomMessageLength,aMessage,3);
+ iScreenDeviceNotificationState=EViewActivationRequested;
+
+ // Setting the iNewViewClientThreadId here indicates that if there are multiple sessions
+ // with the same app uid and we are switching views within one app then the one with the
+ // currently active view should be preferred
+ iNewViewClientThreadId = iServer.ActiveViewSession()->ClientThreadId();
+ RequestActivateNewView();
+ }
+ }
+
+#ifdef _DEBUG
+void CVwsServerEvent_ScreenDeviceChanged::Complete(TInt aError)
+#else
+void CVwsServerEvent_ScreenDeviceChanged::Complete(TInt /*aError*/)
+#endif // _DEBUG
+ {
+ LOG3(CVwsLog::ELoud,_L("Completed processing of screen device changed event with %d"),aError);
+ ReportEventProcessed();
+
+// Disable unused parameter warning under release builds
+#pragma warning (disable: 4100)
+ }
+#pragma warning (default: 4100)
+
+void CVwsServerEvent_ScreenDeviceChanged::HandleAddedToQueue()
+ {
+ // display opaque intercepting window
+ iServer.MakeInterceptingWindowVisibleAndUpdateScreen();
+ }
+
+void CVwsServerEvent_ScreenDeviceChanged::HandleSessionRemoval(const TThreadId& aClientThreadId)
+ {
+ switch (iScreenDeviceNotificationState)
+ {
+ case EScreenDeviceChangeNotificationRequested:
+ {
+ CVwsSession* sessionWithActiveView=iServer.ActiveViewSession();
+ if(sessionWithActiveView && aClientThreadId==sessionWithActiveView->ClientThreadId())
+ {
+ LOG2(CVwsLog::ELoud,_L("Client with active view removed while screen device change request outstanding"));
+ RequestActivateSystemDefaultView();
+ iScreenDeviceNotificationState=EDefaultSystemViewActivationRequested;
+ }
+ }
+ case EViewActivationRequested:
+ case EDefaultSystemViewActivationRequested:
+ CVwsServerEvent_Activate::HandleSessionRemoval(aClientThreadId);
+ break;
+ case EPending:
+ default:
+ break;
+ }
+}
+
+void CVwsServerEvent_ScreenDeviceChanged::HandleTimeOut(CVwsEventTimer::TTimeOut /*aTimeOut*/)
+ {
+ LOG2(CVwsLog::ELoud,_L("CVwsServerEvent_ScreenDeviceChanged view event timer has passed client request time-out"));
+ switch (iScreenDeviceNotificationState)
+ {
+ case EScreenDeviceChangeNotificationRequested:
+ Complete(KErrNone);
+ break;
+
+ case EViewActivationRequested:
+ case EDefaultSystemViewActivationRequested:
+ CVwsServerEvent_Activate::HandleTimeOut(CVwsEventTimer::EClientRequestTimeOut);
+ break;
+
+ case EPending:
+ default:
+ break;
+ }
+ }
+
+//
+// CVwsServerEvent_DeactivateActiveView.
+//
+
+CVwsServerEvent_DeactivateActiveView::CVwsServerEvent_DeactivateActiveView(CVwsServer& aServer,CVwsEventQueue& aQueue,const RMessage2& aMessage,const TThreadId& aClientThreadId,TVwsCompleteRequest aCompleteRequest,CVwsEventTimer* aEventTimer)
+ : CVwsServerEvent(aServer,CVwsServerEvent::ENormal,aQueue),
+ iMessage(aMessage),
+ iClientThreadId(aClientThreadId),
+ iCompleteRequest(aCompleteRequest),
+ iEventTimer(aEventTimer)
+ {
+ }
+
+CVwsServerEvent_DeactivateActiveView::~CVwsServerEvent_DeactivateActiveView()
+ {
+ delete iEventTimer;
+ }
+
+void CVwsServerEvent_DeactivateActiveView::ProcessEventL()
+ {
+ LOG2(CVwsLog::ELoud,_L("Started processing of deactivate active view event"));
+ const TVwsViewId activeView(iServer.ActiveView());
+
+ //Check if the Cross Check UID is set, if it is then enable customised behaviour here
+ if(iServer.CrossCheckUid()!=KNullUid)
+ {
+ CVwsSession* self = iServer.SessionByThreadId(iClientThreadId);
+ CVwsSession* active = iServer.ActiveViewSession();
+ if (self != active)
+ {
+ LOG2(CVwsLog::ELoud,_L("Requested session does not have Active view, so ignoring deactivate active view event"));
+ if(iCompleteRequest==ECompleteRequest&& iServer.SessionByThreadId(iClientThreadId)!=NULL)
+ {
+ iMessage.Complete(KErrNone);
+ }
+ ReportEventProcessed();
+ return;
+ }
+ }
+
+ if (activeView.iAppUid.iUid)
+ {
+ TRAPD(err,RequestDeactivationL());
+ if (err)
+ {
+ Complete(err);
+ }
+ }
+ else
+ {
+ LOG2(CVwsLog::ELoud,_L("No active view, so ignoring deactivate active view event"));
+ Complete(KErrNone);
+ }
+ }
+
+#ifdef _DEBUG
+void CVwsServerEvent_DeactivateActiveView::RequestCompleted(TRequestType aType,TInt,const RMessage2&)
+#else
+void CVwsServerEvent_DeactivateActiveView::RequestCompleted(TRequestType /*aType*/,TInt,const RMessage2&)
+#endif // _DEBUG
+ {
+ switch (iState)
+ {
+ case EPending:
+ ASSERT(EFalse);
+ break;
+ case EDeactivationRequested:
+ ASSERT(aType==EDeactivation);
+ Complete(KErrNone);
+ break;
+ default:
+ ASSERT(EFalse);
+ }
+
+// Disable unused parameter warning under release builds
+#pragma warning (disable: 4100)
+ }
+#pragma warning (default: 4100)
+
+void CVwsServerEvent_DeactivateActiveView::NowObserving(CVwsSessionEvent* aObserved)
+ {
+ if(iObserved)
+ {
+ iObserved->NullifyObserver();
+ }
+ iObserved = aObserved;
+ }
+
+void CVwsServerEvent_DeactivateActiveView::NullifyObserved()
+ {
+ iObserved = NULL;
+ }
+
+void CVwsServerEvent_DeactivateActiveView::RequestDeactivationL()
+ {
+ ASSERT(iState==EPending);
+
+ iEventTimer->Start(this,EFalse);
+
+ iActiveView=iServer.ActiveView();
+ CVwsSession* sessionWithActiveView=iServer.ActiveViewSession();
+ // If the session with currently active view is NULL, then the deactivation request is
+ // completed with KErrNotFound and the previously active view is activated.
+ if (sessionWithActiveView)
+ {
+ //EFalse always because the deactivation of view is requested by the application directly
+ sessionWithActiveView->RequestClientDeactivationL(*this,iActiveView,TVwsViewId(),EFalse);
+ iState=EDeactivationRequested;
+ }
+ else
+ {
+ LOG2(CVwsLog::ELoud,_L("Session with active view is NULL, so completing the deactivation request with KErrNotFound"));
+ User::Leave(KErrNotFound);
+ }
+ }
+
+void CVwsServerEvent_DeactivateActiveView::Complete(TInt aErr)
+ {
+ LOG3(CVwsLog::ELoud,_L("Completing deactivate active view event with %d"),aErr);
+ if (aErr)
+ {
+ iServer.HandleDeactivation(iActiveView,TVwsViewId());
+ }
+ iServer.ClearActiveView();
+ if(iCompleteRequest==ECompleteRequest&& iServer.SessionByThreadId(iClientThreadId)!=NULL)
+ {
+ iMessage.Complete(aErr);
+ }
+ ReportEventProcessed();
+ }
+
+void CVwsServerEvent_DeactivateActiveView::HandleSessionRemoval(const TThreadId& aClientThreadId)
+ {
+ TThreadId threadId(aClientThreadId);
+ if (iState==EDeactivationRequested)
+ {
+ CVwsSession* sessionWithActiveView=iServer.ActiveViewSession();
+ if (sessionWithActiveView && threadId==sessionWithActiveView->ClientThreadId())
+ {
+ LOG2(CVwsLog::ELoud,_L("Client with active view removed while session deactivation request outstanding"));
+ LOG2(CVwsLog::ELoud,_L("Client removal means deactivate active view event will not complete normally - deactivation cancelled"));
+ Complete(KErrCancel);
+ }
+ }
+ }
+
+void CVwsServerEvent_DeactivateActiveView::HandleTimeOut(CVwsEventTimer::TTimeOut aTimeOut)
+ {
+ if (aTimeOut==CVwsEventTimer::EServerEventTimeOut && iServer.IsServerEventTimeOutEnabled())
+ {
+ if (iState==EDeactivationRequested)
+ {
+ LOG3(CVwsLog::ENormal,_L("PANIC CLIENT \"%x\" for timing out activation view event - deactivation request was not completed"),iServer.ActiveView().iAppUid.iUid);
+ CVwsSession* sessionWithActiveView=iServer.ActiveViewSession();
+ if (sessionWithActiveView)
+ {
+ if(iServer.IsPriorityBoostBeforePanicEnabled())
+ {
+ if (iServer.InitializationFinished())
+ {
+ sessionWithActiveView->PanicClient(EVwsViewDeactivationEventTimeOut);
+ }
+ }
+ else
+ {
+ sessionWithActiveView->PanicClient(EVwsViewDeactivationEventTimeOut);
+ }
+ }
+ }
+ else
+ {
+ LOG4(CVwsLog::EQuiet,_L("Aborting deactivation of active view \"%x,%x\" - server event processing timed-out"),iServer.ActiveView().iAppUid.iUid,iServer.ActiveView().iViewUid.iUid);
+ Complete(KErrCancel);
+ }
+ }
+ else if (aTimeOut==CVwsEventTimer::EClientRequestTimeOut)
+ {
+ LOG2(CVwsLog::ELoud,_L("Deactivate active view event timer has passed client request time-out"));
+ if (iCompleteRequest==ECompleteRequest && iServer.SessionByThreadId(iClientThreadId)!=NULL)
+ {
+ LOG2(CVwsLog::ELoud,_L("Client request timed-out - silently completing request"));
+ iCompleteRequest=EDoNotCompleteRequest;
+ iMessage.Complete(KErrNone);
+ }
+ }
+ else if (aTimeOut==CVwsEventTimer::EIntermediateEventTimeOut)
+ {
+ if (iState==EDeactivationRequested)
+ {
+ iServer.BoostPriority(iServer.ActiveViewSession());
+ }
+ }
+ }
+
+//
+// CVwsServerEvent_AppStart.
+//
+
+CVwsServerEvent_AppStart::CVwsServerEvent_AppStart(CVwsServer& aServer,CVwsEventQueue& aQueue,const RMessage2& aMessage,const TUid& aAppToStart,CVwsThreadWatcher* aThreadWatcher)
+ : CVwsServerEvent(aServer,CVwsServerEvent::ENormal,aQueue),iAppToStart(aAppToStart),iMessage(aMessage),iThreadWatcher(aThreadWatcher)
+ {
+ }
+
+CVwsServerEvent_AppStart::~CVwsServerEvent_AppStart()
+ {
+ delete iThreadWatcher;
+ }
+
+void CVwsServerEvent_AppStart::ProcessEventL()
+ {
+ LOG2(CVwsLog::ELoud,_L("Started processing of app start event"));
+
+ iSessionWithNewApp=iServer.SessionByUid(iAppToStart);
+ if (iSessionWithNewApp==NULL)
+ {
+ RequestAppStart();
+ }
+ else
+ {
+ Complete(KErrNone);
+ }
+ }
+
+void CVwsServerEvent_AppStart::HandleViewAdded(const TVwsViewId& aViewId, const TThreadId& aNewViewClientThreadId)
+ {
+ ASSERT(iState==EAppStartRequested);
+
+ if (aViewId.iAppUid==iAppToStart)
+ {
+ delete iThreadWatcher;
+ iThreadWatcher=NULL;
+ iServer.SetViewAdditionObserver(NULL);
+ ASSERT(iSessionWithNewApp==NULL);
+ iSessionWithNewApp=iServer.SessionByThreadIdAndAppUid(aNewViewClientThreadId,aViewId.iAppUid);
+ ASSERT(iSessionWithNewApp);
+ Complete(KErrNone);
+ }
+ }
+
+void CVwsServerEvent_AppStart::RequestAppStart()
+ {
+ iServer.SetViewAdditionObserver(this);
+ TThreadId appThreadId;
+ TInt err=iServer.StartApp(iAppToStart,appThreadId);
+ if (err)
+ {
+ LOG3(CVwsLog::EQuiet,_L("App start FAILED with %d"),err);
+ Complete(err);
+ }
+ else
+ {
+ iState=EAppStartRequested;
+ err=iThreadWatcher->StartWatching(appThreadId,TCallBack(&AppThreadWatcherCallBack,this));
+ if (err)
+ {
+ LOG3(CVwsLog::EQuiet,_L("App start FAILED with %d"),err);
+ Complete(err);
+ }
+ }
+ }
+
+TInt CVwsServerEvent_AppStart::AppThreadWatcherCallBack(TAny* aPtr)
+ // static
+ {
+ LOG2(CVwsLog::EQuiet,_L("App start FAILED with app client thread death"));
+ REINTERPRET_CAST(CVwsServerEvent_AppStart*,aPtr)->Complete(KErrCancel);
+ return 0;
+ }
+
+void CVwsServerEvent_AppStart::Complete(TInt aErr)
+ {
+ LOG3(CVwsLog::EQuiet,_L("App start event completed with %d"),aErr);
+ iServer.SetViewAdditionObserver(NULL);
+ iMessage.Complete(aErr);
+ ReportEventProcessed();
+ }