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: }