commonuisupport/uikon/srvsrc/EIKNFYSV.CPP
changeset 0 2f259fa3e83a
child 10 9f56a4e1b8ab
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 // Copyright (c) 1997-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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "EIKNFYSV.H"
       
    17 #include <barsread.h>
       
    18 #include <coemain.h>
       
    19 #include <eikenv.h>
       
    20 #include <eikmsg.h>
       
    21 #include <e32uid.h>
       
    22 #include "EIKSRV.PAN"
       
    23 #include "eiknotapi.h"
       
    24 #include <bafindf.h>
       
    25 #include <uiklaf/private/lafenv.h>
       
    26 #include "EIKDEBUG.H"
       
    27 #include <uiklaf/private/pluginuid.hrh>
       
    28 #include "eikscchange.h"
       
    29 
       
    30 _LIT(KPanicClient_CEikServNotifySession,"Eiksrv Cli(Nfy)");
       
    31 
       
    32 const TInt KQueued = 1;
       
    33 const TInt KNullClientId = 0;
       
    34 const TUid KNonExistentUid = {KNullUidValue}; 
       
    35 
       
    36 /**
       
    37 @internalComponent
       
    38 */
       
    39 _LIT8(KEikNotifierPaused,"Eik_Notifier_Paused");
       
    40 
       
    41 /**
       
    42 @internalComponent
       
    43 */
       
    44 _LIT8(KEikNotifierResumed,"Eik_Notifier_Resumed");
       
    45 
       
    46 #include <ecom/publicregistry.h>
       
    47 #include <uikon.hrh>
       
    48 static const TUid KUidPluginInterfaceNotifiers = {KUikonUidPluginInterfaceNotifiers};
       
    49 
       
    50 
       
    51 const TUint KNotifierMessageOpCodeLast = 10;
       
    52 const TUint KRangeCount = 5;
       
    53 
       
    54 const TInt KOpCodeRanges[KRangeCount] = 
       
    55 	{	
       
    56 	ENotifierNotify,
       
    57 	ECancelNotifier, 
       
    58 	EStartNotifierAndGetResponse, 
       
    59 	EUpdateNotifierAndGetResponse,
       
    60 	KNotifierMessageOpCodeLast,
       
    61 	};
       
    62 
       
    63 const TUint8 KElementsIndex[KRangeCount] =
       
    64 	{
       
    65 	CPolicyServer::EAlwaysPass, //Allways passing no capability required      [0-2]
       
    66 	CPolicyServer::ECustomCheck, //Custom check for the Notifier Client's SID (ECancelNotifier and EUpdateNotifier) [3-4]
       
    67 	CPolicyServer::EAlwaysPass,	//Allways passing no capability required       [5-8]
       
    68 	CPolicyServer::ECustomCheck,//Custom check for the Notifier Client's SID  (EUpdateNotifierAndGetResponse)[9-(KNotifierMessageOpCodeLast-1)]
       
    69 	CPolicyServer::ENotSupported, //Not Supported					 		   [KNotifierMessageOpCodeLast-End]
       
    70 	};
       
    71 
       
    72 const CPolicyServer::TPolicy KEikServNotifyServerPolicy =
       
    73 	{
       
    74 	CPolicyServer::EAlwaysPass, 
       
    75 	KRangeCount,
       
    76 	KOpCodeRanges,
       
    77 	KElementsIndex, 	
       
    78 	};
       
    79 
       
    80 /**
       
    81 @internalComponent 
       
    82 */
       
    83 NONSHARABLE_CLASS(CDiscoverNewImplementation) : public CActive
       
    84 	{
       
    85 public:
       
    86 	static CDiscoverNewImplementation* NewL(CEikSrvNotifierManager& aManager);
       
    87 	void Start();
       
    88 	~CDiscoverNewImplementation();
       
    89 private:
       
    90 	CDiscoverNewImplementation(CEikSrvNotifierManager& aManager);
       
    91 	void ConstructL();
       
    92 	void RunL();
       
    93 	void DoCancel();
       
    94 private:
       
    95 	CEikSrvNotifierManager& iManager;
       
    96 	REComSession* iEComSession;
       
    97 	CActiveScheduler*  iScheduler;
       
    98 	};
       
    99 
       
   100 /**
       
   101 @internalComponent 
       
   102 */
       
   103 NONSHARABLE_CLASS(CPluginTrack) : public CBase
       
   104 	{
       
   105 public:
       
   106 	NONSHARABLE_CLASS(TNotifierInfo)
       
   107 		{
       
   108 	public:
       
   109 		TNotifierInfo(TUid aNotifierPluginUid, TUid aNotifierPluginChannelUid);
       
   110 	public:
       
   111 		TUid iNotifierPluginUid;
       
   112 		TUid iNotifierPluginChannelUid;
       
   113 		};
       
   114 public:
       
   115 	CPluginTrack();
       
   116 	~CPluginTrack();
       
   117 public:
       
   118 	TUid iDllUid;
       
   119 	TUid iPluginImplementationUid;
       
   120 	TUid iDtr_key;
       
   121 	RArray<TNotifierInfo> iNotifierInfo;
       
   122 	};
       
   123 
       
   124 
       
   125 //
       
   126 // class CEikServNotifyServer
       
   127 //
       
   128 
       
   129 CEikServNotifyServer::CEikServNotifyServer(TInt aPriority, MEikServNotifyAlert* aAlert)
       
   130 	: CPolicyServer(aPriority, KEikServNotifyServerPolicy), iAlert(aAlert)
       
   131 	//
       
   132 	// private c'tor - initialize using NewL()
       
   133 	//
       
   134 	{
       
   135 	}
       
   136 
       
   137 EXPORT_C  CEikServNotifyServer::~CEikServNotifyServer()
       
   138 	{
       
   139 	SetIsExiting();
       
   140 	
       
   141 	if (iAlert)
       
   142 		iAlert->Release();
       
   143 	
       
   144 	if (iInfoMsg)
       
   145 		iInfoMsg->Release();
       
   146 		
       
   147 	iInfoMsgGroupWin.Close();
       
   148 	delete iManager;
       
   149 	}
       
   150 
       
   151 EXPORT_C CEikServNotifyServer* CEikServNotifyServer::NewL(MEikServNotifyAlert* aAlert)
       
   152 	//
       
   153 	// static - Create and start the server
       
   154 	{
       
   155 	CEikServNotifyServer* server = new (ELeave) CEikServNotifyServer(EActivePriorityIpcEventsHigh, aAlert);
       
   156 	CleanupStack::PushL(server);
       
   157 	server->ConstructL();
       
   158 	CleanupStack::Pop(); // server
       
   159 	return server;
       
   160 	}
       
   161 
       
   162 EXPORT_C void CEikServNotifyServer::StartL()
       
   163 	{
       
   164 	CServer2::StartL(__NOTIFIER_NAME);
       
   165 	}
       
   166 
       
   167 void CEikServNotifyServer::SetIsExiting()
       
   168 	{
       
   169 	iExiting = ETrue;
       
   170 	}
       
   171 
       
   172 TBool CEikServNotifyServer::IsExiting() const
       
   173 	{
       
   174 	return iExiting;
       
   175 	}
       
   176 
       
   177 void CEikServNotifyServer::ConstructL()
       
   178 	//
       
   179 	// private second phase construction - initialise using NewL()
       
   180 	//
       
   181 	{
       
   182 	// notifier info print
       
   183 	CEikonEnv* env = CEikonEnv::Static();
       
   184 	RWsSession& wsSession = env->WsSession();
       
   185 	iInfoMsgGroupWin = RWindowGroup(wsSession);
       
   186 	User::LeaveIfError(iInfoMsgGroupWin.Construct((TUint32)this, EFalse)); // EFalse disables key events
       
   187 	iInfoMsgGroupWin.SetOrdinalPosition(0, ECoeWinPriorityAlwaysAtFront-1);
       
   188 	
       
   189 	iInfoMsg = LafEnv::NewInfoMsgWinL(*env, iInfoMsgGroupWin);
       
   190 	
       
   191 	// notifier manager
       
   192 	iManager = CEikSrvNotifierManager::NewL();
       
   193 	iManager->RegisterL();
       
   194 	}
       
   195 
       
   196 EXPORT_C void CEikServNotifyServer::DisplayNotifier(const TDesC& aTitle,const TDesC& aLabel, const TDesC& aBut1, const TDesC& aBut2, MEikNotifyAlertCompletionObserver* aObserver)
       
   197 	{
       
   198 	if(iAlert)
       
   199 		iAlert->DisplayNotifier(aTitle, aLabel, aBut1, aBut2, aObserver);
       
   200 	}
       
   201 
       
   202 EXPORT_C void CEikServNotifyServer::DisplayInfoPrint(const TDesC& aDes)
       
   203 	{
       
   204 	if(iInfoMsg)
       
   205 		iInfoMsg->StartDisplay(aDes, EHRightVTop);
       
   206 	}
       
   207 
       
   208 CSession2* CEikServNotifyServer::NewSessionL(const TVersion &aVersion,const RMessage2&) const
       
   209 	{
       
   210 	const TVersion version(1,0,0); // !! liaise with RNotify client-side class in E32
       
   211 	if (!User::QueryVersionSupported(version,aVersion))
       
   212 		User::Leave(KErrNotSupported);
       
   213 		
       
   214 	return CEikServNotifySession::NewL();
       
   215 	}
       
   216 
       
   217 CPolicyServer::TCustomResult CEikServNotifyServer::CustomSecurityCheckL(const RMessage2& aMsg, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
       
   218 //aAction is not set because default value to it is already set(CPolicyServer::EFailClient)
       
   219 //aMissing is not set because it is not needed as we aren't overriding CheckFailedL
       
   220 	{
       
   221 	const TUid notifierUid = TUid::Uid(aMsg.Int0());
       
   222 	const TSecureId clientSid = aMsg.SecureId();
       
   223 
       
   224 	const TInt count = iAsyncSecureInfoQueue.Count();
       
   225 	for(int i = 0; i < count; i++)
       
   226 		{
       
   227 		if(iAsyncSecureInfoQueue[i].iSecureId == clientSid)
       
   228 			return CPolicyServer::EPass;
       
   229 		}
       
   230 	
       
   231 	return CPolicyServer::EFail;
       
   232 	}
       
   233 
       
   234 //
       
   235 // class TNotifierMessageInfo
       
   236 //
       
   237 
       
   238 TNotifierMessageInfo::TNotifierMessageInfo(const RMessage2& aMessage, CEikServNotifySession& aEikServNotifySession)
       
   239  : iMessage(aMessage), iEikServNotifySession(aEikServNotifySession)
       
   240 	{
       
   241 	}
       
   242 
       
   243 //
       
   244 // class CEikServNotifySession
       
   245 //
       
   246 
       
   247 CEikServNotifySession* CEikServNotifySession::NewL()
       
   248 	{
       
   249 	CEikServNotifySession* const notifySession = new(ELeave) CEikServNotifySession;
       
   250 	CleanupStack::PushL(notifySession);
       
   251 	notifySession->ConstructL();
       
   252 	CleanupStack::Pop(notifySession);
       
   253 	return notifySession;
       
   254 	}
       
   255 
       
   256 CEikServNotifySession::~CEikServNotifySession()
       
   257 	{
       
   258 	const CEikServNotifyServer& server = Server();
       
   259 	if (!server.IsExiting())
       
   260 		server.Manager()->HandleClientExit(iClientId);
       
   261 	
       
   262 	iServer = NULL;
       
   263 	delete iEikSrvPendingAlert;
       
   264 	delete iBuffer;
       
   265 	}
       
   266 	
       
   267 CEikServNotifySession::CEikServNotifySession() : iClientId(reinterpret_cast<TInt>(this))
       
   268 	{
       
   269 	}
       
   270 
       
   271 void CEikServNotifySession::ConstructL()
       
   272 	{
       
   273 	iEikSrvPendingAlert = new(ELeave) CEikSrvPendingAlert(*this);
       
   274 	}
       
   275 
       
   276 void CEikServNotifySession::ServiceL(const RMessage2 &aMessage)
       
   277 	//
       
   278 	// Service requests
       
   279 	//
       
   280 	{
       
   281 	DEBUGPRINT3(_L("CEikServNotifySession::ServiceL(), UID: 0x%X op:%D"),aMessage.Int0(),aMessage.Function());
       
   282 
       
   283 	TBool completeMessage = ETrue;
       
   284 	switch (aMessage.Function())
       
   285 		{
       
   286 	case ENotifierNotify:
       
   287 		DisplayAlert(aMessage);
       
   288 		completeMessage = EFalse; // Completed in HandleAlertCompletion
       
   289 		break;
       
   290 	case ENotifierInfoPrint:
       
   291 		DisplayInfoMsg(aMessage);
       
   292 		break;
       
   293 	case EStartNotifier:
       
   294 		StartNotifierL(aMessage);
       
   295 		break;
       
   296 	case ECancelNotifier:
       
   297 		{
       
   298 		TInt result = NotifierCancel(aMessage);
       
   299 		if(result == KErrNone)
       
   300 			{
       
   301 			result = Server().Manager()->NotifierCancel(TUid::Uid(aMessage.Int0()));
       
   302 			}
       
   303 		aMessage.Complete(result);
       
   304 		completeMessage = EFalse;
       
   305 		}
       
   306 		break;
       
   307 	case EUpdateNotifier:
       
   308 		{
       
   309 		UpdateNotifierL(aMessage);
       
   310 		completeMessage = EFalse; // Completed in UpdateNotifierL
       
   311 		}
       
   312 		break;
       
   313 	case EStartNotifierAndGetResponse:
       
   314 		{
       
   315 		TBool cleanupComplete = ETrue;
       
   316 		StartNotifierAndGetResponseL(aMessage, cleanupComplete);
       
   317 		completeMessage = EFalse; // the plug-in has responsibility for completing the message (either synchronously or asynchronously)
       
   318 		}
       
   319 		break;
       
   320 	case EUpdateNotifierAndGetResponse:
       
   321 		UpdateNotifierAndGetResponseL(aMessage);
       
   322 		completeMessage = EFalse;
       
   323 		break;
       
   324 	default:
       
   325 		aMessage.Complete(KErrNotSupported);
       
   326 		break;
       
   327 		}
       
   328 		
       
   329 	if (completeMessage && !aMessage.IsNull())
       
   330 		aMessage.Complete(KErrNone);
       
   331 
       
   332 	DEBUGPRINT3(_L("CEikServNotifySession::ServiceL() finished, UID: 0x%X Message completed: %U"),aMessage.Int0(),completeMessage);
       
   333 	}
       
   334 
       
   335 void CEikServNotifySession::DisplayAlert(const RMessage2& aMessage)
       
   336 	//
       
   337 	// Display an alert
       
   338 	//
       
   339 	{
       
   340 	iLengthOfCombinedBuffer = aMessage.GetDesLength(1);
       
   341 	if (iLengthOfCombinedBuffer < 0)
       
   342 		return;
       
   343 
       
   344 	iLengthOfFirstLineOfMessage = (static_cast<TUint>(aMessage.Int2())>>16);
       
   345 	iLengthOfSecondLineOfMessage = (aMessage.Int2()&KMaxTUint16);
       
   346 	iLengthOfFirstButtonOfMessage = (static_cast<TUint>(aMessage.Int3())>>16);
       
   347 	iLengthOfSecondButtonOfMessage = (aMessage.Int3()&KMaxTUint16);
       
   348 	
       
   349 	if (iLengthOfCombinedBuffer != iLengthOfFirstLineOfMessage + iLengthOfSecondLineOfMessage + 
       
   350 									iLengthOfFirstButtonOfMessage + iLengthOfSecondButtonOfMessage)
       
   351 		{
       
   352 		aMessage.Panic(KPanicClient_CEikServNotifySession,EEikSrvClientPanicInconsistentMessageParameters);
       
   353 		return;
       
   354 		}
       
   355 		
       
   356 	HBufC* const combinedBuffer = HBufC::New(iLengthOfCombinedBuffer);
       
   357 	if(!combinedBuffer)
       
   358 		return;
       
   359 
       
   360 	TPtr combinedBuffer_asWritable(combinedBuffer->Des());
       
   361 	const TInt error = aMessage.Read(1, combinedBuffer_asWritable);
       
   362 	if (error)
       
   363 		{
       
   364 		delete combinedBuffer;
       
   365 		return;
       
   366 		}
       
   367 		
       
   368 	__ASSERT_DEBUG(iBuffer == NULL, User::Invariant());	
       
   369 	iBuffer = combinedBuffer;
       
   370 	
       
   371 	RNotifierMessageInfoQueue& queue = Server().AsyncMessageQueue();
       
   372 	const TInt err = queue.Append(TNotifierMessageInfo(aMessage,*this));
       
   373 	if (!err && queue.Count() == 1) // if the only thing in the queue is what we've just put in it...
       
   374 		PrepareDisplayAlert();
       
   375 	}
       
   376 
       
   377 void CEikServNotifySession::PrepareDisplayAlert()
       
   378 	{
       
   379 	const RNotifierMessageInfoQueue& queue = Server().AsyncMessageQueue();
       
   380 	//Getting the first element from the queue
       
   381 	ASSERT(queue.Count());
       
   382 	const TNotifierMessageInfo& firstInQueue = queue[0];
       
   383 	
       
   384 	//Getting the parameters for the notifier message to display	
       
   385 	const TInt lengthOfFirstLine = firstInQueue.iEikServNotifySession.iLengthOfFirstLineOfMessage;
       
   386 	const TInt lengthOfSecondLine = firstInQueue.iEikServNotifySession.iLengthOfSecondLineOfMessage;
       
   387 	const TInt lengthOfFirstButton = firstInQueue.iEikServNotifySession.iLengthOfFirstButtonOfMessage;
       
   388 	const TInt lengthOfSecondButton = firstInQueue.iEikServNotifySession.iLengthOfSecondButtonOfMessage;
       
   389 	
       
   390 	const TPtrC firstLineOfMessage(firstInQueue.iEikServNotifySession.iBuffer->Left(lengthOfFirstLine));
       
   391 	const TPtrC secondLineOfMessage(firstInQueue.iEikServNotifySession.iBuffer->Mid(lengthOfFirstLine,lengthOfSecondLine));
       
   392 	const TPtrC firstButtonOfMessage(firstInQueue.iEikServNotifySession.iBuffer->Mid(lengthOfFirstLine+lengthOfSecondLine,lengthOfFirstButton));
       
   393 	const TPtrC secondButtonOfMessage(firstInQueue.iEikServNotifySession.iBuffer->Mid(lengthOfFirstLine+lengthOfSecondLine+lengthOfFirstButton,lengthOfSecondButton));
       
   394 	
       
   395 	// after this line we can guarantee that HandleAlertCompletion will be called (assuming that the call to MEikServNotifyAlert's virtual function DisplayNotifier (which is called inside the DisplayNotifier call below) is well-behaved)
       
   396 	Server().DisplayNotifier(firstLineOfMessage, secondLineOfMessage, firstButtonOfMessage, secondButtonOfMessage, &firstInQueue.iEikServNotifySession);
       
   397 	}
       
   398 
       
   399 void CEikServNotifySession::HandleAlertCompletion(const TInt aButtonVal)
       
   400 	{
       
   401 	RNotifierMessageInfoQueue& queue = Server().AsyncMessageQueue();
       
   402 	__ASSERT_ALWAYS(queue.Count() > 0,Panic(EEikServPanicNotifyAlertQueueEmpty));
       
   403 	
       
   404 	const TNotifierMessageInfo& firstInQueue = queue[0];
       
   405 	firstInQueue.iMessage.Complete(firstInQueue.iMessage.Write(0, TPckgC<TInt>(aButtonVal == EEikBidCancel ? 0 : 1)));
       
   406 	if (firstInQueue.iEikServNotifySession.iBuffer)
       
   407 		{
       
   408 		delete firstInQueue.iEikServNotifySession.iBuffer;
       
   409 		firstInQueue.iEikServNotifySession.iBuffer = NULL;
       
   410 		}
       
   411 		
       
   412 	queue.Remove(0);
       
   413 	if (queue.Count())
       
   414 		iEikSrvPendingAlert->TriggerNext();
       
   415 	}
       
   416 
       
   417 void CEikServNotifySession::DisplayNextPendingAlert()
       
   418 	{
       
   419 	if (Server().AsyncMessageQueue().Count() >= 1)
       
   420 		PrepareDisplayAlert();
       
   421  	}
       
   422 
       
   423 void CEikServNotifySession::DisplayInfoMsg(const RMessage2& aMessage)
       
   424 	//
       
   425 	// Display an info message
       
   426 	//
       
   427 	{
       
   428 	TBuf<400> msg;
       
   429 	const TInt err = aMessage.Read(0, msg);
       
   430 	aMessage.Complete(err);
       
   431 	if(!err)
       
   432 		Server().DisplayInfoPrint(msg);
       
   433 	}
       
   434 
       
   435 HBufC8* CEikServNotifySession::GetRemoteInputBufferLC(const RMessage2& aMessage, TInt aSlot)
       
   436 	{
       
   437 	HBufC8* const inputBuffer = HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesLength(aSlot)));
       
   438 	TPtr8 input(inputBuffer->Des());
       
   439 	aMessage.ReadL(aSlot, input);
       
   440 	return inputBuffer;
       
   441 	}
       
   442 
       
   443 
       
   444 void CEikServNotifySession::StartNotifierL(const RMessage2& aMessage)
       
   445 	{
       
   446 	HBufC8* const inputBuffer = GetRemoteInputBufferLC(aMessage, 1);
       
   447 	const TUid notifierUid = TUid::Uid(aMessage.Int0());
       
   448 	const TSecureId secureId = aMessage.SecureId();
       
   449 	RNotifierSecureInfoQueue& secureInfoQueue = Server().AsyncSecureInfoQueue();
       
   450 	secureInfoQueue.AppendL(TNotifierSecureInfo(notifierUid, secureId));
       
   451 	
       
   452 	if (!aMessage.Int2()) // if the third parameter is null
       
   453 		{
       
   454 		TRAPD(err, Server().Manager()->NotifierStartL(TUid::Uid(aMessage.Int0()),*inputBuffer,NULL,iClientId));
       
   455 		if(err)
       
   456 			{
       
   457 			secureInfoQueue.Remove(secureInfoQueue.Count()-1);
       
   458 			User::Leave(err);
       
   459 			}
       
   460 		}
       
   461 	else
       
   462 		{
       
   463 		HBufC8* const responseBuffer = HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesMaxLength(2)));
       
   464 		TPtr8 response(responseBuffer->Des());
       
   465 		TRAPD(err, Server().Manager()->NotifierStartL(TUid::Uid(aMessage.Int0()), *inputBuffer, &response, iClientId));
       
   466 		if(err)
       
   467 			{
       
   468 			secureInfoQueue.Remove(secureInfoQueue.Count()-1);
       
   469 			User::Leave(err);
       
   470 			}
       
   471 			
       
   472 		aMessage.WriteL(2,response);
       
   473 		CleanupStack::PopAndDestroy(responseBuffer);
       
   474 		}
       
   475 		
       
   476 	CleanupStack::PopAndDestroy(inputBuffer);
       
   477 	}
       
   478 
       
   479 void CEikServNotifySession::UpdateNotifierL(const RMessage2& aMessage)
       
   480 	{
       
   481 	const RNotifierSecureInfoQueue& secureInfoQueue=Server().AsyncSecureInfoQueue();
       
   482 	const TUid notifierUid = TUid::Uid(aMessage.Int0());
       
   483 	const TInt queueTotal = secureInfoQueue.Count();
       
   484 	TBool completeMessage = EFalse;
       
   485 	for(TInt i = 0; i < queueTotal; i++)
       
   486 		{
       
   487 		if(secureInfoQueue[i].iNotifierUid == notifierUid && secureInfoQueue[i].iSecureId == aMessage.SecureId())
       
   488 			{
       
   489 			HBufC8* const inputBuffer = GetRemoteInputBufferLC(aMessage, 1);
       
   490 			if (!aMessage.Int2()) // if the third parameter is null
       
   491 				{
       
   492 				TRAPD(err, Server().Manager()->NotifierUpdateL(TUid::Uid(aMessage.Int0()), *inputBuffer, NULL, iClientId));
       
   493 				aMessage.Complete(err);
       
   494 				}
       
   495 			else
       
   496 				{
       
   497 				HBufC8* const outputBuffer = HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesMaxLength(2)));
       
   498 				TPtr8 output(outputBuffer->Des());
       
   499 				TRAPD(err, Server().Manager()->NotifierUpdateL(notifierUid, *inputBuffer, &output, iClientId));
       
   500 				if(!err)
       
   501 					aMessage.WriteL(2,*outputBuffer);
       
   502 					
       
   503 				CleanupStack::PopAndDestroy(outputBuffer);
       
   504 				aMessage.Complete(err);
       
   505 				}
       
   506 			completeMessage = ETrue;
       
   507 			CleanupStack::PopAndDestroy(inputBuffer);
       
   508 			break;
       
   509 			}
       
   510 		}
       
   511 		
       
   512 	if (!completeMessage)
       
   513 		aMessage.Complete(KErrNotFound);
       
   514 	}
       
   515 
       
   516 void CEikServNotifySession::StartNotifierAndGetResponseL(const RMessage2& aMessage,TBool& aCleanupComplete)
       
   517 	{
       
   518 	HBufC8* const inputBuffer = GetRemoteInputBufferLC(aMessage, 1);
       
   519 	const TUid notifierUid = TUid::Uid(aMessage.Int0());
       
   520 	const TSecureId secureId = aMessage.SecureId();
       
   521 	RNotifierSecureInfoQueue& secureInfoQueue = Server().AsyncSecureInfoQueue();
       
   522 	secureInfoQueue.AppendL(TNotifierSecureInfo(notifierUid,secureId));
       
   523 	
       
   524 	TRAPD(err, Server().Manager()->NotifierStartAndGetResponseL(TUid::Uid(aMessage.Int0()), *inputBuffer, 2, aMessage, iClientId, aCleanupComplete));
       
   525 	if(err)
       
   526 		{
       
   527 		secureInfoQueue.Remove(secureInfoQueue.Count()-1);
       
   528 		User::Leave(err);
       
   529 		}
       
   530 		
       
   531 	CleanupStack::PopAndDestroy(inputBuffer);
       
   532 	}
       
   533 
       
   534 void CEikServNotifySession::UpdateNotifierAndGetResponseL(const RMessage2& aMessage)
       
   535 	{
       
   536 	const RNotifierSecureInfoQueue& secureInfoQueue=Server().AsyncSecureInfoQueue();
       
   537 	const TUid notifierUid = TUid::Uid(aMessage.Int0());
       
   538 	const TInt queueTotal = secureInfoQueue.Count();
       
   539 	TBool completeMessage = ETrue;
       
   540 	for(TInt i = 0; i < queueTotal; i++)
       
   541 		{
       
   542 		if(secureInfoQueue[i].iNotifierUid == notifierUid && secureInfoQueue[i].iSecureId == aMessage.SecureId())
       
   543 			{
       
   544 			HBufC8* const inputBuffer = GetRemoteInputBufferLC(aMessage, 1);
       
   545 			Server().Manager()->NotifierUpdateAndGetResponseL(notifierUid, *inputBuffer, 2, aMessage, iClientId);
       
   546 			CleanupStack::PopAndDestroy(inputBuffer);
       
   547 			completeMessage = EFalse;
       
   548 			break;
       
   549 			}
       
   550 		}
       
   551 		
       
   552 	if (completeMessage)
       
   553 		aMessage.Complete(KErrNotSupported); // The client that initially created or connected to the notifier was not found
       
   554 	}
       
   555 
       
   556 
       
   557 TInt CEikServNotifySession::NotifierCancel(const RMessage2& aMessage)
       
   558 	{
       
   559 	RNotifierSecureInfoQueue& secureInfoQueue = Server().AsyncSecureInfoQueue();
       
   560 	const TUid notifierUid = TUid::Uid(aMessage.Int0());
       
   561 	const TSecureId secureId = aMessage.SecureId();
       
   562 	TInt queueTotal = secureInfoQueue.Count();
       
   563 	
       
   564 	for(TInt i = 0; i < queueTotal; i++)
       
   565 		{
       
   566 		if(secureInfoQueue[i].iNotifierUid == notifierUid && secureInfoQueue[i].iSecureId == secureId)
       
   567 			{
       
   568 			secureInfoQueue.Remove(i);
       
   569 			return KErrNone;
       
   570 			}
       
   571 		}
       
   572 	return KErrNotFound;
       
   573 	}
       
   574 
       
   575 CEikServNotifySession::CEikSrvPendingAlert::CEikSrvPendingAlert(CEikServNotifySession& aEikServNotifySession)
       
   576  : CActive(EActivePriorityClockTimer), iEikServNotifySession(aEikServNotifySession)
       
   577 	{
       
   578 	CActiveScheduler::Add(this);
       
   579 	}
       
   580 
       
   581 CEikServNotifySession::CEikSrvPendingAlert::~CEikSrvPendingAlert()
       
   582 	{
       
   583 	Cancel();
       
   584 	}
       
   585 
       
   586 void CEikServNotifySession::CEikSrvPendingAlert::TriggerNext()
       
   587 	{
       
   588 	iStatus = KRequestPending;
       
   589 	SetActive();
       
   590 	TRequestStatus* status = &iStatus;
       
   591 	User::RequestComplete(status, KErrNone);
       
   592 	}
       
   593 
       
   594 void CEikServNotifySession::CEikSrvPendingAlert::DoCancel()
       
   595 	{
       
   596 	}
       
   597 
       
   598 void CEikServNotifySession::CEikSrvPendingAlert::RunL()
       
   599 	{
       
   600 	iEikServNotifySession.DisplayNextPendingAlert();
       
   601 	}
       
   602 //
       
   603 //CEikSrvNotifierWrapper
       
   604 //
       
   605 
       
   606 CEikSrvNotifierWrapper::CEikSrvNotifierWrapper(MEikSrvNotifierBase2* aNotifier)
       
   607 	: iNotifier(aNotifier)
       
   608 	{
       
   609 	}
       
   610 
       
   611 CEikSrvNotifierWrapper::~CEikSrvNotifierWrapper()
       
   612 	{
       
   613 	if(iNotifier)
       
   614 		iNotifier->Release();
       
   615 	}
       
   616 
       
   617 void CEikSrvNotifierWrapper::RegisterNotifierL()
       
   618 	{
       
   619 	iInfo = iNotifier->RegisterL();
       
   620 	}
       
   621 
       
   622 //
       
   623 //CEikSrvNotifierRemover
       
   624 //
       
   625 
       
   626 CEikSrvNotifierRemover* CEikSrvNotifierRemover::NewL()
       
   627 	{//static
       
   628 	CEikSrvNotifierRemover* self = new(ELeave) CEikSrvNotifierRemover();
       
   629 	CActiveScheduler::Add(self);
       
   630 	return self;
       
   631 	}
       
   632 
       
   633 CEikSrvNotifierRemover::CEikSrvNotifierRemover()
       
   634 	: CActive(EPriorityHigh)	// high priority active object, s.t. it gets run before any more requests to cservers in the eiksrv thread.
       
   635 	{
       
   636 	}
       
   637 
       
   638 CEikSrvNotifierRemover::~CEikSrvNotifierRemover()
       
   639 	{
       
   640 	Cancel();
       
   641 	}
       
   642 
       
   643 void CEikSrvNotifierRemover::Start(CEikSrvNotifierManager* aManager, CArrayPtr<CEikSrvNotifierWrapper>* aObservedList)
       
   644 	{
       
   645 	__ASSERT_ALWAYS(aObservedList, Panic(EEikServPanicNullObservedList));
       
   646 	iManager = aManager;
       
   647 	iObservedList = aObservedList;
       
   648 	SetActive();
       
   649 	iStatus = KRequestPending;
       
   650 	TRequestStatus* status = &iStatus;
       
   651 	User::RequestComplete(status, KErrNone);
       
   652 	}
       
   653 
       
   654 void CEikSrvNotifierRemover::RunL()
       
   655 	{
       
   656 	const TInt maxIndex = iObservedList->Count() - 1;
       
   657 	for(TInt ii = maxIndex; ii >= 0; ii--)
       
   658 		{
       
   659 		CEikSrvNotifierWrapper* notifierWrapper = iObservedList->At(ii);
       
   660 		const MEikSrvNotifierBase2::TNotifierInfo info = notifierWrapper->iNotifier->Info();
       
   661 		const TUid plugInDllUid = notifierWrapper->iPlugInDllUid;
       
   662 		if(notifierWrapper->iIsReadyForRemoval)
       
   663 			{
       
   664 			if(plugInDllUid != KNullUid)	// only cancel if it comes from one of the transient dlls !
       
   665 				{
       
   666 				delete notifierWrapper;
       
   667 				iObservedList->Delete(ii);	// resize the CEikSrvNotifierWrapper array
       
   668 				}
       
   669 			}
       
   670 		}
       
   671 	}
       
   672 
       
   673 void CEikSrvNotifierRemover::DoCancel()
       
   674 	{
       
   675 	}
       
   676 
       
   677 //
       
   678 //CEikSrvNotifierManager
       
   679 //
       
   680 
       
   681 CEikSrvNotifierManager* CEikSrvNotifierManager::NewL()
       
   682 	{
       
   683 	CEikSrvNotifierManager* self = new (ELeave) CEikSrvNotifierManager;
       
   684 	CleanupStack::PushL(self);
       
   685 	self->ConstructL();
       
   686 	CleanupStack::Pop(); // self
       
   687 	return self;
       
   688 	}
       
   689 
       
   690 CEikSrvNotifierManager::~CEikSrvNotifierManager()
       
   691 	{
       
   692 	if (iObservedList)
       
   693 		{
       
   694 		iObservedList->ResetAndDestroy();
       
   695 		delete iObservedList;
       
   696 		}
       
   697 	
       
   698 	// This calls REComSession::DestroyedImplementation which closes plug-in libraries, 
       
   699 	// hence must be called *after* the virtual Release function is called on the 
       
   700 	// plug-ins (inside the iObservedList->ResetAndDestroy() call above)
       
   701 	iPluginUidList.ResetAndDestroy(); 
       
   702 	iPluginUidList.Close();
       
   703 		
       
   704 	delete iChannelMonitor;
       
   705 	delete iActivityMonitor;
       
   706 	delete iQueue;
       
   707 	delete iNotifierRemover;
       
   708 	delete iDiscoverNewImplementation;
       
   709 	}
       
   710 
       
   711 LOCAL_C void DeleteTempMArray(TAny* aPtr)
       
   712 	{
       
   713 	CArrayPtr<MEikSrvNotifierBase2>* array = reinterpret_cast<CArrayPtr<MEikSrvNotifierBase2>*>(aPtr);
       
   714 	const TInt count = array->Count();
       
   715 	for(TInt ii = 0; ii < count; ii++)
       
   716 		(*array)[ii]->Release();
       
   717 
       
   718 	delete array;
       
   719 	}
       
   720 
       
   721 LOCAL_C void DeleteTempCArray(TAny* aPtr)
       
   722 	{
       
   723 	CArrayPtr<CEikSrvNotifierWrapper>* const array = reinterpret_cast<CArrayPtr<CEikSrvNotifierWrapper>*>(aPtr);
       
   724 	array->ResetAndDestroy();
       
   725 	delete array;
       
   726 	}
       
   727 
       
   728 
       
   729 CArrayPtr<CEikSrvNotifierWrapper>* CEikSrvNotifierManager::CreateNotifierArrayFromPlugInArrayL(CArrayPtr<MEikSrvNotifierBase2>* aPlugInArray, const TUidType& /*aUidType*/)
       
   730 	{
       
   731 	User::LeaveIfNull(aPlugInArray);
       
   732 	const TInt count = aPlugInArray->Count();
       
   733 	CleanupStack::PushL(TCleanupItem(DeleteTempMArray,aPlugInArray));
       
   734 	const TInt arrayIncrement = Max(1, count);	// at least one
       
   735 	
       
   736 	CArrayPtrFlat<CEikSrvNotifierWrapper>* retArray = new (ELeave)CArrayPtrFlat<CEikSrvNotifierWrapper>(arrayIncrement);
       
   737 	CleanupStack::PushL(TCleanupItem(DeleteTempCArray,retArray));
       
   738 	for(TInt ii = 0; ii < count; ii++)
       
   739 		{
       
   740 		MEikSrvNotifierBase2* notif = aPlugInArray->At(0);
       
   741 		notif->SetManager(this);
       
   742 		CEikSrvNotifierWrapper* notifier = new (ELeave) CEikSrvNotifierWrapper(notif);
       
   743 		aPlugInArray->Delete(0);	// remove notif from aPlugInArray
       
   744 		CleanupStack::PushL(notifier);
       
   745 		retArray->AppendL(notifier);
       
   746 		CleanupStack::Pop(notifier);
       
   747 		}
       
   748 		
       
   749 	CleanupStack::Pop(retArray);
       
   750 	CleanupStack::PopAndDestroy(aPlugInArray);
       
   751 	return retArray;
       
   752 	}
       
   753 
       
   754 void CEikSrvNotifierManager::UpdateHighestPriorityNotifiersOnThisChannelOfTheirPausingOrResuming(TUid aChannelUid, TUid aHighestPriorityNotifierOnThisChannelUid, const TDesC8& aBuffer)
       
   755 	{
       
   756 	const TInt count = iObservedList->Count();
       
   757 	for (TInt jj = 0; jj < count; jj++)
       
   758 		{
       
   759 		MEikSrvNotifierBase2* notifForUpdate = ((*iObservedList)[jj])->iNotifier;
       
   760 		const MEikSrvNotifierBase2::TNotifierInfo infoForUpdate = notifForUpdate->Info();
       
   761 		if (infoForUpdate.iUid == aHighestPriorityNotifierOnThisChannelUid && infoForUpdate.iChannel == aChannelUid)
       
   762 			{
       
   763 			TRAP_IGNORE(notifForUpdate->UpdateL(aBuffer));
       
   764 			}
       
   765 		}
       
   766 	}
       
   767 
       
   768 void CEikSrvNotifierManager::TryAddNotifiersFromNotifierArrayL(CArrayPtr<CEikSrvNotifierWrapper>* aNotifierArray, TInt& aRollBackChannels)
       
   769 	{
       
   770 	const TInt maxIndex = aNotifierArray->Count() - 1;
       
   771 	for(TInt ii = maxIndex; ii >= 0; ii--)
       
   772 		{
       
   773 		CEikSrvNotifierWrapper* notifier = aNotifierArray->At(ii);
       
   774 		iObservedList->AppendL(notifier);		// notifier is owned by aNotifierArray, so should this fail, everything is ok. 
       
   775 		aNotifierArray->Delete(ii);	// wan't to get this pointer out of aNotifierArray asap to avoid double deletion from cleanup stack.
       
   776 		const MEikSrvNotifierBase2::TNotifierInfo& info = notifier->iInfo;
       
   777 		DEBUGPRINT4(_L("CEikSrvNotifierManager::TryAddNotifiersFromNotifierArrayL; Adding notifier: UID 0x%X, priority %d, channel 0x%X"),info.iUid,info.iPriority,info.iChannel);
       
   778 		
       
   779 		if (!iChannelMonitor->AlreadyHasChannel(info.iChannel))
       
   780 			{
       
   781 			iChannelMonitor->AddNewChannelL(info.iChannel);
       
   782 			++aRollBackChannels;
       
   783 			}
       
   784 		}
       
   785 	}
       
   786 
       
   787 CEikSrvNotifierManager::CEikSrvNotifierManager()
       
   788 	{
       
   789 	}
       
   790 
       
   791 void CEikSrvNotifierManager::ConstructL()
       
   792 	{
       
   793 	iObservedList = new(ELeave) CArrayPtrSeg<CEikSrvNotifierWrapper>(6);
       
   794 	iChannelMonitor = CChannelMonitor::NewL();
       
   795 	iActivityMonitor = CActivityMonitor::NewL();
       
   796 	iQueue = CEikNotifierQueue::NewL();
       
   797 	iNotifierRemover = CEikSrvNotifierRemover::NewL();
       
   798 	iDiscoverNewImplementation = CDiscoverNewImplementation::NewL(*this);
       
   799 	}
       
   800 
       
   801 struct SActivityCleanup
       
   802 	{
       
   803 	CActivityMonitor* iMonitor;
       
   804 	TUid iNotifier;
       
   805 	TInt iClientId;
       
   806 	};
       
   807 
       
   808 LOCAL_C void CleanupActivityMonitor(TAny* aPtr)
       
   809 	{
       
   810 	SActivityCleanup& cleanup = *reinterpret_cast<SActivityCleanup*>(aPtr);
       
   811 	cleanup.iMonitor->Remove(cleanup.iNotifier, cleanup.iClientId);
       
   812 	}
       
   813 
       
   814 class MNotifierStarter
       
   815 	{
       
   816 public:
       
   817 	virtual TInt StartAlreadyActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer) = 0;
       
   818 	virtual void StartInactiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* aResponse) = 0;
       
   819 	virtual CEikNotifierQueue::CQueueItem* NewQueueItemLC(const MEikSrvNotifierBase2::TNotifierInfo& aInfo, TInt aClientId, const TDesC8& aBuffer) = 0;
       
   820 	};
       
   821 
       
   822 class MNotifierUpdater
       
   823 	{
       
   824 public:
       
   825 	virtual void UpdateActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* aResponse) = 0;
       
   826 	};
       
   827 
       
   828 //
       
   829 // class TSynchronousNotifierUpdater
       
   830 //
       
   831 
       
   832 NONSHARABLE_CLASS(TSynchronousNotifierUpdater) : public MNotifierUpdater
       
   833 	{
       
   834 public:
       
   835 	inline TSynchronousNotifierUpdater() {}
       
   836 private:
       
   837 	virtual void UpdateActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* aResponse);
       
   838 	};
       
   839 
       
   840 void TSynchronousNotifierUpdater::UpdateActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* aResponse)
       
   841 	{
       
   842 	if (aResponse)
       
   843 		aResponse->Copy(aNotifier.UpdateL(aBuffer));
       
   844 	else
       
   845 		aNotifier.UpdateL(aBuffer);
       
   846 	}
       
   847 
       
   848 NONSHARABLE_CLASS(TAsynchronousNotifierUpdater) : public MNotifierUpdater
       
   849 	{
       
   850 public:
       
   851 	TAsynchronousNotifierUpdater(TInt aReplySlot, const RMessage2& aMessage);
       
   852 private: // from TSynchronousNotifierUpdater
       
   853 	void UpdateActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* aResponse);
       
   854 private:
       
   855 	TInt iReplySlot;
       
   856 	const RMessage2& iMessage;
       
   857 	};
       
   858 
       
   859 TAsynchronousNotifierUpdater::TAsynchronousNotifierUpdater(TInt aReplySlot, const RMessage2& aMessage)
       
   860 	:iReplySlot(aReplySlot), iMessage(aMessage)
       
   861 	{
       
   862 	}
       
   863 
       
   864 void TAsynchronousNotifierUpdater::UpdateActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* /*aResponse*/)
       
   865 	{
       
   866 	aNotifier.UpdateL(aBuffer, iReplySlot, iMessage);
       
   867 	}
       
   868 
       
   869 //
       
   870 // class CEikSrvNotifierManager
       
   871 // 
       
   872 
       
   873 void CEikSrvNotifierManager::DoNotifierStartL(MNotifierStarter& aNotifierStarter,TBool& aCleanupComplete,TUid aNotifierUid,TUid aChannelUid,const TDesC8& aBuffer,TDes8* aResponse, TInt aClientId)
       
   874 	{
       
   875 	TInt result = KErrNotFound;
       
   876 	RArray<TInt> notifierPositions;
       
   877 	CleanupClosePushL(notifierPositions);
       
   878 	
       
   879 	LookForNotifierInObservedListL(aNotifierUid, aChannelUid, notifierPositions);
       
   880 	
       
   881 	for (TInt ii = 0; ii < notifierPositions.Count(); ii++)
       
   882 		{
       
   883 		MEikSrvNotifierBase2* notif = ((*iObservedList)[notifierPositions[ii]])->iNotifier;
       
   884 		const MEikSrvNotifierBase2::TNotifierInfo info = notif->Info();
       
   885 		if(!NotifierHandlesScreenMode(notif))
       
   886 			User::Leave(KErrNotSupported);
       
   887 
       
   888 		if (iActivityMonitor->IsNotifierActive(aNotifierUid, info.iChannel))
       
   889 			result = aNotifierStarter.StartAlreadyActiveNotifierL(*notif, aBuffer);
       
   890 		else if (info.iPriority > iChannelMonitor->ActivityLevel(info.iChannel))
       
   891 			{
       
   892 			TUid notifier;
       
   893 			MEikSrvNotifierBase2::TNotifierPriority priority;
       
   894 			const TBool channelWasActive = iActivityMonitor->IsChannelActive(info.iChannel, notifier, priority);
       
   895 			iActivityMonitor->AddL(info, aClientId);
       
   896 			
       
   897 			SActivityCleanup cleanup;
       
   898 			cleanup.iMonitor = iActivityMonitor;
       
   899 			cleanup.iNotifier = aNotifierUid;
       
   900 			cleanup.iClientId = aClientId;
       
   901 			CleanupStack::PushL(TCleanupItem(CleanupActivityMonitor,&cleanup));
       
   902 			
       
   903 			aCleanupComplete = EFalse;
       
   904 			aNotifierStarter.StartInactiveNotifierL(*notif,aBuffer,aResponse);
       
   905 			CleanupStack::Pop(&cleanup);
       
   906 			
       
   907 			if (channelWasActive)
       
   908 				UpdateHighestPriorityNotifiersOnThisChannelOfTheirPausingOrResuming(info.iChannel, notifier, KEikNotifierPaused);
       
   909 
       
   910 			iChannelMonitor->UpdateChannel(info.iChannel, info.iPriority);
       
   911 			if (result != KQueued)
       
   912 				result = KErrNone;
       
   913 			}
       
   914 		else
       
   915 			{
       
   916 			if (iQueue->IsAlreadyQueued(info.iUid, info.iChannel))
       
   917 				result = KErrAlreadyExists;
       
   918 			else
       
   919 				{
       
   920 				CEikNotifierQueue::CQueueItem* const queueCopy = aNotifierStarter.NewQueueItemLC(info,aClientId,aBuffer);
       
   921 				iQueue->QueueItemL(queueCopy);
       
   922 				CleanupStack::Pop(queueCopy);
       
   923 				result = KQueued;
       
   924 				}
       
   925 			}
       
   926 		}
       
   927 		
       
   928 	User::LeaveIfError(result);
       
   929 	CleanupStack::PopAndDestroy(&notifierPositions);
       
   930 	}
       
   931 
       
   932 class TSynchronousNotifierStarter : public MNotifierStarter
       
   933 	{
       
   934 public:
       
   935 	inline TSynchronousNotifierStarter() {}
       
   936 private: // from MNotifierStarter
       
   937 	TInt StartAlreadyActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer);
       
   938 	void StartInactiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* aResponse);
       
   939 	CEikNotifierQueue::CQueueItem* NewQueueItemLC(const MEikSrvNotifierBase2::TNotifierInfo& aInfo, TInt aClientId, const TDesC8& aBuffer);
       
   940 private:
       
   941 	};
       
   942 
       
   943 TInt TSynchronousNotifierStarter::StartAlreadyActiveNotifierL(MEikSrvNotifierBase2&,const TDesC8&)
       
   944 	{
       
   945 	return KErrAlreadyExists;
       
   946 	}
       
   947 
       
   948 void TSynchronousNotifierStarter::StartInactiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* aResponse)
       
   949 	{
       
   950 	if(aResponse)
       
   951 		aResponse->Copy(aNotifier.StartL(aBuffer));
       
   952 	else
       
   953 		aNotifier.StartL(aBuffer);
       
   954 	}
       
   955 
       
   956 CEikNotifierQueue::CQueueItem* TSynchronousNotifierStarter::NewQueueItemLC(const MEikSrvNotifierBase2::TNotifierInfo& aInfo, 
       
   957 														TInt aClientId, const TDesC8& aBuffer)
       
   958 	{
       
   959 	return CEikNotifierQueue::CQueueItem::NewLC(aInfo, aClientId, aBuffer, RMessage2(), -1);
       
   960 	}
       
   961 
       
   962 void CEikSrvNotifierManager::NotifierStartL(TUid aNotifierUid, const TDesC8& aBuffer, TDes8* aResponse, TInt aClientId)
       
   963 	{
       
   964 	TBool notUsed = ETrue;
       
   965 	TSynchronousNotifierStarter notifierStarter;
       
   966 	DoNotifierStartL(notifierStarter, notUsed, aNotifierUid, KNonExistentUid, aBuffer, aResponse, aClientId);
       
   967 	}
       
   968 
       
   969 TInt CEikSrvNotifierManager::NotifierUpdateL(TUid aNotifierUid, const TDesC8& aBuffer, TDes8* aResponse, TInt aClientId)
       
   970 	{
       
   971 	TSynchronousNotifierUpdater notifierUpdater;
       
   972 	return DoNotifierUpdateL(notifierUpdater, aNotifierUid, aBuffer, aResponse, aClientId);
       
   973 	}
       
   974 
       
   975 TBool CEikSrvNotifierManager::NotifierHandlesScreenMode(MEikSrvNotifierBase2* aNotifier)
       
   976 	{
       
   977 	const TInt screenMode = CEikonEnv::Static()->ScreenDevice()->CurrentScreenMode();
       
   978 	if(screenMode != 0)
       
   979 		{
       
   980 		const TInt notifierCapabilities = aNotifier->NotifierCapabilites();
       
   981 		if(notifierCapabilities == ENoSpecialCapabilities)
       
   982 			return EFalse;
       
   983 		}
       
   984 		
       
   985 	return ETrue;
       
   986 	}
       
   987 
       
   988 void CEikSrvNotifierManager::LookForNotifierInObservedListL(TUid aNotifierUid, TUid aChannelUid, RArray<TInt>& aNotifierPositions)
       
   989 	{
       
   990 	const TInt count = iObservedList->Count();
       
   991 	for (TInt ii = 0; ii < count; ii++)
       
   992 		{
       
   993 		MEikSrvNotifierBase2* notif = ((*iObservedList)[ii])->iNotifier;
       
   994 		const MEikSrvNotifierBase2::TNotifierInfo info = notif->Info();
       
   995 		if (info.iUid == aNotifierUid && (aChannelUid == KNonExistentUid || info.iChannel == aChannelUid))
       
   996 			User::LeaveIfError(aNotifierPositions.Append(ii));
       
   997 		}
       
   998 	}
       
   999 
       
  1000 void CEikSrvNotifierManager::NotifierStartAndGetResponseL(TUid aNotifierUid, const TDesC8& aBuffer, TInt aReplySlot,
       
  1001 														  const RMessage2& aMessage, TInt aClientId, TBool& aCleanupComplete)
       
  1002 	{
       
  1003 	NotifierStartAndGetResponseL(aNotifierUid, KNonExistentUid, aBuffer, aReplySlot, aMessage, aClientId, aCleanupComplete);
       
  1004 	}
       
  1005 
       
  1006 //
       
  1007 // class TAsynchronousNotifierStarter
       
  1008 //
       
  1009 
       
  1010 NONSHARABLE_CLASS(TAsynchronousNotifierStarter) : public MNotifierStarter
       
  1011 	{
       
  1012 public:
       
  1013 	TAsynchronousNotifierStarter(TInt aReplySlot,const RMessage2& aMessage);
       
  1014 private: // from MNotifierStarter
       
  1015 	TInt StartAlreadyActiveNotifierL(MEikSrvNotifierBase2& aNotifier,const TDesC8& aBuffer);
       
  1016 	void StartInactiveNotifierL(MEikSrvNotifierBase2& aNotifier,const TDesC8& aBuffer,TDes8* aResponse);
       
  1017 	CEikNotifierQueue::CQueueItem* NewQueueItemLC(const MEikSrvNotifierBase2::TNotifierInfo& aInfo,TInt aClientId,const TDesC8& aBuffer);
       
  1018 private:
       
  1019 	TInt iReplySlot;
       
  1020 	const RMessage2& iMessage;
       
  1021 	};
       
  1022 
       
  1023 TAsynchronousNotifierStarter::TAsynchronousNotifierStarter(TInt aReplySlot, const RMessage2& aMessage)
       
  1024 	:iReplySlot(aReplySlot), iMessage(aMessage)
       
  1025 	{
       
  1026 	}
       
  1027 
       
  1028 TInt TAsynchronousNotifierStarter::StartAlreadyActiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer)
       
  1029 	{
       
  1030 	aNotifier.StartL(aBuffer, iReplySlot, iMessage); // asynch notifier can decide whether to support multiple clients
       
  1031 	return KErrNone;
       
  1032 	} 
       
  1033 
       
  1034 void TAsynchronousNotifierStarter::StartInactiveNotifierL(MEikSrvNotifierBase2& aNotifier, const TDesC8& aBuffer, TDes8* /*aResponse*/)
       
  1035 	{
       
  1036 	aNotifier.StartL(aBuffer, iReplySlot, iMessage);
       
  1037 	}
       
  1038 
       
  1039 CEikNotifierQueue::CQueueItem* TAsynchronousNotifierStarter::NewQueueItemLC(const MEikSrvNotifierBase2::TNotifierInfo& aInfo, 
       
  1040 														TInt aClientId, const TDesC8& aBuffer)
       
  1041 	{
       
  1042 	__ASSERT_DEBUG(!iMessage.IsNull(), User::Invariant());
       
  1043 	return CEikNotifierQueue::CQueueItem::NewLC(aInfo, aClientId, aBuffer, iMessage, iReplySlot);
       
  1044 	}
       
  1045 
       
  1046 // 
       
  1047 // class CEikSrvNotifierManager
       
  1048 //
       
  1049 
       
  1050 void CEikSrvNotifierManager::NotifierStartAndGetResponseL(TUid aNotifierUid, TUid aChannelUid, const TDesC8& aBuffer, TInt aReplySlot,
       
  1051 														  const RMessage2& aMessage, TInt aClientId, TBool& aCleanupComplete)
       
  1052 	{
       
  1053 	TAsynchronousNotifierStarter notifierStarter(aReplySlot, aMessage);
       
  1054 	TBuf8<1> notUsed;
       
  1055 	DoNotifierStartL(notifierStarter, aCleanupComplete, aNotifierUid, aChannelUid, aBuffer, &notUsed, aClientId);
       
  1056 	}
       
  1057 
       
  1058 void CEikSrvNotifierManager::NotifierUpdateAndGetResponseL(TUid aNotifierUid, const TDesC8& aBuffer, TInt aReplySlot,
       
  1059 														  const RMessage2& aMessage, TInt aClientId)
       
  1060 	{
       
  1061 	TAsynchronousNotifierUpdater notifierUpdater(aReplySlot, aMessage);
       
  1062 	TBuf8<1> notUsed;
       
  1063 	DoNotifierUpdateL(notifierUpdater, aNotifierUid, aBuffer, &notUsed, aClientId);
       
  1064 	}
       
  1065 
       
  1066 TInt CEikSrvNotifierManager::DoNotifierUpdateL(MNotifierUpdater& aNotifierUpdater, TUid aNotifierUid, const TDesC8& aBuffer, TDes8* aResponse, TInt aClientId)
       
  1067 	{
       
  1068 	TInt result = KErrNotFound;
       
  1069 	TInt foundNotifs = 0;
       
  1070 	const TInt count = iObservedList->Count();
       
  1071 	for (TInt ii = 0; ii < count; ii++)
       
  1072 		{
       
  1073 		MEikSrvNotifierBase2* notif=((*iObservedList)[ii])->iNotifier;
       
  1074 		const MEikSrvNotifierBase2::TNotifierInfo info=notif->Info();
       
  1075 		if(info.iUid == aNotifierUid)
       
  1076 			{
       
  1077 			if (iActivityMonitor->IsNotifierActive(aNotifierUid,info.iChannel))
       
  1078 				{
       
  1079 				if (!iActivityMonitor->IsClientPresent(aNotifierUid,info.iChannel,aClientId))
       
  1080 					iActivityMonitor->AddL(info,aClientId);
       
  1081 
       
  1082 				aNotifierUpdater.UpdateActiveNotifierL(*notif,aBuffer,aResponse);
       
  1083 				foundNotifs++;
       
  1084 				}
       
  1085 			else
       
  1086 				{
       
  1087 				; // not all channels have been started yet so update the queue
       
  1088 				}
       
  1089 
       
  1090 			result = KErrNone;
       
  1091 			}
       
  1092 		}
       
  1093 
       
  1094 	if (!foundNotifs && !result) // No active notifs found
       
  1095 		result = KErrNotReady;
       
  1096 	
       
  1097 	User::LeaveIfError(result); //leave because return code is not handled
       
  1098 	return result;
       
  1099 	}
       
  1100 
       
  1101 TInt CEikSrvNotifierManager::NotifierCancel(TUid aNotifierUid)
       
  1102 	{
       
  1103 /*
       
  1104   1. Old notif always gets cancelled.
       
  1105   2. fetch next item from each channel.  If non-NULL, start these items now
       
  1106   3. if item fails to start call NotifierCancel for that uid, cancelling all 
       
  1107      channels regardless of whether they were already running
       
  1108 */
       
  1109 	TInt result = KErrNotFound;
       
  1110 	const TInt count = iObservedList->Count();
       
  1111 	for (TInt ii = 0; ii < count; ii++)
       
  1112 		{
       
  1113 		MEikSrvNotifierBase2* notif = ((*iObservedList)[ii])->iNotifier;
       
  1114 		const MEikSrvNotifierBase2::TNotifierInfo info = notif->Info();
       
  1115 		if (info.iUid == aNotifierUid)
       
  1116 			{
       
  1117 			// This will cause the client request to be set to complete by the notifier's Cancel
       
  1118 			// (if it has been implemented properly) unless the notifier has never been started
       
  1119 			// (the notifier's StartL function has never been called).
       
  1120 			// If the notifier has never been started it is in the queue and 
       
  1121 			// CEikNotifierQueue::RemoveNotifier will complete the client request instead of the notifier.
       
  1122 			notif->Cancel();
       
  1123 			((*iObservedList)[ii])->iIsReadyForRemoval = ETrue;	// record that this notifier will be removed if it's from a transient type dll.
       
  1124 			if(iNotifierRemover)
       
  1125 				{
       
  1126 				iNotifierRemover->Cancel();
       
  1127 				iNotifierRemover->Start(this, iObservedList);
       
  1128 				}
       
  1129 				
       
  1130 			iActivityMonitor->RemoveNotifier(aNotifierUid,info.iChannel);
       
  1131 			iQueue->RemoveNotifier(aNotifierUid);
       
  1132 			
       
  1133 			//check channel activity and get highest priority on channnel
       
  1134 			TUid notifier;
       
  1135 			MEikSrvNotifierBase2::TNotifierPriority priority;
       
  1136 			if (iActivityMonitor->IsChannelActive(info.iChannel, notifier, priority))
       
  1137 				{
       
  1138 				// Check if priority of a queued item on the same channel is greater 
       
  1139 				const MEikSrvNotifierBase2::TNotifierPriority queuePriority = 
       
  1140 						(MEikSrvNotifierBase2::TNotifierPriority)iQueue->GetHighestQueuePriority(info.iChannel);
       
  1141 				
       
  1142 				if (queuePriority > priority)
       
  1143 					{
       
  1144 					iChannelMonitor->UpdateChannel(info.iChannel, MEikSrvNotifierBase2::ENotifierPriorityLowest);
       
  1145 					StartNextFromQueue(info.iChannel);
       
  1146 					}
       
  1147 				else
       
  1148 					{
       
  1149 					UpdateHighestPriorityNotifiersOnThisChannelOfTheirPausingOrResuming(info.iChannel, notifier, KEikNotifierResumed);
       
  1150 					iChannelMonitor->UpdateChannel(info.iChannel, priority);
       
  1151 					}
       
  1152 				}
       
  1153 			else
       
  1154 				{
       
  1155 				iChannelMonitor->UpdateChannel(info.iChannel, MEikSrvNotifierBase2::ENotifierPriorityLowest);
       
  1156 				StartNextFromQueue(info.iChannel);
       
  1157 				}
       
  1158 				
       
  1159 			result = KErrNone;
       
  1160 			}
       
  1161 		}
       
  1162 		
       
  1163 	return result;
       
  1164 	}
       
  1165 
       
  1166 struct SCleanupMessage
       
  1167 	{
       
  1168 	TBool* iDoCleanup;
       
  1169 	const RMessage2* iMessage;
       
  1170 	};
       
  1171 
       
  1172 LOCAL_C void CleanupStartAndGetResponse(TAny* aPtr)
       
  1173 	{
       
  1174 	SCleanupMessage& cleanup = *reinterpret_cast<SCleanupMessage*>(aPtr);
       
  1175 	if (cleanup.iDoCleanup)
       
  1176 		cleanup.iMessage->Complete(KErrNoMemory);
       
  1177 	}
       
  1178 
       
  1179 void CEikSrvNotifierManager::StartNextFromQueue(TUid aChannel)
       
  1180 	{
       
  1181 	CEikNotifierQueue::CQueueItem* next = iQueue->FetchItem(aChannel);	// Transfer ownership of CQueueItem from the queue
       
  1182 	if (next)
       
  1183 		{
       
  1184 		const TUid notif = next->iInfo.iUid;
       
  1185 		TRAPD(err, DoStartQueuedItemLD(next));	// Safely consumes CQueueItem "next"
       
  1186 		if (err)
       
  1187 			NotifierCancel(notif);
       
  1188 		}
       
  1189 	}
       
  1190 	
       
  1191 void CEikSrvNotifierManager::DoStartQueuedItemLD(CEikNotifierQueue::CQueueItem* aItem)	
       
  1192 	{
       
  1193 	CleanupStack::PushL(aItem);
       
  1194 
       
  1195 	if (aItem->iMessage.IsNull())
       
  1196 		NotifierStartL(aItem->iInfo.iUid, aItem->Buffer(), NULL, aItem->iClientId);
       
  1197 	else
       
  1198 		{
       
  1199 		TBool doCleanup = ETrue;
       
  1200 		SCleanupMessage cleanup;
       
  1201 		cleanup.iDoCleanup = &doCleanup;
       
  1202 		cleanup.iMessage = &aItem->iMessage;
       
  1203 		CleanupStack::PushL(TCleanupItem(CleanupStartAndGetResponse, &cleanup));
       
  1204 		NotifierStartAndGetResponseL(aItem->iInfo.iUid, aItem->iInfo.iChannel, aItem->Buffer(), 
       
  1205 									aItem->iReplySlot, aItem->iMessage, aItem->iClientId, doCleanup);
       
  1206 		CleanupStack::Pop(&cleanup);
       
  1207 		}
       
  1208 
       
  1209 	CleanupStack::PopAndDestroy(aItem);
       
  1210 	}
       
  1211 
       
  1212 void CEikSrvNotifierManager::HandleClientExit(TInt aClientId)
       
  1213 	{
       
  1214 	TUid notifier = KNullUid;
       
  1215 	while (iActivityMonitor->NotifierForClient(notifier, aClientId))
       
  1216 		{
       
  1217 		const TInt count = iObservedList->Count();
       
  1218 		for (TInt ii = 0; ii < count; ii++)
       
  1219 			{
       
  1220 			MEikSrvNotifierBase2* notif = ((*iObservedList)[ii])->iNotifier;
       
  1221 			if (notif->Info().iUid == notifier)
       
  1222 				NotifierCancel(notifier);
       
  1223 			}
       
  1224 			
       
  1225 		iActivityMonitor->Remove(notifier,aClientId);
       
  1226 		}
       
  1227 		
       
  1228 	iActivityMonitor->RemoveClient(aClientId);
       
  1229 	iQueue->RemoveClient(aClientId);
       
  1230 	}
       
  1231 
       
  1232 void CEikSrvNotifierManager::StartNotifierL(TUid aNotifierUid,const TDesC8& aBuffer,TDes8& aResponse)
       
  1233 	{
       
  1234 	NotifierStartL(aNotifierUid,aBuffer,&aResponse,KNullClientId);
       
  1235 	}
       
  1236 
       
  1237 void CEikSrvNotifierManager::CancelNotifier(TUid aNotifierUid)
       
  1238 	{
       
  1239 	NotifierCancel(aNotifierUid);
       
  1240 	}
       
  1241 
       
  1242 void CEikSrvNotifierManager::UpdateNotifierL(TUid aNotifierUid,const TDesC8& aBuffer,TDes8& aResponse)
       
  1243 	{
       
  1244 	NotifierUpdateL(aNotifierUid,aBuffer,&aResponse,KNullClientId);
       
  1245 	}
       
  1246 
       
  1247 void CEikSrvNotifierManager::HandleScreenDeviceChangedL()
       
  1248 	{ 
       
  1249 	//notify any active notifiers of a screen changed event, if they don't support a screen mode change.
       
  1250 	//they are cancelled and the list of notifiers is iterated through again to check for any 
       
  1251 	//queued notifiers that may have been made active.
       
  1252 	const TInt count = iObservedList->Count();
       
  1253 	MEikSrvNotifierBase2::TNotifierInfo notifierInfo;
       
  1254 	for (TInt ii = 0; ii < count; ii++)
       
  1255 		{
       
  1256 		MEikSrvNotifierBase2* notifier = (*iObservedList)[ii]->iNotifier;
       
  1257 		notifierInfo = notifier->Info();
       
  1258 		if(iActivityMonitor->IsNotifierActive(notifierInfo.iUid, notifierInfo.iChannel))
       
  1259 			{
       
  1260 			const TInt notifierCapabilities = notifier->NotifierCapabilites();
       
  1261 			if(notifierCapabilities == ENoSpecialCapabilities)
       
  1262 				{
       
  1263 				//Notifier does not support flip events so cancel it.
       
  1264 				NotifierCancel(notifierInfo.iUid);
       
  1265 				}
       
  1266 			else if(notifierCapabilities&EScreenDeviceChangeSupported)
       
  1267 				{
       
  1268 				notifier->HandleSystemEventL(KUidEventScreenModeChanged);
       
  1269 				}
       
  1270 			}
       
  1271 		}
       
  1272 	}
       
  1273 
       
  1274 //
       
  1275 // CChannelMonitor
       
  1276 //
       
  1277 
       
  1278 CChannelMonitor* CChannelMonitor::NewL()
       
  1279 	{
       
  1280 	CChannelMonitor* self = new(ELeave) CChannelMonitor;
       
  1281 	return self;
       
  1282 	}
       
  1283 
       
  1284 TInt CChannelMonitor::NumberOfChannels() const
       
  1285 	{
       
  1286 	return iMonitor.Count();
       
  1287 	}
       
  1288 
       
  1289 void CChannelMonitor::DeleteChannel(TInt aIndex)
       
  1290 	{
       
  1291 	__ASSERT_ALWAYS((aIndex >= 0) && (aIndex < iMonitor.Count()), Panic(EEikServPanicChannelIndexOutOfRange));
       
  1292 	iMonitor.Delete(aIndex);
       
  1293 	}
       
  1294 
       
  1295 TBool CChannelMonitor::AlreadyHasChannel(TUid aChannel) const
       
  1296 	{
       
  1297 	const TInt count = iMonitor.Count();
       
  1298 	for (TInt ii = 0; ii < count; ii++)
       
  1299 		{
       
  1300 		if (iMonitor[ii].iChannel == aChannel)
       
  1301 			return ETrue;
       
  1302 		}
       
  1303 		
       
  1304 	return EFalse;
       
  1305 	}
       
  1306 
       
  1307 TInt CChannelMonitor::ActivityLevel(TUid aChannel) const
       
  1308 	{
       
  1309 	const TInt count = iMonitor.Count();
       
  1310 	for (TInt ii = 0; ii < count; ii++)
       
  1311 		{
       
  1312 		const TChannelActivity activity = iMonitor[ii];
       
  1313 		if (activity.iChannel == aChannel)
       
  1314 			return activity.iHighestPriorityRunning;
       
  1315 		}
       
  1316 		
       
  1317 	return 0;
       
  1318 	}
       
  1319 
       
  1320 void CChannelMonitor::UpdateChannel(TUid aChannel, TInt aLevel)
       
  1321 	{
       
  1322 	const TInt count = iMonitor.Count();
       
  1323 	for (TInt ii = 0; ii < count; ii++)
       
  1324 		{
       
  1325 		TChannelActivity& activity = iMonitor[ii];
       
  1326 		if (activity.iChannel == aChannel)
       
  1327 			{
       
  1328 			activity.iHighestPriorityRunning = aLevel;
       
  1329 			break;
       
  1330 			}
       
  1331 		}
       
  1332 	}
       
  1333 
       
  1334 CChannelMonitor::CChannelMonitor()
       
  1335 	:iMonitor(3)
       
  1336 	{}
       
  1337 
       
  1338 //
       
  1339 // class CNotifierActivity
       
  1340 //
       
  1341 
       
  1342 CActivityMonitor::CNotifierActivity* CActivityMonitor::CNotifierActivity::NewLC(const MEikSrvNotifierBase2::TNotifierInfo& aInfo,TInt aClientId)
       
  1343 	{ // static
       
  1344 	CNotifierActivity* self=new(ELeave) CNotifierActivity(aInfo);
       
  1345 	CleanupStack::PushL(self);
       
  1346 	self->ConstructL(aClientId);
       
  1347 	return self;
       
  1348 	}
       
  1349 
       
  1350 CActivityMonitor::CNotifierActivity::~CNotifierActivity()
       
  1351 	{
       
  1352 	iClientArray.Reset();
       
  1353 	}
       
  1354 
       
  1355 TInt CActivityMonitor::CNotifierActivity::Find(TInt aClientId) const
       
  1356 	{
       
  1357 	TInt index=KErrNotFound;
       
  1358 	const TInt count=iClientArray.Count();
       
  1359 	for (TInt ii=0;ii<count;ii++)
       
  1360 		{
       
  1361 		TInt clientId=iClientArray[ii];
       
  1362 		if (clientId==aClientId)
       
  1363 			{
       
  1364 			index=ii;
       
  1365 			break;
       
  1366 			}
       
  1367 		}
       
  1368 		
       
  1369 	return index;
       
  1370 	}
       
  1371 
       
  1372 CActivityMonitor::CNotifierActivity::CNotifierActivity(const MEikSrvNotifierBase2::TNotifierInfo& aInfo)
       
  1373 	: iInfo(aInfo), iClientArray(1)
       
  1374 	{}
       
  1375 
       
  1376 void CActivityMonitor::CNotifierActivity::ConstructL(TInt aClientId)
       
  1377 	{
       
  1378 	iClientArray.AppendL(aClientId);
       
  1379 	}
       
  1380 
       
  1381 //
       
  1382 // class CActivityMonitor
       
  1383 //
       
  1384 
       
  1385 CActivityMonitor* CActivityMonitor::NewL()
       
  1386 	{ // static
       
  1387 	CActivityMonitor* self=new(ELeave) CActivityMonitor();
       
  1388 	return self;
       
  1389 	}
       
  1390 
       
  1391 CActivityMonitor::~CActivityMonitor()
       
  1392 	{
       
  1393 	iMonitor.ResetAndDestroy();
       
  1394 	}
       
  1395 
       
  1396 void CActivityMonitor::AddL(const MEikSrvNotifierBase2::TNotifierInfo& aInfo,TInt aClientId)
       
  1397 	{
       
  1398 	const TInt index = Find(aInfo.iUid,aInfo.iChannel);
       
  1399 	if (index == KErrNotFound)
       
  1400 		{
       
  1401 		CNotifierActivity* activity = CNotifierActivity::NewLC(aInfo,aClientId);
       
  1402 		iMonitor.AppendL(activity);
       
  1403 		CleanupStack::Pop(); // activity
       
  1404 		}
       
  1405 	else
       
  1406 		iMonitor[index]->iClientArray.AppendL(aClientId);
       
  1407 	}
       
  1408 
       
  1409 void CActivityMonitor::Remove(TUid aNotifierUid,TInt aClientId)
       
  1410 	{
       
  1411 	const TInt index = Find(aNotifierUid);
       
  1412 	if (index != KErrNotFound)
       
  1413 		{
       
  1414 		CNotifierActivity* activity=iMonitor[index];
       
  1415 		const TInt clientIndex=activity->Find(aClientId);
       
  1416 		if (clientIndex != KErrNotFound)
       
  1417 			{
       
  1418 			if (activity->iClientArray.Count()==1)
       
  1419 				{
       
  1420 				delete activity;
       
  1421 				iMonitor.Delete(index);
       
  1422 				}
       
  1423 			else
       
  1424 				activity->iClientArray.Delete(index);
       
  1425 			}
       
  1426 		}
       
  1427 	}
       
  1428 
       
  1429 void CActivityMonitor::RemoveNotifier(TUid aNotifierUid,TUid aChannel)
       
  1430 	{
       
  1431 	const TInt index = Find(aNotifierUid,aChannel);
       
  1432 	if (index != KErrNotFound)
       
  1433 		{
       
  1434 		delete iMonitor[index];
       
  1435 		iMonitor.Delete(index);
       
  1436 		}
       
  1437 	}
       
  1438 
       
  1439 void CActivityMonitor::RemoveClient(TInt aClientId)
       
  1440 	{
       
  1441 	TInt ii = 0;
       
  1442 	while (ii < iMonitor.Count())
       
  1443 		{
       
  1444 		CNotifierActivity* ptr = iMonitor[ii];
       
  1445 		const TInt index = ptr->Find(aClientId);
       
  1446 		if (index != KErrNotFound)
       
  1447 			ptr->iClientArray.Delete(index);
       
  1448 			
       
  1449 		if (ptr->iClientArray.Count()==0)
       
  1450 			{
       
  1451 			iMonitor.Delete(ii);
       
  1452 			delete ptr;
       
  1453 			}
       
  1454 		else
       
  1455 			++ii;
       
  1456 		}
       
  1457 	}
       
  1458 
       
  1459 TBool CActivityMonitor::IsNotifierActive(TUid aNotifierUid,TUid aChannel) const
       
  1460 	{
       
  1461 	const TInt index = Find(aNotifierUid,aChannel);
       
  1462 	return (index != KErrNotFound);
       
  1463 	}
       
  1464 
       
  1465 TBool CActivityMonitor::IsClientPresent(TUid aNotifierUid,TUid aChannel,TInt aClientId) const
       
  1466 	{
       
  1467 	TBool found = EFalse;
       
  1468 	const TInt index = Find(aNotifierUid,aChannel);
       
  1469 	if (index != KErrNotFound)
       
  1470 		found = (iMonitor[index]->Find(aClientId) != KErrNotFound);
       
  1471 	
       
  1472 	return found;
       
  1473 	}
       
  1474 
       
  1475 TBool CActivityMonitor::IsChannelActive(TUid aChannel,TUid& aNotifier,MEikSrvNotifierBase2::TNotifierPriority& aHighestPriority) const
       
  1476 	{
       
  1477 	TBool isChannelActive = EFalse;
       
  1478 	const TInt count = iMonitor.Count();
       
  1479 	for (TInt ii = 0; ii < count; ii++)
       
  1480 		{
       
  1481 		const MEikSrvNotifierBase2::TNotifierInfo info=iMonitor[ii]->iInfo;
       
  1482 		if (info.iChannel == aChannel)
       
  1483 			{
       
  1484 			if ((!isChannelActive) || (aHighestPriority < (MEikSrvNotifierBase2::TNotifierPriority)info.iPriority))
       
  1485 				{
       
  1486 				isChannelActive = ETrue;
       
  1487 				aNotifier = info.iUid;
       
  1488 				aHighestPriority = (MEikSrvNotifierBase2::TNotifierPriority)info.iPriority;
       
  1489 				}
       
  1490 			}
       
  1491 		}
       
  1492 		
       
  1493 	return isChannelActive;
       
  1494 	}
       
  1495 
       
  1496 TBool CActivityMonitor::NotifierForClient(TUid& aNotifierUid, TInt aClientId) const
       
  1497 	{
       
  1498 	TBool isOnlyClient = EFalse;
       
  1499 	aNotifierUid = KNullUid;
       
  1500 	const TInt count = iMonitor.Count();
       
  1501 	for (TInt ii = 0; ii < count; ii++)
       
  1502 		{
       
  1503 		CNotifierActivity* ptr = iMonitor[ii];
       
  1504 		if (ptr->Find(aClientId) != KErrNotFound)
       
  1505 			{
       
  1506 			aNotifierUid = ptr->iInfo.iUid;
       
  1507 			isOnlyClient = ptr->iClientArray.Count()==1;
       
  1508 			break;
       
  1509 			}
       
  1510 		}
       
  1511 		
       
  1512 	return isOnlyClient;
       
  1513 	}
       
  1514 
       
  1515 CActivityMonitor::CActivityMonitor()
       
  1516 	: iMonitor(1)
       
  1517 	{}
       
  1518 
       
  1519 TInt CActivityMonitor::Find(TUid aNotifierUid) const
       
  1520 	{
       
  1521 	const TInt count = iMonitor.Count();
       
  1522 	for (TInt ii = 0; ii < count; ii++)
       
  1523 		{
       
  1524 		if (iMonitor[ii]->iInfo.iUid == aNotifierUid)
       
  1525 			return ii;
       
  1526 		}
       
  1527 		
       
  1528 	return KErrNotFound;
       
  1529 	}
       
  1530 
       
  1531 TInt CActivityMonitor::Find(TUid aNotifierUid, TUid aChannel) const
       
  1532 	{
       
  1533 	const TInt count = iMonitor.Count();
       
  1534 	for (TInt ii = 0; ii < count; ii++)
       
  1535 		{
       
  1536 		const CNotifierActivity* ptr = iMonitor[ii];
       
  1537 		if (ptr->iInfo.iUid == aNotifierUid && ptr->iInfo.iChannel == aChannel)
       
  1538 			return ii;
       
  1539 		}
       
  1540 
       
  1541 	return KErrNotFound;
       
  1542 	}
       
  1543 
       
  1544 //
       
  1545 // class CQueueItem
       
  1546 //
       
  1547 
       
  1548 CEikNotifierQueue::CQueueItem* CEikNotifierQueue::CQueueItem::NewLC(const MEikSrvNotifierBase2::TNotifierInfo& aInfo, TInt aClientId, 
       
  1549 																	const TDesC8& aBuffer, const RMessage2& aMessage,TInt aReplySlot)
       
  1550 	{
       
  1551 	CQueueItem* self=new(ELeave) CQueueItem(aInfo,aClientId,aMessage,aReplySlot);
       
  1552 	CleanupStack::PushL(self);
       
  1553 	self->ConstructL(aBuffer);
       
  1554 	return self;
       
  1555 	}
       
  1556 
       
  1557 CEikNotifierQueue::CQueueItem::~CQueueItem()
       
  1558 	{
       
  1559 	delete iBuffer;
       
  1560 	}
       
  1561 
       
  1562 CEikNotifierQueue::CQueueItem::CQueueItem(const MEikSrvNotifierBase2::TNotifierInfo& aInfo, TInt aClientId, 
       
  1563 											const RMessage2& aMessage, TInt aReplySlot)
       
  1564 	:iInfo(aInfo),
       
  1565 	 iClientId(aClientId),
       
  1566 	 iMessage(aMessage),
       
  1567 	 iReplySlot(aReplySlot),
       
  1568 	 iBuffer(NULL)
       
  1569 	{
       
  1570 	}
       
  1571 
       
  1572 void CEikNotifierQueue::CQueueItem::ConstructL(const TDesC8& aBuffer)
       
  1573 	{
       
  1574 	iBuffer=aBuffer.AllocL();
       
  1575 	}
       
  1576 
       
  1577 //
       
  1578 // class CEikNotifierQueue
       
  1579 //
       
  1580 
       
  1581 CEikNotifierQueue* CEikNotifierQueue::NewL()
       
  1582 	{
       
  1583 	CEikNotifierQueue* self = new (ELeave) CEikNotifierQueue;
       
  1584 	return self;
       
  1585 	}
       
  1586 
       
  1587 /**
       
  1588 Get the queue item from the notifier queue. CQueueItem ownership is transfered from
       
  1589 the queue to the caller.
       
  1590 */
       
  1591 CEikNotifierQueue::CQueueItem* CEikNotifierQueue::FetchItem(TUid aChannel)
       
  1592 	{
       
  1593 	CEikNotifierQueue::CQueueItem* result = NULL;
       
  1594 	TInt priority = MEikSrvNotifierBase2::ENotifierPriorityLowest-1;
       
  1595 	TInt index = KErrNotFound;
       
  1596 	
       
  1597 	const TInt count = iQueue.Count();
       
  1598 	for (TInt ii = 0; ii < count; ii++)
       
  1599 		{
       
  1600 		CEikNotifierQueue::CQueueItem* item = iQueue[ii];
       
  1601 		if (item->iInfo.iChannel == aChannel && item->iInfo.iPriority > priority)
       
  1602 			{
       
  1603 			index = ii;
       
  1604 			priority = item->iInfo.iPriority;
       
  1605 			result = item;
       
  1606 			}
       
  1607 		}
       
  1608 
       
  1609 	if (index != KErrNotFound)
       
  1610 		iQueue.Delete(index);
       
  1611 
       
  1612 	return result;
       
  1613 	}
       
  1614 
       
  1615 TBool CEikNotifierQueue::IsAlreadyQueued(TUid aNotifier,TUid aChannel) const
       
  1616 	{
       
  1617 	const TInt count = iQueue.Count();
       
  1618 	for (TInt ii = 0; ii < count; ii++)
       
  1619 		{
       
  1620 		CEikNotifierQueue::CQueueItem* item = iQueue[ii];
       
  1621 		if (item->iInfo.iUid == aNotifier && item->iInfo.iChannel == aChannel)
       
  1622 			return ETrue;
       
  1623 		}
       
  1624 
       
  1625 	return EFalse;
       
  1626 	}
       
  1627 
       
  1628 void CEikNotifierQueue::RemoveClient(TInt aClientId)
       
  1629 	{
       
  1630 	const TInt count = iQueue.Count();
       
  1631 	for (TInt ii = count-1; ii >= 0; ii--)
       
  1632 		{
       
  1633 		CEikNotifierQueue::CQueueItem* item = iQueue[ii];
       
  1634 		TInt clientId = item->iClientId;
       
  1635 		if (clientId == aClientId)
       
  1636 			{
       
  1637 			delete item;
       
  1638 			iQueue.Delete(ii);
       
  1639 			}
       
  1640 		}
       
  1641 	}
       
  1642 
       
  1643 
       
  1644 TInt CEikNotifierQueue::GetHighestQueuePriority(TUid aChannel)
       
  1645 	{
       
  1646 	TInt priority = MEikSrvNotifierBase2::ENotifierPriorityLowest-1;
       
  1647 	
       
  1648 	const TInt count = iQueue.Count();
       
  1649 	for (TInt ii = 0; ii < count; ii++)
       
  1650 		{
       
  1651 		CEikNotifierQueue::CQueueItem* item=iQueue[ii];
       
  1652 		if (item->iInfo.iChannel == aChannel && item->iInfo.iPriority>priority)
       
  1653 			priority = item->iInfo.iPriority;
       
  1654 		}
       
  1655 
       
  1656 	return priority;
       
  1657 	}
       
  1658 
       
  1659 const CEikNotifierQueue::CQueueItem& CEikNotifierQueue::At(TInt aIndex) const
       
  1660 	{
       
  1661 	__ASSERT_DEBUG((aIndex>=0) && (aIndex < iQueue.Count()),Panic(EEikServPanicQueueIndexOutOfRange));
       
  1662 	return *(iQueue.At(aIndex));
       
  1663 	}
       
  1664 
       
  1665 void CEikNotifierQueue::RemoveNotifier(TUid aNotifierUid)
       
  1666 	{
       
  1667 	const TInt count=iQueue.Count();
       
  1668 	for(TInt ii = count -1; ii >= 0; --ii)
       
  1669 		{
       
  1670 		if(iQueue[ii]->iInfo.iUid==aNotifierUid)
       
  1671 			{
       
  1672 			if (!iQueue[ii]->iMessage.IsNull())
       
  1673     			{
       
  1674     			// The notifiers in the queue have never been started and so
       
  1675     			// they have no pointer to the RMessage2 (it is passed in as argument 
       
  1676     			// to the StartL function but it has never been called). The framework
       
  1677     			// has to complete the request.
       
  1678     			iQueue[ii]->iMessage.Complete(KErrCancel);
       
  1679     			}
       
  1680 			iQueue.Delete(ii);
       
  1681 			}
       
  1682 		}
       
  1683 	}
       
  1684 
       
  1685 
       
  1686 
       
  1687 //
       
  1688 
       
  1689 LOCAL_C void ReleaseOnCleanup(TAny* aObject)
       
  1690 //
       
  1691 // Used for cleanup of objects on stack if a function leaves.
       
  1692 //
       
  1693 	{
       
  1694 	REINTERPRET_CAST(RImplInfoPtrArray*,(aObject))->ResetAndDestroy();
       
  1695 	REINTERPRET_CAST(RImplInfoPtrArray*,(aObject))->Close();
       
  1696 	}
       
  1697 
       
  1698 TInt FindInOrderFunction(const CPluginTrack& aPluginTrack1,const CPluginTrack& aPluginTrack2)
       
  1699 //
       
  1700 // This function is used to find a plugin with specific implementation uid in the list.
       
  1701 // It is internally called by RPointerArray function FindInOrder.
       
  1702 //
       
  1703 	{
       
  1704 	return (aPluginTrack1.iPluginImplementationUid.iUid - aPluginTrack2.iPluginImplementationUid.iUid);
       
  1705 	}
       
  1706 
       
  1707 void CEikSrvNotifierManager::RegisterL()
       
  1708 //
       
  1709 // Register the plugins at bootup
       
  1710 //
       
  1711 	{
       
  1712 	//This is the list where we have the information of all the ECOM plugin i,e
       
  1713 	// 1. The plugin implementatiuon UID
       
  1714 	// 2. The Number of instances of recognizer in an single implementation
       
  1715 	// 3. The Plugin Destructor Key
       
  1716 	iPluginUidList.Reset();
       
  1717 
       
  1718 	// Array to return all implementations in an interface
       
  1719 	RImplInfoPtrArray plugInArray;
       
  1720 	
       
  1721 	// ListImplementationsL leaves if it cannot find anything so trap the error and ignore it.
       
  1722 	REComSession::ListImplementationsL(KUidPluginInterfaceNotifiers, plugInArray);
       
  1723 
       
  1724 	// Push the plugin array on the stack
       
  1725 	CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,&plugInArray));
       
  1726 	
       
  1727 	// it the plugin count is zero dont load any thing
       
  1728 	for(TInt i=plugInArray.Count()-1; i>=0; --i)
       
  1729 		{
       
  1730 		TUid chosenUid = {0};
       
  1731 		chosenUid = plugInArray[i]->ImplementationUid();
       
  1732 		TRAPD(err, DoAddPlugInL(chosenUid));
       
  1733 		if(err)
       
  1734 			{
       
  1735 			DEBUGPRINT3(_L("CEikSrvNotifierManager::RegisterL() DoAddPlugInL leaved with error:%d for plugin:0x%x"), err, chosenUid);
       
  1736 			}
       
  1737 		}
       
  1738 
       
  1739 	CleanupStack::Pop(&plugInArray);
       
  1740 	plugInArray.ResetAndDestroy();
       
  1741 	plugInArray.Close();
       
  1742 
       
  1743 	//Sort the Pluginlist array
       
  1744 	TLinearOrder<CPluginTrack> linearOrder (&FindInOrderFunction);
       
  1745 	iPluginUidList.Sort(linearOrder);
       
  1746 
       
  1747 	//Start the discovery of newly added plugins so that we can detect a runtime installation
       
  1748 	iDiscoverNewImplementation->Start();
       
  1749 
       
  1750 	}
       
  1751 
       
  1752 CArrayPtr<CEikSrvNotifierWrapper>* CEikSrvNotifierManager::LoadPlugInAndPopulateNotifierArrayL(TUid aUid)
       
  1753 //
       
  1754 // Loads the notifier plugins depending on the chosen implementation uid.
       
  1755 //
       
  1756 	{
       
  1757     DEBUGPRINT2(_L("CEikSrvNotifierManager:: LoadPlugInAndPopulateNotifierArrayL: Loading Plugin: Uid 0x%X"), aUid );
       
  1758 
       
  1759 	TUid destructorKey;
       
  1760 	// Tells that its a dll	& simulating a Notifier for Type V2.
       
  1761 	TUidType aUidType(KDynamicLibraryUid, KUidNotifierPlugInV2, aUid);
       
  1762 	destructorKey.iUid = 0;
       
  1763 
       
  1764 	//Create implementation for the choosen UID. 
       
  1765 	CArrayPtr<MEikSrvNotifierBase2>* array = reinterpret_cast<CArrayPtr<MEikSrvNotifierBase2>*>(
       
  1766 												REComSession::CreateImplementationL(aUid, destructorKey));
       
  1767 
       
  1768 	// passes ownership of 'array'. Array is internally destroyed.
       
  1769 	CArrayPtr<CEikSrvNotifierWrapper>* retArray = CreateNotifierArrayFromPlugInArrayL(array,aUidType);	
       
  1770 
       
  1771 	// Copys the destructor key to the destructorKey variable in CEikSrvNotifierWrapper class.
       
  1772 	// Also construct the wrapper class which gets the notifier registration information in the member
       
  1773 	// variables.
       
  1774 	const TInt retArrayCount = retArray->Count();
       
  1775 	for (TInt i = 0; i < retArrayCount; i++)
       
  1776 		{
       
  1777 		CEikSrvNotifierWrapper* const notifier = retArray->At(i);
       
  1778 		notifier->RegisterNotifierL();
       
  1779 		notifier->iDestructorKey = destructorKey;
       
  1780 		}
       
  1781 
       
  1782 	return retArray;
       
  1783 	}
       
  1784 
       
  1785 
       
  1786 TBool CEikSrvNotifierManager::IsImplementationRemoved(TUid aImplementationUid, RImplInfoPtrArray& aPlugInArray)
       
  1787 // 
       
  1788 // Finds if a particular implementation is present in the ecom registry returned data
       
  1789 //
       
  1790 	{
       
  1791 	for (TInt i=aPlugInArray.Count()-1; i>=0; --i)
       
  1792 		{
       
  1793 		if(aImplementationUid == aPlugInArray[i]->ImplementationUid())
       
  1794 			return EFalse;
       
  1795 		}
       
  1796 			
       
  1797 	return ETrue;
       
  1798 	}
       
  1799 
       
  1800 // 
       
  1801 // Finds if a particular implementation is newly added in the ecom registry returned data
       
  1802 //
       
  1803 TBool CEikSrvNotifierManager::IsImplementationAdded(TUid aImplementationUid)
       
  1804 	{
       
  1805 	for (TInt i=iPluginUidList.Count()-1; i>=0; --i)
       
  1806 		{
       
  1807 		if(aImplementationUid==(iPluginUidList[i])->iPluginImplementationUid)
       
  1808 			return EFalse;
       
  1809 		}
       
  1810 
       
  1811 	return ETrue;
       
  1812 	}
       
  1813 
       
  1814 void CEikSrvNotifierManager::CheckForEcomPluginInstallUninstall()
       
  1815 //
       
  1816 // This function finds out the whether an ecom notifier has been installed or removed
       
  1817 //
       
  1818 	{
       
  1819 	// Array to return all implementations in an interface)
       
  1820 	RImplInfoPtrArray plugInArray;
       
  1821 	
       
  1822 	// ListImplementationsL leaves if it cannot find anything so trap the error and ignore it.
       
  1823 	TRAP_IGNORE(REComSession::ListImplementationsL(KUidPluginInterfaceNotifiers, plugInArray));
       
  1824 	CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup, &plugInArray));
       
  1825 	
       
  1826 	TBool doUpdate = EFalse;
       
  1827 	
       
  1828 	// If an implementation is not present in the iPluginUidList then its added. 
       
  1829 	for(TInt i = plugInArray.Count()-1; i>=0; --i)	
       
  1830 		{
       
  1831 		TUid uid = plugInArray[i]->ImplementationUid();
       
  1832 		if(IsImplementationAdded(uid))
       
  1833 			{
       
  1834 			// Add the implementation which is not present in the plugin array and also 
       
  1835 			// update the plugintrack with new implementation and its dll uid.
       
  1836 			TRAPD(err,DoAddPlugInL(uid));
       
  1837 			if(err)
       
  1838 				{
       
  1839 				DEBUGPRINT3(_L("CEikSrvNotifierManager::CheckForEcomPluginInstallUninstall() DoAddPlugInL leaved with error:%d for plugin:0x%x"), err, uid);
       
  1840 				}
       
  1841 				
       
  1842 			doUpdate = ETrue;
       
  1843 			}
       
  1844 		}
       
  1845 
       
  1846 	// If a implementation is not present in present in the plugInArray then its removed. 
       
  1847 	for(TInt j = iPluginUidList.Count()-1; j >= 0; --j)
       
  1848 		{
       
  1849 		if(IsImplementationRemoved((iPluginUidList[j])->iPluginImplementationUid, plugInArray))
       
  1850 			UnloadEComPlugInImplementation(j);	//Remove the implementation
       
  1851 		}
       
  1852 	
       
  1853 	if(doUpdate)
       
  1854 		{//Sort the Pluginlist array
       
  1855 		TLinearOrder<CPluginTrack> linearOrder(&FindInOrderFunction);
       
  1856 		iPluginUidList.Sort(linearOrder);
       
  1857 		}
       
  1858 
       
  1859 	CleanupStack::Pop(&plugInArray);
       
  1860 	plugInArray.ResetAndDestroy();
       
  1861 	plugInArray.Close();
       
  1862 	}
       
  1863 
       
  1864 void CEikSrvNotifierManager::UnloadEComPlugInImplementation(TInt aIndex)
       
  1865 // 
       
  1866 // Remove the Ecom notifier plugins from the particular implementation
       
  1867 //
       
  1868 	{
       
  1869 	//Remove the Ecom notifier plugins from the particular implementation
       
  1870 	for (TInt i = (iPluginUidList[aIndex])->iNotifierInfo.Count()-1 ; i >=0 ; --i)
       
  1871 		{
       
  1872 		//find in the observed global list the notifier with same Notifier UID, channel UID & destruction key
       
  1873 		for (TInt j = iObservedList->Count()-1; j >=0  ; --j)
       
  1874 			{
       
  1875 			CEikSrvNotifierWrapper* notifier = iObservedList->At(j);
       
  1876 			MEikSrvNotifierBase2::TNotifierInfo info = notifier->iInfo;
       
  1877 			const CPluginTrack& pluginTrack = *iPluginUidList[aIndex];
       
  1878 			const CPluginTrack::TNotifierInfo& info2 = pluginTrack.iNotifierInfo[i];
       
  1879 			if ((info2.iNotifierPluginUid == info.iUid) &&
       
  1880 				(info2.iNotifierPluginChannelUid == info.iChannel) &&
       
  1881 				(pluginTrack.iDtr_key == notifier->iDestructorKey))
       
  1882 				{
       
  1883 				//Delete the notifier
       
  1884 				iObservedList->Delete(j);
       
  1885 				}
       
  1886 			}
       
  1887 		}
       
  1888 
       
  1889 	//Remove the implementation
       
  1890 	delete iPluginUidList[aIndex];
       
  1891 	iPluginUidList.Remove(aIndex);
       
  1892 	}
       
  1893 
       
  1894 void CEikSrvNotifierManager::DoAddPlugInL(TUid aUid)
       
  1895 // 
       
  1896 // Add plugins depending on the implementation UID
       
  1897 //
       
  1898 	{
       
  1899 	CArrayPtr<CEikSrvNotifierWrapper>* array = LoadPlugInAndPopulateNotifierArrayL(aUid);
       
  1900 	User::LeaveIfNull(array);
       
  1901 	CleanupStack::PushL(TCleanupItem(DeleteTempCArray,array));
       
  1902 	TInt rollBackChannels = 0;	// required for removing any added channels should this function fail part way through
       
  1903 
       
  1904 	const TInt currentObsListIndx = iObservedList->Count();
       
  1905 	TRAPD(error, TryAddNotifiersFromNotifierArrayL(array, rollBackChannels));
       
  1906 	if(error)
       
  1907 		{
       
  1908 		TInt indexToDelete;
       
  1909 		for(TInt jj = 0; jj < rollBackChannels; jj++)
       
  1910 			{
       
  1911 			indexToDelete = iChannelMonitor->NumberOfChannels() - 1; 
       
  1912 			iChannelMonitor->DeleteChannel(indexToDelete);
       
  1913 			}
       
  1914 		User::Leave(error);
       
  1915 		}
       
  1916 	CleanupStack::PopAndDestroy(array);
       
  1917 
       
  1918 	//Add the new added plugin to the track list
       
  1919 	CPluginTrack* pluginTrack = new(ELeave) CPluginTrack;
       
  1920 	CleanupStack::PushL(pluginTrack);
       
  1921 	pluginTrack->iPluginImplementationUid = aUid;
       
  1922 	//Add the notifier info to the track pluginlist after successful loading and roll back
       
  1923 	const TInt obsListCount = iObservedList->Count();
       
  1924 	for (TInt i = currentObsListIndx; i < obsListCount; i++)
       
  1925 		{
       
  1926 		CEikSrvNotifierWrapper* notifier = iObservedList->At(i);
       
  1927 		pluginTrack->iDtr_key = notifier->iDestructorKey;
       
  1928 		CPluginTrack::TNotifierInfo notifInfo(notifier->iInfo.iUid,notifier->iInfo.iChannel);
       
  1929 		User::LeaveIfError(pluginTrack->iNotifierInfo.Append(notifInfo));
       
  1930 		}
       
  1931 
       
  1932 	User::LeaveIfError(iPluginUidList.Append(pluginTrack));
       
  1933 	CleanupStack::Pop(pluginTrack);
       
  1934 	}
       
  1935 
       
  1936 //
       
  1937 // class CDiscoverNewImplementation
       
  1938 //
       
  1939 
       
  1940 CDiscoverNewImplementation::CDiscoverNewImplementation(CEikSrvNotifierManager& aManager): CActive(EActivePriorityDefault) , iManager(aManager)
       
  1941 //
       
  1942 // Constructor.
       
  1943 //
       
  1944 	{
       
  1945 	// make and install the active scheduler
       
  1946 	CActiveScheduler::Add(this); // install as active scheduler
       
  1947 	}
       
  1948 
       
  1949 void CDiscoverNewImplementation::ConstructL()
       
  1950 //
       
  1951 // 2 phase construction. opens a econ server session.
       
  1952 //
       
  1953 	{
       
  1954 	iEComSession = &REComSession::OpenL();
       
  1955 	}
       
  1956 
       
  1957 CDiscoverNewImplementation::~CDiscoverNewImplementation()
       
  1958 // 
       
  1959 // Destructor. Closes ecom file server session and cancels the active object itself.
       
  1960 //
       
  1961 	{
       
  1962 	Cancel();
       
  1963 	iEComSession->Close();
       
  1964 	}
       
  1965 
       
  1966 CDiscoverNewImplementation *CDiscoverNewImplementation::NewL(CEikSrvNotifierManager& aManager)
       
  1967 // 
       
  1968 // Static method to instantiate the class. Notifier manager class pointer is passed as a 
       
  1969 //  argument.
       
  1970 //
       
  1971 	{
       
  1972 	CDiscoverNewImplementation* self = new (ELeave) CDiscoverNewImplementation(aManager);
       
  1973 	CleanupStack::PushL(self);
       
  1974 	self->ConstructL();
       
  1975 	CleanupStack::Pop(self);
       
  1976 	return self;
       
  1977 	}
       
  1978 
       
  1979 void CDiscoverNewImplementation::Start()
       
  1980 // 
       
  1981 // Places an outstanding request to active schedular for asynchronous event by ecom server.
       
  1982 //  Mostly it will be an installation or unstallation of the ecom based sis files.
       
  1983 //
       
  1984 	{
       
  1985 	iEComSession->NotifyOnChange(iStatus);
       
  1986 	SetActive();
       
  1987 	}
       
  1988 
       
  1989 void CDiscoverNewImplementation::RunL()
       
  1990 // 
       
  1991 // Called when an asynchronous request from ecom server is invoked.
       
  1992 //
       
  1993 	{
       
  1994 	_LIT(KCDiscoverNewImplementationPanic,"CDiscoverNewImplementation Paniced");
       
  1995 	__ASSERT_ALWAYS(!IsActive(),User::Panic(KCDiscoverNewImplementationPanic,KErrCompletion));
       
  1996 
       
  1997 	//Check wether plugin was installed or removed
       
  1998 	iManager.CheckForEcomPluginInstallUninstall();
       
  1999 	//Restart the active Object
       
  2000 	Start();
       
  2001 	}
       
  2002 
       
  2003 void CDiscoverNewImplementation::DoCancel()
       
  2004 //
       
  2005 // If user want to cancel the active object request. The ecom server outstanding request will
       
  2006 // also get cancelled.
       
  2007 //
       
  2008 	{
       
  2009 	iEComSession->CancelNotifyOnChange(iStatus);
       
  2010 	}
       
  2011 
       
  2012 //
       
  2013 // class CPluginTrack::TNotifierInfo
       
  2014 //
       
  2015 
       
  2016 CPluginTrack::TNotifierInfo::TNotifierInfo(TUid aNotifierPluginUid, TUid aNotifierPluginChannelUid)
       
  2017 //
       
  2018 // Constructor.
       
  2019 //
       
  2020 	{
       
  2021 	iNotifierPluginUid = aNotifierPluginUid;
       
  2022 	iNotifierPluginChannelUid = aNotifierPluginChannelUid;
       
  2023 	}
       
  2024 
       
  2025 //
       
  2026 // class CPluginTrack
       
  2027 //
       
  2028 
       
  2029 CPluginTrack::CPluginTrack()
       
  2030 // 
       
  2031 // Constructor
       
  2032 //
       
  2033 	{
       
  2034 	iPluginImplementationUid.iUid = 0;
       
  2035 	iDtr_key.iUid = 0;
       
  2036 	}
       
  2037 
       
  2038 CPluginTrack::~CPluginTrack()
       
  2039 // 
       
  2040 // Destructor.
       
  2041 //
       
  2042 	{
       
  2043 	iNotifierInfo.Reset();
       
  2044 	iNotifierInfo.Close();
       
  2045 	if(iDtr_key.iUid)
       
  2046 		{
       
  2047 		REComSession::DestroyedImplementation(iDtr_key);
       
  2048 		}
       
  2049 	}
       
  2050 //
       
  2051 
       
  2052 //
       
  2053 // class TNotifierSecureInfo
       
  2054 //
       
  2055 
       
  2056 TNotifierSecureInfo::TNotifierSecureInfo(const TUid aNotifierUid, const TSecureId aSecureId)
       
  2057  : iNotifierUid(aNotifierUid), iSecureId(aSecureId)
       
  2058 	{
       
  2059 	}
       
  2060