ui/uiengine/medialists/src/glxcachemanager.cpp
changeset 23 74c9f037fd5d
child 24 99ad1390cd33
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/uiengine/medialists/src/glxcachemanager.cpp	Fri Mar 19 09:28:59 2010 +0200
@@ -0,0 +1,1568 @@
+/*
+* Copyright (c) 2008-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:    Manager of media item cache
+*
+*/
+
+
+
+
+#include "glxcachemanager.h"
+
+#include <mpxcollectionutility.h>
+#include <glxtracer.h>
+#include <glxthumbnailattributeinfo.h>
+#include <glxthumbnail.h>
+#include <glxsingletonstore.h>
+#include <glximageviewermanager.h>
+
+#include "glxcache.h"
+#include "glxerrormanager.h"
+#include "glxgarbagecollector.h"
+#include "glxmedialist.h"
+#include <hal.h>
+#include <glxcollectionpluginimageviewer.hrh>
+#include <mpxmediacollectiondetaildefs.h>
+#include <mpxmediadrmdefs.h>
+#include <f32file.h>
+#include <lbsposition.h>
+#include <apgcli.h>
+#include <caf/content.h>
+#include <caf/attributeset.h>
+#include <DRMHelper.h>
+
+#ifdef USE_S60_TNM
+#include <thumbnaildata.h>
+const TInt KMaxGridThumbnailWidth = 200;
+_LIT(KFileIdentifier, ":\\");
+#endif
+
+_LIT(KDefaultType, "image/jpg");
+/// How long to wait before rechecking for cleared temporary errors
+/// @todo Find optimal value for this
+const TInt KGlxTemporaryErrorRecheckPeriodInSeconds = 5;
+
+const TInt KGlxLowerMemoryLimitForCleanUp = 15000000;
+
+const TInt KGlxUpperMemoryLimitForCleanUp = 25000000;
+
+//Defining number of pages to be flushed in critical low memory conditions.
+const TInt KGlxNoOfPagesToFlushInCriticalLowMemory = 4;
+// -----------------------------------------------------------------------------
+// InstanceL
+// -----------------------------------------------------------------------------
+//
+CGlxCacheManager* CGlxCacheManager::InstanceL()
+	{
+	TRACER("CGlxCacheManager::InstanceL");
+	
+	return CGlxSingletonStore::InstanceL(&NewL);
+	}
+
+// -----------------------------------------------------------------------------
+// NewL
+// -----------------------------------------------------------------------------
+//
+CGlxCacheManager* CGlxCacheManager::NewL()
+    {
+    TRACER("CGlxCacheManager::NewL");
+    
+    CGlxCacheManager* self = new( ELeave ) CGlxCacheManager();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// Close
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::Close()
+	{
+	TRACER("CGlxCacheManager::Close");
+	
+	CGlxSingletonStore::Close(this);
+	}
+
+// -----------------------------------------------------------------------------
+// Constructor
+// -----------------------------------------------------------------------------
+//
+CGlxCacheManager::CGlxCacheManager()
+    {
+    TRACER("CGlxCacheManager::Default Constructor");
+    
+    }
+    
+// -----------------------------------------------------------------------------
+// ConstructL
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::ConstructL()
+    {
+    TRACER("CGlxCacheManager::ConstructL");
+    
+    iGarbageCollector = CGlxGarbageCollector::NewL( iCaches );
+    iTempErrorTimer = CPeriodic::NewL(CActive::EPriorityStandard);
+    iSchedulerWait = new (ELeave) CActiveSchedulerWait();
+    iMaintainCacheCallback = new ( ELeave )
+	    CAsyncCallBack( TCallBack( MaintainCacheL, this ), CActive::EPriorityStandard );
+	    
+#ifdef USE_S60_TNM
+    iTnEngine = CThumbnailManager::NewL( *this);
+    iTnEngine->SetDisplayModeL( EColor64K );
+#endif
+    }
+        
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CGlxCacheManager::~CGlxCacheManager()
+	{
+	TRACER("CGlxCacheManager::Destructor");
+	
+    delete iSchedulerWait;
+ 	iObserverList.ResetAndDestroy();
+ 	iCaches.ResetAndDestroy();
+ 	delete iTempThumbnail;
+ 	iRequestedItemIds.Reset();
+ 	iRequestedAttrs.Reset();
+ 	iRequestedItemIndexes.Reset();
+    if(iReader)
+        {
+        delete iReader;
+        }
+
+ 	delete iGarbageCollector;
+
+    if (iTempErrorTimer)
+        {
+		iTempErrorTimer->Cancel();	
+		delete iTempErrorTimer;
+        }
+
+#ifdef USE_S60_TNM
+    GLX_DEBUG2("CGlxCacheManager::~CGlxCacheManager() TN Ids count()=%d",
+										 iThumbnailRequestIds.Count());
+    for (TInt i = 0; i < iThumbnailRequestIds.Count(); i++)
+        {
+        iTnEngine->CancelRequest(iThumbnailRequestIds[i].iId);
+        }
+	iThumbnailRequestIds.Reset();
+    delete iTnEngine;
+    delete iMPXMedia;
+#endif
+    
+    delete iMaintainCacheCallback;
+	}
+
+// -----------------------------------------------------------------------------
+// HandleWindowChangedL
+// From MVieMediaItemListManager
+// The list calls this function to hint the list manager, that the items 
+// the list contains might not all be loaded, and it would be nice if the list
+// manager could load the missing items to the cache.
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::HandleWindowChangedL(CGlxMediaList* /*aList*/) 
+	{
+	TRACER("CGlxCacheManager::HandleWindowChangedL");
+	
+	GLX_LOG_INFO("---- MGallery - CGlxCacheManager::HandleWindowChangedL()---- ");
+    
+    iMaintainCacheCallback->CallBack();
+    // Its Better if we are not Cleaning Cache here; Instaed Can Do inside MainTainCache
+    //MaintainCacheL();
+    //iGarbageCollector->Cleanup();
+    }
+
+// -----------------------------------------------------------------------------
+// CancelPreviousRequest
+// This API cancels the pending attributes and thumbnail request  
+// when the media item in focus is NULL
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::CancelPreviousRequest()
+	{
+	TRACER("CGlxCacheManager::CancelPreviousRequest");		
+	
+	// iRequestOwner is NULL, if there are no pending attribute/thumbnail request
+	// If no pending request, do nothing, else cancel the the pending requests
+	if(iRequestOwner)
+		{		
+		MMPXCollection& collection = iRequestOwner->Collection();
+		// Cancel the pending attribute request
+		collection.CancelRequest();	
+		
+#ifdef USE_S60_TNM
+		GLX_DEBUG2("CGlxCacheManager::CancelPreviousRequest() iThumbnailRequestIds.Count() %d", iThumbnailRequestIds.Count());
+		
+		// Check if any thumbnail requests are pending and cancel the requests.		
+		for (TInt i = 0; i < iThumbnailRequestIds.Count(); i++)
+			{ 			
+			iTnEngine->CancelRequest(iThumbnailRequestIds[i].iId);									
+			}
+		iThumbnailRequestIds.Reset();		
+#endif
+		iRequestOwner = NULL;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// HandleGarbageCollection
+// Garbage Collection Quick or with Timer
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::HandleGarbageCollectionL(TBool aStart)
+    {
+    TRACER("CGlxCacheManager::HandleGarbageCollection");
+    TInt freeMemory = 0;
+    
+    HAL::Get( HALData::EMemoryRAMFree, freeMemory );
+        
+    if(aStart)
+        {
+           if(freeMemory < KGlxLowerMemoryLimitForCleanUp)
+               {
+               // 2 page - 30 Items for Flush
+               TInt count = 2;  
+               if(freeMemory < (KGlxLowerMemoryLimitForCleanUp/2))
+                   {
+                   // If Memory is below this limit it's ok i can wait for 60 items to clean-up
+                   count = KGlxNoOfPagesToFlushInCriticalLowMemory;
+                   }
+               // Cancel Clean-up before Flush Page; Clean-up will be starting just after Flush page
+               iGarbageCollector->CancelCleanup(); 
+               iGarbageCollector->FlushPagesL(count);
+               iGarbageCollector->CleanupL();
+               iCleanUpOnGoing = ETrue;         // Clean up is Started now i can call CancelClean-up to Stop Clean Up
+               }
+           else if((freeMemory < KGlxUpperMemoryLimitForCleanUp) && !iCleanUpOnGoing)
+               {
+               iGarbageCollector->CleanupL();
+               iCleanUpOnGoing = ETrue;         // Clean up is Started now i can call CancelClean-up to Stop Clean Up
+               }
+           // This is Added to Keep Assure Clean-up is not going to Disturb normal Flow if there is Enough Memory
+           // We Remove this Code After Evaluation of Use of this Code
+           else if(iCleanUpOnGoing)
+               {
+               iGarbageCollector->CancelCleanup();
+               iCleanUpOnGoing = EFalse;
+               }
+               
+           }
+       else if(freeMemory < KGlxLowerMemoryLimitForCleanUp)
+           {
+           // 2 page - 30 Items for Flush
+           TInt count = 2;
+           if(freeMemory < (KGlxLowerMemoryLimitForCleanUp/2))
+               {
+               // If Memory is below this limit it's ok i can wait for 60 items to clean-up
+               count = KGlxNoOfPagesToFlushInCriticalLowMemory;
+               }
+           // Cancel Clean-up before Flush Page; Clean-up will be starting just after Flush page
+           iGarbageCollector->CancelCleanup();
+           iGarbageCollector->FlushPagesL(count);
+        iGarbageCollector->CleanupL();
+        iCleanUpOnGoing = ETrue;         // Clean up is Started now i can call CancelClean-up to Stop Clean Up
+        }
+    else if(iCleanUpOnGoing)
+        {
+        iGarbageCollector->CancelCleanup();
+        iCleanUpOnGoing = EFalse;
+        }
+    }
+		
+// -----------------------------------------------------------------------------
+// Match
+// return ETrue if path levels match
+// -----------------------------------------------------------------------------
+//
+TBool CGlxCacheManager::Match(const CMPXCollectionPath& aPath1, 
+		const CMPXCollectionPath& aPath2)
+	{
+	TRACER("CGlxCacheManager::Match");
+	
+	TInt levels1 = aPath1.Levels();
+	TInt levels2 = aPath2.Levels();
+	
+	// Paths must be as deep to match
+	if (levels1 != levels2) 
+		{
+		return EFalse; 
+		}
+		
+	// Check if all levels match
+	for (TInt i = 0; i < levels1; i++) 
+		{
+		if (aPath1.Index(i) != aPath2.Index(i))
+			{
+			return EFalse;
+			}
+		}
+		
+	return ETrue;
+	}
+	
+// -----------------------------------------------------------------------------
+// HandleCollectionMediaL
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::HandleCollectionMediaL(const TGlxIdSpaceId& aIdSpaceId, const CMPXMedia& aMedia, TInt aError)
+    {
+    TRACER("CGlxCacheManager::HandleCollectionMediaL");
+    
+    iRequestOwner = NULL;
+
+    if ( KErrNone == aError )
+        {
+        // Update the cache
+        CGlxCache* cache = FindCacheForceCreateL(aIdSpaceId);
+        cache->MediaUpdatedL(aMedia);
+        }
+    else
+        {
+        RPointerArray< MGlxMediaUser > users;
+        CleanupClosePushL( users );
+        
+        // Record the error on all requested attributes
+        TInt idCount = iRequestedItemIds.Count();
+        
+        for( TInt idIndex = 0; idIndex < idCount; idIndex++ )
+            {
+            CGlxMedia* item = MediaForceCreateL(aIdSpaceId, iRequestedItemIds[idIndex]);
+            GlxErrorManager::SetAttributeErrorL(item, iRequestedAttrs, aError);
+            
+            // Keep track of media lists to notify later
+            TInt userCount = item->UserCount();
+            for ( TInt userIndex = 0; userIndex < userCount; userIndex++ )
+                {
+                users.InsertInAddressOrder( &item->User( userIndex ) );
+                }
+            }
+
+        // Notify all affected users of error
+        TInt userCount = users.Count();
+        for ( TInt i = 0; i < userCount; i++ )
+            {
+            users[ i ]->HandleError( aError );
+            }
+
+        CleanupStack::PopAndDestroy( &users );
+        }
+    
+    MaintainCacheL();
+    }
+
+// -----------------------------------------------------------------------------
+// FindCacheForceCreateL
+// -----------------------------------------------------------------------------
+//
+CGlxCache* CGlxCacheManager::FindCacheForceCreateL(const TGlxIdSpaceId& aIdSpaceId)
+    {
+    TRACER("CGlxCacheManager::FindCacheForceCreateL");
+    
+    CGlxCache* cache = NULL;
+
+    // Look for existing cache
+    TInt index = iCaches.FindInOrder(aIdSpaceId, (&CacheOrderByKey));
+    if ( KErrNotFound == index )
+        {
+        // Not found: create one
+    	TLinearOrder<CGlxCache> orderer (&CacheOrderById);
+        cache = new (ELeave) CGlxCache(aIdSpaceId, this);
+
+        CleanupStack::PushL(cache);
+        iCaches.InsertInOrderL(cache, orderer);
+        CleanupStack::Pop(cache);
+        }
+    else
+        {
+        cache = iCaches[index];
+        }
+
+    return cache;
+    }
+    
+// -----------------------------------------------------------------------------
+// Media
+// -----------------------------------------------------------------------------
+//
+CGlxMedia* CGlxCacheManager::Media( const TGlxIdSpaceId& aIdSpaceId, 
+        const TGlxMediaId& aMediaId ) const
+    {
+    TRACER("CGlxCacheManager::Media");
+    
+    // Look for the correct subcache
+    TInt index = iCaches.FindInOrder( aIdSpaceId, &CacheOrderByKey );
+    
+    if ( KErrNotFound == index )
+        {
+        // No caches exist with this space id
+        return NULL;
+        }
+    else
+        {
+        return iCaches[index]->Media( aMediaId );
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// MediaForceCreateL
+// -----------------------------------------------------------------------------
+//
+CGlxMedia* CGlxCacheManager::MediaForceCreateL(const TGlxIdSpaceId& aIdSpaceId, const TGlxMediaId& aMediaId)
+    {
+    TRACER("CGlxCacheManager::MediaForceCreateL");
+    
+    CGlxCache* cache = FindCacheForceCreateL(aIdSpaceId);
+    return cache->FindItemForceCreateL(aMediaId);
+    }
+    
+// -----------------------------------------------------------------------------
+// AddObserverL
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::AddObserverL(MGlxCacheObserver* aObserver)
+    {
+    TRACER("CGlxCacheManager::AddObserverL");
+    
+    if ( aObserver )
+        {
+        if ( KErrNotFound == iObserverList.Find( aObserver ))
+            {
+            iObserverList.AppendL(aObserver);
+            }
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// RemoveObserver
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::RemoveObserver(MGlxCacheObserver* aObserver)
+    {
+    TRACER("CGlxCacheManager::RemoveObserver");
+    
+    if ( aObserver )
+        {
+        TInt index = iObserverList.Find( aObserver );
+        if ( KErrNotFound != index )
+            {
+            iObserverList.Remove(index);
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Refresh
+// ---------------------------------------------------------------------------
+//
+void CGlxCacheManager::RefreshL()
+    {
+    TRACER("CGlxCacheManager::Refresh");
+    
+    if ( !iRequestOwner )
+        {
+        // Currently idle, so trigger timer immediately to begin refresh
+        iTempErrorTimer->Cancel();
+        iTempErrorTimer->Start( 0, 0,
+                            TCallBack( TempErrorTimerCallbackL, this ) );
+        
+        HandleGarbageCollectionL(ETrue);  // Clean-up is needed here; Considering Current Memory Condition
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// MaintainCache
+// -----------------------------------------------------------------------------
+//
+TInt CGlxCacheManager::MaintainCacheL(TAny* aPtr)
+    {
+    TRACER("CGlxCacheManager::MaintainCache");
+    
+    CGlxCacheManager* self
+                    = reinterpret_cast<CGlxCacheManager*>( aPtr );
+    self->MaintainCacheL();
+    
+    // Clean-up is needed here; Considering Current Memory Condition
+    // For Every HandleWindowChangedL; We Should not do Clean-up 
+    self->HandleGarbageCollectionL(ETrue);  
+    return 0;
+    }
+    
+// -----------------------------------------------------------------------------
+// MaintainCacheL
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::MaintainCacheL() 
+    {
+    TRACER("CGlxCacheManager::MaintainCacheL");
+    
+	// Handle lists in priority order: all data for the highest priority list 
+	// is retrieved before the data for a lower priority list. NOTE: This
+	// may need to be changed, since it might not always lead to the best
+	// user experienced. (It may be sensible to retrieve item properties
+	// for a lower priority list before all thumbnails for a higher priority 
+	// list, but this probably depends on the speed of the data sources.
+	// It might be wise to decouple the contexts from the media lists
+
+    if (!iRequestOwner)
+        {
+        iTempError = EFalse;
+        iTempErrorTimer->Cancel();
+
+    	RPointerArray<CGlxMediaList>& mediaLists = CGlxMediaList::MediaListsL();
+     	iRequestedItemIds.Reset();
+     	iRequestedAttrs.Reset();
+    	iRequestedItemIndexes.Reset();
+    	
+    	TInt listCount = mediaLists.Count();
+
+    	// Request attributes in the fetch contexts
+        for (TInt listIndex = 0; listIndex < listCount && !iRequestOwner; listIndex++)      
+            {
+            CGlxMediaList* list = mediaLists[listIndex];
+
+    		CMPXAttributeSpecs* attrSpecs = NULL;
+
+    		list->AttributeRequestL(iRequestedItemIndexes, iRequestedItemIds, iRequestedAttrs, attrSpecs );
+    		CleanupStack::PushL(attrSpecs);
+
+            TInt itemIdsCount = iRequestedItemIds.Count();
+            if (itemIdsCount > 0)
+                {
+                if (attrSpecs)
+                    {
+                    GLX_DEBUG2("CGlxCacheManager::MaintainCacheL() attrSpecs->Count() %d", attrSpecs->Count());
+                    }
+                
+                TGlxMediaId itemId = iRequestedItemIds[0];
+
+                CMPXCollectionPath* path = RequestAsPathLC( *list );
+
+                // Add request for id, if does not exist already. Id is used to 
+                // identify which media object the attribute belongs to when
+                // it is returned
+                TIdentityRelation<TMPXAttribute> match (&TMPXAttribute::Match);
+                if (iRequestedAttrs.Find(KMPXMediaGeneralId, match) == KErrNotFound) 
+                    {
+                    iRequestedAttrs.AppendL(KMPXMediaGeneralId);
+                    }
+
+                // Create the empty bitmap, if the request is for a bitmap
+                TIdentityRelation<TMPXAttribute> matchContent(&TMPXAttribute::MatchContentId);
+                TMPXAttribute tnAttr(KGlxMediaIdThumbnail, 0);
+                if (iRequestedAttrs.Find(tnAttr, matchContent) != KErrNotFound) 
+                    {
+#ifdef USE_S60_TNM
+					if (iRequestedItemIndexes.Count())
+						{
+                        // Cancel Clean-up is needed here;
+                        HandleGarbageCollectionL(EFalse);                           
+						
+			            TSize tnSize;
+						const TMPXAttributeData sizeAttrib = { KGlxMediaIdThumbnail , KGlxAttribSpecThumbnailSize };
+      					if (attrSpecs && attrSpecs->IsSupported(sizeAttrib))
+                        	{
+				    		tnSize = attrSpecs->ValueTObjectL<TSize>(sizeAttrib);
+                        	}
+
+						const TGlxMedia& item = list->Item( iRequestedItemIndexes[0] );
+      					TBool priority = ETrue;
+      					const TMPXAttributeData priorityAttrib = { KGlxMediaIdThumbnail , KGlxAttribSpecThumbnailQualityOverSpeed };
+      					if (attrSpecs && attrSpecs->IsSupported(priorityAttrib))
+      					    {
+      					    priority = attrSpecs->ValueTObjectL<TBool>(priorityAttrib);
+      					    }
+      					
+						TGlxIdSpaceId spaceId = list->IdSpaceId(iRequestedItemIndexes[0]);	
+#ifdef MEDIA_ID_BASED_TN_FETCH_ENABLED
+	               	 	GLX_DEBUG2("CGlxCacheManager::MaintainCacheL() requesting TN attribute (Medialist) itemId %d", itemId.Value());
+						if (item.Uri().Find(KFileIdentifier) != KErrNotFound ||
+						    item.Uri().Length() && itemId.Value())
+#else
+	               	 	GLX_DEBUG1("CGlxCacheManager::MaintainCacheL() requesting TN attribute (Medialist) Uri");
+						if (item.Uri().Find(KFileIdentifier) != KErrNotFound)
+#endif
+							{
+#ifdef _DEBUG
+							iStartTime.HomeTime(); // Get home time
+#endif							
+						    if (tnSize.iWidth < KMaxGridThumbnailWidth)
+						    	{
+						    	iTnEngine->SetFlagsL(CThumbnailManager::ECropToAspectRatio);
+							    iTnEngine->SetThumbnailSizeL(EGridThumbnailSize);
+							    GLX_DEBUG1("MaintainCacheL() - Fetch TN attrib - EGridThumbnailSize");
+						    	}
+						    else
+							    {
+							    iTnEngine->SetFlagsL(CThumbnailManager::EDefaultFlags);
+							    iTnEngine->SetThumbnailSizeL(EFullScreenThumbnailSize);
+                                GLX_DEBUG1("MaintainCacheL() - Fetch TN attrib - EFullScreenThumbnailSize");							    
+							    }
+						    
+						    if (priority)
+						        {
+						        iTnEngine->SetQualityPreferenceL(CThumbnailManager::EOptimizeForQuality);
+                                GLX_DEBUG1("MaintainCacheL() - Fetch TN attrib - EOptimizeForQuality");                                
+						        }
+						    else
+						        {
+						        iTnEngine->SetQualityPreferenceL(CThumbnailManager::EOptimizeForQualityWithPreview);
+                                GLX_DEBUG1("MaintainCacheL() - Fetch TN attrib - EOptimizeForQualityWithPreview");                                
+                                }
+                            
+                            if (list->Collection().UidL().iUid == KGlxCollectionPluginImageViewerImplementationUid)
+                                {
+                                GLX_DEBUG1("void CGlxCacheManager::MaintainCacheL:Imageviewer TN");
+                                _LIT( KPrivateFolder, "\\Private\\" );    // Platsec private folder  
+                                TParsePtrC parse( item.Uri() );
+                                if( parse.PathPresent() &&
+                                    parse.Path().Length() > KPrivateFolder().Length() &&
+                                    parse.Path().Left( KPrivateFolder().Length() ).CompareF( KPrivateFolder ) == 0 )
+                                    {
+                                    CGlxImageViewerManager *imageVwrMgr = CGlxImageViewerManager::InstanceL();
+									CleanupClosePushL(*imageVwrMgr);
+                                    GLX_DEBUG1("KGlxCollectionPluginImageViewerImplementationUid - Fetch (Private) TN!");
+                                    if ( &(imageVwrMgr->ImageFileHandle()) != NULL )
+                                        {
+                                        //CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC(imageVwrMgr->ImageFileHandle());
+                                        CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC(imageVwrMgr->ImageUri()->Des(), 0);
+                                        iThumbnailRequestIds.AppendL(TLoadingTN(iTnEngine->GetThumbnailL(*source), spaceId, tnSize, itemId));
+                                        CleanupStack::PopAndDestroy(source);
+                                        }
+                                    CleanupStack::PopAndDestroy(imageVwrMgr);	
+                                    }
+                                else
+                                    {
+                                    GLX_DEBUG1("void CGlxCacheManager::MaintainCacheL:Imageviewer In else");
+                                    GLX_DEBUG2("CGlxCacheManager::MaintainCacheL: uri %S", &item.Uri());	
+                                    CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC(item.Uri(), 0);
+                                    iThumbnailRequestIds.AppendL(TLoadingTN(iTnEngine->GetThumbnailL(*source), spaceId, tnSize, itemId));
+                                    CleanupStack::PopAndDestroy(source);
+                                    }
+                                }
+                            else
+                                {
+#ifdef MEDIA_ID_BASED_TN_FETCH_ENABLED
+						    iThumbnailRequestIds.AppendL(TLoadingTN(iTnEngine->GetThumbnailL(itemId.Value()), spaceId, tnSize, itemId));
+#else
+						    CThumbnailObjectSource* source = CThumbnailObjectSource::NewLC(item.Uri(), 0);
+						    iThumbnailRequestIds.AppendL(TLoadingTN(iTnEngine->GetThumbnailL(*source), spaceId, tnSize, itemId));
+						    CleanupStack::PopAndDestroy(source);
+#endif
+                                }
+		                    iThumbnailId = itemId;
+							}
+						else
+							{
+		                    delete iTempThumbnail;
+		                    iTempThumbnail = NULL;
+		                    iTempThumbnail = new (ELeave) CFbsBitmap;
+		                    User::LeaveIfError(iTempThumbnail->Create(TSize(), KGlxThumbnailDisplayMode));
+		                    iThumbnailId = itemId;
+	               		 	GLX_DEBUG2("CGlxCacheManager::MaintainCacheL() requesting TN (DataSourceMde) attribute itemId %d", itemId.Value());
+
+		                    // Set bitmap handle in attribute spec
+		                    if (attrSpecs)
+		                        {
+		                        TMPXAttribute thHandleAttrSpec(KGlxMediaIdThumbnail, KGlxAttribSpecThumbnailBitmapHandle);
+		                        attrSpecs->SetTObjectValueL<TInt>(thHandleAttrSpec, iTempThumbnail->Handle());
+		                        }
+
+		                    // Cancel Clean-up is needed here;
+		                    // This is Going to Highly Used Call
+		                    // Can Think about an Ulternative.
+		                    HandleGarbageCollectionL(EFalse);
+
+			                GLX_DEBUG3("MGallery - CGlxCacheManager::MaintainCacheL() requesting attribute for list %x and item %d", list, itemId.Value());
+
+			                // Use list's isolated collection
+			                MMPXCollection& collection = list->Collection();
+
+			    			// Issue the request
+			    			collection.MediaL(*path, iRequestedAttrs.Array(), attrSpecs);
+							}
+						}
+                    }
+                else
+                	{
+	                GLX_DEBUG3("MGallery - CGlxCacheManager::MaintainCacheL() requesting attribute for list %x and item %d", list, itemId.Value());
+
+	                // Use list's isolated collection
+	                MMPXCollection& collection = list->Collection();
+                    if (collection.UidL().iUid == KGlxCollectionPluginImageViewerImplementationUid)
+                        {
+                        CGlxImageViewerManager *imageVwrMgr = CGlxImageViewerManager::InstanceL();
+						CleanupClosePushL(*imageVwrMgr);
+                        TInt mediaCnt = list->Count();
+                        TInt errInImage = KErrNone;
+ 
+                        
+                        GLX_DEBUG3("Image Viewer Collection - Attrib population! mediaCnt=%d, Media Id=%d",
+                                mediaCnt, itemId.Value());
+                        
+                        delete iMPXMedia;
+                        iMPXMedia = NULL;
+
+                        TFileName fileName(KNullDesC);
+                        //retrieve the filename as per the caller app.
+                        if(imageVwrMgr->IsPrivate())
+                            {
+                            const TGlxMedia& item = list->Item( iRequestedItemIndexes[0] );
+                            // If there is an URI available, then the request is due to EPathChanged message 
+                            // due to a file save from Image Viewer, and attribs needs to be re-populated. 
+                            // So, use the same URI; Oherwise getting fullname from handle might result in a crash.
+                            if (item.Uri().Length())
+                                {
+                                fileName.Append(item.Uri());
+                                }
+                            else
+                                {
+                                // private path
+                                RFile64& imageHandle = imageVwrMgr->ImageFileHandle();
+                                if ( &imageHandle != NULL )
+                                    {
+                                    fileName.Append(imageHandle.FullName(fileName));
+                                    }
+                                else
+                                    {
+                                    errInImage = KErrArgument;
+                                    }   
+                                }
+                            }
+                        else
+                            {
+                            // user data path
+                            if(  imageVwrMgr->ImageUri() != NULL  )
+                                {
+                                fileName.Append(imageVwrMgr->ImageUri()->Des());
+                                RFs fs;
+                                CleanupClosePushL(fs);
+                                TInt err = fs.Connect();   
+                                errInImage = KErrArgument;
+                                if(err == KErrNone)
+                                    {
+                                    if (fs.IsValidName(fileName))
+                                        {
+                                        errInImage = KErrNone;
+                                        }
+                                    }
+                                CleanupStack::PopAndDestroy(&fs);
+                                }
+                            else
+                                {
+                                errInImage = KErrArgument;
+                                }
+                            }
+
+                        iMPXMedia = CMPXMedia::NewL();
+
+                        if (errInImage != KErrNone)
+                            {
+                            HandleGarbageCollectionL(EFalse);
+                            CleanupStack::PopAndDestroy(path);
+                            iRequestOwner = list;
+                            CleanupStack::PopAndDestroy(attrSpecs); 
+                            TGlxIdSpaceId spaceId = list->IdSpaceId(iRequestedItemIndexes[0]);
+                            HandleCollectionMediaL(spaceId, *iMPXMedia, KErrArgument);
+                            CleanupStack::PopAndDestroy(imageVwrMgr);
+                            return;
+                            }
+
+                        if(!iReader)
+                            {
+                            TRAP(errInImage,iReader = CGlxImageReader::NewL(*this));
+                            if(errInImage == KErrNone)
+                                {
+                                iSchedulerWait->Start();
+                                }
+                            }
+                    
+                        for ( TInt i = 0; i < iRequestedAttrs.Count(); i++ )
+                            {
+                            if ( iRequestedAttrs[i] == KMPXMediaGeneralId )
+                                {
+                                iMPXMedia->SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, 
+                                        (TMPXItemId)itemId.Value());
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralType )
+                                {
+                                iMPXMedia->SetTObjectValueL(KMPXMediaGeneralType, EMPXItem);
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralCategory )
+                                {
+                                iMPXMedia->SetTObjectValueL(KMPXMediaGeneralCategory, EMPXImage);
+                                }                           
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralUri )
+                                {
+                                iMPXMedia->SetTextValueL(KMPXMediaGeneralUri, fileName);
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralTitle )
+                                {
+                                TParsePtrC parser(fileName);
+                                iMPXMedia->SetTextValueL(KMPXMediaGeneralTitle, parser.Name());
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralDate )
+                                {
+                                TTime time;
+                                time.HomeTime();
+                                iMPXMedia->SetTObjectValueL(KMPXMediaGeneralDate, time.Int64());
+                                }
+                            else if ( iRequestedAttrs[i] == KGlxMediaGeneralLastModifiedDate )
+                                {
+                                if(errInImage == KErrNone)
+                                    {
+                                    RFs fs;
+                                    CleanupClosePushL(fs);
+                                    TInt err = fs.Connect();   
+                                    if(err == KErrNone)
+                                        {                                    
+                                        TEntry entry;   
+                                        fs.Entry(fileName,entry);    
+                                        TTime time = entry.iModified;   
+                                        iMPXMedia->SetTObjectValueL(
+                                                KGlxMediaGeneralLastModifiedDate, 
+                                                time.Int64());
+                                        }
+                                    else
+                                        {
+                                        TTime time;
+                                        time.HomeTime();
+                                        iMPXMedia->SetTObjectValueL(
+                                                KGlxMediaGeneralLastModifiedDate, 
+                                                time.Int64());
+                                        }
+                                    CleanupStack::PopAndDestroy(&fs);                                    
+                                    }
+                                else
+                                    {
+                                    TTime time;
+                                    time.HomeTime();
+                                    iMPXMedia->SetTObjectValueL(KGlxMediaGeneralLastModifiedDate, time.Int64());
+                                    }
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralSize )
+                                {
+                                if(errInImage == KErrNone)
+                                    {
+                                    if(imageVwrMgr->IsPrivate())
+                                        {
+                                        TInt64 sz = 0;
+                                        TInt err = KErrNotFound;                                      
+                                        RFile64& imageHandle = imageVwrMgr->ImageFileHandle();
+                                        if ( imageHandle.SubSessionHandle() != KNullHandle )
+                                            {
+                                            err = imageHandle.Size(sz);
+                                            }
+                                        if(err == KErrNone)
+                                            {
+                                            iMPXMedia->SetTObjectValueL(KMPXMediaGeneralSize, sz);
+                                            }
+                                        else
+                                            {
+                                            iMPXMedia->SetTObjectValueL(KMPXMediaGeneralSize, 0);                                            
+                                            }
+                                        }
+                                    else
+                                        {
+                                        RFs fs;
+                                        CleanupClosePushL(fs);
+                                        TInt err = fs.Connect();   
+                                        if(err == KErrNone)
+                                            {
+                                            TEntry entry;   
+                                            fs.Entry(fileName,entry);    
+                                            TInt sz = (TUint)entry.iSize;                                      
+                                            iMPXMedia->SetTObjectValueL(KMPXMediaGeneralSize, sz);
+                                            }
+                                        else
+                                            {
+                                            iMPXMedia->SetTObjectValueL(KMPXMediaGeneralSize, 0);
+                                            }
+                                        CleanupStack::PopAndDestroy(&fs);
+                                        }
+                                    }
+                                // If any error while image is being decoded by image decorder, Need to set
+                                // default vaule for that image. Typical case is corrupted image.
+                                else
+                                    {
+                                    iMPXMedia->SetTObjectValueL(KMPXMediaGeneralSize, 0);
+                                    }
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralDrive )
+                                {
+                                TParsePtrC parser(fileName);
+                                iMPXMedia->SetTextValueL(KMPXMediaGeneralDrive, parser.Drive());
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralMimeType )
+                                {
+                                if(errInImage == KErrNone)
+                                    {
+                                    TDataType dataType;
+                                    GetMimeTypeL(fileName, dataType);
+                                    iMPXMedia->SetTextValueL(KMPXMediaGeneralMimeType, dataType.Des());
+                                    }
+                                else
+                                    {
+                                    iMPXMedia->SetTextValueL(KMPXMediaGeneralMimeType, KDefaultType);
+                                    }                                
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralDuration )
+                                {
+                                iMPXMedia->SetTObjectValueL(KMPXMediaGeneralDuration, 0);
+                                }
+                            else if ( iRequestedAttrs[i] == KGlxMediaGeneralSystemItem)
+                                {
+                                iMPXMedia->SetTObjectValueL(KGlxMediaGeneralSystemItem, EFalse);
+                                }
+                            else if ( iRequestedAttrs[i] == KGlxMediaGeneralDimensions )
+                                {
+                                if(errInImage == KErrNone)
+                                    {
+                                    //need to fetch the original file dimensions
+                                    TSize dimensions(iImgSz.iWidth,iImgSz.iHeight);
+                                    iMPXMedia->SetTObjectValueL(KGlxMediaGeneralDimensions, dimensions);
+                                    }
+                                else
+                                    {
+                                    TSize dimensions(0,0);
+                                    iMPXMedia->SetTObjectValueL(KGlxMediaGeneralDimensions, dimensions);
+                                    }
+                                }
+                            else if ( iRequestedAttrs[i] == KGlxMediaGeneralFramecount )
+                                {
+                                TInt fcount = 1;
+                                iMPXMedia->SetTObjectValueL(KGlxMediaGeneralFramecount, fcount);
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralComment )
+                                {
+                                iMPXMedia->SetTextValueL(KMPXMediaGeneralComment, KNullDesC); 
+                                }
+                            else if (iRequestedAttrs[i] == KMPXMediaDrmProtected )
+                                {
+                                TBool protection = EFalse;
+                                if(errInImage == KErrNone)
+                                    {
+                                    protection = iReader->GetDRMRightsL
+                                    (ContentAccess::EIsProtected);
+                                    }
+                                iMPXMedia->SetTObjectValueL(KMPXMediaDrmProtected, protection);
+                                }
+                            else if ( iRequestedAttrs[i] == KGlxMediaGeneralDRMRightsValid )
+                                {
+                                TInt rightsValid = EGlxDrmRightsValidityUnknown;
+                                if(errInImage == KErrNone)
+                                    {
+                                    TBool canView = iReader->GetDRMRightsL(ContentAccess::ECanView);
+                                    rightsValid = canView ? 
+                                        EGlxDrmRightsValid : EGlxDrmRightsInvalid;
+                                    }
+                                iMPXMedia->SetTObjectValueL(KGlxMediaGeneralDRMRightsValid,
+                                                             rightsValid); 
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaGeneralCount )
+                                {
+                                iMPXMedia->SetTObjectValueL(KMPXMediaGeneralCount, 1);
+                                }
+                            else if ( iRequestedAttrs[i] == KMPXMediaColDetailSpaceId )
+                                {
+                                TGlxIdSpaceId spaceId = list->IdSpaceId(iRequestedItemIndexes[0]);
+                                iMPXMedia->SetTObjectValueL(KMPXMediaColDetailSpaceId,
+                                		 spaceId.Value());
+                                }
+                            else if ( iRequestedAttrs[i] == KGlxMediaGeneralSlideshowableContent )
+                                {
+                                iMPXMedia->SetTObjectValueL(KGlxMediaGeneralSlideshowableContent, -1);
+                                }
+                            else if ( iRequestedAttrs[i] == KGlxMediaGeneralLocation)
+                                {
+                                // Set the attribute to a TCoordinate initialised to NaN. 
+                                iMPXMedia->SetTObjectValueL(KGlxMediaGeneralLocation, TCoordinate());
+                                }
+                            else
+                                {
+                                User::Leave(KErrNotSupported);
+                                }
+                            }
+                        
+                        HandleGarbageCollectionL(EFalse);
+                        CleanupStack::PopAndDestroy(imageVwrMgr);
+                        CleanupStack::PopAndDestroy(path);
+                        iRequestOwner = list;
+                        CleanupStack::PopAndDestroy(attrSpecs); 
+                        TGlxIdSpaceId spaceId = list->IdSpaceId(iRequestedItemIndexes[0]);
+                        HandleCollectionMediaL(spaceId, *iMPXMedia, KErrNone);
+                        return;
+                        }
+                    else
+                        {
+                    // Issue the request
+                    collection.MediaL(*path, iRequestedAttrs.Array(), attrSpecs);
+                        }
+                    }
+#else // USE_S60_TNM
+                    delete iTempThumbnail;
+                    iTempThumbnail = NULL;
+                    iTempThumbnail = new (ELeave) CFbsBitmap;
+                    User::LeaveIfError(iTempThumbnail->Create(TSize(), KGlxThumbnailDisplayMode));
+                    iThumbnailId = itemId;
+
+                    // Set bitmap handle in attribute spec
+                    if (attrSpecs)
+                        {
+                        TMPXAttribute thHandleAttrSpec(KGlxMediaIdThumbnail, KGlxAttribSpecThumbnailBitmapHandle);
+                        attrSpecs->SetTObjectValueL<TInt>(thHandleAttrSpec, iTempThumbnail->Handle());
+                        }
+                    // Cancel Clean-up is needed here;
+                    // This is Going to Highly Used Call
+                    // Can Think about an Ulternative.
+                    HandleGarbageCollectionL(EFalse);
+                    }
+
+                GLX_DEBUG3("MGallery - CGlxCacheManager::MaintainCacheL() requesting attribute for list %x and item %d", list, itemId.Value());
+
+                // Use list's isolated collection
+                MMPXCollection& collection = list->Collection();
+
+    			// Issue the request
+    			collection.MediaL(*path, iRequestedAttrs.Array(), attrSpecs);
+#endif
+    			CleanupStack::PopAndDestroy(path);
+    			
+    			iRequestOwner = list;
+    			}		
+    			
+    		CleanupStack::PopAndDestroy(attrSpecs);	
+    		}
+    		
+        if ( !iRequestOwner )
+            {
+            if ( iTempError )
+                {
+                // Reawaken in a while to check again
+                StartTempErrorTimer();
+                }
+            }
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// BroadcastAttributesAvailableL
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::BroadcastAttributesAvailableL(const TGlxIdSpaceId& aIdSpaceId, 
+                    const TGlxMediaId& aMediaId, 
+                    const RArray<TMPXAttribute>& aAttributes, 
+                    const CGlxMedia* aMedia)
+   {
+   TRACER("CGlxCacheManager::BroadcastAttributesAvailableL");
+   
+    TInt count = iObserverList.Count();
+    TInt i;
+    for ( i = 0; i < count; i++ )
+        {
+        iObserverList[i]->HandleAttributesAvailableL(aIdSpaceId, aMediaId, aAttributes, aMedia);
+        }
+   }
+
+/**
+ * Cleanup the media of the given media id: broadcast this to all observers
+ * @param aMediaId The media id of the item
+ */ 
+void CGlxCacheManager::CleanupMedia(const TGlxMediaId& aMediaId)
+	{
+	TRACER("CGlxCacheManager::CleanupMedia");
+    TInt count = iObserverList.Count();
+    GLX_DEBUG2("CGlxCacheManager::CleanupMedia -  aMediaId = %d", aMediaId.Value());
+    TInt i;
+    for ( i = 0; i < count; i++ )
+        {
+        iObserverList[i]->CleanupMedia(aMediaId);
+        }
+   }
+
+// -----------------------------------------------------------------------------
+// Handles modification of item in a cache
+// -----------------------------------------------------------------------------
+void CGlxCacheManager::HandleItemModified(const TGlxIdSpaceId& aIdSpaceId, const TGlxMediaId& aMediaId, const RArray<TMPXAttribute>& aAttributes)
+	{
+	TRACER("CGlxCacheManager::HandleItemModified");
+	
+	// Look for the correct subcache
+	TInt index = iCaches.FindInOrder(aIdSpaceId, (&CacheOrderByKey));
+	if (index != KErrNotFound)
+		{
+		iCaches[index]->HandleItemModified(aMediaId, aAttributes);
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CacheOrderById
+// -----------------------------------------------------------------------------
+//
+TInt CGlxCacheManager::CacheOrderById(const CGlxCache& aItem1, const CGlxCache& aItem2) 
+	{
+	TRACER("CGlxCacheManager::CacheOrderById");
+	
+	// Cannot do aItem1.IdSpaceId() - aItem2.IdSpaceId(), since IdSpaceId().Value() returns an unsigned value
+	TGlxIdSpaceId id1 = aItem1.IdSpaceId();
+	TGlxIdSpaceId id2 = aItem2.IdSpaceId();
+	if (id1 < id2) 
+		{
+		return -1;
+		}
+		
+	if (id1 > id2) 
+		{
+		return 1;
+		}
+
+	return 0;
+	}
+
+// -----------------------------------------------------------------------------
+// CacheOrderByKey
+// -----------------------------------------------------------------------------
+//
+TInt CGlxCacheManager::CacheOrderByKey(const TGlxIdSpaceId* aIdSpaceId, const CGlxCache& aItem2) 
+	{
+	TRACER("CGlxCacheManager::CacheOrderByKey");
+	
+	TGlxIdSpaceId id2 = aItem2.IdSpaceId();
+	if (*aIdSpaceId < id2) 
+		{
+		return -1;
+		}
+		
+	if (*aIdSpaceId > id2) 
+		{
+		return 1;
+		}
+
+	return 0;
+	}
+
+// -----------------------------------------------------------------------------
+// TempThumbnail
+// -----------------------------------------------------------------------------
+//
+CFbsBitmap* CGlxCacheManager::TempThumbnail()
+    {
+    TRACER("CGlxCacheManager::TempThumbnail");
+    
+    return iTempThumbnail;
+    }
+    
+// -----------------------------------------------------------------------------
+// TempThumbnailId
+// -----------------------------------------------------------------------------
+//
+TGlxMediaId CGlxCacheManager::TempThumbnailId()
+    {
+    TRACER("CGlxCacheManager::TempThumbnailId");
+    
+    return iThumbnailId;
+    }
+
+// -----------------------------------------------------------------------------
+// SetTempThumbnail
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::SetTempThumbnailToNull()
+    {
+    TRACER("CGlxCacheManager::SetTempThumbnailToNull");
+    
+    iTempThumbnail = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// ErrorsOnRequestedItemsL
+// -----------------------------------------------------------------------------
+//
+TBool CGlxCacheManager::ErrorsOnRequestedItemsL()
+    {
+    TRACER("CGlxCacheManager::ErrorsOnRequestedItemsL");
+    
+    TBool errorFound = EFalse;
+    
+    TInt itemCount = iRequestedItemIds.Count();
+    TInt attrCount = iRequestedAttrs.Count();
+    
+    for ( TInt itemIndex = 0; itemIndex < itemCount && !errorFound; itemIndex++ )
+        {
+        CGlxMedia* media = Media(iRequestedItemsIdSpace, iRequestedItemIds[itemIndex]);
+        
+        if ( media )
+            {
+            for ( TInt attrIndex = 0; attrIndex < attrCount && !errorFound; attrIndex++ )
+                {
+                errorFound = (KErrNone != GlxErrorManager::HasAttributeErrorL(media, iRequestedAttrs[attrIndex]));
+                }
+            }
+        }
+    
+    return errorFound;
+    }
+    
+// -----------------------------------------------------------------------------
+// Caches
+// -----------------------------------------------------------------------------
+//
+const RPointerArray<CGlxCache>& CGlxCacheManager::Caches()
+    {
+    TRACER("CGlxCacheManager::Caches");
+    
+    return iCaches;
+    }
+
+// -----------------------------------------------------------------------------
+// SetTemporaryErrorFlag
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::SetTemporaryErrorFlag()
+    {
+    TRACER("CGlxCacheManager::SetTemporaryErrorFlag");
+    
+    iTempError = ETrue;
+    }
+    
+// -----------------------------------------------------------------------------
+// StartTempErrorTimer
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::StartTempErrorTimer()
+    {
+    TRACER("CGlxCacheManager::StartTempErrorTimer");
+    
+    iTempErrorTimer->Cancel();
+	iTempErrorTimer->Start(
+		TTimeIntervalMicroSeconds32(KGlxTemporaryErrorRecheckPeriodInSeconds * 1000000),
+		TTimeIntervalMicroSeconds32(KGlxTemporaryErrorRecheckPeriodInSeconds * 1000000),
+		TCallBack(&CGlxCacheManager::TempErrorTimerCallbackL,(TAny *)this));
+	}
+
+// -----------------------------------------------------------------------------
+// TempErrorTimerCallbackL
+// -----------------------------------------------------------------------------
+//
+TInt CGlxCacheManager::TempErrorTimerCallbackL(TAny* aPtr)
+    {
+    TRACER("CGlxCacheManager::TempErrorTimerCallback");
+    
+	CGlxCacheManager* self = (CGlxCacheManager*) aPtr;
+	
+	if ( self )
+	    {
+    	self->TempErrorTimerCompleteL();
+    	}
+
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// TempErrorTimerComplete
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::TempErrorTimerCompleteL()
+    {
+    TRACER("CGlxCacheManager::TempErrorTimerComplete");
+    
+    iTempErrorTimer->Cancel();
+    TRAPD(err, MaintainCacheL());
+    
+    // If MaintainCacheL leaves, force gabage collection to start and restart timer
+    if ( KErrNone != err )
+        {
+        if ( KErrNoMemory == err )
+            {
+            //iGarbageCollector->Cleanup();
+            HandleGarbageCollectionL(ETrue);
+            }
+            
+        if ( !iRequestOwner )
+            {
+            StartTempErrorTimer();
+            }
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// Create a path with the request items
+// -----------------------------------------------------------------------------
+//
+inline CMPXCollectionPath* CGlxCacheManager::RequestAsPathLC(const CGlxMediaList& aList)
+    {
+    TRACER("CGlxCacheManager::RequestAsPathLC");
+    
+    CMPXCollectionPath* path = aList.PathLC( NGlxListDefs::EPathParent );
+
+    RArray<TMPXItemId> mpxIds;
+    CleanupClosePushL( mpxIds );
+
+    TInt itemIdsCount = iRequestedItemIds.Count();
+
+    // Reserve space for all items
+    mpxIds.ReserveL( itemIdsCount );
+
+    for (TInt i = 0; i < itemIdsCount; ++i)
+        {
+        mpxIds.AppendL( iRequestedItemIds[ i ].Value() );
+        }
+
+    path->AppendL( mpxIds.Array() );
+    path->SelectAllL();
+
+    CleanupStack::PopAndDestroy( &mpxIds );
+
+    return path;
+    }
+
+// -----------------------------------------------------------------------------
+// HandleListDeleted
+// -----------------------------------------------------------------------------
+void CGlxCacheManager::HandleListDeleted(CGlxMediaList* aList)
+    {
+    TRACER("CGlxCacheManager::HandleListDeleted");
+    
+    if (iRequestOwner == aList)
+        {
+        iRequestOwner = NULL;
+
+        TRAP_IGNORE( MaintainCacheL() );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Inform cache manager to reserve users for an item, for a particular cache
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::ReserveUsersL(const TGlxIdSpaceId& aIdSpaceId, TInt aCount)
+    {
+    TRACER("CGlxCacheManager::ReserveUsersL");
+    
+    // Look for existing cache
+    TInt index = iCaches.FindInOrder( aIdSpaceId, ( &CacheOrderByKey ) );
+    if (index != KErrNotFound)
+        {
+        iCaches[index]->ReserveUsersL( aCount );
+        }
+    }
+//OOM 
+// -----------------------------------------------------------------------------
+// Start cache cleanup on Low memory event from OOM
+// -----------------------------------------------------------------------------
+//   
+void CGlxCacheManager::ReleaseRAML(TBool aFlushOnRequest)
+{
+    TRACER("CGlxCacheManager::ReleaseRAM");
+    if(aFlushOnRequest)
+        {
+        HandleGarbageCollectionL(aFlushOnRequest);        
+        }
+	else
+	{
+		iGarbageCollector->CleanupL(); 	 				
+	} 	
+}
+// -----------------------------------------------------------------------------
+// Force a cleanup on particular media id : remove all attributes
+// -----------------------------------------------------------------------------
+// 
+void CGlxCacheManager::ForceCleanupMedia(TGlxIdSpaceId aSpaceId, 
+                                          TGlxMediaId aMediaId)
+    {
+    TRACER("CGlxCacheManager::ForceCleanupMedia");  
+    TInt spaceIdIndex = iCaches.FindInOrder( aSpaceId, &CacheOrderByKey );
+    if ( KErrNotFound != spaceIdIndex )
+        {
+        if ( iCaches[spaceIdIndex]->Media( aMediaId ) )
+            {            
+            TInt mediaIdIndex = iCaches[spaceIdIndex]->FindMediaIndexInCache(aMediaId);
+            if ( KErrNotFound != mediaIdIndex )
+            	{
+            	iCaches[spaceIdIndex]->Delete(mediaIdIndex);
+            	}
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Stop cache cleanup on good memory event from OOM
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::StopRAMReleaseL()
+{
+    TRACER("CGlxCacheManager::StopRAMRelease");
+    iGarbageCollector->CancelCleanup(); 		
+
+}
+//OOM
+
+#ifdef USE_S60_TNM
+// -----------------------------------------------------------------------------
+// CGlxCacheManager::FindLoadingById()
+// -----------------------------------------------------------------------------
+//
+TInt CGlxCacheManager::FindLoadingById(TThumbnailRequestId aId, TBool aRemove)
+    {
+    TRACER("CGlxCacheManager::FindLoadingById");
+    TInt index = KErrNotFound;
+    for(TInt i = 0; i < iThumbnailRequestIds.Count(); ++i)
+        {
+        if(iThumbnailRequestIds[i].iId == aId)
+            {
+            index = i;
+            if(aRemove)
+                {
+                iThumbnailRequestIds.Remove(i);
+                }
+            break;
+            }
+        }
+    return index;
+    }
+
+// -----------------------------------------------------------------------------
+// CGlxCacheManager::ThumbnailPreviewReady()
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::ThumbnailPreviewReady(MThumbnailData& aThumbnail,
+        TThumbnailRequestId aId)
+    {
+    TRACER("CGlxCacheManager::ThumbnailPreviewReady");
+    TInt error = KErrNotSupported;
+    if (aThumbnail.Bitmap() != NULL)
+         {
+		 GLX_DEBUG1("CGlxCacheManager::ThumbnailPreviewReady preview aval");
+         error = KErrNone;
+         }
+    ThumbnailReadyL(error, aThumbnail, aId, EFalse);
+    }
+
+// -----------------------------------------------------------------------------
+// CGlxCacheManager::ThumbnailReady()
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::ThumbnailReady(TInt aError,
+        MThumbnailData& aThumbnail, TThumbnailRequestId aId)
+    {
+    TRACER("CGlxCacheManager::ThumbnailReady");
+    GLX_DEBUG2("CGlxCacheManager::ThumbnailReady aError=%d", aError);
+    ThumbnailReadyL(aError, aThumbnail, aId, ETrue);
+    }
+
+// -----------------------------------------------------------------------------
+// CGlxCacheManager::ThumbnailReadyL()
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::ThumbnailReadyL(TInt aError, MThumbnailData& aThumbnail, 
+                                       TThumbnailRequestId aId, TBool aQuality)
+    {
+    TRACER("CGlxCacheManager::ThumbnailReadyL");
+    GLX_DEBUG3("CGlxCacheManager::ThumbnailReadyL aError=%d, aQuality=%d",
+                                aError, aQuality);
+
+#ifdef _DEBUG
+    iStopTime.HomeTime(); // Get home time
+    GLX_DEBUG2("=>CGlxCacheManager::ThumbnailReadyL - TN Fetch took <%d> us", 
+                    (TInt)iStopTime.MicroSecondsFrom(iStartTime).Int64());
+#endif
+    
+	TInt reqIndex = FindLoadingById(aId, EFalse);
+		
+    if (reqIndex == KErrNotFound)
+        {
+		return;
+        }
+
+    delete iMPXMedia;
+    iMPXMedia = NULL;
+        
+    iMPXMedia = CMPXMedia::NewL();
+    if (aError == KErrNone)
+        {
+        delete iTempThumbnail;
+        iTempThumbnail = NULL;
+        iTempThumbnail = aThumbnail.DetachBitmap();
+
+        CGlxThumbnailAttribute* tnAttribute = new (ELeave) CGlxThumbnailAttribute;
+        CleanupStack::PushL(tnAttribute);
+        tnAttribute->iDimensions = iThumbnailRequestIds[reqIndex].iSize;
+	    tnAttribute->iThumbnailQuality = aQuality;
+                
+        iMPXMedia->SetTObjectValueL<TMPXItemId>(KMPXMediaGeneralId, 
+						iThumbnailRequestIds[reqIndex].iThumbnailId.Value());
+        TUint attributeId = GlxFullThumbnailAttributeId(aQuality, 
+								iThumbnailRequestIds[reqIndex].iSize.iWidth, 
+								iThumbnailRequestIds[reqIndex].iSize.iHeight);
+        iMPXMedia->SetNoNewLCObjectL(
+               TMPXAttribute(KGlxMediaIdThumbnail, attributeId), tnAttribute);
+        CleanupStack::PopAndDestroy(tnAttribute);
+
+        HandleCollectionMediaL(iThumbnailRequestIds[reqIndex].iSpaceId,
+                                                    *iMPXMedia, aError);
+        }
+    else
+        {
+        HandleCollectionMediaL(iThumbnailRequestIds[reqIndex].iSpaceId, 
+													*iMPXMedia, aError);
+        }
+    
+    if (aQuality)
+        {
+        FindLoadingById(aId, ETrue);
+        }   
+    }
+#endif
+
+// -----------------------------------------------------------------------------
+// GetMimeTypeL()
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::GetMimeTypeL(TFileName& aFileName, TDataType& aMimeType)
+    {
+    TRACER("CGlxCacheManager::GetMimeTypeL");
+    RApaLsSession session;
+    User::LeaveIfError( session.Connect() );
+    CleanupClosePushL( session );
+
+    TUid uid;
+    User::LeaveIfError( session.AppForDocument( aFileName, uid, aMimeType ) );
+    CleanupStack::PopAndDestroy(&session);
+    }
+
+// -----------------------------------------------------------------------------
+// ImageSizeReady()
+// -----------------------------------------------------------------------------
+//
+void CGlxCacheManager::ImageSizeReady(TInt aError, const TSize aSz)
+    {
+    TRACER("CGlxCacheManager::ImageSizeReady");
+    GLX_DEBUG2("CGlxCacheManager::ImageSizeReady aError=%d", aError);
+    iImgSz = TSize();
+    if(iSchedulerWait)
+        {
+        iSchedulerWait->AsyncStop();    
+        }    
+
+    iImgSz = aSz;
+    GLX_DEBUG3("CGlxCacheManager::ImageSizeReady() iImgSz w(%d) h(%d)", 
+            iImgSz.iWidth, iImgSz.iHeight);    
+    }
+
+//End of file