os/graphics/graphicscomposition/surfaceupdate/src/surfaceupdateserver.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/graphicscomposition/surfaceupdate/src/surfaceupdateserver.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1112 @@
     1.4 +// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "surfaceupdateserver.h"
    1.20 +
    1.21 +#include <graphics/compositionsurfaceupdate.h>
    1.22 +#include <graphics/extensioncontainer.h>
    1.23 +
    1.24 +#include "surfaceupdate.h"
    1.25 +#include "suerror.h"
    1.26 +#ifdef TEST_SURFACE_UPDATE
    1.27 +#include "surfaceupdatetest.h"
    1.28 +#endif
    1.29 +
    1.30 +
    1.31 +const TUint KDefaultHeapSize=0x10000;
    1.32 +
    1.33 +void *gProvider = NULL;
    1.34 +RFastLock gProviderFastLock;
    1.35 +
    1.36 +/**
    1.37 +The server maintains session with the clients. 
    1.38 +It starts during the initialization of the Content update receiver thread.  
    1.39 +*/
    1.40 +CSurfaceUpdateServer* CSurfaceUpdateServer::NewL()
    1.41 +	{
    1.42 +	CSurfaceUpdateServer* server = new (ELeave) CSurfaceUpdateServer(EPriorityStandard);
    1.43 +	CleanupStack::PushL(server);
    1.44 +	server->ConstructL();
    1.45 +	CleanupStack::Pop();
    1.46 +	return server;	
    1.47 +	}
    1.48 +	
    1.49 +CSurfaceUpdateServer::CSurfaceUpdateServer(CActive::TPriority aPriority) :
    1.50 +	CServer2(aPriority)
    1.51 +	{
    1.52 +	}
    1.53 +	
    1.54 +CSurfaceUpdateServer::~CSurfaceUpdateServer()
    1.55 +	{
    1.56 +	iUpdateReceiver.Close();
    1.57 +	iUpdateReceiverPriorityOrder.ResetAndDestroy();
    1.58 +	delete iServerProvider;
    1.59 +	}	
    1.60 +	
    1.61 +void CSurfaceUpdateServer::ConstructL()
    1.62 +	{
    1.63 +	iServerProvider = CSurfaceUpdateServerProvider::NewL(EPriorityStandard, this);
    1.64 +	}
    1.65 +	
    1.66 +/**
    1.67 +Assign Content update receiver instance to particular screen. 
    1.68 +The following calls of this function will override the previous. 
    1.69 +
    1.70 +@see MSurfaceUpdateServerProvider::Register
    1.71 +*/	
    1.72 +TInt CSurfaceUpdateServer::Register(TInt aScreen, CBase* aUpdateReceiver, TInt aPriority)
    1.73 +	{
    1.74 +	if(aScreen < 0)
    1.75 +		{
    1.76 +		return KErrArgument;
    1.77 +		}
    1.78 +		
    1.79 +	TInt err = KErrNone;
    1.80 +	while((iUpdateReceiver.Count() <= aScreen) && (err == KErrNone))
    1.81 +		{
    1.82 +		err = iUpdateReceiver.Append(NULL);
    1.83 +		}
    1.84 +	
    1.85 +	if(err == KErrNone)
    1.86 +		{
    1.87 +		TUpdateReceiverPriorityEntry *receiverPriorityEntry = NULL; 
    1.88 +		if(!aUpdateReceiver)
    1.89 +			{//Client wants to unregister the Content update receiver which has been associated with the given screen number.
    1.90 +			MCompositionSurfaceUpdate* receiver = iUpdateReceiver[aScreen];
    1.91 +			if(receiver)
    1.92 +				{
    1.93 +				TInt num = iUpdateReceiverPriorityOrder.Count() - 1;
    1.94 +				for(;;)
    1.95 +					{//Content update receiver must be in priority list, therefore we don't need to check num >= 0
    1.96 +					receiverPriorityEntry = iUpdateReceiverPriorityOrder[num];
    1.97 +					if(receiverPriorityEntry->iUpdateReceiver == receiver)
    1.98 +						{//remove the Content update receiver from the priority list
    1.99 +						iUpdateReceiverPriorityOrder.Remove(num);
   1.100 +						delete receiverPriorityEntry;
   1.101 +						break;
   1.102 +						}
   1.103 +					num--;
   1.104 +					}
   1.105 +				iUpdateReceiver[aScreen] = NULL; //unregister the Content update receiver by setting the entry to NULL
   1.106 +				}
   1.107 +			}
   1.108 +		else
   1.109 +			{
   1.110 +	        CExtensionContainer* extCont=static_cast<CExtensionContainer*>(aUpdateReceiver);
   1.111 +	        MCompositionSurfaceUpdate* updateReceiver=extCont->GetInterface<MCompositionSurfaceUpdate>();
   1.112 +	        if (updateReceiver)
   1.113 +	            {
   1.114 +                receiverPriorityEntry = new TUpdateReceiverPriorityEntry;
   1.115 +                if(!receiverPriorityEntry)
   1.116 +                    return KErrNoMemory;
   1.117 +                receiverPriorityEntry->iPriority = aPriority;
   1.118 +                receiverPriorityEntry->iUpdateReceiver = updateReceiver;
   1.119 +        
   1.120 +                err = iUpdateReceiverPriorityOrder.InsertInOrder(receiverPriorityEntry, CSurfaceUpdateServer::CompareUpdateReceiverPriority);
   1.121 +                if(err == KErrNone)
   1.122 +                    {
   1.123 +                    iUpdateReceiver[aScreen] = updateReceiver;
   1.124 +                    }
   1.125 +                else
   1.126 +                    {
   1.127 +                    delete receiverPriorityEntry;
   1.128 +                    }
   1.129 +	            }
   1.130 +	        else
   1.131 +	            {
   1.132 +	            err=KErrArgument;
   1.133 +	            }
   1.134 +			}	
   1.135 +		}
   1.136 +	return err;
   1.137 +	}
   1.138 +
   1.139 +/**
   1.140 +Create a new session with a server. Derived from CSession2.
   1.141 +
   1.142 +@param aVersion required version of the server
   1.143 +@param aMessage message from the client.
   1.144 +@return New instance of the CSurfaceUpdateSession.
   1.145 +*/
   1.146 +CSession2* CSurfaceUpdateServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
   1.147 +	{
   1.148 +      // Check that the version is OK
   1.149 +	TVersion v(KSurfaceUpdateServMajorVersionNumber,KSurfaceUpdateServMinorVersionNumber,KSurfaceUpdateServBuildVersionNumber);
   1.150 +	if (!User::QueryVersionSupported(v,aVersion))
   1.151 +		User::Leave(KErrNotSupported);	
   1.152 +	
   1.153 +	// Security is not an issue, any client can have connection to the server	
   1.154 +	// Create the session.
   1.155 +	return new (ELeave) CSurfaceUpdateSession(UpdateReceiverPriority());
   1.156 +	}
   1.157 +
   1.158 +/**
   1.159 +Utility function to panic the server
   1.160 +
   1.161 +@param aPanic Panic code
   1.162 +*/
   1.163 +void CSurfaceUpdateServer::PanicServer(TSurfaceUpdateServPanic aPanic)
   1.164 +	{
   1.165 +	_LIT(KTxtServerPanic,"Surface Update Server panic");
   1.166 +	User::Panic(KTxtServerPanic, aPanic);
   1.167 +	}
   1.168 +
   1.169 +/**
   1.170 +Provide composition receiver.
   1.171 +
   1.172 +@param aScreen targeted screen
   1.173 +@return Composition receiver object, associated to particular screen
   1.174 +*/
   1.175 +MCompositionSurfaceUpdate* CSurfaceUpdateServer::UpdateReceiver(TInt aScreen) const
   1.176 +	{
   1.177 +	if(aScreen >= iUpdateReceiver.Count())//negative value won't reach this point 
   1.178 +		return NULL;
   1.179 +	return iUpdateReceiver[aScreen];	
   1.180 +	}
   1.181 +
   1.182 +TInt CSurfaceUpdateServer::ThreadFunction(TAny* aAny)
   1.183 +	{
   1.184 +	  // get clean-up stack
   1.185 +	CTrapCleanup* cleanup=CTrapCleanup::New();
   1.186 +	__ASSERT_ALWAYS(cleanup!=NULL, CSurfaceUpdateServer::PanicServer(EUpdateServPanicNoMemory));
   1.187 +	
   1.188 +	  // create an active scheduler and server
   1.189 +	CActiveScheduler *pA = new CActiveScheduler;
   1.190 +	__ASSERT_ALWAYS(pA != NULL, CSurfaceUpdateServer::PanicServer(EUpdateServPanicNoMemory));
   1.191 +
   1.192 +	  //Install the active scheduler
   1.193 +	CActiveScheduler::Install(pA);
   1.194 +
   1.195 +	CSurfaceUpdateServer *pS = NULL;
   1.196 +	TRAPD(err, pS = CSurfaceUpdateServer::NewL());
   1.197 +	__ASSERT_ALWAYS(err == KErrNone, CSurfaceUpdateServer::PanicServer(EUpdateServPanicNoMemory));
   1.198 +	
   1.199 +	  // Start the server
   1.200 +#ifndef TEST_SURFACE_UPDATE
   1.201 +	err = pS->Start(KSurfaceUpdateServerName);
   1.202 +#else
   1.203 +	err = pS->Start(KTestSurfaceUpdateServerName);
   1.204 +#endif
   1.205 +	
   1.206 +	if (err != KErrNone)
   1.207 +		{
   1.208 +		CSurfaceUpdateServer::PanicServer(EUpdateServPanicStartUp);
   1.209 +		}
   1.210 +	*(static_cast <MSurfaceUpdateServerProvider**> (aAny)) = pS->SurfaceUpdateProvider();
   1.211 +      
   1.212 +      // Let everyone know that we are ready to
   1.213 +      // deal with requests.
   1.214 +	RThread::Rendezvous(KErrNone);
   1.215 +	  // And start fielding requests from client(s).
   1.216 +	CActiveScheduler::Start();
   1.217 +
   1.218 +     // Tidy up... 	
   1.219 +	delete pS;
   1.220 +	delete pA;
   1.221 +	delete cleanup; 
   1.222 +	
   1.223 +	return KErrNone;
   1.224 +	}
   1.225 +
   1.226 +inline TInt CSurfaceUpdateServer::NumUpdateReceivers() const
   1.227 +	{
   1.228 +	return iUpdateReceiver.Count(); 
   1.229 +	}
   1.230 +
   1.231 +/**
   1.232 +Compare two content update receiver entries according to their priority. 
   1.233 +The function is used when receiver priority entry is inserted/retrieved from the array (iCompReceiverPriorityOrder).
   1.234 +
   1.235 +@return zero, if the priorities of two receivers are equal; 
   1.236 +a negative value, if the priority of the first receiver is less than the priority of the second one; 
   1.237 +a positive value, if the priority of the first receiver is greater than the priority of the second one.
   1.238 +*/
   1.239 +TInt CSurfaceUpdateServer::CompareUpdateReceiverPriority(const TUpdateReceiverPriorityEntry& aEntry1, const TUpdateReceiverPriorityEntry& aEntry2)
   1.240 +	{
   1.241 +	return aEntry2.iPriority - aEntry1.iPriority;
   1.242 +	}
   1.243 +
   1.244 +/**
   1.245 +class CSurfaceUpdateSession
   1.246 +
   1.247 +Maintain the channel between clients and the server. 
   1.248 +Functions are provided will respond appropriately to client messages. 
   1.249 +*/
   1.250 +
   1.251 +CSurfaceUpdateSession::CSurfaceUpdateSession(const RPointerArray<TUpdateReceiverPriorityEntry>& aEntryList) :
   1.252 +	CSession2(),
   1.253 +	iUpdateReceiverEntryList(aEntryList)
   1.254 +	{
   1.255 +	}
   1.256 +
   1.257 +/**
   1.258 +Cancel any outstanding client notification requests. 
   1.259 +All resources owned by the session will either be immediately released or 
   1.260 +scheduled for deferred deletion.
   1.261 +*/
   1.262 +CSurfaceUpdateSession::~CSurfaceUpdateSession()
   1.263 +	{
   1.264 +	CancelAllUpdateNotifications();
   1.265 +	iUpdateReceiverNotificationBatches.ResetAndDestroy();
   1.266 +	}
   1.267 +
   1.268 +/**
   1.269 +Main function which deals with requests from clients.
   1.270 +*/	
   1.271 +void CSurfaceUpdateSession::ServiceL(const RMessage2& aMessage)
   1.272 +	{
   1.273 +	switch (aMessage.Function())
   1.274 +		{
   1.275 +	case EUpdateServNotifyWhenAvailable:
   1.276 +		NotifyWhenAvailable(aMessage);
   1.277 +		return;
   1.278 +	case EUpdateServNotifyWhenDisplayed:
   1.279 +		NotifyWhenDisplayed(aMessage);
   1.280 +		return;
   1.281 +	case EUpdateServNotifyWhenDisplayedXTimes:
   1.282 +		NotifyWhenDisplayedXTimes(aMessage);
   1.283 +		return;
   1.284 +	case EUpdateServSubmitUpdate:
   1.285 +		SubmitUpdate(aMessage);
   1.286 +		return;
   1.287 +	case EUpdateServCancelAllNotifications:
   1.288 +		CancelAllUpdateNotifications();
   1.289 +		aMessage.Complete(KErrNone);
   1.290 +		return;
   1.291 +#ifdef TEST_SURFACE_UPDATE
   1.292 +	case EUpdateServOOM:
   1.293 +		{
   1.294 +		SetHeapFailure(aMessage);
   1.295 +		return;
   1.296 +		}
   1.297 +#endif
   1.298 +	default:
   1.299 +		PanicClient(aMessage, EUpdateServPanicBadRequest);
   1.300 +		return;
   1.301 +		}	 
   1.302 +	}
   1.303 +
   1.304 +#ifdef TEST_SURFACE_UPDATE
   1.305 +/**
   1.306 +  Simulate heap allocation failure for the SUS thread's heap.
   1.307 +  Aim for OOM testing.
   1.308 + */
   1.309 +void CSurfaceUpdateSession::SetHeapFailure(const RMessage2& aMessage)
   1.310 +	{
   1.311 +	TInt numElement = iUpdateReceiverNotificationBatches.Count();
   1.312 +	TInt index = 0;
   1.313 +	while(numElement)
   1.314 +		{
   1.315 +		CUpdateReceiverNotificationBatch* batch = iUpdateReceiverNotificationBatches[index];
   1.316 +		if(batch->iType == EUpdateSrvReusable)
   1.317 +			{
   1.318 +			iUpdateReceiverNotificationBatches.Remove(index);
   1.319 +			delete batch;
   1.320 +			}
   1.321 +		else
   1.322 +			{
   1.323 +			index++;
   1.324 +			}
   1.325 +		numElement--;            
   1.326 +		}
   1.327 +	if(numElement == 0)
   1.328 +		{
   1.329 +		iUpdateReceiverNotificationBatches.Reset();
   1.330 +		}
   1.331 +	TInt failRate = aMessage.Int0();
   1.332 +	if(!failRate)
   1.333 +		{
   1.334 +		__UHEAP_RESET;
   1.335 +		}
   1.336 +	else
   1.337 +		{
   1.338 +		__UHEAP_SETFAIL(RHeap::EDeterministic, failRate);
   1.339 +		}
   1.340 +	aMessage.Complete(KErrNone);
   1.341 +	}
   1.342 +#endif
   1.343 +
   1.344 +void CSurfaceUpdateSession::PanicClient(const RMessage2& aMessage, TInt aPanic) const
   1.345 +	{
   1.346 +	_LIT(KTxtServer,"SurfUpServ");
   1.347 +	aMessage.Panic(KTxtServer, aPanic);
   1.348 +	}
   1.349 +
   1.350 +/**
   1.351 +Return first inactive spare notification object stored in the notification array, 
   1.352 +create a new one if fail to find it in the array.
   1.353 +*/	
   1.354 +CUpdateReceiverNotificationBatch* CSurfaceUpdateSession::UpdateReceiverNotificationBatchL()
   1.355 +	{
   1.356 +	TInt numElement = iUpdateReceiverNotificationBatches.Count();
   1.357 +	CUpdateReceiverNotificationBatch* notifier = NULL;
   1.358 +	CSurfaceUpdateServer* server = (CSurfaceUpdateServer*) Server();
   1.359 +	for(TInt index = 0; index < numElement; index++)
   1.360 +		{
   1.361 +		notifier = iUpdateReceiverNotificationBatches[index];
   1.362 +		if(notifier->iType == EUpdateSrvReusable)
   1.363 +			{
   1.364 +			__ASSERT_ALWAYS(notifier->iMsg.IsNull(), CSurfaceUpdateServer::PanicServer(EUpdateServPanicDataIntegrity));
   1.365 +            notifier->SetNumUpdateReceivers(server->NumUpdateReceivers());
   1.366 +			if(numElement > index + 1)
   1.367 +				{
   1.368 +			//to improve a search, append the element to the end of the array
   1.369 +				iUpdateReceiverNotificationBatches.Remove(index);
   1.370 +				iUpdateReceiverNotificationBatches.AppendL(notifier);
   1.371 +				}
   1.372 +			return notifier;
   1.373 +			}
   1.374 +		}
   1.375 +	
   1.376 +	notifier = new (ELeave) CUpdateReceiverNotificationBatch(this, server->NumUpdateReceivers());
   1.377 +	CleanupStack::PushL(notifier);
   1.378 +	iUpdateReceiverNotificationBatches.AppendL(notifier);
   1.379 +	CleanupStack::Pop();
   1.380 +	
   1.381 +	return notifier;
   1.382 +	}
   1.383 +	
   1.384 +void CSurfaceUpdateSession::NotifyWhenAvailable(const RMessage2& aMessage)
   1.385 +	{
   1.386 +	StoreNotification(iAvailable, aMessage, EUpdateSrvAvailable);
   1.387 +	}
   1.388 +	
   1.389 +void CSurfaceUpdateSession::NotifyWhenDisplayed(const RMessage2& aMessage)
   1.390 +	{
   1.391 +	StoreNotification(iDisplayed, aMessage, EUpdateSrvDisplayed);
   1.392 +	}
   1.393 +	
   1.394 +void CSurfaceUpdateSession::NotifyWhenDisplayedXTimes(const RMessage2& aMessage)
   1.395 +	{
   1.396 +	StoreNotification(iDisplayedXTimes, aMessage, EUpdateSrvDisplayedXTimes);
   1.397 +	}
   1.398 +
   1.399 +void CSurfaceUpdateSession::StoreNotification(CUpdateReceiverNotificationBatch*& aNotifier, const RMessage2& aMessage, TNotificationType aType)
   1.400 +	{
   1.401 +	if(aNotifier)
   1.402 +		{
   1.403 +		if(!aNotifier->iMsg.IsNull())
   1.404 +			{//not expected behaviour
   1.405 +			//would happen if a client sends the same notification request in a row
   1.406 +			IssueRequestComplete(KErrCancel);
   1.407 +			PanicClient(aMessage, EUpdateServPanicDataIntegrity);
   1.408 +			return;
   1.409 +			}
   1.410 +		}
   1.411 +	else
   1.412 +		{
   1.413 +		TRAPD(res, aNotifier = UpdateReceiverNotificationBatchL());
   1.414 +		if(res != KErrNone)
   1.415 +			{
   1.416 +			aMessage.Complete(res);
   1.417 +			return;
   1.418 +			}
   1.419 +		}	
   1.420 +	
   1.421 +	aNotifier->iMsg = aMessage;
   1.422 +	aNotifier->iType=aType;
   1.423 +	}
   1.424 +
   1.425 +/*
   1.426 +Complete the outstanding requests and reset internal request variables to zero.
   1.427 +@param aErr Error code for completion.   
   1.428 +*/ 	
   1.429 +void CSurfaceUpdateSession::IssueRequestComplete(TInt aErr)
   1.430 +	{
   1.431 +	if(iAvailable)
   1.432 +		{
   1.433 +		if(!iAvailable->iMsg.IsNull())
   1.434 +			{
   1.435 +			iAvailable-> iMsg.Complete(aErr);
   1.436 +			iAvailable->CheckForReuse();	 
   1.437 +			}
   1.438 +		iAvailable = NULL;
   1.439 +		}
   1.440 +
   1.441 +	if(iDisplayed)
   1.442 +		{
   1.443 +		if(!iDisplayed -> iMsg.IsNull())
   1.444 +			{
   1.445 +			iDisplayed -> iMsg.Complete(aErr);
   1.446 +			iDisplayed->CheckForReuse();
   1.447 +			}
   1.448 +		iDisplayed = NULL;
   1.449 +		}
   1.450 +
   1.451 +	if(iDisplayedXTimes)
   1.452 +		{
   1.453 +		if(!iDisplayedXTimes->iMsg.IsNull())
   1.454 +			{
   1.455 +			iDisplayedXTimes->iMsg.Complete(aErr);
   1.456 +			iDisplayedXTimes->CheckForReuse();
   1.457 +			}
   1.458 +		iDisplayedXTimes=NULL;
   1.459 +		}
   1.460 +	}
   1.461 +
   1.462 +/**
   1.463 +Redirect call to the DoSubmitUpdateL; error handling
   1.464 +*/
   1.465 +void CSurfaceUpdateSession::SubmitUpdate(const RMessage2& aMessage)
   1.466 +	{
   1.467 +	TInt err = KErrNone;
   1.468 +	TRAP(err, DoSubmitUpdateL(aMessage));
   1.469 +	if(err != KErrNone)
   1.470 +		{
   1.471 +		IssueRequestComplete(err);
   1.472 +		}
   1.473 +	aMessage.Complete(err);	
   1.474 +	}
   1.475 +
   1.476 +/**
   1.477 +Issue request for the update to the composition receiver; 
   1.478 +ask notification on composition event if required.
   1.479 +*/	
   1.480 +void CSurfaceUpdateSession::DoSubmitUpdateL(const RMessage2& aMessage)
   1.481 +	{
   1.482 +	TInt displayedXTimes = 0;
   1.483 +	TInt screen;
   1.484 +	TInt buffer;
   1.485 +	TSurfaceId surfaceId;
   1.486 +	TPckg<TSurfaceId> surfaceIdPckg(surfaceId);
   1.487 +
   1.488 +	RRegion *region = NULL;
   1.489 +	TRect *rectangleList = NULL;
   1.490 +
   1.491 +	//extract the composition data
   1.492 +	aMessage.ReadL(1, surfaceIdPckg);
   1.493 +	
   1.494 +	screen = aMessage.Int0();
   1.495 +	buffer = aMessage.Int2();
   1.496 +	
   1.497 +	//validate parameters
   1.498 +	if((screen < 0) || (buffer < 0))
   1.499 +		{
   1.500 +		User::Leave(KErrArgument);
   1.501 +		}
   1.502 +	//Check that we haven't used another update method before
   1.503 +	//The comparison is slightly optimized for performance as oppose to code size
   1.504 +	if(iUpdateMethod == EUpdateMethodGlobal) 
   1.505 +		{
   1.506 +		if(screen != KAllScreens)
   1.507 +			User::Leave(KErrNotSupported);
   1.508 +		}
   1.509 +	else if(iUpdateMethod == EUpdateMethodPerScreen) 
   1.510 +		{
   1.511 +		if(screen == KAllScreens)
   1.512 +			User::Leave(KErrNotSupported);
   1.513 +		}
   1.514 +	
   1.515 +	TInt len = aMessage.GetDesLength(3);
   1.516 +	if(len > 0)
   1.517 +		{
   1.518 +		rectangleList = (TRect*) (User::AllocL(len));
   1.519 +		CleanupStack::PushL(rectangleList);
   1.520 +		TPtr8 ptrRect(reinterpret_cast<TUint8*> (rectangleList), len);
   1.521 +		aMessage.ReadL(3, ptrRect);
   1.522 +		TInt regionCount = len / sizeof(TRect);
   1.523 +		region = new (ELeave) RRegion(regionCount, rectangleList);
   1.524 +		CleanupStack::PushL(region);
   1.525 +		}
   1.526 +	if(iDisplayedXTimes)
   1.527 +		{
   1.528 +		displayedXTimes = iDisplayedXTimes -> iMsg.Int0();
   1.529 +		if(displayedXTimes < 1)
   1.530 +			{
   1.531 +			iDisplayedXTimes->iMsg.Complete(KErrArgument);
   1.532 +			iDisplayedXTimes->CheckForReuse();
   1.533 +			iDisplayedXTimes = NULL;
   1.534 +			}
   1.535 +		}
   1.536 +	
   1.537 +	const CSurfaceUpdateServer* server = static_cast <const CSurfaceUpdateServer*> (Server());	
   1.538 +	if(screen != KAllScreens)
   1.539 +		{
   1.540 +		MCompositionSurfaceUpdate* receiver = server->UpdateReceiver(screen);
   1.541 +		if(!receiver)
   1.542 +			{
   1.543 +			User::Leave(KErrUpdateReceiverNotAvailable);
   1.544 +			}
   1.545 +		DispatchUpdate(surfaceId, buffer, region, &displayedXTimes, receiver);
   1.546 +		iUpdateMethod = EUpdateMethodPerScreen;
   1.547 +		}
   1.548 +	else
   1.549 +		{
   1.550 +		DispatchUpdate(surfaceId, buffer, region, &displayedXTimes);
   1.551 +		iUpdateMethod = EUpdateMethodGlobal;
   1.552 +		}
   1.553 +				
   1.554 +	if(region)
   1.555 +		{
   1.556 +		CleanupStack::PopAndDestroy(2, rectangleList);
   1.557 +		}
   1.558 +	}
   1.559 +
   1.560 +/**
   1.561 + Dispatch update to the composition update receivers. 
   1.562 + The function could fail to allocate the notification objects 
   1.563 + due to memory shortage, however, the content update command will still be submitted to the GCE.  
   1.564 + */
   1.565 +void CSurfaceUpdateSession::DispatchUpdate(const TSurfaceId& aSurfaceId, TInt aBuffer, RRegion* aRegion, TInt* aDisplayedXTimes, MCompositionSurfaceUpdate* aReceiver)
   1.566 +	{
   1.567 +	TInt index = 1;
   1.568 +	TInt numReceivers = 1;
   1.569 +	TInt priority = 0;
   1.570 +	
   1.571 +	if(!aReceiver)
   1.572 +		{
   1.573 +		aReceiver = iUpdateReceiverEntryList[0]->iUpdateReceiver;
   1.574 +		priority = iUpdateReceiverEntryList[0]->iPriority;
   1.575 +		numReceivers = iUpdateReceiverEntryList.Count(); //get the number of all receivers present in the system
   1.576 +		}
   1.577 +	
   1.578 +	for(;;)
   1.579 +		{	
   1.580 +		CUpdateReceiverNotification* receiverNotificationAvailable = NULL;
   1.581 +		CUpdateReceiverNotification* receiverNotificationDisplayed = NULL;
   1.582 +		CUpdateReceiverNotification* receiverNotificationDisplayedXTimes = NULL;
   1.583 +		TUint32* timeStamp = NULL;
   1.584 +	
   1.585 +	//activate objects
   1.586 +		if(iAvailable)
   1.587 +			{
   1.588 +			receiverNotificationAvailable = iAvailable->UpdateReceiverNotification();
   1.589 +			if(!receiverNotificationAvailable)
   1.590 +				{
   1.591 +				iAvailable->iMsg.Complete(KErrNoMemory);
   1.592 +				iAvailable->CheckForReuse();
   1.593 +				iAvailable = NULL;
   1.594 +				}
   1.595 +			}
   1.596 +
   1.597 +		if(iDisplayed)
   1.598 +			{
   1.599 +			receiverNotificationDisplayed = iDisplayed->UpdateReceiverNotification(priority);
   1.600 +			if(!receiverNotificationDisplayed)
   1.601 +				{
   1.602 +				iDisplayed->iMsg.Complete(KErrNoMemory);
   1.603 +				iDisplayed->CheckForReuse();
   1.604 +				iDisplayed = NULL;
   1.605 +				}
   1.606 +			}
   1.607 +
   1.608 +		if(iDisplayedXTimes)
   1.609 +			{
   1.610 +			receiverNotificationDisplayedXTimes = iDisplayedXTimes->UpdateReceiverNotification();
   1.611 +			if(!receiverNotificationDisplayedXTimes)
   1.612 +				{
   1.613 +				iDisplayedXTimes->iMsg.Complete(KErrNoMemory);
   1.614 +				iDisplayedXTimes->CheckForReuse();
   1.615 +				iDisplayedXTimes = NULL;
   1.616 +				}
   1.617 +			}
   1.618 +	
   1.619 +		TRequestStatus *statusAvailable = NULL;
   1.620 +		TRequestStatus *statusDisplayed = NULL;
   1.621 +		TRequestStatus *statusDisplayedXTimes = NULL;
   1.622 +	//activate all notifications
   1.623 +		if(receiverNotificationAvailable)
   1.624 +			{
   1.625 +			statusAvailable = &(receiverNotificationAvailable->Status());
   1.626 +			receiverNotificationAvailable->Activate();
   1.627 +			}
   1.628 +		if(receiverNotificationDisplayed)
   1.629 +			{
   1.630 +			statusDisplayed = &(receiverNotificationDisplayed->Status());
   1.631 +			timeStamp = & receiverNotificationDisplayed -> iTimeStamp;
   1.632 +			receiverNotificationDisplayed->Activate();
   1.633 +			}
   1.634 +		if(receiverNotificationDisplayedXTimes)
   1.635 +			{
   1.636 +			statusDisplayedXTimes = &(receiverNotificationDisplayedXTimes->Status());
   1.637 +			receiverNotificationDisplayedXTimes->Activate();
   1.638 +			}
   1.639 +	//And finally, send request to the receiver   
   1.640 +		aReceiver->ContentUpdated(aSurfaceId, aBuffer, aRegion,
   1.641 +				statusAvailable, statusDisplayed, timeStamp, 
   1.642 +				statusDisplayedXTimes, statusDisplayedXTimes ? aDisplayedXTimes : NULL);
   1.643 +	
   1.644 +		if(numReceivers > index)
   1.645 +			{
   1.646 +			priority = iUpdateReceiverEntryList[index]->iPriority;
   1.647 +			aReceiver = iUpdateReceiverEntryList[index++]->iUpdateReceiver;
   1.648 +			}
   1.649 +		else
   1.650 +			break;
   1.651 +		}//for(;;)
   1.652 +	
   1.653 +	iAvailable = NULL;
   1.654 +	iDisplayed = NULL;
   1.655 +	iDisplayedXTimes = NULL;
   1.656 +	}
   1.657 +
   1.658 +void CSurfaceUpdateSession::CancelAllUpdateNotifications()
   1.659 +	{
   1.660 +	//go through all notification objects and issue request complete for outstanding requests
   1.661 +	TInt count = iUpdateReceiverNotificationBatches.Count();
   1.662 +	
   1.663 +	for(TInt index = 0; index < count; index++)
   1.664 +		{
   1.665 +		CUpdateReceiverNotificationBatch* notifier = iUpdateReceiverNotificationBatches[index];
   1.666 +		if(!notifier->iMsg.IsNull())
   1.667 +			{
   1.668 +			notifier->iMsg.Complete(KErrCancel);
   1.669 +			}
   1.670 +		}
   1.671 +
   1.672 +	iAvailable = NULL;
   1.673 +	iDisplayed = NULL;
   1.674 +	iDisplayedXTimes = NULL;
   1.675 +	}
   1.676 +	
   1.677 +//*********************
   1.678 +CUpdateReceiverNotification::CUpdateReceiverNotification(CActive::TPriority aPriority, TInt aReceiverPriority, CUpdateReceiverNotificationBatch *aParentNotificationBatch) :
   1.679 +	CActive(aPriority), iUpdateReceiverPriority(aReceiverPriority), iParentNotificationBatch(aParentNotificationBatch)
   1.680 +	{
   1.681 +	CActiveScheduler::Add(this);
   1.682 +#ifdef TEST_SURFACE_UPDATE
   1.683 +	iServer = iParentNotificationBatch->Server();
   1.684 +#endif
   1.685 +	}
   1.686 +	
   1.687 +CUpdateReceiverNotification::~CUpdateReceiverNotification()
   1.688 +	{
   1.689 +	//Content updates can not be cancelled. The user must ensure that the associated content update 
   1.690 +	//is complete before deleting this object.
   1.691 +	__ASSERT_ALWAYS(!IsActive(), CSurfaceUpdateServer::PanicServer(EUpdateServPanicDataIntegrity));
   1.692 +	}
   1.693 +	
   1.694 +void CUpdateReceiverNotification::DoCancel()
   1.695 +	{
   1.696 +	//Content Updates can not be cancelled. Content Updates must be allowed to complete normally.
   1.697 +	CSurfaceUpdateServer::PanicServer(EUpdateServPanicDataIntegrity);
   1.698 +	}
   1.699 +
   1.700 +/**
   1.701 +Is triggered every time the GCE signals on notification objects.
   1.702 +Delegates processing to the parent notification batch.   
   1.703 +*/	
   1.704 +void CUpdateReceiverNotification::RunL()
   1.705 +	{
   1.706 +	// CReceiverNotification object is deleted here once it is set to self destroying when run.
   1.707 +	if (iSelfDestructWhenRun)
   1.708 +		{
   1.709 +#ifdef TEST_SURFACE_UPDATE
   1.710 +		DecNumberPendingNotifications();
   1.711 +#endif
   1.712 +		delete this;
   1.713 +		return;
   1.714 +		}
   1.715 +	iParentNotificationBatch->ProcessNotificationEvent(this);
   1.716 +	}
   1.717 +	
   1.718 +TRequestStatus& CUpdateReceiverNotification::Status()
   1.719 +	{
   1.720 +	return iStatus;	
   1.721 +	}
   1.722 +
   1.723 +void CUpdateReceiverNotification::Activate()
   1.724 +	{
   1.725 +	iStatus = KRequestPending;
   1.726 +	SetActive();
   1.727 +	}
   1.728 +
   1.729 +#ifdef TEST_SURFACE_UPDATE
   1.730 +void CUpdateReceiverNotification::DecNumberPendingNotifications()
   1.731 +	{
   1.732 +	if (iServer)
   1.733 +		{
   1.734 +		iServer-> iNumberPendingNotification--;
   1.735 +		}
   1.736 +	}
   1.737 +#endif
   1.738 +
   1.739 +/**
   1.740 +The class maintains the notification objects of the same type and attributed to a 
   1.741 +particular submit update command.   
   1.742 + */
   1.743 +CUpdateReceiverNotificationBatch::CUpdateReceiverNotificationBatch(CSurfaceUpdateSession *aSession, TInt aNumReceivers) :
   1.744 +	iSession(aSession), iNumUpdateReceivers(aNumReceivers)
   1.745 +	{
   1.746 +	CheckForReuse();
   1.747 +	}
   1.748 +
   1.749 +CUpdateReceiverNotificationBatch::~CUpdateReceiverNotificationBatch()
   1.750 +	{
   1.751 +	TInt count = iUpdateReceiverNotifications.Count();
   1.752 +	for(TInt index = 0; index < count; index++)
   1.753 +		{
   1.754 +		CUpdateReceiverNotification* notifier = iUpdateReceiverNotifications[index];
   1.755 +		// CReceiverNotification active object cannot be destroyed if it is active and waiting for
   1.756 +		// receiver to complete the notification. It deletes itself inside its RunL function when the
   1.757 +		// notification is completed.
   1.758 +		if (notifier->IsActive())
   1.759 +			{
   1.760 +			notifier->iSelfDestructWhenRun = ETrue;
   1.761 +#ifdef TEST_SURFACE_UPDATE
   1.762 +			IncNumberPendingNotifications();
   1.763 +#endif
   1.764 +			}
   1.765 +		else
   1.766 +			{
   1.767 +			delete notifier;
   1.768 +			}
   1.769 +		}
   1.770 +	iUpdateReceiverNotifications.Close();
   1.771 +	}
   1.772 +
   1.773 +/**
   1.774 +The function processes signal from composition receiver. 
   1.775 +It completes outstanding messages on the client and set timestamp parameters if appropriate.
   1.776 +Note that this object will not be removed from the 
   1.777 +array (CSurfaceUpdateSession:: iReceiverNotifications) and can be reused later.
   1.778 +*/
   1.779 +void CUpdateReceiverNotificationBatch::ProcessNotificationEvent(CUpdateReceiverNotification* aReceiverNotification)
   1.780 +	{
   1.781 +	TInt index = iUpdateReceiverNotifications.Find(aReceiverNotification);
   1.782 +	__ASSERT_DEBUG(index != KErrNotFound, CSurfaceUpdateServer::PanicServer(EUpdateServPanicDataIntegrity));
   1.783 +	iUpdateReceiverNotifications.Remove(index);
   1.784 +	if(iMsg.IsNull())
   1.785 +		{
   1.786 +		CheckForReuse();
   1.787 +		delete aReceiverNotification;
   1.788 +		return; // the message has already been completed, possibly, because of request cancelation
   1.789 +		}
   1.790 +	TBool oldCompleteWithSuccess = iCompleteWithSuccess;
   1.791 +	TBool newCompleteWithSuccess = EFalse;
   1.792 +	if(aReceiverNotification->iStatus.Int() == KErrNone)
   1.793 +		{
   1.794 +		iCompleteWithSuccess = ETrue;
   1.795 +		newCompleteWithSuccess = ETrue;
   1.796 +		}
   1.797 +	
   1.798 +	switch(iType)
   1.799 +		{
   1.800 +	case EUpdateSrvAvailable:
   1.801 +		if(iUpdateReceiverNotifications.Count() == 0)
   1.802 +			{
   1.803 +			TInt res = iCompleteWithSuccess ? KErrNone : aReceiverNotification->iStatus.Int();
   1.804 +			iMsg.Complete(res);
   1.805 +			}
   1.806 +		break;
   1.807 +	case EUpdateSrvDisplayedXTimes:
   1.808 +		if((newCompleteWithSuccess && (index == 0)) || (iUpdateReceiverNotifications.Count() == 0))
   1.809 +			{
   1.810 +			TInt res = iCompleteWithSuccess ? KErrNone : aReceiverNotification->iStatus.Int();
   1.811 +			iMsg.Complete(res);
   1.812 +			}
   1.813 +		break;
   1.814 +	case EUpdateSrvDisplayed:
   1.815 +		if(newCompleteWithSuccess && 
   1.816 +				((iHighestPriority < aReceiverNotification->iUpdateReceiverPriority) || !oldCompleteWithSuccess))
   1.817 +			{
   1.818 +			iHighestPriority = aReceiverNotification->iUpdateReceiverPriority;
   1.819 +			iTimeStamp = aReceiverNotification->iTimeStamp;
   1.820 +			}
   1.821 +		if((newCompleteWithSuccess && (index == 0)) || (iUpdateReceiverNotifications.Count() == 0))
   1.822 +			{
   1.823 +			TPckgBuf<TUint32> p(iTimeStamp);
   1.824 +			TInt res = iMsg.Write(0, p); //We must not leave here as it will cause panic on Active scheduler. This would be inappropriate for the server side thread.
   1.825 +			if(res == KErrNone)
   1.826 +				{
   1.827 +				res = iCompleteWithSuccess ? KErrNone : aReceiverNotification->iStatus.Int();
   1.828 +				}
   1.829 +			iMsg.Complete(res);
   1.830 +			}
   1.831 +		break;
   1.832 +	default:	
   1.833 +		break;
   1.834 +		}
   1.835 +	
   1.836 +	delete aReceiverNotification;
   1.837 +	CheckForReuse();
   1.838 +	}
   1.839 +
   1.840 +/**
   1.841 + The method allocates a notification object and inserts it into the list
   1.842 +*/ 
   1.843 +CUpdateReceiverNotification* CUpdateReceiverNotificationBatch::UpdateReceiverNotification(TInt aReceiverPriority)
   1.844 +	{
   1.845 +	__ASSERT_DEBUG(iNumUpdateReceivers > iUpdateReceiverNotifications.Count(), CSurfaceUpdateServer::PanicServer(EUpdateServPanicDataIntegrity));
   1.846 +	
   1.847 +	CUpdateReceiverNotification* receiverNotification = new CUpdateReceiverNotification(CActive::EPriorityStandard, aReceiverPriority, this);
   1.848 +	if(receiverNotification)
   1.849 +		{
   1.850 +		TInt res = iUpdateReceiverNotifications.Append(receiverNotification);
   1.851 +		if(res != KErrNone)
   1.852 +			{
   1.853 +			delete receiverNotification;
   1.854 +			receiverNotification = NULL;
   1.855 +			}
   1.856 +		}
   1.857 +	
   1.858 +	return receiverNotification;
   1.859 +	}
   1.860 +
   1.861 +/**
   1.862 +If notification list is empty mark the batch for further use
   1.863 +*/
   1.864 +void CUpdateReceiverNotificationBatch::CheckForReuse()
   1.865 +	{
   1.866 +	if(iUpdateReceiverNotifications.Count() == 0)
   1.867 +		{
   1.868 +		iType = EUpdateSrvReusable;
   1.869 +		iCompleteWithSuccess = EFalse;
   1.870 +		iHighestPriority = 0;
   1.871 +		iTimeStamp = 0;
   1.872 +		}
   1.873 +	}
   1.874 +
   1.875 +#ifdef TEST_SURFACE_UPDATE
   1.876 +CSurfaceUpdateServer* CUpdateReceiverNotificationBatch::Server()
   1.877 +	{
   1.878 +	return (CSurfaceUpdateServer*)(iSession->Server());
   1.879 +	}
   1.880 +
   1.881 +void CUpdateReceiverNotificationBatch::IncNumberPendingNotifications()
   1.882 +	{
   1.883 +	CServer2* server = static_cast<CServer2*> (Server());
   1.884 +	if(server)
   1.885 +		{
   1.886 +		(static_cast<CSurfaceUpdateServer*> (server))-> iNumberPendingNotification++;
   1.887 +		}
   1.888 +	}
   1.889 +#endif
   1.890 +
   1.891 +
   1.892 +/**
   1.893 +Set number of UpdateReceivers - called when update receivers are added/removed.
   1.894 +
   1.895 +@param aNumUpdateReceivers - new number of update receivers for the batch.
   1.896 + */
   1.897 +void CUpdateReceiverNotificationBatch::SetNumUpdateReceivers(TInt aNumUpdateReceivers)
   1.898 +    {
   1.899 +    __ASSERT_DEBUG(aNumUpdateReceivers >= 0 && aNumUpdateReceivers < 1000 /* arbitrary "large" limit */,
   1.900 +            CSurfaceUpdateServer::PanicServer(EUpdateServPanicDataIntegrity));
   1.901 +    __ASSERT_DEBUG(iType == EUpdateSrvReusable, 
   1.902 +            CSurfaceUpdateServer::PanicServer(EUpdateServPanicDataIntegrity));
   1.903 +    iNumUpdateReceivers = aNumUpdateReceivers;
   1.904 +    }
   1.905 +/**
   1.906 +
   1.907 +The class will be used by composition receiver
   1.908 +*/
   1.909 +CSurfaceUpdateServerProvider* CSurfaceUpdateServerProvider::NewL(CActive::TPriority aPriority, CSurfaceUpdateServer* aServer)
   1.910 +	{
   1.911 +	CSurfaceUpdateServerProvider* serverProvider = new (ELeave) CSurfaceUpdateServerProvider(aPriority, aServer);
   1.912 +	CleanupStack::PushL(serverProvider);
   1.913 +	serverProvider->ConstructL();
   1.914 +	CleanupStack::Pop();
   1.915 +	return serverProvider;
   1.916 +	}
   1.917 +
   1.918 +CSurfaceUpdateServerProvider::CSurfaceUpdateServerProvider(CActive::TPriority aPriority, CSurfaceUpdateServer* aServer) :
   1.919 +								CActive(aPriority), iServer(aServer)
   1.920 +	{
   1.921 +	RThread thread;
   1.922 +	iThreadId = thread.Id();
   1.923 +	}
   1.924 +	
   1.925 +CSurfaceUpdateServerProvider::~CSurfaceUpdateServerProvider()
   1.926 +	{
   1.927 +	iSemaphore.Close();
   1.928 +	Cancel();
   1.929 +	}
   1.930 +/**
   1.931 +Create provider and add it to the active scheduler
   1.932 +*/
   1.933 +void CSurfaceUpdateServerProvider::ConstructL()
   1.934 +	{
   1.935 +	User::LeaveIfError(iSemaphore.CreateLocal(0));
   1.936 +	CActiveScheduler::Add(this);
   1.937 +	iStatus = KRequestPending;
   1.938 +	SetActive();
   1.939 +	}
   1.940 +
   1.941 +/**  
   1.942 + Assign composition receiver instance to particular screen.
   1.943 + The following calls of this function for the same screen will override the previous.
   1.944 + @see MSurfaceUpdateServerProvider::::Register
   1.945 + */	
   1.946 +EXPORT_C TInt CSurfaceUpdateServerProvider::Register(TInt aScreen, CBase* aReceiver, TInt aPriority)
   1.947 +	{
   1.948 +	RThread thread;
   1.949 +	TInt res = thread.Open(iThreadId);
   1.950 +	if(res == KErrNone)
   1.951 +		{
   1.952 +		iScreen = aScreen;
   1.953 +		iUpdateReceiver = aReceiver;
   1.954 +		iPriority = aPriority;
   1.955 +
   1.956 +		TRequestStatus* status = &iStatus;
   1.957 +		thread.RequestComplete(status, EUpdateServEventRegister);
   1.958 +		thread.Close();
   1.959 +		iSemaphore.Wait();
   1.960 +		res = iRegisterErr;
   1.961 +		}
   1.962 +	return res;
   1.963 +	}
   1.964 +
   1.965 +/**
   1.966 +Terminate the SUS and release all memory associated with it. 
   1.967 +The function was introduced for debugging purpose only and is not considered 
   1.968 +as part of public API.
   1.969 +*/
   1.970 +EXPORT_C void CSurfaceUpdateServerProvider::Terminate()
   1.971 +	{
   1.972 +#ifdef TEST_SURFACE_UPDATE
   1.973 +	RThread thread;
   1.974 +
   1.975 +	if(thread.Open(iThreadId) == KErrNone)
   1.976 +		{
   1.977 +	    TInt err = gProviderFastLock.CreateLocal();
   1.978 +	    __ASSERT_ALWAYS(err == KErrNone || err == KErrAlreadyExists, CSurfaceUpdateServer::PanicServer(EUpdateServPanicGlobalFastLock));
   1.979 +	    
   1.980 +	    gProviderFastLock.Wait();
   1.981 +	    gProvider = NULL;
   1.982 +		if (iServer)
   1.983 +			{
   1.984 +			while((static_cast<CSurfaceUpdateServer*> (iServer))-> iNumberPendingNotification)
   1.985 +				User::After(TTimeIntervalMicroSeconds32(1000));
   1.986 +			}
   1.987 +		TRequestStatus* status = &iStatus;
   1.988 +		thread.RequestComplete(status, EUpdateServEventTerminate);
   1.989 +		
   1.990 +		//wait until the thread dies
   1.991 +		TRequestStatus status1;
   1.992 +		thread.Logon(status1);
   1.993 +		User::WaitForRequest(status1);
   1.994 +		thread.Close();
   1.995 +		
   1.996 +     	gProviderFastLock.Close();
   1.997 +		}
   1.998 +#endif
   1.999 +	}
  1.1000 +
  1.1001 +/**
  1.1002 +The function processes signals which come from composition receiver thread.
  1.1003 +*/	
  1.1004 +void CSurfaceUpdateServerProvider::RunL()
  1.1005 +	{
  1.1006 +	switch(iStatus.Int())
  1.1007 +		{
  1.1008 +	case EUpdateServEventTerminate:
  1.1009 +		CActiveScheduler::Stop();
  1.1010 +		return; 
  1.1011 +	case EUpdateServEventRegister:
  1.1012 +		iRegisterErr = iServer->Register(iScreen, iUpdateReceiver, iPriority);
  1.1013 +		iUpdateReceiver = NULL;
  1.1014 +		iStatus = KRequestPending;
  1.1015 +		SetActive();
  1.1016 +		iSemaphore.Signal();
  1.1017 +		break;
  1.1018 +	default :
  1.1019 +		CSurfaceUpdateServer::PanicServer(EUpdateServPanicBadRequest); 
  1.1020 +		iStatus = KRequestPending;
  1.1021 +		SetActive();
  1.1022 +		break;	
  1.1023 +		}
  1.1024 +	}
  1.1025 +	
  1.1026 +void CSurfaceUpdateServerProvider::DoCancel()
  1.1027 +	{
  1.1028 +	}
  1.1029 +
  1.1030 +/**
  1.1031 +Spawn a thread within WSERV process. This will lead to starting the surface update server in it 
  1.1032 +@publishedPartner
  1.1033 +@prototype Intended to be used by Surface Update control flow
  1.1034 +	
  1.1035 +@param aUpdateProvider - [out] reference pointer to surface update server provider, 
  1.1036 +		which will be set when the server is started. The variable will be used to registry 
  1.1037 +		composition receiver instances. The caller doesn't acquire the ownership of this instance,
  1.1038 +		thus mustn't delete it. The pointer will be valid until server is operating, 
  1.1039 +		i.e. system is up.
  1.1040 +
  1.1041 +@return KErrNone if an operation is successful, any other system error codes otherwise
  1.1042 +*/
  1.1043 +EXPORT_C TInt StartSurfaceUpdateServer(MSurfaceUpdateServerProvider*& aSurfaceUpdateServerProvider)
  1.1044 +	{
  1.1045 +#ifndef TEST_SURFACE_UPDATE
  1.1046 +	TPtrC serverName(KSurfaceUpdateServerName);
  1.1047 +#else
  1.1048 +	TPtrC serverName(KTestSurfaceUpdateServerName);
  1.1049 +#endif
  1.1050 +	//locking
  1.1051 +	TInt err = gProviderFastLock.CreateLocal();
  1.1052 +	
  1.1053 +	if (err != KErrNone && err != KErrAlreadyExists)
  1.1054 +	    {
  1.1055 +        return err;
  1.1056 +	    }
  1.1057 +	
  1.1058 +	gProviderFastLock.Wait();
  1.1059 +
  1.1060 +	TAny *provider = gProvider;
  1.1061 +	if(provider)
  1.1062 +		{
  1.1063 +		aSurfaceUpdateServerProvider = static_cast <MSurfaceUpdateServerProvider*> (provider);
  1.1064 +		gProviderFastLock.Signal();
  1.1065 +		return KErrNone;
  1.1066 +		}
  1.1067 +	TFullName   name;
  1.1068 +	RThread serverThread;
  1.1069 +	TInt res = KErrAlreadyExists;
  1.1070 +	
  1.1071 +	TFindServer findSurfaceUpdateServer(serverName);
  1.1072 +	  // Need to check that the server exists.
  1.1073 +	if (findSurfaceUpdateServer.Next(name) !=KErrNone)
  1.1074 +		{
  1.1075 +		TTime tm;
  1.1076 +		TBuf<32> buf;
  1.1077 +		tm.UniversalTime();
  1.1078 +		TRAP(res, tm.FormatL(buf, _L("_%H%T%S%C")));
  1.1079 +		if(res != KErrNone)	
  1.1080 +			{
  1.1081 +			gProviderFastLock.Signal();
  1.1082 +			return res;
  1.1083 +			}
  1.1084 +		TBuf<128> threadName(serverName);
  1.1085 +		threadName.Append(buf); //guarantee uniqueness  of the thread name
  1.1086 +		  // Create the thread for the server.
  1.1087 +		res = serverThread.Create(threadName,
  1.1088 +			CSurfaceUpdateServer::ThreadFunction,
  1.1089 +			KDefaultStackSize,
  1.1090 +			KDefaultHeapSize,
  1.1091 +			KDefaultHeapSize,
  1.1092 +			(TAny*) &aSurfaceUpdateServerProvider
  1.1093 +			);
  1.1094 +          // The thread has been created OK so get it started - however
  1.1095 +          // we need to make sure that it has started before we continue.
  1.1096 +		if (res==KErrNone)
  1.1097 +			{
  1.1098 +			TRequestStatus rendezvousStatus;
  1.1099 +			TThreadPriority priority = RThread().Priority();    
  1.1100 +			serverThread.SetPriority(priority); // The same as the priority of the creating thread
  1.1101 +			serverThread.Rendezvous(rendezvousStatus);
  1.1102 +			serverThread.Resume();
  1.1103 +			User::WaitForRequest(rendezvousStatus);
  1.1104 +			res = rendezvousStatus.Int();
  1.1105 +			gProvider = aSurfaceUpdateServerProvider;
  1.1106 +			}
  1.1107 +    // The thread has not been created - clearly there's been a problem.
  1.1108 +		else
  1.1109 +			{
  1.1110 +			serverThread.Close();
  1.1111 +			}
  1.1112 +		}
  1.1113 +       gProviderFastLock.Signal();
  1.1114 +		return res;
  1.1115 +	}