filemanager/schbkup/src/filemanagerschbackuptask.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 20:09:41 +0200
changeset 0 6a9f87576119
child 14 efe289f793e7
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* Copyright (c) 2006-2008 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:  Handles file manager scheduled backup task start
*
*/



// INCLUDE FILES
#include <e32base.h>
#include <schtask.h>
#include <w32std.h>
#include <apgtask.h>
#include <apgcli.h>
#include <apgwgnam.h>
#include <apacmdln.h>
#include <centralrepository.h>
#include <ctsydomainpskeys.h>
#include <UsbWatcherInternalPSKeys.h>
#include <usbpersonalityids.h>
#include <DataSyncInternalPSKeys.h>
#include <connect/sbdefs.h>
#include "filemanagerschbackuptask.h"
#include "filemanagerschsubscriber.h"
#include "FileManagerUID.h"
#include "FileManagerDebug.h"
#include "FileManagerSchDefinitions.h"
#include "FileManagerPrivateCRKeys.h"

using namespace conn;

// CONSTANTS
const TUid KUidFileManager = { KFileManagerUID3 };
_LIT_SECURE_ID( KFileManagerSID, KFileManagerUID3 );
const TInt KStartStateChangeTimeoutSecs = 30;
const TInt KPhoneStateChangeTimeoutSecs = 120;
const TInt KNumAttempts = -1; // Try forever


// ======== LOCAL FUNCTIONS ========

// ---------------------------------------------------------------------------
// FindStandaloneAppL
// ---------------------------------------------------------------------------
//
static TBool FindStandaloneAppL(
        RWsSession& aWs, const TUid& aUid, TInt& aWgId )
    {
    FUNC_LOG

    aWgId = 0; // Used window group id is always greater than zero
    RArray< RWsSession::TWindowGroupChainInfo > windowChain;
    User::LeaveIfError( aWs.WindowGroupList( &windowChain ) );
    CleanupClosePushL( windowChain );
    TInt count( windowChain.Count() );
    for( TInt i( 0 ); i < count; ++i )
        {
        const RWsSession::TWindowGroupChainInfo& entry( windowChain[ i ] );
        CApaWindowGroupName* app = CApaWindowGroupName::NewLC(
            aWs, entry.iId );
        TUid appUid( app->AppUid() );
        CleanupStack::PopAndDestroy( app );
        // Match the app's UID and the embedded status.
        // The app is standalone when there is no parent window group.
        if ( appUid == aUid && entry.iParentId <= 0 )
            {
            // Standalone application found
            aWgId = entry.iId;
            break;
            }
        }
    CleanupStack::PopAndDestroy( &windowChain );
    return aWgId > 0;
    }


// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::CFileManagerSchBackupTask
// ---------------------------------------------------------------------------
//
CFileManagerSchBackupTask::CFileManagerSchBackupTask() :
        CActive( EPriorityStandard ),
        iDay( KErrNotFound ),
        iAttemptsLeft( KNumAttempts )
    {
    FUNC_LOG
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::NewL
// ---------------------------------------------------------------------------
//
CFileManagerSchBackupTask* CFileManagerSchBackupTask::NewL(
        const CScheduledTask& aTask )
    {
    FUNC_LOG

    CFileManagerSchBackupTask* self =
        new ( ELeave ) CFileManagerSchBackupTask();
    CleanupStack::PushL( self );
    self->ConstructL( aTask );
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::~CFileManagerSchBackupTask
// ---------------------------------------------------------------------------
//
CFileManagerSchBackupTask::~CFileManagerSchBackupTask()
    {
    FUNC_LOG

    delete iSubscriber;
    delete iCenRep;
    Cancel();
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::RunL
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::RunL()
    {
    StartL();
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::DoCancel
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::DoCancel()
    {
    delete iSubscriber;
    iSubscriber = NULL;
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::RunError()
// ---------------------------------------------------------------------------
//
TInt CFileManagerSchBackupTask::RunError(
#ifdef FILE_MANAGER_ERROR_LOG_ENABLED
    TInt aError
#else // FILE_MANAGER_ERROR_LOG_ENABLED
    TInt /*aError*/
#endif // FILE_MANAGER_ERROR_LOG_ENABLED
     )
    {    
    ERROR_LOG1( "CFileManagerSchBackupTask::RunError()-Error=%d", aError )

    // Try again
    Retry();

    return KErrNone;
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::ConstructL
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::ConstructL( const CScheduledTask& aTask )
    {
    FUNC_LOG

    INFO_LOG1( "CFileManagerTaskScheduler::ConstructL()-Repeat=%d",
        aTask.Info().iRepeat )

    CActiveScheduler::Add( this );

    // Check task creator
    if( aTask.SecurityInfo().iSecureId.iId != KFileManagerSID )
        {
        User::Leave( KErrPermissionDenied );
        }

    // Get pointer to file manager settings
    iCenRep = CRepository::NewL( KCRUidFileManagerSettings );

    // Get backup weekday if given from originator
    const HBufC& data( aTask.Data() );
    if ( data.Length() )
        {
        TLex parse;
        parse.Assign( data );
        User::LeaveIfError( parse.Val( iDay ) );
        }

    Retry();
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::CheckBackupRequired
// ---------------------------------------------------------------------------
//
TBool CFileManagerSchBackupTask::CheckBackupRequired()
    {
    TBool ret( ETrue );

    // Check schedule type
    TInt scheduling( 0 );
    iCenRep->Get( KFileManagerBackupScheduling, scheduling );
    if ( scheduling == EFileManagerBackupScheduleNone )
        {
        // Backup is not required
        ret = EFalse;
        }

    // Check weekday
    if ( ret && iDay != KErrNotFound )
        {
        TTime time;
        time.HomeTime();
        if ( time.DayNoInWeek() != iDay )
            {
            // Backup is not required today
            ret = EFalse;
            }
        }

    if ( !ret )
        {
        INFO_LOG( "CFileManagerSchBackupTask::CheckBackupRequired()-No" )
        Exit();
        }

    return ret;
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::CheckPhoneStateL
// ---------------------------------------------------------------------------
//
TBool CFileManagerSchBackupTask::CheckPhoneStateL()
    {
    // Check call state
    TInt callState( 0 );
    RProperty::Get(
        KPSUidCtsyCallInformation, KCTsyCallState, callState ); 
    if ( callState != EPSCTsyCallStateNone )
        {
        INFO_LOG1( "CFileManagerSchBackupTask::CheckPhoneStateL()-callState=%d",
            callState )

        // Set subscriber to wait call to finish
        iSubscriber = CFileManagerSchSubscriber::NewL(
            *this,
            KPSUidCtsyCallInformation,
            KCTsyCallState,
            CFileManagerSchSubscriber::ESubscribePS,
            KPhoneStateChangeTimeoutSecs );
        return EFalse;
        }

    // Check usb transfer state
    TInt usbState( 0 );
    RProperty::Get(
        KPSUidUsbWatcher, KUsbWatcherSelectedPersonality, usbState );
    if ( usbState == KUsbPersonalityIdMS )
        {
        INFO_LOG( "CFileManagerSchBackupTask::CheckPhoneStateL()-Usb transfer on" )

        // Set subscriber to wait usb transfer to finish
        iSubscriber = CFileManagerSchSubscriber::NewL(
            *this,
            KPSUidUsbWatcher,
            KUsbWatcherSelectedPersonality,
            CFileManagerSchSubscriber::ESubscribePS,
            KPhoneStateChangeTimeoutSecs );
        return EFalse;
        }

    // Check synchronization state
    TInt syncState( 0 );
    RProperty::Get(
        KPSUidDataSynchronizationInternalKeys, KDataSyncStatus, syncState );
    if ( syncState > 0 )
        {
        INFO_LOG( "CFileManagerSchBackupTask::CheckPhoneStateL()-Synchronization on" )

        // Set subscriber to wait usb transfer to finish
        iSubscriber = CFileManagerSchSubscriber::NewL(
            *this,
            KPSUidDataSynchronizationInternalKeys,
            KDataSyncStatus,
            CFileManagerSchSubscriber::ESubscribePS,
            KPhoneStateChangeTimeoutSecs );
        return EFalse;
        }

    // Check backup/restore (e.g. PC Suite initiated) state
    TInt burState( 0 );
    RProperty::Get(
        KUidSystemCategory, KUidBackupRestoreKey, burState );

    const TBURPartType partType = static_cast< TBURPartType >
        ( burState & KBURPartTypeMask );
        
    if ( partType != EBURUnset && partType != EBURNormal )
        {
        INFO_LOG( "CFileManagerSchBackupTask::CheckPhoneStateL()-Backup/restore on" )

        // Set subscriber to wait backup or restore to finish
        iSubscriber = CFileManagerSchSubscriber::NewL(
            *this,
            KUidSystemCategory,
            KUidBackupRestoreKey,
            CFileManagerSchSubscriber::ESubscribePS,
            KPhoneStateChangeTimeoutSecs );
        return EFalse;
        }

    return ETrue;
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::StartL
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::StartL()
    {
    FUNC_LOG

    delete iSubscriber;
    iSubscriber = NULL;

    if ( !CheckBackupRequired() )
        {
        return;
        }
    if ( !CheckPhoneStateL() )
        {
        return;
        }

    // Set backup starting state
    iCenRep->Set(
        KFileManagerLastSchBackupStatus,
        EFileManagerSchBackupStatusStarting );

    // Set subscriber to watch backup start success
    iSubscriber = CFileManagerSchSubscriber::NewL(
        *this,
        KCRUidFileManagerSettings,
        KFileManagerLastSchBackupStatus,
        CFileManagerSchSubscriber::ESubscribeCR,
        KStartStateChangeTimeoutSecs );

    // Start file manager for backup and ensure that it starts properly
    StartFileManagerL();
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::Exit
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::Exit()
    {
    FUNC_LOG

    Cancel();
    CActiveScheduler::Stop();
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::Retry
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::Retry()
    {
    if ( iAttemptsLeft != 0 )
        {
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, KErrNone );
        SetActive();

        if ( iAttemptsLeft > 0 )
            {
            --iAttemptsLeft;
            }
        }
    else
        {
        Exit();
        }
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::StartFileManagerL
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::StartFileManagerL()
    {
    FUNC_LOG

    RWsSession wsSession;
    User::LeaveIfError( wsSession.Connect() );
    CleanupClosePushL( wsSession );
    // Backup cannot be done from embedded file manager.
    // Backup operation closes the app where file manager is started and 
    // the backup operation stops because file manager gets closed as well.
    TInt wgId( 0 );
    if ( FindStandaloneAppL( wsSession, KUidFileManager, wgId ) )
        {
        // Notify running standalone file manager to start backup
        HBufC8* param8 = HBufC8::NewLC( KSchBackupTaskName().Length() );
        TPtr8 paramPtr( param8->Des() );
        paramPtr.Copy( KSchBackupTaskName );
        wsSession.SendMessageToWindowGroup(
            wgId,
            TUid::Uid( KUidApaMessageSwitchOpenFileValue ),
            *param8 );
        CleanupStack::PopAndDestroy( param8 );
        }
    else
        {
        // Start standalone file manager for backup
        TApaAppInfo appInfo;
        RApaLsSession apaLsSession;
        User::LeaveIfError( apaLsSession.Connect() );
        CleanupClosePushL( apaLsSession );
        User::LeaveIfError( apaLsSession.GetAppInfo(
            appInfo, KUidFileManager ) );
        CApaCommandLine* apaCmdLine = CApaCommandLine::NewLC();
        apaCmdLine->SetExecutableNameL( appInfo.iFullName );
        apaCmdLine->SetCommandL( EApaCommandBackground );
        TThreadId fmThreadId;
        User::LeaveIfError( apaLsSession.StartApp(
            *apaCmdLine, fmThreadId ) );
        CleanupStack::PopAndDestroy( apaCmdLine );
        CleanupStack::PopAndDestroy( &apaLsSession );
        }
    CleanupStack::PopAndDestroy( &wsSession );
    }

// ---------------------------------------------------------------------------
// CFileManagerSchBackupTask::NotifyKeyChangeOrTimeoutL
// ---------------------------------------------------------------------------
//
void CFileManagerSchBackupTask::NotifyKeyChangeOrTimeoutL(
        const TUid& aCategory,
        const TUint aKey,
        const TBool aTimeout )
    {
    FUNC_LOG

    if ( aCategory == KCRUidFileManagerSettings &&
        aKey == KFileManagerLastSchBackupStatus &&
        !aTimeout )
        {
        // Backup was started, the task starter can be finished
        Exit();
        }
    else
        {
        // Backup was not started, try starting it again
        Retry();
        }
    }

// End of file