--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicshwdrivers/surfacemgr/test/src/tsurfacemanagermultithread.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1849 @@
+// 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()
+ {
+ }