uifw/AknGlobalUI/NotifierWrapper/src/AknNotifierWrapper.cpp
changeset 0 2f259fa3e83a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AknGlobalUI/NotifierWrapper/src/AknNotifierWrapper.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,702 @@
+/*
+* Copyright (c) 2004-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Notifier server app wrapper implementation.
+*
+*/
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <uiklaf/private/pluginuid.hrh>
+#include <uikon/eiknotifyalert.h>
+#endif
+#include <apgtask.h>
+#include <apgcli.h>
+#include <apacmdln.h>
+#include <coemain.h>
+#include <uikon/eiksrvui.h>
+#include "AknNotifierWrapper.h"
+#include "AknNotifierControllerUtilities.h"
+#include <AknNotifierControllerPlugin.h>
+#include <AknCapServerDefs.h>
+
+const TInt KPreLoadEnabledButNotDoneYet(2);
+
+//-------------------------------------------
+// CAknNotifierMessageObserver
+//-------------------------------------------    
+ 
+CAknNotifierMessageObserver::CAknNotifierMessageObserver(TUid aNotifierUid, 
+    MAknNotifierWrapper* aOwner, 
+    const RMessagePtr2& aClientMessage, 
+    TInt aReplySlot)
+:CActive(CActive::EPriorityStandard), 
+    iNotifierUid(aNotifierUid), 
+    iReplySlot(aReplySlot), 
+    iOwner(aOwner)
+    {
+    iMessage = aClientMessage;
+    CActiveScheduler::Add(this);       
+    }
+ 
+ 
+EXPORT_C CAknNotifierMessageObserver* CAknNotifierMessageObserver::NewServerRequestL(
+    TUid aNotifierUid, 
+    MAknNotifierWrapper* aOwner, 
+    const RMessagePtr2& aClientMessage, 
+    TInt aReplySlot)
+    {
+    CAknNotifierMessageObserver* me = 
+        new (ELeave) CAknNotifierMessageObserver(aNotifierUid,aOwner,aClientMessage,aReplySlot);
+    
+    // a bit awkward I admit...
+    if (!aClientMessage.IsNull())
+        {
+        CleanupStack::PushL(me);
+        me->iReplyBuf = HBufC8::NewL(aClientMessage.GetDesLength(aReplySlot));
+        // we need ptr which keeps its address during async operation
+        me->iReplyDesc = new (ELeave) TPtr8(me->iReplyBuf->Des());
+        CleanupStack::Pop();
+
+        // just in case: if notifier implementation wants to transmit data via replybuf for 
+        // some reason
+        aClientMessage.Read(aReplySlot,*(me->iReplyDesc));  
+        }
+        
+    return me;    
+    }
+ 
+ 
+CAknNotifierMessageObserver::~CAknNotifierMessageObserver()
+    {
+    delete iReplyDesc;
+    delete iReplyBuf;
+    delete iInputBuf;
+    __ASSERT_DEBUG(!IsActive(), User::Invariant() );
+    }
+  
+void CAknNotifierMessageObserver::DoCancel()
+    {
+    if (iOwner)
+        {
+        iOwner->AsyncMessageCompleted( this );
+        }
+
+    if (!iMessage.IsNull())
+        {
+        iMessage.Complete(KErrCancel);
+        }
+
+    User::WaitForRequest(iStatus);
+    delete this;
+    }
+ 
+void CAknNotifierMessageObserver::RunL()
+    {
+    if (iOwner)
+        {// offer message from app-server for wrapper to clone
+        iOwner->AsyncMessageCompleted( this );
+        }
+
+    // if Owner did not complete the message, do default reply 
+    if (!iMessage.IsNull())
+        {
+        TInt err = iMessage.Write(iReplySlot,iReplyBuf->Des());
+        iMessage.Complete(err?err:iStatus.Int());
+        }
+    delete this;
+    }
+
+//-------------------------------------------
+// MAknNotifierWrapper
+//-------------------------------------------  
+
+// Default implementation to avoid SC break.
+EXPORT_C void MAknNotifierWrapper::UpdateNotifierL( 
+    TUid /*aNotifierUid*/,
+    const TDesC8& /*aBuffer*/,
+    TInt /*aReplySlot*/, 
+    const RMessagePtr2& /*aMessage*/ )
+    {
+    User::Leave( KErrNotSupported );
+    }
+ 
+//-------------------------------------------
+// CAknNotifierWrapperLight
+//-------------------------------------------    
+EXPORT_C CAknNotifierWrapperLight::~CAknNotifierWrapperLight()
+    {
+    }
+ 
+EXPORT_C CAknNotifierWrapperLight::CAknNotifierWrapperLight(
+    MAknNotifierWrapper& aSessionOwningNotifier, 
+    TUid aNotifierUid, 
+    TUid aChannel, 
+    TInt aPriority )
+:iOwner(aSessionOwningNotifier)
+    {
+    iInfo.iUid = aNotifierUid;
+    iInfo.iChannel = aChannel;
+    iInfo.iPriority = aPriority;   
+    }
+    
+
+EXPORT_C TPtrC8 CAknNotifierWrapperLight::UpdateL(const TDesC8& aBuffer)
+    {
+    return iOwner.UpdateNotifierL( iInfo.iUid, aBuffer );
+    }
+    
+EXPORT_C void CAknNotifierWrapperLight::UpdateL(const TDesC8& aBuffer, TInt aReplySlot, 
+    const RMessagePtr2& aMessage)
+    {
+    iOwner.UpdateNotifierL( iInfo.iUid, aBuffer, aReplySlot, aMessage );
+    }
+
+EXPORT_C void CAknNotifierWrapperLight::Cancel()
+    {
+    iOwner.CancelNotifier(iInfo.iUid);
+    }
+        
+EXPORT_C void CAknNotifierWrapperLight::StartL(const TDesC8& aBuffer, TInt aReplySlot, 
+    const RMessagePtr2& aMessage)
+    {
+    iOwner.StartNotifierL(iInfo.iUid, aBuffer, aReplySlot, aMessage);
+    }
+    
+EXPORT_C TPtrC8 CAknNotifierWrapperLight::StartL(const TDesC8& aBuffer)
+    {
+    return iOwner.StartNotifierL(iInfo.iUid, aBuffer);
+    }
+        
+EXPORT_C MEikSrvNotifierBase2::TNotifierInfo CAknNotifierWrapperLight::Info() const
+    {
+    return iInfo;    
+    }
+        
+EXPORT_C MEikSrvNotifierBase2::TNotifierInfo CAknNotifierWrapperLight::RegisterL()
+    {
+    return iInfo;    
+    }
+  
+EXPORT_C void CAknNotifierWrapperLight::Release()
+    {
+    Cancel();
+    delete this;
+    }
+
+EXPORT_C TInt CAknNotifierWrapperLight::NotifierCapabilites()
+    {
+    return MEikSrvNotifierBase2::NotifierCapabilites();
+    }
+    
+//-------------------------------------------
+// CAknNotifierWrapper
+//-------------------------------------------    
+
+EXPORT_C CAknNotifierWrapper::CAknNotifierWrapper(TUid aNotifierUid, TUid aChannel, TInt aPriority)
+    :CAknNotifierWrapperLight(*this, aNotifierUid, aChannel, aPriority)
+    {
+    iClient.SetServerAppUid(AppServerUid());
+    }
+    
+CAknNotifierWrapper::CAknNotifierWrapper(TUid aNotifierUid, TUid aChannel, TInt aPriority, 
+    TUid aAppServerUid)
+:CAknNotifierWrapperLight(*this, aNotifierUid, aChannel, aPriority), iAppServerUid(aAppServerUid)
+    {
+    iClient.SetServerAppUid(iAppServerUid);
+    }
+     
+
+EXPORT_C CAknNotifierWrapper::~CAknNotifierWrapper()
+    {
+    CEikServAppUi* appUi = (CEikServAppUi*)CCoeEnv::Static()->AppUi();
+    if (appUi && appUi->NotifierController())
+        {
+        appUi->NotifierController()->RegisterNotifierControllerPlugin(this, ETrue);
+        }
+    
+    delete iReplyBuffer;
+    
+    // Make sure that there are no pending messages
+    __ASSERT_DEBUG(iMessageQueue.Count()==0, User::Invariant());
+    
+    iClient.Close();
+    }
+
+// We use CEikServAppUi idle queue to launch application servers (applications will be started after 
+// eiksrv-construction has been completed )
+EXPORT_C MEikSrvNotifierBase2::TNotifierInfo CAknNotifierWrapper::RegisterL()
+    {
+    CEikServAppUi* appUi = (CEikServAppUi*)CCoeEnv::Static()->AppUi();
+    if (appUi)
+        {
+        if (AppServerUid()!=KAknCapServerUid) // aknCapServer is handled elsewhere
+            {
+            appUi->StartNewServerApplicationL(AppServerUid());
+            }
+        
+        appUi->NotifierController()->RegisterNotifierControllerPlugin(this, EFalse);
+        }
+    return CAknNotifierWrapperLight::RegisterL();    
+    }
+
+ 
+EXPORT_C TPtrC8 CAknNotifierWrapper::UpdateNotifierL( TUid aNotifierUid, const TDesC8& aBuffer)
+    {
+    User::LeaveIfError(iClient.SendSync(EUpdateNotifier, aNotifierUid, aBuffer, 
+        SynchronousReplyBuf(), KNullDesC));
+        
+    return TPtrC8(SynchronousReplyBuf()); 
+    }
+
+EXPORT_C void CAknNotifierWrapper::UpdateNotifierL( TUid aNotifierUid, const TDesC8& aBuffer, 
+    TInt aReplySlot, const RMessagePtr2& aMessage)
+    {    
+    CAknNotifierMessageObserver* entry = 
+        CreateNewQueueEntryL(aNotifierUid, aBuffer, aReplySlot, aMessage);
+        
+    if (entry)
+        {
+        iClient.SendAsync(EUpdateNotifierAndGetResponse, aNotifierUid,*entry->iInputBuf, entry, 
+            KNullDesC);
+        }        
+    }
+    
+void CAknNotifierWrapper::CompleteOutstandingRequests( TUid aNotifierUid, TInt aReason )
+    {
+    for ( TInt i = 0; i < iMessageQueue.Count(); i++ )
+        {
+        if (iMessageQueue[i]->iNotifierUid == aNotifierUid)
+            {
+            // This leaves listener to active state, it will be destroyed when a message in
+            // Notifier server application is completed. 
+            // Effectively this means that plugin can't send any data inside message which is 
+            // being cancelled.
+            if (!iMessageQueue[i]->iMessage.IsNull())
+                {
+                iMessageQueue[i]->iMessage.Complete(aReason);               
+                }
+            }
+        }
+    }
+    
+EXPORT_C void CAknNotifierWrapper::CancelNotifier( TUid aNotifierUid )
+    {
+    iClient.SendSync(ECancelNotifier, aNotifierUid, KNullDesC8, SynchronousReplyBuf(), KNullDesC);
+    CompleteOutstandingRequests( aNotifierUid, KErrCancel);
+    }
+
+
+CAknNotifierMessageObserver* CAknNotifierWrapper::CreateNewQueueEntryL(TUid aNotifierUid, 
+    const TDesC8& aBuffer, TInt aReplySlot, const RMessagePtr2& aMessage)
+    {
+    CAknNotifierMessageObserver* entry = 0;
+    if (!aMessage.IsNull())
+        {
+        entry = CAknNotifierMessageObserver::NewServerRequestL(aNotifierUid, this, aMessage, 
+            aReplySlot);
+            
+        CleanupStack::PushL(entry);
+        entry->iInputBuf = aBuffer.AllocL();
+        CleanupStack::Pop();
+        TInt err = iMessageQueue.Append(entry);  
+        if (err)
+            { // completes client message with err;
+            TRequestStatus* ptr = &entry->iStatus;
+            User::RequestComplete(ptr, err);
+            entry = 0;
+            }
+        }
+    return entry;
+    }
+
+EXPORT_C void CAknNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer, 
+    TInt aReplySlot, const RMessagePtr2& aMessage)
+    {    
+    CAknNotifierMessageObserver* entry = 
+        CreateNewQueueEntryL(aNotifierUid, aBuffer, aReplySlot, aMessage);
+        
+    if (entry)
+        {
+        iClient.SendAsync(
+            EStartNotifierAndGetResponse, 
+            aNotifierUid, 
+            *entry->iInputBuf, 
+            entry, 
+            KNullDesC);        
+        }        
+    }
+
+EXPORT_C TPtrC8 CAknNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer)
+    {
+    User::LeaveIfError(iClient.SendSync(EStartNotifier, aNotifierUid, aBuffer, 
+        SynchronousReplyBuf(), KNullDesC));      
+        
+    return TPtrC8(SynchronousReplyBuf());     
+    }
+
+// Just remove completed entry from queue, default completion (ie. just copying message from 
+// app server) is currently enough for us. 
+EXPORT_C void CAknNotifierWrapper::AsyncMessageCompleted( CAknNotifierMessageObserver* aEntry )
+    {
+    TInt status = aEntry->iStatus.Int();
+
+    TInt index = iMessageQueue.Find(aEntry);
+    if (index != KErrNotFound)
+        {
+        iMessageQueue.Remove(index);    
+        }     
+
+    if ( status == KErrServerTerminated && AppServerUid() != KCommonNotifierAppSrvUid)
+        { // Just try to restart (connect on next request), not interested if success or fail
+          //
+          // We could clone the original message here and resend it to server
+          // if information was really vital for system
+        Client().Close();    
+        Client().SetHandle(0);
+        
+        TRAP_IGNORE(((CEikServAppUi*)CCoeEnv::Static()->AppUi())->StartNewServerApplicationL(
+            AppServerUid()));    
+        }
+    }
+
+EXPORT_C CAknNotifierWrapper* CAknNotifierWrapper::NewL( 
+    TUid aNotifierUid, 
+    TUid aChannel, 
+    TInt aPriority, 
+    TUid aAppServerUid, 
+    TUint aReplyBufSize)
+    {
+    CAknNotifierWrapper* me = 
+        new (ELeave) CAknNotifierWrapper(aNotifierUid, aChannel, aPriority, aAppServerUid);
+        
+    CleanupStack::PushL(me);
+    me->ConstructL(aReplyBufSize);
+    CleanupStack::Pop();
+    return me;
+    }
+    
+EXPORT_C void CAknNotifierWrapper::DoNotifierControllerCommand(TInt aCommand)
+    {
+    iClient.SendAsync(aCommand);
+    }
+                                    
+void CAknNotifierWrapper::ConstructL(TUint aReplyBufSize)
+    {
+    iReplyBuffer = HBufC8::NewL(aReplyBufSize);
+    }
+
+RAknNotifierAppServClient::RAknNotifierAppServClient()
+    :iAppServerUid(KNullUid), iOwnerUsingMonitor(0)
+    {       
+    }   
+ 
+void RAknNotifierAppServClient::SetServerAppUid(TUid aAppServerUid)
+    {
+    iAppServerUid = aAppServerUid;   
+    }
+ 
+TInt RAknNotifierAppServClient::StartServer()
+    {
+    TRAPD(ret, StartServerL())        
+    return ret;
+    }
+ 
+void RAknNotifierAppServClient::StartServerL()
+    {
+    if (Handle() != 0)
+        {
+        return;
+        }
+            
+    if (iAppServerUid == KNullUid)
+        {
+        User::Leave(KErrGeneral);
+        }
+
+    _LIT(KServerNameFormat, "%08x_%08x_AppServer");
+    TFullName serverName;
+    serverName.Format(KServerNameFormat, KUikonUidPluginInterfaceNotifiers, iAppServerUid);
+    TFindServer find(serverName);
+    TFullName fullName;
+    if (find.Next(fullName) == KErrNone)
+        {
+        ConnectExistingByNameL(serverName); 
+        if (iOwnerUsingMonitor)
+            {
+            iOwnerUsingMonitor->AppServerConnectedL();
+            }
+        return;
+        }
+
+    User::Leave(KErrNotReady);
+    }
+    
+TUid RAknNotifierAppServClient::ServiceUid() const
+    {
+    return KAknNotifierServiceUid;
+    }
+    
+TInt RAknNotifierAppServClient::SendSync(TNotifierMessage aFunction, TUid aNotifierUid, 
+    const TDesC8& aBuffer, TPtr8 aReply, const TDesC& aLibraryName)
+    {
+    // just an optimisation
+    if (aFunction == ECancelNotifier && !Handle())
+        {
+        return KErrNone;
+        }
+    
+    TInt err = StartServer();
+    return err ? err : SendReceive(aFunction, TIpcArgs((TInt)aNotifierUid.iUid, &aBuffer, &aReply, 
+        &aLibraryName));
+    }
+ 
+void RAknNotifierAppServClient::SendAsync(TNotifierMessage aFunction, TUid aNotifierUid, 
+    const TDesC8& aBuffer, CAknNotifierMessageObserver* aQueueEntry, const TDesC& aLibraryName)
+    {
+    TInt err = StartServer();
+
+    aQueueEntry->Start();  
+    if (err)
+        {
+        TRequestStatus* sptr= &aQueueEntry->iStatus;
+        User::RequestComplete(sptr, err);
+        return;
+        }
+    // we implicitely trust that aLibraryName will exist when data is extracted at other end...    
+    SendReceive(
+        aFunction, 
+        TIpcArgs((TInt)aNotifierUid.iUid, &aBuffer, aQueueEntry->iReplyDesc, &aLibraryName), 
+        aQueueEntry->iStatus);
+    }
+
+TInt RAknNotifierAppServClient::SendAsync(TInt aNotifierControllerCommand)
+    {
+    if (Handle()!=0)
+        {
+        return Send(KDoNotifierControllerCommand, TIpcArgs(aNotifierControllerCommand));
+        }
+        
+    // omit error as there is no need to forward commands to server apps which are not running yet.
+    return KErrNone; 
+    }
+
+EXPORT_C CAknCommonNotifierWrapper* CAknCommonNotifierWrapper::NewL( 
+    TUid aNotifierUid, 
+    TUid aChannel, 
+    TInt aPriority, 
+    const TDesC& aLibraryName, 
+    TUint aReplyBufSize,
+    TBool aPreLoad)
+    {
+    CAknCommonNotifierWrapper* me = 
+        new (ELeave) CAknCommonNotifierWrapper(aNotifierUid, aChannel, aPriority, aPreLoad);
+        
+    CleanupStack::PushL(me);
+    me->ConstructL(aLibraryName, aReplyBufSize);
+    CleanupStack::Pop();   
+    return me;
+    }
+
+void CAknCommonNotifierWrapper::ConstructL(const TDesC& aLibraryName, TUint aReplyBufSize)
+    {
+    SetSynchReplybuf(HBufC8::NewL(aReplyBufSize));
+    iLibraryName = aLibraryName.AllocL();
+    Client().SetOwnerUsingMonitor(this);
+    }
+
+CAknCommonNotifierWrapper::CAknCommonNotifierWrapper( 
+    TUid aNotifierUid, 
+    TUid aChannel, 
+    TInt aPriority,
+    TBool aPreLoad)
+:CAknNotifierWrapper(aNotifierUid, aChannel, aPriority), iPreLoad(aPreLoad)
+    {
+    Client().SetServerAppUid(AppServerUid());
+    if (aPreLoad)
+        {
+        iPreLoad = KPreLoadEnabledButNotDoneYet;
+        }
+    }
+
+EXPORT_C void CAknCommonNotifierWrapper::SetCustomSecurityHandler(
+    MAknNotifierCustomSecurityCheck* aHandler)
+    {
+    iCustomSecurityCheck = aHandler;
+    }
+
+CAknCommonNotifierWrapper::~CAknCommonNotifierWrapper()
+    {
+    delete iMonitor;
+    delete iIdle;
+    if (iCustomSecurityCheck)
+        {
+        iCustomSecurityCheck->Release();
+        }
+    delete iLibraryName;
+    iPendingArray.Close();
+    }
+
+void CAknCommonNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer, 
+    TInt aReplySlot, const RMessagePtr2& aMessage)
+    {
+    if (iPreLoad == KPreLoadEnabledButNotDoneYet) // only preload libs to support message queue
+        {
+        iPendingArray.AppendL(TPendingMsg(aNotifierUid, aMessage));
+        return;
+        }
+
+    if (iCustomSecurityCheck)
+        {
+        iCustomSecurityCheck->CustomSecurityCheckL(aMessage);
+        }
+    
+    CAknNotifierMessageObserver* entry = 
+        CreateNewQueueEntryL(aNotifierUid, aBuffer, aReplySlot, aMessage);
+        
+    if (entry)
+        {
+        Client().SendAsync(
+            EStartNotifierAndGetResponse, 
+            aNotifierUid,
+            *entry->iInputBuf,
+            entry, 
+            *iLibraryName);        
+        }        
+    }
+
+TPtrC8 CAknCommonNotifierWrapper::StartNotifierL( TUid aNotifierUid, const TDesC8& aBuffer)          
+    {
+    if (iPreLoad == KPreLoadEnabledButNotDoneYet) 
+        {              
+        // In case of synchronous commands (start / update) we cannot delay sending messages,
+        // only way to recover is to return error. Update cannot occur before one successfull 
+        // start so it does need changes.
+        User::Leave(KErrNotReady); 
+        }
+
+    User::LeaveIfError(Client().SendSync(EStartNotifier, aNotifierUid, aBuffer, 
+        SynchronousReplyBuf(), *iLibraryName));      
+    
+    return TPtrC8(SynchronousReplyBuf());     
+    }
+
+TBool CallBackLoad(TAny* aThis)
+    {
+    return ((CAknCommonNotifierWrapper*)aThis)->PreLoadLibrary();
+    }
+ 
+EXPORT_C void CAknCommonNotifierWrapper::PreLoadLibraryL()
+    {
+    iPreLoad = ETrue; // restore original, real boolean value once callback from server arrives
+    if (!iIdle)
+        {
+        iIdle = CIdle::NewL(CActive::EPriorityIdle);
+        iIdle->Start(TCallBack(CallBackLoad, this));
+        }
+    }
+
+// On succes this method will cause unbalanced reference count in app server -> library will not be 
+// unloaded unless server terminates.
+TBool CAknCommonNotifierWrapper::PreLoadLibrary()
+    {
+    TInt err = Client().SendSync(
+        (TNotifierMessage)EAknNfySrvLoadLibrary, 
+        KNullUid, 
+        KNullDesC8, 
+        SynchronousReplyBuf(), 
+        *iLibraryName);
+        
+    if (err == KErrNotReady)
+        {
+        return ETrue;
+        }
+    else
+        {
+        delete iIdle;
+        iIdle = 0;  
+        return EFalse;  
+        }
+    }
+    
+MEikSrvNotifierBase2::TNotifierInfo CAknCommonNotifierWrapper::RegisterL()
+    {
+    if (iPreLoad)
+        {
+        CEikServAppUi* appUi = (CEikServAppUi*)CCoeEnv::Static()->AppUi();
+        if (appUi)
+            {
+            appUi->NotifierController()->RegisterPreloadPluginL(this);
+            }
+        }
+    return CAknNotifierWrapper::RegisterL();
+    }
+
+
+void CAknCommonNotifierWrapper::HandleServerAppExit(TInt)
+    {
+    delete iMonitor;
+    iMonitor = 0;
+    Client().Close();    
+    Client().SetHandle(0);
+    if (iPreLoad)
+        {
+        iPreLoad = KPreLoadEnabledButNotDoneYet;
+        }
+    }
+
+void CAknCommonNotifierWrapper::CancelNotifier( TUid aNotifierUid )
+    {
+    // if there are pending requests, there cannot be actual connection to server yet
+    if (iPendingArray.Count())
+        {
+        for (TInt i = iPendingArray.Count()-1; i >= 0; i--)
+            {
+            if (iPendingArray[i].iUid == aNotifierUid.iUid)
+                {
+                iPendingArray.Remove(i);
+                }
+            }
+        }
+    else
+        {
+        CAknNotifierWrapper::CancelNotifier( aNotifierUid );
+        }        
+    }
+
+void TryProcessPendingEntryL(CAknCommonNotifierWrapper::TPendingMsg& aPendingEntry, 
+    CAknCommonNotifierWrapper* aThis)
+    {
+    HBufC8* buf = HBufC8::NewLC(aPendingEntry.iMessage.GetDesLengthL(1));
+    TPtr8 ptr = buf->Des();
+    aPendingEntry.iMessage.ReadL(1, ptr );
+    aThis->StartNotifierL(TUid::Uid(aPendingEntry.iUid), *buf, 2, aPendingEntry.iMessage );
+    CleanupStack::PopAndDestroy();            
+    }
+
+void CAknCommonNotifierWrapper::AppServerConnectedL()
+    {
+    if (!iMonitor)
+        {
+        iMonitor = CApaServerAppExitMonitor::NewL(Client(), *this, CActive::EPriorityStandard);   
+        }
+        
+    for (TInt i = 0; i < iPendingArray.Count(); i++)
+        { // common app servers have no problem with asynch message slots
+        // anyway, we don't allow pending messages to abort StartServerL so trap needed 
+        TRAP_IGNORE(TryProcessPendingEntryL(iPendingArray[i], this));
+        }
+        
+    iPendingArray.Reset();    
+    }
+
+// End of file