uifw/AknGlobalUI/OldStyleNotif/Src/AknSoftNotificationPlugin.cpp
changeset 0 2f259fa3e83a
child 29 a8834a2e9a96
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uifw/AknGlobalUI/OldStyleNotif/Src/AknSoftNotificationPlugin.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,2653 @@
+/*
+* Copyright (c) 2002-2008 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: 
+*
+*/
+
+// INCLUDE FILES
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <vwsdefpartner.h>
+#endif
+#include <avkon.rsg>
+#include <eikbtgpc.h>
+#include <eikenv.h>
+#include <avkon.hrh>
+#include <aknnotpi.rsg>
+#include <aknnotedialog.h>
+#include <AknPanic.h>
+#include <aknappui.h>
+#include <StringLoader.h>
+#include "AknSoftNotificationPlugin.h"
+#include <AknNotifyStd.h>
+#include <msvstd.hrh>   // for Messaging centre constants
+#include "AknNotifyPlugin.hrh"
+#include <centralrepository.h>
+#include <AvkonInternalCRKeys.h>
+#include <viewcli.h>
+#include <s32file.h>
+#include <s32mem.h>
+#include <e32cmn.h>
+#include "AknNotifierController.h"
+#include <eikfrlb.h>
+#include <eiklbi.h>
+#include <bautils.h>
+#include <AknNotifySignature.h>
+#include <apgcli.h>
+#include <aknsoundsystem.h>
+#include "AknCapServerEntry.h"
+#include "AknDynamicNotificationData.h"
+#include "aknsoftnoteconsts.h"
+#include "akndynamicsoftnoteeventmanager.h"
+
+// Messaging UIDs
+// Traditional messaging UIDs.
+#define KMessagingCentreMainViewUid TVwsViewId(TUid::Uid(0x100058C5),TUid::Uid(0x01))
+#define KMessagingCentreInboxView TVwsViewId(TUid::Uid(0x100058C5),TUid::Uid(0x02))
+
+// Conversational messaging UIDs.
+#define KConversationApplicationViewUid TVwsViewId(TUid::Uid(0x2002A540),TUid::Uid(0x01))
+const TInt KConversationListViewUid  = 0x01 ;
+
+// Messaging central repository. Used to read default view settings.
+const TUid KCRUidMessageSettings = {0x101F87EB};
+const TUint32 KMessagingAppDefaultViewCRKey = 0x0000001C;  
+
+// Cbs topic list view Uid. This view is shown when there are several cbs messages
+#define KCbsApplicationUidTopicListView TVwsViewId(TUid::Uid(0x101F4CD3),TUid::Uid(0x02))
+// Cbs message view Uid. This view is shown when there is only one new cbs message
+#define KCbsApplicationUidMessageView TVwsViewId(TUid::Uid(0x101F4CD3),TUid::Uid(0x04))
+
+// Voice messages are handleb by speed dial application.
+#define KSpeeddialVmbxDialUidView TVwsViewId( TUid::Uid( 0x1000590A ),TUid::Uid( 0x02 ) )
+
+// Logs application UID
+#define KUidLogs TUid(TUid::Uid(0x101F4CD5))
+_LIT8(KLogsActivationMsg ,"missed");
+
+_LIT8( KExternalLaunch, "outside" );
+
+#define KUidGS TUid(TUid::Uid(0x100058EC))
+#define KSettListNetViewId TUid(TUid::Uid(0x102824A8)) // Implementation UID for GSNetworkPlugin in GS.
+#define KSelectNetworkAppUidView TVwsViewId(KUidGS, KSettListNetViewId)
+
+#define KChatSpecificView TVwsViewId(TUid::Uid(0x101F4673),TUid::Uid(7))
+const TInt KGSCustomActivateNetView = 9000;
+
+const TInt KSoftNoteGranularity = 4;
+
+const TInt KNetworkInfoPriority     = 2500;
+const TInt KSelectNetworkPriority   = 2400;
+const TInt KUSSDPriority            = 2300;
+const TInt KVoiceMailPriority       = 2200;
+const TInt KVoiceMailOnLinePriority = 2100;
+const TInt KCBSPriority             = 2000;
+const TInt KGroupedNotification     = 1500;
+const TInt KMissedCallsPriority     = 1300;
+const TInt KNewMessagesPriority     = 1200;
+const TInt KChatMessagePriority     = 1150;
+const TInt KNewEmailPriority        = 1100;
+
+/// Lowest value for unique id. Id range: KMinimumUniqueId...KMaxTInt.
+const TInt KMinimumUniqueId         = 0x00ff;
+
+#define KDeliveryTextMaxLength 64
+
+_LIT( KAknSNFilename, "c:\\private\\10207218\\softnote.dat" );
+/// File where to store unique identification counter.
+_LIT( KAknDynamicIdFilename, "c:\\private\\10207218\\dynamic.dat" );
+
+NONSHARABLE_CLASS(CCustomNotifParams) : public CBase
+    {
+public:
+    ~CCustomNotifParams()
+        {
+        delete iParamData;
+        delete iDynamicData;
+        if ( iCoeResourceHandle )
+            {
+            CCoeEnv::Static()->DeleteResourceFile(iCoeResourceHandle);
+            }
+        };
+        
+    /**
+     * Internalize content of CCustomNotifParams from stream.
+     * @param aStream Source stream.
+     */
+    void InternalizeL( RReadStream& aStream );
+    /**
+     * Externalize content of CCustomNotifParams to stream.
+     * @param aStream Destination stream.
+     */
+    void ExternalizeL( RWriteStream& aStream ) const;
+    /**
+     * Return text for custom notification.
+     * 
+     * @param aCount Count of items to be displayed in notification.
+     * @param aGroupText ETrue  : Text is shown in grouped list.
+     *                   EFalse : Text is shown in single dialog.
+     * @return Custom text.
+     */
+    const TDesC& CustomText( TInt aCount, TBool aGroupText ) const;
+    /**
+     * @return View activation message or KNullDesC8 if not defined.
+     */
+    const TDesC8& ViewActivationMessage() const;
+    /**
+     * @return Flag whether user events are wanted by the event manager.
+     */
+    TBool EnableObserver() const;
+    
+    TInt iId;
+    TInt iNoteId;
+    TBool iSupportsGroupedform;
+    TBool iHasViewInfo;
+    TInt iCount;
+    /// Data for custom soft notification.
+    CAknPrivateSoftNoteParameters* iParamData;
+    /// Data for dynamic soft notification.
+    CAknDynamicNotificationData* iDynamicData;
+    /// Parameter type to distinguish dynamic note from custom note. 
+    /// Use KAknSoftNotificationCustom or KAknSoftNotificationDynamic. 
+    TInt iParamType;
+    CCustomNotifParams* iNext;
+    TInt iCoeResourceHandle;
+    };
+
+TBool CCustomNotifParams::EnableObserver() const
+    {
+    if (iDynamicData)
+        {
+        return iDynamicData->EnableObserver();
+        }
+    else
+        {
+        return EFalse;
+        }        
+    }
+
+// ---------------------------------------------------------
+// CCustomNotifParams::InternalizeL
+// ---------------------------------------------------------
+//
+void CCustomNotifParams::InternalizeL( RReadStream& aStream )
+    {
+    iParamType = aStream.ReadInt16L();
+    switch( iParamType )
+        {
+        case KAknSoftNotificationCustom:
+            {
+            CAknPrivateSoftNoteParameters* param = 
+                CAknPrivateSoftNoteParameters::NewL(); 
+            aStream >> *param;
+            delete iParamData;
+            iParamData = param;
+            break;
+            }
+        case KAknSoftNotificationDynamic:
+            {
+            CAknDynamicNotificationData* data = 
+                CAknDynamicNotificationData::NewLC( aStream );
+            
+            // Duplicate values to ease the changes required
+            //
+            CAknPrivateSoftNoteParameters* param = 
+                CAknPrivateSoftNoteParameters::NewL();
+            CleanupStack::PushL( param );
+            
+            // copy some values
+            param->iCustomMessageId = data->CustomMsgUid();
+            param->iPluralViewId = data->PluralViewId();
+            param->iViewId = data->ViewId();
+            param->iPriority = data->Priority();
+            param->iTone = data->Tone();
+            param->iNoteResourceId = data->Id();
+            param->iAcceptSoftKey = EAknSoftkeyShow;
+            
+            // secondary display data
+            if( aStream.ReadInt8L() ) 
+                {
+                // item has secondary display data
+                CAknSDData* sddata = new (ELeave) CAknSDData();
+                CleanupStack::PushL( sddata );
+                aStream >> *sddata;
+                delete param->iSecondaryDisplayData;
+                param->iSecondaryDisplayData = sddata;
+                CleanupStack::Pop( sddata );
+                }
+
+            // Assign values when we can't leave anymore. 
+            CleanupStack::Pop( 2, data ); // param
+            delete iParamData;
+            iParamData = param;
+            delete iDynamicData;
+            iDynamicData = data;
+
+            break;
+            }
+        default:
+            {
+            User::Leave( KErrCorrupt );
+            break;
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CCustomNotifParams::ExternalizeL
+// ---------------------------------------------------------
+//
+void CCustomNotifParams::ExternalizeL( RWriteStream& aStream ) const
+    {
+    if( iParamType <= KAknSoftNotificationCustom && iParamData ) // default
+        {
+        aStream.WriteInt16L( KAknSoftNotificationCustom );
+        aStream << *iParamData;
+        }
+    else if( iParamType == KAknSoftNotificationDynamic && iDynamicData )
+        {
+        aStream.WriteInt16L( KAknSoftNotificationDynamic );
+        aStream << *iDynamicData;
+        
+        // secondary display data
+        if( iParamData && iParamData->iSecondaryDisplayData )
+            {
+            aStream.WriteInt8L( ETrue );
+            aStream << iParamData->iSecondaryDisplayData;
+            }
+        else
+            {
+            aStream.WriteInt8L( EFalse );
+            }
+        }
+    else
+        {
+        User::Leave( KErrCorrupt );
+        }
+    }
+
+// ---------------------------------------------------------
+// CCustomNotifParams::CustomText
+// ---------------------------------------------------------
+//
+const TDesC& CCustomNotifParams::CustomText( 
+    TInt count, TBool aGroupText ) const
+    {
+    if( iParamType == KAknSoftNotificationDynamic && iDynamicData )
+        {
+        if( count > 1 )
+            {
+            // use plural text
+            return aGroupText ? iDynamicData->PluralLabelGroup() :
+                iDynamicData->PluralLabel();
+            }
+        else
+            {
+            // use singular text
+            return aGroupText ? iDynamicData->SingularLabelGroup() : 
+                iDynamicData->SingularLabel();
+            }
+        }
+    return KNullDesC();
+    }
+
+// ---------------------------------------------------------
+// CCustomNotifParams::ViewActivationMessage
+// ---------------------------------------------------------
+//
+const TDesC8& CCustomNotifParams::ViewActivationMessage() const
+    {
+    if( iParamType == KAknSoftNotificationDynamic && iDynamicData )
+        {
+        return iDynamicData->CustomMsg();
+        }
+    else if( iParamData && iParamData->iViewActivationMsg )
+        {
+        return *iParamData->iViewActivationMsg;
+        }
+    return KNullDesC8();
+    }
+
+void AknSoftNoteSDObserver::SetSoftNotificationSubject( CAknSoftNotificationSubject* aSubject )
+    {
+    iSubject = aSubject;
+    }
+    
+TAknDialogMediatorObserverCommand AknSoftNoteSDObserver::MediatorCommandL( TUid, TUid, TInt, 
+    const TDesC8& aData)
+    {
+    RDesReadStream* readStreamSDData = new(ELeave) RDesReadStream();
+    CleanupStack::PushL( readStreamSDData );
+    readStreamSDData->Open( aData ); // aData = data received from Mediator    
+    TPckgBuf<SAknSoftNotificationFeedbackData> paramsBuf;
+    *readStreamSDData >> paramsBuf;
+    
+    if ( paramsBuf().iType == EShowGroupedNotification ) 
+        {
+        CAknGroupedNotifierNote* groupedNote = iSubject->iGroupedNote;
+        iSubject->GroupedNoteCompletedL(EAknSoftkeyExit, EMaxItem); // saves as well
+        // iSubject->iGroupedNote equals to NULL now
+        delete groupedNote;
+        }
+        
+    else if (paramsBuf().iType != ECustomSoftNotification )
+        {
+        TAknSoftNotificationType type = paramsBuf().iType;
+        iSubject->iSoftNotificationAmounts[ type ] = 0;
+        iSubject->RemoveByType( type );
+
+        if ( type == EMissedCallsNotification ||
+             type == ENewMessagesNotification ||
+             type == ENewMailNotification ||
+             type == EChatMessageNotification)
+            {
+            iSubject->RemoveByType(EShowGroupedNotification);
+            iSubject->ScheduleGroupedNotifierL();
+            }
+        else
+            {
+            iSubject->iGlobalNoteController->TryDisplayNextNoteL();
+            }
+        
+        iSubject->iNotificationsSaved = EFalse;
+        iSubject->SaveSoftNotificationsL();
+        }
+        
+    else
+        {
+        CCustomNotifParams* params = iSubject->iCustomNoteParamsStack;
+        for (;params;params = params->iNext)
+            {
+            if (params->iParamData->iSecondaryDisplayData)
+                {
+                if ( params->iParamData->iSecondaryDisplayData->iCategory.iUid == paramsBuf().iCategory 
+                     && params->iParamData->iSecondaryDisplayData->iDialogIdx == paramsBuf().iDialogID )
+                    {
+                    TInt noteId = params->iNoteId;
+                    if ( noteId == 0 )
+                        {
+                        iSubject->RemoveCustomNoteForId( params->iId );
+                        iSubject->ScheduleGroupedNotifierL();
+                        }
+                    else
+                        {
+                        iSubject->RemoveCustomNoteForId( noteId, ETrue );
+                        if ( noteId != KErrNotFound ) // was added to global notes queue
+                            {
+                            iSubject->iGlobalNoteController->TryDisplayNextNoteL();
+                            }
+                        }
+
+                    iSubject->iNotificationsSaved = EFalse;
+                    iSubject->SaveSoftNotificationsL();
+                    break;
+                    }
+                }
+            }
+        }
+        
+    readStreamSDData->Close(); 
+    CleanupStack::PopAndDestroy(); // read stream
+    return EDoNothingWithThisCommand;
+    }
+    
+    
+// ================= MEMBER FUNCTIONS =======================
+
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+CAknSoftNotificationSubject::CAknSoftNotificationSubject(
+    MAknKeyLockController* aKeyLockController,
+    CAknGlobalNoteSubject* aGlobalNoteController)
+:iKeyLockController(aKeyLockController), 
+    iGlobalNoteController(aGlobalNoteController), 
+    iNotificationsSaved(ETrue), // We'll have to assume there are saved notifications on startup
+    iUniqueIdCounter(KMinimumUniqueId)
+    {
+    iMessagingRepository = NULL;
+    iDynamicSoftNoteManager = CAknDynamicSoftNoteEventManager::UniqueInstance();
+    __ASSERT_ALWAYS(iDynamicSoftNoteManager != NULL, User::Invariant());
+    }
+
+// EPOC default constructor can leave.
+void CAknSoftNotificationSubject::ConstructL()
+    {
+    iKeyLockController->AddObserverL(this);
+
+    iSoftNoteEntryList = new(ELeave)CArrayFixFlat<TSoftNoteEntry>(KSoftNoteGranularity);
+    iGlobalNoteController->SetSoftNoteObserver(this);
+    // Set initial state to 'non-idle'
+    iGlobalNoteController->SetMaxDisplayPriorityL(KMinimumSoftNotePriority);
+
+    iGlobalNoteController->SetMessageNotifierObserver(this);
+
+    // Messaging settings repository
+    TRAP_IGNORE( iMessagingRepository = CRepository::NewL(KCRUidMessageSettings) );
+    
+#ifdef __COVER_DISPLAY  
+    // Just to give something, not used.
+    iCoverClient = CAknMediatorFacade::NewL((CEikDialog*)CEikonEnv::Static()->Alert()->AsEikDialog()); 
+    
+    iCoverClient->SetObserver(&iObsStub);
+    iObsStub.SetSoftNotificationSubject( this );
+    iCoverClient->CatUid() = KAknSecondaryDisplayCategory;
+    iCoverClient->DialogIndex() = EAknSoftNotificationSDInfo;
+#endif
+    
+    // If the loading fails, then we'll start using unique id's 
+    // from KMinimumUniqueId.
+    TRAPD( err, LoadUniqueIdL() );
+    if( err )
+        {
+#ifdef _DEBUG
+        _LIT( KDmsg, "AknSoftNotificationPlugin, Unique Id restore err: %d" );
+        RDebug::Print( KDmsg, err );
+#endif //_DEBUG
+        }
+    }
+
+CAknSoftNotificationSubject::~CAknSoftNotificationSubject()
+    {
+    delete iSoftNoteEntryList;
+
+    while(iCustomNoteParamsStack)
+        {
+        CCustomNotifParams* params = iCustomNoteParamsStack->iNext;
+        delete iCustomNoteParamsStack;
+        iCustomNoteParamsStack = params;
+        }
+
+    delete iIdle;
+    delete iCoverClient;
+    
+    if(iKeyLockController)
+        {
+        iKeyLockController->RemoveObserver(this);
+        }    
+
+    if ( iMessagingRepository )
+        {
+        delete iMessagingRepository;
+        iMessagingRepository = NULL;
+        }
+    }
+
+// Two-phased constructor.
+CAknSoftNotificationSubject* CAknSoftNotificationSubject::NewL(
+    MAknKeyLockController* aKeyLockController,
+    CAknGlobalNoteSubject* aGlobalNoteController )
+    {
+    CAknSoftNotificationSubject* self = new (ELeave) CAknSoftNotificationSubject(
+        aKeyLockController, 
+        aGlobalNoteController);
+        
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self);
+    return self;
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::KeyLockStatusChange
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::KeyLockStatusChange(TKeyLockStatus aStatus)
+    {
+    if ( aStatus == EKeyLockEnabled )
+        {
+        iKeysLocked = ETrue;
+        }
+    else if ( aStatus == EKeyLockDisabled )
+        {
+        iKeysLocked = EFalse;
+        }
+        
+    if ( iGroupedNote && iGroupedNote->ListBox())
+        {
+        if ( aStatus == EKeyLockEnabled )
+            {
+            iGroupedNote->ListBox()->View()->ItemDrawer()->SetFlags(
+                CListItemDrawer::EDisableHighlight);
+                
+            iGroupedNote->DrawDeferred();
+            }
+        else if ( aStatus == EKeyLockDisabled )
+            {
+            iGroupedNote->ListBox()->View()->ItemDrawer()->ClearFlags(
+                CListItemDrawer::EDisableHighlight);
+                
+            iGroupedNote->DrawDeferred();
+            }
+        }
+    }    
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::Release()
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::Release()
+    {
+    delete this;
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::RegisterL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+CAknSoftNotificationSubject::TNotifierInfo CAknSoftNotificationSubject::RegisterL()
+    {
+    iInfo.iUid=KAknSoftNotificationUid;
+    iInfo.iChannel=EAknNotifierChannelNote;
+    iInfo.iPriority=ENotifierPriorityHigh;
+    return iInfo;
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::Info()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+CAknSoftNotificationSubject::TNotifierInfo CAknSoftNotificationSubject::Info() const
+    {
+    return iInfo;
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::StartL(const TDesC8& aBuffer)
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TPtrC8 CAknSoftNotificationSubject::StartL(const TDesC8& aBuffer)
+    {
+    TInt id = KErrNotFound;
+    HandleNotifierMessageL( aBuffer, id );
+
+    if( id > 0 )
+        {
+        // Custom note id generated, report it back to client
+        WriteResponse( iResponseMsg, id );
+        return iResponseMsg;
+        }
+    return KNullDesC8();
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::StartL()
+// This is the asynchronous version that should not be used
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::StartL(const TDesC8& aBuffer, TInt aReplySlot, 
+    const RMessagePtr2& aMessage)
+    {
+    TInt id = KErrNotFound;
+    HandleNotifierMessageL( aBuffer, id );    
+    if( id > 0 )
+        {
+        // Custom note id generated, report it back to client
+        WriteResponse( iResponseMsg, id );
+        aMessage.WriteL( aReplySlot, iResponseMsg );
+        }
+    aMessage.Complete( KErrNone );
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::Cancel()
+// Not much happening here. If a certain type of of soft
+// notification should be canceled, please use the wrapper's
+// method
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::Cancel()
+    {
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::UpdateL(const TDesC8& aBuffer)
+//
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TPtrC8 CAknSoftNotificationSubject::UpdateL(const TDesC8& aBuffer)
+    {
+    return StartL( aBuffer );
+    }
+
+// ---------------------------------------------------------
+// HandleMessageL(const TDesC8& aBuffer)
+// Required because of framework
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void HandleMessageL( const TDesC8& /*aBuffer*/ )
+    {
+    }
+
+void CAknSoftNotificationSubject::HandleNotifierMessageL( 
+    const TDesC8& aBuffer, TInt& aNoteId )
+    {
+    RDesReadStream readStream( aBuffer );
+
+    if ( aBuffer.Length() < 4 // TInt takes four char
+        || readStream.ReadInt32L() != KAKNNOTIFIERSIGNATURE )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TAknSoftNotificationType type = STATIC_CAST(TAknSoftNotificationType,readStream.ReadUint8L());
+    TInt16 count = readStream.ReadInt16L();
+    
+    //set current idle status to appui
+    if ( type == ESetIdleState )
+        {
+        ((CAknCapAppServerAppUi*)(CEikonEnv::Static())->EikAppUi())
+            ->SetIdleActive( count ? ETrue : EFalse );
+        }
+        
+    switch ( type )
+        {
+        case ENetworkInformationNotification:
+        case ESelectNetworkNotification:
+        case EUnstructuredSSDataNotification:
+        case EVoiceMailNotification:
+        case ESeparateVoiceMailOnLine1Notification:
+        case ESeparateVoiceMailOnLine2Notification:
+        case ECellBroadcastNotification:
+        case EDeliveryReportNotification:
+        case EClass0SmsNotification:
+        case EMissedCallsNotification:
+        case ENewMessagesNotification:
+        case ENewMailNotification:
+        case EShowActiveNotifications:
+        case EShowGroupedNotification:
+        case ECustomSoftNotification:
+        case EChatMessageNotification:
+        case ESetIdleState:
+            break;
+        case ENoSoftNotification:
+        case EMaxSoftNotification:
+        default:
+            // Simply return with no error code.
+            return;
+        }
+
+    // Stores value for future use.
+    TBool notificationsSavedTmp = iNotificationsSaved;
+
+    TInt err = KErrNone;
+    if ( !iIdleStateActive )
+        {
+        TRAP( err, LoadAndQueueSoftNotesL() ); // leaves if file does not exist.
+        }
+    else if ( type != ESetIdleState && type != EShowActiveNotifications ) 
+        {
+        // To make sure that changes will be saved even we didn't load them.
+        iNotificationsSaved = EFalse; 
+        }
+
+    if ( err && err != KErrNotFound && err != KErrNoMemory ) 
+        {
+        // There was an error, check allowed error codes, others mean corruption of data.
+        CEikonEnv::Static()->FsSession().Delete( KAknSNFilename );
+        iNotificationsSaved = EFalse;
+        }
+
+#ifdef _DEBUG
+    _LIT(KDmsg, "AknSoftNotificationPlugin, HandleNotifierMessageL:type %d,count %d, Load returned %d");
+    RDebug::Print(KDmsg,type,count,err);
+#endif
+
+    if ( type == EShowActiveNotifications )
+        {
+        return;
+        }
+
+    if ( type == ESetIdleState )
+        {
+        if ( count )
+            {
+            iGlobalNoteController->SetMaxDisplayPriorityL( KMaxTInt );
+            iIdleStateActive = ETrue;
+            }
+        else
+            {
+            iGlobalNoteController->SetMaxDisplayPriorityL( KMinimumSoftNotePriority );
+            iIdleStateActive = EFalse;
+            }
+        return;
+        }
+
+    TChar isCancel = readStream.ReadUint8L();
+    TChar addCount = readStream.ReadUint8L();
+
+    // using hbuf allows us to use dynamic sized buffers, client should send the info...
+    HBufC* noteTextH = HBufC::NewLC( KGlobalNoteTextLength );
+    TPtr noteText = noteTextH->Des();
+    
+    readStream >> noteText;
+
+    if ( count == 0 && !addCount )
+        {
+        isCancel = 1; // true
+        }
+    else if ( count < 0 )
+        {
+        count = 1;
+        }
+
+    if ( type == ECustomSoftNotification )
+        {
+        TInt customNoteID = readStream.ReadInt32L();
+
+        CCustomNotifParams* params = SeekCustomNoteForId( customNoteID );
+        TInt noteId = ( params==0 ) ? KErrNotFound : params->iNoteId;
+
+        if ( isCancel )
+            {
+            if ( !params ) 
+                {
+                // No note for id, no need to do anything but restore the iNotificationsSaved value.
+                CleanupStack::PopAndDestroy( noteTextH );
+                iNotificationsSaved = notificationsSavedTmp;
+                return;
+                }
+
+            if ( noteId == 0 ) // was displayed in grouped form
+                {
+                RemoveCustomNoteForId( customNoteID );
+                
+                if (!IsGroupedFormed())
+                    {
+                    // ScheduleGroupedNotifierL does not remove EShowGroupedNotification item
+                    // so let's do it here.
+                    RemoveByType(EShowGroupedNotification);
+                    }                
+                
+                ScheduleGroupedNotifierL();
+                SaveSoftNotificationsL();
+                
+                // If grouped note was visible and only one groupable soft note was left,
+                // then iSoftNoteEntryList and iCustomNoteParamsStack states are not exactly 
+                // correct. Load restores this state.
+                TRAP_IGNORE(LoadAndQueueSoftNotesL());
+                }
+            else
+                {
+                RemoveCustomNoteForId( noteId, ETrue );
+                if ( noteId != KErrNotFound ) // was added to global notes queue
+                    {
+                    iGlobalNoteController->TryDisplayNextNoteL();
+                    }
+                    
+                SaveSoftNotificationsL();           
+                }
+            
+            CleanupStack::PopAndDestroy( noteTextH );
+            return;
+            }
+
+        if ( params ) // Remove old
+            {
+            count += ( addCount ? params->iCount : 0 );
+            TBool isNotGrouped = noteId != 0;
+            RemoveCustomNoteForId( isNotGrouped ? noteId : customNoteID, isNotGrouped );
+            }
+
+        TBool newNote = ( params == NULL );
+        AddNewCustomNoteL( readStream, count, newNote );
+
+        if( iCustomNoteParamsStack && 
+            iCustomNoteParamsStack->iParamType == KAknSoftNotificationDynamic )
+            {
+            aNoteId = iCustomNoteParamsStack->iId; // generated id
+            TPtrC customTxt( iCustomNoteParamsStack->CustomText( count, EFalse ) );
+            if( customTxt.Length() > 0 )
+                {
+                noteText.Copy( customTxt.Left( KGlobalNoteTextLength ) );
+                }
+            }
+        }
+
+    if ( !isCancel )
+        {
+#ifdef __COVER_DISPLAY
+        // Play tone for select network notification immediately if device has cover display.
+        if ((type == ESelectNetworkNotification) && count && !iSoftNotificationAmounts[type])
+            {
+            ((CAknCapAppServerAppUi*)(CEikonEnv::Static())->EikAppUi())->KeySounds()->
+                PlaySound(CAknNoteDialog::EErrorTone);
+            }
+#endif // __COVER_DISPLAY            
+
+        TBool countChanged = ETrue;
+        
+        if ( addCount )
+            {
+            iSoftNotificationAmounts[type] += count;
+            }
+        else
+            {
+            if ( iSoftNotificationAmounts[type] == count )
+                {
+                // If the amount is not changed, set up a flag for
+                // not updating the note.
+                countChanged = EFalse;
+                }
+            iSoftNotificationAmounts[type] = count;
+            }
+            
+        UpdateNoteL(type, noteText, iSoftNotificationAmounts[type], countChanged);
+        CleanupStack::PopAndDestroy( noteTextH );
+
+        User::ResetInactivityTime();
+        }
+    else // Cancel note by type
+        {
+        CleanupStack::PopAndDestroy( noteTextH );
+
+        if (iSoftNotificationAmounts[type] == 0)
+            {
+            // There is not this type of soft notifications on queue
+            // Just restore the iNotificationsSaved value and return.
+            iNotificationsSaved = notificationsSavedTmp;
+            return;
+            }
+            
+        iSoftNotificationAmounts[type] = 0;
+        RemoveByType(type);
+        
+        if (type == EMissedCallsNotification ||
+            type == ENewMessagesNotification ||
+            type == ENewMailNotification ||
+            type == EChatMessageNotification)
+            {
+            RemoveByType(EShowGroupedNotification);
+            ScheduleGroupedNotifierL();
+            }
+        else
+            {
+            iGlobalNoteController->TryDisplayNextNoteL();
+            }
+        }
+
+    SaveSoftNotificationsL();
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::GroupedNoteCompletedL(TInt aCommandId,TAknGroupedNotifierItem aSelectedItem)
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::GroupedNoteCompletedL(TInt aCommandId,TAknGroupedNotifierItem aSelectedItem)
+    {
+    if ( iGroupedNote )
+        {
+        //No delete is necessary as the dialog will take care of deleting itself
+        iGroupedNote->RemoveEditorIndicator();
+        iGroupedNote = NULL;
+        }
+
+    if ( aCommandId == EEikBidTab ) // Apps or end-key pressed
+        {
+        SaveSoftNotificationsL();
+        ClearAllNotes();
+        return;
+        }
+
+    if ( aCommandId == EAknSoftkeyExit )
+        {
+        SetNcnFlag(EFalse);
+        }
+
+    // Make sure goruped notification is removed from queue
+    RemoveByType(EShowGroupedNotification);
+
+    if (aSelectedItem > EMaxItem || aSelectedItem < 0 ) // out of "static" range
+        {
+        CCustomNotifParams* params = SeekCustomNoteForId(aSelectedItem);
+        if (params)
+            {
+            HandleCustomNoteCompletedL(params, aCommandId);
+            }
+        RemoveCustomNoteForId(aSelectedItem);
+        
+        // To allow this to fall through next clause (saving, rescheduling etc.).
+        aCommandId = EAknSoftkeyOk; 
+        }
+
+    if (aCommandId == EAknSoftkeyShow  || aCommandId == EAknSoftkeyOk)
+        {
+        if (aSelectedItem == EMissedCalls)
+            {
+            iSoftNotificationAmounts[EMissedCallsNotification] = 0;
+            LaunchMissedCallsAppL();
+            }
+        else if (aSelectedItem == ENewMessages)
+            {
+            iSoftNotificationAmounts[ENewMessagesNotification] = 0;
+            LaunchNewMessagesAppL();
+            }
+        else if (aSelectedItem == ENewChatMsgs)
+            {
+            iSoftNotificationAmounts[EChatMessageNotification] = 0;
+            LaunchNewIMAppL();
+            }
+        else if (aSelectedItem == ENewMails)
+            {
+            iSoftNotificationAmounts[ENewMailNotification] = 0;
+            LaunchNewMailAppL();
+            }
+
+        ScheduleGroupedNotifierL();
+        iNotificationsSaved = EFalse;
+
+    }
+    else if (aCommandId == EAknSoftkeyExit || aCommandId == KErrCancel)
+        {
+        if ( aCommandId == EAknSoftkeyExit )
+            {
+            iSoftNotificationAmounts[EMissedCallsNotification] = 0;
+            iSoftNotificationAmounts[ENewMessagesNotification] = 0;
+            iSoftNotificationAmounts[EChatMessageNotification] = 0;
+            iSoftNotificationAmounts[ENewMailNotification] = 0;
+
+            // Null Customs
+            CCustomNotifParams* params = iCustomNoteParamsStack;
+            while(params)
+                {
+                CCustomNotifParams* tmp = params->iNext;
+                if (params->iSupportsGroupedform)
+                    {
+                    if( params->iParamType == KAknSoftNotificationDynamic )
+                        {
+                        if (params->EnableObserver())
+                            {
+                            // notify user event
+                            iDynamicSoftNoteManager->IssueEvent(
+                                params->iId, EAknDynamicSNoteEventCanceled, ETrue);    
+                            }
+                        }
+                    RemoveCustomNoteForId(params->iId);
+                    }
+                params = tmp;
+                }
+
+            RemoveByType(EShowGroupedNotification); // Remove also from global notes queue
+            iNotificationsSaved = EFalse;
+            }
+        iGlobalNoteController->TryDisplayNextNoteL();
+        }
+    SaveSoftNotificationsL();
+    }
+
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::UpdateNoteL(TSoftNotifierType aType)
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::UpdateNoteL(
+    TAknSoftNotificationType aType,const TDesC& aText, TInt aCount, TBool aCountChanged)
+    {
+    iLatestType = aType;
+
+    if ((aType > ENoSoftNotification && aType < EMissedCallsNotification)
+        || aType == ECustomSoftNotification)
+        {
+        // Received an ungrouped soft notification
+        DisplayUngroupedNotifierL(aType, aText, aCount);
+        }
+    else if ((aType >= EMissedCallsNotification && aType <= ENewMailNotification)
+        || aType == EChatMessageNotification)
+        {
+        // Set shared data flag if this is missed calls notification.
+        // This is needed for synchronizing notes with screensaver
+        // indicator view.
+        if (aType == EMissedCallsNotification && aCount > 0)
+            {
+            SetNcnFlag( ETrue );
+            }
+            
+        // Update grouped notifier only if the count has actually changed.
+        // This removes flicker in some cases.
+        if ( aCountChanged )
+            {
+            ScheduleGroupedNotifierL();
+            }
+        }
+    }
+
+
+void CAknSoftNotificationSubject::ScheduleGroupedNotifierL()
+    {
+    // Possible grouped notification
+    TBool grouped = IsGroupedFormed();
+    if (grouped)
+        {
+        if (iGroupedNote)
+            {
+            // grouped note already exists, so just update it
+            ShowGroupedNotificationL();
+            }
+        else
+            {
+            // Schedule grouped note
+            RemoveByType(EShowGroupedNotification);
+            RemoveByType(EMissedCallsNotification);
+            RemoveByType(ENewMessagesNotification);
+            RemoveByType(EChatMessageNotification);
+            RemoveByType(ENewMailNotification);
+
+            CCustomNotifParams* params = iCustomNoteParamsStack;
+            for (;params;params = params->iNext)
+                {
+                if( params->iSupportsGroupedform )
+                    {
+                    if ( params->iNoteId != KErrNotFound && params->iNoteId != 0)
+                        {
+                        iGlobalNoteController->CancelNote(params->iNoteId, EFalse);
+                        for (TInt ii = 0; ii < iSoftNoteEntryList->Count(); ii++)
+                            {
+                            if (params->iNoteId == iSoftNoteEntryList->At(ii).iId )
+                                {
+                                iSoftNoteEntryList->At(ii).iId = 0;
+                                iSoftNoteEntryList->At(ii).iCustomId = params->iId;
+                                break;
+                                }
+                            }
+                        }
+
+                    params->iNoteId = 0;
+                    }
+                }
+
+            // Create grouped notification
+            TSoftNoteEntry softNote;
+            softNote.iType = EShowGroupedNotification;
+            softNote.iId = iGlobalNoteController->AddSoftNotificationL(KNullDesC, 0, 0,
+                KGroupedNotification, 0);
+            iGlobalNoteController->TryDisplayNextNoteL();
+            iSoftNoteEntryList->AppendL(softNote);
+            }
+        }
+    else
+        {
+        if (iGroupedNote)
+            {
+            delete iGroupedNote;
+            iGroupedNote = NULL;
+            }
+        // Display using ungrouped layout
+        if (iSoftNotificationAmounts[EMissedCallsNotification])
+            {
+            DisplayUngroupedNotifierL(EMissedCallsNotification, KNullDesC, 
+                iSoftNotificationAmounts[EMissedCallsNotification]);
+            }
+        if (iSoftNotificationAmounts[ENewMessagesNotification])
+            {
+            DisplayUngroupedNotifierL(ENewMessagesNotification, KNullDesC, 
+                iSoftNotificationAmounts[ENewMessagesNotification]);
+            }
+        if (iSoftNotificationAmounts[EChatMessageNotification])
+            {
+            DisplayUngroupedNotifierL(EChatMessageNotification, KNullDesC, 
+                iSoftNotificationAmounts[EChatMessageNotification]);
+            }
+        if (iSoftNotificationAmounts[ENewMailNotification])
+            {
+            DisplayUngroupedNotifierL(ENewMailNotification, KNullDesC, 
+                iSoftNotificationAmounts[ENewMailNotification]);
+            }
+        }
+    }
+
+
+
+void CAknSoftNotificationSubject::DisplayUngroupedNotifierL(TAknSoftNotificationType aType, 
+    const TDesC& aText, TInt aCount)
+    {
+    TInt resource = 0;
+    TInt priority = 0;
+    TBool cancel = EFalse;
+    TInt count = 0;
+    TInt softkeys = 0;
+    TInt tone = 0; // ENoTone;
+    switch (aType)
+        {
+        case ENetworkInformationNotification:
+            resource = R_NETWORK_INFORMATION_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_OK_EMPTY__OK;
+            priority = KNetworkInfoPriority;
+            break;
+        case ESelectNetworkNotification:
+            resource = R_SELECT_NETWORK_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_OK_CANCEL__OK;
+            priority = KSelectNetworkPriority;
+#ifndef __COVER_DISPLAY            
+            tone = CAknNoteDialog::EErrorTone;
+#endif // __COVER_DISPLAY            
+            if ( CheckIfAlreadyExists(ESelectNetworkNotification) )
+                {
+                return;
+                }
+            break;
+        case EUnstructuredSSDataNotification:
+            resource = R_UNSTRUCTURED_SS_DATA_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_READ_EXIT__READ;
+            priority = KUSSDPriority;
+            break;
+        case EVoiceMailNotification:
+            resource = R_VOICE_MAIL_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_LISTEN_EXIT__LISTEN;
+            priority = KVoiceMailPriority;
+            cancel = ETrue;
+            break;
+        case ESeparateVoiceMailOnLine2Notification:
+            resource = R_VOICE_MAIL_ON_LINE2_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_LISTEN_EXIT__LISTEN;
+            priority = KVoiceMailOnLinePriority;
+            cancel = ETrue;
+            break;
+        case ESeparateVoiceMailOnLine1Notification:
+            resource = R_VOICE_MAIL_ON_LINE1_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_LISTEN_EXIT__LISTEN;
+            priority = KVoiceMailOnLinePriority;
+            cancel = ETrue;
+            break;
+        case ECellBroadcastNotification:
+            resource = R_CELL_BROADCAST_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_READ_EXIT__READ;
+            priority = KCBSPriority;
+            cancel = ETrue;
+            break;
+        case EMissedCallsNotification:
+            resource = R_MISSED_CALLS_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_SHOW_EXIT__SHOW;
+            priority = KMissedCallsPriority;
+            cancel = ETrue;
+            SetNcnFlag(ETrue);
+            break;
+        case ENewMessagesNotification:
+            resource = R_NEW_MESSAGES_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_SHOW_EXIT__SHOW;
+            priority = KNewMessagesPriority;
+            cancel = ETrue;
+            break;
+        case ENewMailNotification:
+            resource = R_NEW_MAIL_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_SHOW_EXIT__SHOW;
+            priority = KNewEmailPriority;
+            cancel = ETrue;
+            break;
+        case EChatMessageNotification:
+            resource = R_NEW_CHAT_MESSAGES_NOTE;
+            softkeys = R_AVKON_SOFTKEYS_SHOW_EXIT__SHOW;
+            priority = KChatMessagePriority;
+            cancel = ETrue;
+            break;
+        case ECustomSoftNotification:
+            {
+            resource = iCustomNoteParamsStack->iId;
+            softkeys = iCustomNoteParamsStack->iParamData->iSoftkeys;
+            priority = iCustomNoteParamsStack->iParamData->iPriority;
+            tone = iCustomNoteParamsStack->iParamData->iTone;
+            cancel = EFalse;
+            count = iCustomNoteParamsStack->iCount;
+            break;
+            }
+        default:
+            break;
+        };
+
+    if (cancel)
+        {
+        // Remove duplicate notes
+        RemoveByType(aType);
+        count = aCount;
+        }
+
+    TSoftNoteEntry softNote;
+    softNote.iType = aType;
+    softNote.iCount = count;
+
+#ifdef _DEBUG
+    _LIT(KDmsg, "AknSoftNotificationPlugin, Adding ungrouped:type %d,count %d ");
+    RDebug::Print(KDmsg,aType, count);
+#endif
+
+    if ( aType == ECustomSoftNotification )
+        {
+        if( iCustomNoteParamsStack->iParamType == KAknSoftNotificationCustom )
+            {
+            TFileName resourceFile;
+            CEikonEnv* environment = CEikonEnv::Static();
+            resourceFile.Append(iCustomNoteParamsStack->iParamData->iResourceFile->Des());
+            BaflUtils::NearestLanguageFile(environment->FsSession(),resourceFile);
+    
+            TRAPD( err, iCustomNoteParamsStack->iCoeResourceHandle =
+                environment->AddResourceFileL(resourceFile));
+    
+            if ( err )
+                { // couldn't load note resource, remove note from queue
+#ifdef _DEBUG
+                _LIT(KDmsg2,"AknSoftNotificationPlugin,Resource loading failed: %s");
+                RDebug::Print(KDmsg2,&resourceFile);
+#endif
+                RemoveCustomNoteForId(resource);
+                return;
+                }
+            }
+
+        if (iCustomNoteParamsStack->iSupportsGroupedform && IsGroupedFormed())
+            { // don't add to global notes queue
+            softNote.iId = 0; // grouped, not in global notes queue
+            softNote.iCustomId = iCustomNoteParamsStack->iId;
+            iSoftNoteEntryList->AppendL(softNote);
+            ScheduleGroupedNotifierL();
+            return;
+            }
+        }
+
+    if( aType == ECustomSoftNotification &&
+        iCustomNoteParamsStack->iParamType == KAknSoftNotificationDynamic )
+        {
+        if( iCustomNoteParamsStack->iDynamicData )
+            {
+            CAknDynamicNotificationData* data = 
+                iCustomNoteParamsStack->iDynamicData;
+            softNote.iId = iGlobalNoteController->AddSoftNotificationL(
+                aText,
+                count,
+                data->Priority(),
+                data->Tone(),
+                data->LeftSoftkey(),
+                data->RightSoftkey(),
+                data->ImageData() );
+            }
+        }
+    else
+        {
+        softNote.iId = iGlobalNoteController->AddSoftNotificationL(aText, resource, count, priority, 
+            softkeys, tone );
+        }
+        
+    if ( aType == ECustomSoftNotification )
+        {
+        CAknSDData* sdData = iCustomNoteParamsStack->iParamData->iSecondaryDisplayData;
+        
+        if ( sdData )
+            {
+            CAknSDData* cloneSDData = NULL;
+            cloneSDData = CAknSDData::NewL( sdData->iCategory, sdData->iDialogIdx, *(sdData->iAdditionalData) );
+            CleanupStack::PushL( cloneSDData );
+            
+            TBool sdDataSet = iGlobalNoteController->SetSDData( softNote.iId, cloneSDData );
+            
+            if ( sdDataSet )
+                {
+                CleanupStack::Pop( cloneSDData );
+                }          
+            else // cloneSDData ownership not transferred
+            	{
+            	CleanupStack::PopAndDestroy( cloneSDData );
+            	}
+            }
+            
+        iCustomNoteParamsStack->iNoteId = softNote.iId;
+        }
+
+    iGlobalNoteController->TryDisplayNextNoteL();
+    iSoftNoteEntryList->AppendL(softNote);
+
+#ifdef _DEBUG
+    _LIT(KDmsg3,"AknSoftNotificationPlugin, Added SoftNote:type %d,NoteId %d ");
+    RDebug::Print(KDmsg3,aType, softNote.iId);
+#endif
+    }
+
+
+void CAknSoftNotificationSubject::RemoveByType(TAknSoftNotificationType aType, TInt aId)
+    {
+    TInt count = iSoftNoteEntryList->Count();
+    for (TInt ii=count-1; ii>=0; ii--)
+        {
+        TSoftNoteEntry& entry = (*iSoftNoteEntryList)[ii];
+
+        if ( ( aType != ECustomSoftNotification && entry.iType == aType)
+            || ( aId != 0 && entry.iType == ECustomSoftNotification && entry.iId == aId) )
+            {
+            iGlobalNoteController->CancelNote(entry.iId, EFalse);
+            iSoftNoteEntryList->Delete(ii);
+            }
+        }
+    }
+
+void CAknSoftNotificationSubject::ClearAllNotes()
+    {
+#ifdef _DEBUG
+    _LIT(KDmsg, "AknSoftNotificationPlugin,ClearAllNotes");
+    RDebug::Print(KDmsg);
+#endif
+
+    while ( iSoftNoteEntryList->Count())
+        {
+        TSoftNoteEntry& entry = (*iSoftNoteEntryList)[0];
+        if (entry.iId != 0)
+            {
+            iGlobalNoteController->CancelNote(entry.iId, EFalse);
+            }
+        iSoftNotificationAmounts[entry.iType] = 0;
+        iSoftNoteEntryList->Delete(0);
+        }
+
+    CCustomNotifParams* params = iCustomNoteParamsStack;
+    while ( params )
+        {
+        CCustomNotifParams* tmp = params;
+        params = params->iNext;
+        delete tmp;
+        }
+    iCustomNoteParamsStack = 0;
+    }
+
+// Used only with ungrouped notes
+TAknSoftNotificationType CAknSoftNotificationSubject::TypeFromId(TInt aId)
+    {
+    TInt count = iSoftNoteEntryList->Count();
+    for (TInt ii = count - 1; ii >= 0; ii--)
+        {
+        TSoftNoteEntry& entry = (*iSoftNoteEntryList)[ii];
+        if (entry.iId == aId)
+            {
+            return entry.iType;
+            }
+        }
+    return ENoSoftNotification;
+    }
+
+// Used only with ungrouped notes
+void CAknSoftNotificationSubject::CompleteId(TInt aId)
+    {
+    TInt count = iSoftNoteEntryList->Count();
+    for (TInt ii=count-1; ii>=0; ii--)
+        {
+        TSoftNoteEntry& entry = (*iSoftNoteEntryList)[ii];
+        if (entry.iId == aId)
+            {
+            // Set notification count to zero
+            iSoftNotificationAmounts[entry.iType] = 0;
+            iSoftNoteEntryList->Delete(ii);
+            RemoveCustomNoteForId(aId,ETrue);
+            iNotificationsSaved = EFalse;
+            return;
+            }
+        }
+    return;
+    }
+
+void CAknSoftNotificationSubject::SoftNoteCompleted(TInt aId, TInt aCommand)
+    {
+    TRAPD(err, DoSoftNoteCompletedL(aId, aCommand));
+    if (err)
+        {
+        CEikonEnv::Static()->HandleError(err);
+        }
+    }
+
+void CAknSoftNotificationSubject::DoSoftNoteCompletedL(TInt aId, TInt aCommand)
+    {
+    TAknSoftNotificationType type = TypeFromId( aId );
+
+#ifdef _DEBUG
+    _LIT(KDmsg, "AknSoftNotificationPlugin,DoSoftNoteCompletedL:type %d,NoteId %d, command %d ");
+    RDebug::Print(KDmsg,type, aId, aCommand);
+#endif
+
+    if ( aCommand == EAknSoftkeyExit )
+        {
+        if ( type == EMissedCallsNotification )
+            {
+            SetNcnFlag(EFalse);
+            }
+        if( type == ECustomSoftNotification )
+            {
+            CCustomNotifParams* params = SeekCustomNoteForId( aId, ETrue );
+            if( params )
+                {
+                HandleCustomNoteCanceledL( params, aCommand );
+                }            
+            }
+        CompleteId(aId);
+        SaveSoftNotificationsL();
+        return;
+        }
+
+    switch (type)
+        {
+        case ESelectNetworkNotification:
+            if (aCommand == EAknSoftkeyOk)
+                {
+                LaunchSelectNetworkAppL();
+                CompleteId(aId);
+                }
+            break;
+        case EUnstructuredSSDataNotification:
+            if (aCommand == EAknSoftkeyRead || aCommand == EAknSoftkeyOk)
+                {
+                LaunchUSSDAppL();
+                CompleteId(aId);
+                }
+            break;
+        case EVoiceMailNotification:
+        case ESeparateVoiceMailOnLine1Notification:
+        case ESeparateVoiceMailOnLine2Notification:
+            if (aCommand == EAknSoftkeyListen || aCommand == EAknSoftkeyOk)
+                {
+                LaunchNewVoiceMailAppL(type);
+                CompleteId(aId);
+                }
+            break;
+        case ECellBroadcastNotification:
+            if (aCommand == EAknSoftkeyRead || aCommand == EAknSoftkeyOk)
+                {
+                LaunchNewCbsAppL();
+                CompleteId(aId);
+                }
+            break;
+        case EMissedCallsNotification:
+            if (aCommand == EAknSoftkeyShow || aCommand == EAknSoftkeyOk)
+                {
+                LaunchMissedCallsAppL();
+                CompleteId(aId);
+                }
+            break;
+        case ENewMessagesNotification:
+            if (aCommand == EAknSoftkeyShow || aCommand == EAknSoftkeyOk)
+                {
+                LaunchNewMessagesAppL();
+                CompleteId(aId);
+                }
+            break;
+        case ENewMailNotification:
+            if (aCommand == EAknSoftkeyShow || aCommand == EAknSoftkeyOk)
+                {
+                LaunchNewMailAppL();
+                CompleteId(aId);
+                }
+            break;
+        case EChatMessageNotification:
+            if (aCommand == EAknSoftkeyShow || aCommand == EAknSoftkeyOk)
+                {
+                LaunchNewIMAppL();
+                CompleteId(aId);
+                }
+            break;
+        case ECustomSoftNotification:
+            {
+            CCustomNotifParams* params = SeekCustomNoteForId(aId, ETrue);
+            if (params)
+                {
+                HandleCustomNoteCompletedL(params, aCommand);
+                CompleteId(aId);
+                }
+            }
+            break;
+        default:
+            // Note type something else, this should not be the case.
+            // Remove note from queue anyway.
+            CompleteId( aId );
+            break;
+        }
+    SaveSoftNotificationsL();
+    }
+
+
+void CAknSoftNotificationSubject::HandleCustomNoteCompletedL(CCustomNotifParams* aParams, 
+    TInt aCommand)
+    {
+    if (aParams->iHasViewInfo)
+        {
+        if ( aCommand == EAknSoftkeyOk ||
+             aParams->iParamData->iAcceptSoftKey == aCommand )
+            {
+            LaunchViewL( 
+                ((aParams->iParamData->iPluralViewId != KNullViewId && aParams->iCount > 1)?
+                    aParams->iParamData->iPluralViewId:
+                    aParams->iParamData->iViewId),
+
+                aParams->iParamData->iCustomMessageId,
+                aParams->ViewActivationMessage() );
+            }
+        }
+    
+    // notify user event
+    if( aParams->iParamType == KAknSoftNotificationDynamic )
+        {
+        if( aParams->EnableObserver() )
+            {
+            iDynamicSoftNoteManager->IssueEvent( 
+                aParams->iId, EAknDynamicSNoteEventAccepted, ETrue );
+            }        
+        }
+    }
+
+void CAknSoftNotificationSubject::HandleCustomNoteCanceledL( 
+    CCustomNotifParams* aParams, TInt /*aCommand*/ )
+    {
+    // notify user event
+    if( aParams->iParamType == KAknSoftNotificationDynamic )
+        {
+        if( aParams->EnableObserver() )
+            {
+            iDynamicSoftNoteManager->IssueEvent( 
+                aParams->iId, EAknDynamicSNoteEventCanceled, ETrue );
+            }         
+        }
+    }
+
+//
+// Sets shared data flag to indicate that NCN is active.
+// This implementation sets this only for missed calls note.
+//
+void CAknSoftNotificationSubject::SetNcnFlag(TBool aValue)
+    {
+    CRepository* repository = NULL;
+    TRAPD(ret, repository = CRepository::NewL(KCRUidAvkon));
+    if (ret == KErrNone)
+        {
+        ret = repository->Set(KAknNewContactsNoteActive, aValue);
+        }
+    delete repository;
+    }
+
+
+// Handler function for ncn flag shared data state change.
+TInt CAknSoftNotificationSubject::HandleNcnFlagStateChange(TAny* /* aPtr */)
+    {
+    return KErrNone;
+    }
+
+TBool CAknSoftNotificationSubject::ShowSoftNoteL(TInt aPriority, const TDesC& /*aText*/)
+    {
+    if (aPriority == KGroupedNotification)
+        {
+        ShowGroupedNotificationL();
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+TBool CAknSoftNotificationSubject::CancelSoftNote(TInt aPriority)
+    {
+    if (aPriority == KGroupedNotification)
+        {
+        if (iGroupedNote)
+            {
+            iGroupedNote->RemoveEditorIndicator();
+            delete iGroupedNote;
+            iGroupedNote = NULL;
+            }
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::ShowGroupedNotificationL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::ShowGroupedNotificationL()
+    {
+    if ( iGroupedNote )
+        {
+        iGroupedNote->RemoveEditorIndicator();
+        }
+
+    CAknGroupedNotifierNote* note = new (ELeave) CAknGroupedNotifierNote();
+    CleanupStack::PushL( note );
+    note->ConstructL( this );
+
+    note->SetItemAmountL(
+        EMissedCalls, 
+        iSoftNotificationAmounts[EMissedCallsNotification], 
+        iLatestType == EMissedCallsNotification);
+        
+    note->SetItemAmountL(
+        ENewMessages, 
+        iSoftNotificationAmounts[ENewMessagesNotification], 
+        iLatestType == ENewMessagesNotification);
+        
+    note->SetItemAmountL(
+        ENewChatMsgs, 
+        iSoftNotificationAmounts[EChatMessageNotification], 
+        iLatestType == EChatMessageNotification);
+        
+    note->SetItemAmountL(
+        ENewMails, 
+        iSoftNotificationAmounts[ENewMailNotification], 
+        iLatestType == ENewMailNotification);
+        
+    CleanupStack::Pop( note );
+
+    note->ExecuteLD( R_GROUPED_SOFT_NOTIFICATION );
+
+    delete iGroupedNote;
+    iGroupedNote = note;
+    if ( iKeysLocked && note )
+        {
+        iGroupedNote->ListBox()->View()->ItemDrawer()->SetFlags(
+            CListItemDrawer::EDisableHighlight );
+        }
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::MessageNotifierShown()
+// ---------------------------------------------------------
+//
+TBool CAknSoftNotificationSubject::MessageNotifierShown()
+    {
+    TBool messageNotifierActive( EFalse );
+
+    for ( TInt ii = 0; ii <= ECustomSoftNotification; ii++)
+        {
+        // Check that one of the message notifiers is first in the 
+        // priority order (visible). 
+        if (iSoftNotificationAmounts[ii] > 0)
+            {
+            if (ii == EMissedCallsNotification && IsGroupedFormed())
+                {
+                continue;
+                }
+            if ( ii == ENewMessagesNotification ||
+                 ii == ENewMailNotification ||
+                 ii == ECustomSoftNotification ) // Email uses custom soft note.
+                {
+                messageNotifierActive = ETrue;
+                }
+            break;                
+            }
+        }
+
+    return messageNotifierActive;
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::ButtonGroupContainer()
+// ---------------------------------------------------------
+//
+CEikButtonGroupContainer* CAknSoftNotificationSubject::ButtonGroupContainer()
+    {
+    CEikButtonGroupContainer* container = NULL;
+    if ( iGroupedNote ) 
+        {
+        container = &iGroupedNote->ButtonGroupContainer();
+        }
+    return container;
+    }
+        
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::IsGroupedFormed()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TBool CAknSoftNotificationSubject::IsGroupedFormed()
+    {
+    TInt foundTypes = 0;
+    if (iSoftNotificationAmounts[EMissedCallsNotification])
+        {
+        foundTypes++;
+        }
+    if (iSoftNotificationAmounts[ENewMessagesNotification])
+        {
+        foundTypes++;
+        }
+    if (iSoftNotificationAmounts[EChatMessageNotification])
+        {
+        foundTypes++;
+        }
+    if (iSoftNotificationAmounts[ENewMailNotification])
+        {
+        foundTypes++;
+        }
+        
+    // check custom notes which support grouped form
+    CCustomNotifParams* params = iCustomNoteParamsStack;
+    for (;params;params = params->iNext)
+        {
+        if(params->iSupportsGroupedform)
+            {
+            foundTypes++;
+            }
+        }
+
+    if (foundTypes > 1)
+        {
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+// ------------------------------------
+// From MAknGroupedNotifierNoteObserver
+// Add items to grouped form
+// ------------------------------------
+void CAknSoftNotificationSubject::AddItemsL( CDesCArray& aTexts, CArrayFix<TInt>& aOrder )
+    {
+    // check custom notes which support grouped form
+    CCustomNotifParams* params = iCustomNoteParamsStack;
+    for (;params;params = params->iNext)
+        {
+        if(params->iSupportsGroupedform)
+            {
+            if( params->iParamType == KAknSoftNotificationDynamic )
+                {
+                if( params->iCount > 1 )
+                    {
+                    // plural text needs to be formatted
+                    TPtrC text( params->CustomText( params->iCount, ETrue ) );
+                    const TInt formatSpace = 11; // space needed for 'count'
+                    HBufC* buf = HBufC::NewLC( text.Length() + formatSpace );
+                    buf->Des().Format( text, params->iCount );
+                    
+                    aTexts.AppendL( *buf );
+                    aOrder.AppendL( params->iId );
+                    
+                    CleanupStack::PopAndDestroy( buf );
+                    }
+                else
+                    {
+                    // append singular text
+                    aTexts.AppendL( params->CustomText( params->iCount, ETrue ) );
+                    aOrder.AppendL( params->iId );
+                    }
+                }
+            else
+                {
+                // Load text
+                CCoeEnv* coe = CCoeEnv::Static();
+                TResourceReader reader;
+                HBufC* buf = 0;
+    
+                // Resources are loaded in DisplayUngroupedNotifierL()
+                coe->CreateResourceReaderLC(reader, params->iParamData->iGroupedTextResourceId);
+                TInt stringResource = reader.ReadInt32();
+    
+                // Handle Singular / plural + possible plural string w/o number tag
+                if (params->iCount == 1)
+                    {
+                    buf = coe->AllocReadResourceLC(stringResource);
+                    }
+                else 
+                    {
+                    stringResource = reader.ReadInt32();
+                    buf = coe->AllocReadResourceLC(stringResource);
+                    _LIT(KNumberId, "%N");
+                    if (buf->Find(KNumberId) != KErrNotFound)
+                        {
+                        CleanupStack::PopAndDestroy();
+                        buf = 0;
+                        buf = StringLoader::LoadLC(stringResource,params->iCount);
+                        }
+                    }
+ 
+                // Add Text
+                aTexts.AppendL(buf->Des());
+                // add order
+                aOrder.AppendL(params->iId);
+                
+                CleanupStack::PopAndDestroy( 2 ); // buf and reader
+                }
+            
+
+            }
+        }
+    }
+    
+// --------------------------------------------------
+// CAknSoftNotificationSubject::SoftkeysForCustomItem
+// (other items were commented in a header).
+// --------------------------------------------------
+void CAknSoftNotificationSubject::SoftkeysForCustomItem(TAknGroupedNotifierItem aCustomItem,
+    TInt& aSoftkeyResourceId, TInt& aAcceptKeyId,
+    TDes& aLeftSoftkey,
+    TDes& aRightSoftkey )
+    {
+    CCustomNotifParams* params = SeekCustomNoteForId(aCustomItem, EFalse);
+    if( params )
+        {
+        if( params->iParamType == KAknSoftNotificationCustom && 
+            params->iParamData )
+            {
+            aSoftkeyResourceId = params->iParamData->iSoftkeys;
+            aAcceptKeyId       = params->iParamData->iAcceptSoftKey;
+            }
+        
+        if( params->iParamType == KAknSoftNotificationDynamic && 
+            params->iDynamicData )
+            {
+            TPtrC sk( params->iDynamicData->LeftSoftkey() );
+            if( sk.Length() > 0 )
+                {
+                aLeftSoftkey.Copy( sk.Left( aLeftSoftkey.MaxLength() ) );
+                }
+            
+            sk.Set( params->iDynamicData->RightSoftkey() );
+            if( sk.Length() > 0 )
+                {
+                aRightSoftkey.Copy( sk.Left( aRightSoftkey.MaxLength() ) );
+                }
+            
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::LaunchMissedCallsAppL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::LaunchMissedCallsAppL()
+    {
+    TPtrC8 msg(KLogsActivationMsg);                
+    
+    TApaTaskList taskList( CCoeEnv::Static()->WsSession() );
+    TApaTask task = taskList.FindApp( KUidLogs );
+
+    // close fsw in case it is active.
+    // this is needed because LaunchMissedCallsAppL doesn't call 
+    // method LaunchViewL, which does the same
+    ((CAknCapAppServerAppUi*)(CEikonEnv::Static())->EikAppUi())->
+        HandleResourceChangeL(KAknInternalFSWClose); // won't leave
+    
+    TInt err = KErrNone;
+    
+    if( task.Exists() ) //Logs already open. Request it to
+        {               //activate the correct view
+        task.SendMessage( KUidLogs, msg ); // the uid has no meaning so just re-use existing 
+
+     // preventing from the flicker of log view, the view will activte ieself when receiving a message.   
+     // task.BringToForeground();
+        }
+    else                //Start Logs and request it to activate
+        {               //the correct view
+        TApaAppInfo appInfo;
+        RApaLsSession lsSession;
+        err = lsSession.Connect();
+        
+        if ( err == KErrNone )
+            {
+            CleanupClosePushL( lsSession );
+            
+            if( lsSession.GetAppInfo( appInfo, KUidLogs ) == KErrNone )
+                {
+                CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
+                cmdLine->SetExecutableNameL( appInfo.iFullName );
+                cmdLine->SetCommandL( EApaCommandRun );
+                cmdLine->SetTailEndL( msg );
+
+                lsSession.StartApp( *cmdLine );
+                CleanupStack::PopAndDestroy( cmdLine );
+                }
+
+            CleanupStack::PopAndDestroy();  // lsSession
+            }
+        else
+            {
+            User::LeaveIfError( err );
+            }
+        }
+    
+    if ( err == KErrNone )
+        {
+        // We'll assume that application was launched/activated succesfully
+        SetNcnFlag(EFalse);
+        }
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::LaunchNewMessagesAppL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::LaunchNewMessagesAppL()
+    {        
+    TInt viewtype = 0; // Default is traditional Inbox
+
+    if ( iMessagingRepository )
+        {
+	// Read the messaging settings
+        iMessagingRepository->Get(KMessagingAppDefaultViewCRKey,viewtype);
+        }
+
+    if ( viewtype == 1 ) // Launch conversations 
+        {
+        LaunchViewL( 
+                KConversationApplicationViewUid,           
+                TUid::Uid(KConversationListViewUid),         
+                KNullDesC8() );
+        }    
+    else  // Launch traditional Inbox
+        {
+        LaunchViewL( 
+            KMessagingCentreInboxView, 
+            TUid::Uid(KMsvGlobalInBoxIndexEntryIdValue), 
+            KNullDesC8() );
+        }    
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::LaunchNewMailAppL()
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::LaunchNewMailAppL()
+    {
+    // reactivate MCE main view with arbitrary UID
+    LaunchViewL( KMessagingCentreMainViewUid, TUid::Uid(1),KNullDesC8() );
+    }
+
+void CAknSoftNotificationSubject::LaunchNewCbsAppL()
+    {
+    if ( iSoftNotificationAmounts[ECellBroadcastNotification] == 1)
+        {
+        LaunchViewL( KCbsApplicationUidMessageView, TUid::Uid(1), KNullDesC8() );
+        }
+    else
+        {
+        LaunchViewL( KCbsApplicationUidTopicListView, TUid::Uid(1), KNullDesC8() );
+        }
+    }
+
+void CAknSoftNotificationSubject::LaunchNewVoiceMailAppL(TInt aType)
+    {
+    TUid uid = {1}; // als line 1 or no als (TVmbxNumberEntry::EAlsLine1Entry)
+    if ( aType == ESeparateVoiceMailOnLine2Notification )
+        {
+        uid.iUid = 2; // (TVmbxNumberEntry::EAlsLine2Entry)
+        }
+
+    LaunchViewL( KSpeeddialVmbxDialUidView, uid, KExternalLaunch );
+    }
+
+void CAknSoftNotificationSubject::LaunchSelectNetworkAppL()
+    {
+    LaunchViewL( KSelectNetworkAppUidView, TUid::Uid( KGSCustomActivateNetView ), KNullDesC8() );
+    }
+
+void CAknSoftNotificationSubject::LaunchUSSDAppL()
+    {
+    }
+
+void CAknSoftNotificationSubject::LaunchViewL(const TVwsViewId& aViewId, TUid aCustomMessageId, 
+    const TDesC8& aCustomMessage)
+    {
+    CCoeEnv::Static()->AppUi()->CreateActivateViewEventL(aViewId, aCustomMessageId, aCustomMessage);
+
+    SaveSoftNotificationsL();
+    
+    // close fsw in case it is active.
+    ((CAknCapAppServerAppUi*)(CEikonEnv::Static())->EikAppUi())->HandleResourceChangeL(
+        KAknInternalFSWClose); // won't leave
+   
+    // We assume that view switching was successful, change idle state to false:
+    delete iIdle;
+    iIdle = 0;
+    iIdle = CIdle::NewL(EPriorityLow);
+    iIdle->Start(TCallBack(SetIdleStateFalse, this));
+    }
+
+TInt CAknSoftNotificationSubject::SetIdleStateFalse(TAny* aThis)
+    {
+    TRAPD( err, ((CAknSoftNotificationSubject*)aThis)->iGlobalNoteController->
+        SetMaxDisplayPriorityL(KMinimumSoftNotePriority))
+    if (!err)
+        {
+        ((CAknSoftNotificationSubject*)aThis)->iIdleStateActive = EFalse;
+        ((CAknCapAppServerAppUi*)(CEikonEnv::Static())->EikAppUi())->SetIdleActive( EFalse );
+        }
+    return err;
+    }
+
+void CAknSoftNotificationSubject::SaveSoftNotificationsL()
+    {
+    // Save all soft notifications in case of power failure
+    if ( iNotificationsSaved ) // notifications haven't been loaded since saved i.e. no changes
+        {
+        return;
+        }
+
+    TInt count = iSoftNoteEntryList->Count();
+    RFs& fs = CEikonEnv::Static()->FsSession();
+#ifdef __COVER_DISPLAY  
+    iCoverClient->CancelCommand();
+    iCoverClient->ResetBuffer();
+#endif
+    if (count == 0)
+        {
+        // Nothing to save, delete any existing file
+        TInt err = fs.Delete(KAknSNFilename);
+        iNotificationsSaved = EFalse;
+#ifdef __COVER_DISPLAY  
+        // if deleted for the first time, inform the cover ui,
+        // otherwise the deletion returns KErrNotFound
+        if ( err == KErrNone ) 
+            {
+            // inform the cover ui that there are no soft notifications
+            iCoverClient->BufStream().WriteInt32L(count);
+            iCoverClient->BufStream().CommitL();
+            iCoverClient->IssueCommand();
+            }
+#endif        
+        }
+    else
+        {
+        // Create new file and save soft notifications
+        RFileWriteStream file;
+        TInt err = file.Replace(fs, KAknSNFilename, EFileWrite);
+        // path may not yet exist in 3.0 (private directory).
+        if (err == KErrPathNotFound)
+            {
+            User::LeaveIfError(fs.MkDirAll(KAknSNFilename));
+            User::LeaveIfError(file.Create(fs, KAknSNFilename, EFileWrite));
+            }
+
+        CleanupClosePushL(file);
+        file.WriteInt32L(count);
+
+#ifdef __COVER_DISPLAY  
+        TBool groupedExists = EFalse;
+        iCoverClient->BufStream().WriteInt32L(count);
+#endif
+
+        // Save in reverse order so order of notifications with identical priority remains
+        for (TInt ii = count - 1; ii >= 0; ii--)
+            {
+            TSoftNoteEntry& entry = (*iSoftNoteEntryList)[ii];
+            SaveNoteL(file, entry);
+
+#ifdef __COVER_DISPLAY
+            if (entry.iType == EShowGroupedNotification)
+                {
+                groupedExists = ETrue;
+                }
+            
+            iCoverClient->BufStream().WriteInt32L(entry.iType);
+            iCoverClient->BufStream().WriteInt32L(entry.iCount);
+#endif
+            };
+
+#ifdef __COVER_DISPLAY
+
+        TUint8 customsWCoverDataCount( 0 );
+        // we don't have actual count of custom params (nor ones with secondary display data..)
+        for (CCustomNotifParams* params = iCustomNoteParamsStack; params; params = params->iNext)
+            {
+            if (params->iParamData->iSecondaryDisplayData)
+                {
+                customsWCoverDataCount++;
+                }
+            }                
+            
+        iCoverClient->BufStream().WriteInt8L(customsWCoverDataCount);
+        if (customsWCoverDataCount)
+            {
+            for (CCustomNotifParams* params = iCustomNoteParamsStack; params; params = params->iNext)
+                {
+                if (params->iParamData->iSecondaryDisplayData)
+                    {
+                    iCoverClient->BufStream() << *params->iParamData->iSecondaryDisplayData;
+                    }
+                }
+            }
+
+        if (groupedExists)
+            {
+            iCoverClient->BufStream().WriteInt32L(EMissedCallsNotification);
+            iCoverClient->BufStream().WriteInt32L(iSoftNotificationAmounts[EMissedCallsNotification]);
+            iCoverClient->BufStream().WriteInt32L(ENewMessagesNotification);
+            iCoverClient->BufStream().WriteInt32L(iSoftNotificationAmounts[ENewMessagesNotification]);
+            iCoverClient->BufStream().WriteInt32L(EChatMessageNotification);
+            iCoverClient->BufStream().WriteInt32L(iSoftNotificationAmounts[EChatMessageNotification]);
+            iCoverClient->BufStream().WriteInt32L(ENewMailNotification);
+            iCoverClient->BufStream().WriteInt32L(iSoftNotificationAmounts[ENewMailNotification]);
+            }
+
+        iCoverClient->BufStream().CommitL();
+        iCoverClient->IssueCommand();
+#endif
+        CleanupStack::PopAndDestroy();  // close file
+        iNotificationsSaved = ETrue;
+        }
+    }
+
+
+void CAknSoftNotificationSubject::SaveNoteL(RWriteStream& aFile, TSoftNoteEntry& aEntry)
+    {
+    TInt plural = aEntry.iCount;
+    const TDesC& text = iGlobalNoteController->NoteText(aEntry.iId);
+
+#ifdef _DEBUG
+    _LIT(KDmsg, "AknSoftNotificationPlugin,SaveNoteL:type %d,NoteId %d, count %d ");
+    RDebug::Print(KDmsg, aEntry.iType, aEntry.iId, plural);
+#endif
+
+    switch (aEntry.iType)
+        {
+        case ENetworkInformationNotification:
+        case EUnstructuredSSDataNotification:
+            aFile.WriteUint8L(aEntry.iType);
+            aFile << text;
+            break;
+        case ESelectNetworkNotification:
+            aFile.WriteUint8L(aEntry.iType);
+            break;
+        case ESeparateVoiceMailOnLine1Notification:
+        case ESeparateVoiceMailOnLine2Notification:
+        case ECellBroadcastNotification:
+        case EVoiceMailNotification:
+        case EMissedCallsNotification:
+        case ENewMessagesNotification:
+        case ENewMailNotification:
+        case EChatMessageNotification:
+            aFile.WriteUint8L(aEntry.iType);
+            aFile.WriteInt32L(plural);
+            break;
+        case EShowGroupedNotification:
+            aFile.WriteUint8L(aEntry.iType);
+            aFile.WriteInt32L(iSoftNotificationAmounts[EMissedCallsNotification]);
+            aFile.WriteInt32L(iSoftNotificationAmounts[ENewMessagesNotification]);
+            aFile.WriteInt32L(iSoftNotificationAmounts[EChatMessageNotification]);
+            aFile.WriteInt32L(iSoftNotificationAmounts[ENewMailNotification]);
+            break;
+        case ECustomSoftNotification:
+            {
+            CCustomNotifParams* params = 0;
+            if (aEntry.iId != 0 )
+                {
+                params = SeekCustomNoteForId(aEntry.iId,ETrue);
+                }
+            else
+                {
+                params = SeekCustomNoteForId(aEntry.iCustomId);
+                }
+
+            if ( params )
+                {
+                aFile.WriteUint8L(aEntry.iType);
+                aFile.WriteInt16L(params->iCount);
+                aFile << *params;
+                }
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+void CAknSoftNotificationSubject::LoadAndQueueSoftNotesL()
+    {
+    if ( !iNotificationsSaved )
+        {
+        return;
+        }
+
+    RFs& fs = CEikonEnv::Static()->FsSession();
+    RFileReadStream file;
+
+    TInt err = file.Open(fs, KAknSNFilename, EFileRead);
+    if ( err != KErrNone )
+        {
+        iNotificationsSaved =EFalse;
+        User::Leave(err);
+        }
+
+    CleanupClosePushL(file);
+
+    TInt count = file.ReadInt32L();
+
+    if ( count > 0 )
+        {
+        ClearAllNotes();
+        }
+
+    for (TInt ii=0; ii<count; ii++)
+        {
+        LoadAndQueueNoteL(file);
+        }
+
+    iNotificationsSaved = EFalse;
+
+    if ( iSoftNotificationAmounts[EMissedCallsNotification] )
+        {
+        SetNcnFlag(ETrue);
+        }
+
+    CleanupStack::PopAndDestroy();  // close file
+    }
+
+void CAknSoftNotificationSubject::LoadAndQueueNoteL(RReadStream& aStream)
+    {
+    TAknSoftNotificationType type = STATIC_CAST(TAknSoftNotificationType, aStream.ReadUint8L());
+    TInt count = 1;
+    TBuf<200> text;
+    switch (type)
+        {
+        case ENetworkInformationNotification:
+        case EUnstructuredSSDataNotification:
+            aStream >> text;
+            break;
+        case ESeparateVoiceMailOnLine1Notification:
+        case ESeparateVoiceMailOnLine2Notification:
+        case ECellBroadcastNotification:
+        case EVoiceMailNotification:
+        case EMissedCallsNotification:
+        case ENewMessagesNotification:
+        case ENewMailNotification:
+        case EChatMessageNotification:
+            count = aStream.ReadInt32L();
+            break;
+        case EShowGroupedNotification:
+            iSoftNotificationAmounts[EMissedCallsNotification] = aStream.ReadInt32L();
+            iSoftNotificationAmounts[ENewMessagesNotification] = aStream.ReadInt32L();
+            iSoftNotificationAmounts[EChatMessageNotification] = aStream.ReadInt32L();
+            iSoftNotificationAmounts[ENewMailNotification]     = aStream.ReadInt32L();
+            break;
+        case ECustomSoftNotification:
+            {
+            count = aStream.ReadInt16L();
+            AddNewCustomNoteL(aStream, count);
+            if( iCustomNoteParamsStack )
+                {
+                TPtrC customTxt( iCustomNoteParamsStack->CustomText( count, EFalse ) );
+                if( customTxt.Length() > 0 )
+                    {
+                    text.Copy( customTxt.Left( text.MaxLength() ) );
+                    }
+                }            
+            }
+        default:
+            break;
+        }
+
+#ifdef _DEBUG
+    _LIT(KDmsg, "AknSoftNotificationPlugin,LoadNoteL:type %d, count %d ");
+    RDebug::Print(KDmsg,type, count);
+#endif
+
+    if (type != EShowGroupedNotification)
+        {
+        TBool countChanged = ( iSoftNotificationAmounts[type] != count );
+        iSoftNotificationAmounts[type] = count;
+        UpdateNoteL(type, text, count, countChanged);
+        }
+    else
+        {
+        ScheduleGroupedNotifierL();
+        }
+    }
+
+
+TBool CAknSoftNotificationSubject::CheckIfAlreadyExists(TAknSoftNotificationType aType)
+    {
+    TInt count = iSoftNoteEntryList->Count();
+    for (TInt ii=count-1; ii>=0; ii--)
+        {
+        TSoftNoteEntry& entry = (*iSoftNoteEntryList)[ii];
+        if (entry.iType == aType)
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+
+TBool CAknSoftNotificationSubject::AutoLockEnabled()
+    {
+    return EFalse;
+    }
+
+void CAknSoftNotificationSubject::AddNewCustomNoteL(
+    RReadStream& readStream, TInt aCount, TBool aNewNote )
+    {
+    AddNewCustomNoteL((RDesReadStream&)readStream, aCount, aNewNote );
+    }
+
+
+void CAknSoftNotificationSubject::AddNewCustomNoteL(
+    RDesReadStream& readStream, TInt aCount, TBool aNewNote )
+    {
+    // Before adding, check if there is a note of this type
+    CCustomNotifParams* next = new (ELeave) CCustomNotifParams;
+    CleanupStack::PushL( next );
+    readStream >> *next;
+    CCustomNotifParams* existing = SeekCustomNoteForId(next->iParamData->iNoteResourceId,EFalse);
+    if ( existing )
+        {
+        existing->iCount = aCount;
+        CleanupStack::PopAndDestroy( next );
+        return;
+        }
+
+    // do the switch (append new entry to stack)    
+    next->iNext = iCustomNoteParamsStack;
+    iCustomNoteParamsStack = next;
+    CleanupStack::Pop();
+
+    if( next->iParamType == KAknSoftNotificationDynamic )
+        {
+        if( aNewNote )
+            {
+            // if new note, then generate new id
+            next->iDynamicData->SetId( GenerateUniqueId() );
+            }
+        next->iId = next->iDynamicData->Id();
+        next->iHasViewInfo = ( KNullViewId != next->iDynamicData->ViewId() );
+        next->iCount = aCount;
+        next->iNoteId = KErrNotFound;
+        next->iSupportsGroupedform = ( 
+            next->iDynamicData->SingularLabelGroup().Length() > 0 ||
+            next->iDynamicData->PluralLabelGroup().Length() > 0 );
+        }
+    else // default
+        {
+        iCustomNoteParamsStack->iId = iCustomNoteParamsStack->iParamData->iNoteResourceId;
+        
+        iCustomNoteParamsStack->iHasViewInfo = ( 
+            KNullViewId != iCustomNoteParamsStack->iParamData->iViewId);
+            
+        iCustomNoteParamsStack->iCount = aCount;
+        iCustomNoteParamsStack->iNoteId = KErrNotFound;
+        
+        iCustomNoteParamsStack->iSupportsGroupedform = 
+            (iCustomNoteParamsStack->iParamData->iGroupedTextResourceId != 0);
+        }
+    }
+
+CCustomNotifParams* CAknSoftNotificationSubject::SeekCustomNoteForId(TInt aID, TBool aSeekByGNoteId)
+    {
+    CCustomNotifParams* params = iCustomNoteParamsStack;
+
+    for (;params && (aID != (aSeekByGNoteId?params->iNoteId:params->iId));)
+        {
+        params = params->iNext;
+        }
+
+    return params;
+    }
+
+
+void CAknSoftNotificationSubject::RemoveCustomNoteForId(TInt aID, TBool aSeekByGNoteId)
+    {
+    CCustomNotifParams* params = iCustomNoteParamsStack;
+
+    if ( !params )
+        {
+        return;
+        }
+
+    if ( aSeekByGNoteId )
+        {
+        RemoveByType(ECustomSoftNotification, aID);
+        }
+    else
+        { // just remove entry from list
+        TInt count = iSoftNoteEntryList->Count();
+        for (TInt ii=0; ii<count; ii++)
+            {
+            if ( iSoftNoteEntryList->At(ii).iCustomId == aID )
+                {
+                iSoftNoteEntryList->Delete(ii);
+                break;
+                }
+            }
+        }
+
+    if ( aID == (aSeekByGNoteId?params->iNoteId:params->iId)) // Remove first note on stack
+        {
+        iCustomNoteParamsStack = params->iNext;
+        delete params;
+
+        if (!iCustomNoteParamsStack)
+            {
+            iSoftNotificationAmounts[ECustomSoftNotification] = 0;
+            }
+
+        return;
+        }
+
+
+    for (;params->iNext && (aID != (aSeekByGNoteId?params->iNext->iNoteId:params->iNext->iId));)
+        {
+        params = params->iNext;
+        }
+
+    if ( params->iNext ) // Found previous item
+        {
+        CCustomNotifParams* tmp = params->iNext;
+        params->iNext = tmp->iNext;
+        delete tmp;
+        }
+
+    if (!iCustomNoteParamsStack)
+        {
+        iSoftNotificationAmounts[ECustomSoftNotification] = 0;
+        }
+    }
+
+void CAknPrivateSoftNoteParameters::InternalizeL( RReadStream& aStream )
+    {
+    delete iResourceFile;
+    iResourceFile = 0;
+    TInt length = aStream.ReadInt32L();
+    if ( length )
+        {
+        iResourceFile = HBufC::NewL(length);
+        TPtr resptr( iResourceFile->Des() );
+        aStream >> resptr;
+        }
+
+    iNoteResourceId = aStream.ReadInt32L();
+    iPriority = aStream.ReadInt32L();
+    iSoftkeys = aStream.ReadInt32L();
+    iTone = (CAknNoteDialog::TTone)aStream.ReadInt32L();
+
+    iViewId.iAppUid = TUid::Uid(aStream.ReadUint32L());
+    iViewId.iViewUid = TUid::Uid(aStream.ReadUint32L());
+    iCustomMessageId = TUid::Uid(aStream.ReadUint32L());
+    iAcceptSoftKey = aStream.ReadInt32L();
+
+    iPluralViewId.iAppUid = TUid::Uid(aStream.ReadUint32L());
+    iPluralViewId.iViewUid = TUid::Uid(aStream.ReadUint32L());
+    iGroupedTextResourceId = aStream.ReadInt32L();
+
+    delete iViewActivationMsg;
+    iViewActivationMsg = 0;
+    length = aStream.ReadInt32L();
+    if ( length != KErrNotFound )
+        {
+        iViewActivationMsg = HBufC8::NewL(length);
+        TPtr8 ptr( iViewActivationMsg->Des() );
+        aStream >> ptr;
+        }
+    
+    delete iSecondaryDisplayData;
+    iSecondaryDisplayData = 0;
+        
+    if (aStream.ReadInt8L()) // item has secondary display data
+        {
+        iSecondaryDisplayData = new (ELeave) CAknSDData();
+        aStream >> *iSecondaryDisplayData;
+        }
+    }
+
+void CAknPrivateSoftNoteParameters::ExternalizeL( RWriteStream& aStream ) const
+    {
+    aStream.WriteInt32L(iResourceFile->Length());
+    aStream << (*iResourceFile);
+    aStream.WriteInt32L(iNoteResourceId);
+    aStream.WriteInt32L(iPriority);
+    aStream.WriteInt32L(iSoftkeys);
+    aStream.WriteInt32L(iTone);
+    aStream.WriteUint32L(iViewId.iAppUid.iUid);
+    aStream.WriteUint32L(iViewId.iViewUid.iUid);
+    aStream.WriteUint32L(iCustomMessageId.iUid);
+    aStream.WriteInt32L(iAcceptSoftKey);
+
+    aStream.WriteUint32L(iPluralViewId.iAppUid.iUid);
+    aStream.WriteUint32L(iPluralViewId.iViewUid.iUid);
+    aStream.WriteUint32L(iGroupedTextResourceId);
+
+    if ( iViewActivationMsg ) // optional
+        {
+        aStream.WriteInt32L(iViewActivationMsg->Length());
+        aStream << (*iViewActivationMsg);
+        }
+    else
+        {
+        aStream.WriteInt32L(KErrNotFound);
+        }
+    
+    if (iSecondaryDisplayData)
+        {
+        aStream.WriteInt8L(ETrue);
+        aStream << *iSecondaryDisplayData;
+        }
+    else
+        {
+        aStream.WriteInt8L(EFalse);            
+        }
+    }
+
+void CAknSoftNotificationSubject::LaunchNewIMAppL()
+    {
+    LaunchViewL( KChatSpecificView, TUid::Uid(42), KNullDesC8() );
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::LoadUniqueIdL
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::LoadUniqueIdL()
+    {
+    RFs& fs( CEikonEnv::Static()->FsSession() );
+
+    RFileReadStream file;
+    User::LeaveIfError( file.Open( fs, KAknDynamicIdFilename, EFileRead ) );
+
+    file.PushL();
+    iUniqueIdCounter = file.ReadInt32L();
+    CleanupStack::PopAndDestroy( &file );
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::StoreUniqueIdL
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::StoreUniqueIdL()
+    {
+    RFs& fs( CEikonEnv::Static()->FsSession() );
+
+    RFileWriteStream file;
+    TInt err = file.Replace( fs, KAknDynamicIdFilename, EFileWrite );
+
+    if( err == KErrPathNotFound )
+        {
+        // folder not found -> create it
+        User::LeaveIfError( fs.MkDirAll( KAknDynamicIdFilename ) );
+        User::LeaveIfError( file.Create( fs, KAknDynamicIdFilename, EFileWrite ) );
+        }
+    else
+        {
+#ifdef _DEBUG
+        if( err )
+            {
+            _LIT(KDmsg, "AknSoftNotificationPlugin,StoreUniqueIdL: error %d");
+            RDebug::Print( KDmsg, err);
+            }
+#endif        
+        User::LeaveIfError( err );
+        }
+
+    file.PushL();
+    file.WriteInt32L( iUniqueIdCounter );
+    file.CommitL();
+    CleanupStack::PopAndDestroy( &file );
+    }
+
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::GenerateUniqueId
+// ---------------------------------------------------------
+//
+TInt CAknSoftNotificationSubject::GenerateUniqueId()
+    {
+    TInt failsafe = KMaxTInt; // prevent infinite loop
+    while( failsafe ) // loop until found or failsafe expires
+        {
+        // try next id. Disallow values below KMinimumUniqueId.
+        iUniqueIdCounter = Max( KMinimumUniqueId, iUniqueIdCounter + 1 );
+        
+        // go through existing notes and verify that the id is not used
+        CCustomNotifParams* params = iCustomNoteParamsStack;
+        while( params && params->iId != iUniqueIdCounter )
+            {
+            params = params->iNext;
+            }
+        
+        if( !params )
+            {
+            // Unique id found
+            break;
+            }
+        
+        --failsafe;
+        }
+    
+    // Store new id always when it has changed. We can't do anything if the
+    // saving fails, so we just ignore the error. 
+    TRAPD( err, StoreUniqueIdL() );
+    if( err )
+        {
+#ifdef _DEBUG
+        _LIT(KDmsg, "AknSoftNotificationPlugin,GenerateUniqueId: save error %d");
+        RDebug::Print( KDmsg, err );
+#endif //_DEBUG    
+        }
+    
+    return iUniqueIdCounter;
+    }
+
+// ---------------------------------------------------------
+// CAknSoftNotificationSubject::WriteResponse
+// ---------------------------------------------------------
+//
+void CAknSoftNotificationSubject::WriteResponse( 
+    TDes8& aResponse, TInt aNoteId ) const
+    {
+    TPckg<TInt> response( aNoteId );
+    aResponse.Copy( response.Left( aResponse.MaxLength() ) );
+    }
+
+//  End of File