applicationinterworkingfw/ServiceHandler/src/AiwServiceHandlerImpl.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/applicationinterworkingfw/ServiceHandler/src/AiwServiceHandlerImpl.cpp	Tue Feb 02 01:00:49 2010 +0200
@@ -0,0 +1,1853 @@
+/*
+* Copyright (c) 2003-2005 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:     Implements API for consumer application to access Application
+*                Interworking Framework. 
+*
+*/
+
+
+
+
+#include <eikenv.h>
+#include <aiwservicehandler.rsg>
+#include <EIKON.HRH>
+#include "AiwMenuBinding.h"
+#include "AiwServiceHandlerImpl.h"
+#include "AiwMenu.h"
+#include "AiwUids.hrh"
+#include "AiwCommon.hrh"
+#include "AiwMenuSlot.hrh"
+#include "AiwEcomMonitor.h"
+#include "AiwTlsData.h"
+#include "data_caging_path_literals.hrh"
+
+// CONSTANTS
+// Max number of empty menu resource slots.
+const TInt KMaxMenuResources = 16;
+
+// This value tells how many times consumer can call InitializeMenuPaneL() without 
+// closing the Options-menu.
+const TInt KMaxPaneIds = KMaxMenuResources;
+
+// The range reserved for individual menu pane.
+const TInt KIndividualMenuPaneIdRange = 10000;
+
+// The whole range that is reserved to all menu panes. Currently value is 170 000.
+const TInt KMenuPaneCommandRange = (KMaxMenuResources + 1) * KIndividualMenuPaneIdRange; 
+
+_LIT(KAiwResourceFile, "AiwServiceHandler.rSC");
+_LIT(KAiwZDrive, "z:");
+
+const TInt KMaxMenuTitleSize = 100;
+
+// Command id space reserved for single placeholder.
+const TInt KPlaceholderCmdIdRange = 200;
+
+void Cleanup(TAny* aAny);
+void InterestCleanup(TAny* aAny);
+void IntArrayCleanup(TAny* aAny);
+void FilteredCleanup(TAny* aAny);
+
+
+//
+// AiwServiceHandler
+//
+
+CAiwServiceHandlerImpl* CAiwServiceHandlerImpl::NewL()
+    {
+    CAiwServiceHandlerImpl* handler = new (ELeave) CAiwServiceHandlerImpl();
+    CleanupStack::PushL( handler );
+    handler->ConstructL();
+    CleanupStack::Pop(); // handler
+    return handler;
+    }
+
+
+
+CAiwServiceHandlerImpl::CAiwServiceHandlerImpl()
+    {
+    // Nothing to do here.
+    }
+
+
+
+void CAiwServiceHandlerImpl::ConstructL()
+    {
+    TFileName resFile;
+
+    TCallBack callBack(SynchronizeCallBack, this);
+    iEcomMonitor = CAiwEcomMonitor::NewL(callBack);
+
+    resFile.Copy(KAiwZDrive);
+    resFile.Append(KDC_RESOURCE_FILES_DIR);
+    resFile.Append(KAiwResourceFile);
+
+    iCoeEnv = CCoeEnv::Static();
+    
+    // A Service Handler instance can be created also when CCoeEnv is not 
+    // available (e.g. from server applications). In this case, the methods 
+    // needing CCoeEnv/CEikonEnv will leave with KErrNotSupported.
+    if(iCoeEnv)
+        {
+        iResourceOffset = iCoeEnv->AddResourceFileL(resFile);
+        }
+
+    // CAiwTlsData has a reference count so each OpenL call
+    // must have a matching Close call (done in destructor).
+    // OpenL is called only here, the TLS data object can be
+    // referenced by calling CAiwTlsData::Instance().
+    CAiwTlsData* data = CAiwTlsData::OpenL();
+    iTlsDataOpened = ETrue;
+
+    // CEikMenuPane informs all menu launch observers
+    // when an options menu is launched.
+    data->AddMenuLaunchObserverL( this );
+    }
+
+
+
+CAiwServiceHandlerImpl::~CAiwServiceHandlerImpl()
+    {
+    if (iResourceOffset && iCoeEnv)
+        {
+        iCoeEnv->DeleteResourceFile(iResourceOffset);
+        }
+    Reset();
+
+    delete iEcomMonitor;
+
+    if ( iTlsDataOpened )
+        {
+        CAiwTlsData* data = CAiwTlsData::Instance();
+        data->RemoveMenuLaunchObserver( this );
+        CAiwTlsData::Close();
+        }
+    }
+
+
+
+void CAiwServiceHandlerImpl::Reset()
+    {
+    iInterestList.ResetAndDestroy();
+    iMenuBindings.ResetAndDestroy();
+    iBaseBindings.ResetAndDestroy();
+    iProviders.ResetAndDestroy();
+
+    iLastInitialized.Reset();
+
+    iMenuPanes.ResetAndDestroy();
+
+    delete iInParams;
+    iInParams = NULL;
+    delete iOutParams;
+    iOutParams = NULL;
+    }
+
+
+
+void CAiwServiceHandlerImpl::ListProvidersForCriteriaL(RArray<TInt>& aResult, 
+    CAiwCriteriaItem& aItem)
+    {
+    TInt i;
+
+    for (i = 0; i < iProviders.Count(); i++)
+        {   
+        if (iProviders[i]->HasCriteria(aItem))
+            {
+            User::LeaveIfError(aResult.Append(iProviders[i]->ImplementationUid().iUid));
+            }
+        }
+    }
+
+
+
+TInt CAiwServiceHandlerImpl::NbrOfProviders(const CAiwCriteriaItem* aCriteria)
+    {
+    if(!aCriteria)
+        {
+        return 0;
+        }
+    
+    TInt i, j;
+
+    for (i = 0; i < iBaseBindings.Count(); i++)
+        {
+        for (j = 0; j < iBaseBindings[i]->Interest().Count(); j++)
+            {
+            if ((*iBaseBindings[i]->Interest()[j]) == (*aCriteria))
+                {
+                return iBaseBindings[i]->NumberOfProviders();
+                }
+            }
+        }
+
+    for (i = 0; i < iMenuBindings.Count(); i++)
+        {
+        for (j = 0; j < iMenuBindings[i]->Interest().Count(); j++)
+            {
+            if ((*iMenuBindings[i]->Interest()[j]) == (*aCriteria))
+                {
+                return iMenuBindings[i]->NumberOfProviders();
+                }
+            }       
+        }
+
+    return 0;
+    }
+
+
+
+void CAiwServiceHandlerImpl::AttachL(TInt aInterestResourceId)
+    {
+    // CCoeEnv/CEikonEnv needs to be accessible.
+    if(!iCoeEnv)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    
+    RCriteriaArray interest, filtered;
+
+    CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+    CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+
+    TResourceReader reader;
+    iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+    ReadInterestListL(reader, interest);
+    CleanupStack::PopAndDestroy(); // reader
+
+    FilterInterestListL(interest, filtered);
+    
+    DoAttachL(filtered);
+
+    filtered.Reset();
+
+    CleanupStack::Pop(); // filtered
+    CleanupStack::Pop(); // interest
+    }
+
+
+
+void CAiwServiceHandlerImpl::AttachL(const RCriteriaArray& aInterest)
+    {
+    RCriteriaArray interest, filtered;
+    
+    CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+    CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+        
+    for(TInt i = 0; i < aInterest.Count(); i++)
+        {
+        CAiwCriteriaItem* item = CAiwCriteriaItem::NewLC();
+        
+        item->SetId(               aInterest[i]->Id()                    );
+        item->SetServiceCmd(       aInterest[i]->ServiceCmd()            );
+        item->SetContentTypeL(     aInterest[i]->ContentType()           );
+        item->SetServiceClass(     aInterest[i]->ServiceClass()          );
+        item->SetOptions(          aInterest[i]->Options()               );
+        item->SetDefaultProvider( (aInterest[i]->DefaultProvider()).iUid );
+        item->SetMaxProviders(     aInterest[i]->MaxProviders()          );       
+        
+        User::LeaveIfError(interest.Append(item));
+        CleanupStack::Pop(item); 
+        }
+        
+    FilterInterestListL(interest, filtered);        
+
+    DoAttachL(filtered);
+
+    filtered.Reset();
+
+    CleanupStack::Pop(); // filtered
+    CleanupStack::Pop(); // interest
+    }
+
+
+
+void CAiwServiceHandlerImpl::DoAttachL(const RCriteriaArray& aInterest)
+    {
+    CAiwBinding* bind;
+    for (TInt i = 0; i < aInterest.Count(); i++)
+        {
+        bind = CAiwBinding::NewLC();
+        
+        if (ResolveProvidersL(bind, aInterest[i]))
+            {
+            User::LeaveIfError(iBaseBindings.Append( bind ));
+            CleanupStack::Pop(); // bind
+            bind->AddCriteriaL(aInterest[i]);
+
+            // Initialise providers.
+            for (TInt k = 0; k < bind->NumberOfProviders(); k++)
+                {
+                // Trap the initialisation. If not done, a leaving provider
+                // could prevent the initialisation of other providers.
+                TRAPD(err, bind->BaseProvider(k)->InitialiseL(*this, bind->Interest()));
+                if(err)
+                    {
+#ifdef _DEBUG                    
+                    RDebug::Print(_L("AIW PROVIDER ERROR: CAiwServiceIfBase::InitialiseL() failed, leave code:%d"), err);
+#endif                    
+                    }
+                }
+            }
+        else
+            {
+            CleanupStack::PopAndDestroy(); // bind
+            }
+        }
+    }
+
+
+void CAiwServiceHandlerImpl::GetInterest(RCriteriaArray& aInterest)
+    {
+    for (TInt i = 0; i < iInterestList.Count(); i++)
+        {
+        if (aInterest.Append(iInterestList[i]) != KErrNone)
+            {
+            return;
+            }
+        }
+    }
+    
+    
+
+void CAiwServiceHandlerImpl::DetachL(const RCriteriaArray& aInterest)
+    {
+    // First, remove relevant criteria items from relevat base bindings.
+    for (TInt i = 0; i < aInterest.Count(); i++)
+        {
+        for (TInt j = 0; j < iBaseBindings.Count(); j++)
+            {
+            TInt index = iBaseBindings[j]->HasCriteriaItem(*aInterest[i]);
+            if (index != KErrNotFound)
+                {
+                iBaseBindings[j]->RemoveCriteria(index);
+                }                           
+            }
+        }
+
+    // Second pass removes empty bindings.
+    for (TInt i = 0; i < iBaseBindings.Count(); i++)
+        {
+        if (iBaseBindings[i]->Interest().Count() == 0)
+            {
+            delete iBaseBindings[i];
+            iBaseBindings.Remove(i);
+            i--;
+            }
+        }
+
+    // Then check if there were left obselete criteria items and remove them.   
+    RemoveObsoleteCriteriaItems();
+    
+    // Finally check if there were left obselete providers and remove them.
+    RemoveObsoleteProviders();        
+    }
+
+
+
+void CAiwServiceHandlerImpl::DetachL(TInt aInterestResourceId)
+    { 
+    // CCoeEnv/CEikonEnv needs to be accessible.
+    if(!iCoeEnv)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    
+    RCriteriaArray interest;
+
+    CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+
+    TResourceReader reader;
+    iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+    ReadInterestListL(reader, interest);
+    CleanupStack::PopAndDestroy(); // reader
+
+    DetachL( interest );
+
+    interest.ResetAndDestroy();
+    CleanupStack::Pop(); // interest
+    }
+
+
+const CAiwCriteriaItem* CAiwServiceHandlerImpl::GetCriteria(TInt aId)
+    {
+    for (TInt i = 0; i < iInterestList.Count(); i++)
+        {
+        if (iInterestList[i]->Id() == aId)
+            {
+            return iInterestList[i];
+            }
+        }
+
+    return NULL;  
+    }
+    
+TInt CAiwServiceHandlerImpl::NumAlreadyInitializedPaneIdsL() const
+    {
+    TInt ret = 0;
+    TInt paneIds[KMaxPaneIds] = {0};
+    TBool found = EFalse;
+    
+    for (TInt i = 0; i < iLastInitialized.Count(); i++)
+        {
+        found = EFalse;
+        
+        for (TInt j = 0; j < ret; j++)
+            {
+            if (iLastInitialized[i]->MenuResourceId() == paneIds[j])
+                {
+                found = ETrue;
+                break;              
+                }
+            }
+                
+        if (!found) 
+            {
+            // Create new item.
+            if (ret >= KMaxPaneIds)
+                {
+#ifdef _DEBUG
+                RDebug::Print(_L("ERROR: OVERFLOW in CAiwServiceHandlerImpl::NumAlreadyInitializedPaneIdsL()"));
+#endif
+                User::Leave(KErrOverflow);
+                }
+            paneIds[ret] = iLastInitialized[i]->MenuResourceId();
+            ret++;
+            }                       
+        }
+    return ret;         
+    }    
+
+void CAiwServiceHandlerImpl::InitializeMenuPaneL(
+    CEikMenuPane& aMenuPane,
+    TInt aMenuResourceId, 
+    TInt aBaseMenuCmdId,
+    const CAiwGenericParamList& aInParamList)
+    {
+    InitializeMenuPaneL(aMenuPane, aMenuResourceId, aBaseMenuCmdId, 
+        aInParamList, EFalse, EFalse);    
+    }        
+        
+void CAiwServiceHandlerImpl::InitializeMenuPaneL(
+    CEikMenuPane& aMenuPane,
+    TInt aMenuResourceId, 
+    TInt aBaseMenuCmdId,
+    const CAiwGenericParamList& aInParamList,
+    TBool aUseSubmenuTextsIfAvailable)
+    {
+    InitializeMenuPaneL(aMenuPane, aMenuResourceId, aBaseMenuCmdId, aInParamList, aUseSubmenuTextsIfAvailable, EFalse);
+    }
+
+
+void CAiwServiceHandlerImpl::InitializeMenuPaneL(
+    CEikMenuPane& aMenuPane,
+    TInt aMenuResourceId, 
+    TInt aBaseMenuCmdId,
+    const CAiwGenericParamList& aInParamList,
+    TBool aUseSubmenuTextsIfAvailable,
+    TBool aSetAsItemSpecific)
+    {        
+    // CCoeEnv/CEikonEnv needs to be accessible.
+    if(!iCoeEnv)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    
+    if (!iMenuBindings.Count())
+        {
+        // Either no menu is attached to interest or menu was attached but
+        // it didn't contain any placeholders for criteria items. So
+        // nothing to do, get out.
+        return;
+        }
+
+    TInt index;
+    TInt slotcmd;
+    TBuf <KMaxMenuTitleSize> subTitle;
+    TBool titleLocked;
+    TInt paneOffset = NumAlreadyInitializedPaneIdsL() * KIndividualMenuPaneIdRange;
+
+    iSubmenuCmd = aBaseMenuCmdId + KMenuPaneCommandRange;
+    slotcmd = SlotItemCmd(aMenuPane);
+    if (slotcmd >= 0)
+        {
+        // aMenuPane is aiw submenu. At this point it is empty and we must
+        // copy provider menu items to it.
+        CAiwMenuPane* aiwPane = MenuPaneForSlotCmd(slotcmd);
+        if (aiwPane)
+            {
+            CopyMenuItemsL(aiwPane, aMenuPane, 0, ETrue, aSetAsItemSpecific);
+            aMenuPane.DeleteMenuItem(slotcmd);
+            iSubmenu = aiwPane;
+            }
+        }
+    else
+        {
+        iSubmenu = NULL;
+        
+        const TInt bindcount = iMenuBindings.Count();
+        for (TInt i = 0; i < bindcount; i++)
+            {
+            if  ((iMenuBindings[i]->MenuId() == aMenuResourceId) &&
+                (aMenuPane.MenuItemExists(iMenuBindings[i]->MenuCmd(), index)))
+                {
+                CAiwMenuPane* aiwPane = iMenuBindings[i]->MenuPane();
+                TInt menuResourceId = -1;
+                if(aiwPane)
+                    {
+                    // An AIW menu pane already exists (this means that a normal
+                    // non-AIW submenu with AIW items has been opened more than once). 
+                    // In this case we use the existing resource slot id.
+                    menuResourceId = aiwPane->ResourceSlotId();
+                    paneOffset = aiwPane->PaneOffset();
+                    DeleteAiwMenuPane(aiwPane);
+                    aiwPane = NULL;
+                    }
+                aiwPane = CreateEmptyAiwMenuPaneL(aBaseMenuCmdId, menuResourceId);
+                CleanupStack::PushL(aiwPane);
+                aiwPane->SetPaneOffset(paneOffset);
+                paneOffset += KPlaceholderCmdIdRange;
+                iMenuBindings[i]->SetMenuPane(aiwPane);     
+
+                // Clean previous service commands from list.
+                CAiwGenericParamList& list = const_cast<CAiwGenericParamList&>(aInParamList);
+                while (list.Remove(EGenericParamServiceCommand)) 
+                    {
+                    // Intentionally left empty.    
+                    }
+
+                // Add service commands for current placeholder.
+                const TInt icount = iMenuBindings[i]->Interest().Count();
+                for (TInt k = 0; k < icount; k++)
+                    {
+                    list.AppendL(TAiwGenericParam(EGenericParamServiceCommand,
+                        TAiwVariant(iMenuBindings[i]->Interest()[k]->ServiceCmd())));
+                    }
+
+                // Loop from last entry to first entry always inserting to same index.
+                // Default provider is the first item in list, so if there is a default
+                // provider defined, it will be the first one to appear in menus.               
+                for (TInt j = iMenuBindings[i]->NumberOfProviders() - 1; j >= 0; j--)
+                    {
+                    aiwPane->SetInitializingOwner(iMenuBindings[i]->MenuProvider(j));
+                    iMenuBindings[i]->MenuProvider(j)->InitializeMenuPaneHookL(aiwPane,
+                        0, 0, aInParamList);
+                    }
+
+                GetSubmenuTitle(aiwPane->MenuPane(), subTitle);
+            
+                TAiwPlaceholderType phtype = PlaceholderType(aMenuPane, 
+                    iMenuBindings[i]->MenuCmd(), titleLocked);
+
+                if ((phtype == EAiwPlaceholderCascade) ||
+                    (phtype == EAiwPlaceholderIntelligentCascade))
+                    {
+                    if (aiwPane->MenuPane().NumberOfItemsInPane() == 1)
+                        {
+                        // Remove placeholder item.
+                        aMenuPane.DeleteMenuItem(iMenuBindings[i]->MenuCmd());
+                        CleanupStack::PopAndDestroy(); // aiwPane
+                        continue;
+                        }
+                    else if ((aiwPane->MenuPane().NumberOfItemsInPane() == 2) &&
+                        (phtype == EAiwPlaceholderIntelligentCascade))
+                        {
+                        UnCascadeL(aMenuPane, iMenuBindings[i]->MenuCmd(), *aiwPane, aSetAsItemSpecific);
+                        User::LeaveIfError(iLastInitialized.Append(aiwPane));
+                        }
+                    else
+                        {
+                        if (titleLocked)
+                            {
+                            subTitle.Zero();
+                            }
+                        ConvertPlaceholderL(aMenuPane, iMenuBindings[i]->MenuCmd(), *aiwPane, 
+                            subTitle, aSetAsItemSpecific);
+                        }       
+                    }
+                else
+                    {
+                    // Remove placeholder item.
+                    aMenuPane.DeleteMenuItem(iMenuBindings[i]->MenuCmd());
+        
+                    // Copy menu items to actual menu pane
+                    CopyMenuItemsL(aiwPane, aMenuPane, index, aUseSubmenuTextsIfAvailable, aSetAsItemSpecific);
+                    
+                    User::LeaveIfError(iLastInitialized.Append(aiwPane));
+                    }
+                aiwPane->SetMenuResourceId(aMenuResourceId);
+                User::LeaveIfError(iMenuPanes.Append(aiwPane));
+                CleanupStack::Pop(); // aiwPane
+                }
+            }
+        }
+    }
+
+
+TInt CAiwServiceHandlerImpl::ServiceCmdByMenuCmd(TInt aMenuCmdId) const
+    {
+    for (TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        if ((IsInLastInitialized(iMenuBindings[i]->MenuPane())) &&
+            (iMenuBindings[i]->MenuPane()->IsCmdInRange(KPlaceholderCmdIdRange, aMenuCmdId)))
+            {
+            return iMenuBindings[i]->MenuPane()->ServiceCmdId(aMenuCmdId); 
+            }
+        }
+
+    return 0;   
+    }
+
+
+
+void CAiwServiceHandlerImpl::ExecuteMenuCmdL(
+    TInt aMenuCmdId,
+    const CAiwGenericParamList& aInParamList,
+    CAiwGenericParamList& aOutParamList,
+    TUint aCmdOptions,
+    MAiwNotifyCallback* aCallback)
+    {
+    // CCoeEnv/CEikonEnv needs to be accessible.
+    if(!iCoeEnv)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    
+    if (!iMenuBindings.Count())
+        {
+        return;
+        }   
+
+    // Handle real menu providers.
+    for (TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        CAiwMenuPane* menuPane = iMenuBindings[i]->MenuPane();
+
+        if (IsInLastInitialized(menuPane))
+            {
+            for (TInt j = 0; j < iMenuBindings[i]->NumberOfProviders(); j++)
+                {
+                if ((menuPane->IsCmdInRange(KPlaceholderCmdIdRange, aMenuCmdId)) && 
+                    (menuPane->CommandOwner(aMenuCmdId) == iMenuBindings[i]->MenuProvider(j)))
+                    {
+                    iMenuBindings[i]->MenuProvider(j)->HandleMenuCmdHookL(
+                        menuPane, 
+                        aMenuCmdId, 
+                        aInParamList, 
+                        aOutParamList, 
+                        aCmdOptions, 
+                        aCallback); 
+                    return;
+                    }
+                }
+            }
+        }
+    }
+
+
+
+void CAiwServiceHandlerImpl::AttachMenuL(TInt aMenuResourceId, TInt aInterestResourceId)
+    {
+    // CCoeEnv/CEikonEnv needs to be accessible.
+    if(!iCoeEnv)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    
+    RCriteriaArray interest, filtered;
+    TResourceReader reader;
+
+    CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+    CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+    iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+    ReadInterestListL(reader, interest);
+    CleanupStack::PopAndDestroy(); // reader
+    FilterInterestListL(interest, filtered);
+
+    iCoeEnv->CreateResourceReaderLC(reader, aMenuResourceId);
+    DoAttachMenuL(reader, aMenuResourceId, filtered);
+    filtered.Reset();
+    CleanupStack::PopAndDestroy(); // reader
+    CleanupStack::Pop(); // filtered
+    CleanupStack::Pop(); // interest
+    }
+
+
+
+void CAiwServiceHandlerImpl::AttachMenuL(TInt aMenuResourceId, TResourceReader& aReader)
+    {
+    // CCoeEnv/CEikonEnv needs to be accessible.
+    if(!iCoeEnv)
+        {
+        User::Leave(KErrNotSupported);
+        }
+    
+    RCriteriaArray interest, filtered;
+    TResourceReader reader;
+
+    CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+    CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+    ReadInterestListL(aReader, interest);
+    FilterInterestListL(interest, filtered);
+
+    iCoeEnv->CreateResourceReaderLC(reader, aMenuResourceId);
+    DoAttachMenuL(reader, aMenuResourceId, filtered);
+    filtered.Reset();
+    CleanupStack::PopAndDestroy(); // reader
+    CleanupStack::Pop(); // filtered
+    CleanupStack::Pop(); // interest
+    }
+
+
+void CAiwServiceHandlerImpl::AttachMenuL(TInt aMenuResourceId, const RCriteriaArray& aInterest)
+    {
+    // CCoeEnv/CEikonEnv needs to be accessible.
+    if(!iCoeEnv)
+        {
+        User::Leave(KErrNotSupported);
+        }    
+    
+    RCriteriaArray interest, filtered;
+    TResourceReader reader;
+    
+    CleanupStack::PushL( TCleanupItem( InterestCleanup, &interest ) );
+    CleanupStack::PushL( TCleanupItem( FilteredCleanup, &filtered ) );
+        
+    for(TInt i = 0; i < aInterest.Count(); i++)
+        {
+        CAiwCriteriaItem* item = CAiwCriteriaItem::NewLC();
+        
+        item->SetId(               aInterest[i]->Id()                    );
+        item->SetServiceCmd(       aInterest[i]->ServiceCmd()            );
+        item->SetContentTypeL(     aInterest[i]->ContentType()           );
+        item->SetServiceClass(     aInterest[i]->ServiceClass()          );
+        item->SetOptions(          aInterest[i]->Options()               );
+        item->SetDefaultProvider( (aInterest[i]->DefaultProvider()).iUid );
+        item->SetMaxProviders(     aInterest[i]->MaxProviders()          );       
+        
+        User::LeaveIfError(interest.Append(item));
+        CleanupStack::Pop(item); 
+        }
+        
+    FilterInterestListL(interest, filtered);        
+
+    iCoeEnv->CreateResourceReaderLC(reader, aMenuResourceId);
+    DoAttachMenuL(reader, aMenuResourceId, filtered);
+    filtered.Reset();
+    CleanupStack::PopAndDestroy(); // reader
+    CleanupStack::Pop(); // filtered
+    CleanupStack::Pop(); // interest    
+    }   
+
+
+void CAiwServiceHandlerImpl::DoAttachMenuL(TResourceReader& aReader, TInt aMenuId, 
+    RCriteriaArray& aInterest)
+    {
+    TInt menuCmd;
+    TInt count = aReader.ReadInt16();
+    TBool bound;
+
+    for (TInt i = 0; i < count; i++)
+        {
+        menuCmd = aReader.ReadInt32();
+        CAiwMenuBinding* bind = NULL;
+        bound = EFalse;
+
+        for (TInt j = 0; j < aInterest.Count(); j++)
+            {           
+            if (aInterest[j]->Id() == menuCmd)
+                {                       
+                if (!bind)
+                    {
+                    bind = AlreadyBound(aMenuId, menuCmd, i);
+                    if (!bind)
+                        {
+                        bind = CAiwMenuBinding::NewLC(i, aMenuId);
+                        bind->SetMenuCmd( menuCmd );
+                        }
+                    else
+                        {
+                        bound = ETrue;
+                        }
+                    }
+                
+                if (bind->HasCriteriaItem(*(aInterest[j])) == KErrNotFound)
+                    {
+                    ResolveProvidersL(bind, aInterest[j]);
+                    bind->AddCriteriaL(aInterest[j]);
+                    }
+                }
+            }
+
+        // Initialise providers.
+        if (bind)
+            {
+            for (TInt k = 0; k < bind->NumberOfProviders(); k++)
+                {
+                TRAPD(err, bind->MenuProvider(k)->InitialiseL(*this, bind->Interest()));
+                if(err)
+                    {
+#ifdef _DEBUG
+                    RDebug::Print(_L("AIW PROVIDER ERROR: CAiwServiceIfMenu::InitialiseL() failed, leave code:%d"), err);
+#endif                     
+                    // The provider failed to initialise.
+                    // Remove the failed provider from this menu binding.
+                    CAiwServiceIfMenu* provider = bind->MenuProvider(k);
+                    TInt implUid = provider->ImplementationUid().iUid;
+                    bind->RemoveProvider(implUid);
+                    
+                    // Remove the failed provider also from other menu bindings.
+                    for (TInt m = 0; m < iMenuBindings.Count(); m++)
+                        {
+                        iMenuBindings[m]->RemoveProvider(implUid);
+                        }
+
+                    // Then remove provider from the owner list and delete it.
+                    for (TInt m = 0; m < iProviders.Count(); m++)
+                        {
+                        if (iProviders[m]->ImplementationUid().iUid == implUid)
+                            {
+                            delete iProviders[m];
+                            iProviders.Remove(m);
+                            m--;
+                            }
+                        }                    
+                    }
+                }
+            if (!bound)
+                {
+                User::LeaveIfError(iMenuBindings.Append( bind ));
+                CleanupStack::Pop();  // bind                       
+                }
+            }
+        SkipMenuFields(aReader);  // Jump to next menu item
+        }
+    }
+
+
+void CAiwServiceHandlerImpl::ReadInterestL(RCriteriaArray& aInterest, TInt aInterestResourceId)
+    {
+    CleanupStack::PushL( TCleanupItem( InterestCleanup, &aInterest ) );
+    TResourceReader reader;
+    iCoeEnv->CreateResourceReaderLC(reader, aInterestResourceId);
+    ReadInterestListL(reader, aInterest);
+    CleanupStack::PopAndDestroy(); // reader
+    CleanupStack::Pop(&aInterest);
+    }
+
+
+void CAiwServiceHandlerImpl::DetachMenu(TInt aMenuResourceId, TInt aInterestResourceId)
+    {
+    // If interest resource id is null, then detach all items in the given menu.
+    if (!aInterestResourceId)
+        {
+        DoDetachMenu(aMenuResourceId);        
+        }
+    else
+        {
+        // CCoeEnv/CEikonEnv needs to be accessible.
+        if(!iCoeEnv)
+            {
+            // We cannot leave because this is a non-leaving method.
+            return; 
+            }    
+
+        RCriteriaArray interest;
+        TRAPD(err, ReadInterestL(interest, aInterestResourceId));
+        if (err)
+            {
+            return;
+            }
+        
+        DoDetachMenu(aMenuResourceId, interest);
+        
+        interest.ResetAndDestroy();
+        }
+    }
+        
+
+void CAiwServiceHandlerImpl::DoDetachMenu(TInt aMenuResourceId)
+    {
+    // First, delete the relevant menu bindings.
+    for (TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        if (iMenuBindings[i]->MenuId() == aMenuResourceId)
+            {
+            delete iMenuBindings[i];
+            iMenuBindings.Remove(i);
+            i--;
+            }
+        }
+
+    // Then check if there were left obselete criteria items and remove them.   
+    RemoveObsoleteCriteriaItems();
+    
+    // Finally check if there were left obselete providers and remove them.
+    RemoveObsoleteProviders();  
+    }
+
+    
+void CAiwServiceHandlerImpl::DoDetachMenu(TInt aMenuResourceId, RCriteriaArray& aInterest)
+    {
+    // First, remove relevant criteria items from relevant menu bindings.
+    for (TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        if (iMenuBindings[i]->MenuId() == aMenuResourceId) 
+            {
+            for (TInt j = 0; j < aInterest.Count(); j++)
+                {
+                TInt index = iMenuBindings[i]->HasCriteriaItem(*aInterest[j]);
+                if (index != KErrNotFound)
+                    {
+                    iMenuBindings[i]->RemoveCriteria(index);
+                    }
+                }
+            }
+        }
+
+    // Second pass removes empty bindings.
+    for (TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        if (iMenuBindings[i]->Interest().Count() == 0)
+            {
+            delete iMenuBindings[i];
+            iMenuBindings.Remove(i);
+            i--;
+            }
+        }
+    
+    // Then check if there were left obselete criteria items and remove them.   
+    RemoveObsoleteCriteriaItems();
+    
+    // Finally check if there were left obselete providers and remove them.
+    RemoveObsoleteProviders();        
+    }    
+    
+    
+void CAiwServiceHandlerImpl::RemoveObsoleteCriteriaItems()
+    {
+    for (TInt i = 0; i < iInterestList.Count(); i++)
+        {
+        CAiwCriteriaItem* criteria = iInterestList[i];
+        TBool found = EFalse;
+        
+        // Loop through base bindings.
+        for (TInt j = 0; j < iBaseBindings.Count(); j++)
+            {
+            if (iBaseBindings[j]->HasCriteriaItem(*criteria) != KErrNotFound)
+                {
+                found = ETrue;
+                break;
+                }
+            }
+
+        // If still not found, loop through menu bindings.        
+        if (!found)
+            {
+            for (TInt j = 0; j < iMenuBindings.Count(); j++)
+                {
+                if (iMenuBindings[j]->HasCriteriaItem(*criteria) != KErrNotFound)
+                    {
+                    found = ETrue;
+                    break;
+                    }
+                }            
+            }
+            
+        // Criteria item can be deleted if it was not found.            
+        if (!found)
+            {
+            delete iInterestList[i];
+            iInterestList.Remove(i);
+            i--;
+            }
+        }    
+    }
+    
+    
+void CAiwServiceHandlerImpl::RemoveObsoleteProviders()
+    {
+    for (TInt i = 0; i < iProviders.Count(); i++)
+        {
+        CAiwServiceIfBase* provider = iProviders[i];
+        TBool found = EFalse;
+        
+        // Loop through base bindings.
+        for (TInt j = 0; j < iBaseBindings.Count(); j++)
+            {
+            if (iBaseBindings[j]->HasProvider(provider))
+                {
+                found = ETrue;
+                break;
+                }
+            }
+
+        // If still not found, loop through menu bindings.        
+        if (!found)
+            {
+            for (TInt j = 0; j < iMenuBindings.Count(); j++)
+                {
+                if (iMenuBindings[j]->HasProvider(provider))
+                    {
+                    found = ETrue;
+                    break;
+                    }
+                }            
+            }
+            
+        // Criteria item can be deleted if it was not found.            
+        if (!found)
+            {
+            delete iProviders[i];
+            iProviders.Remove(i);
+            i--;
+            }
+        }    
+    }
+
+
+TBool CAiwServiceHandlerImpl::IsSubMenuEmpty(TInt aSubMenuId)
+    {
+    for (TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        if (iMenuBindings[i]->MenuId() == aSubMenuId)
+            {
+            if (iMenuBindings[i]->NumberOfProviders() > 0)
+                {
+                return EFalse;
+                }
+
+            return ETrue;
+            }
+        }
+
+    return EFalse;
+    }
+
+
+
+
+CAiwMenuBinding* CAiwServiceHandlerImpl::AlreadyBound(TInt aMenuId, TInt aMenuCmd, 
+    TInt aMenuItemIndex) const
+    {
+    for (TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        if ((iMenuBindings[i]->MenuId() == aMenuId) &&
+            (iMenuBindings[i]->MenuCmd() == aMenuCmd) &&
+            (iMenuBindings[i]->MenuItemIndex() == aMenuItemIndex))
+            {
+            return iMenuBindings[i];
+            }
+        }
+
+    return NULL;
+    }
+
+
+void CAiwServiceHandlerImpl::ExecuteServiceCmdL(
+    const TInt& aCmdId,
+    const CAiwGenericParamList& aInParamList,
+    CAiwGenericParamList& aOutParamList,
+    TUint aCmdOptions,
+    MAiwNotifyCallback* aCallback)
+    {
+    for (TInt i = 0; i < iBaseBindings.Count(); i++)
+        {
+        if(iBaseBindings[i]->HasServiceCmd(aCmdId))
+            {
+            for (TInt j = 0; j < iBaseBindings[i]->NumberOfProviders(); j++)
+                {
+                iBaseBindings[i]->BaseProvider(j)->HandleServiceCmdL(
+                    aCmdId,
+                    aInParamList, 
+                    aOutParamList, 
+                    aCmdOptions, 
+                    aCallback);
+                }
+            }
+        }
+    }
+
+
+
+void CAiwServiceHandlerImpl::ReadInterestListL(TResourceReader& aReader, 
+    RPointerArray<CAiwCriteriaItem>& aResult)  
+    {
+    const TInt count = aReader.ReadInt16();
+    for (TInt ii = 0; ii < count; ++ii)
+        {
+        CAiwCriteriaItem* item = CAiwCriteriaItem::NewLC();
+        item->ReadFromResoureL( aReader );
+        User::LeaveIfError(aResult.Append(item));
+        CleanupStack::Pop(); // item
+        }
+    }
+
+
+TInt CAiwServiceHandlerImpl::ResolveProvidersL(CAiwBinding* aBinding, CAiwCriteriaItem* aItem)
+    {
+    RImplInfoPtrArray infoArray;
+    TInt result = 0;
+
+    CleanupStack::PushL( TCleanupItem( Cleanup, &infoArray ) );
+
+    iEcomMonitor->ListImplemetationsL(infoArray, aItem);
+
+    FilterInfoArray(infoArray, aItem);
+
+    // First resolve for providers already in memory.
+    TInt i;
+    for (i = 0; i < iProviders.Count(); i++)
+        {
+        if (iProviders[i]->Match(aItem))
+            {
+            aBinding->AddProviderL((CAiwServiceIfBase*)iProviders[i], 
+                iProviders[i]->ImplementationUid() == aItem->DefaultProvider());          
+            result++;
+            }     
+        }
+
+    // If cached providers were found, then it means that all the matching
+    // providers must be already in memory. No need to query from ECom framework.
+    if (!result)
+        {
+        for (i = 0; i < infoArray.Count(); i++)
+            {
+            if ((aItem->Options() & AIW_OPTIONS_ROM_ONLY) && (infoArray[i]->RomBased() == EFalse))
+                {
+                continue;
+                }
+    
+    		CAiwServiceIfBase* iface = NULL;
+    		TRAP_IGNORE( iface = iEcomMonitor->CreateImplementationL(
+                infoArray[i]->ImplementationUid()) );
+ 			       
+            if (iface)
+                {
+                if (!IsCached(iface))
+                    {
+                    CleanupStack::PushL(iface);
+                    result++;
+                    iface->AddCriteria(aItem);
+                    User::LeaveIfError(iProviders.Append( iface ));
+                    CleanupStack::Pop(iface);
+                    
+                    aBinding->AddProviderL(iface, 
+                        infoArray[i]->ImplementationUid() == aItem->DefaultProvider());
+                    }                           
+                else    
+                    {
+                    delete iface;
+                    iface = NULL;                
+                    }
+                }
+            }
+        }
+
+    CleanupStack::PopAndDestroy(); // infoArray     
+
+    return result;
+    }
+
+
+
+void CAiwServiceHandlerImpl::FilterInfoArray(RImplInfoPtrArray& aArray, CAiwCriteriaItem* aItem)
+    {
+    if (aItem->MaxProviders() <= 0)
+        {
+        aArray.ResetAndDestroy();
+        }
+    else
+        {
+        while (aArray.Count() > aItem->MaxProviders())
+            {
+            // Skip default provider.
+            if (aArray[0]->ImplementationUid() == aItem->DefaultProvider())
+                {
+                delete aArray[1];
+                aArray.Remove(1);               
+                }
+            else
+                {
+                delete aArray[0];
+                aArray.Remove(0);               
+                }
+            }
+        }
+    }
+
+
+
+TBool CAiwServiceHandlerImpl::IsCached(CAiwServiceIfBase* /*aProvider*/)
+    {
+    return EFalse;
+    }
+
+
+CAiwGenericParamList& CAiwServiceHandlerImpl::InParamListL()
+    {
+    if (!iInParams)
+        {
+        iInParams = CAiwGenericParamList::NewL();
+        }
+    iInParams->Reset();
+    return *iInParams;
+    }
+
+
+
+CAiwGenericParamList& CAiwServiceHandlerImpl::OutParamListL()
+    {
+    if (!iOutParams)
+        {
+        iOutParams = CAiwGenericParamList::NewL();
+        }
+    iOutParams->Reset();
+    return *iOutParams;
+    }
+
+
+
+TBool CAiwServiceHandlerImpl::IsInLastInitialized(CAiwMenuPane* aiwPane) const
+    {
+    if (aiwPane)
+        {
+        if (iSubmenu == aiwPane)
+            {
+            return ETrue;       
+            }
+
+        for (TInt i = 0; i < iLastInitialized.Count(); i++)
+            {
+            if (iLastInitialized[i] == aiwPane)
+                {
+                return ETrue;
+                }
+            }
+        }
+
+    return EFalse;
+    }
+
+
+TInt CAiwServiceHandlerImpl::HandleNotifyL(
+    TInt /*aCmdId*/,
+    TInt /*aEventId*/,
+    CAiwGenericParamList& /*aEventParamList*/,
+    const CAiwGenericParamList& /*aInParamList*/)
+    {
+    return KErrNone;    
+    }
+
+
+// CEikMenuPane::ConstructFromresourceL is defined as 'protected' so
+// we have to use a wrapper class for accessing it.
+class CAiwMenuResource : public CEikMenuPane
+    {
+    public:
+        CAiwMenuResource() : CEikMenuPane(NULL) {}
+        CAiwMenuResource(MEikMenuObserver* aObserver) : CEikMenuPane(aObserver) {}
+
+        void CreateL(TResourceReader& aReader)
+            {
+            ConstructFromResourceL(aReader);
+            }
+    };
+
+
+CAiwMenuPane* CAiwServiceHandlerImpl::CreateEmptyAiwMenuPaneL(TInt aBaseMenuCmdId, 
+    TInt aResourceId)
+    {
+    CAiwMenuPane* result = NULL;
+    TResourceReader reader; 
+    
+    TInt id;
+    if(aResourceId >= 0)
+        {
+        // Use existing id.
+        id = aResourceId;
+        }
+    else
+        {
+        // Create new id.
+        id = ResourceIdForNextFreeSlot();
+        if (id < 0)
+            {
+            User::Leave(KErrOverflow);
+            }
+        }
+    iCoeEnv->CreateResourceReaderLC(reader, id);
+    
+    CAiwMenuResource* pane = new (ELeave) CAiwMenuResource(this);
+    CleanupStack::PushL(pane);
+    pane->ConstructL(NULL);
+    pane->CreateL(reader);
+
+    result = new (ELeave) CAiwMenuPane(*pane, aBaseMenuCmdId);
+    
+    CleanupStack::Pop(pane);
+    CleanupStack::PopAndDestroy(); // reader
+    
+    result->SetResourceSlotId( id );
+    
+    return result;
+    }
+
+
+void CAiwServiceHandlerImpl::DeleteAiwMenuPane(CAiwMenuPane* aAiwPane)
+    {
+    delete aAiwPane->iMenuPane;
+    aAiwPane->iMenuPane = NULL;
+
+    // Reset iIdMap and extraText.
+    for(TInt i = 0; i < aAiwPane->iIdMap.Count(); i++)
+        {
+        aAiwPane->iIdMap[i].extraText.Close();
+        }
+    aAiwPane->iIdMap.Reset();
+    
+    // Remove the aiw menu pane from iMenuPanes array.
+    for(TInt i = 0; i < iMenuPanes.Count(); i++)
+        {
+        if(iMenuPanes[i] == aAiwPane)
+            {
+            iMenuPanes.Remove(i);
+            break;                            
+            }
+        }
+    
+    // Remove the aiw menu pane from iMenuLastInitialized array.
+    for(TInt i = 0; i < iLastInitialized.Count(); i++)
+        {
+        if(iLastInitialized[i] == aAiwPane)
+            {
+            iLastInitialized.Remove(i);
+            break;                            
+            }
+        }                        
+    
+    delete aAiwPane;
+    aAiwPane = NULL;    
+    }
+
+const TInt resourceSlotIds[KMaxMenuResources] =
+    {
+    R_AIW_EMPTY_MENU_0,
+    R_AIW_EMPTY_MENU_1,
+    R_AIW_EMPTY_MENU_2,
+    R_AIW_EMPTY_MENU_3,
+    R_AIW_EMPTY_MENU_4,
+    R_AIW_EMPTY_MENU_5,
+    R_AIW_EMPTY_MENU_6,
+    R_AIW_EMPTY_MENU_7,
+    R_AIW_EMPTY_MENU_8,
+    R_AIW_EMPTY_MENU_9,
+    R_AIW_EMPTY_MENU_10,
+    R_AIW_EMPTY_MENU_11,
+    R_AIW_EMPTY_MENU_12,
+    R_AIW_EMPTY_MENU_13,
+    R_AIW_EMPTY_MENU_14,
+    R_AIW_EMPTY_MENU_15
+    };
+
+
+TInt CAiwServiceHandlerImpl::ResourceIdForNextFreeSlot()
+    {
+    if (iNextFreeSlot < KMaxMenuResources)
+        {
+        return resourceSlotIds[iNextFreeSlot++];
+        }
+
+    return -1;
+    }
+
+
+void CAiwServiceHandlerImpl::SetEmphasis(CCoeControl* /*aMenuControl*/,TBool /*aEmphasis*/)
+    {
+    }
+
+
+void CAiwServiceHandlerImpl::ProcessCommandL(TInt /*aCommandId*/) 
+    {
+    }
+
+
+void Cleanup( TAny* aAny )
+    {
+    RImplInfoPtrArray* implArray = 
+        reinterpret_cast< RImplInfoPtrArray*> ( aAny );
+    implArray->ResetAndDestroy();
+    implArray->Close();
+    }
+
+
+void InterestCleanup( TAny* aAny )
+    {
+    RPointerArray<CAiwCriteriaItem>* interestArray = 
+        reinterpret_cast<RPointerArray<CAiwCriteriaItem>*> ( aAny );
+
+    interestArray->ResetAndDestroy();   
+    }
+
+void FilteredCleanup( TAny* aAny )
+    {
+    RPointerArray<CAiwCriteriaItem>* filteredArray = 
+        reinterpret_cast<RPointerArray<CAiwCriteriaItem>*> ( aAny );
+
+    filteredArray->Reset();   
+    }
+
+
+void IntArrayCleanup(TAny* aAny)
+    {
+    RArray<TInt>* intArray = 
+        reinterpret_cast<RArray<TInt>*> ( aAny );
+
+    intArray->Close();
+    }
+
+
+void CAiwServiceHandlerImpl::CopyMenuItemsL(CAiwMenuPane* aSource, CEikMenuPane& aDest, 
+    TInt aStartIndex, TBool aIsSubmenu, TBool aSetAsItemSpecific)
+    {
+    TInt cmdId;
+    TInt inPos = aStartIndex;
+
+    for (TInt i = 0; i < aSource->MenuPane().NumberOfItemsInPane(); i++)
+        {
+        cmdId = aSource->FindCmdId(i);
+        if (cmdId >= 0)
+            {
+            CEikMenuPaneItem::SData itemData = aSource->MenuPane().ItemData(cmdId);
+            
+            // The menu item might include alternative texts for a main menu level 
+            // and for submenu. Use submenu string if it is intended so.       
+            if(aIsSubmenu)
+                {
+                const TDesC& extraText = aSource->ExtraText(cmdId);
+                if(extraText.Length())
+                    {
+                    itemData.iText.Zero();
+                    itemData.iText.Append(extraText);
+                    }                 
+                }
+
+            if ( aSetAsItemSpecific )
+                {
+                itemData.iFlags |= EEikMenuItemSpecific;
+                }
+            
+            aDest.InsertMenuItemL(itemData, inPos++);
+            }   
+        }   
+    }
+
+
+
+TInt CAiwServiceHandlerImpl::SlotItemCmd(CEikMenuPane& aPane)
+    {
+    TInt index;
+
+    for (TInt i = 0; i < KMaxMenuResources; i++)
+        {
+        if (aPane.MenuItemExists(EAiwMenuSlotBase + i, index))
+            {
+            return EAiwMenuSlotBase + i;
+            }
+        }
+
+    return -1;
+    }
+
+
+
+CAiwMenuPane* CAiwServiceHandlerImpl::MenuPaneForSlotCmd(TInt aCmdId)
+    {
+    TInt index = aCmdId - EAiwMenuSlotBase; 
+
+    if (index < KMaxMenuResources)
+        {
+        TInt resId = resourceSlotIds[index];
+        for (TInt i = 0; i < iMenuPanes.Count(); i++)
+            {
+            if (iMenuPanes[i]->ResourceSlotId() == resId)
+                {
+                return iMenuPanes[i];
+                }
+            }
+        }
+
+    return NULL;
+    }
+
+
+
+CAiwServiceHandlerImpl::TAiwPlaceholderType CAiwServiceHandlerImpl::PlaceholderType(
+    CEikMenuPane& aPane, TInt aCmd, TBool& aTitleLocked)
+    {
+    CEikMenuPaneItem::SData& itemData = aPane.ItemData(aCmd);
+
+    aTitleLocked = EFalse;
+
+    if ((itemData.iCascadeId & AIW_CASCADE_ID) == AIW_CASCADE_ID)
+        {
+        if (itemData.iCascadeId & AIW_LOCK_SUBMENU_TITLE)
+            {
+            aTitleLocked = ETrue;
+            }
+        return EAiwPlaceholderCascade;
+        }
+    else if ((itemData.iCascadeId & AIW_INTELLIGENT_CASCADE_ID) == AIW_INTELLIGENT_CASCADE_ID)
+        {
+        if (itemData.iCascadeId & AIW_LOCK_SUBMENU_TITLE)
+            {
+            aTitleLocked = ETrue;
+            }
+        return EAiwPlaceholderIntelligentCascade;
+        }
+
+    return EAiwPlaceholderNormal;
+    }
+
+
+void CAiwServiceHandlerImpl::ConvertPlaceholderL(CEikMenuPane& aPane, TInt aCmd, 
+    CAiwMenuPane& aAiwPane, const TDesC& aTitle, TBool aSetAsItemSpecific)
+    {
+    CEikMenuPaneItem::SData itemData = aPane.ItemData(aCmd);
+    TInt index;
+
+    // Remenber index.
+    aPane.MenuItemExists(aCmd, index);
+
+    // Remove placeholder item.
+    aPane.DeleteMenuItem(aCmd);
+
+    // Replace aiw cascade id with actual menu resource id.
+    itemData.iCascadeId = aAiwPane.iResourceSlotId;
+
+    if (aTitle.Length())
+        {
+        itemData.iText.Copy(aTitle);
+        }
+
+    // Set unused dynamic cmd id.   
+    itemData.iCommandId = iSubmenuCmd++;
+
+    if ( aSetAsItemSpecific )
+        {
+        itemData.iFlags |= EEikMenuItemSpecific;
+        }
+
+    // Insert cascade item.
+    aPane.InsertMenuItemL(itemData, index);
+    }
+
+
+void CAiwServiceHandlerImpl::UnCascadeL(CEikMenuPane& aPane, TInt aCmd,
+    CAiwMenuPane& aAiwPane, TBool aSetAsItemSpecific)
+    {
+    CEikMenuPaneItem::SData itemData = aAiwPane.MenuPane().ItemData(aAiwPane.FindCmdId(0));
+    TInt index;
+
+    // Remenber index.
+    aPane.MenuItemExists(aCmd, index);
+
+    // Remove placeholder item.
+    aPane.DeleteMenuItem(aCmd);
+
+    // Uncascade 
+    itemData.iCascadeId = 0;
+
+    if ( aSetAsItemSpecific )
+        {
+        itemData.iFlags |= EEikMenuItemSpecific;
+        }
+
+    // Insert cascade item.
+    aPane.InsertMenuItemL(itemData, index);     
+    }
+
+
+
+void CAiwServiceHandlerImpl::SkipMenuFields(TResourceReader& aReader)
+    {
+    aReader.ReadInt32(); // Skip cascade id
+    aReader.ReadInt32(); // Skip flags
+    aReader.ReadTPtrC(); // Skip text
+    aReader.ReadTPtrC(); // Skip extra text
+    aReader.ReadTPtrC(); // Skip bmpfile.
+    aReader.ReadInt16(); // Skip bmpid.
+    aReader.ReadInt16(); // Skip bmpmask. 
+    aReader.ReadInt32(); // Skip extension.   
+    }
+
+
+TBool CAiwServiceHandlerImpl::IsAiwMenu(TInt aMenuResourceId)
+    {
+    TInt i;
+
+    // First check if this is aiw submenu id
+    for (i = 0; i < KMaxMenuResources; i++)
+        {
+        if (aMenuResourceId == resourceSlotIds[i])
+            {
+            return ETrue;
+            }
+        }
+
+    // Then check if this menu is among attached menus.
+    for (i = 0; i < iMenuBindings.Count(); i++)
+        {
+        if (iMenuBindings[i]->MenuId() == aMenuResourceId)
+            {
+            return ETrue;
+            }
+        }
+
+    return EFalse;
+    }
+
+
+
+TBool CAiwServiceHandlerImpl::HandleSubmenuL(CEikMenuPane& aPane)
+    {
+    TInt slotcmd = SlotItemCmd(aPane);
+    if (slotcmd >= 0)
+        {
+        // aPane is aiw submenu. At this point it is empty and we must
+        // copy provider menu items to it.
+        CAiwMenuPane* aiwPane = MenuPaneForSlotCmd(slotcmd);
+        if (aiwPane)
+            {
+            CopyMenuItemsL(aiwPane, aPane, 0, ETrue, EFalse);
+            aPane.DeleteMenuItem(slotcmd);
+            iSubmenu = aiwPane;     
+            return ETrue;
+            }
+        }
+
+    return EFalse;
+    }
+
+
+
+TBool CAiwServiceHandlerImpl::GetSubmenuTitle(CEikMenuPane& aPane, TDes& aResult)
+    {
+    TInt index;
+    
+    aResult.Zero();
+    while (aPane.MenuItemExists(AIW_SUBMENU_TITLE, index))
+        {
+        CEikMenuPaneItem::SData& itemData = aPane.ItemData(AIW_SUBMENU_TITLE);
+        if (aResult.Length() == 0)
+            {
+            aResult.Copy(itemData.iText);
+            }
+        aPane.DeleteMenuItem(AIW_SUBMENU_TITLE);
+        return ETrue;
+        }
+
+    return EFalse;
+    }
+
+
+
+CAiwCriteriaItem* CAiwServiceHandlerImpl::ConvertCriteriaItemPointerL(CAiwCriteriaItem* aCandidate)
+    {
+    for (TInt i = 0; i < iInterestList.Count(); i++)
+        {
+        if ((*iInterestList[i]) == (*aCandidate))
+            {
+            // Already in list, aCandidate is not needed.
+            delete aCandidate;
+            return iInterestList[i];
+            }
+        }
+
+    CleanupStack::PushL(aCandidate);
+    User::LeaveIfError(iInterestList.Append(aCandidate));
+    CleanupStack::Pop(); // aCandidate
+
+    return aCandidate;
+    }
+
+
+
+void CAiwServiceHandlerImpl::FilterInterestListL(RPointerArray<CAiwCriteriaItem>& aOriginal,
+    RPointerArray<CAiwCriteriaItem>& aFiltered)
+    {
+    CAiwCriteriaItem* item;
+
+    while (aOriginal.Count() > 0)
+        {
+        item = aOriginal[0];
+        aOriginal.Remove(0);
+        item = ConvertCriteriaItemPointerL(item);
+        User::LeaveIfError(aFiltered.Append(item));
+        }
+    aOriginal.Reset();
+    }
+
+
+
+void CAiwServiceHandlerImpl::RemoveProvider(TInt aImplUid)
+    {
+    TInt i;
+
+    // First go through bindings and remove all the 
+    // references to given provider.
+    for (i = 0; i < iBaseBindings.Count(); i++)
+        {
+        iBaseBindings[i]->RemoveProvider(aImplUid);
+        }
+
+    for (i = 0; i < iMenuBindings.Count(); i++)
+        {
+        iMenuBindings[i]->RemoveProvider(aImplUid);
+        }
+    
+    // Then remove provider from the owner list and delete it.
+    for (i = 0; i < iProviders.Count(); i++)
+        {
+        if (iProviders[i]->ImplementationUid().iUid == aImplUid)
+            {
+            delete iProviders[i];
+            iProviders.Remove(i);
+            i--;
+            }
+        }
+    }
+
+
+void CAiwServiceHandlerImpl::AddProviderL(TUid aImplUid, CAiwCriteriaItem* aItem)
+    {
+    TInt i;
+    CAiwServiceIfBase* iface = iEcomMonitor->CreateImplementationL(aImplUid);
+    
+    if (iface)
+        {
+        CleanupStack::PushL(iface);
+        iface->AddCriteria(aItem);
+        User::LeaveIfError(iProviders.Append( iface ));
+        CleanupStack::Pop(iface);
+
+        for (i = 0; i < iBaseBindings.Count(); i++)
+            {
+            if (iBaseBindings[i]->HasCriteriaItem(*aItem) != KErrNotFound)
+                {
+                iBaseBindings[i]->AddProviderL(iface, aImplUid == aItem->DefaultProvider());
+                iface->InitialiseL(*this, iBaseBindings[i]->Interest());
+                }               
+            }
+
+        for (i = 0; i < iMenuBindings.Count(); i++)
+            {
+            if (iMenuBindings[i]->HasCriteriaItem(*aItem) != KErrNotFound)
+                {
+                iMenuBindings[i]->AddProviderL(iface, aImplUid == aItem->DefaultProvider());
+                iface->InitialiseL(*this, iMenuBindings[i]->Interest());
+                }               
+            }
+        }
+    }
+
+
+
+TInt CAiwServiceHandlerImpl::SynchronizeCallBack(TAny* aImpl)
+    {
+    CAiwServiceHandlerImpl* impl = reinterpret_cast<CAiwServiceHandlerImpl*>(aImpl);
+    TRAPD(err, impl->SynchronizeDbL());
+    return err;
+    }
+
+
+
+void CAiwServiceHandlerImpl::SynchronizeDbL()
+    {
+    TInt i;
+    RArray<TInt> providers;
+    RImplInfoPtrArray infoArray;
+
+    CleanupStack::PushL( TCleanupItem( IntArrayCleanup, &providers ) );
+    CleanupStack::PushL( TCleanupItem( Cleanup, &infoArray ) );
+
+    for (i = 0; i < iInterestList.Count(); i++)
+        {
+        if (iInterestList[i]->RomOnly())  // Rom-only criterias can be skipped.
+            {
+            continue;
+            }
+
+        providers.Reset();
+        infoArray.ResetAndDestroy();
+        ListProvidersForCriteriaL(providers, *(iInterestList[i]));
+        iEcomMonitor->ListImplemetationsL(infoArray, iInterestList[i]);
+        HandleRemovedProviders(providers, infoArray);          
+        HandleNewProvidersL(providers, infoArray, iInterestList[i]);        
+        }
+
+    CleanupStack::PopAndDestroy(2); // providers, infoArray
+    }
+
+
+void CAiwServiceHandlerImpl::HandleRemovedProviders(RArray<TInt>& aInMemory, 
+    RImplInfoPtrArray& aInSystem)
+    {
+    TInt i, j;
+
+    for (i = 0; i < aInMemory.Count(); i++)
+        {
+        for (j = 0; j < aInSystem.Count(); j++)
+            {
+            if (aInSystem[j]->ImplementationUid().iUid == aInMemory[i])
+                {
+                break;
+                }
+            }
+        if (j >= aInSystem.Count())  // Was removed from system.
+            {
+            RemoveProvider(aInMemory[i]);
+            }
+        }
+    }
+
+
+void CAiwServiceHandlerImpl::HandleNewProvidersL(RArray<TInt>& aInMemory, 
+    RImplInfoPtrArray& aInSystem, CAiwCriteriaItem* aItem)
+    {
+    TInt i;
+
+    for (i = 0; i < aInSystem.Count(); i++)
+        {
+        if (aInMemory.Find(aInSystem[i]->ImplementationUid().iUid) == KErrNotFound)
+            {
+            AddProviderL(aInSystem[i]->ImplementationUid(), aItem);
+            }       
+        }
+    }
+    
+void CAiwServiceHandlerImpl::MenuLaunched()
+    {  
+    ClearMenuPaneArray();
+    iNextFreeSlot = 0;
+    iLastInitialized.Reset();
+
+    // Reset the iMenuPane pointers from iMenuBindings.
+    for(TInt i = 0; i < iMenuBindings.Count(); i++)
+        {
+        iMenuBindings[i]->SetMenuPane(NULL);
+        }
+    }
+
+// End of file