fotaapplication/fotaserver/FotaServer/src/fotadownload.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 21 Jun 2010 16:37:58 +0300
branchRCL_3
changeset 42 490439ac0bd4
parent 9 57a65a3a658c
child 58 4af31167ea77
permissions -rw-r--r--
Revision: 201023 Kit: 2010125

/*
* Copyright (c) 2005 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:   downloads upd pkg
*
*/



// INCLUDES
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <es_enum_internal.h>
#endif
#include <centralrepository.h>
#include <f32file.h>
#include <AknWaitDialog.h>
#include <fotaserver.rsg>
#include <eikprogi.h>
#include <eikenv.h>
#include <apgtask.h>
#include <apgwgnam.h>
#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <es_sock.h>
#else
#include <es_sock.h>
#include <es_sock_partner.h>
#endif
#include <es_enum.h>
#include <NSmlDMSync.rsg>	//OMA DM UI for reading resource
#include <bautils.h>
#include <StringLoader.h>
#include <DevManInternalCRKeys.h> //for reading san feature
#include <e32property.h>
#include "fotastorage.h"
#include "FotaSrvApp.h"
#include "fotadownload.h"
#include "fotaserverPrivatePSKeys.h"
#include "FotaNetworkRegStatus.h"
#include <startupdomainpskeys.h>	//globalrfsstates
#define __LEAVE_IF_ERROR(x) if(KErrNone!=x) {FLOG(_L("LEAVE in %s: %d"), __FILE__, __LINE__); User::Leave(x); }
#define __LEAVE(x) {FLOG(_L("LEAVE in %s: %d"), __FILE__, __LINE__); User::Leave(x); }


// --------------------------------------------------------------------------
// CFotaDownload::NewL 
// --------------------------------------------------------------------------
CFotaDownload* CFotaDownload::NewL (CFotaServer* aServer)
	{
	__ASSERT_ALWAYS( aServer, User::Panic(KFotaPanic, KErrArgument) );
	CFotaDownload* ao = new (ELeave) CFotaDownload();
	ao->iFotaServer = aServer;
	return ao;
	}


// --------------------------------------------------------------------------
// CFotaDownload::RunL
// Do operations started in HandleDmgrEvent
// --------------------------------------------------------------------------
void CFotaDownload::RunL()
	{
	FLOG(_L( "[FotaServer] CFotaDownload::RunL() >>"));
	CancelDownload( ETrue );
	CreateDownloadL();
	FLOG(_L( "[FotaServer] CFotaDownload::RunL() <<" ) );
	}


// --------------------------------------------------------------------------
// CFotaDownload::DoCancel()
// Cancel notifier request
// --------------------------------------------------------------------------
//
void CFotaDownload::DoCancel()
	{
	FLOG(_L("CFotaDownload::DoCancel() >>"));
	FLOG(_L("CFotaDownload::DoCancel() <<"));
	}


// --------------------------------------------------------------------------
// CFotaDownload::RunError(TInt aError)
// Handle active object run error.
// --------------------------------------------------------------------------
//
TInt CFotaDownload::RunError(TInt aError)
	{
	if(aError)
		{
		FLOG(_L(" CFotaDownload::RunError err %d"), aError );
		}
	return aError;
	}


// --------------------------------------------------------------------------
// CFotaDownload::CFotaDownload()
// --------------------------------------------------------------------------
//
CFotaDownload::CFotaDownload() : CActive(EPriorityNormal)
		, iUpdateAfterDownload (EFalse), iUrl( NULL ),
		iDownload (NULL),
		iDownloadedContentSize(0),
		iPreviousContentSize ( 0 ), iShowOMACDUI(EFalse), iShowDLPrgUI(EFalse),
		iDownloadResumable (EFalse),				
		iFMSEnabled (EFalse),
		iDownloadActive (EFalse),
		iFreshDL(ETrue),
		iUserInitiatedResume(EFalse),		
		iSanValue(KErrNotFound),
		iDownloadFinalized(EFalse)		
	{
	CActiveScheduler::Add( this ); 
	FLOG(_L("CFotaDownload::CFotaDownload()"));
	}


// --------------------------------------------------------------------------
// CFotaDownload::~CFotaDownload()
// --------------------------------------------------------------------------
//
CFotaDownload::~CFotaDownload()
	{
	FLOG(_L("CFotaDownload::~CFotaDownload() >>"));
	Cancel();
	
	//Sets download state inactive if accidently closed. This is anyhow taken care in FinalizeDownload in Server.
	SetDownloadActive(EFalse);
	CancelDownload( ETrue );
	if ( iUrl )
		{
		delete iUrl; iUrl=NULL;
		}
/*	if ( iNotifHandler ) Deleted at server
		{
		iNotifHandler->Cancel();
		delete iNotifHandler;        
		}*/
	if ( iDLProgressDlg )
		{
		delete iDLProgressDlg; iDLProgressDlg=NULL;
		}

	if (iDownloadMgr.Handle())
		iDownloadMgr.Close();
	//don't delete iFotaServer as it doesn't belong here.
	
	FLOG(_L("CFotaDownload::~CFotaDownload() <<"));
}


// --------------------------------------------------------------------------
// CFotaDownload::CancelDownload
// Cancel download
// --------------------------------------------------------------------------
//
void CFotaDownload::CancelDownload( const TBool aCancelProgressBar )
	{
	FLOG(_L("CFotaDownload::CancelDownload() >>"));
	
	if( iDownloadMgr.Handle() )
		{
		iDownloadMgr.Close();
		}

	if ( aCancelProgressBar  && iDLProgressDlg )
		{
		TRAPD(err, iDLProgressDlg->ProcessFinishedL() ) ;// deletes
		if(err); // remove compiler warning
		delete iDLProgressDlg;
		iDLProgressDlg = NULL;
		}
	FLOG(_L("CFotaDownload::CancelDownload() <<"));
	}

// --------------------------------------------------------------------------
// CFotaDownload::CreateDownloadL
// Create  download
// --------------------------------------------------------------------------
//
void CFotaDownload::CreateDownloadL()
	{
	FLOG(_L("CFotaDownload::CreateDownloadL() >>") );
	__ASSERT_ALWAYS( iDownloadMgr.Handle()==0, User::Leave(KErrAlreadyExists) );
	RHttpDownload*  d(NULL);
	iDLNeedsReset = EFalse;
	TBool       created;
	iDownloadMgr.ConnectL( TUid::Uid(KFotaServerUid) , *this, EFalse); 
	FLOG(_L("CFotaDownload::CreateDownloadL, Stage 1") );
	iDownloadMgr.DeleteAll();

	TRAPD(err, d = &iDownloadMgr.CreateDownloadL( *iUrl, created ) );
	RFs fs;	
	if(fs.Connect() == KErrNone)
	    {
	    RFile file;    
	    CleanupClosePushL( fs );
	    CleanupClosePushL( file );
	    err=fs.MkDir(KDDDirPath);
	    FLOG(_L("creating directory err as %d"),err);
	    err=fs.SetSessionPath(KDDDirPath);
	    FLOG(_L("setting session path err as %d"),err);
	    err=fs.ShareProtected();
	    FLOG(_L("ShareProtected err as %d"),err);
	    err = file.Replace(fs,KDDFilename, EFileWrite|EFileShareAny);	
	    FLOG(_L("creating rfile err as %d"),err);	
	    err = d->SetFileHandleAttribute(file);
	    FLOG(_L("setting dlmgr destfile attrib err as %d"),err);
	    CleanupStack::PopAndDestroy( &file );
	    CleanupStack::PopAndDestroy( &fs );
	    }	
	FLOG(_L("CFotaDownload::CreateDownloadL, Stage 2. err %d"),err);
	if ( err  == KErrArgument ) User::Leave( KErrNotFound );
	else if( err !=KErrNone)    User::Leave( err );

	if ( iDLState.iIapId > KErrNotFound )
		{
		FLOG(_L("   Using internet access point iapid: %d"), iDLState.iIapId);
		err = iDownloadMgr.SetIntAttribute( EDlMgrIap, iDLState.iIapId); // IAP id
		User::LeaveIfError( err );        
		//At this point the iIapId used in the SyncML Session is presumed working. Hence
		//the same is stored in database for use during download.
		FLOG(_L("Setting IAPID=%d is FotaState"),iDLState.iIapId);
		iFotaServer->iDatabase->OpenDBL();
		iFotaServer->iDatabase->SetStateL(iDLState,KNullDesC8, EFDBIapId );
		iFotaServer->iDatabase->CloseAndCommitDB();
		}
	FLOG(_L("CFotaDownload::CreateDownloadL, Stage 3") );
	User::LeaveIfError( d->SetIntAttribute(EDlAttrFotaPckgId ,iDLState.iPkgId) );
	FLOG(_L("CFotaDownload::CreateDownloadL, Stage 4") );
	User::LeaveIfError( d->SetBoolAttribute(EDlAttrNoContentTypeCheck,ETrue) );

	// If ui hidden or download restarting, do not show descriptor
	if ( !iShowOMACDUI || iRestartCounter > 0 )
		{
		FLOG(_L("setting DD to hidden"));
		User::LeaveIfError(iDownloadMgr.SetBoolAttribute( EDlMgrSilentMode,ETrue )) ;
		}
	//It's a fresh download
	iFreshDL = ETrue;

	// Start download 
	User::LeaveIfError(iDownloadMgr.StartAll()); 
	FLOG(_L("CFotaDownload::CreateDownloadL, Stage 5") );
	iDLProgress = EStarted;

	//This P&S Key is used to notify DM UI on any download event. key=0 for idle and key=1 for download
	err = RProperty::Set( TUid::Uid(KOmaDMAppUid),
			KFotaDMRefresh,
			ETrue );
	FLOG(_L("RProperty KFotaDMRefresh Set Etrue, err = %d"), err);

	SetDownloadActive(ETrue);

	User::LeaveIfError(err);
	FLOG(_L("[FotaServer]  CFotaDownload::CreateDownloadL <<"));
}

	// --------------------------------------------------------------------------
	// CFotaDownload::DownloadL
	// Start download of swupd package.
	// --------------------------------------------------------------------------
	//
void CFotaDownload::DownloadL(TDownloadIPCParams aParams,const TDesC8& aPkgURL
		,TBool aUpdateAfterDownload,const TInt aIapid,const TInt aRestartDownload)
	{
	FLOG(_L("[FotaServer]  CFotaDownload::DownloadL >> restart %d"),aRestartDownload);

	TInt err = RProperty::Define( TUid::Uid(KOmaDMAppUid),
			KFotaDMRefresh,
			RProperty::EInt,KReadPolicy,KWritePolicy);
	FLOG(_L("RProperty KFotaDMRefresh Define, err = %d"), err);        
	if (err != KErrAlreadyExists )
		{
		User::LeaveIfError(err);

		err = RProperty::Set( TUid::Uid(KOmaDMAppUid),
				KFotaDMRefresh,
				KErrNotFound );

		FLOG(_L("RProperty KFotaDMRefresh Set KErrNotFound, err = %d"), err);
		User::LeaveIfError(err);
		}

	if ( iUrl ) {delete iUrl; iUrl=NULL;}
	iUrl = aPkgURL.Alloc();
	iUpdateAfterDownload = aUpdateAfterDownload;
	iRestartCounter = aRestartDownload;

	iDLState        = aParams;
	FLOG(_L("CFotaDownload::DownloadL, Stage 1") );

	// Set state -------------------------------------------------------------
	iDLState.iState = RFotaEngineSession::EStartingDownload;

	iDLState.iResult = KErrNotFound;
	iDLState.iUpdateLtr = aUpdateAfterDownload;
	iFotaServer->iDatabase->OpenDBL();
	iFotaServer->iDatabase->SetStateL( iDLState, *iUrl,EFDBState|EFDBResult
			| EFDBProfileId|EFDBPkgUrl|EFDBPkgName|EFDBVersion|EFDBUpdateLtr);
	iFotaServer->iDatabase->CloseAndCommitDB();
	FLOG(_L("CFotaDownload::DownloadL, Stage 2, pkgid:%d"),iDLState.iPkgId);

	// 2. Get Iap Id to use for download. This would be set in iDLState.iIapId.
	SetIapToUseL(aParams, aIapid);

	// 3. Determine whether download should be visible or not
	// Autoaccepted profile?

	SetDownloadUiBehavior(ETrue);

	CancelDownload( ETrue );

	FLOG(_L("Setting SessionType=%d in FotaState"),iDLState.iSessionType);
	iFotaServer->iDatabase->OpenDBL();
	iFotaServer->iDatabase->SetStateL(iDLState,KNullDesC8, EFDBSessionType );
	iFotaServer->iDatabase->CloseAndCommitDB();
	FLOG(_L("CFotaDownload::DownloadL, Stage 3") );
	//Called to read the download variations in Fota (resume support & FMS)
	CheckDownloadVariations();

	//Create the download
	CreateDownloadL( );
	FLOG(_L("[FotaServer]  CFotaDownload::DownloadL <<"));
	}

// ---------------------------------------------------------------------------
// CFotaDownload::HandleDLProgressDialogExitL
// Handle canceling of download
// ---------------------------------------------------------------------------
TBool CFotaDownload::HandleDLProgressDialogExitL( TInt aButtonId ) 
	{
	FLOG(_L("CFotaDownload::HandleDLProgressDialogExitL %d, note = %d >>"),aButtonId, iDLProgressDlg->iNoteType);
	// Cancel clicked during download
	if ( aButtonId == KErrNotFound )
		{
		iRestartCounter = -1;
		FLOG(_L("[FotaServer]  CFotaDownload::HandleDLProgressDialogExitL Hiding UI"));
		iFotaServer->iParentApp->SetUIVisibleL ( EFalse, ETrue );
		iUpdateAfterDownload = EFalse;

		iDLState.iResult = RFotaEngineSession::EResUserCancelled;

		if (iDLProgressDlg->iNoteType == EConnectingNote)
			{
			iDLState.iState = RFotaEngineSession::EDownloadProgressingWithResume;

			TInt active (KErrNotFound);
			RProperty::Get( TUid::Uid(KFotaServerUid), KFotaDownloadActive, active );
			FLOG(_L("active = %d"),active);
			
			if (active) //Resume operation has just begun and download request is submitted to dlmgr. Hence need to suspend.
				{
				RunDownloadSuspendL(RFotaEngineSession::EResUserCancelled, ETrue);
				}
			else //Resume operation has just begun, but download request is not submitted to dlmgr
				{
				LaunchNotifierL( ESyncMLFwUpdOmaDLPostponed, EFalse, EFalse );
				iFotaServer->FinalizeDownloadL( iDLState );
				}
			}
		else if (iDLProgressDlg->iNoteType == EDownloadingNote)
			{
			if (iDownloadResumable)
				{
				//Resume is supported. Query user whether to postpone or cancel download.
				FLOG(_L("User pressed cancel. Resume is supported; hence pause download and query user if download has to be postponed or cancelled permanently."));
				RunDownloadSuspendL(RFotaEngineSession::EResUserCancelled);
				}
			else
				{
				//Resume is not supported. Download is cancelled
				FLOG(_L("User pressed cancel. Resume is not supported & hence download has to be cancelled"));
				RunDownloadCancelL(RFotaEngineSession::EResUserCancelled);
				}
			}
		}
	FLOG(_L("CFotaDownload::HandleDLProgressDialogExitL <<"));
	return ETrue;
	}


// --------------------------------------------------------------------------
// CFotaDownload::DoHandleDMgrEventL
// Handles download events. Updates package state accordingly
// --------------------------------------------------------------------------
void CFotaDownload::DoHandleDMgrEventL( RHttpDownload* aDownload
		, THttpDownloadEvent aEvent )
	{
	__ASSERT_ALWAYS( aDownload, User::Panic(KFotaPanic, KErrArgument) );
	TInt32                      sysErrorId( KErrNone );
	TInt32                      contentsize;
	TInt32                      downloadedsize;

	TInt32                      tmp;
	THttpDownloadMgrError       dlErrorId;
	iDownload = aDownload;
	// If DL is in final state (complete/fail), there's an error id available.
	User::LeaveIfError( aDownload->GetIntAttribute( EDlAttrGlobalErrorId
			,sysErrorId ) );
	User::LeaveIfError( aDownload->GetIntAttribute( EDlAttrDownloadedSize
			,downloadedsize ) );
	User::LeaveIfError( aDownload->GetIntAttribute( EDlAttrLength
			,contentsize ) );
	User::LeaveIfError( aDownload->GetIntAttribute( EDlAttrErrorId
			,tmp ) );
	dlErrorId = (THttpDownloadMgrError)tmp;


	// Update progress dlg progress
	if ( !iDLProgressDlg && iRestartCounter>0)
		{
		FLOG(_L("reshowing progress..."));
		iDLProgressDlg = new(ELeave) CFotaDLProgressDlg((CEikDialog** ) &iDLProgressDlg , EFalse, this, EDownloadingNote );
		iDLProgressDlg->PrepareLC( R_FOTASERVER_DL_PROGRESS_DIALOG );
		iDLProgressDlg->RunLD();
		}
	if (iDLProgressDlg)
		{
		CEikProgressInfo* progressInfo = iDLProgressDlg->GetProgressInfoL();
		__ASSERT_ALWAYS( progressInfo, User::Panic(KFotaPanic, KErrBadHandle) );
		if ( iPreviousContentSize!=contentsize )
			{
			iPreviousContentSize = contentsize;
			if ( contentsize > 0 )
				{
				progressInfo->SetFinalValue( contentsize );
				}
			}
		TInt incr = downloadedsize - iDownloadedContentSize;
		if (incr<=0) incr=0; //Protection
		progressInfo->IncrementAndDraw(incr);
		iDownloadedContentSize = downloadedsize;
		}
	FLOG(_L("CFotaDownload::HandleDMgrEventL() >>   DLstate:%d  ProgressSt:%d\
	globErr: %d DLError: %d (%d/%d)"),aEvent.iDownloadState
	,aEvent.iProgressState,sysErrorId,dlErrorId,downloadedsize,contentsize );

	if ( sysErrorId <= -25000)  { FLOG(_L("  error %d interpreted as http \
	error %d") , sysErrorId, sysErrorId + 25000 ); }

	switch ( aEvent.iDownloadState )
	{
	case EHttpDlCreated:		// 1
		{
		FLOG(_L("Download State: EHttpDlCreated"));
		}
		break;
	case EHttpDlInprogress:     // 2
		{
		FLOG(_L("Download State: EHttpDlProgress"));


		if (aEvent.iProgressState == EHttpProgCodDescriptorDownloaded)
			{
			if (iShowOMACDUI || iShowDLPrgUI)
				{
				iFotaServer->iParentApp->SetUIVisibleL ( ETrue, EFalse);
				}
			}

		// Is ECodLoadEnd optimized out?
		if ( aEvent.iProgressState == EHttpProgCodLoadEnd ) // 2503
			{
			TInt    err;
			err = aDownload->Start();  // PPAR-6FRHFY fixed
			if(err)
				{
				FLOG(_L(" ERROR when restarting DL %d"),err);
				User::Leave(err);
				}
			FLOG( _L("          DL restarted") );
			}

		// Should tell user to free disk space. But how do we know that disk space is about be exceeded?

		if ( iDLNeedsReset )
			{
			FLOG(_L("aDownload->Reset();"));
			iDLNeedsReset = EFalse;
			iStatus = KRequestPending;
			SetActive();
			TRequestStatus* status = &iStatus;
			User::RequestComplete( status, KErrNone );
			User::LeaveIfError( aDownload->Reset() );
			}

		// Body data of descriptor or payload pkg
		if ( aEvent.iProgressState == EHttpProgResponseBodyReceived && iDLProgress==EDescriptorDownloaded/*2500*/)
			{
			// Now pkg size can be retrieved. must check size.
			iDLState.iPkgSize = contentsize;
			FLOG(_L("Setting PkgSize=%d in FotaState"),contentsize);
			iFotaServer->iDatabase->OpenDBL();
			iFotaServer->iDatabase->SetStateL(iDLState,KNullDesC8, EFDBPkgSize );
			iFotaServer->iDatabase->CloseAndCommitDB();
			

			TInt contentsize2 = contentsize;
			
			TInt dlsize (KErrNone);
			TInt tlsize (KErrNone);

			TRAPD(err, iFotaServer->GetDownloadUpdatePackageSizeL(iDLState.iPkgId, dlsize,tlsize));
			if(err); // remove compiler warning
			contentsize2 -= dlsize;
			FLOG(_L("check pkg size = %d"),contentsize2 );

			CFotaStorage::TFreeSpace avail = iFotaServer->StoragePluginL()->IsPackageStoreSizeAvailableL(contentsize2);

			iDLProgress = ESizeChecked;

			if ( avail==CFotaStorage::EDoesntFitToFileSystem )
				{
				FLOG(_L("CFotaStorage::EDoesntFitToFileSystem"));
				if (iFreshDL)
					{
					if ( iShowDLPrgUI )
						{
						FLOG(_L("iDLNeedsReset = ETrue;"));
						iDLNeedsReset = ETrue;
						LaunchNotifierL( ESyncMLFwUpdOmaDLNotEnoughMemory, KErrDiskFull,contentsize2 );
						}
					else
						{
						iDLState.iResult = RFotaEngineSession::EResDLFailDueToDeviceOOM;
						iDLState.iState  = RFotaEngineSession::EDownloadFailed;
						iUpdateAfterDownload = EFalse;
						LaunchNotifierL( ESyncMLFwUpdErrorNote, KErrGeneral, contentsize2,ETrue );
						}
					}
				else //resuming download
					{
					FLOG(_L("Memory need in order to resume. Notify user..."));
					LaunchNotifierL( ESyncMLFwUpdOmaDLNotEnoughMemory, KErrDiskFull,contentsize2 );
					RunDownloadSuspendL(RFotaEngineSession::EResDLFailDueToDeviceOOM);
					}
					
				}
			}

		// OMA DD download completed , must hide progress
		if ( aEvent.iProgressState == EHttpProgContentTypeChanged ) // 2055
			{
			if ( iDLProgressDlg )
				{
				iDLProgressDlg->ProcessFinishedL(); // deletes itself
				delete iDLProgressDlg;
				iDLProgressDlg = NULL;
				}
			}
		// OMA DD accepted,show progress
		if ( aEvent.iProgressState == EHttpProgCodDescriptorAccepted ) // 2502

			{
			iDLProgress = EDescriptorDownloaded;
			if ( iShowDLPrgUI )
				{
				FLOG(_L("SHOW PROGRESS"));
				if ( iDLProgressDlg )
					{
					FLOG(_L("Removing Connecting progress note..."));
					iDLProgressDlg->ProcessFinishedL();
					delete iDLProgressDlg;
					iDLProgressDlg = NULL;
					}
				if (!iDLProgressDlg)
					{
					
					FLOG(_L("Creating iDLProgressDlg"));
					iDLProgressDlg = new(ELeave) CFotaDLProgressDlg((CEikDialog** ) &iDLProgressDlg , EFalse, this, EDownloadingNote );
					iDLProgressDlg->PrepareLC( R_FOTASERVER_DL_PROGRESS_DIALOG );
					iDLProgressDlg->RunLD();
					}
				CEikProgressInfo* progressInfo = iDLProgressDlg->GetProgressInfoL();
				progressInfo->SetFinalValue( 500 );
				iPreviousContentSize = -1;
				iDownloadedContentSize = 0;
				iFotaServer->iParentApp->SetUIVisibleL ( ETrue , EFalse );
				}
			if (iDownloadResumable)
				{
				FLOG(_L("Setting download as resumable"));
				iDLState.iState = RFotaEngineSession::EDownloadProgressingWithResume;
		    	iFotaServer->SetStartupReason(EFotaDownloadInterrupted);
				}
			else
				{
				FLOG(_L("Setting download as non resumable"));
				iDLState.iState = RFotaEngineSession::EDownloadProgressing;
				iFotaServer->SetStartupReason(EFotaPendingGenAlert);
				}
			iFotaServer->iDatabase->OpenDBL();
			iFotaServer->iDatabase->SetStateL(iDLState,KNullDesC8, EFDBState );
			iFotaServer->iDatabase->CloseAndCommitDB();


			if (iDLState.iIapId <= 0) //Read the IAP ID when not known, and set it into db.
				{
				TInt32 usedapid (KErrNotFound);
				TInt er = iDownloadMgr.GetIntAttribute( EDlMgrIap, usedapid);
				iDLState.iIapId = usedapid;
				FLOG(_L("Setting IAPID=%d is FotaState"),iDLState.iIapId);
				iFotaServer->iDatabase->OpenDBL();
				iFotaServer->iDatabase->SetStateL(iDLState,KNullDesC8, EFDBIapId );
				iFotaServer->iDatabase->CloseAndCommitDB();
				}
			}
		}
		break;
	case EHttpDlCompleted:      // 4
		{
		FLOG(_L("Download State: EHttpDlCompleted"));

		iRestartCounter = -1;
		if ( iDLProgressDlg )
			{
			iDLProgressDlg->ProcessFinishedL(); // deletes itself
			delete iDLProgressDlg;
			iDLProgressDlg = NULL;
			}
		iDLState.iState     = RFotaEngineSession::EDownloadComplete;

		if (iUpdateAfterDownload)
			iDLState.iResult = KErrNotFound;
		else
			iDLState.iResult    = RFotaEngineSession::EResSuccessful;
		iFotaServer->FinalizeDownloadL( iDLState );
		}
		break;
	case EHttpDlPaused: //Event thrown for any resumable download
	case EHttpDlFailed: //Event thrown for any non-resumable download or critical error on resumable download
		{
		
		if (aEvent.iProgressState != EHttpProgNone) //Accepting only events from COD
			return;

		if (aEvent.iDownloadState == EHttpDlPaused)
			{
			FLOG(_L("Download State: EHttpDlPaused"));
			if (iDownloadResumable)
				{
				iDLState.iState     = RFotaEngineSession::EDownloadProgressingWithResume;
				}
			else 
				{
				// iDownloadResumable remains 0 even for resumable download.
				iDLState.iState     = RFotaEngineSession::EDownloadFailed;
				}
			}
		else //aEvent.iDownloadState = EHttpDlFailed
			{
			FLOG(_L("Download State: EHttpDlFailed"));
			iDLState.iState     = RFotaEngineSession::EDownloadFailed;
			iDownloadResumable = EFalse;
			}
		//Remove the download progress bar
		if ( iDLProgressDlg && (iDLState.iResult != RFotaEngineSession::EResUserCancelled ))
			{
			FLOG(_L("Shd not come in EResUserCancelled"));
			iDLProgressDlg->ProcessFinishedL(); // deletes itself
			delete iDLProgressDlg;
			iDLProgressDlg = NULL;
			}
		// This is restarted download => decrement counter
		if ( iRestartCounter > 0 )
			{
			--iRestartCounter;
			if ( iRestartCounter <=0 ) iRestartCounter = -1;
			FLOG(_L("   iRestartCounter to %d"),iRestartCounter );
			}
		/*****************************/
		//Handling all errors now...//
		/****************************/
		TInt notifType (KErrNotFound);
		TInt notifParam (KErrNotFound);
		//Handling User Cancel of Download Descriptor
		if ( dlErrorId == EGeneral && (sysErrorId == KErrAbort || sysErrorId == KErrCancel ))
			{
			FLOG(_L("Reason: User cancelled download descriptor"));
			//LaunchNotifierL(ESyncMLFwUpdOmaDLCancelled, EFalse, EFalse);
			iRestartCounter = -1;
			iDLState.iResult = RFotaEngineSession::EResUserCancelled;
			notifType = ESyncMLFwUpdOmaDLCancelled;
			notifParam = KErrNone;
			}
		//Handling User Cancel
		else if ( iDLState.iResult == RFotaEngineSession::EResUserCancelled ) //This variable is set in RunDownloadCancelL or RunDownloadSuspendL
			{
			iRestartCounter = -1;
			//If initial pause is successful, query user if he wants to postpone or cancel permanently.
			iFotaServer->iDatabase->OpenDBL();
			iFotaServer->iDatabase->SetStateL(iDLState,KNullDesC8, EFDBState);
			iFotaServer->iDatabase->CloseAndCommitDB();

			if (iDownloadResumable)
				{
				if (!iSilentOpn)
					{
					FLOG(_L("Download has been paused successful. Query user if he wants to postpone or cancel permanently"));
					LaunchNotifierL(ESyncMLFwUpdOmaDLUserCancel, KErrNone, KErrNone);
					break;
					}
				else
					{
					notifType = ESyncMLFwUpdOmaDLPostponed;
					notifParam = KErrNone;
					}
				}
			else 
				{
				FLOG(_L("Error while initial pausing...%d Hence download has to be cancelled permanently!"));
				RunDownloadCancelL(RFotaEngineSession::EResUserCancelled);
        notifType = ESyncMLFwUpdOmaDLCancelled;
        notifParam = KErrNone;
				}
			}
		else if ( iDLState.iResult == RFotaEngineSession::EResDLFailDueToDeviceOOM )
			{
			FLOG(_L("Reason: Not enough memory to perform resume"));
			iRestartCounter = -1;

			if (iDownloadResumable)
				iDLState.iState = RFotaEngineSession::EDownloadProgressingWithResume;
			else
				iDLState.iState = RFotaEngineSession::EDownloadFailed;
			}
		//Handling user cancel IAP selection popup
		else if ( dlErrorId == EConnectionFailed && sysErrorId == KErrCancel)
			{
			FLOG(_L("Reason: User canceled IAP selection popup"));
			iDLState.iResult = RFotaEngineSession::EResUserCancelled;
			iRestartCounter = -1;

			notifType = ESyncMLFwUpdOmaDLPostponed;
			notifParam = KErrNone;
			}
		//Handling temproary network timeout. This may either try resume or restart based on download.
/*		else if ( dlErrorId == EGeneral && sysErrorId == KErrTimedOut )
			{
			FLOG(_L("Reason: Network timeout"));
			// No restart issued yet, this is 1st download attempt
			if ( iRestartCounter == 0 )
				{
				iRestartCounter = KFotaDownloadTimeoutRestartCount;
				iDLState.iState     = RFotaEngineSession::EIdle;
				FLOG(_L("Trying to restart download (iRestartCounter=%d)"),iRestartCounter );
				}
			
			}*/
		//Handling all Network interrupts
		else if ( (dlErrorId == EConnectionFailed && sysErrorId == KErrCommsLineFail)|| 
				  dlErrorId == ETransactionFailed || 
				  (dlErrorId == KErrCodWapConnectionDropped && sysErrorId == KErrGeneral) ||
				  (dlErrorId == EGeneral && sysErrorId == KErrTimedOut) ||
				  (dlErrorId == EConnectionFailed && sysErrorId == KErrGprsServicesNotAllowed ) ||
				  (dlErrorId == EConnectionFailed && sysErrorId == KErrGsmMMNetworkFailure ) ||
				  (dlErrorId == EConnectionFailed && sysErrorId == KErrWlanNetworkNotFound )
				  )
			{
			FLOG(_L("Reason: Network breakage"));
			iRestartCounter = -1;
			notifType = ESyncMLFwUpdErrorNote;
			if (iDownloadResumable)
				{
				notifParam = KErrCommsLineFail2;
				iDLState.iState = RFotaEngineSession::EDownloadProgressingWithResume;
				iDLState.iResult = RFotaEngineSession::EResDLFailDueToNWIssues;
				}
			else
				{
				notifParam = KErrCommsLineFail;
				iDLState.iState = RFotaEngineSession::EDownloadFailed;
				iDLState.iResult = RFotaEngineSession::EResDLFailDueToNWIssues;
				}
			}
		//Handling Out Of Memory interrupt
		else if ((dlErrorId == EGeneral && sysErrorId == KErrDiskFull ) || sysErrorId == KErrCodInsufficientSpace)
			{
			FLOG(_L("Reason: Disk full"));
			iRestartCounter = -1;
			notifType = KErrNotFound;
			notifParam = KErrNotFound; // don't show anything
			iDLState.iResult = RFotaEngineSession::EResDLFailDueToDeviceOOM;
			}
		//Handle unclassified (general) interrupts
		else
			{
			iRestartCounter = -1;

			
			RProperty prop;
			TInt val = KErrNone;
		
			TInt err = prop.Get(KPSUidStartup, KPSGlobalSystemState, val);
			if (err==KErrNone && val!=ESwStateShuttingDown)
				{
				notifType = ESyncMLFwUpdErrorNote;				
				}
			else
				{
				FLOG(_L("Phone is powering down..."));
				}

			if (iDownloadResumable)
				{
				notifParam = KErrGeneralResume;
				iDLState.iState = RFotaEngineSession::EDownloadProgressingWithResume;
				}
			else
				{
				notifParam = KErrGeneralNoResume;
				iDLState.iState = RFotaEngineSession::EDownloadFailed;
				}


        SetDLResultdlErrorId(dlErrorId ,sysErrorId  );
			

			}
		if ( iRestartCounter <= 0)
			{
			iUpdateAfterDownload = EFalse;
			SetDownloadActive(EFalse);
			if ( iDLState.iSessionType!= ESanSilent && notifType!=KErrNotFound )
				{
				if ( iShowDLPrgUI )
					LaunchNotifierL( (TSyncMLFwUpdNoteTypes)notifType, notifParam,0 );
				else
					LaunchNotifierL( (TSyncMLFwUpdNoteTypes)notifType, notifParam,0, ETrue);
				}
			FLOG(_L("Should  come here for nonpausable "));	
			iDownloadFinalized = ETrue;
			iFotaServer->FinalizeDownloadL( iDLState );
			}
		else
			{
			if (iDownloadResumable)
				{
				FLOG(_L("Resuming download..."));
				iDownload->Start();
				}
			else
				{
				FLOG(_L("Restarting download..."));
				iFotaServer->FinalizeDownloadL( iDLState );
				}
			}
		}
		break;

	case EHttpDlPausable:
		{
		FLOG(_L("Download State: EHttpDlPausable"));
		if (iDownloadResumable) //This is initially set by IsDownloadSuspendResumeSupported()
			{
			FLOG(_L("Download Suspend/Resume is supported!"));       				
			}
		else
			{
			FLOG(_L("Download Server support Suspend/Resume, but Fota doesn't!"));
			//retain the state iDownloadResumable = EOmaDLResumeNotSupported;
			}
		}
		break;

	case EHttpDlNonPausable:
		{
		FLOG(_L("Download State: EHttpDlNonPausable"));
		if (iDownloadResumable) //This is initially set by CheckDownloadVariations()
			{
			FLOG(_L("Download Server doesn't support Suspend/Resume, but Fota does!"));
			//Reset the state to not supported.
			iDownloadResumable = EFalse;
			}
		else
			{
			FLOG(_L("Download Server doesn't support Suspend/Resume, neither does Fota!"));
			}
		}
		break;
	case EHttpDlDeleting:	//13
		{
		FLOG(_L("Download State: EHttpDlDeleting"));
		}
		break;
	case EHttpDlDeleted:	//11
		{
		FLOG(_L("Download State: EHttpDlDeleted"));
		}
		break;
	default:
		{
		FLOG(_L("Default. No action performed for this Download State"));
		}
		break;
	}
	FLOG(_L("CFotaDownload::HandleDMgrEventL()  <<"));
	}



// --------------------------------------------------------------------------
// CFotaDownload::SetDLResultdlErrorId
// Sets the appropriate error
// --------------------------------------------------------------------------
//

void CFotaDownload::SetDLResultdlErrorId( THttpDownloadMgrError adlErrorId, TInt32 asysErrorId)
{
      if ( adlErrorId == EInternal)
				{
				FLOG(_L("Reason:   error EInternal"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( adlErrorId == EContentFileIntegrity)
				{
				FLOG(_L("Reason:   error EContentFileIntegrity"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( adlErrorId == EMMCRemoved)
				{
				FLOG(_L("Reason:   error EMMCRemoved,"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( adlErrorId == EBadUrl) 
				{
				FLOG(_L("Reason:   error EBadUrl"));
				iDLState.iResult = RFotaEngineSession::EResMalformedOrBadURL;
				}
			else if ( adlErrorId == EHttpUnhandled)
				{
				FLOG(_L("Reason:   error EHttpUnhandled, check global error id!"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( adlErrorId == EHttpAuthenticationFailed)
				{
				FLOG(_L("Reason:   error EHttpAuthenticationFailed"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( adlErrorId == EObjectNotFound)
				{
				FLOG(_L("Reason:   error EObjectNotFound"));
				iDLState.iResult = RFotaEngineSession::EResAlternateDLServerUnavailable;
				}
			else if ( adlErrorId == EPartialContentModified)
				{
				FLOG(_L("Reason:   error EPartialContentModified"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( adlErrorId == EContentExpired)
				{
				FLOG(_L("Reason:   error EContentExpired"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( adlErrorId == EHttpRestartFailed)
				{
				FLOG(_L("Reason:   error EHttpRestartFailed"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}
			else if ( asysErrorId == KErrCodInvalidDescriptor )
				{
				FLOG(_L("Reason:   error KErrCodInvalidDescriptor"));
				iDLState.iResult  = RFotaEngineSession::EResMalformedOrBadURL;
				}
			else
				{
				FLOG(_L("Reason: unknown, check dlError!"));
				iDLState.iResult = RFotaEngineSession::EResUndefinedError;
				}

}

// --------------------------------------------------------------------------
// CFotaDownload::HandleDMgrEventL
// --------------------------------------------------------------------------
//
void CFotaDownload::HandleDMgrEventL( RHttpDownload& aDownload
		, THttpDownloadEvent aEvent )
	{   
	DoHandleDMgrEventL(&aDownload,aEvent);
	}


// --------------------------------------------------------------------------
// CFotaDownload::LaunchNotifierL
// Launches notifier. This method is also used to finalize erronous DL
// --------------------------------------------------------------------------
//
void CFotaDownload::LaunchNotifierL( const TSyncMLFwUpdNoteTypes aNotetype
		,const TInt aIntParam
		,const TInt aMemoryNeeded
		,TBool aFinishOnly )
	{
	if ( iNotifHandler ) iNotifHandler->Cancel();
	else				 iNotifHandler = CFotaDownloadNotifHandler::NewL(this);
	iNotifHandler->LaunchNotifierL( aNotetype,aIntParam,aMemoryNeeded
			,aFinishOnly );
	}

// --------------------------------------------------------------------------
// CFotaDownload::CheckDownloadVariations
// Reads download variations - fota suspend & resume bahavior & FMS from cenrep keys
// --------------------------------------------------------------------------
//
void CFotaDownload::CheckDownloadVariations()
	{
	FLOG(_L("CFotaDownload::CheckDownloadVariations >>"));

	CRepository* centrep( NULL);
	TRAPD(err, centrep = CRepository::NewL( KCRUidFotaServer ) );
	if (err) FLOG(_L("Error reading FotaServer cenrep... %d"),err);
	TInt supported(KErrNone);
	if (centrep ) 
		{
		err = centrep->Get( KSuspendResumeFeatureSupported, supported );
		if (err) FLOG(_L("Error reading cenrep key... %d"),err);
		iDownloadResumable = (supported==1)? ETrue:EFalse;

		supported = KErrNone;
		centrep->Get( KFotaMonitoryServiceEnabled, supported );
		if (err) FLOG(_L("Error reading cenrep key... %d"),err);
		iFMSEnabled = (supported > 0)? ETrue:EFalse;

		delete centrep;
		centrep = NULL;
		}

	FLOG(_L("Susp&Resume feature supported = %d, FMS feature supported = %d"),iDownloadResumable,iFMSEnabled);
	FLOG(_L("CFotaDownload::CheckDownloadVariations <<"));
	}

// --------------------------------------------------------------------------
// CFotaDownload::RunDownloadCancelL
// Starts to cancel the download operation
// --------------------------------------------------------------------------
//
void CFotaDownload::RunDownloadCancelL(const TInt aReason, TBool aSilent)
	{
	FLOG(_L("CFotaDownload::RunDownloadCancelL, reason = %d, silent = %d >>"), aReason, aSilent);

	iDLState.iState     = RFotaEngineSession::EDownloadFailed;
	iDLState.iResult    = aReason;
	iSilentOpn = aSilent;
	
	iRestartCounter = -1;
	iUpdateAfterDownload = EFalse;
	
	if (!iDownload)
		{
		//iDownload is null when user cancels the download permanently when prompted to resume.
		//hence retrieve the download object first 
		iDownload = RetrieveDownloadL();
		}
	TInt err = iDownload->Delete(); //or Cancel or Reset?
	FLOG(_L("Error = %d"),err);
	
	if(iDownloadFinalized == EFalse)
	{
	iFotaServer->FinalizeDownloadL( iDLState );
	FLOG(_L("Should not come here fro nopausable "));
	if (aReason == RFotaEngineSession::EResUserCancelled)
		LaunchNotifierL(ESyncMLFwUpdOmaDLCancelled, EFalse, EFalse);
	else if (aReason == RFotaEngineSession::EResUndefinedError)
		LaunchNotifierL(ESyncMLFwUpdErrorNote, KErrGeneralNoResume, EFalse );
  }
	FLOG(_L("CFotaDownload::RunDownloadCancelL <<"));
	}

// --------------------------------------------------------------------------
// CFotaDownload::RunDownloadSuspendL
// Starts to suspend the download operation
// --------------------------------------------------------------------------
//
void CFotaDownload::RunDownloadSuspendL(const TInt aReason, TBool aSilent)
	{
	FLOG(_L("CFotaDownload::RunDownloadSuspendL, reason = %d, silent = %d >>"), aReason, aSilent);

	iDLState.iState     = RFotaEngineSession::EDownloadProgressingWithResume;
	iDLState.iResult    = aReason;
	iSilentOpn = aSilent;
	//First pause download, and later ask for user action.
	TInt err = iDownload->Pause();

	if (err)
	{
	//initial pausing becomes a problem.
	FLOG(_L("Error while initial pausing...%d Hence download has to be cancelled permanently!"),err);
	RunDownloadCancelL(aReason);
	}

	FLOG(_L("CFotaDownload::RunDownloadSuspendL <<"));
	}

// --------------------------------------------------------------------------
// CFotaDownload::TryResumeDownloadL
// Tries to resume the download operation
// --------------------------------------------------------------------------
//
void CFotaDownload::TryResumeDownloadL(TBool aUserInitiated)
	{
	FLOG(_L("CFotaDownload::TryResumeDownloadL >>"));

	iUserInitiatedResume = aUserInitiated;
	TInt err = RProperty::Define( TUid::Uid(KOmaDMAppUid),
			KFotaDMRefresh,
			RProperty::EInt,KReadPolicy,KWritePolicy);
	FLOG(_L("RProperty KFotaDMRefresh Define, err = %d"), err);        
	if (err != KErrAlreadyExists )
		{
		User::LeaveIfError(err);
		}
	//This P&S Key is used to notify DM UI on any download event. key=0 for idle and key=1 for download
	err = RProperty::Set( TUid::Uid(KOmaDMAppUid),
			KFotaDMRefresh,
			ETrue );
	FLOG(_L("RProperty KFotaDMRefresh Set ETrue, err = %d"), err);    

	//Called to read the download variations in Fota (resume support & FMS)
	CheckDownloadVariations();	
	if (IsFMSEnabled() && iUserInitiatedResume)
		iFotaServer->CancelFmsL();

	//Query based on the type of DM session used earlier.
	if (iUserInitiatedResume || iDLState.iSessionType != ESanSilent)
		{
		//Query user for resume
		FLOG(_L("Quering user for resume..."));
		if (iFotaServer->iNotifHandler)
			{
			iFotaServer->iNotifHandler->Cancel();
			delete iFotaServer->iNotifHandler;
			iFotaServer->iNotifHandler = NULL;
			}
		iNotifHandler = CFotaDownloadNotifHandler::NewL(this);

		iNotifHandler->LaunchNotifierL(ESyncMLFwUpdOmaDLResume, EFalse, EFalse);
		}
	else //Only FMS initiated Silent Session download
		{
		//Resume directly
		FLOG(_L("Resuming automatically..."));
		ResumeDownloadL();
		}
	FLOG(_L("CFotaDownload::TryResumeDownloadL <<"));
	}

// --------------------------------------------------------------------------
// CFotaDownload::ResumeDownloadL
// Resume the download operation
// --------------------------------------------------------------------------
//
void CFotaDownload::ResumeDownloadL()
	{
	FLOG(_L("CFotaDownload::ResumeDownloadL >>"));
	TBool toresetdl (EFalse);
	TBool downloadiapvalid (ETrue);
	//Find the download ui behavior from fota cenrep
	TInt behavior(KErrNotFound);
	CRepository* centrep = NULL;
	TRAPD(err, centrep = CRepository::NewL( KCRUidFotaServer ) );
	if (( centrep ) && ( err == KErrNone))
	    {
	    centrep->Get( KSilentOmaDlUIBehavior, behavior );
	    delete centrep;
	    }
	centrep = NULL;

	if (iUserInitiatedResume || 
	        (behavior == EOmacdOffdlprgOn || behavior == EOmacdOndlprgOn))
		{
		FLOG(_L("Showing Connecting progress note..."));
		iFotaServer->iParentApp->SetUIVisibleL ( ETrue , EFalse );
		
		if ( !iDLProgressDlg )
			{
			iDLProgressDlg = new(ELeave) CFotaDLProgressDlg((CEikDialog** ) &iDLProgressDlg , EFalse, this, EConnectingNote );
			iDLProgressDlg->PrepareLC( R_CONNECTION_NOTE );
			}
		// Load the resource files
	    TInt err = KErrNone;
	       
	    // Localize the file name, and load the SCP resources
	    TFileName resFile;
	    resFile.Copy( KDriveZ );
	    resFile.Append( KSCPResourceFilename );
    	    
	    BaflUtils::NearestLanguageFile( CCoeEnv::Static()->FsSession(), resFile );    

	    TInt Res1(KErrNone);
	    TRAP( err, Res1 =CCoeEnv::Static()->AddResourceFileL( resFile ) );        

	    HBufC* buf = StringLoader::LoadLC(R_SYNCSTATUS_SYNC_CONN);
	
	    if( Res1 )
	    	{
	        iFotaServer->GetEikEnv()->DeleteResourceFile( Res1 );
	    	}
	    FLOG(_L("Reading txt as: %S"), &buf->Des());
		iDLProgressDlg->SetTextL(buf->Des());
		CleanupStack::PopAndDestroy(buf);
	
		iDLProgressDlg->RunLD();
		}
	FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 1"));
	
	iDownload = RetrieveDownloadL();
	if (iDownload)
		{
		FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 2: Successfully retrieved download object >>"));

		SetIapToUseL(iDLState, iDLState.iIapId);

		FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 3: Using iapid %d for resume..."), iDLState.iIapId);
		downloadiapvalid = iFotaServer->CheckIapExistsL(iDLState.iIapId);
		if (iDLState.iIapId > 0 && downloadiapvalid)
			{
			if (!iMonitor)
				{
				iMonitor = CFotaNetworkRegStatus::NewL (iFotaServer);
				}
			TBool val = iMonitor->IsConnectionPossibleL(iDLState.iIapId);
			FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 4"));
			delete iMonitor; iMonitor = NULL;
			
#if defined(__WINS__)
			val =ETrue;
#endif
			if (!val)
				{
				FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 5.1: Disallowing resume operation as connection not possible"));
				
				if ( !iShowDLPrgUI && iDLProgressDlg )
					{
					FLOG(_L("Removing Connecting progress note..."));

					iDLProgressDlg->ProcessFinishedL();
					delete iDLProgressDlg;
					iDLProgressDlg = NULL;
					}
				if (iUserInitiatedResume || iDLState.iSessionType!=ESanSilent)
					LaunchNotifierL(ESyncMLFwUpdErrorNote, KErrCommsLineFail2,0);
				iDLState.iState = RFotaEngineSession::EDownloadProgressingWithResume;
				iDLState.iResult = RFotaEngineSession::EResDLFailDueToNWIssues;
				iUpdateAfterDownload = EFalse;
				iFotaServer->FinalizeDownloadL(iDLState);
				return;
				}
			}

		if (iDLState.iIapId == KErrNotFound || !downloadiapvalid )
		    {
		    iDLState.iIapId = KErrNotFound;
			User::LeaveIfError( iDownloadMgr.SetIntAttribute( EDlMgrIap, 0)); // Download mgr interprets 0 for Always Ask
		    }
		else
			User::LeaveIfError( iDownloadMgr.SetIntAttribute( EDlMgrIap, iDLState.iIapId)); // IAP id

		FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 5.2"));
		SetDownloadUiBehavior(EFalse);		

		if ( !iShowDLPrgUI && iDLProgressDlg )
			{
			FLOG(_L("Removing Connecting progress note..."));

			iDLProgressDlg->ProcessFinishedL();
			delete iDLProgressDlg;
			iDLProgressDlg = NULL;
			}
		TInt dlsize, tlsize;
		FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 6"));
		iFotaServer->GetDownloadUpdatePackageSizeL(iDLState.iPkgId, dlsize,tlsize);
		iDownloadedContentSize = dlsize; //for progress bar update only
		iUpdateAfterDownload = iDLState.iUpdateLtr; //should update after reboot?
		iRestartCounter = 0;
		
		//Set right states in fota db
		iDLState.iState = RFotaEngineSession::EDownloadProgressingWithResume;
		iDLState.iResult = KErrNotFound;
		
		iFotaServer->iDatabase->OpenDBL();
		iFotaServer->iDatabase->SetStateL( iDLState, KNullDesC8, EFDBState|EFDBResult);
		iFotaServer->iDatabase->CloseAndCommitDB();
		iFreshDL = EFalse;
		FLOG(_L("CFotaDownload::ResumeDownloadL, Stage 6: Starting to resume download now..."));
		TInt err = iDownload->Start();
		if (err == KErrNone)
			{
			//Set the P&S Key to active...
			FLOG(_L("Resume operation is success!"));
			SetDownloadActive(ETrue);
			}
		else
			{
			FLOG(_L("An error occured during resume, err = %d"),err);
			toresetdl = ETrue;
			}
		}
	else
		{
		FLOG(_L("Failed to get the paused download object"));
		if ( iDLProgressDlg )
			{
			FLOG(_L("Removing Connecting progress note..."));
			iDLProgressDlg->ProcessFinishedL(); // deletes itself
			delete iDLProgressDlg;
			iDLProgressDlg = NULL;
			}
		toresetdl = ETrue;
		}
      ReSetDownloadL(	toresetdl);
	
	FLOG(_L("CFotaDownload::ResumeDownloadL <<"));
	}
// --------------------------------------------------------------------------
// CFotaDownload::ReSetDownloadL
// Sets the download state to failed
// --------------------------------------------------------------------------
//
void CFotaDownload::ReSetDownloadL(TBool atoresetdl)
{
if (atoresetdl)
		{
		FLOG(_L("Resetting fota download !!!"));
		if (iUserInitiatedResume || iDLState.iSessionType!=ESanSilent)
			LaunchNotifierL(ESyncMLFwUpdErrorNote, KErrGeneralNoResume,0);
		iDLState.iState = RFotaEngineSession::EDownloadFailed;
		iDLState.iResult = RFotaEngineSession::EResUndefinedError;
		iUpdateAfterDownload = EFalse;
		iFotaServer->FinalizeDownloadL(iDLState);
		}
}



// --------------------------------------------------------------------------
// CFotaDownload::IsFMSEnabled
// Returns FMS enabled state
// --------------------------------------------------------------------------
//
TBool CFotaDownload::IsFMSEnabled()
	{
	FLOG(_L("CFotaDownload::IsFMSEnabled, iFMSEnabled = %d <<"), iFMSEnabled);
	return iFMSEnabled;
	}

// --------------------------------------------------------------------------
// CFotaDownload::IsDownloadResumable
// Returns whether the download is resumable or not.
// --------------------------------------------------------------------------
//
TBool CFotaDownload::IsDownloadResumable()
	{
	FLOG(_L("CFotaDownload::IsDownloadResumable, iDownloadResumable = %d <<"), iDownloadResumable);
	return iDownloadResumable;
	}

// --------------------------------------------------------------------------
// CFotaDownload::SetIapToUseL
// Sets the IAP ID to use. This menthod is used in fresh and resume download.
// --------------------------------------------------------------------------
//
void CFotaDownload::SetIapToUseL(TPackageState aParams, const TInt aIapid)
	{
	FLOG(_L("CFotaDownload::SetIapToUseL >>"));

	RSyncMLSession sml;
	TInt profIapid( KErrNotFound );
	TInt sockIapid( KErrNotFound );
	TSmlServerAlertedAction saa(ESmlConfirmSync);

	CleanupClosePushL( sml );
	sml.OpenL();
	iFotaServer->GetProfileDataL(&sml,aParams.iProfileId, profIapid, saa
			,iIsjobStartedFromUI, iSanValue );
	CleanupStack::PopAndDestroy( &sml );

	// 2/3 GET IAP FROM ESOCK ----------------------------------------------
	// resolve which accespoint is used for current DM session
	if ( (profIapid == KErrNotFound || profIapid == KErrGeneral)  
			&& aIapid==KErrNotFound)
		{
		RSocketServ serv;
		CleanupClosePushL( serv );
		User::LeaveIfError( serv.Connect() );

		RConnection conn;
		CleanupClosePushL( conn );
		User::LeaveIfError( conn.Open( serv ) );

		TUint count( 0 );
		User::LeaveIfError( conn.EnumerateConnections ( count ) );
		// enumerate connections
		for( TUint idx=1; idx<=count; ++idx )
			{
			TConnectionInfo connectionInfo;
			TConnectionInfoBuf connInfo( connectionInfo );

			TInt err = conn.GetConnectionInfo( idx, connInfo ); // iapid
			if( err != KErrNone )
				{
				CleanupStack::PopAndDestroy( 2 ); // conn, serv
				User::Leave( err );
				}
			// enumerate connectionclients
			TConnectionEnumArg	conArg;
			conArg.iIndex = idx;
			TConnEnumArgBuf conArgBuf(conArg);
			err=conn.Control(KCOLConnection,KCoEnumerateConnectionClients
					,conArgBuf);
			if( err != KErrNone )
				{
				CleanupStack::PopAndDestroy( 2 ); // conn, serv
				User::Leave( err );
				}
			TInt cliCount = conArgBuf().iCount;
			for ( TUint j=1; j<=cliCount ;++j )
				{
				TConnectionGetClientInfoArg conCliInfo;
				conCliInfo.iIndex = j;
				TConnGetClientInfoArgBuf conCliInfoBuf(conCliInfo);
				err=conn.Control(KCOLConnection, KCoGetConnectionClientInfo
						, conCliInfoBuf);

				if( err != KErrNone )
					{
					CleanupStack::PopAndDestroy( 2 ); // conn, serv
					User::Leave( err );
					}				
				TConnectionClientInfo conCliInf = conCliInfoBuf().iClientInfo;
				TUid uid = conCliInf.iUid;
				if ( uid == TUid::Uid(KSosServerUid) )
					{
					sockIapid = connInfo().iIapId;
					FLOG(_L("[FotaServer]  IAP found %x"),sockIapid);
					}

				FLOG(_L("[FotaServer]  CFotaDownload::DownloadL uid %x")
						,uid.iUid);
				}
			}
		CleanupStack::PopAndDestroy( 2 ); // conn, serv		
		}
	TInt newIapid( KErrNotFound );
	if ( sockIapid!=KErrNotFound  ) newIapid = sockIapid;
	if ( profIapid!=KErrNotFound && profIapid != KErrGeneral ) newIapid = profIapid;
	if ( aIapid   !=KErrNotFound ) newIapid = aIapid;

	//Do some intelligent work during resume
	/* Some rules..
	 * 1. If IAP is always ask in DM profile, use the earlier set during FMS trigger
	 * 2. If IAP is always ask in DM profile, query user for IAP during user trigger
	 * 3. If IAP has changed in DM profile after suspend, use the newer one during resume
	 * 4. 
	 */
	TInt active (KErrNotFound);
	RProperty::Get(TUid::Uid(KFotaServerUid), KFotaDownloadActive, active );
	FLOG(_L("active = %d"),active);
	if (active==EFalse && iDLState.iState == RFotaEngineSession::EDownloadProgressingWithResume)
		{
		//Actual resume only
		if (!iUserInitiatedResume && (profIapid == KErrNotFound || profIapid == KErrGeneral  ) )
			{
			//FMS triggered resume, apply Rule 1
			newIapid = iDLState.iIapId;
			}
		else if (profIapid == KErrNotFound || profIapid == KErrGeneral )
			{
			//User triggered resume, apply Rule 2
			newIapid = KErrNotFound;
			}
		else if (profIapid != iDLState.iIapId && profIapid > KErrNone)
			{
			//IAP has changed in DM profile, apply Rule 3
			newIapid = profIapid;
			}
		}
	iDLState.iIapId = newIapid;


	FLOG(_L("CFotaDownload::SetIapToUseL, iap = %d <<"), iDLState.iIapId);
	}

// --------------------------------------------------------------------------
// CFotaDownload::SetDownloadUiBehavior
// Sets Download UI behavior. ex: DD display and Progress note
// --------------------------------------------------------------------------
//
void CFotaDownload::SetDownloadUiBehavior(TBool aFreshDL)
	{
	FLOG(_L("CFotaDownload::SetDownloadUiBehavior, aFreshDL = %d >>"),aFreshDL);

	if (aFreshDL) //Fresh download
		{
		iDLState.iSessionType = iSanValue;
		}
	else //resuming download
		{
		iSanValue = iDLState.iSessionType;
		}

	if ( !iIsjobStartedFromUI &&  iRestartCounter==0 ) //iRestartCounter to ensure that the UI behavior is read only once.
		{
		TInt behavior(KErrNotFound);
		TInt sansupported(KErrNone);

		//Find whether SAN is supported or not
	    CRepository* centrep = NULL;

	    TRAPD( err, centrep = CRepository::NewL( KCRUidDeviceManagementInternalKeys) );    
	    if( centrep ) centrep->Get( KDevManSANUIBitVariation, sansupported );
	    delete centrep; centrep = NULL;
	    FLOG(_L("...1..."));
	    if (sansupported != 1) sansupported = 0;
	    
		//Find the download ui behavior from fota cenrep
		TRAP(err, centrep = CRepository::NewL( KCRUidFotaServer ) );
		if ( centrep ) 	centrep->Get( KSilentOmaDlUIBehavior, behavior );
		delete centrep; centrep = NULL;

		FLOG(_L("Values are... SAN enabled: %d, session type: %d, downloadbehavior: %d"),sansupported, iDLState.iSessionType,behavior);

		if (sansupported) //SAN is supported
			{
				
			DetermineUISANON(behavior)	;
			
			}
		else //SAN not supported
			{
				DetermineUISANOFF(behavior);
		
			}
		}
	else// if (iRestartCounter==0) //Started from DM UI, but not retry
		{
		iShowOMACDUI = ETrue;
		iShowDLPrgUI = ETrue;
		if (aFreshDL)
			iDLState.iSessionType = KErrNotFound;
		}

TInt value (EFotaUpdateDM);
TInt err = RProperty::Get( KPSUidNSmlDMSyncApp, KNSmlCurrentFotaUpdateAppName, value );
if (!err && ((value == EFotaUpdateNSC) || (value == EFotaUpdateNSCBg)))
{
			iShowOMACDUI = EFalse;		
			iShowDLPrgUI = ETrue;
			FLOG(_L("CFotaDownload::DownloadL UI will not be shown!"));
}
	FLOG(_L("UI Behavior: OMA DD Display = %d, Download Progress = %d"),iShowOMACDUI,iShowDLPrgUI);

	FLOG(_L("CFotaDownload::SetDownloadUiBehavior <<"));
	}


// --------------------------------------------------------------------------
// CFotaDownload::DetermineUISANON
// Determine UI when SAN is ON
// --------------------------------------------------------------------------
//
void CFotaDownload::DetermineUISANON(TInt aBehavior)
{
				switch (aBehavior)
					{
					case EOmacdOffdlprgOff: //0
						{
						iShowOMACDUI = EFalse;
						iShowDLPrgUI = EFalse;
						}
						break;
					case EOmacdOffdlprgOn: //1
						{
						iShowOMACDUI = EFalse;
						iShowDLPrgUI = ETrue;
						}
						break;
					case EOmacdOndlprgOff: //2
						{
						iShowOMACDUI = ETrue;
						iShowDLPrgUI = EFalse;
						}
						break;
					case EOmacdOndlprgOn: //3
						{
						iShowOMACDUI = ETrue;
						iShowDLPrgUI = ETrue;
						}
						break;
					default: //includes EChooseFromSan
						{
						if(iSanValue == ESanSilent)
							{
							iShowOMACDUI = EFalse;
							iShowDLPrgUI = EFalse;
							}
						else if (iSanValue == ESanInformative)
							{
							iShowOMACDUI = EFalse;
							iShowDLPrgUI = ETrue;
							}
						else //includes ESanInteractive, ESanNotSpecified
							{
							iShowOMACDUI = ETrue;
							iShowDLPrgUI = ETrue;
							}
						}
						break;
					}
	
	
}

// --------------------------------------------------------------------------
// CFotaDownload::DetermineUISANOFF
// Determine UI when SAN is OFF
// --------------------------------------------------------------------------
//

void CFotaDownload::DetermineUISANOFF(TInt aBehavior)
{
			if (iSanValue==EAcceptedYes) //Accepted is Yes in Profile
				{
				switch (aBehavior)
					{
					case EOmacdOffdlprgOff: //0
						{
						iShowOMACDUI = EFalse;
						iShowDLPrgUI = EFalse;
						}
						break;
					case EOmacdOffdlprgOn: //1
						{
						iShowOMACDUI = EFalse;
						iShowDLPrgUI = ETrue;
						}
						break;
					case EOmacdOndlprgOff: //2
						{
						iShowOMACDUI = ETrue;
						iShowDLPrgUI = EFalse;
						}
						break;
					default: //includes EOmacdOndlprgOn
						{
						iShowOMACDUI = ETrue;
						iShowDLPrgUI = ETrue;
						}
						break;
					}
				}
			else // includes iSanValue = EAcceptedNo (Accepted is No in profile)
				{
				iShowOMACDUI = ETrue;
				iShowDLPrgUI = ETrue;
				}
}







// --------------------------------------------------------------------------
// CFotaDownload::RetrieveDownloadL
// Retrieves the RHttpDownload object from download manager during resume
// --------------------------------------------------------------------------
//
RHttpDownload* CFotaDownload::RetrieveDownloadL()
	{
	FLOG(_L("CFotaDownload::RetrieveDownloadL >>"));
	//Retrieve RHttpDownload object for the suspended download from Download Mgr.
	if (!iDownloadMgr.Handle())
		iDownloadMgr.ConnectL( TUid::Uid(KFotaServerUid) , *this, EFalse);
	const CDownloadArray& downloads = iDownloadMgr.CurrentDownloads();
	
	TBuf8<KMaxPath> url8;
	TInt32 val (KErrNone);
	
	RHttpDownload* aDownload (NULL);
	for (TInt i = 0; i < downloads.Count(); i++ )
		{
		User::LeaveIfError( downloads[i]->GetStringAttribute( EDlAttrCurrentUrl, url8 ));
		User::LeaveIfError( downloads[i]->GetIntAttribute( EDlAttrFotaPckgId, val));
	
		FLOG(_L("Current download(s) as per download mgr: %d, url = %S, pkgid = %d"), i+1, &url8, val);
	
		if (iDLState.iPkgId ==  val)
			{
			FLOG(_L("Successfully found the paused download object"));
			aDownload = downloads[i];
			if ( iUrl ) {delete iUrl; iUrl=NULL;}
			iUrl = url8.Alloc();
	
			}
		}
	FLOG(_L("CFotaDownload::RetrieveDownloadL <<"));
	return aDownload;
	}

// --------------------------------------------------------------------------
// CFotaDownload::SetDownloadActive
// Sets the download activity state P&S key
// --------------------------------------------------------------------------
//
void CFotaDownload::SetDownloadActive(TBool aValue)
	{
	FLOG(_L("CFotaDownload::SetDownloadActive, aValue = %d"),aValue);
	iDownloadActive = aValue;
	TBool val (EFalse);
	TInt err = RProperty::Get(TUid::Uid(KFotaServerUid), KFotaDownloadActive, val );

	if (err == KErrNone && val != aValue)
		{
		err = RProperty::Set(TUid::Uid(KFotaServerUid), KFotaDownloadActive, aValue );
		FLOG(_L("RProperty KFotaDownloadActive Set %d, err = %d"), aValue, err);
		}
	
	FLOG(_L("CFotaDownload::SetDownloadActive <<"));
	}

// --------------------------------------------------------------------------
// IsDownloadActive
// Returns the activeness of the download
// --------------------------------------------------------------------------
//

TBool CFotaDownload::IsDownloadActive()
	{
	FLOG(_L("CFotaDownload::IsDownloadActive, value = %d"),iDownloadActive);
	return iDownloadActive;
	}


// --------------------------------------------------------------------------
// CFotaDownloadNotifHandler::NewL 
// --------------------------------------------------------------------------
//
CFotaDownloadNotifHandler* CFotaDownloadNotifHandler::NewL (CFotaDownload* aDownload)
	{
	FLOG(_L("CFotaDownloadNotifHandler::NewL"));
	__ASSERT_ALWAYS( aDownload, User::Panic(KFotaPanic, KErrArgument) );	
	CFotaDownloadNotifHandler* h=new (ELeave)CFotaDownloadNotifHandler;
	h->iDownload = aDownload;
	h->iDownload->iFotaServer->iNotifHandler = h;
	return h;
	}

// --------------------------------------------------------------------------
CFotaDownloadNotifHandler::CFotaDownloadNotifHandler() : CActive(EPriorityNormal)
	{
	FLOG(_L("CFotaDownloadNotifHandler::CFotaDownloadNotifHandler()"));
	CActiveScheduler::Add( this ); 
	}

// --------------------------------------------------------------------------
CFotaDownloadNotifHandler::~CFotaDownloadNotifHandler()
	{
	FLOG(_L("CFotaDownloadNotifHandler::~CFotaDownloadNotifHandler >>"));
	iNotifier.Close();
	Cancel();
	FLOG(_L("CFotaDownloadNotifHandler::~CFotaDownloadNotifHandler <<"));
	}

// --------------------------------------------------------------------------
void CFotaDownloadNotifHandler::RunL()
	{
	FLOG(_L("CFotaDownloadNotifHandler::RunL() note:%d, param:%d" ),iNotifParams.iNoteType, iNotifParams.iIntParam);

	TBool reset (ETrue);

	iNotifier.Close();

	iDownload->SetDownloadActive(EFalse);
	if ( iNotifParams.iNoteType == ESyncMLFwUpdErrorNote  ) // 1 
		{
		//do nothing here
		}
	if ( iNotifParams.iNoteType == ESyncMLFwUpdOmaDLNotEnoughMemory ) // 7
		{
		//To be active as Flexible mem is in action.
		if (iDownload->iFreshDL)
			iDownload->SetDownloadActive(ETrue);
		}
	if ( iNotifParams.iNoteType == ESyncMLFwUpdOmaDLUserCancel )
		{
		//At this point Download Mgr has already paused the download successfully.
		if (iStatus.Int() == KErrCancel) //RSK Press
			{
			//User wants to cancel download permanently.
			FLOG(_L("User choose to cancel download permanently!"));
			iDownload->RunDownloadCancelL(RFotaEngineSession::EResUserCancelled);
			}
		else
			{
			//Other keys pressed, like LSK or Call termination key
			FLOG(_L("User choose to resume download later, key press = %d"),iStatus.Int());
			iDownload->iFotaServer->FinalizeDownloadL( iDownload->iDLState );
			if (iStatus.Int() == KErrNone) //RSK is pressed
				{
				LaunchNotifierL(ESyncMLFwUpdOmaDLPostponed, EFalse, EFalse);
				reset = EFalse;
				}
			else
				iDownload->iFotaServer->ShutApp();
			}
		}

	if ( iNotifParams.iNoteType == ESyncMLFwUpdOmaDLPostponed )
		{
		//Nothing to do
		}

	if ( iNotifParams.iNoteType == ESyncMLFwUpdOmaDLCancelled )
		{
		//Nothing to do
		}

	if ( iNotifParams.iNoteType == ESyncMLFwUpdOmaDLResume )
		{
		if (iStatus.Int() == KErrNone) // LSK Press
			{
			FLOG(_L("User choose to continue download now."));
			iNotifParams.iNoteType = ESyncMLFwUpdUnknown;
			iNotifParams.iIntParam = 0;
			iDownload->ResumeDownloadL();
			reset = EFalse;
			}
		else	//RSK or any other key
			{
			FLOG(_L("User cancelled to continue download now, key press = %d."),iStatus.Int());
			if (iStatus.Int() == KErrCancel) //RSK is pressed
				{
				iDownload->iDLState.iResult = RFotaEngineSession::EResUserCancelled;
				LaunchNotifierL(ESyncMLFwUpdOmaDLUserCancel, EFalse, EFalse);
				reset = EFalse;
				}
			else
				iDownload->iFotaServer->ShutApp();
			}
		}

	if (reset)
		{
		iNotifParams.iNoteType = ESyncMLFwUpdUnknown;
		iNotifParams.iIntParam = 0;
		}
	}

// --------------------------------------------------------------------------
TInt CFotaDownloadNotifHandler::RunError(TInt aError)
	{	
	FLOG(_L("CFotaDownloadNotifHandler::RunError %d"),aError);
	return aError;
	}

// --------------------------------------------------------------------------
void CFotaDownloadNotifHandler::DoCancel()
	{
	FLOG(_L("CFotaDownloadNotifHandler::DoCancel >>"));
	if (iNotifier.Handle())
		{
		iNotifier.CancelNotifier( KSyncMLFwUpdNotifierUid );
		iNotifier.Close();
		}
		FLOG(_L("CFotaDownloadNotifHandler::DoCancel <<"));
	}

// --------------------------------------------------------------------------
void CFotaDownloadNotifHandler::LaunchNotifierL( const TSyncMLFwUpdNoteTypes aNotetype
		,const TInt aIntParam
		, const TInt aMemoryNeeded
		,TBool aFinishOnly)
	{
	FLOG(_L("CFotaDownloadNotifHandler::LaunchNotifierL, aNoteType=%d, aParam=%d, aMemoryNeeded=%d aFinishOnly=%d >>  "), aNotetype, aIntParam, aMemoryNeeded, aFinishOnly?1:0);
	
	__ASSERT_ALWAYS( iNotifier.Handle()==0, User::Leave(KErrAlreadyExists) );
	__ASSERT_ALWAYS( aMemoryNeeded>=0, User::Leave(KErrArgument) );


	// Launch notifier
	TSyncMLFwUpdNotifParams         params;
	FLOG(_L("           1"));
	params.iNoteType        = aNotetype;
	params.iIntParam        = aIntParam;

	TInt rem = 0;
	rem = aMemoryNeeded % 1024 ;
	if (rem)
		{
		params.iMemoryNeeded = (aMemoryNeeded /1024) + 1;   	
		}
	else
		{  
		params.iMemoryNeeded = (aMemoryNeeded /1024) ;
		}

	//    #endif    
	TSyncMLFwUpdNotifParamsPckg     pckg(params);
	iNotifParams.iNoteType  = params.iNoteType;
	iNotifParams.iIntParam  = params.iIntParam;

	iNotifParams.iMemoryNeeded = params.iMemoryNeeded;

	iDummyResponsePckg = TSyncMLFwUpdNotifRetValPckg();
	FLOG(_L("           2"));
	if ( !aFinishOnly )
		{
		User::LeaveIfError( iNotifier.Connect() );
		iNotifier.StartNotifierAndGetResponse( iStatus, KSyncMLFwUpdNotifierUid
				, pckg, iDummyResponsePckg );
		SetActive();
		}
	else
		{
		iStatus = KRequestPending;
		SetActive();
		TRequestStatus* status = &iStatus;
		User::RequestComplete( status, KErrNone );
		}
	FLOG(_L("           3  %d"),iStatus.Int());
	FLOG(_L("CFotaDownloadNotifHandler::LaunchNotifierL() <<"));	
	}

TBool CFotaDownloadNotifHandler::IsOpen()
	{
	FLOG(_L("Handle = %d"), iNotifier.Handle());
	return (iNotifier.Handle())? ETrue:EFalse;
	}