First public contribution.
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
19 @internalComponent - Internal Symbian test code
23 #include "tcompositionbackend.h"
24 #include <graphics/suerror.h>
26 const TInt KNotificationsAtTime = 10; //how many notifications could be processed at a time, varies from 1...
28 CTContentUpdateReceiver::CTContentUpdateReceiver(TInt aScreen) :
29 iScreen(aScreen), iVisible(ETrue)
32 iReceiverThreadId = thread.Id();
35 CTContentUpdateReceiver::~CTContentUpdateReceiver()
41 iPriorityLock.Close();
44 void CTContentUpdateReceiver::ConstructL()
46 TCallBack callback(CallBack);
48 User::LeaveIfError(iLock.CreateLocal());
49 User::LeaveIfError(iPriorityLock.CreateLocal(0));
50 iPeriodic= CPeriodic::NewL(CPeriodic::EPriorityStandard);
51 iPeriodic->Start(TTimeIntervalMicroSeconds32(0),TTimeIntervalMicroSeconds32(KCompositionInterval), callback);
54 CTContentUpdateReceiver* CTContentUpdateReceiver::NewL(TInt aScreen)
56 CTContentUpdateReceiver* receiver = new (ELeave) CTContentUpdateReceiver(aScreen);
57 CleanupStack::PushL(receiver);
58 receiver->ConstructL();
63 TInt CTContentUpdateReceiver::Extension_(TUint aExtensionId, TAny*& aRetIface, TAny* a1)
67 case MCompositionSurfaceUpdate::ETypeId:
68 aRetIface= static_cast<MCompositionSurfaceUpdate*>(this);
73 return CExtensionContainer::Extension_(aExtensionId,aRetIface,a1);
76 TInt CTContentUpdateReceiver::CallBack(TAny *aAny)
78 return (static_cast <CTContentUpdateReceiver*> (aAny))->CheckNewNotifications();
81 void CTContentUpdateReceiver::Stop()
88 EXPORT_C void CTContentUpdateReceiver::SetVisible(TBool aVisible)
95 TInt CTContentUpdateReceiver::CheckNewNotifications()
98 if(iStop && (iNumberElements <= 0))
101 CActiveScheduler::Stop();
102 return 0;//the return value is irrelevant for CPeriodic function
104 if(iSetInternalPriority)
106 TRAPD(res, DoSetInternalPriorityL());
108 __ASSERT_ALWAYS(res ==KErrNone, User::Panic(_L("CheckNewNotifications"), KErrGeneral));
109 return 0;//the return value is irrelevant for CPeriodic function
113 TInt res = thread.Open(iThreadId);
114 __ASSERT_ALWAYS(res ==KErrNone, User::Panic(_L("CheckNewNotifications"), KErrGeneral));
116 //we will check only one limited amount of requests at the time
117 for(TInt iteration = 0; (iNumberElements > index) && (iteration < KNotificationsAtTime); iteration++)
119 if(iArray[index].iType == EReqDisplayed)
121 *(iArray[index].iTimeStamp) = User::FastCounter();
122 if(iCompositionOrder)
124 iCompositionOrder->SetOrder(EOrderComposition);
127 else if(iArray[index].iType == EReqDisplayedXTimes)
129 iArray[index].iDisplayedXTimes--;
130 if(iArray[index].iDisplayedXTimes > 0)
136 TRequestStatus* status = iArray[index].iStatus;
137 res = iVisible ? KErrNone : KErrNotVisible;
139 thread.RequestComplete(status, res);
143 return 0;//the return value is irrelevant for CPeriodic function
146 void CTContentUpdateReceiver::DoSetInternalPriorityL()
149 User::LeaveIfError(thread.Open(iReceiverThreadId));
150 thread.SetPriority(iInternalPriority);
152 TInt compositionInterval = KCompositionInterval;
153 CPeriodic::TPriority priority = CPeriodic::EPriorityStandard;
154 if(iInternalPriority < EPriorityNormal)
156 priority = CPeriodic::EPriorityIdle;
157 compositionInterval = KCompositionIntervalLong;
159 else if (iInternalPriority > EPriorityNormal)
161 priority = CPeriodic::EPriorityHigh;
162 compositionInterval = KCompositionIntervalShort;
165 TCallBack callback(CallBack);
166 callback.iPtr = this;
169 iPeriodic= CPeriodic::NewL(priority);
170 iPeriodic->Start(TTimeIntervalMicroSeconds32(compositionInterval),TTimeIntervalMicroSeconds32(compositionInterval), callback);
171 iSetInternalPriority = EFalse;
172 iPriorityLock.Signal();
175 EXPORT_C TInt CTContentUpdateReceiver::SetInternalPriority(TThreadPriority aInternalPriority)
178 iInternalPriority = aInternalPriority;
179 iSetInternalPriority = ETrue;
182 //wait for the priority changes takes place
183 iPriorityLock.Wait();
187 void CTContentUpdateReceiver::ContentUpdated(const TSurfaceId& aId,
189 const TRegion* aRegion,
190 TRequestStatus* aStatusAvailable,
191 TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp,
192 TRequestStatus* aStatusDisplayedXTimes, TInt* aDisplayedXTimes)
203 User::RequestComplete(aStatusAvailable, KErrDied);
207 User::RequestComplete(aStatusDisplayed, KErrDied);
209 if(aStatusDisplayedXTimes)
211 User::RequestComplete(aStatusDisplayedXTimes, KErrDied);
218 iThreadId = thread.Id();
222 Add(aStatusAvailable, EReqAvailable);
226 Add(aStatusDisplayed, EReqDisplayed, 0, aTimeStamp);
228 if(aStatusDisplayedXTimes)
230 Add(aStatusDisplayedXTimes, EReqDisplayedXTimes, *aDisplayedXTimes);
236 Add notification to the list. The function is called from the SUS thread.
237 The client of this API must use a lock mechanizm to preserve data integrity.
239 TInt CTContentUpdateReceiver::Add(TRequestStatus *aStatus, RequestType aType,
240 TInt aDisplayedXTimes, TUint32* aTimeStamp)
242 TInt index = iNumberElements;
243 TInt max = sizeof(iArray) / sizeof(iArray[0]) - 1;
247 iArray[index].iStatus = aStatus;
248 iArray[index].iType = aType;
249 iArray[index].iDisplayedXTimes = aDisplayedXTimes;
250 iArray[index].iTimeStamp = aTimeStamp;
257 Remove notification from the list.
258 The function is called from the backend thread.
259 The client of this API must use a lock mechanizm to preserve data integrity.
261 void CTContentUpdateReceiver::Remove(TInt aIndex)
263 TInt max = sizeof(iArray) / sizeof(iArray[0]) - 1;
264 if((aIndex < 0) || (aIndex >= max))
268 if(aIndex < iNumberElements)
270 Mem::Move(&iArray[aIndex], &iArray[aIndex + 1], (iNumberElements - aIndex) * sizeof(RequestObject));
271 iArray[iNumberElements].iType= EReqEmpty;
275 iArray[aIndex].iType = EReqEmpty;
279 TInt CTContentUpdateReceiver::ThreadFunction(TAny* aAny)
281 // get clean-up stack
282 CTrapCleanup* cleanup=CTrapCleanup::New();
284 _LIT(KTestReceiver, "TestReceiver");
285 __ASSERT_ALWAYS(cleanup!=NULL, thread.Panic( KTestReceiver, KErrNoMemory));
287 // create an active scheduler and server
288 CActiveScheduler *pA = new CActiveScheduler;
289 __ASSERT_ALWAYS(pA != NULL, thread.Panic( KTestReceiver, KErrNoMemory));
291 //Install the active scheduler
292 CActiveScheduler::Install(pA);
294 CTContentUpdateReceiver *pCB = NULL;
295 TInt screen = * (static_cast <TInt*> (aAny));
296 TRAPD(err, pCB = CTContentUpdateReceiver::NewL(screen));
297 __ASSERT_ALWAYS(err == KErrNone, thread.Panic( KTestReceiver, err));
299 *(static_cast <CTContentUpdateReceiver**> (aAny)) = pCB;
301 // Let everyone know that we are ready to
302 // deal with requests.
303 RThread::Rendezvous(KErrNone);
304 // And start fielding requests from client(s).
305 CActiveScheduler::Start();
315 _LIT(KMaskBackend, "CompositionBackend_%d");
316 const TUint KDefaultHeapSize=0x10000;
318 EXPORT_C TInt StartTestUpdateReceiver(CTContentUpdateReceiver*& aReceiver, TInt aScreen)
320 RThread compositionThread;
321 TInt res = KErrGeneral;
322 TBuf<64> contentUpdateReceiverThreadName;
323 TBuf<64> contentUpdateReceiverThreadMask;
325 // Guarantee uniqueness of thread name by using timestamp
329 TRAP(res, tm.FormatL(timeStamp, _L("_%H%T%S%C")));
335 contentUpdateReceiverThreadName.Format(KMaskBackend, aScreen);
336 contentUpdateReceiverThreadName.Append(timeStamp);
337 contentUpdateReceiverThreadMask = contentUpdateReceiverThreadName;
338 contentUpdateReceiverThreadMask.Insert(0, _L("*"));
339 TFindThread findThread(contentUpdateReceiverThreadMask);
341 // Need to check that the thread exists.
342 if (findThread.Next(name)!=KErrNone)
344 aReceiver = reinterpret_cast <CTContentUpdateReceiver*> (aScreen);
346 // Create the thread for the server.
347 res = compositionThread.Create(contentUpdateReceiverThreadName,
348 CTContentUpdateReceiver::ThreadFunction,
355 // The thread has been created OK so get it started - however
356 // we need to make sure that it has started before we continue.
359 TRequestStatus rendezvousStatus;
360 compositionThread.SetPriority(EPriorityNormal);
361 compositionThread.Rendezvous(rendezvousStatus);
362 compositionThread.Resume();
363 User::WaitForRequest(rendezvousStatus);
364 res = rendezvousStatus.Int();
367 compositionThread.Close();
371 EXPORT_C void CloseTestUpdateReceiver(CTContentUpdateReceiver* aReceiver)
376 TBuf<64> contentUpdateReceiverThreadName;
377 contentUpdateReceiverThreadName.Format(KMaskBackend, aReceiver->Screen());
378 TBuf<64> contentUpdateReceiverThreadMask;
379 contentUpdateReceiverThreadMask = contentUpdateReceiverThreadName;
380 contentUpdateReceiverThreadMask.Insert(0, _L("*"));
381 contentUpdateReceiverThreadMask.Append('*');
382 TFindThread findThread(contentUpdateReceiverThreadMask);
385 if((findThread.Next(name)!=KErrNone) ||
386 (thread.Open(findThread) != KErrNone))
391 TRequestStatus status;
392 thread.Logon(status);
395 User::WaitForRequest(status);