fotaapplication/fotaserver/FotaEngine/SRC/fotaengine.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 31 Mar 2010 23:00:03 +0300
branchRCL_3
changeset 19 86979fe66c4c
parent 0 b497e44ab2fc
permissions -rw-r--r--
Revision: 201011 Kit: 201013

/*
* 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:   Client for fotaserver
*
*/




// INCLUDES
#include <bldvariant.hrh>
#include "fotaengine.h"
#include "FotaIPCTypes.h"
#include "fotaConst.h"
#include "fotaenginedebug.h"
#include <apgcli.h>
#include <AknServerApp.h>

// CONSTANTS
_LIT(KServerNameFormat, "%08x_%08x_AppServer");        

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

// ---------------------------------------------------------------------------
// IsClientFota()   Checks if client is another fotaserver
// ---------------------------------------------------------------------------
TBool IsClientFota()
    {
    RThread thread;
    TUid    fota,dlmgr;
    fota.iUid           = KFotaServerUid;
    dlmgr.iUid			= KDLMgrServerUid;
    if (thread.SecureId() == fota.iUid || thread.SecureId() == dlmgr.iUid )
        {
        return ETrue;
        }
    return EFalse;
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::StartServerL() 
// Start application server
// ---------------------------------------------------------------------------
//
void RFotaEngineSession::StartApplicationL( const TUid& aNameUid
                                            , const TUid& aAppServerUid )
    {
    TInt err;
    FLOG(_L("RFotaEngineSession::StartApplicationL >>"));
    RApaLsSession apa;
    err = apa.Connect();
    User::LeaveIfError(err);
    CleanupClosePushL(apa);

    // Get application information
    TApaAppInfo info;
    err=0;
    for(TInt i = 20; ((err = apa.GetAppInfo(info, 
	    aAppServerUid)) == RApaLsSession::EAppListInvalid) && i > 0; i--)
        {
        User::After(500000);
        }
    User::LeaveIfError(err);

    // Start aplication server
    CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
    cmdLine->SetExecutableNameL(info.iFullName);
    cmdLine->SetServerRequiredL( aNameUid.iUid );
    cmdLine->SetCommandL(EApaCommandBackground);
    TThreadId   srvid;
    err = apa.StartApp(*cmdLine, srvid);
    User::LeaveIfError(err);

    // Wait until server is running.

    // Rendezvous() is not reliable for synchronising with the new server
    // in this case as we may not be able
    // to open the server thread before it has reached its rendezvous
    // point, in which case we hang.
    // So, the standby algorithm is to poll for server existence (yuk)
	const TInt maxPoll = 100;
	const TInt waitDelay = 100000;	// 0.1 seconds
    TFullName serverName;
    serverName.Format(KServerNameFormat, aNameUid, aAppServerUid);
	for (TInt ii = 0; ii < maxPoll; ii++)
		{
		// look for the server name
		TFindServer find(serverName);
		TFullName fullName;
        err = find.Next(fullName);
		if ( err == KErrNone)
			{
			break;		// found the server, so return
			}
		User::After(waitDelay);			// wait before trying again
		}
	User::LeaveIfError(err);	// failed to find the server, bomb out

    CleanupStack::PopAndDestroy(2, &apa);	// cmdLine and apa
    FLOG(_L("RFotaEngineSession::StartApplicationL <<"));
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::StartServerL() 
// Connect to existing server
// ---------------------------------------------------------------------------
//
void RFotaEngineSession::ConnectToServerL( const TUid& aNameUid
                                            , const TUid& aAppServerUid )
    {
    RWsSession  ws;
    TInt        err;

    FLOG(_L("RFotaEngineSession::ConnectToServerL >>"));
    if (aAppServerUid == KNullUid)
        {
        User::Leave(KErrGeneral);
        }

	// Connect to server
    TFullName serverName;
	serverName.Format(KServerNameFormat, 
	aNameUid, aAppServerUid);
    TRAP(err, ConnectExistingByNameL(serverName) );
    if(err)
        {
        TVersion vers(0,0,1);
        err = CreateSession (serverName, vers);
        User::LeaveIfError(err);
        }
    FLOG(_L("       3"));

    FLOG(_L("RFotaEngineSession::ConnectToServerL <<"));
    }
    
// ---------------------------------------------------------------------------
// RFotaEngineSession::OpenL( )
// Opens session to fotaserver. 
// ---------------------------------------------------------------------------
EXPORT_C void RFotaEngineSession::OpenL( )
{
    RProcess pr; TFullName fn = pr.FullName(); 
    TInt err(0);
    TUid diff1 = TUid::Uid(KUikonUidPluginInterfaceNotifiers);
    FLOG(_L("[RFotaEngineSession] OpenL\tcalled by '%S' >>"),&fn );

    // -------------------------------------------- V
    err = KErrNotFound;
    // If client is fotaserver - MUST create new server
    if( !IsClientFota() ) 
        {
        TRAP(err, ConnectToServerL( diff1 , TUid::Uid(KFotaServerUid)) );
        }
    else
        {
        diff1 = TUid::Uid(KUikonUidPluginInterfaceNotifiers+1);
        }

    if(err!=KErrNone)
        {
        StartApplicationL( diff1 , TUid::Uid(KFotaServerUid));
        ConnectToServerL( diff1 , TUid::Uid(KFotaServerUid));
        }
    FLOG(_L("[RFotaEngineSession]\tconnected <<") );
}


// ---------------------------------------------------------------------------
// RFotaEngineSession::Close( )
// Closes session to fotaserver
// ---------------------------------------------------------------------------
EXPORT_C void RFotaEngineSession::Close( )
{
    RProcess pr; TFullName fn = pr.FullName(); 
    FLOG(_L("[RFotaEngineSession] RFotaEngineSession::Close() >> called by '%S'"),&fn );
        
    if ( iStream )
        {
        iStream->Close(); // this uses iChunk
        delete iStream;  iStream=0;
        }
    iChunk.Close();

    // Tell server that generic alert is sent for this pkg, so state is 
    // cleaned up     
    if ( iGenericAlertSentPkgID != -1 )
        {
        TInt err = SendReceive( EGenericAlertSentForPackage
                                    , TIpcArgs(iGenericAlertSentPkgID) );
        }

    REikAppServiceBase::Close();
    FLOG(_L("[RFotaEngineSession] RFotaEngineSession::Close() <<") );
}


// ---------------------------------------------------------------------------
// RFotaEngineSession::Download
// Starts download of upd package.
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::Download(const TInt aPkgId
    , const TDesC8& aPkgURL, const TSmlProfileId aProfileId
    , const TDesC8& aPkgName, const TDesC8& aPkgVersion)
{
    TInt err;
    TDownloadIPCParams          ipcparam;
    ipcparam.iPkgId             = aPkgId;
    ipcparam.iProfileId         = aProfileId;
    ipcparam.iPkgName.Copy      (aPkgName);
    ipcparam.iPkgVersion.Copy   (aPkgVersion);
    TPckg<TDownloadIPCParams>   pkg(ipcparam);
    err = SendReceive ( EFotaDownload ,  TIpcArgs(&pkg, &aPkgURL));
    return err;
}

// ---------------------------------------------------------------------------
// RFotaEngineSession::DownloadAndUpdate
// Starts download and update of update pakcage
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::DownloadAndUpdate(const TInt aPkgId
        ,const TDesC8& aPkgURL, const TSmlProfileId aProfileId
        ,const TDesC8& aPkgName, const TDesC8& aPkgVersion)
{
    TInt err;
    TDownloadIPCParams          ipcparam;
    ipcparam.iPkgId             = aPkgId;
    ipcparam.iProfileId         = aProfileId;
    ipcparam.iPkgName.Copy      (aPkgName);
    ipcparam.iPkgVersion.Copy   (aPkgVersion);
    TPckg<TDownloadIPCParams>   pkg(ipcparam);
    err = SendReceive( EFotaDownloadAndUpdate,  TIpcArgs(&pkg, &aPkgURL));
    return err;
}

// ---------------------------------------------------------------------------
// RFotaEngineSession::Update
// Starts update of update package
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::Update(const TInt aPkgId
        ,const TSmlProfileId aProfileId, const TDesC8& aPkgName
        ,const TDesC8& aPkgVersion)
{
    TInt err;
    TDownloadIPCParams          ipcparam;
    ipcparam.iPkgId             = aPkgId;
    ipcparam.iProfileId         = aProfileId;
    ipcparam.iPkgName.Copy      (aPkgName);
    ipcparam.iPkgVersion.Copy   (aPkgVersion);
    TPckg<TDownloadIPCParams>   pkg(ipcparam);
    err = SendReceive ( EFotaUpdate ,  TIpcArgs(&pkg));
    return err;
}


// ---------------------------------------------------------------------------
// RFotaEngineSession::IsPackageStoreSizeAvailable
// Checks if there's space enough for update package
// ---------------------------------------------------------------------------
EXPORT_C TBool RFotaEngineSession::IsPackageStoreSizeAvailable(
                                                    const TInt aSize)
    {
//    // -------------------------------------------- v 
//    if( IsClientFota() ) 
//        {
//        FLOG(_L("     IsPackageStoreSizeAvailable  NOT CONNECTING"));
//        return ETrue;
//        }
//    // -------------------------------------------- ^ 
    TInt            err;
    TBool           available;
    TPckg<TBool>    pavailable(available);
    err = SendReceive ( EIsPackageStoreSizeAvailable, TIpcArgs(aSize
                                                        , &pavailable ) );
    if ( err ) 
        {   
        FLOG(_L("RFotaEngineSession::IsPackageStoreSizeAvailable error %d")
                    ,err);
        }
    return available;
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::OpenUpdatePackageStore
// OPens update package storage for writing.
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::OpenUpdatePackageStore(const TInt aPkgId
                                                 ,RWriteStream*& aPkgStore)
	{
    FLOG(_L( "RFotaEngineSession::OpenUpdatePackageStore >> pkgid %d " )
                    ,aPkgId );
    TInt err;
    err = iChunk.CreateGlobal( KNullDesC, KFotaChunkMinSize, KFotaChunkMaxSize );
    if(err) return err;
    iStream = new RFotaWriteStream();
    iStream->iFotaEngineSession = this;    
    TRAP( err, iStream->OpenL(aPkgId) );
    aPkgStore = iStream;
    if(err) return err;

    TIpcArgs args;
    args.Set(0,aPkgId);
    args.Set(1,iChunk );
	err = SendReceive( EFotaOpenUpdatePackageStore, args );
    FLOG(_L( "RFotaEngineSession::OpenUpdatePackageStore << err  %d" ),err );
    return err;
    }
// ---------------------------------------------------------------------------
// RFotaEngineSession::GetDownloadUpdatePackageSize
// Gets the downloaded and full size of the update package. 
// Implementation is not ready and will be provided later.
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::GetDownloadUpdatePackageSize(const TInt aPkgId, TInt& aDownloadedSize, TInt& aTotalSize)
	{
	FLOG(_L("RFotaEngineSession::GetDownloadUpdatePackageSize, aPkgId=%d >>"),aPkgId);
	TInt err (KErrNone);
    TPckg<TInt> pkg1(aDownloadedSize);
    TPckg<TInt>	pkg2(aTotalSize);
	err = SendReceive( EFotaGetDownloadUpdatePackageSize,TIpcArgs(aPkgId,&pkg1, &pkg2)  );
	FLOG(_L("RFotaEngineSession::GetDownloadUpdatePackageSize << err = %d, aDownloadedSize = %d, aTotalSize = %d" ), err, aDownloadedSize, aTotalSize);
	return err;
	}

// ---------------------------------------------------------------------------
// RFotaEngineSession::TryResumeDownload
// Requests to resume the suspended download of the update package. 
// Implementation is not ready and will be provided later.
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::TryResumeDownload()
	{
	FLOG(_L("RFotaEngineSession::TryResumeDownload >>"));

	TInt err = KErrNone;
	
	err = SendReceive( EFotaTryResumeDownload );
	
	FLOG(_L("RFotaEngineSession::TryResumeDownload << err = %d" ),err);
	return err;
	}

// ---------------------------------------------------------------------------
// RFotaEngineSession::UpdatePackageDownloadComplete
// Ends update pkg storing. Closes resources.
// ---------------------------------------------------------------------------
EXPORT_C void RFotaEngineSession::UpdatePackageDownloadComplete(
                                                          const TInt aPkgId)
    {
    FLOG(_L("RFotaEngineSession::UpdatePackageDownloadComplete >> id %d")
                            ,aPkgId);
    if ( iStream )
        {
        iStream->Close();
        delete iStream;
        iStream=0;
        }
    TInt err = SendReceive(EUpdatePackageDownloadComplete, TIpcArgs(aPkgId) );
    FLOG(_L("RFotaEngineSession::UpdatePackageDownloadComplete << error %d ")
                            ,err);
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::GetState
// ---------------------------------------------------------------------------
EXPORT_C RFotaEngineSession::TState RFotaEngineSession::GetState(
                                                         const TInt aPkgId)
    {
    FLOG(_L("RFotaEngineSession::GetState"));
    TInt err(0);
    RFotaEngineSession::TState          state;
    TPckg<RFotaEngineSession::TState>   pkgstate(state);
    err = SendReceive ( EGetState , TIpcArgs(aPkgId, &pkgstate));
    if ( err ) 
        {
        FLOG(_L("RFotaEngineSession::GetState error %d"),err);
        }
    return state;
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::GetResult    
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::GetResult(const TInt aPkgId)
    {
    FLOG(_L("RFotaEngineSession::GetResult"));
    TInt            result;
    TPckg<TInt>     pkgresult(result);
    SendReceive ( EGetResult , TIpcArgs(aPkgId, &pkgresult));
    return result;
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::DeleteUpdatePackage
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::DeleteUpdatePackage(const TInt aPkgId)
{
    TInt err = SendReceive(EDeletePackage, TIpcArgs(aPkgId) );
    return err;
}


// ---------------------------------------------------------------------------
// RFotaEngineSession::LastUpdate
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::LastUpdate(TTime& aUpdates)
    {
    TInt err;
    FLOG(_L("RFotaEngineSession::LastUpdate >>"));
    TBuf<15>                    timestamp;
    err = SendReceive ( EGetUpdateTimestamp, TIpcArgs(&timestamp) );

    if ( timestamp.Length() > 0 )
        {
        TInt year   = timestamp[0];
        TInt month  = timestamp[1];
        TInt day    = timestamp[2];
        TInt hour   = timestamp[3];
        TInt minute = timestamp[4];
        aUpdates = TDateTime (year,(TMonth)month,day,hour,minute,0,0 );
        }
    else
        {
        aUpdates.Set( _L( "19900327:101010.000000" ) ); 
        err = KErrUnknown;
        }
    FLOG(_L("RFotaEngineSession::LastUpdate <<"));
    return err;
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::CurrentVersion
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::CurrentVersion(TDes& aSWVersion)
    {
    aSWVersion.Copy(_L("1.0"));  
    return KErrNone;
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::ExtensionInterface
// ---------------------------------------------------------------------------
EXPORT_C void RFotaEngineSession::ExtensionInterface(TUid /*aInterfaceId*/
                                              ,TAny*& /*aImplementation*/)
    {
    RProcess pr; TFullName fn = pr.FullName(); 
    FLOG(_L("RFotaEngineSession::ExtensionInterface called by %S"), &fn);
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::RFotaEngineSession
// ---------------------------------------------------------------------------
EXPORT_C RFotaEngineSession::RFotaEngineSession() : iStream(0)
                    , iGenericAlertSentPkgID(-1)
    {
    FLOG(_L("RFotaEngineSession::RFotaEngineSession() >>"));
    FLOG(_L("RFotaEngineSession::RFotaEngineSession() <<"));
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::GetUpdatePackageIds
// Gets ids of the update packages present in the system.
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::GetUpdatePackageIds(TDes16& aPackageIdList)
    {
    TInt err;
    FLOG(_L("RFotaEngineSession::GetUpdatePackageIds >>"));
    TBuf<10> b; b.Copy(_L("dkkd"));
    TPkgIdList                  pkgids;
    TPckg<TPkgIdList>           pkgids_pkg(pkgids);
    TIpcArgs                    args ( &pkgids_pkg);
    err = SendReceive ( EGetUpdatePackageIds, args);
    aPackageIdList.Copy(pkgids);
    FLOG(_L("RFotaEngineSession::GetUpdatePackageIds <<"));
    return err;
    }



// ---------------------------------------------------------------------------
// RFotaEngineSession::GenericAlertSentL
// marks genereic alert being sent
// ---------------------------------------------------------------------------
EXPORT_C void RFotaEngineSession::GenericAlertSentL ( const TInt aPackageID )
    {
    iGenericAlertSentPkgID = aPackageID;
    }

// ---------------------------------------------------------------------------
// RFotaEngineSession::ScheduledUpdateL
// Update fw
// ---------------------------------------------------------------------------
EXPORT_C TInt RFotaEngineSession::ScheduledUpdateL ( const TFotaScheduledUpdate aSchedule )
    {
  	TInt err(KErrNotSupported);

    TPckg<TFotaScheduledUpdate> p(aSchedule);
    err = SendReceive( EScheduledUpdate, TIpcArgs(&p) );

    return err;
    }

// ---------------------------------------------------------------------------
// RFotaEngineSession::ServiceUid
// Apparc asks which session class to create in server side
// ---------------------------------------------------------------------------
TUid RFotaEngineSession::ServiceUid() const
	{
    RProcess pr; TFullName fn = pr.FullName(); 
    FLOG(_L( "RFotaEngineSession::ServiceUid() >> called by: %S" ), &fn );
    FLOG(_L( "RFotaEngineSession::ServiceUid() << ret: 0x%X" ),
                                            KFotaServiceUid );
	return TUid::Uid( KFotaServiceUid );
	}


// ---------------------------------------------------------------------------
// RFotaEngineSession::SendChunkL
// Tells server to read chunk contnets
// ---------------------------------------------------------------------------
void RFotaEngineSession::SendChunkL(const TUint8* aP1, const TUint8* aP2)
    {
    TInt writecount = aP2-aP1;
    TInt err = SendReceive(EFotaSendChunk, TIpcArgs(writecount) );

    if ( err )
        {   
        FLOG(_L("RFotaEngineSession::SendChunkL error %d"),err);
        }
    User::LeaveIfError ( err );
    }


// ---------------------------------------------------------------------------
// RFotaEngineSession::ReleaseChunkHandle()
// Releases server's handle to the chuhnk
// ---------------------------------------------------------------------------
TInt RFotaEngineSession::ReleaseChunkHandle()
	{
	return Send( EFotaReleaseChunkHandle);
	}