graphicstest/uibench/src/tmultiptreventhandlingperf.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/src/tmultiptreventhandlingperf.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,523 @@
+// Copyright (c) 2008-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:
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Symbian test code 
+*/
+
+#include "tmultiptreventhandlingperf.h"
+#include <hal.h>
+
+_LIT(KPerformanceTimingChunk, "PerformanceTimingChunk");
+
+// Number of iterations for eventset
+const TInt KNumOfIterations = 100;
+
+// Maximum descriptor length for results
+const TInt KMaxDescLength = 528;
+
+// Static variables used for synchronisation between threads
+GLDEF_D TInt NumOfEventsAdded = 0;
+GLDEF_D RMutex Mutex;
+GLDEF_D RCondVar ConVar;
+
+void MultiPtrPerfPanic(TInt aPanic)
+	{
+	User::Panic(_L("MultiPterEventHanldingPerformancePanic"), aPanic);
+	}
+
+// This function opens the chunk and adds the failure description followed by '*'
+TInt CMultiPtrPerfTestControl::Failed(TPoint3D aExp3DPoint, TPoint3D aActual3DPoint, TInt aErrorCode, TInt aExpPtrNum, TInt aActPtrNum)
+	{
+	TInt ret = iChunk.OpenGlobal(KPerformanceTimingChunk, ETrue);
+	if (ret != KErrNone)
+		{
+		return ret;
+		}
+	TUint8* desPtr = iChunk.Base() + iChunkOffset;
+	TPtr8 ptrDes(desPtr, 0, KMaxDescLength);
+	
+	TBuf<80> buf;
+	if (aExpPtrNum != aActPtrNum)
+		{
+		_LIT(KFailedPointerNum, "Failed Expected Pointer Num = %d Actual Pointer Num = %d*");
+		buf.AppendFormat(KFailedPointerNum, aExpPtrNum, aActPtrNum);
+		ptrDes.Append(buf);
+		} 
+	else if (aErrorCode != KErrNone)
+		{
+		_LIT(KFailedErrorCode, "Failed Errorcode = %d*");
+		buf.AppendFormat(KFailedErrorCode, aErrorCode);
+		ptrDes.Append(buf);
+		}
+	else
+		{
+		_LIT(KFailedWrongCoord, "Failed Coordinates Expected = [%d, %d, %d] Actual = [%d, %d, %d]*");
+		buf.AppendFormat(KFailedWrongCoord, aExp3DPoint.iX, aExp3DPoint.iY, aExp3DPoint.iZ, aActual3DPoint.iX, aActual3DPoint.iY, aActual3DPoint.iZ);
+		ptrDes.Append(buf);
+		}
+	
+	iChunk.Close();
+	return ret;
+	}
+
+// This function opens the chunk and adds a pointer event not supported message followed by '#'
+TInt CMultiPtrPerfTestControl::PointerEventsNotSupported()
+    {
+    iPointerEventNotSupported = ETrue;
+    TInt ret = iChunk.OpenGlobal(KPerformanceTimingChunk, ETrue);
+        if (ret != KErrNone)
+            {
+            return ret;
+            }
+    TUint8* desPtr = iChunk.Base() + iChunkOffset;
+    TPtr8 ptrDes(desPtr, 0, KMaxDescLength);
+    TBuf<80> buf;
+    _LIT(KPointerEventsNotSupported, "Test Skipped As Pointer Events Are Not Supported By This Configuration#");
+    buf.AppendFormat(KPointerEventsNotSupported);
+    ptrDes.Append(buf);
+    iChunk.Close();
+    return ret;
+    }
+
+// This function calulates the average latency, opens the chunk and appends
+// the same in descriptor form. Then close the child thread and calls function 
+// for creating new thread for events. 
+// If all the events have been tested then stops the tests
+// by calling active CActiveScheduler::Stop. 
+TInt CMultiPtrPerfTestControl::CalculateLatencyAndStartThread()
+	{
+	TInt ret = KErrNone;
+	switch (iPtrAppUi->TestCaseNum())
+		{
+		case 1:
+		case 5:
+		case 9:
+		case 13:	
+			iAverageLatency = iLatency/(4*KNumOfIterations);
+			break;
+		case 2:
+		case 6:
+		case 10:
+		case 14:
+			iAverageLatency = iLatency/(8*KNumOfIterations);
+			break;
+		case 3:
+		case 7:
+		case 11:
+		case 15:
+			iAverageLatency = iLatency/(16*KNumOfIterations);
+			break;
+		case 4:
+		case 8:
+		case 12:
+		case 16:
+			iAverageLatency = iLatency/(32*KNumOfIterations);
+			break;
+		default:
+			MultiPtrPerfPanic(EMultiPtrPerfPanicWrongTest);
+		}
+
+	ret = iChunk.OpenGlobal(KPerformanceTimingChunk, ETrue);
+	if (ret != KErrNone)
+		{
+		return ret;
+		}
+	TUint8* desPtr = iChunk.Base() + iChunkOffset;
+	TPtr8 ptrDes(desPtr, iLatLenInLetters, KMaxDescLength);
+	
+	TBuf<66> buf;
+	buf.Num(iAverageLatency);
+	buf.Append(',');
+	ptrDes.Append(buf);
+	
+	// reset the iLatency for next set of test
+	iLatency = 0;	
+	
+	// For writing the next latency in chunk memory
+	iLatLenInLetters = ptrDes.Length();
+	
+	iChunk.Close();
+	
+	// Before calling the thread Function close the current thread and then call the function
+	// here when we kill the child thread it releases both mutex and condvar that it holds
+	iPtrAppUi->ChildThread().Kill(KErrNone);
+	iPtrAppUi->ChildThread().Close();
+	
+	if (iPtrAppUi->TestCaseNum() == 16)
+		{
+		// It it is the last test case then stop the active scheduler
+		CActiveScheduler::Stop();
+		return ret;
+		}
+	else
+		{
+		return iPtrAppUi->CreateEventSimulatingThreads();
+		}
+	}
+
+// This function is called by Cone whenever a event is outstanding
+// Here we check if the sent event is same as the expected event in array.
+// Then resumes the thread for next set of events. When all the events are completed
+// calls CalculateLatencyAndStartThread
+void CMultiPtrPerfTestControl::HandlePointerEventL(const TPointerEvent& aPointerEvent)
+	{
+    ASSERT(!iPointerEventNotSupported);
+	// The event that is received is (0,0,0) then it is the first event that the test code is sending
+	const TAdvancedPointerEvent* advancedPointerEvent = aPointerEvent.AdvancedPointerEvent();
+	
+	if (iPtrAppUi->TestCaseNum() == 0)
+		{
+		if (advancedPointerEvent->PointerNumber() == 0 && advancedPointerEvent->Position3D() == TPoint3D())
+			{
+			iPtrAppUi->CreateEventSimulatingThreads();
+			return;
+			}
+		else
+			{
+			return;	// ignore other events before starting the tests
+			}
+		}
+
+	// Get the current time.
+	// Subtract from the test start time.
+	TTime currentTime;
+	currentTime.UniversalTime();
+	TInt64 curTime64 = currentTime.Int64();
+	TInt timeSinceTestStart = curTime64 - iPtrAppUi->TestStartTime();
+	
+	// Get the event, get the time stored in Z corodinate
+	// Then subtract the calculated time from Z coordinate
+	iLatency += timeSinceTestStart - advancedPointerEvent->ProximityAndPressure(); 
+	
+	// Get the current event from buffer and compare it with got event
+	TAdvancedPointerEvent expectedPtrEvent;
+	if(0 == iEventBuffer.Remove(&expectedPtrEvent))
+		{
+		iPtrAppUi->Failed(TPoint3D(), TPoint3D(), KErrNotFound);
+		return;
+		}
+	
+	// Here Z corodinate is not checked.
+	if (expectedPtrEvent.iPosition != advancedPointerEvent->iPosition)
+		{
+		iPtrAppUi->Failed(expectedPtrEvent.Position3D(), advancedPointerEvent->Position3D(), KErrNone);
+		return;
+		}
+	
+	if (expectedPtrEvent.PointerNumber() != advancedPointerEvent->PointerNumber())
+		{
+		iPtrAppUi->Failed(TPoint3D(), TPoint3D(), KErrNone, expectedPtrEvent.PointerNumber(), advancedPointerEvent->PointerNumber());
+		return;
+		}
+	
+	iPtrAppUi->DecrementEventCount();
+	NumOfEventsAdded--;
+	
+	// Event count is zero when all the events have been tested
+	if (iPtrAppUi->EventCount() == 0)
+		{
+		TInt ret = CalculateLatencyAndStartThread(); 
+		if (ret != KErrNone)
+			{
+			iPtrAppUi->Failed(TPoint3D(), TPoint3D(), ret);
+			return;
+			}
+		}
+	else if (NumOfEventsAdded == 0) 
+		{
+		ConVar.Signal();
+		}
+	}
+
+void CMultiPtrPerfTestControl::AddExpectedEvent(TAdvancedPointerEvent& aExpEvent)
+	{
+	iEventBuffer.Add(&aExpEvent);
+	}
+
+CMultiPtrPerfTestControl::~CMultiPtrPerfTestControl()
+	{
+	iChunk.Close();
+	}
+
+void CMultiPtrPerfTestControl::ConstructL()
+	{
+    iPointerEventNotSupported = EFalse;
+	ConstructL(TPoint(), ControlEnv()->ScreenDevice()->SizeInPixels());
+	}
+
+void CMultiPtrPerfTestControl::ConstructL(TPoint aOrigin, TSize aSize)
+	{
+    iEventBuffer.SetLengthL(EEventBufferSize);
+    
+    iPtrAppUi = static_cast<CMultiPtrPerfTestAppUi*>(ControlEnv()->AppUi());
+        
+    CreateWindowL();
+    Window().EnableAdvancedPointers();
+    EnableDragEvents();
+    SetExtent(aOrigin, aSize);
+    ActivateL();
+    
+ 	// Get the cmdline argument of this process in descriptor
+ 	// convert the descriptor to number and store it in iChunkOffset
+ 	TBuf<128> buf;
+ 	User::CommandLine(buf);
+ 	TLex lex(buf);
+ 	User::LeaveIfError(lex.Val(iChunkOffset));
+	}
+
+// This function gets the current time and subtracts it from the time when the whole test was started.
+// Simulates the event and suspends the thread if aWaitAfterEachEvent is ETrue
+// If aWaitAfterEachEvent is EFalse then it suspends the thread after each set of event i,e after 4, 8, 16 and 32 events 
+void SimulatePointerEvents(TInt aCount, CMultiPtrPerfTestAppUi* appUi, TBool aMultiPtrEvent = EFalse, TBool aWaitAfterEachEvent = ETrue)
+	{
+	TRawEvent rawEvent;
+	TPoint ptrPos;
+	TTime currentTime;
+	TInt64 testStartTime = appUi->TestStartTime();
+	TInt ptrNum = 0;
+	TInt ptrMax = 0;
+	// HAL as already been tested at the start of these tests. So no need to test once again
+	HAL::Get(HALData::EPointerNumberOfPointers, ptrMax);
+	
+	appUi->SetNumberOfEvents((KNumOfIterations*aCount)-1);
+
+	// For testing time taken for each event and for each set of events we make use of RMutex and RConvar.
+	// RMutex is used not to preempt this thread until events has been added
+	// RConVar is used to hold this thread until the events have been tested
+	for (TInt loop = 0; loop < KNumOfIterations; loop++)
+		{
+		ptrNum = 0;
+		ptrPos.iX = ptrPos.iY = 0;
+		Mutex.Wait();
+		for (TInt count = 0; count < aCount/2; count++, ptrNum++)
+			{
+			if (ptrNum >= ptrMax)
+				{
+				ptrNum = 0;
+				}			
+			ptrPos.iX += 2;
+			ptrPos.iY += 1;
+			
+			TWsEvent event;
+			event.InitAdvancedPointerEvent(TPointerEvent::EButton1Down, 0, TPoint3D(ptrPos.iX, ptrPos.iY, 0), (aMultiPtrEvent ? ptrNum : 0));
+			appUi->AddExpectedEvent(*event.Pointer());
+			currentTime.UniversalTime();
+			TInt64 curTime64 = currentTime.Int64();
+			TInt timeSinceTestStart = curTime64 - testStartTime;
+			rawEvent.Set(TRawEvent::EButton1Down, ptrPos.iX, ptrPos.iY, timeSinceTestStart, (aMultiPtrEvent ? ptrNum : 0));
+			UserSvr::AddEvent(rawEvent);
+			NumOfEventsAdded++;
+			if (aWaitAfterEachEvent)
+				{
+				while(NumOfEventsAdded)
+					ConVar.Wait(Mutex);
+				}
+			
+			event.InitAdvancedPointerEvent(TPointerEvent::EButton1Up, 0, TPoint3D(ptrPos.iX, ptrPos.iY, 0), (aMultiPtrEvent ? ptrNum : 0));
+			appUi->AddExpectedEvent(*event.Pointer());
+			currentTime.UniversalTime();
+			curTime64 = currentTime.Int64();
+			timeSinceTestStart = curTime64 - testStartTime;
+			rawEvent.Set(TRawEvent::EButton1Up, ptrPos.iX, ptrPos.iY, timeSinceTestStart, (aMultiPtrEvent ? ptrNum : 0));
+			UserSvr::AddEvent(rawEvent);
+			NumOfEventsAdded++;
+			if (aWaitAfterEachEvent)
+				{
+				while(NumOfEventsAdded)
+					ConVar.Wait(Mutex);
+				}
+			}
+		if (!aWaitAfterEachEvent)
+			{
+			while(NumOfEventsAdded)
+				ConVar.Wait(Mutex);
+			}
+		Mutex.Signal();
+		}
+	}
+
+TInt EventSimulatingThreadStartFunc(TAny* aAny)
+	{
+	CMultiPtrPerfTestAppUi* appUi = static_cast<CMultiPtrPerfTestAppUi*>(aAny);
+
+	switch(appUi->TestCaseNum()++)
+		{
+		case 0:
+			SimulatePointerEvents(4, appUi);
+			break;
+		case 1:
+			SimulatePointerEvents(8, appUi);
+			break;
+		case 2:
+			SimulatePointerEvents(16, appUi);
+			break;
+		case 3:
+			SimulatePointerEvents(32, appUi);
+			break;
+		case 4:
+			SimulatePointerEvents(4, appUi, ETrue);
+			break;
+		case 5:
+			SimulatePointerEvents(8, appUi, ETrue);
+			break;
+		case 6:
+			SimulatePointerEvents(16, appUi, ETrue);
+			break;
+		case 7:
+			SimulatePointerEvents(32, appUi, ETrue);
+			break;
+		case 8:
+			SimulatePointerEvents(4, appUi, EFalse, EFalse);
+			break;
+		case 9:
+			SimulatePointerEvents(8, appUi, EFalse, EFalse);
+			break;
+		case 10:
+			SimulatePointerEvents(16, appUi, EFalse, EFalse);
+			break;
+		case 11:
+			SimulatePointerEvents(32, appUi, EFalse, EFalse);
+			break;
+		case 12:
+			SimulatePointerEvents(4, appUi, ETrue, EFalse);
+			break;
+		case 13:
+			SimulatePointerEvents(8, appUi, ETrue, EFalse);
+			break;
+		case 14:
+			SimulatePointerEvents(16, appUi, ETrue, EFalse);
+			break;
+		case 15:
+			SimulatePointerEvents(32, appUi, ETrue, EFalse);
+			break;		
+		default:
+			break;
+		}
+	return KErrNone;
+	}
+
+TInt CMultiPtrPerfTestAppUi::CreateEventSimulatingThreads()
+	{
+	// Depending upon the iTestCase number create thread and simulate events in that thread function
+	TInt ret = KErrNone;
+	_LIT(KSimulateEventsThread, "Events simulating thread");
+	ret = iThread.Create(KSimulateEventsThread, EventSimulatingThreadStartFunc, KDefaultStackSize, 0x4000, 0x4000, this, EOwnerThread);
+	if (ret == KErrNone)
+		{
+		iThread.Resume();
+		}
+	return ret;
+	}
+
+void CMultiPtrPerfTestAppUi::AddExpectedEvent(TAdvancedPointerEvent& aExpEvent)
+	{
+	iControl->AddExpectedEvent(aExpEvent);
+	}
+
+void CMultiPtrPerfTestAppUi::Failed(TPoint3D aExp3DPoint, TPoint3D aActual3DPoint, TInt aErrorCode, TInt aExpPtrNum, TInt aActPtrNum)
+	{
+	// Write error description in the memory of shared chunk 
+	// so that the main performance test just stops by saying that it failed
+	// and then stop the active scheduler.
+	iControl->Failed(aExp3DPoint, aActual3DPoint, aErrorCode, aExpPtrNum, aActPtrNum);
+	CActiveScheduler::Stop();
+	}
+
+void CMultiPtrPerfTestAppUi::PointerEventsNotSupported()
+    {
+    // Write a pointer events not supported message in the memory of shared chunk 
+    // so that the main performance test just skips the pointer test
+    iControl->PointerEventsNotSupported();
+    }
+
+CMultiPtrPerfTestAppUi::CMultiPtrPerfTestAppUi()
+	{
+	}
+
+CMultiPtrPerfTestAppUi::~CMultiPtrPerfTestAppUi()
+	{
+	RemoveFromStack(iControl);
+	delete iControl;
+	}
+
+void CMultiPtrPerfTestAppUi::ConstructL()
+	{
+	CCoeAppUi::ConstructL();
+	
+	TTime testStartTime;
+	testStartTime.UniversalTime();
+	iTestStartTime = testStartTime.Int64();
+	
+	iControl = new (ELeave) CMultiPtrPerfTestControl();
+	iControl->ConstructL();
+	AddToStackL(iControl);
+	}
+
+void ConstructControlEnvironmentL(CCoeEnv* aCoe)
+	{
+ 	aCoe->ConstructL();
+ 	CMultiPtrPerfTestAppUi* appUi=new(ELeave) CMultiPtrPerfTestAppUi();
+ 	CleanupStack::PushL(appUi);			// If it leaves after this then there is no way of deleting the appui
+ 	aCoe->SetAppUi(appUi);				// So pushed it on to cleanup stack
+ 	aCoe->WsSession().SetAutoFlush(ETrue);
+ 	appUi->ConstructL();
+ 	User::LeaveIfError(Mutex.CreateLocal(EOwnerProcess));
+ 	User::LeaveIfError(ConVar.CreateLocal(EOwnerProcess));
+ 	CleanupStack::Pop(appUi);
+	}
+
+GLDEF_C TInt E32Main()
+	{
+	__UHEAP_MARK;
+	CCoeEnv* coe = new CCoeEnv;
+	if (!coe)
+		{
+		return KErrNoMemory; 
+		}
+	TRAPD(err, ConstructControlEnvironmentL(coe));
+	if (err != KErrNone)
+		{
+		delete coe;
+		}
+	else	// If KErrNone then no need to delte coe as it is taken care by ConEnv
+		{
+        // Check whether the configuration supports pointer events.
+        // If it dosn't support pointer events then the pointer cursor area will be empty,
+        // in this case skip the test and inform the test framework that the test has been skipped
+        TRect pointerCursorArea = coe->WsSession().PointerCursorArea();
+        if(pointerCursorArea.IsEmpty())
+            {
+            RDebug::Printf("PointerCursorArea is Empty");
+            CMultiPtrPerfTestAppUi* appUi = static_cast<CMultiPtrPerfTestAppUi*>(coe->AppUi());
+            appUi->PointerEventsNotSupported();
+            }
+        else
+            {
+            // First event which starts the test from HandlePointerEventL
+            TRawEvent rawEvent;
+            rawEvent.Set(TRawEvent::EButton1Down, 0, 0, 0, 0);
+            UserSvr::AddEvent(rawEvent);
+            coe->ExecuteD();
+            }
+		Mutex.Close();
+		ConVar.Close();
+	 	}
+	
+	__UHEAP_MARKEND;
+	return err;
+	}