contentstorage/casrv/caappscanner/src/casrvappscanner.cpp
branchRCL_3
changeset 113 0efa10d348c0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contentstorage/casrv/caappscanner/src/casrvappscanner.cpp	Tue Aug 31 15:30:51 2010 +0300
@@ -0,0 +1,1261 @@
+/*
+* Copyright (c) 2009 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: casrvappscanner.cpp
+*
+*/
+
+#include <e32property.h>
+#include <bautils.h>
+#include <usif/scr/screntries.h>
+
+#include "cadef.h"
+#include "casrvappscanner.h"
+#include "cautils.h"
+#include "casrvmmchistory.h"
+#include "pathinfo.h"
+#include "casrvengutils.h"
+#include "cainnerquery.h"
+#include "cainnerentry.h"
+#include "caarraycleanup.inl"
+#include "castorageproxy.h"
+
+#include "caarraycleanup.inl"
+
+using namespace Usif;
+
+
+
+// ==================== LOCAL FUNCTIONS ====================
+
+/**
+ * Identity function to search in an array of CCaInnerEntry.
+ * Identity is the ID.
+ * @param aLeft Search term.
+ * @param aRight Array item.
+ * @return ETrue if ID-s match.
+ */
+LOCAL_C TBool IdMatch( const CCaInnerEntry& aLeft,
+        const CCaInnerEntry& aRight )
+    {
+    return aLeft.GetId() == aRight.GetId();
+    }
+
+/**
+ * Identity function to search in an array of CCaInnerEntry.
+ * Identity is the ID.
+ * @param aLeft Search term.
+ * @param aRight Array item.
+ * @return ETrue if ID-s match.
+ */
+LOCAL_C TBool UidMatch( const CCaInnerEntry& aLeft,
+        const CCaInnerEntry& aRight )
+    {
+    return aLeft.GetUid() == aRight.GetUid();
+    }
+
+// ==================== MEMBER FUNCTIONS ====================
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CCaSrvAppScanner* CCaSrvAppScanner::NewL( CCaStorageProxy& aCaStorageProxy,
+        Usif::RSoftwareComponentRegistry& aSoftwareRegistry,
+        CCaSrvEngUtils& aUtils )
+    {
+    CCaSrvAppScanner* scanner = new ( ELeave ) CCaSrvAppScanner(
+            aCaStorageProxy, aSoftwareRegistry, aUtils );
+    CleanupStack::PushL( scanner );
+    scanner->ConstructL();
+    CleanupStack::Pop( scanner );
+    return scanner;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CCaSrvAppScanner::~CCaSrvAppScanner()
+    {
+    Cancel();
+    iApaLsSession.Close();
+    delete iMmcHistory;
+    iFs.Close();
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CCaSrvAppScanner::CCaSrvAppScanner( CCaStorageProxy& aCaStorageProxy,
+        Usif::RSoftwareComponentRegistry& aSoftwareRegistry,
+        CCaSrvEngUtils& aUtils ) :
+    CActive( CActive::EPriorityStandard ),
+    iCaStorageProxy( aCaStorageProxy ),
+    iSoftwareRegistry(aSoftwareRegistry), iSrvEngUtils( aUtils )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::ConstructL()
+    {
+    User::LeaveIfError( iFs.Connect() );
+    TFileName path;
+    User::LeaveIfError( iFs.PrivatePath( path ) );
+    TUint attribute;
+    if( iFs.Att( path, attribute ) == KErrNotFound )
+        {
+        TInt mdRes = iFs.MkDirAll( path );
+        if ( mdRes != KErrNone )
+            {
+            User::Leave( mdRes );
+            }
+        }
+    iMmcHistory = CCaSrvMmcHistory::NewL();
+    iMmcHistory->LoadL( iFs, KCaMmcHistoryFname() );
+
+    User::LeaveIfError( iApaLsSession.Connect() );
+    iApaLsSession.SetNotify( EFalse, iStatus );
+    iCollectionDownloadId = 0;
+    iAllCollectionId = 0;
+
+    UpdateApplicationEntriesL();
+    MakeNotEmptyCollectionsVisibleL();
+
+    SetActive();
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RunL()
+    {
+    User::LeaveIfError( iStatus.Int() );
+
+    // AppArc app scan complete, we have the app list.
+    RArray<TApaAppUpdateInfo> updatedAppsInfo;
+    CleanupClosePushL( updatedAppsInfo );
+    iApaLsSession.UpdatedAppsInfoL( updatedAppsInfo );
+
+    for( TInt i = 0; i < updatedAppsInfo.Count(); i++ )
+    	{
+		TApaAppUpdateInfo::TApaAppAction action = updatedAppsInfo[i].iAction;
+        RPointerArray<CCaInnerEntry> resultArray;
+        CleanupResetAndDestroyPushL( resultArray );
+        GetCaAppEntriesL( updatedAppsInfo[i].iAppUid.iUid, resultArray );
+		if( action == TApaAppUpdateInfo::EAppPresent
+				|| action == TApaAppUpdateInfo::EAppInfoChanged )
+			{
+			TInt id;
+			if( !resultArray.Count() )
+				{
+                id = AddAppEntryL(
+                        updatedAppsInfo[i].iAppUid.iUid, UpdateMmcHistoryL() );
+                AddEntryToDownloadedCollectionL( id );
+				}
+			else
+			    {
+                ASSERT( resultArray.Count() == 1 );
+                id = resultArray[0]->GetId();
+                UpdateAppEntryL( resultArray[0], UpdateMmcHistoryL(), ETrue );
+                }
+            MakeNotEmptyCollectionsVisibleL();
+			}
+		else if( action == TApaAppUpdateInfo::EAppNotPresent )
+			{
+			HandleMissingItemsL( resultArray );
+			}
+		else
+			{
+			User::Leave( KErrNotSupported );
+			}
+        CleanupStack::PopAndDestroy( &resultArray );
+    	}
+    CleanupStack::PopAndDestroy( &updatedAppsInfo );
+
+    iApaLsSession.SetNotify( EFalse, iStatus );
+    SetActive();
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::DoCancel()
+    {
+    iApaLsSession.CancelNotify();
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::RunError( TInt /*aError*/)
+    {
+    // Ignore the error (what else could we do?).
+    // When next update occurs, we will run again.
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::UpdateApplicationEntryL(
+        RPointerArray<CCaInnerEntry>& aCaEntries,
+        TUint aAppUid, TUint aMmcId )
+    {
+    RPointerArray<CCaInnerEntry> resultArray;
+    CleanupResetAndDestroyPushL( resultArray );
+    GetCaAppEntriesL( aAppUid, resultArray );
+
+    // This app is not in the storage, add it now.
+    // We don't add hidden items, there are too many of them!
+    // do not display Menu app
+    if( !resultArray.Count() )
+        {
+        AddAppEntryL( aAppUid, aMmcId );
+        }//if
+
+    // "removable", "missing" and "visible"  flags update
+    for( TInt j = 0; j < resultArray.Count(); j++ )
+        {
+        //We need to handle first run of appscanner,
+        //there might be some incorrect data. If this will have impact
+        //on performance we may run this methods only at start up.
+
+        UpdateAppEntryL( resultArray[j], aMmcId );
+        TInt index = aCaEntries.Find( resultArray[j],
+                TIdentityRelation<CCaInnerEntry>( IdMatch ) );
+        if( index != KErrNotFound )
+            {
+            delete aCaEntries[index];
+            aCaEntries.Remove( index );
+            }
+        }//for
+    CleanupStack::PopAndDestroy( &resultArray );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::UpdateAppEntryL(
+        CCaInnerEntry* aEntry, TUint aMmcId, TBool aAlwaysUpdate )
+    {
+    TBool missingFlagChanged = HandleMissingFlagsUpdate( aEntry );
+    TBool visibleFlagChanged = HandleVisibleFlagUpdate( aEntry );
+
+
+    // To handle case with mmc card. When mmc attritube is updated then
+    // used flag should be change. When aplication is update but
+    // it is not appear then this flag should be change too.
+    if( aAlwaysUpdate && !missingFlagChanged )
+        {
+        HandleUsedFlagUpdate( aEntry );
+        }
+    TBool toUpdate = missingFlagChanged || visibleFlagChanged;
+    toUpdate = SetApaAppInfoL( aEntry ) || toUpdate;
+    toUpdate = HandleRemovableFlagAndMmcAttrUpdateL( aEntry, aMmcId ) || toUpdate;
+    toUpdate = RemoveUninstallFlagL( aEntry ) || toUpdate;
+
+    if( toUpdate || aAlwaysUpdate )
+        {
+        //update app in storage
+        TItemAppearance itemAppearanceChange = EItemAppearanceNotChanged;
+        if( missingFlagChanged || visibleFlagChanged )
+            {
+            itemAppearanceChange = EItemAppeared;
+            }
+        if( !missingFlagChanged )
+            {
+            AddEntryToPredefinedCollectionL( aEntry, ETrue );
+            if ( aEntry->GetFlags() & ERemovable )
+                {
+                AddEntryToDownloadedCollectionL( aEntry->GetId() );
+                }
+            }
+        iCaStorageProxy.AddL( aEntry, EFalse, itemAppearanceChange );
+        }
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleMmcAttrUpdateL(
+        const Usif::CComponentEntry* aEntry,
+        CCaInnerEntry* aItem, TUint aMmcId )
+    {
+    TBool toChange( EFalse );
+    if( aEntry && aEntry->IsRemovable() )
+        {
+        TChar currentDriveLetter;
+        if ( aEntry->SoftwareType().Compare(KCaAttrAppTypeValueNative()) != 0 )
+            {
+            TDriveList driveList = aEntry->InstalledDrives();
+            for ( TInt driveNr=EDriveY; driveNr >= EDriveA; driveNr-- )
+                {
+                if ( driveList[driveNr] )
+                    {
+                    User::LeaveIfError( iFs.DriveToChar( driveNr,
+                            currentDriveLetter ) );
+                    }
+                }
+            }
+        else
+            {
+            TApaAppInfo* appInfo = new ( ELeave ) TApaAppInfo();
+            if( !iApaLsSession.GetAppInfo( *appInfo,
+                    TUid::Uid( aItem->GetUid() ) ) )
+                {
+                currentDriveLetter = appInfo->iFullName[0];
+                }
+            }
+
+        if( IsCharInDrive( currentDriveLetter,
+                DriveInfo::EDefaultRemovableMassStorage ) )
+            {
+            //app is instaled on mmc - KCaAttrMmcId attribute update
+            RBuf uidString;
+            uidString.CleanupClosePushL();
+            uidString.CreateL( KUidChars );
+            uidString.Format( KHexFormat, aMmcId );
+            toChange = AddAttributeL( aItem, KCaAttrMmcId, uidString );
+            CleanupStack::PopAndDestroy( &uidString );
+            }
+        else if ( IsCharInDrive( currentDriveLetter, DriveInfo::EDefaultMassStorage ) )
+            {
+            //its app installed on mass storage, we need to leave it
+            //in case of connecting usb in mass storage mode
+            toChange = AddAttributeL( aItem, KCaAttrMmcId, KCaMassStorage );
+            }
+        else
+            {
+            toChange = RemoveAttributeL( aItem, KCaAttrMmcId );
+            }
+        }
+    else
+        {
+        toChange = RemoveAttributeL( aItem, KCaAttrMmcId );
+        //its installed on c: drive - remove attribute
+        }
+    return toChange;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::UpdateApplicationEntriesL()
+    {
+    TUint currentMmcId = UpdateMmcHistoryL();
+    // get all Content arsenal enties with type application
+    RPointerArray<CCaInnerEntry> resultArray;
+    CleanupResetAndDestroyPushL( resultArray );
+    GetCaAppEntriesL( resultArray );
+    HandleHsAppEntryL( resultArray );
+    RemoveSatAppL( resultArray );
+
+    RArray<TUint> appUids;
+    CleanupClosePushL( appUids );
+    GetApaItemsL( appUids );
+    RemoveApp( appUids, KSatUid.iUid );
+    RemoveApp( appUids, KHsAppUid.iUid );
+
+    //for every item in apaAndCrItems array
+    for( TInt i = 0; i < appUids.Count(); i++ )
+        {
+        // if there was leave for any item we ignore it
+        // and proceed to the next one
+        TRAP_IGNORE(UpdateApplicationEntryL(
+                resultArray, appUids[i], currentMmcId));
+        }
+    // Here the big list with items that refer to missing apps.
+    HandleMissingItemsL( resultArray );
+    CleanupStack::PopAndDestroy( &appUids );
+    CleanupStack::PopAndDestroy( &resultArray );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleRemovableFlagAndMmcAttrUpdateL(
+        CCaInnerEntry* aItem, TUint aMmcId )
+    {
+    TBool toChange( EFalse );
+    TComponentId compId = GetComponentIdFromEntryL( aItem );
+
+    TBool isRemovable( EFalse );
+    if( compId )
+        {
+        CComponentEntry* entry = CComponentEntry::NewLC();
+        iSoftwareRegistry.GetComponentL( compId , *entry );
+        isRemovable = entry->IsRemovable();
+        toChange = HandleMmcAttrUpdateL( entry, aItem, aMmcId );
+        CleanupStack::PopAndDestroy( entry );
+        }
+
+    if( ( aItem->GetFlags() & EVisible ) && !isRemovable )
+        {
+        if( ( aItem->GetFlags() & ERemovable ) != 0 )
+            {
+            aItem->SetFlags( aItem->GetFlags() & ~ERemovable );
+            toChange = ETrue;
+            }
+        }
+    else
+        {
+        if( ( aItem->GetFlags() & ERemovable ) == 0 && isRemovable )
+            {
+            aItem->SetFlags( aItem->GetFlags() | ERemovable );
+            toChange = ETrue;
+            }
+        }
+    return toChange;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::RemoveUninstallFlagL( CCaInnerEntry* aItem )
+    {
+    TBool toChange( EFalse );
+    if( aItem->GetFlags() & EUninstall )
+        {
+		aItem->SetFlags( aItem->GetFlags() & ~EUninstall );
+		toChange = ETrue;
+        }
+    return toChange;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleMissingFlagsUpdate(
+        CCaInnerEntry* aItem )
+    {
+    TBool ret( EFalse );
+    if( aItem->GetFlags() & EMissing )
+        {
+        //application found so we unset "missing" flag
+        aItem->SetFlags( aItem->GetFlags() & ~EMissing );
+        ret = ETrue;
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleVisibleFlagUpdate( CCaInnerEntry* aItem )
+    {
+    TBool toChange( EFalse );
+    if( !( aItem->GetFlags() & EVisible ) )
+        {
+        aItem->SetFlags( aItem->GetFlags() | EVisible );
+        toChange = ETrue;
+        }
+    return toChange;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleUsedFlagUpdate( CCaInnerEntry* aItem )
+    {
+    TBool changed( EFalse );
+    if( aItem->GetFlags() & EUsed )
+        {
+        aItem->SetFlags( aItem->GetFlags() & ~EUsed );
+        changed = ETrue;
+        }
+    return changed;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RemoveApp( RArray<TUint>& aArray, TInt32 aUid )
+    {
+    TInt id = aArray.Find( aUid );
+    if( id != KErrNotFound )
+        {
+        aArray.Remove( id );
+        }
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RemoveSatAppL( RPointerArray<CCaInnerEntry>& aArray )
+    {
+    CCaInnerEntry* sat = CCaInnerEntry::NewL();
+    sat->SetUid( KSatUid.iUid );
+    TInt index = aArray.Find(
+            sat, TIdentityRelation<CCaInnerEntry>( UidMatch ) );
+    if ( index != KErrNotFound )
+        {
+        delete aArray[index];
+        aArray.Remove( index );
+        }
+    delete sat;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::HandleHsAppEntryL(
+        RPointerArray<CCaInnerEntry>& aArray )
+    {
+    CCaInnerEntry* appEntry = CCaInnerEntry::NewLC();
+    appEntry->SetUid( KHsAppUid.iUid );
+    TInt index = aArray.Find(
+            appEntry, TIdentityRelation<CCaInnerEntry>( UidMatch ) );
+
+    if ( index != KErrNotFound )
+        {
+        // hs app already in storage - ensure it is hidden
+        // and remove from resultArray
+        if ( aArray[index]->GetFlags() & EVisible )
+            {
+            aArray[index]->SetFlags( aArray[index]->GetFlags() & ~EVisible);
+            iCaStorageProxy.AddL( aArray[index], EFalse, EItemDisappeared );
+            }
+        delete aArray[index];
+        aArray.Remove( index );
+        }
+    else
+        {
+        // if not found add as not visible to the storage
+        appEntry->SetEntryTypeNameL( KCaTypeApp );
+        appEntry->SetFlags( 0 );
+        appEntry->SetRole( EItemEntryRole );
+        SetApaAppInfoL( appEntry );
+        iCaStorageProxy.AddL( appEntry );
+        }
+    CleanupStack::PopAndDestroy( appEntry );
+    }
+
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::GetApaItemsL( RArray<TUint>& aArray )
+    {
+    TApaAppInfo* appInfo = new ( ELeave ) TApaAppInfo();
+    CleanupStack::PushL(appInfo);
+    TApaAppCapabilityBuf appCap;
+
+    User::LeaveIfError( iApaLsSession.GetAllApps( 0 ) );
+    // for every application get uid, hidden and missing attribute
+    // and add to aArray.
+    while( KErrNone == iApaLsSession.GetNextApp( *appInfo ) )
+        {
+        User::LeaveIfError( iApaLsSession.GetAppCapability(
+                appCap, appInfo->iUid ) );
+        // "Hidden" status according to AppArc.
+        if( !appCap().iAppIsHidden )
+            {
+            aArray.AppendL( appInfo->iUid.iUid );
+            }
+        }
+    CleanupStack::PopAndDestroy(appInfo);
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::GetCaAppEntriesL(
+        RPointerArray<CCaInnerEntry>& aArray )
+    {
+    CCaInnerQuery* allAppQuery = CCaInnerQuery::NewLC();
+    CDesC16ArrayFlat* appType =
+            new ( ELeave ) CDesC16ArrayFlat( KGranularityOne );
+    CleanupStack::PushL( appType );
+    appType->AppendL( KCaTypeApp );
+    allAppQuery->SetEntryTypeNames( appType );
+    CleanupStack::Pop( appType );
+    iCaStorageProxy.GetEntriesL( allAppQuery, aArray );
+    CleanupStack::PopAndDestroy( allAppQuery );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::GetCollectionDownloadIdL()
+    {
+    if( iCollectionDownloadId == 0 )
+        {
+        RPointerArray<CCaInnerEntry> resultArray;
+        CleanupResetAndDestroyPushL( resultArray );
+        CCaInnerQuery* allAppQuery = CCaInnerQuery::NewLC();
+        CDesC16ArrayFlat* appType =
+                new ( ELeave ) CDesC16ArrayFlat( KGranularityOne );
+        CleanupStack::PushL( appType );
+        appType->AppendL( KCaTypeCollectionDownload );
+        allAppQuery->SetEntryTypeNames( appType );
+        CleanupStack::Pop( appType );
+        iCaStorageProxy.GetEntriesL( allAppQuery, resultArray );
+        CleanupStack::PopAndDestroy( allAppQuery );
+        if( resultArray.Count() )
+            {
+            iCollectionDownloadId = resultArray[0]->GetId();
+            }
+        CleanupStack::PopAndDestroy( &resultArray );
+        }
+    return iCollectionDownloadId;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::GetAllCollectionIdL()
+    {
+    if( iAllCollectionId == 0 )
+        {
+        CCaInnerQuery *getAllCollectionIdQuery = CCaInnerQuery::NewLC();
+        CDesC16ArrayFlat *typenameArray = new(ELeave) CDesC16ArrayFlat(
+                KGranularityOne );
+        CleanupStack::PushL( typenameArray );
+        typenameArray->AppendL( KCaTypeMenuCollections );
+        getAllCollectionIdQuery->SetEntryTypeNames( typenameArray );
+        CleanupStack::Pop( typenameArray );
+
+        RArray<TInt> idArray;
+        CleanupClosePushL( idArray );
+        iCaStorageProxy.GetEntriesIdsL( getAllCollectionIdQuery,
+                idArray );
+        if( idArray.Count() )
+            {
+            iAllCollectionId = idArray[0];
+            }
+        CleanupStack::PopAndDestroy( &idArray );
+        CleanupStack::PopAndDestroy( getAllCollectionIdQuery );
+        }
+    return iAllCollectionId;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::GetCaAppEntriesL( TInt aUid,
+        RPointerArray<CCaInnerEntry>& aArray )
+    {
+    CCaInnerQuery* allAppQuery = CCaInnerQuery::NewLC();
+    allAppQuery->SetUid( aUid );
+    iCaStorageProxy.GetEntriesL( allAppQuery, aArray );
+    CleanupStack::PopAndDestroy( allAppQuery );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::AddEntryToDownloadedCollectionL( TInt aEntryId )
+    {
+    TCaOperationParams params;
+    params.iOperationType = TCaOperationParams::EPrepend;
+    params.iGroupId = GetCollectionDownloadIdL();
+    params.iBeforeEntryId = 0; // Not used.
+
+    RArray<TInt> entryIds;
+    CleanupClosePushL( entryIds );
+    entryIds.AppendL( aEntryId );
+    iCaStorageProxy.OrganizeL( entryIds, params );
+
+    CleanupStack::PopAndDestroy( &entryIds );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::AddEntryToPredefinedCollectionL(
+        CCaInnerEntry* aEntry, TBool aUpdate )
+    {
+    TApaAppCapabilityBuf capability;
+    User::LeaveIfError( iApaLsSession.GetAppCapability( capability,
+            TUid::Uid( aEntry->GetUid() ) ) );
+
+    if( capability().iGroupName.Length() )
+        {
+        // appgroup_name is defined for this app. Find or create folder.
+        CCaInnerQuery *innerQuery = CCaInnerQuery::NewLC();
+        innerQuery->SetRole( CCaInnerQuery::Group );
+        innerQuery->AddAttributeL( KCaAppGroupName,
+                capability().iGroupName );
+
+        // get entries by attributes
+        RPointerArray<CCaInnerEntry> resultArrayItems;
+        CleanupResetAndDestroyPushL( resultArrayItems );
+        iCaStorageProxy.GetEntriesL( innerQuery, resultArrayItems );
+
+        RArray<TInt> entryIds;
+        CleanupClosePushL( entryIds );
+        entryIds.AppendL( aEntry->GetId() );
+        TCaOperationParams organizeParams;
+        organizeParams.iBeforeEntryId = 0;
+        organizeParams.iOperationType = TCaOperationParams::EAppend;
+
+        if( resultArrayItems.Count() )
+            {
+            // collection with appgroup_name exist - add entry
+            // to this collection
+            organizeParams.iGroupId = resultArrayItems[0]->GetId();
+            }
+        else
+            {
+            // create new collection
+            TInt predefinedCollectionId = CreatePredefinedCollectionL(
+                    capability().iGroupName );
+
+            organizeParams.iGroupId = predefinedCollectionId;
+
+            // add new collection to all collection
+            AddCollectionToAllCollectionL( predefinedCollectionId );
+
+            if( aUpdate )
+                {
+                iCaStorageProxy.OrganizeL( entryIds, organizeParams );
+                }
+            }
+
+        if( !aUpdate )
+            {
+            iCaStorageProxy.OrganizeL( entryIds, organizeParams );
+            }
+
+        CleanupStack::PopAndDestroy( &entryIds );
+        CleanupStack::PopAndDestroy( &resultArrayItems );
+        CleanupStack::PopAndDestroy( innerQuery );
+        }
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::CreatePredefinedCollectionL( const TDesC& aGroupName )
+    {
+    CCaInnerEntry *innerEntry = CCaInnerEntry::NewLC();
+    innerEntry->SetTextL( aGroupName );
+    innerEntry->SetEntryTypeNameL( KCaTypeCollection );
+    innerEntry->SetRole( CCaInnerQuery::Group );
+    innerEntry->AddAttributeL( KCaAppGroupName, aGroupName );
+    innerEntry->SetFlags( EVisible | ERemovable );
+    innerEntry->SetIconDataL( KCollectionIconFileName,
+            KNullDesC, KNullDesC );
+    iCaStorageProxy.AddL( innerEntry );
+    // Get new collection Id
+    TInt newCollectionId = innerEntry->GetId();
+    CleanupStack::PopAndDestroy( innerEntry );
+
+    return newCollectionId;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::AddCollectionToAllCollectionL( TInt aCollectionId )
+    {
+    RArray<TInt> entryIds;
+    CleanupClosePushL( entryIds );
+    entryIds.AppendL( aCollectionId );
+
+    TCaOperationParams organizeParams;
+    organizeParams.iBeforeEntryId = 0;
+    organizeParams.iOperationType = TCaOperationParams::EAppend;
+    organizeParams.iGroupId = GetAllCollectionIdL();
+    iCaStorageProxy.OrganizeL( entryIds, organizeParams );
+    CleanupStack::PopAndDestroy( &entryIds );
+    }
+
+
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RemoveEntryFromDownloadedL( TInt aEntryId )
+    {
+    TCaOperationParams params;
+    params.iOperationType = TCaOperationParams::ERemove;
+    params.iGroupId = GetCollectionDownloadIdL();
+    params.iBeforeEntryId = 0; // Not Used
+
+    RArray<TInt> entryIds;
+    CleanupClosePushL( entryIds );
+    entryIds.AppendL( aEntryId );
+    iCaStorageProxy.OrganizeL( entryIds, params );
+
+    CleanupStack::PopAndDestroy( &entryIds );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::AddAppEntryL( TUint aUid, TUint aCurrentMmcId )
+    {
+    TInt id(KErrNotFound);
+    // Now add the app entry.
+    CCaInnerEntry* appEntry = CCaInnerEntry::NewLC();
+
+    appEntry->SetEntryTypeNameL( KCaTypeApp );
+    appEntry->SetUid( aUid );
+    appEntry->SetFlags( EVisible );
+    appEntry->SetRole( EItemEntryRole );
+
+    SetApaAppInfoL( appEntry );
+    HandleRemovableFlagAndMmcAttrUpdateL( appEntry, aCurrentMmcId );
+
+    iCaStorageProxy.AddL( appEntry );
+    id = appEntry->GetId();
+
+    AddEntryToPredefinedCollectionL( appEntry );
+
+    CleanupStack::PopAndDestroy( appEntry );
+    return id;
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool CCaSrvAppScanner::SetApaAppInfoL( CCaInnerEntry* aEntry )
+    {
+    TBool changed( EFalse );
+    TApaAppInfo* info = new ( ELeave ) TApaAppInfo();
+    CleanupStack::PushL(info);
+    if( KErrNone == iSrvEngUtils.GetAppInfo( *aEntry, *info ) )
+        {
+        changed = SetAppCaptionL( aEntry, info ) || changed;
+        changed = UpdateComponentIdL( *aEntry ) || changed;
+
+        // check if its java app and add attr for entries
+        TUid appTypeUid;
+        if( KErrNone == iApaLsSession.GetAppType( appTypeUid, info->iUid ) )
+            {
+            if( appTypeUid == KMidletApplicationTypeUid )
+                {
+                changed = SetJavaAppL( aEntry ) || changed;
+                }
+            else if( appTypeUid == KCWRTApplicationTypeUid )
+                {
+                changed = SetCWRTAppL( aEntry ) || changed;
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy( info );
+    return changed;
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool CCaSrvAppScanner::SetAppCaptionL(
+        CCaInnerEntry* aEntry, TApaAppInfo* info )
+    {
+    TBool changed(EFalse);
+    if( aEntry->GetText().Compare( info->iCaption ) != KErrNone )
+        {
+        aEntry->SetTextL( info->iCaption );
+        changed = ETrue;
+        }
+    changed = AddAttributeL( aEntry, KCaAttrShortName, info->iShortCaption )
+            || changed;
+
+    return changed;
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool CCaSrvAppScanner::SetJavaAppL( CCaInnerEntry* aEntry )
+    {
+    TBool changed = AddAttributeL(
+            aEntry, KCaAttrAppType, KCaAttrAppTypeValueJava );
+    TComponentId compId = GetComponentIdFromEntryL( aEntry );
+    CPropertyEntry* propertyEntry = iSoftwareRegistry.GetComponentPropertyL(
+            compId, KCaScrPropertyAppSettings );
+    CleanupStack::PushL( propertyEntry );
+
+    if( propertyEntry
+            && propertyEntry->PropertyType()
+                    == CPropertyEntry::ELocalizedProperty )
+        {
+        changed = AddAttributeL( aEntry, KCaAttrAppSettingsPlugin,
+                static_cast<CLocalizablePropertyEntry*>(
+                        propertyEntry)->StrValue() ) || changed;
+        }
+    CleanupStack::PopAndDestroy( propertyEntry );
+    return changed;
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+TBool CCaSrvAppScanner::SetCWRTAppL( CCaInnerEntry* aEntry )
+    {
+    TBool changed = AddAttributeL( aEntry, KCaAttrAppType, KCaAttrAppTypeValueCWRT );
+    TComponentId compId = GetComponentIdFromEntryL( aEntry );
+
+    CPropertyEntry* isMiniview = iSoftwareRegistry.GetComponentPropertyL(
+            compId, KCaScrPropertyIsMiniviewSupported );
+    CleanupStack::PushL( isMiniview );
+
+    // check first if we support mini view
+    if( isMiniview && isMiniview->PropertyType() == CPropertyEntry::EIntProperty
+            && static_cast<CIntPropertyEntry*>( isMiniview)->IntValue() )
+        {
+        CPropertyEntry* appId = iSoftwareRegistry.GetComponentPropertyL(
+                compId, KCaScrPropertyAppId );
+        CleanupStack::PushL( appId );
+
+        if ( appId
+                && appId->PropertyType() == CPropertyEntry::ELocalizedProperty )
+            {
+            changed = AddAttributeL(
+                    aEntry, KCaAttrAppWidgetUri, KCaAttrAppWidgetUriCWRTValue )
+                        || changed;
+            changed = AddAttributeL( aEntry, KCaAttrAppWidgetParamWebAppId,
+                    static_cast<CLocalizablePropertyEntry*>(
+                            appId)->StrValue() ) || changed;
+            }
+        CleanupStack::PopAndDestroy( appId );
+        }
+    CleanupStack::PopAndDestroy( isMiniview );
+    return changed;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::AddAttributeL( CCaInnerEntry* aEntry, const TDesC& aKey,
+        const TDesC& aValue )
+    {
+    TBool changed(EFalse);
+    RBuf attrValue;
+    attrValue.CleanupClosePushL();
+    attrValue.CreateL( KCaMaxAttrValueLen );
+
+    TBool found = aEntry->FindAttribute( aKey, attrValue );
+    if( !( found && attrValue.Compare( aValue ) == KErrNone ) )
+        {
+        aEntry->AddAttributeL( aKey, aValue );
+        changed = ETrue;
+        }
+    CleanupStack::PopAndDestroy( &attrValue );
+    return changed;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::RemoveAttributeL( CCaInnerEntry* aEntry,
+        const TDesC& aKey )
+    {
+    TBool toChange( EFalse );
+    RBuf attrVal;
+    attrVal.CleanupClosePushL();
+    attrVal.CreateL( KCaMaxAttrValueLen );
+    if( aEntry->FindAttribute( KCaAttrMmcId, attrVal ) )
+        {
+        aEntry->RemoveAttributeL( aKey );
+        toChange = ETrue;
+        }
+    CleanupStack::PopAndDestroy( &attrVal );
+    return toChange;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::HandleMissingItemsL(
+        RPointerArray<CCaInnerEntry>& aCaEntries )
+    {
+    for( TInt i = 0; i < aCaEntries.Count(); i++ )
+        {
+        RBuf attrVal;
+        attrVal.CleanupClosePushL();
+        attrVal.CreateL( KCaMaxAttrValueLen );
+        if( aCaEntries[i]->FindAttribute( KCaAttrMmcId(), attrVal ) )
+            {
+            TUint mmcId = 0;
+            MenuUtils::GetTUint( attrVal, mmcId );
+            if( ( mmcId && KErrNotFound != iMmcHistory->Find( mmcId )
+                        && mmcId != CurrentMmcId() )
+                    || ( attrVal == KCaMassStorage()
+                        && IsDriveInUse( DriveInfo::EDefaultMassStorage ) ) )
+                {
+                // This item is on an MMC which is currently
+                // in the MMC history or on a mass storage in use.
+                // Set it "missing" but keep it.
+                SetMissingFlagL( aCaEntries[i] );
+                }
+            else
+                {
+                aCaEntries[i]->RemoveAttributeL( KCaAttrMmcId() );
+                ClearAllFlagsL( aCaEntries[i] );
+                }
+            }
+        else
+            {
+            ClearAllFlagsL( aCaEntries[i] );
+            }
+        CleanupStack::PopAndDestroy( &attrVal );
+        }
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::SetMissingFlagL( CCaInnerEntry* aEntry )
+    {
+    if( !( aEntry->GetFlags() & EMissing ) )
+        {
+        aEntry->SetFlags( ( aEntry->GetFlags() | EMissing ) & ~EUninstall );
+        iCaStorageProxy.AddL( aEntry, EFalse, EItemDisappeared );
+        }
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::ClearAllFlagsL( CCaInnerEntry* aEntry )
+    {
+    if( aEntry->GetFlags() & EVisible )
+        {
+        aEntry->SetFlags( 0 );
+        iCaStorageProxy.AddL( aEntry, EFalse, EItemDisappeared );
+        }
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TUint CCaSrvAppScanner::UpdateMmcHistoryL()
+    {
+    TUint mmcId = CurrentMmcId();
+    if( mmcId )
+        {
+        iMmcHistory->InsertL( mmcId );
+        iMmcHistory->SaveL( iFs, KCaMmcHistoryFname() );
+        }
+    return mmcId;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TUint CCaSrvAppScanner::CurrentMmcId() const
+    {
+    // Get mmc id. Errors are ignored.
+    TUint mmcId = 0;
+    TInt mmcDrive;
+    TInt err = DriveInfo::GetDefaultDrive(
+            DriveInfo::EDefaultRemovableMassStorage, mmcDrive );
+    if( !err )
+        {
+        TVolumeInfo volumeInfo;
+        err = iFs.Volume( volumeInfo, mmcDrive );
+        if( !err )
+            {
+            mmcId = volumeInfo.iUniqueID;
+            }
+        }
+    return mmcId;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::IsCharInDrive( const TChar& aDriveLetter,
+        const DriveInfo::TDefaultDrives& aDefaultDrive ) const
+    {
+    TBool retVal( EFalse );
+    TInt mmcDrive;
+    TInt err = DriveInfo::GetDefaultDrive( aDefaultDrive, mmcDrive );
+    if( !err )
+        {
+        TInt fileDrive;
+        err = RFs::CharToDrive( aDriveLetter, fileDrive );
+        if( !err && fileDrive == mmcDrive )
+            {
+            retVal = ETrue;
+            }
+        }
+    return retVal;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::IsDriveInUse(
+        const DriveInfo::TDefaultDrives& aDefaultDrive )
+    {
+    TBool inUse( EFalse );
+    TInt drive;
+
+    TInt err = DriveInfo::GetDefaultDrive( aDefaultDrive, drive );
+    if( err == KErrNone )
+        {
+        TUint status;
+        err = DriveInfo::GetDriveStatus( iFs, drive, status );
+        if( err == KErrNone && ( status & DriveInfo::EDriveInUse ) )
+            {
+            inUse = ETrue;
+            }
+        }
+
+    return inUse;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::MakeNotEmptyCollectionsVisibleL()
+    {
+    RPointerArray<CCaInnerEntry> resultArray;
+    CleanupResetAndDestroyPushL( resultArray );
+    CCaInnerQuery* hiddenCollectionsQuery = CCaInnerQuery::NewLC();
+    CDesC16ArrayFlat* entryType = new ( ELeave ) CDesC16ArrayFlat(
+            KGranularityOne );
+    CleanupStack::PushL( entryType );
+    entryType->AppendL( KCaTypeCollection );
+    hiddenCollectionsQuery->SetEntryTypeNames( entryType );
+    hiddenCollectionsQuery->SetFlagsOff( EVisible );
+    iCaStorageProxy.GetEntriesL( hiddenCollectionsQuery, resultArray );
+    CleanupStack::Pop( entryType );
+    CleanupStack::PopAndDestroy( hiddenCollectionsQuery );
+    if( resultArray.Count() )
+        {
+        for( TInt i=0; i<resultArray.Count(); i++ )
+            {
+            // for any not visible collection
+            MakeCollectionVisibleIfHasVisibleEntryL( resultArray[i] );
+            }
+        }
+    CleanupStack::PopAndDestroy( &resultArray );
+   }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::MakeCollectionVisibleIfHasVisibleEntryL(
+        CCaInnerEntry* aEntry )
+    {
+    RPointerArray<CCaInnerEntry> resultEntriesArray;
+    CleanupResetAndDestroyPushL( resultEntriesArray );
+    CCaInnerQuery* visibleEntriesQuery = CCaInnerQuery::NewLC();
+    visibleEntriesQuery->SetParentId( aEntry->GetId() );
+    visibleEntriesQuery->SetFlagsOn( EVisible );
+    visibleEntriesQuery->SetFlagsOff( EMissing );
+    iCaStorageProxy.GetEntriesL( visibleEntriesQuery, resultEntriesArray );
+    if( resultEntriesArray.Count() )
+        {
+        // set collection visible if hidden
+        if( HandleVisibleFlagUpdate( aEntry ) )
+            {
+            // update here this collection
+            iCaStorageProxy.AddL( aEntry );
+            }
+        }
+    CleanupStack::PopAndDestroy( visibleEntriesQuery );
+    CleanupStack::PopAndDestroy( &resultEntriesArray );
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::GetComponentIdFromEntryL( CCaInnerEntry* aEntry )
+    {
+    TInt id(0);
+    RBuf componentId;
+    componentId.CleanupClosePushL();
+    componentId.CreateL( KCaMaxAttrValueLen );
+
+    TBool found = aEntry->FindAttribute( KCaComponentId, componentId );
+    if( found )
+        {
+        TLex parser;
+        parser.Assign( componentId );
+        parser.Val( id );
+        }
+    CleanupStack::PopAndDestroy( &componentId );
+
+    return id;
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::UpdateComponentIdL( CCaInnerEntry& aEntry )
+    {
+    TBool updated( EFalse );
+    TComponentId componentId( 0 );
+
+    TRAPD(err, componentId = iSoftwareRegistry.GetComponentIdForAppL(
+            TUid::Uid( aEntry.GetUid() ) ) )
+
+    if ( componentId > 0 && err == KErrNone )
+        {
+        RBuf newComponentId;
+        newComponentId.CleanupClosePushL();
+        newComponentId.CreateL( sizeof(TComponentId) + 1 );
+        newComponentId.AppendNum( componentId );
+
+        // 'add' or 'update' the component id attribute value
+        updated = AddAttributeL( &aEntry, KCaComponentId, newComponentId );
+
+        CleanupStack::PopAndDestroy( &newComponentId );
+        }
+    return updated;
+    }