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