locationcentre/lcservice/src/lcsyncoperation.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 00:16:03 +0200
changeset 0 522cd55cc3d7
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2007 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 all the Synchronous operations with the Location
*                Centre Client Session
*
*/


// SYSTEM INCLUDES
#include <s32mem.h>

// USER INCLUDES
#include "lcsyncoperation.h"
#include "lcclientsession.h"
#include "lcipcparams.h"
#include "lcdebug.h"

// CONSTANT DEFINTIONS
const TInt  KLcLengthofInteger  = 4;

// ----- Member funtions for LcSyncOperation ---------------------------------

// ---------------------------------------------------------------------------
// CLcLocationAppInfoArray* CLcServiceImpl::GetLocationApplicationsL
// ---------------------------------------------------------------------------
//    
CLcLocationAppInfoArray* LcSyncOperation::GetLocationApplicationsL(
											  RLcClientSession&   	aSession,
							            const TLcLocationAppFilter& aLocationAppFilter )
    {
    DEBUG("+ LcSyncOperation::GetLocationApplicationsL")
    DEBUG("Filtering")
    
    // This function needs to obtain a list of all applications. This would
    // first require to obtain the length of the buffer that needs to be
    // passed from the client to the server to pack the array.
    CBufFlat* lengthBuf = CBufFlat::NewL( KLcLengthofInteger );
    CleanupStack::PushL( lengthBuf );
    
    // Set the size of this buffer to 4. This is required because we dont
    // actually fill this buffer but expect the server to fill it. In that case
    // if we dont set the expected length, the server would fail with
    // KrrBadDescriptor.
    lengthBuf->ResizeL( KLcLengthofInteger );
    
    // Fill the IPC argument structure with the Length buffer, the server
    // will write the data onto this buffer.
    TIpcArgs    args;
    
    // Pass the filter parameters to the Location Centre Server
    TPckg< TLcLocationAppFilter >    filterBuffer( aLocationAppFilter );
    
    // By the IPC exchange parameter defintion, this must be the first
    // argument to the IPC message.
    args.Set( 0, &filterBuffer );
    
    // Set the buffer pointer to the start of the Length buffer
    TPtr8 bufPtr( const_cast< TUint8 *>( lengthBuf->Ptr( 0 ).Ptr()),
                  0,
                  KLcLengthofInteger );
    
    // This will be the second argument passed to this IPC message.
    args.Set( 1, &bufPtr);
    
    // Send a synchrnous message to the server to obtain the length. On return the
    // server is expected to pack the length of the Application information
    // arrays in the LengthBuffer pointer.
    User::LeaveIfError( aSession.SendReceive( ELcFilteredAppsBufferLength, args ));

    // If the server has not set the buffer then leave with KErrNotFound
    if ( !bufPtr.Length())
        {
        User::Leave( KErrNotFound );
        }
    
    // Obtain the length from the Length buffer;
    RBufReadStream  readStream( *lengthBuf, 0 );
    CleanupClosePushL( readStream );
    TUint length = readStream.ReadInt32L();
    CleanupStack::PopAndDestroy( 2, lengthBuf );   // readStream
    
    // If the server has returned a length of 0, then there are no applications
    // registered with Location Centre.
    if ( !length )
        {
        User::Leave( KErrNotFound );
        }
    
    // Now that the length has been obtained. Allocate the descriptor
    // of suitable length and send it across to the server.
    CBufFlat* appInfoBuf = CBufFlat::NewL( length );
    CleanupStack::PushL( appInfoBuf );
    
    // Set the actual size to 'length' obtained in the previous IPC. This is required
    // because we dont actually fill this buffer but expect the server to fill it.
    // In that case if we dont set the expected length, the server would fail with
    // KrrBadDescriptor.
    appInfoBuf->ResizeL( length );
    
    // Fill the IPC argument structure with the Application info buffer, the server
    // will write the data onto this buffer.
    
    // Pass the filter parameters to the Location Centre Server
    // By the IPC exchange parameter defintion, this must be the first
    // argument to the IPC message.
    args.Set( 0, &filterBuffer );
    
    // Set the buffer pointer to the start of the Length buffer
    bufPtr.Set( const_cast< TUint8 *>( appInfoBuf->Ptr( 0 ).Ptr()),
                0,
                length );
    
    // This will be the second argument passed to this IPC message.
    args.Set( 1, &bufPtr);
    
    // Send a synchrnous message to the server to obtain the length. On return the
    // server is expected to pack the length of the Application information
    // arrays in the LengthBuffer pointer.
    TInt error =  aSession.SendReceive( ELcFilteredApps, args );
    
	// If the Retrieval function completes with KErrOverflow then there has been
	// an update to the registry since the time we obtained the length.
	if ( KErrOverflow == error )
		{
		// Cleanup the current state and Re-issue the same request again
		CleanupStack::PopAndDestroy( appInfoBuf );
		return GetLocationApplicationsL( aSession, aLocationAppFilter );
		}
	else if( error )
		{
		User::Leave( error );
		}

    // If the server has not set the buffer then leave with KErrNotFound
    if ( !bufPtr.Length())
        {
        User::Leave( KErrNotFound );
        }
        
    // Parse the Application information array to obtain the array
    RBufReadStream  appReadStream( *appInfoBuf, 0 );
    CleanupClosePushL( appReadStream );
    
    CLcLocationAppInfoArray* array = ParseLocAppBufferL( appReadStream );
    
    CleanupStack::PopAndDestroy( 2, appInfoBuf );   // appReadStream

    DEBUG("- LcSyncOperation::GetLocationApplicationsL")
    
    return array;

    }

// ---------------------------------------------------------------------------
// CLcLocationAppInfoArray* LcSyncOperation::GetLocationApplicationsL
// ---------------------------------------------------------------------------
//     
CLcLocationAppInfoArray* LcSyncOperation::GetLocationApplicationsL(
                                      RLcClientSession&   		aSession,
                                      const RArray<TPtrC>&      aAppArray,
                                            TBool               aIncludeFlag )
    {
        
    // Obtain the array of Application Identifiers in a buffer
    RLcIpcAppIdArray        idArray;
    CleanupStack::PushL( TCleanupItem( RLcIpcAppIdArray::ResetAndDestroyIdArray, &idArray ));
    
    // Append all the identifiers to the Array    
    for ( TInt i = 0; i < aAppArray.Count(); i++ )
        {
        // Create a new element
        HBufC* newElement = HBufC::NewLC( aAppArray[i].Length());
        
        // Copy the contents to the buffer and append it to the array
        newElement->Des().Copy( aAppArray[i] );
        User::LeaveIfError( idArray.Append( newElement ));
        
        // Now that the ownership is transferred, the content can be removed from
        // the Cleanup stack
        CleanupStack::Pop();
        }
    
    // Create the buffer for packing the Application Information
    // structure and pack the contents into this buffer
    CBufFlat* buffer = CBufFlat::NewL( idArray.BufferLength());
    CleanupStack::PushL( buffer );
    
    RBufWriteStream writeStream( *buffer, 0 );
    CleanupClosePushL( writeStream );                
    idArray.ExternalizeL( writeStream );
    CleanupStack::PopAndDestroy(); // writeStream
                   
    // This needs to be popped inorder to Close the idArray;
    CleanupStack::Pop( 2 ); // buffer, idArray
    idArray.ResetAndDestroy();
    idArray.Close();
    
    // Now reinsert the App buffer back into the Cleanupstack
    CleanupStack::PushL( buffer );
       
    // This function needs to obtain a list of all applications. This would
    // first require to obtain the length of the buffer that needs to be
    // passed from the client to the server to pack the array.
    
    TIpcArgs    args;
        
    // First pack the application id array to the IPC args
    // By the IPC exchange parameter defintion, this must be the first
    // argument to the IPC message.
    TPtr8 appArrayPtr( buffer->Ptr(0));
      
    args.Set( 0, &appArrayPtr );
     
    // The second argument is the Include flag
    args.Set( 1, aIncludeFlag );
               
    CBufFlat* lengthBuf = CBufFlat::NewL( KLcLengthofInteger );
    CleanupStack::PushL( lengthBuf );
    
    // Set the size of this buffer to 4. This is required because we dont
    // actually fill this buffer but expect the server to fill it. In that case
    // if we dont set the expected length, the server would fail with
    // KrrBadDescriptor.
    lengthBuf->ResizeL( KLcLengthofInteger );
 
    // Set the buffer pointer to the start of the Length buffer
    TPtr8 bufPtr( const_cast< TUint8 *>( lengthBuf->Ptr( 0 ).Ptr()),
                  0,
                  KLcLengthofInteger );
    
    // This will be the third argument passed to this IPC message.
    args.Set( 2, &bufPtr);
    
    // Send a synchrnous message to the server to obtain the length. On return the
    // server is expected to pack the length of the Application information
    // arrays in the LengthBuffer pointer.
    User::LeaveIfError( aSession.SendReceive( ELcSpecifiedAppsBufferLength, args ));

    // If the server has not set the buffer then leave with KErrNotFound
    if ( !bufPtr.Length())
        {
        User::Leave( KErrNotFound );
        }
    
    // Obtain the length from the Length buffer;
    RBufReadStream  readStream( *lengthBuf, 0 );
    CleanupClosePushL( readStream );
    TUint length = readStream.ReadInt32L();
    CleanupStack::PopAndDestroy( 2, lengthBuf );   // readStream
    
    // If the server has returned a length of 0, then there are no applications
    // registered with Location Centre.
    if ( !length )
        {
        User::Leave( KErrNotFound );
        }
    
    // Now that the length has been obtained. Allocate the descriptor
    // of suitable length and send it across to the server.
    CBufFlat* appInfoBuf = CBufFlat::NewL( length );
    CleanupStack::PushL( appInfoBuf );
    
    // Set the actual size to 'length' obtained in the previous IPC. This is required
    // because we dont actually fill this buffer but expect the server to fill it.
    // In that case if we dont set the expected length, the server would fail with
    // KrrBadDescriptor.
    appInfoBuf->ResizeL( length );
    
    // Fill the IPC argument structure with the Application info buffer, the server
    // will write the data onto this buffer.
    
    // Pass the Application ids to the Location Centre Server
    // By the IPC exchange parameter defintion, this must be the first
    // argument to the IPC message.
    args.Set( 0, &appArrayPtr );
    
    // The second argument is the Include flag
    args.Set( 1, aIncludeFlag );
    
    // Set the buffer pointer to the start of the Length buffer
    bufPtr.Set( const_cast< TUint8 *>( appInfoBuf->Ptr( 0 ).Ptr()),
                0,
                length );
    
    // This will be the third argument passed to this IPC message.
    args.Set( 2, &bufPtr);
    
    // Send a synchrnous message to the server to obtain the length. On return the
    // server is expected to pack the length of the Application information
    // arrays in the LengthBuffer pointer.
    TInt error = aSession.SendReceive( ELcSpecifiedApps, args );

	// If the Retrieval function completes with KErrOverflow then there has been
	// an update to the registry since the time we obtained the length.
	if ( KErrOverflow == error )
		{
		// Cleanup the current state and Re-issue the same request again
		CleanupStack::PopAndDestroy( 2, buffer );
		return GetLocationApplicationsL( aSession, aAppArray, aIncludeFlag );
		}
	else if( error )
		{
		User::Leave( error );
		}
		
		
    // If the server has not set the buffer then leave with KErrNotFound
    if ( !bufPtr.Length())
        {
        User::Leave( KErrNotFound );
        }
        
    // Parse the Application information array to obtain the array
    RBufReadStream  appReadStream( *appInfoBuf, 0 );
    CleanupClosePushL( appReadStream );
    
    CLcLocationAppInfoArray* array = LcSyncOperation::ParseLocAppBufferL( appReadStream );
    
    CleanupStack::PopAndDestroy( 3, buffer );   // idArray, appInfoBuf and buffer

    return array;  
    }
    
// ---------------------------------------------------------------------------
// CLcBasicAppInfo* LcSyncOperation::GetLocationAppInfoL
// ---------------------------------------------------------------------------
// 
CLcBasicAppInfo* LcSyncOperation::GetLocationAppInfoL( 
									RLcClientSession&   aSession,
							  const TDesC&				aIdentifier )
	{
    // This function needs to obtain the Length of the buffer which needs to be
    // passed to the Server to pack the Location Application Information.
    CBufFlat* lengthBuf = CBufFlat::NewL( KLcLengthofInteger );
    CleanupStack::PushL( lengthBuf );
    
    // Set the size of this buffer to 4. This is required because we dont
    // actually fill this buffer but expect the server to fill it. In that case
    // if we dont set the expected length, the server would fail with
    // KrrBadDescriptor.
    lengthBuf->ResizeL( KLcLengthofInteger );
    
    // Fill the IPC argument structure with the Length buffer, the server
    // will write the data onto this buffer.
    TIpcArgs    args;
    
    // By the IPC exchange parameter defintion, the first argument must the
    // Identifier name
    args.Set( 0, &aIdentifier );
    
    // Set the buffer pointer to the start of the Length buffer
    TPtr8 bufPtr( const_cast< TUint8 *>( lengthBuf->Ptr( 0 ).Ptr()),
                  0,
                  KLcLengthofInteger );
    
    // This will be the second argument passed to this IPC message.
    args.Set( 1, &bufPtr);
    
    // Send a synchrnous message to the server to obtain the length. On return the
    // server is expected to pack the length of the Application information
    // arrays in the LengthBuffer pointer.
    User::LeaveIfError( aSession.SendReceive( ELcAppInfoLength, args ));

    // If the server has not set the buffer then leave with KErrNotFound
    if ( !bufPtr.Length())
        {
        User::Leave( KErrNotFound );
        }
    
    // Obtain the length from the Length buffer;
    RBufReadStream  readStream( *lengthBuf, 0 );
    CleanupClosePushL( readStream );
    TUint length = readStream.ReadInt32L();
    CleanupStack::PopAndDestroy( 2, lengthBuf );   // readStream
    
    // If the server has returned a length of 0, then there are no applications
    // registered with Location Centre.
    if ( !length )
        {
        User::Leave( KErrNotFound );
        }
    
    // Now that the length has been obtained. Allocate the descriptor
    // of suitable length and send it across to the server.
    CBufFlat* appInfoBuf = CBufFlat::NewL( length );
    CleanupStack::PushL( appInfoBuf );
    
    // Set the actual size to 'length' obtained in the previous IPC. This is required
    // because we dont actually fill this buffer but expect the server to fill it.
    // In that case if we dont set the expected length, the server would fail with
    // KrrBadDescriptor.
    appInfoBuf->ResizeL( length );
    
    // Fill the IPC argument structure with the Application info buffer, the server
    // will write the data onto this buffer.
    
    // Pass the Application Identifier to the Location Centre Server
    // By the IPC exchange parameter defintion, this must be the first
    // argument to the IPC message.
    args.Set( 0, &aIdentifier );
    
    // Set the buffer pointer to the start of the Length buffer
    bufPtr.Set( const_cast< TUint8 *>( appInfoBuf->Ptr( 0 ).Ptr()),
                0,
                length );
    
    // This will be the second argument passed to this IPC message.
    args.Set( 1, &bufPtr);
    
    // Send a synchrnous message to the server to obtain the length. On return the
    // server is expected to pack the length of the Application information
    // in the buffer pointer.
    TInt error = aSession.SendReceive( ELcAppInfo, args );

	// If the Retrieval function completes with KErrOverflow then there has been
	// an update to the registry since the time we obtained the length.
	if ( KErrOverflow == error )
		{
		// Cleanup the current state and Re-issue the same request again
		CleanupStack::PopAndDestroy( appInfoBuf );
		return GetLocationAppInfoL( aSession, aIdentifier );
		}
	else if( error )
		{
		User::Leave( error );
		}
		
    // If the server has not set the buffer then leave with KErrNotFound
    if ( !bufPtr.Length())
        {
        User::Leave( KErrNotFound );
        }
        
    // Parse the Application information structure to obtain the Application
    // information structure
    RBufReadStream  appReadStream( *appInfoBuf, 0 );
    CleanupClosePushL( appReadStream );
    
    CLcBasicAppInfo* appInfo = CLcBasicAppInfo::NewLC();
    appInfo->InternalizeL( appReadStream );
    CleanupStack::Pop( appInfo );
    
    CleanupStack::PopAndDestroy( 2, appInfoBuf );   // appReadStream

    return appInfo;	
	}
	
// ---------------------------------------------------------------------------
// CLcLocationAppInfoArray* LcSyncOperation::ParseLocAppBufferL
// ---------------------------------------------------------------------------
// 
CLcLocationAppInfoArray* LcSyncOperation::ParseLocAppBufferL( 
                                                RReadStream&   aReadStream )
    {
    DEBUG("+ LcSyncOperation::ParseLocAppBufferL")
        
    CLcLocationAppInfoArray* appArray = CLcLocationAppInfoArray::NewLC();
    
    // Parse the contents into RLcIpcAppInfoArray type.
    RLcIpcAppInfoArray  ipcArray;
    CleanupStack::PushL( TCleanupItem( RLcIpcAppInfoArray::ResetAndDestroyAppArray, &ipcArray ));
    
    // Internalize the array onto the ipcArray structure.
    ipcArray.InternalizeL( aReadStream );

    // Pack the Application info array
    for ( TInt i = 0; i < ipcArray.Count(); i++ )
        {
        
        // Form the Application information object corresponding to
        // this ipcAppInfo.
        
        // Create a new Application Information object. This object will
        // be populated and the appended to the appArray.
        CLcLocationAppInfo* appInfo = CLcLocationAppInfo::NewLC();
        
        // Set the Unique identifer for the application
        appInfo->SetIdL( ipcArray[i]->Id());
        
        // Set the display name of the application
        appInfo->SetNameL( ipcArray[i]->Name());
        
        // Set the Launch Mode for the application
        // There is no need to check the launch mode and compare it with
        // the values of TLcLaunchMode. Internally its ensured that the 
        // server would only set the parameter based in TLcLaunchMode.
        appInfo->SetLaunchMode( static_cast<CLcLocationAppInfo::
                            TLcLaunchMode>( ipcArray[i]->LaunchMode()));
        
        // Set the Application characteristics
        appInfo->SetApplicationCharacteristics( 
                            ipcArray[i]->ApplicationCharacteristics());
        
        // Set the system characteristics
        appInfo->SetSystemCharacteristics( ipcArray[i]->SystemCharacteristics());
         
        // Load the application Icon Related Data
        if ( ipcArray[i]->IconFile().Compare( KNullDesC ))
        	{
        	// The Icon file name is specified. So Load the icons from the 
        	// Icon file. So we can set these values for the Icon file.
        	appInfo->SetIconL( ipcArray[i]->IconFileType(),
        					   ipcArray[i]->IconFile(),
        					   ipcArray[i]->FrameNo());
        	}
        else if ( ipcArray[i]->ApplicationType() == ELcNativeApplication )
        	{
        	// Only native applications are handled here.
        	// Here we have to pass the Application UID as the Icon data since
        	// the Icon will be loaded from the App shell
        	appInfo->SetIconL( ipcArray[i]->IconFileType(),
        					   ipcArray[i]->ApplicationData());        	
        	}
        		   
        appArray->AppendL( appInfo );
        CleanupStack::Pop( appInfo );
        }
    CleanupStack::PopAndDestroy(); // ipcArray
    
    // If there are no elements in the array then that means that there
    // are no applications registered with LC. So leave with KErrNotFound
    if ( !appArray->Count())
        {
        User::Leave( KErrNotFound );
        }
    
    CleanupStack::Pop( appArray ); 
    
    DEBUG("- LcSyncOperation::ParseLocAppBufferL")
           
    return appArray;
    }	                                                                                                            
// End of File