diff -r 000000000000 -r bde4ae8d615e os/graphics/graphicstest/uibench/src/tmultiptreventhandlingperf.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/graphicstest/uibench/src/tmultiptreventhandlingperf.cpp Fri Jun 15 03:10:57 2012 +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 + +_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(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(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(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; + }