Fix TRANSPARENCY_NONE composition for surfaces narrower than the context.
Improve performance of point sample scaling with 8-bit samples, by using fixed point code
Allow any non-zero value for the boolean attribute WFC_ELEMENT_SOURCE_FLIP
Simplify RemoveElement code
// Copyright (c) 2007-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:
// Surface manager multi-threaded test code
//
//
/**
@file
@test
@internalComponent - Internal Symbian test code
*/
#include "tsurfacemanagermultithread.h"
#include <e32base.h>
#include <e32cons.h>
#include <e32test.h>
#include <e32std.h>
#include <e32cmn.h>
#include <e32def.h>
static TSurfaceId globalSurfaceId;
static TInt testResult;
typedef CTSurfaceManagerMultiThread::TInfo TInfo;
CTSurfaceManagerMultiThread::CTSurfaceManagerMultiThread(CTestStep* aStep):
CTGraphicsBase(aStep)
{
}
CTSurfaceManagerMultiThread::~CTSurfaceManagerMultiThread()
{
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::RunTestCaseL(TInt aCurTestCase)
{
TInt procHandles1 =0;
TInt threadHandles1=0;
RThread().HandleCount(procHandles1, threadHandles1);
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(KUnknownSYMTestCaseIDName);
switch(aCurTestCase)
{
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0078
@SYMPREQ PREQ1879, PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test accessing surface in another thread without opening it
Thread 1: Create Surface
Thread 2: Map Surface - KErrNone (still accessible)
Thread 2: SurfaceInfo - KErrNone (still accessible)
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),MapSurface(), SurfaceInfo()
@SYMTestExpectedResults The surface can be successfully accessed in other threads without first opening it.
*/
case 1:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0078"));
TestAccessSurfaceWithoutOpeningL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0079
@SYMPREQ PREQ1879, PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test accessing a surface created in the existing shared chunk in another thread without opening it.
Thread 1: Create a Surface in the new chunk with valid creation attributes
Thread 1: Map the surface in the current process to get the chunk handle
Thread 1: Create a new surface in the existing chunk with valid creation attributes
Thread 2: Map the second Surface – KErrNone (still accessible)
Thread 2: SurfaceInfo – KErrNone (still accessible)
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),MapSurface(), SurfaceInfo()
@SYMTestExpectedResults MapSurface, SurfaceInfo return KerrNone
*/
case 2:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0079"));
TestAccessSurfaceInExistingSharedChunkL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0080
@SYMPREQ PREQ1879, PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test closing surface in another thread without opening it
Thread 1: Create Surface
Thread 2: Close Surface - KErrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface()
@SYMTestExpectedResults The surface can be successfully closed in other threads without first opening it.
*/
case 3:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0080"));
TestCloseSurfaceWithoutOpeningL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0081
@SYMPREQ PREQ1879, PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test accessing an surface which is created in another thread but closed in current thread
Thread 2: Create Surface
Thread 1: Close Surface - KerrNone
Thread 2: Map Surface - KErrArgument
Thread 2: SurfaceInfo - KErrArgument
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), MapSurface(), SurfaceInfo()
@SYMTestExpectedResults The surface cant be accessd even after it is closed in other threads.
*/
case 4:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0081"));
TestAccessSurfaceClosedThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0067
@SYMPREQ PREQ1879, PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test closing surface created in the existing chunk in another thread without opening it
Thread 1: Create a Surface in a new shared chunk with valid attributes
Thread 1: Map the surface in the process to get the shared chunk handle
Thread 1: Create a new surface in the existing shared chunk
Thread 2: Close the second surface – KErrNone (the second surface is deleted)
Thread 2: Call SurfaceInfo to the first surface and it returns KErrNone, but it returns KErrArgument to the second surface.
Thread 2: Close the first surface and check it returns KErrNone (the first surface is deleted).
Thread 1: Call SurfaceInfo to both surfaces and return KErrArgument
Thread 1: Check the chunk is still accessible by calling RChunk::Base()
Thread 1: Close the chunk handle
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface()
@SYMTestExpectedResults CloseSurface returns KErrNone. The chunk handle is not closed even when both surfaces are deleted.
*/
case 5:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0067"));
TestCloseSurfaceExistingSharedChunkL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0068
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test closing an surface which is already closed in other thread return KErrArgument
Thread 2: Create Surface
Thread 1: Close Surface - KerrNone
Thread 2: Close Surface - KErrArgument
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface()
@SYMTestExpectedResults The surface cant be closed again.
*/
case 6:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0068"));
TestCloseSurfaceClosedThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0069
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test accessing an surface which is already opened and closed in another thread, given that the process still owns the surface
Thread 1: Create Surface
Thread 2: Open Surface -- KErrNone
Thread 2: Close Surface -- KErrNone
Thread 1: Map Surface - KErrNone
Thread 1: SurfaceInfo - KErrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), MapSurface(), SurfaceInfo, OpenSurface()
@SYMTestExpectedResults The surface is still accessible in the thread residing the owning process
*/
case 7:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0069"));
TestAccessSurfaceOpenedClosedThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0070
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test closing an surface which is already opened and closed in another thread, given that the process still owns the surface
Thread 1: Create Surface
Thread 2: Open Surface
Thread 2: Close Surface
Thread 1: Close Surface - KErrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), OpenSurface()
@SYMTestExpectedResults The surface is still closible in the thread residing in the owning process
*/
case 8:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0070"));
TestCloseSurfaceOpenedClosedThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0071
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test accessing surface in another thread when the opening thread is killed
Thread 1: Create Surface
Thread 2: Open Surface
Thread 2: Kill the thread
Thread 1: Map Surface - KErrNone
Thread 1: Surface Info -- KErrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), MapSurface(), SurfaceInfo(), OpenSurface()
@SYMTestExpectedResults The surface is accessible when the opening thread is killed
*/
case 9:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0071"));
TestAccessSurfaceOpenedKilledThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0072
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test closing surface in another thread when the opening thread is killed
Thread 1: Create Surface
Thread 2: Open Surface
Thread 2: Kill the thread
Thread 1: Close Surface - KErrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), OpenSurface()
@SYMTestExpectedResults The surface is closible when the opening thread is killed
*/
case 10:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0072"));
TestCloseSurfaceOpenedKilledThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0073
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test accessing surface in another thread when the creating thread is killed and it is closed in other threads
Thread 2: Create Surface
Thread 1: Close Surface
Thread 2: Kill Thread
Thread 1: Map Surface - KErrArgument
Thread 1: Surface Info - KErrArgument
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), MapSurface(), SurfaceInfo(),
@SYMTestExpectedResults The surface is accessible when the creating thread is killed and it is closed in other threads
*/
case 11:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0073"));
TestAccessSurfaceCreateKilledThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0074
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test accessing surface in another thread when the creating thread is killed and it is closed in other threads
Thread 2: Create Surface
Thread 1: Close Surface
Thread 2: Kill Thread
Thread 1: Close Surface - KErrArgument
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface()
@SYMTestExpectedResults The surface is accessible when the creating thread is killed and it is closed in other threads
*/
case 12:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0074"));
TestCloseSurfaceCreateKilledThreadL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0075
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test closing on one thread doesn't prevent opening on other Threads, provided one Thread still owns surface
Thread 1: Create Surface
Thread 2: Open Surface
Thread 2: Close Surface
Thread 3: Open Surface - KerrNone
Thread 3: Map Surface - KerrNone
Thread 3: SurfaceInfo -- KErrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), MapSurface(), SurfaceInfo(),
@SYMTestExpectedResults It is expected that closing on one thread doesn't prevent opening on other Threads, provided one Thread still owns surface
*/
case 13:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0075"));
TestAccessSurfaceThreeThreadsL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0076
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test surface can be accessed from third thread when creating thread dies and second thread closes
Thread 2: Create Surface
Thread 1: Open Surface
Thread 3: Open Surface
Thread 1: Close Surface
Thread 2: Kill Thread
Thread 3: Close Surface
Thread 3: Map Surface - KerrNone
Thread 3: SurfaceInfo -- KErrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), MapSurface(), SurfaceInfo(), OpenSurface()
@SYMTestExpectedResults It is expected that surface can be accessed from third thread when creating thread dies and second thread closes
*/
case 14:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0076"));
TestAccessSurfaceDieCloseOtherThreadsL();
break;
/**
@SYMTestCaseID GRAPHICS-SURFACEMANAGER-0077
@SYMPREQ PREQ1007
@SYMREQ REQ8222,REQ8223
@SYMTestPriority High
@SYMTestCaseDesc Test that the surface can be opened from the third Thread after creating thread dies and second and third thread close the surface
Thread 2: Create Surface
Thread 1: Open Surface
Thread 3: Open Surface
Thread 1: Close Surface
Thread 2: Kill Thread
Thread 3: Close Surface
Thread 3: Open Surface - KerrNone
@SYMTestStatus Implemented
@SYMTestActions Call CreateSurface(),CloseSurface(), OpenSurface()
@SYMTestExpectedResults It is expected that the surface can be opened from the third Thread after creating thread dies and second and third thread close the surface
*/
case 15:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(_L("GRAPHICS-SURFACEMANAGER-0077"));
TestOpenSurfaceDieCloseOtherThreadsL();
break;
default:
((CTSurfaceManagerMultiThreadStep*)iStep)->SetTestStepID(KNotATestSYMTestCaseIDName);
((CTSurfaceManagerMultiThreadStep*)iStep)->CloseTMSGraphicsStep();
TestComplete();
break;
}
((CTSurfaceManagerMultiThreadStep*)iStep)->RecordTestResultL();
// Handle check
TInt procHandles2 =0;
TInt threadHandles2=0;
RThread().HandleCount(procHandles2,threadHandles2);
if (threadHandles1 != threadHandles2)
{
User::Leave(KErrGeneral); // Thread-owned handles not closed
}
}
void CTSurfaceManagerMultiThread::CloseSurfaceWhenLeave(TAny* aInfo)
{
TInt err1 = ((TInfo*)aInfo)->iSurfaceManager.CloseSurface(((TInfo*)aInfo)->iSurfaceId);
TInt err2 = ((TInfo*)aInfo)->iSurfaceManager.CloseSurface(((TInfo*)aInfo)->iSurfaceIdNew);
if (err1!=KErrNone || err2!=KErrNone)
RDebug::Print(_L("Error closing surfaces err1= %d, err2= %d\n"),err1,err2);
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceWithoutOpeningL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
// Logging info
INFO_PRINTF1(_L("Test accessing surface in another thread without opening it\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Create a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iSurfaceIdNew = TSurfaceId::CreateNullId();
iInfo.iThreadTestCase = EMapSurfaceInfo;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread1;
_LIT(KNameThreadSecond1, "Test_SurfaceManager_ThreadSecond1");
User::LeaveIfError(thread1.Create(KNameThreadSecond1,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch second thread
TRequestStatus statusThreadSecond;
thread1.Logon(statusThreadSecond);
thread1.SetPriority(EPriorityLess);
thread1.Resume();
testResult = EAllZero;
// Passes control to the second process
sem.Wait();
thread1.Suspend();
// Test results in second thread
TEST (testResult = (EMapSurfaceTestPassed | ESurfaceInfoTestPassed));
// Pass control off to the second process again
thread1.Resume();
// Wait for a second for the second thread to terminate
User::WaitForRequest(statusThreadSecond);
//Close the handles
CleanupStack::PopAndDestroy(1, &sem); //invoke surface manager to close the surface also close the handle to RSemaphore
thread1.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceInExistingSharedChunkL()
{
// Logging info
INFO_PRINTF1(_L("Test accessing a surface created in the existing shared chunk in another thread without opening it\r\n"));
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(100,100);
attributes.iBuffers = 1; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422SemiPlanar; // 2bpp
attributes.iStride = 400; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = 2; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
//Map the surface in the current processs
RChunk handle;
TEST(KErrNone == iSurfaceManager.MapSurface(iSurfaceId,handle));
// Cache, Contiguous and Alignment attributes are ignored for the already existing chunks
RSurfaceManager::TSurfaceCreationAttributesBuf buff;
RSurfaceManager::TSurfaceCreationAttributes& attributesNew = buff();
attributesNew.iSize = TSize(480,16);
attributesNew.iBuffers = 2; // number of buffers in the surface
attributesNew.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributesNew.iStride = 1013; // Number of bytes between start of one line and start of next
attributesNew.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributesNew.iHintCount = 1;
attributesNew.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124545), 50, EFalse);
attributesNew.iAlignment = 2;
attributesNew.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
// For the time being KErrArgument will be returned as the core codes are
// not ready to check the passed in shared chunk handle.
TEST(KErrNone == iSurfaceManager.CreateSurface(buff, iSurfaceIdNew, handle));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Create a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceIdNew;
iInfo.iSurfaceIdNew = iSurfaceId;
iInfo.iThreadTestCase = EMapSurfaceInfo;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread2;
_LIT(KNameThreadSecond2, "Test_SurfaceManager_ThreadSecond2");
User::LeaveIfError(thread2.Create(KNameThreadSecond2,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch second thread
TRequestStatus statusThreadSecond;
thread2.Logon(statusThreadSecond);
thread2.SetPriority(EPriorityLess);
thread2.Resume();
testResult = EAllZero;
// Passes control to the second process
sem.Wait();
thread2.Suspend();
// Test results in second thread
TEST (testResult = (EMapSurfaceTestPassed | ESurfaceInfoTestPassed));
// Pass control off to the second process again
thread2.Resume();
// Wait for a second for the second thread to terminate
User::WaitForRequest(statusThreadSecond);
//Close the handles
CleanupStack::PopAndDestroy(1, &sem); //invoke surface manager to close the surface also close the handle to RSemaphore
handle.Close();
thread2.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestCloseSurfaceWithoutOpeningL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
INFO_PRINTF1(_L("Test closing surface in another thread without opening it\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = ECloseSurfaces;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread3;
_LIT(KNameThreadSecond3, "Test_SurfaceManager_ThreadSecond3");
User::LeaveIfError(thread3.Create(KNameThreadSecond3,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch second thread to close the surface
TRequestStatus statusThreadSecond;
thread3.Logon(statusThreadSecond);
thread3.SetPriority(EPriorityLess);
thread3.Resume();
testResult = EAllZero;
// Passes control to the second thread
sem.Wait();
thread3.Suspend();
// Test the results in the second thread
TEST(testResult == ECloseSurfaceTestPassed);
thread3.Resume();
// Wait for a second for the second process to terminate
User::WaitForRequest(statusThreadSecond);
//Close the handle
CleanupStack::PopAndDestroy(1, &sem);
thread3.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceClosedThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Logging info
INFO_PRINTF1(_L("Test accessing an surface which is created in another thread but closed in current thread\r\n"));
// Create a semaphore
RSemaphore sem;
RSemaphore semMain;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
TEST(KErrNone == semMain.CreateGlobal(KMainThreadSemaphore, 0));
CleanupClosePushL(semMain);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = ECreateSurfaceMapInfo;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread4;
_LIT(KNameThreadSecond4, "Test_SurfaceManager_ThreadSecond4");
User::LeaveIfError(thread4.Create(KNameThreadSecond4,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second trhead
TRequestStatus statusThreadSecond;
thread4.Logon(statusThreadSecond);
thread4.SetPriority(EPriorityLess);
thread4.Resume();
testResult = EAllZero;
// Passes control to the second process
sem.Wait();
// Test creating surface in second thread
TEST(testResult == ECreateSurfaceTestPassed);
// Reset testResult
testResult = EAllZero;
// Test closing surface
iSurfaceId = globalSurfaceId;
TEST(KErrNone == iSurfaceManager.CloseSurface(globalSurfaceId));
semMain.Signal();
// Wait the second thread to terminate
User::WaitForRequest(statusThreadSecond);
// Test mapsurface and surfaceinfo executed in the second thread
TEST(testResult == (EMapSurfaceTestFailed|ESurfaceInfoTestFailed));
// Close all the handles
CleanupStack::PopAndDestroy(2, &sem);
thread4.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestCloseSurfaceExistingSharedChunkL()
{
// Logging info
INFO_PRINTF1(_L("Test closing surface created in the existing chunk in another thread without opening it\r\n"));
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(100,100);
attributes.iBuffers = 1; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422SemiPlanar; // 2bpp
attributes.iStride = 400; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = 2; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
//Map the surface in the current processs
RChunk handle;
TEST(KErrNone == iSurfaceManager.MapSurface(iSurfaceId,handle));
// Cache, Contiguous and Alignment attributes are ignored for the already existing chunks
RSurfaceManager::TSurfaceCreationAttributesBuf buff;
RSurfaceManager::TSurfaceCreationAttributes& attributesNew = buff();
attributesNew.iSize = TSize(480,16);
attributesNew.iBuffers = 2; // number of buffers in the surface
attributesNew.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributesNew.iStride = 1013; // Number of bytes between start of one line and start of next
attributesNew.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributesNew.iHintCount = 1;
attributesNew.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124545), 50, EFalse);
attributesNew.iAlignment = 2;
attributesNew.iOffsetBetweenBuffers = 0;
attributesNew.iMappable = ETrue;
// Test create surface doesn't return an error
// For the time being KErrArgument will be returned as the core codes are
// not ready to check the passed in shared chunk handle.
TEST(KErrNone == iSurfaceManager.CreateSurface(buff, iSurfaceIdNew, handle));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Create a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iSurfaceIdNew = iSurfaceIdNew;
iInfo.iThreadTestCase = ECloseBothSurfaces;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread5;
_LIT(KNameThreadSecond5, "Test_SurfaceManager_ThreadSecond5");
User::LeaveIfError(thread5.Create(KNameThreadSecond5,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch second thread
TRequestStatus statusThreadSecond;
thread5.Logon(statusThreadSecond);
thread5.SetPriority(EPriorityLess);
thread5.Resume();
testResult = EAllZero;
// Passes control to the second process
sem.Wait();
thread5.Suspend();
// Test results in second thread
TEST (testResult = (ECloseSurfaceTestPassed | ESurfaceInfoTestPassed | ESurfaceInfoTestPassed2));
RSurfaceManager::TInfoBuf infoBuf;
TEST (KErrArgument == iSurfaceManager.SurfaceInfo(iSurfaceId, infoBuf));
TEST (KErrArgument == iSurfaceManager.SurfaceInfo(iSurfaceIdNew, infoBuf));
// Pass control off to the second process again
thread5.Resume();
// Wait for a second for the second thread to terminate
User::WaitForRequest(statusThreadSecond);
CleanupStack::PopAndDestroy(1, &sem); //invoke surface manager to close the surface also close the handle to RSemaphore
handle.Close();
thread5.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestCloseSurfaceClosedThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Logging info
INFO_PRINTF1(_L("Test closing an surface which is already closed in other thread return KErrArgument\r\n"));
// Create a semaphore
RSemaphore sem;
RSemaphore semMain;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
TEST(KErrNone == semMain.CreateGlobal(KMainThreadSemaphore, 0));
CleanupClosePushL(semMain);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = ECreateSurfaceClose;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread6;
_LIT(KNameThreadSecond6, "Test_SurfaceManager_ThreadSecond6");
User::LeaveIfError(thread6.Create(KNameThreadSecond6,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch second thread
TRequestStatus statusThreadSecond;
thread6.Logon(statusThreadSecond);
thread6.SetPriority(EPriorityLess);
thread6.Resume();
testResult = EAllZero;
// Passes control to the second thread
sem.Wait();
// Test creating surface in second thread
TEST(testResult == ECreateSurfaceTestPassed);
testResult = EAllZero;
// Test closing surface
iSurfaceId = globalSurfaceId;
TEST(KErrNone == iSurfaceManager.CloseSurface(globalSurfaceId));
semMain.Signal();
// Wait for a second for the second process to terminate
User::WaitForRequest(statusThreadSecond);
TEST(testResult == ECloseSurfaceTestFailed);
// Close all the handles
CleanupStack::PopAndDestroy(2, &sem);
thread6.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceOpenedClosedThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
// Logging info
INFO_PRINTF1(_L("Test accessing an surface which is already opened and closed in another thread, given that the process still owns the surface\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = EOpenCloseSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread7;
_LIT(KNameThreadSecond7, "Test_SurfaceManager_ThreadSecond7");
User::LeaveIfError(thread7.Create(KNameThreadSecond7,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thread
TRequestStatus statusThreadSecond;
thread7.Logon(statusThreadSecond);
thread7.SetPriority(EPriorityLess);
thread7.Resume();
testResult = EAllZero;
sem.Wait();
thread7.Suspend();
// Test open and close surface in the second thread
TEST(testResult == (EOpenSurfaceTestPassed|ECloseSurfaceTestPassed));
RChunk handle;
// To prove killing threads doesnt affect the ref count...
TEST(KErrNone == iSurfaceManager.MapSurface(iSurfaceId, handle));
handle.Close();
RSurfaceManager::TInfoBuf infoBuf;
TEST(KErrNone ==iSurfaceManager.SurfaceInfo(iSurfaceId, infoBuf));
thread7.Resume();
// Wait for a second for the second process to terminate
User::WaitForRequest(statusThreadSecond);
// Close all the handles
CleanupStack::PopAndDestroy(1, &sem);
thread7.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestCloseSurfaceOpenedClosedThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
INFO_PRINTF1(_L("Test closing an surface which is already opened and closed in another thread, given that the process still owns the surface\r\n"));
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = EOpenCloseSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread8;
_LIT(KNameThreadSecond8, "Test_SurfaceManager_ThreadSecond8");
User::LeaveIfError(thread8.Create(KNameThreadSecond8,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
TRequestStatus statusThreadSecond;
thread8.Logon(statusThreadSecond);
thread8.SetPriority(EPriorityLess);
thread8.Resume();
testResult = EAllZero;
sem.Wait();
thread8.Suspend();
// Test open and close surface in the second thread
TEST(testResult == (EOpenSurfaceTestPassed|ECloseSurfaceTestPassed));
thread8.Resume();
// Wait for a second for the second process to terminate
User::WaitForRequest(statusThreadSecond);
// Close all the handles
CleanupStack::PopAndDestroy(1, &sem);
thread8.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceOpenedKilledThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
INFO_PRINTF1(_L("Test accessing surface in another thread when the opening thread is killed\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = EOpenKillSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread9;
_LIT(KNameThreadSecond9, "Test_SurfaceManager_ThreadSecond9");
User::LeaveIfError(thread9.Create(KNameThreadSecond9,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thraed
TRequestStatus statusThreadSecond;
thread9.Logon(statusThreadSecond);
thread9.SetPriority(EPriorityLess);
thread9.Resume();
// Waiting the second thread to terminate
User::WaitForRequest(statusThreadSecond);
RChunk handle;
// Test the surface is still accessible
TEST(KErrNone == iSurfaceManager.MapSurface(iSurfaceId, handle));
handle.Close();
RSurfaceManager::TInfoBuf infoBuf;
TEST(KErrNone ==iSurfaceManager.SurfaceInfo(iSurfaceId, infoBuf));
// Close all the handles
CleanupStack::PopAndDestroy(1, &sem);
thread9.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestCloseSurfaceOpenedKilledThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
// Logging info
INFO_PRINTF1(_L("Test closing surface in another thread when the opening thread is killed\r\n"));
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = EOpenKillSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread10;
_LIT(KNameThreadSecond10, "Test_SurfaceManager_ThreadSecond10");
User::LeaveIfError(thread10.Create(KNameThreadSecond10,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thread
TRequestStatus statusThreadSecond;
thread10.Logon(statusThreadSecond);
thread10.SetPriority(EPriorityLess);
thread10.Resume();
// Waiting the second thread to terminate
User::WaitForRequest(statusThreadSecond);
// Test closing surface
TEST(KErrNone ==iSurfaceManager.CloseSurface(iSurfaceId));
// Close all the handles
CleanupStack::PopAndDestroy(1, &sem);
thread10.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceCreateKilledThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Logging info
INFO_PRINTF1(_L("Test accessing surface in another thread when the creating thread is killed\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = ECreateKillSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread11;
_LIT(KNameThreadSecond11, "Test_SurfaceManager_ThreadSecond11");
User::LeaveIfError(thread11.Create(KNameThreadSecond11,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thread
TRequestStatus statusThreadSecond;
thread11.Logon(statusThreadSecond);
thread11.SetPriority(EPriorityLess);
thread11.Resume();
testResult = EAllZero;
sem.Wait();
// Test creating surface in the second thread
TEST(testResult = ECreateSurfaceTestPassed);
// Test closing surface
TEST(KErrNone == iSurfaceManager.CloseSurface(globalSurfaceId));
// Wait the second thread to terminate
User::WaitForRequest(statusThreadSecond);
// Test the surface is not accessible any more
RChunk handle;
TEST(KErrArgument == iSurfaceManager.MapSurface(globalSurfaceId, handle));
handle.Close();
RSurfaceManager::TInfoBuf infoBuf;
TEST(KErrArgument ==iSurfaceManager.SurfaceInfo(globalSurfaceId, infoBuf));
// Close all the handles
CleanupStack::PopAndDestroy(1, &sem);
thread11.Close();
iSurfaceManager.Close();
}
/**
210 Test closing surface in another thread when the creating thread is killed
Thread 2: Create Surface
Thread 1: Close Surface
Thread 2: Kill the thread
Thread 1: Close Surface - KErrArgument
*/
void CTSurfaceManagerMultiThread::TestCloseSurfaceCreateKilledThreadL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Logging info
INFO_PRINTF1(_L("Test closing surface in another thread when the creating thread is killed\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = ECreateKillSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread12;
_LIT(KNameThreadSecond12, "Test_SurfaceManager_ThreadSecond12");
User::LeaveIfError(thread12.Create(KNameThreadSecond12,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thread
TRequestStatus statusThreadSecond;
thread12.Logon(statusThreadSecond);
thread12.SetPriority(EPriorityLess);
thread12.Resume();
sem.Wait();
// Test creating surface in the second thread
TEST(testResult = ECreateSurfaceTestPassed);
// Test closing surface
TEST(KErrNone == iSurfaceManager.CloseSurface(globalSurfaceId));
// Wait the second thread to terminate
User::WaitForRequest(statusThreadSecond);
// Test the surface is removed and not closable
TEST(KErrArgument ==iSurfaceManager.CloseSurface(globalSurfaceId));
// Close the handles
CleanupStack::PopAndDestroy(1, &sem);
thread12.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceThreeThreadsL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Test create surface doesn't return an error
TEST(KErrNone == iSurfaceManager.CreateSurface(buf, iSurfaceId));
// Logging info
INFO_PRINTF1(_L("Test closing on one thread doesn't prevent opening on other Threads, provided one Thread still owns surface\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore,0));
CleanupClosePushL(sem);
// Creates a second thread in the current process and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = EOpenCloseSurfaceMultiThread;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread13;
_LIT(KNameThreadSecond13, "Test_SurfaceManager_ThreadSecond13");
User::LeaveIfError(thread13.Create(KNameThreadSecond13,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thread
TRequestStatus statusThreadSecond;
thread13.Logon(statusThreadSecond);
thread13.SetPriority(EPriorityLess);
thread13.Resume();
testResult = EAllZero;
sem.Wait();
TEST(testResult == EOpenSurfaceTestPassed);
testResult = EAllZero;
// Create a third thread in the same process and opens the handle
iInfo2 = iInfo;
iInfo2.iThreadTestCase = EOpenMapSurfaceInfoMultiThread;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo2));
RThread thread13_2;
_LIT(KNameThreadSecond13_2, "Test_SurfaceManager_ThreadSecond13_2");
User::LeaveIfError(thread13_2.Create(KNameThreadSecond13_2,ThreadThirdStart, KDefaultStackSize, &User::Heap(), &iInfo2));
CleanupStack::Pop();
// Launch the third thread
TRequestStatus statusThreadThird;
thread13_2.Logon(statusThreadThird);
thread13_2.SetPriority(EPriorityLess);
thread13_2.Resume();
sem.Wait();
TEST(testResult == EOpenSurfaceTestPassed);
testResult = EAllZero;
thread13.Resume();
User::WaitForRequest(statusThreadSecond);
TEST(testResult == ECloseSurfaceTestPassed);
testResult = EAllZero;
thread13_2.Resume();
User::WaitForRequest(statusThreadThird);
TEST(testResult == (EMapSurfaceTestPassed|ESurfaceInfoTestPassed));
// Close all the handles
CleanupStack::PopAndDestroy(1, &sem);
thread13.Close();
thread13_2.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestAccessSurfaceDieCloseOtherThreadsL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Logging info
INFO_PRINTF1(_L("Test surface can be accessed from third thread when creating thread dies and second thread closes\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Create a second thread and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = ECreateKillSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread14;
_LIT(KNameThreadSecond14, "Test_SurfaceManager_ThreadSecond14");
User::LeaveIfError(thread14.Create(KNameThreadSecond14,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thread
TRequestStatus statusThreadSecond;
thread14.Logon(statusThreadSecond);
thread14.SetPriority(EPriorityLess);
thread14.Resume();
testResult = EAllZero;
sem.Wait();
//suspend the 2nd thread
thread14.Suspend();
TEST(testResult == ECreateSurfaceTestPassed);
testResult = EAllZero;
TEST(KErrNone == iSurfaceManager.OpenSurface(globalSurfaceId));
// Create a third thread in the current process and opens the handle
iInfo2.iSurfaceManager = iSurfaceManager;
iInfo2.iSurfaceId = globalSurfaceId;
iInfo2.iSurfaceIdNew = iSurfaceId;
iInfo2.iThreadTestCase = EOpenCloseMapSurfaceInfoMultiThread;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo2));
RThread thread14_2;
_LIT(KNameThreadSecond14_2, "Test_SurfaceManager_ThreadSecond14_2");
User::LeaveIfError(thread14_2.Create(KNameThreadSecond14_2,ThreadThirdStart, KDefaultStackSize, &User::Heap(), &iInfo2));
CleanupStack::Pop();
// Launch the third thread
TRequestStatus statusThreadThird;
thread14_2.Logon(statusThreadThird);
thread14_2.SetPriority(EPriorityLess);
thread14_2.Resume();
sem.Wait();
// Test opening the surface in the second thread
TEST(testResult == EOpenSurfaceTestPassed);
testResult = EAllZero;
// Test closing the surface in the main thread
TEST(KErrNone == iSurfaceManager.CloseSurface(globalSurfaceId));
thread14.Resume();
User::WaitForRequest(statusThreadSecond);
thread14_2.Resume();
User::WaitForRequest(statusThreadThird);
// Test the execution results in the third thread
TEST(testResult == (ECloseSurfaceTestPassed|EMapSurfaceTestPassed|ESurfaceInfoTestPassed));
// Close all the handles
CleanupStack::PopAndDestroy(1, &sem);
thread14.Close();
thread14_2.Close();
iSurfaceManager.Close();
}
void CTSurfaceManagerMultiThread::TestOpenSurfaceDieCloseOtherThreadsL()
{
User::LeaveIfError(iSurfaceManager.Open());
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(480,16);
attributes.iBuffers = 2; // number of buffers in the surface
attributes.iPixelFormat = EUidPixelFormatYUV_422Reversed; // 2bpp
attributes.iStride = 1013; // Number of bytes between start of one line and start of next
attributes.iOffsetToFirstBuffer = 0; // way of reserving space before the surface pixel data
attributes.iAlignment = RSurfaceManager::EPageAligned; // alignment, 1,2,4,8,16,32,64 byte aligned or EPageAligned
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iContiguous = ETrue;
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
// Logging info
INFO_PRINTF1(_L("Test that the surface can be opened from the third Thread after creating thread dies and second and third thread close the surface\r\n"));
// Create a semaphore
RSemaphore sem;
TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
CleanupClosePushL(sem);
// Create a second thread and opens the handle
iInfo.iSurfaceManager = iSurfaceManager;
iInfo.iSurfaceId = iSurfaceId;
iInfo.iThreadTestCase = ECreateKillSurface;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo));
RThread thread15;
_LIT(KNameThreadSecond15, "Test_SurfaceManager_ThreadSecond15");
User::LeaveIfError(thread15.Create(KNameThreadSecond15,ThreadSecondStart, KDefaultStackSize, &User::Heap(), &iInfo));
CleanupStack::Pop();
// Launch the second thread
TRequestStatus statusThreadSecond;
thread15.Logon(statusThreadSecond);
thread15.SetPriority(EPriorityLess);
thread15.Resume();
testResult = EAllZero;
sem.Wait();
thread15.Suspend(); //suspend the 2nd thread
TEST(testResult == ECreateSurfaceTestPassed);
testResult = EAllZero;
// Test creating the surface in the second thread
TEST(KErrNone == iSurfaceManager.OpenSurface(globalSurfaceId));
// Create a third thread and opens the handle
iInfo2.iSurfaceManager = iSurfaceManager;
iInfo2.iSurfaceId = globalSurfaceId;
iInfo2.iSurfaceIdNew = iSurfaceId;
iInfo2.iThreadTestCase = EOpenCloseOpenMultiThread;
// Create a TCleanupItem object
CleanupStack::PushL(TCleanupItem((TCleanupOperation)CloseSurfaceWhenLeave, &iInfo2));
RThread thread15_2;
_LIT(KNameThreadSecond15_2, "Test_SurfaceManager_ThreadSecond15_2");
User::LeaveIfError(thread15_2.Create(KNameThreadSecond15_2,ThreadThirdStart, KDefaultStackSize, &User::Heap(), &iInfo2));
CleanupStack::Pop();
// Launch the third thread
TRequestStatus statusThreadThird;
thread15_2.Logon(statusThreadThird);
thread15_2.SetPriority(EPriorityLess);
thread15_2.Resume();
sem.Wait();
// Test opening the surface in the third thread
TEST(testResult == EOpenSurfaceTestPassed);
// Test closing the surface in the main thread
TEST(KErrNone == iSurfaceManager.CloseSurface(globalSurfaceId));
thread15.Resume();
User::WaitForRequest(statusThreadSecond);
thread15_2.Resume();
User::WaitForRequest(statusThreadThird);
// Test the surface is still accessible in the third thread
TEST(testResult == (ECloseSurfaceTestPassed | EOpenSurfaceTestPassed));
// Close the handles
CleanupStack::PopAndDestroy(1, &sem);
thread15.Close();
thread15_2.Close();
iSurfaceManager.Close();
}
/**
The second thread entry point
*/
TInt CTSurfaceManagerMultiThread::ThreadSecondStart(TAny* aInfo)
{
TInt procHandles1 =0;
TInt threadHandles1=0;
RThread().HandleCount(procHandles1, threadHandles1);
__UHEAP_MARK;
CChildThreadWrapper* newThread = new CChildThreadWrapper(aInfo);
if (newThread==NULL)
{
return KErrNoMemory;
}
RSemaphore sem;
RSemaphore semMain;
TInt ret = sem.OpenGlobal(KMultiThreadSemaphore);
if (ret == KErrNone)
{
TThreadTestCase testCase = newThread->iThreadTestCase;
switch (testCase)
{
case ECreateSurfaceMapInfo:
User::LeaveIfError(semMain.OpenGlobal(KMainThreadSemaphore));
newThread->CreateSurfaceThread();
sem.Signal();
semMain.Wait();
newThread->MapSurfaceInfo();
delete newThread;
semMain.Close();
break;
case ECreateSurfaceClose:
User::LeaveIfError(semMain.OpenGlobal(KMainThreadSemaphore));
newThread->CreateSurfaceThread();
sem.Signal();
semMain.Wait();
newThread->CloseSurface();
delete newThread;
semMain.Close();
break;
case EMapSurfaceInfo:
newThread->MapSurfaceInfo();
sem.Signal();
delete newThread;
break;
case ECloseSurfaces:
newThread->CloseSurface();
sem.Signal();
delete newThread;
break;
case EOpenCloseSurface:
newThread->OpenSurface();
newThread->CloseSurface();
sem.Signal();
delete newThread;
break;
case EOpenKillSurface:
newThread->OpenSurface();
delete newThread;
sem.Close();
RThread().Kill(ret);
break;
case ECreateKillSurface:
newThread->CreateSurfaceThread();
sem.Signal();
delete newThread;
sem.Close();
RThread().Kill(ret);
break;
case EOpenCloseSurfaceMultiThread:
newThread->OpenSurface();
sem.Signal();
RThread().Suspend();
newThread->CloseSurface();
delete newThread;
sem.Close();
return ret;
case ECloseBothSurfaces:
newThread->CloseBothSurfaces();
sem.Signal();
delete newThread;
break;
default:
break;
}
}
__UHEAP_MARKEND;
sem.Close();
TInt procHandles2 =0;
TInt threadHandles2=0;
RThread().HandleCount(procHandles2,threadHandles2);
if (threadHandles1 != threadHandles2)
{
ret = KErrGeneral; // Thread-owned handles not closed
}
return ret;
}
// Implementation of CChildThreadWrapper class
CChildThreadWrapper::CChildThreadWrapper(TAny* aInfo) :
iSurfaceManager (((TInfo*)aInfo)->iSurfaceManager),
iSurfaceId(((TInfo*)aInfo)->iSurfaceId),
iSurfaceIdNew(((TInfo*)aInfo)->iSurfaceIdNew),
iThreadTestCase(((TInfo*)aInfo)->iThreadTestCase)
{
}
CChildThreadWrapper::~CChildThreadWrapper()
{
}
void CChildThreadWrapper::CreateSurfaceThread()
{
// Setup attributes
RSurfaceManager::TSurfaceCreationAttributesBuf buf;
RSurfaceManager::TSurfaceCreationAttributes& attributes = buf();
attributes.iSize = TSize(200,200);
attributes.iBuffers = 1;
attributes.iPixelFormat = EUidPixelFormatARGB_1555;
attributes.iStride = 1024;
attributes.iOffsetToFirstBuffer = 80;
attributes.iAlignment = 8;
attributes.iContiguous=ETrue;
RSurfaceManager::THintPair hints[2]; // two hint pairs specified
attributes.iHintCount = 2;
attributes.iSurfaceHints = hints;
hints[0].Set(TUid::Uid(0x124578), 25, ETrue);
hints[1].Set(TUid::Uid(0x237755), 50, ETrue);
attributes.iCacheAttrib = RSurfaceManager::ECached;
attributes.iOffsetBetweenBuffers = 0;
attributes.iMappable = ETrue;
if (KErrNone == iSurfaceManager.CreateSurface(buf,iSurfaceId))
{
testResult |= ECreateSurfaceTestPassed;
}
else
{
testResult |= ECreateSurfaceTestFailed;
}
// record the surfaceId as a global variable
globalSurfaceId = iSurfaceId;
}
void CChildThreadWrapper::MapSurfaceInfo()
{
// Access the surface and pass back the test results to the main thread
RChunk handle;
// Call Map Surface
if (iSurfaceManager.MapSurface(iSurfaceId,handle)== KErrNone)
{
testResult |= EMapSurfaceTestPassed;
}
else
{
testResult |= EMapSurfaceTestFailed;
}
handle.Close();
RSurfaceManager::TInfoBuf infoBuf;
// Call Surface Info
if (iSurfaceManager.SurfaceInfo(iSurfaceId, infoBuf) == KErrNone)
{
testResult |= ESurfaceInfoTestPassed;
}
else
{
testResult |= ESurfaceInfoTestFailed;
}
}
void CChildThreadWrapper::CloseSurface()
{
// Call close surface and pass back the results to the main thread
if (iSurfaceManager.CloseSurface(iSurfaceId) == KErrNone)
{
testResult |= ECloseSurfaceTestPassed;
}
else
{
testResult |= ECloseSurfaceTestFailed;
}
}
void CChildThreadWrapper::OpenSurface()
{
// Call close surface and pass back the results to the main thread
if (iSurfaceManager.OpenSurface(iSurfaceId) == KErrNone)
{
testResult |= EOpenSurfaceTestPassed;
}
else
{
testResult |= EOpenSurfaceTestFailed;
}
}
void CChildThreadWrapper::CloseBothSurfaces()
{
// Call close surface and pass back the results to the main thread
if (iSurfaceManager.CloseSurface(iSurfaceIdNew) == KErrNone)
{
testResult |= ECloseSurfaceTestPassed;
}
else
{
testResult |= ECloseSurfaceTestFailed;
}
RSurfaceManager::TInfoBuf infoBuf;
// Call Surface Info
if (iSurfaceManager.SurfaceInfo(iSurfaceId, infoBuf) == KErrNone)
{
testResult |= ESurfaceInfoTestPassed;
}
else
{
testResult |= ESurfaceInfoTestFailed;
}
if (iSurfaceManager.SurfaceInfo(iSurfaceIdNew, infoBuf) == KErrArgument)
{
testResult |= ESurfaceInfoTestPassed2;
}
else
{
testResult |= ESurfaceInfoTestFailed2;
}
iSurfaceManager.CloseSurface(iSurfaceId);
}
/**
The third thread entry point
*/
TInt CTSurfaceManagerMultiThread::ThreadThirdStart(TAny* aInfo)
{
TInt procHandles1 =0;
TInt threadHandles1=0;
RThread().HandleCount(procHandles1, threadHandles1);
__UHEAP_MARK;
CTrapCleanup* cleanupStack=CTrapCleanup::New();
if (cleanupStack==NULL)
{
return KErrNoMemory;
}
CChildThreadWrapper* newThread = new CChildThreadWrapper(aInfo);
if (newThread==NULL)
{
delete cleanupStack;
return KErrNoMemory;
}
// Pass control back to the first process
RSemaphore sem;
TInt ret = sem.OpenGlobal(KMultiThreadSemaphore);
if (ret!=KErrNone)
return ret;
TInt err = KErrNone;
TThreadTestCase testCase = newThread->iThreadTestCase;
switch (testCase)
{
case EOpenMapSurfaceInfoMultiThread:
newThread->OpenSurface();
sem.Signal();
RThread().Suspend();
newThread->MapSurfaceInfo();
break;
case EOpenCloseMapSurfaceInfoMultiThread:
newThread->OpenSurface();
sem.Signal();
RThread().Suspend();
newThread->CloseSurface();
newThread->MapSurfaceInfo();
break;
case EOpenCloseOpenMultiThread:
newThread->OpenSurface();
sem.Signal();
RThread().Suspend();
newThread->CloseSurface();
newThread->OpenSurface();
break;
default:
break;
}
delete newThread;
delete cleanupStack;
__UHEAP_MARKEND;
sem.Close();
TInt procHandles2 =0;
TInt threadHandles2=0;
RThread().HandleCount(procHandles2,threadHandles2);
if (threadHandles1 != threadHandles2)
{
err = KErrGeneral; // Thread-owned handles not closed
}
return err;
}
//--------------
__CONSTRUCT_STEP__(SurfaceManagerMultiThread)
void CTSurfaceManagerMultiThreadStep::TestSetupL()
{
}
void CTSurfaceManagerMultiThreadStep::TestClose()
{
}