contentstorage/casrv/caappscanner/src/casrvappscanner.cpp
changeset 60 f62f87b200ec
child 61 8e5041d13c84
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contentstorage/casrv/caappscanner/src/casrvappscanner.cpp	Fri Mar 19 09:35:23 2010 +0200
@@ -0,0 +1,998 @@
+/*
+* 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 <swi/sisregistrysession.h>
+#include <swi/sisregistryentry.h>
+#include <swi/sisregistrypackage.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"
+
+// ==================== 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::NewL
+// ---------------------------------------------------------
+//
+CCaSrvAppScanner* CCaSrvAppScanner::NewL( CCaStorageProxy& aCaStorageProxy,
+        CCaSrvEngUtils& aUtils )
+    {
+    CCaSrvAppScanner* scanner = new ( ELeave ) CCaSrvAppScanner(
+            aCaStorageProxy, aUtils );
+    CleanupStack::PushL( scanner );
+    scanner->ConstructL();
+    CleanupStack::Pop( scanner );
+    return scanner;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::~CCaSrvAppScanner
+// ---------------------------------------------------------
+//
+CCaSrvAppScanner::~CCaSrvAppScanner()
+    {
+    Cancel();
+    iApaLsSession.Close();
+    iInstalledPackages.Close();
+    delete iInstallNotifier;
+    delete iNotifier;
+    delete iMmcHistory;
+    iFs.Close();
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::CCaSrvAppScanner
+// ---------------------------------------------------------
+//
+CCaSrvAppScanner::CCaSrvAppScanner( CCaStorageProxy& aCaStorageProxy,
+        CCaSrvEngUtils& aUtils ) :
+    CActive( CActive::EPriorityStandard ),
+    iCaStorageProxy( aCaStorageProxy ), iSrvEngUtils( aUtils )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::ConstructL
+// ---------------------------------------------------------
+//
+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 = new (ELeave) CCaSrvMmcHistory();
+    iMmcHistory->LoadL( iFs, KCaMmcHistoryFname() );
+    // The notifier has its own session to apparc, instead of taking
+    // it as argument... :(
+    iNotifier = CApaAppListNotifier::NewL(
+            this, CActive::EPriorityStandard );
+    iInstallNotifier = CCaInstallNotifier::NewL(
+            *this, CCaInstallNotifier::ESisInstallNotification );
+
+    User::LeaveIfError( iApaLsSession.Connect() );
+    User::LeaveIfError( iApaLsSession.GetAllApps() ); // This is async.
+    iApaLsSession.RegisterListPopulationCompleteObserver( iStatus );
+    iCollectionDownloadId = 0;
+    SetActive();
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::RunL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RunL()
+    {
+    User::LeaveIfError( iStatus.Int() ); // Handle errors in RunL.
+    // AppArc app scan complete, we have the app list.
+    UpdateApplicationEntriesL();
+    InstallationNotifyL();
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::DoCancel
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::DoCancel()
+    {
+    iApaLsSession.CancelListPopulationCompleteObserver();
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::RunError
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::RunError( TInt /*aError*/)
+    {
+    // Ignore the error (what else could we do?).
+    // When next AppArc update occurs, we will run again.
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::UpdateApplicationItemL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::UpdateApplicationEntryL(
+        RPointerArray<CCaInnerEntry>& aCaEntries,
+        const TCaAppAtributes& aApaItem, TUint aMmcId )
+    {
+    TInt appuid = aApaItem.GetUid();
+    RPointerArray<CCaInnerEntry> resultArray;
+    CleanupResetAndDestroyPushL( resultArray );
+    GetCaAppEntriesL( appuid, 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( appuid, 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 in content xml file
+        //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 );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::UpdateAppEntryL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::UpdateAppEntryL( CCaInnerEntry* aEntry, TUint aMmcId )
+    {
+    TBool toUpdate = HandleMmcAttrUpdateL( aEntry, aMmcId );
+    toUpdate = HandleHiddenFlagUpdateL( aEntry ) || toUpdate;
+    toUpdate = HandleMissingFlagUpdate( aEntry ) || toUpdate;
+    toUpdate = HandleLockDeleteFlagUpdateL( aEntry ) || toUpdate;
+    toUpdate = SetApaAppInfoL( aEntry ) || toUpdate;
+       
+    if( iInstalledPackages.Find( aEntry->GetUid() ) != KErrNotFound )
+        {
+        AddEntryToDownloadedCollectionL( aEntry->GetId() );
+        toUpdate = HandleUsedFlagUpdateL( aEntry ) || toUpdate;
+        }
+    if( toUpdate )
+        {
+        //update app in storage
+        iCaStorageProxy.AddL( aEntry );
+        RemoveFromInstalledPackages( aEntry->GetUid() );
+        }
+    }
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleHiddenFlagUpdateL
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleHiddenFlagUpdateL( CCaInnerEntry* aItem )
+    {
+    TBool toChange( EFalse );
+    TBool itemHidden = ( 0 == ( aItem->GetFlags() & EVisible ) );
+    if( itemHidden )
+        {
+        aItem->SetFlags( aItem->GetFlags() | EVisible );
+        toChange = ETrue;
+        }
+    return toChange;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleUsedFlagUpdateL
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleUsedFlagUpdateL( CCaInnerEntry* aItem )
+    {
+    if( aItem->GetFlags() & EUsed )
+        {
+        aItem->SetFlags( aItem->GetFlags() & ~EUsed );
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleMmcAttrUpdateL
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleMmcAttrUpdateL(
+        CCaInnerEntry* aItem, TUint aMmcId )
+    {
+    TBool toUpdate( ETrue );
+    if( IsInMmc( TUid::Uid( aItem->GetUid() ) ) )
+        {
+        //app is instaled on mmc - KCaAttrMmcId attribute update
+        TBuf<KUidChars> uidString;
+        uidString.Format( KHexFormat, aMmcId );
+        aItem->AddAttributeL( KCaAttrMmcId, uidString );
+        }
+    else if ( IsInMassStorage( TUid::Uid( aItem->GetUid() ) ) )
+        {
+        //its app installed on mass storage, we need to leave it
+        //in case of connecting usb in mass storage mode
+        aItem->AddAttributeL( KCaAttrMmcId, KCaMassStorage );
+        }
+    else
+        {
+        RBuf attrVal;
+        attrVal.CleanupClosePushL();
+        attrVal.CreateL( KCaMaxAttrValueLen );
+        if( aItem->FindAttribute( KCaAttrMmcId, attrVal ) )
+            {
+            aItem->RemoveAttributeL( KCaAttrMmcId );
+            }
+        else
+            {
+            toUpdate = EFalse;
+            }
+        CleanupStack::PopAndDestroy( &attrVal );
+        //its installed on c: drive - remove attribute
+        }
+    return toUpdate;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::UpdateApplicationItemsL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::InstallationNotifyL()
+    {
+    for( TInt i = iInstalledPackages.Count() - 1; i >= 0; i-- )
+        {
+        NotifyL( iInstalledPackages[i] );
+        iInstalledPackages.Remove( i );
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::UpdateApplicationItemsL
+// ---------------------------------------------------------
+//
+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<TCaAppAtributes> apaItems;
+    CleanupClosePushL( apaItems );
+    GetApaItemsL( apaItems );
+    RemoveApp( apaItems, KSatUid.iUid );
+    RemoveApp( apaItems, KHsAppUid.iUid );
+
+    //for every item in apaAndCrItems array
+    for( TInt i = 0; i < apaItems.Count(); i++ )
+        {
+            // if there was leave for any item we ignore it
+            // and proceed to the next one
+            TRAP_IGNORE(UpdateApplicationEntryL(
+                            resultArray, apaItems[i], currentMmcId));
+        }
+    // Here the big list cwith items that refer to missing apps.
+    HandleMissingItemsL( resultArray );
+    CleanupStack::PopAndDestroy( &apaItems );
+    CleanupStack::PopAndDestroy( &resultArray );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleLockDeleteFlagUpdateL
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleLockDeleteFlagUpdateL( CCaInnerEntry* aItem )
+    {
+    TBool toChange( EFalse );
+    TBool isVisible = ( ( aItem->GetFlags() & EVisible ) != 0 );
+    if( isVisible && IsInRom( aItem->GetUid() ) )
+        {
+        if( ( aItem->GetFlags() & ERemovable ) != 0 )
+            {
+            aItem->SetFlags( aItem->GetFlags() & ~ERemovable );
+            toChange = ETrue;
+            }
+        }
+    else
+        {
+        if( ( aItem->GetFlags() & ERemovable ) == 0 )
+            {
+            aItem->SetFlags( aItem->GetFlags() | ERemovable );
+            toChange = ETrue;
+            }
+        }
+    return toChange;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleMissingFlagUpdateL
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::HandleMissingFlagUpdate( CCaInnerEntry* aItem )
+    {
+    if( aItem->GetFlags() & EMissing )
+        {
+        //application found so we unset "missing" flag
+        aItem->SetFlags( aItem->GetFlags() & ~EMissing );
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::RemoveApp
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RemoveApp( RArray<TCaAppAtributes>& aArray, TInt32 aUid )
+    {
+    TCaAppAtributes app( aUid );
+    TInt id = aArray.Find( app, TCaAppAtributes::MatchItems );
+    if( id != KErrNotFound )
+        {
+        aArray.Remove( id );
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::RemoveSatApp
+// ---------------------------------------------------------
+//
+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;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleHsAppEntryL
+// ---------------------------------------------------------
+//
+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 ) != 0 )
+            {
+            aArray[index]->SetFlags( aArray[index]->GetFlags() & ~EVisible);
+            iCaStorageProxy.AddL( aArray[index] );
+            }        
+        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 );
+    }
+
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::GetApaItemsL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::GetApaItemsL( RArray<TCaAppAtributes>& aArray )
+    {
+    TApaAppInfo 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 )
+            {
+            TCaAppAtributes appAtributes( appInfo.iUid.iUid );
+            aArray.AppendL( appAtributes );
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::GetMcsItemsL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::GetCaAppEntriesL(
+        RPointerArray<CCaInnerEntry>& aArray )
+    {
+    CCaInnerQuery* allAppQuery = CCaInnerQuery::NewLC();
+    CDesC16ArrayFlat* appType = new ( ELeave ) CDesC16ArrayFlat( 1 );
+    CleanupStack::PushL( appType );
+    appType->AppendL( KCaTypeApp );
+    allAppQuery->SetEntryTypeNames( appType );
+    CleanupStack::Pop( appType );
+    iCaStorageProxy.GetEntriesL( allAppQuery, aArray );
+    CleanupStack::PopAndDestroy( allAppQuery );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::GetMcsItemsL
+// ---------------------------------------------------------
+//
+TInt CCaSrvAppScanner::GetCollectionDownloadIdL()
+    {
+    if( iCollectionDownloadId == 0 )
+        {
+        RPointerArray<CCaInnerEntry> resultArray;
+        CleanupResetAndDestroyPushL( resultArray );
+        CCaInnerQuery* allAppQuery = CCaInnerQuery::NewLC();
+        CDesC16ArrayFlat* appType = new ( ELeave ) CDesC16ArrayFlat( 1 );
+        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;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::GetMcsItemsL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::GetCaAppEntriesL( TInt aUid,
+        RPointerArray<CCaInnerEntry>& aArray )
+    {
+    CCaInnerQuery* allAppQuery = CCaInnerQuery::NewLC();
+    allAppQuery->SetUid( aUid );
+    iCaStorageProxy.GetEntriesL( allAppQuery, aArray );
+    CleanupStack::PopAndDestroy( allAppQuery );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleAppListEvent
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::HandleAppListEvent( TInt /*aEvent*/)
+    {
+    // We only have one event, EAppListChanged.
+    // Call back RunL async, to requeue and initiate rescan.
+    if( !IsActive() )
+        {
+        ScheduleScan();
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleInstallNotifyL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::HandleInstallNotifyL( TInt aUid )
+    {
+    NotifyL( aUid );
+    RArray<TUid> uids;
+    CleanupClosePushL( uids );
+
+    Swi::RSisRegistrySession iSisRegSession;
+    User::LeaveIfError( iSisRegSession.Connect() );
+    CleanupClosePushL( iSisRegSession );
+
+    // Open sis package entry related to aUid
+    Swi::RSisRegistryEntry packageEntry;
+    if( KErrNone
+            == packageEntry.Open( iSisRegSession, TUid::Uid( aUid ) ) )
+        {
+        CleanupClosePushL( packageEntry );
+
+        // Get packageEntry's embedded sis'
+        RPointerArray<Swi::CSisRegistryPackage> embedded;
+        CleanupClosePushL( embedded );
+        packageEntry.EmbeddedPackagesL( embedded );
+        if( embedded.Count() )
+            {
+            // For each embadded sis we notify storage - recursive call
+            for( TInt i = 0; i < embedded.Count(); ++i )
+                {
+                HandleInstallNotifyL( embedded[i]->Uid().iUid );
+                }
+            }
+        else
+            {
+            // There are no embaddes sis', so we can notify storage
+            // of changes in apps included in packageEntry
+            NotifyL( packageEntry );
+            }
+        embedded.ResetAndDestroy();
+        CleanupStack::PopAndDestroy( &embedded );
+        CleanupStack::PopAndDestroy( &packageEntry );
+        }
+    CleanupStack::PopAndDestroy( &iSisRegSession );
+    CleanupStack::PopAndDestroy( &uids );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::NotifyL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::NotifyL( Swi::RSisRegistryEntry & aPackageEntry )
+    {
+    // Get sids ( == uids of exetucables included in aPackageEntry )
+    RArray<TUid> sids;
+    CleanupClosePushL( sids );
+    aPackageEntry.SidsL( sids );
+    if( sids.Count() )
+        {
+        // For each sid we notify storage
+        for( TInt i = 0; i < sids.Count(); ++i )
+            {
+            iInstalledPackages.Append( sids[i].iUid );
+            }
+        }
+    CleanupStack::PopAndDestroy( &sids );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::NotifyL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::NotifyL( TInt aAppUid )
+    {
+    // Get entries for given aAppUid
+    RPointerArray<CCaInnerEntry> resultArray;
+    CleanupResetAndDestroyPushL( resultArray );
+    GetCaAppEntriesL( aAppUid, resultArray );
+    if( resultArray.Count() )
+        {
+        iCaStorageProxy.AddL( resultArray[0] );
+        }
+    CleanupStack::PopAndDestroy( &resultArray );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::AddEntryToDownloadedCollectionL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::AddEntryToDownloadedCollectionL( TInt aEntryId )
+    {
+    TCaOperationParams params = { TCaOperationParams::EPrepend, GetCollectionDownloadIdL(), 0 // not used
+    		};
+
+    RArray<TInt> entryIds;
+    CleanupClosePushL( entryIds );
+    entryIds.AppendL( aEntryId );
+    iCaStorageProxy.OrganizeL( entryIds, params );
+
+    CleanupStack::PopAndDestroy( &entryIds );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::RemoveToDownloadedCollectionL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RemoveEntryFromDownloadedL( TInt aEntryId )
+    {
+    TCaOperationParams params = { TCaOperationParams::ERemove, GetCollectionDownloadIdL(), 0 // not used
+    		};
+
+    RArray<TInt> entryIds;
+    CleanupClosePushL( entryIds );
+    entryIds.AppendL( aEntryId );
+    iCaStorageProxy.OrganizeL( entryIds, params );
+
+    CleanupStack::PopAndDestroy( &entryIds );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::ScheduleScan
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::ScheduleScan()
+    {
+    if( !IsActive() )
+        {
+        TRequestStatus* ownStatus = &iStatus;
+        *ownStatus = KRequestPending;
+        SetActive();
+        User::RequestComplete( ownStatus, KErrNone );
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::AddAppItemL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::AddAppEntryL( TUint aUid, TUint aCurrentMmcId )
+    {
+    // Now add the app entry.
+    CCaInnerEntry* appEntry = CCaInnerEntry::NewLC();
+
+    appEntry->SetEntryTypeNameL( KCaTypeApp );
+    appEntry->SetUid( aUid );
+    appEntry->SetFlags( EVisible );
+    appEntry->SetRole( EItemEntryRole );
+
+    SetApaAppInfoL( appEntry );
+    HandleLockDeleteFlagUpdateL( appEntry );
+    HandleMmcAttrUpdateL( appEntry, aCurrentMmcId );
+
+    iCaStorageProxy.AddL( appEntry );
+    if( iInstalledPackages.Find( aUid ) != KErrNotFound )
+        {
+        AddEntryToDownloadedCollectionL( appEntry->GetId() );
+        }
+    RemoveFromInstalledPackages( aUid );
+
+    CleanupStack::PopAndDestroy( appEntry );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::RemoveFromInstalledPackages
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RemoveFromInstalledPackages( TUint aUid )
+    {
+    TInt appIndex = iInstalledPackages.Find( aUid );
+    if( appIndex != KErrNotFound )
+        {
+        iInstalledPackages.Remove( appIndex );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CCaSrvAppScanner::IsMidletL
+// Checks if given app is midlet by reading the apptype uid (2nd uid)
+// ---------------------------------------------------------------------------
+//
+TBool CCaSrvAppScanner::SetApaAppInfoL( CCaInnerEntry* aEntry )
+    {
+    TBool changed( EFalse );
+    TApaAppInfo info;
+    if( KErrNone == iSrvEngUtils.GetAppInfo( *aEntry, info ) )
+        {
+        RBuf attrVal;
+        attrVal.CleanupClosePushL();
+        attrVal.CreateL( KCaMaxAttrValueLen );
+        aEntry->FindAttribute( KCaAttrLongName, attrVal );
+        if( attrVal.Compare( info.iCaption ) != KErrNone
+                || aEntry->GetText().Compare( info.iShortCaption )
+                        != KErrNone )
+            {
+            aEntry->SetTextL( info.iShortCaption );
+            aEntry->AddAttributeL( KCaAttrLongName, info.iCaption );
+            changed = ETrue;
+            }
+        CleanupStack::PopAndDestroy( &attrVal );
+        }
+    return changed;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::HandleMissingItemsL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::HandleMissingItemsL(
+        RPointerArray<CCaInnerEntry>& aCaEntries )
+    {
+    for( TInt i = 0; i < aCaEntries.Count(); i++ )
+        {
+        const TInt id = aCaEntries[i]->GetId();
+        TUint mmcId = 0;
+        RBuf attrVal;
+        attrVal.CleanupClosePushL();
+        attrVal.CreateL( KCaMaxAttrValueLen );
+        if( aCaEntries[i]->FindAttribute( KCaAttrMmcId(), attrVal ) )
+            {
+            MenuUtils::GetTUint( attrVal, mmcId );
+            if( mmcId && KErrNotFound != iMmcHistory->Find( mmcId )
+                    && mmcId != CurrentMmcId() )
+                {
+                // This item is on an MMC which is currently in the MMC history.
+                // Set it "missing" but keep it.
+                AddObjectFlagL( aCaEntries[i], EMissing );
+                }
+            else if ( attrVal == KCaMassStorage()
+                    && IsDriveInUse( DriveInfo::EDefaultMassStorage ) )
+                {
+                AddObjectFlagL( aCaEntries[i], EMissing );
+                }
+            else
+                {
+                RemoveAppL( aCaEntries[i] );
+                }
+            }
+        else
+            {
+            RemoveAppL( aCaEntries[i] );
+            }
+        CleanupStack::PopAndDestroy( &attrVal );
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::RemoveAppL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::RemoveAppL( CCaInnerEntry* aAppEntry )
+    {
+    RArray<TInt> idsToRemove;
+    CleanupClosePushL( idsToRemove );
+    idsToRemove.AppendL( aAppEntry->GetId() );
+    iCaStorageProxy.RemoveL( idsToRemove );
+    CleanupStack::PopAndDestroy( &idsToRemove );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::AddObjectFlagL
+// ---------------------------------------------------------
+//
+void CCaSrvAppScanner::AddObjectFlagL(
+        CCaInnerEntry* aEntry, const TInt& aFlags )
+    {
+    TBool itemFlagPresent = ( 0 != ( aEntry->GetFlags() & aFlags ) );
+    if( !itemFlagPresent )
+        {
+        aEntry->SetFlags( aEntry->GetFlags() | aFlags );
+        iCaStorageProxy.AddL( aEntry );
+        }
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::UpdateMmcHistoryL
+// ---------------------------------------------------------
+//
+TUint CCaSrvAppScanner::UpdateMmcHistoryL()
+    {
+    TUint mmcId = CurrentMmcId();
+    if( mmcId )
+        {
+        iMmcHistory->InsertL( mmcId );
+        iMmcHistory->SaveL( iFs, KCaMmcHistoryFname() );
+        }
+    return mmcId;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::CurrentMmcId
+// ---------------------------------------------------------
+//
+TUint CCaSrvAppScanner::CurrentMmcId() const
+    {
+    // Get mmc id. Errors are ignored.
+    TUint mmcId = 0;
+    TInt mmcDrive;
+    TInt err;
+    err = DriveInfo::GetDefaultDrive(
+            DriveInfo::EDefaultRemovableMassStorage, mmcDrive );
+    if( !err )
+        {
+        TVolumeInfo volumeInfo;
+        err = iFs.Volume( volumeInfo, mmcDrive );
+        if( !err )
+            {
+            mmcId = volumeInfo.iUniqueID;
+            }
+        }
+    return mmcId;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::IsFileInDrive
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::IsFileInDrive(
+        const TDesC& aFileName,
+        const DriveInfo::TDefaultDrives& aDefaultDrive ) const
+        {
+        if ( aFileName.Length() )
+            {
+            TInt mmcDrive;
+        TInt err = DriveInfo::GetDefaultDrive( aDefaultDrive, mmcDrive );
+        if( !err )
+            {
+            TInt fileDrive;
+            err = RFs::CharToDrive( aFileName[0], fileDrive );
+            if( !err && fileDrive == mmcDrive )
+                {
+                return ETrue;
+                }
+            }
+        }
+    return EFalse;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::IsAppInDrive
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::IsAppInDrive(
+        const TUid aUid,
+        const DriveInfo::TDefaultDrives& aDefaultDrive ) const
+    {
+    TBool ret( EFalse );
+    TApaAppInfo info;
+    TInt err = iApaLsSession.GetAppInfo( info, aUid );
+    if( !err && IsFileInDrive( info.iFullName, aDefaultDrive ) )
+        {
+        ret = ETrue;
+        }
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::IsInMmc
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::IsInMmc( const TUid aUid ) const
+    {
+    return IsAppInDrive( aUid, DriveInfo::EDefaultRemovableMassStorage );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::IsInMassStorage
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::IsInMassStorage( const TUid aUid ) const
+    {
+    return IsAppInDrive( aUid, DriveInfo::EDefaultMassStorage );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::IsInRom
+// ---------------------------------------------------------
+//
+TBool CCaSrvAppScanner::IsInRom( TInt aUid )
+    {
+    return IsAppInDrive( TUid::Uid( aUid ), DriveInfo::EDefaultRom );
+    }
+
+// ---------------------------------------------------------
+// CCaSrvAppScanner::IsDriveInUse
+// ---------------------------------------------------------
+//
+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;
+    }
+
+// ==================== MEMBER FUNCTIONS ====================
+
+// ---------------------------------------------------------
+// TAppAtributes::TAppAtributes
+// ---------------------------------------------------------
+//
+TCaAppAtributes::TCaAppAtributes( TUint aUid )
+    {
+    iUid = aUid;
+    }
+
+// ---------------------------------------------------------
+// TAppAtributes::GetUid
+// ---------------------------------------------------------
+//
+TUint TCaAppAtributes::GetUid() const
+    {
+    return iUid;
+    }
+
+// ---------------------------------------------------------
+// TAppAtributes::MatchItems
+// ---------------------------------------------------------
+//
+TBool TCaAppAtributes::MatchItems( const TCaAppAtributes& item1,
+        const TCaAppAtributes& item2 )
+    {
+    return item1.GetUid() == item2.GetUid();
+    }
+