// 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;
delete iPendingRequestTimer;
__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);
CreateRegistrySessionAndEntryL();
// 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() != iDpIdProxyDp))
{
iDataProviderIds.AppendL(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 == EEnumeratedFulllyCompleted)
{
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);
}
//DeviceDP need handle the SessionClose Notification
if ((dp->DataProviderId() == iDpIdDeviceDp) &&
( EMTPSessionClosed == aNotification))
{
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)
{
TInt dpId = KErrNotFound;
for (TUint index=0; index < iDataProviders.Count(); index++)
{
if (iDataProviders[index]->ImplementationUid().iUid == aUid)
{
dpId = iDataProviders[index]->DataProviderId();
break;
}
}
return dpId;
}
/**
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::EEnumeratingPhaseOneDone) && ( !iOpenSessionWaiter->IsStarted()))
{
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"));
__FLOG_VA((_L8("Entry iEnumerationState: 0x%x DpId: %d"), iEnumerationState, aDp.DataProviderId()));
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:
iEnumerationState = EEnumeratingDataProviderObjects;
iEnumerationPhase = DataProviderL(iDataProviderIds[0]).DataProviderConfig().UintValue(MMTPDataProviderConfig::EEnumerationPhase);
iDpIdArrayIndex = 0;
Schedule();
break;
}
break;
case EEnumeratingDataProviderObjects:
case EEnumeratingSubDirFiles:
if(KMTPImplementationUidFileDp == aDp.ImplementationUid().iUid && NeedEnumeratingPhase2())
{
__FLOG(_L8("File DP first level enum complete"));
Cancel();
//clean the root level snapshot
TRAP_IGNORE(iSingletons.ObjectMgr().ObjectStore().CleanDBSnapshotL(ETrue));
//Schedule again to scan subdir
iEnumerationState = EEnumeratingSubDirFiles;
}
else
{
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())
{
Cancel();
iEnumerationState = EEnumeratingCleanDBSnapshot;
TRAP_IGNORE(iSingletons.ObjectMgr().ObjectStore().CleanDBSnapshotL(EFalse));
}
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 EEnumeratedFulllyCompleted:
case EUnenumerated:
case EEnumerationStarting:
case EEnumeratingPhaseOneDone:
default:
__DEBUG_ONLY(User::Invariant());
break;
}
__FLOG_VA((_L8("Exit iEnumerationState: 0x%x, DpId: %d, UID=0x%x"), iEnumerationState, aDp.DataProviderId(), aDp.ImplementationUid().iUid));
__FLOG(_L8("EnumerationStateChangedL - Exit"));
}
void CMTPDataProviderController::DoCancel()
{
__FLOG(_L8("DoCancel - Entry"));
__FLOG(_L8("DoCancel - Exit"));
}
/*
*Buid Db SnapShot for storage
*/
void CMTPDataProviderController::EstablishDBSnapshotL(TUint32 aStorageId)
{
if(KMTPStorageAll == aStorageId)
{
iSingletons.ObjectMgr().ObjectStore().EstablishDBSnapshotL(aStorageId);
}
else
{
const CMTPStorageMetaData& storage(iSingletons.StorageMgr().StorageL(aStorageId));
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"), logicalIds[i]));
iSingletons.ObjectMgr().ObjectStore().EstablishDBSnapshotL(logicalIds[i]);
}
}
}
}
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 = EEnumeratedFulllyCompleted;
}
else
{
//deal next storage
iNextDpId = iDpIdDeviceDp;
Schedule();
}
}
else
{
// Enumerate framework data providers sequentially.
if(iNextDpId == iDpIdDeviceDp)
{
EstablishDBSnapshotL(storageId);
}
EnumerateDataProviderObjectsL(iNextDpId);
}
}
break;
case EEnumeratingDataProviderObjects:
case EEnumeratingSubDirFiles:
{
if(EEnumeratingSubDirFiles == iEnumerationState && NeedEnumeratingPhase2())
{
TUint32 storageId = iEnumeratingStorages[0];
EnumerateDataProviderObjectsL(iDpIdFileDp);
SetNeedEnumeratingPhase2(EFalse);
if(iOpenSessionWaiter->IsStarted())
{
iOpenSessionWaiter->AsyncStop();
}
ExecutePendingRequestL();
}
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++];
__FLOG_VA((_L8("Enumerating dpid %d"), currentDp));
iEnumeratingDps.InsertInOrderL(currentDp);
EnumerateDataProviderObjectsL(currentDp);
}
__FLOG_VA((_L8("iDpIdArrayIndex = %d, KLoadedDps = %d"), iDpIdArrayIndex, KLoadedDps));
}
break;
case EEnumeratingCleanDBSnapshot:
{
iEnumeratingStorages.Remove(0);
iSingletons.ObjectMgr().ObjectStore().ObjectsEnumComplete();
if(iOpenSessionWaiter->IsStarted())
{
iOpenSessionWaiter->AsyncStop();
}
ExecutePendingRequestL();
if (iEnumeratingStorages.Count() > 0)
{
iNextDpId = iDpIdDeviceDp;
iEnumerationState = EEnumeratingFrameworkObjects;
Schedule();
}
else
{
iEnumerationState = EEnumeratedFulllyCompleted; //Really finished
}
}
break;
case EEnumeratedFulllyCompleted:
case EUnenumerated:
case EEnumeratingPhaseOneDone:
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 EEnumeratingPhaseOneDone:
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();
SetNeedEnumeratingPhase2(EFalse);
iOpenSessionWaiter = new(ELeave) CActiveSchedulerWait();
iPendingRequestTimer = CMTPPendingReqestTimer::NewL(this);
__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]);
}
if ((KMTPStorageAll == iEnumeratingStorages[0]) || (iSingletons.StorageMgr().ValidStorageId(iEnumeratingStorages[0])))
{
//Only initiate the data provider enumeration sequence for valid storage or all storage
dp.EnumerateObjectsL(iEnumeratingStorages[0]);
}
else
{
EnumerationStateChangedL(dp);
}
}
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()
{
if(iStubFound)
{
return;
}
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();
}
EXPORT_C void CMTPDataProviderController::SetNeedEnumeratingPhase2(TBool aNeed)
{
__FLOG(_L8("SetNeedEnumeratingPhase2 - Entry"));
__FLOG_VA((_L8("Need = %d"), aNeed));
iNeedEnumeratingPhase2 = aNeed;
__FLOG(_L8("SetNeedEnumeratingPhase2 - Exit"));
}
EXPORT_C TBool CMTPDataProviderController::NeedEnumeratingPhase2() const
{
return iNeedEnumeratingPhase2;
}
EXPORT_C void CMTPDataProviderController::RegisterPendingRequestDP(TUint aDpUid, TUint aTimeOut)
{
__FLOG(_L8("CMTPDataProviderController::RegisterPendingRequestDP - Entry"));
__ASSERT_DEBUG((iPendingRequestDpUid == 0), User::Invariant());
iPendingRequestDpUid = aDpUid;
if (aTimeOut > 0)
{
iPendingRequestTimer->Start(aTimeOut);
}
__FLOG(_L8("CMTPDataProviderController::RegisterPendingRequestDP - Exit"));
}
EXPORT_C void CMTPDataProviderController::ExecutePendingRequestL()
{
__FLOG(_L8("CMTPDataProviderController::ExecutePendingRequestL - Entry"));
if (iPendingRequestDpUid == 0)
{
iPendingRequestTimer->Cancel();
return;
}
int i = 0;
int count = iDataProviders.Count();
for (i = 0; i < count; ++i)
{
if (iDataProviders[i]->ImplementationUid().iUid == iPendingRequestDpUid)
{
iDataProviders[i]->ExecutePendingRequestL();
iPendingRequestDpUid = 0;
break;
}
}
iPendingRequestTimer->Cancel();
__FLOG(_L8("CMTPDataProviderController::ExecutePendingRequestL - Exit"));
}
EXPORT_C TUint CMTPDataProviderController::StorageEnumerateState(TUint aStorageId)
{
if (iEnumeratingStorages.Count() == 0)
return EEnumeratedFulllyCompleted;
TUint ret = EUnenumerated;
CMTPStorageMgr& storages = iSingletons.StorageMgr();
TInt idx = iEnumeratingStorages.Find(storages.PhysicalStorageId(aStorageId));
if (idx == KErrNotFound)
{
if (iEnumeratingStorages[0] == KMTPStorageAll)
{
ret = EnumerateState();
}
else
{
ret = EEnumeratedFulllyCompleted;
}
}
else if (idx > 0)
{
ret = EUnenumerated;
}
else //idx == 0
{
ret = EnumerateState();
}
return ret;
}
CMTPDataProviderController::CMTPPendingReqestTimer* CMTPDataProviderController::CMTPPendingReqestTimer::NewL(CMTPDataProviderController* aDPController)
{
CMTPPendingReqestTimer* self = new (ELeave) CMTPDataProviderController::CMTPPendingReqestTimer(aDPController);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
CMTPDataProviderController::CMTPPendingReqestTimer::~CMTPPendingReqestTimer()
{
__FLOG(_L8("~CMTPPendingReqestTimer - Entry"));
Cancel();
__FLOG(_L8("~CMTPPendingReqestTimer - Exit"));
__FLOG_CLOSE;
}
void CMTPDataProviderController::CMTPPendingReqestTimer::Start(TUint aTimeOut)
{
__FLOG(_L8("CMTPPendingReqestTimer::Start - Entry"));
if (aTimeOut > 0)
{
const TUint KMTPPendingRequestDelay = (1000000 * aTimeOut);
After(KMTPPendingRequestDelay);
}
__FLOG(_L8("CMTPPendingReqestTimer::Start - Exit"));
}
void CMTPDataProviderController::CMTPPendingReqestTimer::RunL()
{
__FLOG(_L8("CMTPPendingReqestTimer::RunL - Entry"));
iDPController->ExecutePendingRequestL();
__FLOG(_L8("CMTPPendingReqestTimer::RunL - Exit"));
}
CMTPDataProviderController::CMTPPendingReqestTimer::CMTPPendingReqestTimer(CMTPDataProviderController* aDPController) :
CTimer(EPriorityNormal)
{
iDPController = aDPController;
}
void CMTPDataProviderController::CMTPPendingReqestTimer::ConstructL()
{
__FLOG_OPEN(KMTPSubsystem, KComponent);
__FLOG(_L8("CMTPPendingReqestTimer::ConstructL - Entry"));
CTimer::ConstructL();
CActiveScheduler::Add(this);
__FLOG(_L8("CMTPPendingReqestTimer::ConstructL - Exit"));
}