mtpfws/mtpfw/dataproviders/devdp/src/cmtpstoragewatcher.cpp
changeset 0 d0791faffa3f
child 1 f8e15b44d440
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtpfws/mtpfw/dataproviders/devdp/src/cmtpstoragewatcher.cpp	Tue Feb 02 01:11:40 2010 +0200
@@ -0,0 +1,524 @@
+// 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 <mtp/cmtpdataproviderplugin.h>
+#include <mtp/mmtpdataproviderframework.h>
+#include <mtp/mtpprotocolconstants.h>
+#include <mtp/mtpdataproviderapitypes.h>
+
+#include "cmtpdataprovider.h"
+#include "cmtpdataprovidercontroller.h"
+#include "cmtpframeworkconfig.h"
+#include "cmtpstoragemgr.h"
+#include "cmtpobjectmgr.h"
+#include "cmtpstoragewatcher.h"
+#include "rmtpdevicedpsingletons.h"
+#include "cmtpdevicedpconfigmgr.h"
+
+
+// Class constants.
+__FLOG_STMT(_LIT8(KComponent,"StorageWatcher");)
+static const TBool KAllDrives(ETrue);
+static const TBool KAvailableDrives(EFalse);
+
+const TInt KFolderExclusionGranularity = 8;
+
+/**
+MTP system storage watcher factory method.
+@return A pointer to an MTP system storage watcher object. Ownership IS 
+transfered.
+@leave One of the system wide error codes, if a processing failure occurs.
+*/
+CMTPStorageWatcher* CMTPStorageWatcher::NewL(MMTPDataProviderFramework& aFramework)
+    {
+    CMTPStorageWatcher* self = new (ELeave) CMTPStorageWatcher(aFramework);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+/**
+Destructor.
+*/    
+CMTPStorageWatcher::~CMTPStorageWatcher()
+    {
+    __FLOG(_L8("~CMTPStorageWatcher - Entry"));
+    Cancel();
+    delete iFolderExclusionList;
+    iDpSingletons.Close();
+    iDrivesExcluded.Close();
+    iFrameworkSingletons.Close();
+    __FLOG(_L8("~CMTPStorageWatcher - Exit"));
+    __FLOG_CLOSE;
+    }
+    
+void CMTPStorageWatcher::EnumerateStoragesL()
+    {
+    __FLOG(_L8("EnumerateStoragesL - Entry"));
+
+    //Use Hash to replace it
+    AppendFolderExclusionListL();
+    
+    // Retrieve the drive exclusion list.
+    iFrameworkSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::EExcludedStorageDrives, iDrivesExcluded);
+    iDrivesExcluded.Sort();
+    
+    // Claim system storages ownership.
+    CMTPStorageMgr& mgr(iFrameworkSingletons.StorageMgr());
+    mgr.SetFrameworkId(iFramework.DataProviderId());
+    
+    /* 
+    Enumerate the initial drive set. 
+    
+        1.   Enumerate each known drive as a physical storage.
+    */
+    iDrivesConfig = DriveConfigurationL(KAllDrives);
+    CMTPStorageMetaData* storage = CMTPStorageMetaData::NewLC();
+    storage->SetUint(CMTPStorageMetaData::EStorageSystemType, CMTPStorageMetaData::ESystemTypeDefaultFileSystem);
+    _LIT(KSuidTemplate, "?:");
+    RBuf suid;
+    suid.CleanupClosePushL();
+    suid.Assign((KSuidTemplate().AllocL()));
+    
+    for (TInt drive(0); (drive < KMaxDrives); drive++)
+        {
+        const TUint32 mask(1 << drive);
+        if (iDrivesConfig & mask)
+            {
+            TChar driveChar;
+            User::LeaveIfError(iFramework.Fs().DriveToChar(drive, driveChar));
+            suid[0] = driveChar;
+            storage->SetDesCL(CMTPStorageMetaData::EStorageSuid, suid);
+                    
+            TUint32 id(mgr.AllocatePhysicalStorageIdL(iFramework.DataProviderId(), *storage));
+            mgr.SetDriveMappingL(static_cast<TDriveNumber>(drive), id);
+            }
+        }
+        
+    CleanupStack::PopAndDestroy(&suid);
+    CleanupStack::PopAndDestroy(storage);
+    
+    /* 
+        2.  If so configured, enumerate a single logical storage for each of 
+            the available drives.
+    */
+    if (iAllocateLogicalStorages)
+        {
+        iDrivesConfig = DriveConfigurationL(KAvailableDrives);
+
+        for (TInt drive(0); (drive < KMaxDrives); drive++)
+            {
+            const TUint32 mask(1 << drive);
+            if (iDrivesConfig & mask)
+                {
+                StorageAvailableL(static_cast<TDriveNumber>(drive));
+                }
+            }
+        }
+    
+    // Set the default storage.
+    TUint defaultDrive;
+    iFrameworkSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::EDefaultStorageDrive, defaultDrive);
+    
+    if ( defaultDrive <= EDriveZ )
+        {
+        // Default drive is specified by drive number.. retrieve from manager..
+        if (iAllocateLogicalStorages)
+            {
+            mgr.SetDefaultStorageId(mgr.FrameworkStorageId(static_cast<TDriveNumber>(defaultDrive)));
+            }
+        else
+            {
+            mgr.SetDefaultStorageId(mgr.PhysicalStorageId(static_cast<TDriveNumber>(defaultDrive)));
+            }
+        }
+    else
+       {
+       // Default drive is specified by storage number
+       mgr.SetDefaultStorageId(defaultDrive);
+       }
+       
+    __FLOG(_L8("EnumerateStoragesL - Exit"));
+    }
+
+/**
+Initiates storage change notice subscription.
+*/
+void CMTPStorageWatcher::Start()
+    {
+    __FLOG(_L8("Start - Entry"));
+    if (!(iState & EStarted))
+        {
+        __FLOG(_L8("Starting RFs notifier"));
+        TRequestStatus* status(&iStatus);
+        User::RequestComplete(status, KErrNone);
+        SetActive();
+        iState |= EStarted;
+        }
+    __FLOG(_L8("Start - Exit"));    
+    }
+    
+void CMTPStorageWatcher::DoCancel()
+    {
+    __FLOG(_L8("DoCancel - Entry"));
+    __FLOG(_L8("Stopping RFs notifier"));
+    iFrameworkSingletons.Fs().NotifyChangeCancel();
+    iState &= (!EStarted);
+    __FLOG(_L8("DoCancel - Exit"));
+    }
+
+/**
+Append all DPs folder exclusion list strings in Device DP
+ */
+void CMTPStorageWatcher::AppendFolderExclusionListL()
+    {
+    CDesCArraySeg* folderExclusionSets = new (ELeave) CDesCArraySeg(KFolderExclusionGranularity);
+    CleanupStack::PushL(folderExclusionSets);
+    CMTPDataProviderController& dps(iFrameworkSingletons.DpController());
+    TUint currentDpIndex = 0, count = dps.Count();
+    while (currentDpIndex < count)
+        {
+        CMTPDataProvider& dp(dps.DataProviderByIndexL(currentDpIndex));
+        if(KMTPImplementationUidDeviceDp != dp.ImplementationUid().iUid)
+            {
+            folderExclusionSets->Reset();
+            dp.Plugin().SupportedL(EFolderExclusionSets,*folderExclusionSets);
+            for(TInt i = 0; i < folderExclusionSets->Count(); ++i)
+                {
+                TPtrC16 excludedFolder = (*folderExclusionSets)[i];
+                iFolderExclusionList->AppendL(excludedFolder);
+                }
+            }
+        currentDpIndex++;
+        }
+    CleanupStack::PopAndDestroy(folderExclusionSets);
+    }
+
+/**
+Handles leaves occurring in RunL.
+@param aError leave error code
+@return KErrNone
+*/
+#ifdef __FLOG_ACTIVE
+TInt CMTPStorageWatcher::RunError(TInt aError)
+#else
+TInt CMTPStorageWatcher::RunError(TInt /*aError*/)
+#endif
+    {
+    __FLOG(_L8("RunError - Entry"));
+    __FLOG_VA((_L8("Error = %d"), aError));
+
+    // Ignore the error, meaning that the storages may not be accurately accounted for
+    RequestNotification();
+
+    __FLOG(_L8("RunError - Exit"));
+    return KErrNone;
+    }
+    
+void CMTPStorageWatcher::RunL()
+    {
+    __FLOG(_L8("RunL - Entry"));
+    const TUint32 previous(iDrivesConfig);
+    const TUint32 current(DriveConfigurationL(KAvailableDrives));
+    if (current != previous)
+        {        
+        const TUint32 changed(current ^ previous);
+        const TUint32 added(changed & current);
+        const TUint32 removed(changed & previous);
+        TInt i(KMaxDrives);
+        while (i--)
+            {
+            const TUint32 mask(1 << i);
+            if (added & mask)
+                {
+                StorageAvailableL(static_cast<TDriveNumber>(i));
+                }
+            else if (removed & mask)
+                {
+                StorageUnavailableL(static_cast<TDriveNumber>(i));
+                }
+            }
+        }
+    iDrivesConfig = current;
+    RequestNotification();
+    __FLOG(_L8("RunL - Exit"));
+    }
+    
+/**
+Constructor.
+@param aConnectionMgr The MTP connection manager interface.
+*/
+CMTPStorageWatcher::CMTPStorageWatcher(MMTPDataProviderFramework& aFramework) :
+    CActive(EPriorityStandard),
+    iFramework(aFramework)
+    {
+    CActiveScheduler::Add(this);
+    }
+    
+/**
+Second phase constructor.
+*/
+void CMTPStorageWatcher::ConstructL()
+    {
+    __FLOG_OPEN(KMTPSubsystem, KComponent);
+    __FLOG(_L8("ConstructL - Entry"));
+    iFrameworkSingletons.OpenL();
+    iFrameworkSingletons.FrameworkConfig().GetValueL(CMTPFrameworkConfig::ELogicalStorageIdsAllocationEnable, iAllocateLogicalStorages);
+    
+    RMTPDeviceDpSingletons devSingletons;
+    devSingletons.OpenL(iFramework);
+    CleanupClosePushL(devSingletons);
+    
+    iDpSingletons.OpenL(iFramework);
+    iFolderExclusionList = devSingletons.ConfigMgr().GetArrayValueL(CMTPDeviceDpConfigMgr::EFolderExclusionList); 
+    CleanupStack::PopAndDestroy(&devSingletons);
+    __FLOG(_L8("ConstructL - Exit"));
+    }
+    
+TUint32 CMTPStorageWatcher::DriveConfigurationL(TBool aAllDrives) const
+    {
+    __FLOG(_L8("DriveConfigurationL - Entry"));
+    TUint32     config(0);
+    TDriveList  drives;
+    RFs&        fs(iFrameworkSingletons.Fs());
+    User::LeaveIfError(fs.DriveList(drives));
+    TInt i(KMaxDrives);
+    while (i--)
+        {        
+        __FLOG_VA((_L8("Drive number %d, available = 0x%02d"), i, drives [i]));
+        if ((drives[i]) &&
+            (!Excluded(static_cast<TDriveNumber>(i))))
+            {
+            TDriveInfo info;
+            User::LeaveIfError(fs.Drive(info, i));
+            if ((info.iType != EMediaNotPresent) || (aAllDrives))
+                {
+                TVolumeInfo volumeInfo;
+                if(KErrNone == fs.Volume(volumeInfo,i))
+                	{
+                	config |=  (1 << i);
+                	}
+                }
+            }
+        }
+    __FLOG_VA((_L8("Drives list = 0x%08X, AllDrives = %d"), config, aAllDrives));
+    __FLOG(_L8("DriveConfigurationL - Exit"));
+    return config;
+    }
+
+TBool CMTPStorageWatcher::Excluded(TDriveNumber aDriveNumber) const
+    {
+    __FLOG(_L8("Excluded - Entry"));
+    TBool ret(iDrivesExcluded.FindInOrder(aDriveNumber) != KErrNotFound);
+    __FLOG_VA((_L8("Drive = %d, excluded = %d"), aDriveNumber, ret));
+    __FLOG(_L8("Excluded - Exit"));
+    return ret;
+    }
+    
+void CMTPStorageWatcher::RequestNotification()
+    {
+    __FLOG(_L8("RequestNotification - Entry"));
+    _LIT(KPath, "?:\\..");
+    iFrameworkSingletons.Fs().NotifyChange(ENotifyEntry, iStatus, KPath);
+    SetActive();
+    __FLOG(_L8("RequestNotification - Exit"));
+    }
+ 
+void CMTPStorageWatcher::SendEventL(TUint16 aEvent, TUint32 aStorageId)
+    {
+    __FLOG(_L8("SendEventL - Entry"));
+    if (iState & EStarted)
+        {
+        __FLOG_VA((_L8("Sending event 0x%04X for StorageID 0x%08X"), aEvent, aStorageId));
+        iEvent.Reset();
+        iEvent.SetUint16(TMTPTypeEvent::EEventCode, aEvent);
+        iEvent.SetUint32(TMTPTypeEvent::EEventSessionID, KMTPSessionAll);
+        iEvent.SetUint32(TMTPTypeEvent::EEventTransactionID, KMTPTransactionIdNone);
+        iEvent.SetUint32(TMTPTypeEvent::EEventParameter1, aStorageId);
+        iFramework.SendEventL(iEvent);
+        }
+    __FLOG(_L8("SendEventL - Exit"));
+    }
+
+/**
+Configures the specified drive as an available MTP storage.
+@param aDriveNumber The Symbian OS file system drive number.
+@leave One of the system wide error codes, if a processing failure occurs.
+*/    
+void CMTPStorageWatcher::StorageAvailableL(TDriveNumber aDriveNumber)
+    {
+    __FLOG(_L8("StorageAvailableL - Entry"));
+    __FLOG_VA((_L8("Drive = %d is available."), aDriveNumber));
+    CMTPStorageMgr& mgr(iFrameworkSingletons.StorageMgr());
+    TInt32 physical(mgr.PhysicalStorageId(aDriveNumber));
+    _LIT(KSuidTemplate, "?:");
+    // Generate the storage SUID as the drive root folder.
+    RBuf suid;
+    suid.CleanupClosePushL();
+    suid.Assign((KSuidTemplate().AllocL()));
+    TChar driveChar;
+    User::LeaveIfError(iFramework.Fs().DriveToChar(aDriveNumber, driveChar));
+    driveChar.LowerCase();
+    suid[0] = driveChar;
+    // Create the storage meta-data.
+    CMTPStorageMetaData* storage = CMTPStorageMetaData::NewLC();
+    storage->SetUint(CMTPStorageMetaData::EStorageSystemType, CMTPStorageMetaData::ESystemTypeDefaultFileSystem);
+    storage->SetDesCL(CMTPStorageMetaData::EStorageSuid, suid);
+    if(physical == KErrNotFound)
+    	{
+        TUint32 id(mgr.AllocatePhysicalStorageIdL(iFramework.DataProviderId(), *storage));
+        mgr.SetDriveMappingL(aDriveNumber, id);
+    	}
+    physical = mgr.PhysicalStorageId(aDriveNumber);
+
+    User::LeaveIfError(physical);
+    TUint32 logical(physical);
+
+    // If configured to do so, assign a logical storage ID mapping.
+    if (iAllocateLogicalStorages)
+        {
+        __FLOG(_L8("Assigning local storage ID mapping"));
+        
+        // Try to read from resource file to use a specified root dir path, if available.
+        RBuf rootDirPath;
+        rootDirPath.CreateL(KMaxFileName);
+        rootDirPath.CleanupClosePushL();
+        RMTPDeviceDpSingletons devSingletons;
+        devSingletons.OpenL(iFramework);
+        CleanupClosePushL(devSingletons);
+        TRAPD(resError, devSingletons.ConfigMgr().GetRootDirPathL(aDriveNumber, rootDirPath));
+        __FLOG_VA((_L8("ResError = %d"), resError));
+        if ((KErrNone == resError) && (0 < rootDirPath.Length()))
+            {
+            __FLOG(_L8("Reading resource file succeeded"));
+            // If there is a root directory information in rss file then check the directory exist or not. 
+            // If not exists, then create it. 
+            // Before doing anything, delete the leading and trailing white space.
+            rootDirPath.Trim();       
+            TBuf<KMaxFileName> buffer;
+            buffer.Append(driveChar);
+            _LIT(KSeperator,":");
+            buffer.Append(KSeperator);
+            buffer.Append(rootDirPath);
+            TInt error = iFramework.Fs().MkDir(buffer);
+            suid.Close();
+            _LIT(KSuidTemplate, "?:\\");
+            suid.Assign((KSuidTemplate().AllocL()));
+            driveChar.LowerCase();
+            suid[0] = driveChar;
+
+            if ((KErrNone == error) || (KErrAlreadyExists == error))
+                {
+                __FLOG(_L8("Overwriting SUID to specified root dir path from resource file"));  
+                //if dir already existed or created, make that as root directory
+                suid.ReAllocL(buffer.Length());
+                suid = buffer;
+                }
+            }
+        CleanupStack::PopAndDestroy(&devSingletons);
+        CleanupStack::PopAndDestroy(&rootDirPath);
+        
+        // Set up folder exclusion list
+        CDesCArraySeg* storageExclusions = new (ELeave) CDesCArraySeg(KFolderExclusionGranularity);
+        CleanupStack::PushL(storageExclusions);
+        TInt excludedFolderCount = iFolderExclusionList->Count();
+
+        for (TInt i = 0; i < excludedFolderCount; ++i)
+            {
+            TPtrC16 excludedFolder = (*iFolderExclusionList)[i];
+
+            if (excludedFolder[0] == '?' ||
+                excludedFolder[0] == '*' ||
+                excludedFolder[0] == suid[0])
+                {
+                storageExclusions->AppendL(excludedFolder);
+                }
+            }
+        for ( TInt i=0; i<storageExclusions->Count();++i)
+            {
+            HBufC16* temp = static_cast<TPtrC16>((*storageExclusions)[i]).AllocL();
+            TPtr16 tempptr(temp->Des());
+            tempptr[0] = suid[0];
+            storage->SetHashPath(tempptr,i);
+            delete temp;
+            }
+        
+        storage->SetDesCL(CMTPStorageMetaData::EStorageSuid, suid);
+        storage->SetDesCArrayL(CMTPStorageMetaData::EExcludedAreas, *storageExclusions);
+        CleanupStack::PopAndDestroy(storageExclusions);
+
+        // Create the logical StorageID and drive mapping.
+        logical = mgr.AllocateLogicalStorageIdL(iFramework.DataProviderId(), physical, *storage);
+        mgr.SetDriveMappingL(aDriveNumber, logical);
+
+        __FLOG_VA((_L8("Drive = %d mapped as storage 0x%08X"), aDriveNumber, logical));
+        }
+
+    CleanupStack::PopAndDestroy(storage);
+    CleanupStack::PopAndDestroy(&suid);
+    
+    // Notify the active data providers.
+    if (iState & EStarted)
+        {
+        TMTPNotificationParamsStorageChange params = {physical};
+        iFrameworkSingletons.DpController().NotifyDataProvidersL(EMTPStorageAdded, static_cast<TAny*>(&params));
+        }
+
+    // Notify any connected Initiator(s).
+    if (iAllocateLogicalStorages)
+        {
+        SendEventL(EMTPEventCodeStoreAdded, logical);
+        }
+        
+    __FLOG(_L8("StorageAvailableL - Exit"));
+    }
+
+/**
+Configures the specified drive as an unavailable MTP storage.
+@param aDriveNumber The Symbian OS file system drive number.
+@leave One of the system wide error codes, if a processing failure occurs.
+*/    
+void CMTPStorageWatcher::StorageUnavailableL(TDriveNumber aDriveNumber)
+{
+    __FLOG(_L8("StorageUnavailableL - Entry"));
+    __FLOG_VA((_L8("Drive = %d is unavailable."), aDriveNumber));
+    CMTPStorageMgr& mgr(iFrameworkSingletons.StorageMgr());
+    TInt32 physical(mgr.PhysicalStorageId(aDriveNumber));
+    User::LeaveIfError(physical);
+    TUint32 logical(0);
+    
+    // If configured to do so, assign a logical storage ID mapping.
+    if (iAllocateLogicalStorages)
+        {
+        logical = mgr.FrameworkStorageId(aDriveNumber);
+
+        // Deassign the logical storage ID mapping.
+        mgr.DeallocateLogicalStorageIds(iFramework.DataProviderId(), physical);
+        mgr.SetDriveMappingL(aDriveNumber, physical);
+        __FLOG_VA((_L8("Drive = %d unmapped as storage 0x%08X"), aDriveNumber, logical));
+        }
+
+    // Notify the active data providers.
+    TMTPNotificationParamsStorageChange params = {physical};
+    iFrameworkSingletons.DpController().NotifyDataProvidersL(EMTPStorageRemoved, static_cast<TAny*>(&params));
+
+    // Notify any connected Initiator(s).
+    if (iAllocateLogicalStorages)
+        {
+        SendEventL(EMTPEventCodeStoreRemoved, logical);
+        }   
+    __FLOG(_L8("StorageUnavailableL - Exit"));
+    }