mtpfws/mtpfw/src/cmtpdataprovidercontroller.cpp
changeset 0 d0791faffa3f
child 1 f8e15b44d440
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpfws/mtpfw/src/cmtpdataprovidercontroller.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,1150 @@
+// Copyright (c) 2006-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:
+//
+
+#include <barsc.h> 
+#include <barsread.h> 
+#include <e32property.h>
+#include <mtp/cmtpdataproviderplugin.h>
+#include <mtp/mtpprotocolconstants.h>
+#include <mtp/rmtpclient.h>
+
+#include "cmtpdataprovider.h"
+#include "cmtpdataproviderconfig.h"
+#include "cmtpdataprovidercontroller.h"
+#include "cmtpobjectmgr.h"
+#include "mtpframeworkconst.h"
+#include "cmtpframeworkconfig.h"
+#include "cmtpstoragemgr.h"
+
+
+// Class constants.
+_LIT(KMTPDpResourceDirectory, "z:\\resource\\mtp\\");
+_LIT(KMTPDpDummyResourcefile, "z:\\resource\\mtp\\dummydp.rsc");
+
+// Class constants.
+__FLOG_STMT(_LIT8(KComponent,"DataProviderController");)
+
+static const TUint KOpaqueDataLength(64);
+
+/**
+CMTPDataProviderController panics
+*/
+_LIT(KMTPPanicCategory, "CMTPDataProviderController");
+enum TMTPPanicReasons
+    {
+    EMTPPanicStorageEnumeration = 0,
+    EMTPPanicFrameworkEnumeration = 1,
+    EMTPPanicDataProviderStorageEnumeration = 2,
+    EMTPPanicDataProviderEnumeration = 3
+    };
+    
+LOCAL_C void Panic(TInt aReason)
+    {
+    User::Panic(KMTPPanicCategory, aReason);
+    }
+
+/**
+CMTPDataProviderController factory method. 
+@return A pointer to a new CMTPDataProviderController instance. Ownership IS 
+transfered.
+@leave One of the system wide error codes if a processing failure occurs.
+*/
+CMTPDataProviderController* CMTPDataProviderController::NewL()
+    {
+    CMTPDataProviderController* self = new (ELeave) CMTPDataProviderController();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+/**
+Destructor.
+*/
+CMTPDataProviderController::~CMTPDataProviderController()
+    {
+    __FLOG(_L8("~CMTPDataProviderController - Entry"));
+    Cancel();
+    UnloadDataProviders();
+    iDataProviderIds.Close();
+    iEnumeratingDps.Close();
+    iEnumeratingStorages.Close();
+    iSingletons.Close();
+    CloseRegistrySessionAndEntryL();
+    delete iOpenSessionWaiter;
+    __FLOG(_L8("~CMTPDataProviderController - Exit"));
+    __FLOG_CLOSE;
+    }
+    
+/**
+Loads the set of available data providers and initiates the data provider
+enumeration sequence.
+@leave One of the system wide error codes, if a processing failure occurs.
+*/
+EXPORT_C void CMTPDataProviderController::LoadDataProvidersL()
+    {
+    __FLOG(_L8("LoadDataProvidersL - Entry"));
+    // Retrieve the ECOM data provider implementations list
+    RImplInfoPtrArray   implementations;
+    TCleanupItem        cleanup(ImplementationsCleanup, reinterpret_cast<TAny*>(&implementations));
+    CleanupStack::PushL(cleanup);
+    REComSession::ListImplementationsL(KMTPDataProviderPluginInterfaceUid, implementations);
+    implementations.Sort(TLinearOrder<CImplementationInformation>(ImplementationsLinearOrderUid));
+    
+    // Retrieve the data provider registration resource file list.
+    CDir* registrations;
+    User::LeaveIfError(iSingletons.Fs().GetDir(KMTPDpResourceDirectory, KEntryAttNormal, ESortByName, registrations));
+    CleanupStack::PushL(registrations);
+
+    // Load the registered data providers. 
+    const TUint KCount(registrations->Count());
+    TInt index = 0; 
+    for (TInt i = 0; i < KCount; ++i)
+        {
+        TUint uid = 0;
+        if(Uid((*registrations)[i].iName, uid) != KErrNone)
+        	{
+        	__FLOG_1(_L8("LoadDataProvidersL - Fail to get UID = %s"),&((*registrations)[i].iName) );
+        	continue;
+        	}
+        index = implementations.FindInOrder(TUid::Uid(uid), ImplementationsLinearOrderUid);
+        if (KErrNotFound == index)
+        	{
+        	continue;
+        	}
+		if( uid != KMTPImplementationUidDeviceDp && uid != KMTPImplementationUidProxyDp && uid != KMTPImplementationUidFileDp )
+			{
+	        //get the dpid for the uid from dpidstore table
+	        TBool tFlag;
+		    iNextDpId = iSingletons.ObjectMgr().DPIDL(uid, tFlag);
+		    if(tFlag == EFalse)
+		    	{
+		    	iSingletons.ObjectMgr().InsertDPIDObjectL(iNextDpId,uid);
+		    	}	       	
+			}
+		else
+			{
+			switch (uid)
+				{
+				case KMTPImplementationUidDeviceDp : 
+					iNextDpId = KMTPDeviceDPID;
+					break;
+
+				case KMTPImplementationUidFileDp   : 
+					iNextDpId = KMTPFileDPID;
+					break;
+
+				case KMTPImplementationUidProxyDp  : 
+					iNextDpId = KMTPProxyDPID;
+					break;				
+				}
+			}
+		LoadROMDataProvidersL((*registrations)[i].iName, implementations);
+		delete implementations[index];
+		implementations.Remove(index);
+        }
+
+    //Load installed DPs on non-ROM drives.
+    for (index = 0; index < implementations.Count(); ++index)
+        {
+        TRAPD(err, LoadInstalledDataProvidersL(implementations[index]));
+        if (KErrNone != err)
+            {
+            __FLOG_VA((_L8("Load installed data provider[0x%x] failed."),implementations[index]->ImplementationUid().iUid));
+            }
+        }
+
+    CleanupStack::PopAndDestroy(registrations);
+    CleanupStack::PopAndDestroy(&implementations);    
+
+    // Verify that the framework data providers are loaded.
+    User::LeaveIfError(DpId(KMTPImplementationUidDeviceDp));
+    User::LeaveIfError(DpId(KMTPImplementationUidProxyDp));
+    User::LeaveIfError(DpId(KMTPImplementationUidFileDp));
+
+	// Sort the data provider set on enumeration phase order.
+	iDataProviders.Sort(TLinearOrder<CMTPDataProvider>(CMTPDataProvider::LinearOrderEnumerationPhase));
+	// Add the DP IDs into DP ID array, except for device DP, File DP and proxy DP
+	for (TUint index=0; index < iDataProviders.Count(); index++)
+	  {
+	  if ((iDataProviders[index]->DataProviderId() != iDpIdDeviceDp)
+	  	  && (iDataProviders[index]->DataProviderId() != iDpIdFileDp)
+	  	  && (iDataProviders[index]->DataProviderId() != iDpIdProxyDp))
+	    {
+	    iDataProviderIds.Append(iDataProviders[index]->DataProviderId());
+	    }
+	  }
+	
+    // Ensure that the data provider set is ordered on DataProvider Id.
+    iDataProviders.Sort(TLinearOrder<CMTPDataProvider>(CMTPDataProvider::LinearOrderDPId));
+    
+    // Start enumerating.
+    iEnumeratingStorages.AppendL(KMTPStorageAll);
+    iEnumerationState = EEnumerationStarting;
+    Schedule();
+    __FLOG(_L8("LoadDataProvidersL - Exit"));
+    }
+    
+/**
+Unloads all active data providers.
+@leave One of the system wide error codes, if a processing failure occurs.
+*/
+EXPORT_C void CMTPDataProviderController::UnloadDataProviders()
+    {
+    __FLOG(_L8("UnloadDataProviders - Entry"));
+    TRAP_IGNORE(iSingletons.ObjectMgr().ObjectStore().CleanL());
+    iDataProviders.ResetAndDestroy();
+    iDataProviderIds.Reset();
+    __FLOG(_L8("UnloadDataProviders - Exit"));
+    }
+    
+/**
+Issues the specified notification to all loaded data providers.
+@param aNotification The notification type identifier.
+@param aParams The notification type specific parameter block
+@leave One of the system wide error code if a processing failure occurs
+in the data provider.
+*/
+EXPORT_C void CMTPDataProviderController::NotifyDataProvidersL(TMTPNotification aNotification, const TAny* aParams)
+    {
+    NotifyDataProvidersL(KMTPDataProviderAll, aNotification, aParams);
+    }
+
+EXPORT_C void CMTPDataProviderController::NotifyDataProvidersL(TUint aDPId, TMTPNotification aNotification, const TAny* aParams)
+    {
+    __FLOG(_L8("NotifyDataProvidersL - Entry"));
+    // Schedule any long running operations.
+    switch (aNotification)
+        {
+    case EMTPStorageAdded:
+        {
+        // Queue a storage enumeration operation.
+        __ASSERT_DEBUG(aParams, User::Invariant());
+        const TMTPNotificationParamsStorageChange* params(static_cast<const TMTPNotificationParamsStorageChange*>(aParams));
+        iEnumeratingStorages.AppendL(params->iStorageId);
+        
+        // Only schedule the operation start if there is not one currently underway.
+        if (iEnumerationState == EEnumerated)
+            {
+            iNextDpId           = iDpIdDeviceDp;
+            iEnumerationState   = EEnumeratingFrameworkObjects;
+            Schedule();
+            }
+        }
+        break;
+	case EMTPStorageRemoved:
+		{
+		// Dequeue an unhandled storage enumeration operations if existed.
+        // If not existed, just ignore the remove event, since the logical storageId already removed from StorageMgr
+        // by the caller, i.e. CMTPStorageWatcher. 
+        __ASSERT_DEBUG(aParams, User::Invariant());
+        const TMTPNotificationParamsStorageChange* params(static_cast<const TMTPNotificationParamsStorageChange*>(aParams));
+        //Start checking from the second event, since iEnumeratingStorages[0] is the event being handled by DPs.
+        TUint32 storageId = params->iStorageId;
+        for(TInt i=1; i<iEnumeratingStorages.Count(); i++)
+            {
+            if(storageId==iEnumeratingStorages[i])
+                {
+                iEnumeratingStorages.Remove(i);
+                __FLOG_VA((_L8("Unhandle memory card add event removed, storageId: %d"), storageId));
+                }
+            }
+        }
+        break;
+    case EMTPObjectAdded:
+        break;
+    default:
+        break;        
+        }
+        
+    // Issue the notification.    
+    const TUint KLoadedDps(iDataProviders.Count());
+    if(aDPId == KMTPDataProviderAll)
+        {
+        for (TUint i(0); i < KLoadedDps; ++i)
+            {
+            CMTPDataProvider *dp = iDataProviders[i];
+            if ((dp->DataProviderId() != iDpIdDeviceDp) &&
+                (dp->DataProviderId() != iDpIdProxyDp))
+                {
+                dp->Plugin().ProcessNotificationL(aNotification, aParams);
+                }
+            }
+        }
+    else
+        {
+        for (TUint i(0); i < KLoadedDps; ++i)
+            {
+            CMTPDataProvider *dp = iDataProviders[i];
+            if ( dp->DataProviderId() == aDPId )
+                {
+                dp->Plugin().ProcessNotificationL(aNotification, aParams);
+                break;
+                }
+            }
+        }    
+    __FLOG(_L8("NotifyDataProvidersL - Exit"));
+    }
+
+/**
+Provides the number of active data providers.
+@return the number of active data providers.
+*/
+EXPORT_C TUint CMTPDataProviderController::Count()
+    {
+    return iDataProviders.Count();
+    }
+
+/**
+Provides a reference to the data provider with the specified identifier.
+@param aId The data provider identifier.
+@return The data provider reference.
+*/
+EXPORT_C CMTPDataProvider& CMTPDataProviderController::DataProviderL(TUint aId)
+    {
+    return DataProviderByIndexL(iDataProviders.FindInOrder(aId, CMTPDataProvider::LinearOrderDPId));
+    }  
+
+/**
+Provides a reference to the data provider with the specified index.
+@param aIndex The data provider index.
+@return The data provider reference.
+*/
+EXPORT_C CMTPDataProvider& CMTPDataProviderController::DataProviderByIndexL(TUint aIndex)
+    {
+    __ASSERT_DEBUG((aIndex < iDataProviders.Count()), User::Invariant());
+    return *(iDataProviders[aIndex]);
+    }  
+
+/**
+ * Determine whether a data provider with the specified data provider id has been loaded
+ * @param aId the id of the data provider to be checked
+ * @return true if the data provider has been loaded, otherwise false
+ */
+EXPORT_C TBool CMTPDataProviderController::IsDataProviderLoaded(TUint aId) const
+	{
+	TInt index = iDataProviders.FindInOrder(aId, CMTPDataProvider::LinearOrderDPId);
+	if (index >= 0 && index < iDataProviders.Count())
+		{
+		return ETrue;
+		}
+	else
+		{
+		return EFalse;
+		}
+	}
+
+/**
+Provides the identifier of the device data provider.
+@return TInt The device data provider identifier.
+*/
+EXPORT_C TInt CMTPDataProviderController::DeviceDpId()
+    {
+    return iDpIdDeviceDp;
+    }
+    
+/**
+Provides the identifier of the data provider with the specified implementation 
+UID.
+@param aUid The implementation UID.
+@return TInt The proxy data provider identifier.
+*/  
+EXPORT_C TInt CMTPDataProviderController::DpId(TUint aUid)
+    {
+    return iDataProviders.FindInOrder(TUid::Uid(aUid), CMTPDataProvider::LinearOrderUid);
+    }
+
+/**
+Provides the identifier of the proxy data provider.
+@return TInt The proxy data provider identifier.
+*/  
+EXPORT_C TInt CMTPDataProviderController::ProxyDpId()
+    {
+    return iDpIdProxyDp;
+    }
+
+EXPORT_C TInt CMTPDataProviderController::FileDpId()
+    {
+    return iDpIdFileDp;
+    }
+
+/**
+Wait for the enumeration complete.
+*/ 
+EXPORT_C void CMTPDataProviderController::WaitForEnumerationComplete()
+{
+	if(EnumerateState() != CMTPDataProviderController::EEnumerated)
+		{
+		iOpenSessionWaiter->Start();
+		}
+}
+TBool CMTPDataProviderController::FreeEnumerationWaiter()
+	{
+	if(iOpenSessionWaiter->IsStarted())
+		{
+		iOpenSessionWaiter->AsyncStop();
+		return ETrue;
+		}
+	return EFalse;
+	}
+/**
+Data provider enumeration state change notification callback.
+@param aDp The notifying data provider.
+*/    
+void CMTPDataProviderController::EnumerationStateChangedL(const CMTPDataProvider& aDp)
+    {
+    __FLOG(_L8("EnumerationStateChangedL - Entry"));
+    switch (iEnumerationState)
+        {        
+    case EEnumeratingFrameworkStorages:
+    	switch (aDp.ImplementationUid().iUid)
+            {
+        case KMTPImplementationUidDeviceDp:
+            iNextDpId = iDpIdProxyDp;
+            break;
+
+            
+        case KMTPImplementationUidProxyDp:
+            iNextDpId = iDpIdFileDp;
+            break;
+            
+        case KMTPImplementationUidFileDp:
+            iEnumerationState   = EEnumeratingDataProviderStorages;
+            iDpIdArrayIndex     = 0;
+            break;
+            }
+        Schedule();
+        break;    
+        
+    case EEnumeratingDataProviderStorages:
+        // Data provider storage enumerations execute sequentially.
+        if (++iDpIdArrayIndex >= iDataProviderIds.Count())
+            {
+            iNextDpId           = iDpIdDeviceDp;
+            iEnumerationState   = EEnumeratingFrameworkObjects;
+            }
+        Schedule();
+        break;
+          
+    case EEnumeratingFrameworkObjects:
+        switch (aDp.ImplementationUid().iUid)
+            {
+        case KMTPImplementationUidDeviceDp:
+            iSingletons.ObjectMgr().RemoveNonPersistentObjectsL(aDp.DataProviderId());
+            iNextDpId = iDpIdProxyDp;
+            Schedule();
+            break;
+            
+        case KMTPImplementationUidProxyDp:
+            //iNextDpId = iDpIdFileDp;
+            if ( iDataProviderIds.Count()>0 )
+                {
+                iEnumerationState   = EEnumeratingDataProviderObjects;
+                iEnumerationPhase   = DataProviderL(iDataProviderIds[0]).DataProviderConfig().UintValue(MMTPDataProviderConfig::EEnumerationPhase);
+                iDpIdArrayIndex     = 0;                
+                }
+            else
+                {
+                iNextDpId = iDpIdFileDp;
+                }
+            Schedule();
+            break;
+            
+        case KMTPImplementationUidFileDp:
+            iSingletons.ObjectMgr().RemoveNonPersistentObjectsL(aDp.DataProviderId());
+            // No other data providers
+            iNextDpId = 0;
+            iEnumeratingStorages.Remove(0);
+            if (iEnumeratingStorages.Count() == 0)
+                {
+                // No queued enumerations.
+                iSingletons.ObjectMgr().ObjectStore().CleanDBSnapshotL();
+                iEnumerationState   = EEnumerated;
+                Cancel();
+                if(iOpenSessionWaiter->IsStarted())
+                    {
+                    iOpenSessionWaiter->AsyncStop();
+                    }
+                }
+            else
+                {
+                // Queued enumerations.
+                iNextDpId           = iDpIdDeviceDp;
+                Schedule();
+                }
+            }
+        break;
+        
+    case EEnumeratingDataProviderObjects:
+        // Enumerate non-framework data providers concurrently.
+        iEnumeratingDps.Remove(iEnumeratingDps.FindInOrderL(aDp.DataProviderId()));
+        // Remove any non-persistent objects that are still marked.
+        iSingletons.ObjectMgr().RemoveNonPersistentObjectsL(aDp.DataProviderId());
+
+        if ((iEnumeratingDps.Count() == 0) && iDpIdArrayIndex >= iDataProviderIds.Count())
+            {
+            // Enumeration complete.
+            iNextDpId = 0;
+            iNextDpId           = iDpIdFileDp;
+            iEnumerationState   = EEnumeratingFrameworkObjects;
+            }
+        else
+            {
+            if ((iEnumeratingDps.Count() == 0) && (iEnumerationPhase != DataProviderL(iDataProviderIds[iDpIdArrayIndex]).DataProviderConfig().UintValue(MMTPDataProviderConfig::EEnumerationPhase)))
+                {
+                // Enter next enumeration phase
+                iEnumerationPhase = DataProviderL(iDataProviderIds[iDpIdArrayIndex]).DataProviderConfig().UintValue(MMTPDataProviderConfig::EEnumerationPhase);
+                }
+            }
+        Schedule();        
+        break;
+        
+    case EUnenumerated:
+    case EEnumerationStarting:
+    case EEnumerated:
+    default:
+        __DEBUG_ONLY(User::Invariant());
+        break;
+        }
+    __FLOG(_L8("EnumerationStateChangedL - Exit"));
+    }
+
+void CMTPDataProviderController::DoCancel()
+    {
+    __FLOG(_L8("DoCancel - Entry"));
+    __FLOG(_L8("DoCancel - Exit"));
+    }
+    
+void CMTPDataProviderController::RunL()
+    {
+    __FLOG(_L8("RunL - Entry"));
+    __FLOG_VA((_L8("iEnumerationState: 0x%x iNextDpId: %d"), iEnumerationState, iNextDpId));
+    switch (iEnumerationState)
+        {
+    case EEnumerationStarting:
+        iEnumerationState   = EEnumeratingFrameworkStorages;
+        iNextDpId           = iDpIdDeviceDp;
+        // Fall through to issue the StartStorageEnumerationL signal.
+        
+    case EEnumeratingFrameworkStorages:
+        // Enumerate storages sequentially.
+    	DataProviderL(iNextDpId).EnumerateStoragesL();
+        break;
+        
+    case EEnumeratingDataProviderStorages:
+        // Enumerate storages sequentially.
+            
+        // In case there was no DPs other than devdp and proxydp.
+        if (iDpIdArrayIndex < iDataProviderIds.Count())
+            {
+            DataProviderL(iDataProviderIds[iDpIdArrayIndex]).EnumerateStoragesL();
+            }
+        else
+            {
+            iNextDpId           = iDpIdDeviceDp;
+            iEnumerationState   = EEnumeratingFrameworkObjects;
+	
+            
+        
+            Schedule();
+            }
+        break;
+        
+    case EEnumeratingFrameworkObjects:
+        {
+        TUint32 storageId = iEnumeratingStorages[0];
+        if( ( KMTPStorageAll != storageId ) && (!iSingletons.StorageMgr().ValidStorageId(storageId)))
+            {
+            iNextDpId = 0;
+            //Specified storage not existed, not necessary to start enumeration on this stroage.
+            //Do this check will save enumeration time, i.e. avoid unnecessary enumeration, since memory card removed before enumeration starts.
+            iEnumeratingStorages.Remove(0);
+            if (iEnumeratingStorages.Count() == 0)
+                {
+                iEnumerationState = EEnumerated;
+                }
+            else
+                {
+                //deal next storage
+                iNextDpId = iDpIdDeviceDp;
+                Schedule();
+                }
+            }
+        else
+        	{
+            // Enumerate framework data providers sequentially.
+            if(iNextDpId == iDpIdDeviceDp)
+                {
+                if(KMTPStorageAll == storageId)
+                    {
+                    iSingletons.ObjectMgr().ObjectStore().EstablishDBSnapshotL(storageId);
+                    }
+                else
+                    {
+                    const CMTPStorageMetaData& storage(iSingletons.StorageMgr().StorageL(storageId));
+                    if(storage.Uint(CMTPStorageMetaData::EStorageSystemType) == CMTPStorageMetaData::ESystemTypeDefaultFileSystem)
+                        {
+                        const RArray<TUint>& logicalIds(storage.UintArray(CMTPStorageMetaData::EStorageLogicalIds));
+                        const TUint KCountLogicalIds(logicalIds.Count());
+                        for (TUint i(0); (i < KCountLogicalIds); i++)
+                            {
+                            __FLOG_VA((_L8("Establish snapshot for storage: 0x%x"), storageId));
+                            iSingletons.ObjectMgr().ObjectStore().EstablishDBSnapshotL(storageId);
+                            }
+                        }
+                    }
+                }
+            EnumerateDataProviderObjectsL(iNextDpId);          
+            }
+        	}
+        break;
+        
+    case EEnumeratingDataProviderObjects:
+        {
+        TUint currentDp = 0;
+        
+        // Enumerate non-framework data providers concurrently.
+        const TUint KLoadedDps(iDataProviderIds.Count());
+        while ((iEnumeratingDps.Count() < KMTPMaxEnumeratingDataProviders) && (iDpIdArrayIndex < KLoadedDps)
+               && (iEnumerationPhase == DataProviderL(iDataProviderIds[iDpIdArrayIndex]).DataProviderConfig().UintValue(MMTPDataProviderConfig::EEnumerationPhase)))
+            {
+            currentDp = iDataProviderIds[iDpIdArrayIndex++];
+            iEnumeratingDps.InsertInOrderL(currentDp);
+            EnumerateDataProviderObjectsL(currentDp);
+            }
+        }
+        break;
+        
+    case EUnenumerated:
+    case EEnumerated:
+    default:
+        __DEBUG_ONLY(User::Invariant());
+        break;
+        }
+    __FLOG(_L8("RunL - Exit"));
+    }
+
+#ifdef __FLOG_ACTIVE
+TInt CMTPDataProviderController::RunError(TInt aError)
+#else
+TInt CMTPDataProviderController::RunError(TInt /*aError*/)
+#endif
+    {
+    __FLOG(_L8("RunError - Entry"));
+    __FLOG_VA((_L8("Error = %d"), aError));
+    
+    // If a RunL error happens, there's no point in trying to continue.
+    switch (iEnumerationState)
+        {
+    case EEnumerationStarting:
+    case EEnumeratingFrameworkStorages:
+        Panic(EMTPPanicStorageEnumeration);
+        break;
+        
+    case EEnumeratingFrameworkObjects:
+        Panic(EMTPPanicFrameworkEnumeration);
+        break;
+        
+    case EEnumeratingDataProviderStorages:
+        Panic(EMTPPanicDataProviderStorageEnumeration);
+        break;
+        
+    case EEnumeratingDataProviderObjects:
+        Panic(EMTPPanicDataProviderEnumeration);
+        break;
+        
+    case EUnenumerated:
+    case EEnumerated:
+    default:
+        User::Invariant();
+        break;
+        }
+
+    // This code is never reached
+    __FLOG(_L8("RunError - Exit"));
+    return KErrNone;
+    }
+
+/**
+Constructor.
+*/
+CMTPDataProviderController::CMTPDataProviderController() :
+    CActive(EPriorityNormal)
+    {
+    CActiveScheduler::Add(this);
+    }
+
+/**
+Second-phase constructor.
+@leave One of the system wide error codes if a processing failure occurs.
+*/
+void CMTPDataProviderController::ConstructL()
+    {
+    __FLOG_OPEN(KMTPSubsystem, KComponent);
+    __FLOG(_L8("ConstructL - Entry"));
+    iSingletons.OpenL();
+	TInt tMTPMode;
+	TInt err = RProperty::Get(KUidSystemCategory, KUidMTPModeKeyValue, tMTPMode);
+	if(err != KErrNone)
+		{
+		tMTPMode = KMTPModeMTP;		
+		}
+	else
+		{
+		if(tMTPMode != KMTPModeMTP && tMTPMode != KMTPModePTP && tMTPMode != KMTPModePictBridge)
+		tMTPMode = KMTPModeMTP;
+		}
+	iMode = (TMTPOperationalMode)tMTPMode;
+	CreateRegistrySessionAndEntryL();
+    
+	iFlagDb = 0;
+	
+    iOpenSessionWaiter = new(ELeave) CActiveSchedulerWait();
+    __FLOG(_L8("ConstructL - Exit"));
+    }
+    
+/**
+Creates a data provider configurability parameter data instance on the cleanup 
+stack.
+@param aResourceFilename The data provider configuration data resource filename.
+@return A pointer to the data provider configurability parameter data instance, 
+which is also placed on the cleanup stack. Ownership is transferred.
+@leave One of the system wide error codes, if a processing failure occurs.
+*/    
+CMTPDataProviderConfig* CMTPDataProviderController::CreateConfigLC(const TDesC& aResourceFilename)
+    {
+    __FLOG(_L8("CreateConfigLC - Entry"));
+    // Open the configuration data resource file
+    RResourceFile file;
+    CleanupClosePushL(file);
+    file.OpenL(iSingletons.Fs(), aResourceFilename);    
+    
+    // Create the resource reader.
+    const TInt KDefaultResourceId(1);
+    HBufC8* buffer(file.AllocReadLC(KDefaultResourceId));
+    TResourceReader reader;
+    reader.SetBuffer(buffer);
+    
+    // Load the data provider configurability parameter data.
+    CMTPDataProviderConfig* config(CMTPDataProviderConfig::NewL(reader, aResourceFilename));
+    CleanupStack::PopAndDestroy(buffer);
+    CleanupStack::PopAndDestroy(&file);
+    CleanupStack::PushL(config);
+    __FLOG(_L8("CreateConfigLC - Exit"));
+    return config;
+    }
+
+/**
+Check the  necessity of objects enumeration as given the data provider 
+@param dp CMTPDataProvider reference
+*/
+TBool CMTPDataProviderController::IsObjectsEnumerationNeededL(CMTPDataProvider& dp)
+{
+    __FLOG(_L8("CheckEnumerateDPObjectsL - Entry"));
+
+	CMTPStorageMgr& storages = iSingletons.StorageMgr();
+	TUint32 aStorageId = iEnumeratingStorages[0];
+	
+    TBool doEnumeration = true;
+	
+	if (aStorageId != KMTPStorageAll && storages.PhysicalStorageId(aStorageId))
+		{
+		TBool isFSBased(false);
+		RArray<TUint> storageTypes = dp.SupportedCodes( EStorageSystemTypes );
+                // check whether the storage type of the dp is file system based.
+		for (TInt i = 0; i < storageTypes.Count() && !isFSBased; i++)
+			{
+			   isFSBased= (storageTypes[i] == CMTPStorageMetaData::ESystemTypeDefaultFileSystem);
+			}
+		// As given physical storage id, only fs based dp need to do the enumeration.
+		if (!isFSBased)
+			{
+			  doEnumeration = false;
+			}
+	    }
+	__FLOG(_L8("CheckEnumerateDPObjectsL - Exit"));
+	return doEnumeration;
+}
+
+/**
+Requests that the given data provider enumerate its objects.
+@param aId data provider ID
+*/
+void CMTPDataProviderController::EnumerateDataProviderObjectsL(TUint aId)
+    {
+    __FLOG(_L8("EnumerateDataProviderObjectsL - Entry"));
+    CMTPDataProvider& dp(DataProviderL(aId));
+
+	if (IsObjectsEnumerationNeededL(dp))
+		{   
+		TBool abnormaldown = ETrue;
+		iSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::EAbnormalDown , abnormaldown);
+		if ( (!abnormaldown) && (dp.DataProviderConfig().BoolValue(MMTPDataProviderConfig::EObjectEnumerationPersistent)))
+			{       
+			// Initialize persistent objects store.
+            iSingletons.ObjectMgr().RestorePersistentObjectsL(aId);
+			}
+        else
+        	{
+			// Mark all non-persistent objects.    
+			iSingletons.ObjectMgr().MarkNonPersistentObjectsL(aId,iEnumeratingStorages[0]);
+		    }
+    
+        // Initiate the data provider enumeration sequence.
+        dp.EnumerateObjectsL(iEnumeratingStorages[0]);
+		}
+	else 
+		{
+		//The DP does not need enumeration this time, so just change the state to go on.
+		EnumerationStateChangedL(dp);
+		}
+
+    __FLOG(_L8("EnumerateDataProviderObjectsL - Exit"));
+    }
+    
+/**
+Loads the dataprovider on ROM drives depending upon the mode and activates the specified ECOM data provider.
+@param aResourceFilename The data provider registration and configuration data 
+resource filename.
+@param aImplementations The ECOM data provider implementations list (ordered by 
+implementation UID).
+@return ETrue if data provider is successfully loaded, EFalse otherwise.
+@leave One of the system wide error codes, if a processing failure occurs. 
+*/
+TBool CMTPDataProviderController::LoadROMDataProvidersL(const TDesC& aResourceFilename, const RImplInfoPtrArray& aImplementations)
+    {
+    __FLOG(_L8("LoadROMDataProvidersL - Entry"));
+    // Retrieve the implementation UID
+    TUint uid(0);
+    User::LeaveIfError(Uid(aResourceFilename, uid));
+    TBool success(EFalse);
+
+    // Check for a corresponding plug-in implementation.
+    TInt index = aImplementations.FindInOrder(TUid::Uid(uid), ImplementationsLinearOrderUid);
+    if (index >= 0)
+        {       	
+        // Construct the configuration data resource file full path name.
+        RBuf filename;
+        CleanupClosePushL(filename);  
+        filename.CreateL(KMTPDpResourceDirectory.BufferSize + aResourceFilename.Length());
+        filename.Append(KMTPDpResourceDirectory);
+        filename.Append(aResourceFilename); 
+        if(iStubFound)
+            {
+            RPointerArray<HBufC> files;
+            CleanupClosePushL(files);
+            iSisEntry.FilesL(files);
+            for (TInt i = 0; i< files.Count(); ++i)
+                {
+                TPtrC resourceFileName = files[i]->Des();
+                TPtrC fileName = resourceFileName.Mid(resourceFileName.LocateReverse('\\') + 1);
+                if(fileName.MatchF(aResourceFilename) != KErrNotFound)
+                    {
+                    TDriveName drive = aImplementations[index]->Drive().Name();
+                    //replace "z:" with "c:" or "d:" or ...
+                    filename.Replace(0,2,drive);
+                    break;
+                    }
+                }
+            CleanupStack::Pop(&files);
+            files.ResetAndDestroy();  	        	
+            }
+        success = LoadDataProviderL(filename);
+        CleanupStack::PopAndDestroy(&filename);
+        }    	
+    __FLOG(_L8("LoadROMDataProvidersL - Exit"));
+    return success;
+    }
+
+/**
+Load all data providers installed on non-ROM drives depending upon the mode and activates 
+the specified ECOM data provider.
+@param aImplementations The installed ECOM data provider implementations list (ordered by 
+implementation UID).
+@leave One of the system wide error codes, if a processing failure occurs. 
+*/
+void CMTPDataProviderController::LoadInstalledDataProvidersL(const CImplementationInformation* aImplementations)
+    {
+    __FLOG(_L8("LoadInstalledDataProvidersL - Entry"));
+    TUint uid = aImplementations->ImplementationUid().iUid;
+    TBool tFlag(EFalse);
+    iNextDpId = iSingletons.ObjectMgr().DPIDL(uid, tFlag);
+    if(!tFlag)
+        {
+        iSingletons.ObjectMgr().InsertDPIDObjectL(iNextDpId, uid);
+        }   
+
+    HBufC8 *OpaqData = HBufC8::NewLC(KOpaqueDataLength);
+    *OpaqData = aImplementations->OpaqueData();
+    TBuf16<KOpaqueDataLength> pkgIDstr;
+    pkgIDstr.Copy(*OpaqData);
+    CleanupStack::PopAndDestroy(OpaqData);
+    pkgIDstr.Trim();
+    _LIT(prefix, "0x");
+    TInt searchindex = pkgIDstr.FindC(prefix);
+    if(KErrNotFound != searchindex)
+        {
+        //Skip "0x".
+        pkgIDstr = pkgIDstr.Mid(searchindex + 2);
+        }
+    if (0 == pkgIDstr.Length())
+        {
+        User::Leave(KErrArgument);
+        }
+    
+    TUint aUid(0);
+    User::LeaveIfError(Uid(pkgIDstr, aUid));
+    
+    iSingletons.ObjectMgr().InsertPkgIDObjectL(iNextDpId, aUid);
+    TDriveName drive = aImplementations->Drive().Name();
+    RBuf resourcefilename;
+    CleanupClosePushL(resourcefilename);  
+    resourcefilename.CreateL(KMaxFileName);
+    resourcefilename.Copy(KMTPDpResourceDirectory);
+    //Replace "z:"(at 0 position) with "c:" or "d:" or ...
+    resourcefilename.Replace(0,2,drive);
+
+    RBuf rscfile;
+    CleanupClosePushL(rscfile);
+    rscfile.CreateL(KMaxFileName);
+    rscfile.NumUC(uid,EHex);
+    _LIT(postfix, ".rsc");
+    rscfile.Append(postfix);
+    resourcefilename.Append(rscfile);
+    CleanupStack::PopAndDestroy(&rscfile);
+   
+    LoadDataProviderL(resourcefilename);
+
+    CleanupStack::PopAndDestroy(&resourcefilename);
+    __FLOG(_L8("LoadInstalledDataProvidersL - Exit"));
+    }
+
+/**
+Load data providers
+@param aImplementations The installed ECOM data provider implementations list (ordered by 
+implementation UID).
+@return ETrue if data provider is successfully loaded, EFalse otherwise.
+@leave One of the system wide error codes, if a processing failure occurs. 
+*/
+TBool CMTPDataProviderController::LoadDataProviderL(const TDesC& aResourceFilename)
+    {
+    __FLOG(_L8("LoadDataProviderL - Entry"));
+    // Load the configurability parameter data.
+    CMTPDataProviderConfig* config(CreateConfigLC(aResourceFilename));
+    
+    
+    TBool success(EFalse);
+    TBool supported(ETrue);
+    TUint aUid(0);
+    if ( Uid(aResourceFilename,aUid) != KErrNone )
+       	{
+        return success;	
+       	}
+    TUint uid(aUid);
+    if ((uid != KMTPImplementationUidDeviceDp) && (uid != KMTPImplementationUidProxyDp) && (uid != KMTPImplementationUidFileDp))
+        {
+        supported = EFalse;
+        RArray<TUint> supportedModeArray;			
+        config->GetArrayValue(MMTPDataProviderConfig::ESupportedModes, supportedModeArray);
+        TInt i=0;
+        while (i < supportedModeArray.Count())
+            {
+            if(iMode == supportedModeArray[i])
+                {
+                supported = ETrue;
+                break;
+                }
+            i++;
+            }
+        supportedModeArray.Close();
+        if(!supported)
+            {
+            //Update the Database table last IsDploaded filed with Efalse;
+            /* create dummy  DP which is just new of Dervied DataPRoviderClass
+            update the DataBase  so that DPIP which this was get then set handle Store DB */
+            iSingletons.ObjectMgr().MarkDPLoadedL(iNextDpId,EFalse);
+            RBuf dummyfilename;
+            CleanupClosePushL(dummyfilename);
+            dummyfilename.CreateL(KMTPDpDummyResourcefile.BufferSize);        		
+            dummyfilename.Append(KMTPDpDummyResourcefile);							
+            CMTPDataProviderConfig* aDummyConfig(CreateConfigLC(dummyfilename));
+            CMTPDataProvider* dummyDp(NULL);		
+            dummyDp = CMTPDataProvider::NewLC(iNextDpId, TUid::Uid(uid), aDummyConfig);
+            iDataProviders.InsertInOrderL(dummyDp, TLinearOrder<CMTPDataProvider>(CMTPDataProvider::LinearOrderUid));			
+            CleanupStack::Pop(dummyDp);          						
+            CleanupStack::Pop(aDummyConfig);
+            CleanupStack::PopAndDestroy(&dummyfilename);			
+            }
+        }
+    CMTPDataProvider* dp(NULL);
+    if(supported)
+        {
+        // Load the data provider.        	
+        switch (config->UintValue(MMTPDataProviderConfig::EDataProviderType))
+            {
+        case EEcom:
+            {
+            // Configurability parameter data ownership is passed to the data provider.
+            iSingletons.ObjectMgr().MarkDPLoadedL(iNextDpId, ETrue);
+            dp = CMTPDataProvider::NewLC(iNextDpId, TUid::Uid(uid), config);
+            }
+            break;
+
+        default:
+            __DEBUG_ONLY(User::Invariant());
+            break;
+            }
+    	}
+    if (dp)
+        {
+        // Register the data provider.
+        switch (uid)
+            {
+            case KMTPImplementationUidDeviceDp:
+                iDpIdDeviceDp = iNextDpId;
+                break;
+
+            case KMTPImplementationUidFileDp:
+                iDpIdFileDp = iNextDpId;
+                break;
+
+            case KMTPImplementationUidProxyDp:
+                iDpIdProxyDp = iNextDpId;
+                break;
+
+            default:
+                break;
+            }
+        iDataProviders.InsertInOrderL(dp,  TLinearOrder<CMTPDataProvider>(CMTPDataProvider::LinearOrderUid));
+        CleanupStack::Pop(dp);
+        CleanupStack::Pop(config);
+        success = ETrue;
+        }
+    else
+        {
+        // No data provider was created.
+        CleanupStack::PopAndDestroy(config);
+        }
+    __FLOG(_L8("LoadDataProviderL - Exit"));
+    return success;
+    }
+
+/**
+Provides the implemetation UID associated with the specified data provider 
+configuration data resource filename.
+@param aResourceFilename The data provider configuration data resource
+filename.
+@param aUid On completion, the implemetation UID.
+*/
+TInt CMTPDataProviderController::Uid(const TDesC& aResourceFilename, TUint& aUid)
+    {
+    __FLOG(_L8("Uid - Entry"));
+    // Extract the implemetation UID from the filename.
+    TParsePtrC parser(aResourceFilename);
+    TLex lex(parser.Name());
+    TInt err = lex.Val(aUid, EHex);
+    __FLOG(_L8("Uid - Exit"));
+    return err;
+    }
+
+/**
+Schedules an enumeration iteration.
+*/
+void CMTPDataProviderController::Schedule()
+    {
+    __FLOG(_L8("Schedule - Entry"));
+    if (!IsActive())
+        {
+        TRequestStatus* status(&iStatus);
+        *status = KRequestPending;
+        SetActive();
+        User::RequestComplete(status, KErrNone);
+        }
+    __FLOG(_L8("Schedule - Exit"));
+    }
+/**
+Get the mtpkey mode.
+*/    
+TMTPOperationalMode CMTPDataProviderController::Mode()
+	{
+	return iMode;
+	}
+     
+void CMTPDataProviderController::ImplementationsCleanup(TAny* aData)
+    {
+    reinterpret_cast<RImplInfoPtrArray*>(aData)->ResetAndDestroy();
+    }
+    
+/**
+Implements a linear order relation for @see CImplementationInformation 
+objects based on relative @see CImplementationInformation::ImplementationUid.
+@param aUid The implementation UID object to match.
+@param aObject The object instance to match.
+@return Zero, if the two objects are equal; A negative value, if the first 
+object is less than the second, or; A positive value, if the first object is 
+greater than the second.
+*/     
+TInt CMTPDataProviderController::ImplementationsLinearOrderUid(const TUid* aUid, const CImplementationInformation& aObject)
+    {
+    return (aUid->iUid - aObject.ImplementationUid().iUid);
+    }
+    
+/**
+Implements a @see TLinearOrder for @see CImplementationInformation objects 
+based on relative @see CImplementationInformation::ImplementationUid.
+@param aL The first object instance.
+@param aR The second object instance.
+@return Zero, if the two objects are equal; A negative value, if the first 
+object is less than the second, or; A positive value, if the first object is 
+greater than the second.
+*/   
+TInt CMTPDataProviderController::ImplementationsLinearOrderUid(const CImplementationInformation& aL, const CImplementationInformation& aR)
+    {
+    return (aL.ImplementationUid().iUid - aR.ImplementationUid().iUid);
+    }
+
+/**
+Provides the enumeration state
+@return iEnumerationState
+*/
+EXPORT_C TUint CMTPDataProviderController::EnumerateState()
+    {
+    return iEnumerationState;
+    } 
+
+void CMTPDataProviderController::CreateRegistrySessionAndEntryL()
+	{
+	User::LeaveIfError(iSisSession.Connect());
+    CleanupClosePushL(iSisSession);
+    TInt err = KErrNone;
+    TUint stubuid;
+    iSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::EPackageStubUID , stubuid);
+ 	TRAP_IGNORE(err=iSisEntry.Open(iSisSession, TUid::Uid(stubuid) ));
+	if(err == KErrNone)
+		{
+		iStubFound = ETrue;	
+		}
+	CleanupStack::Pop();	
+	}
+	
+void  CMTPDataProviderController::CloseRegistrySessionAndEntryL()
+	{
+	if (&iSisEntry != NULL)
+		{
+		iSisEntry.Close();	
+		}
+	iSisSession.Close();
+	}
+