diff -r 000000000000 -r 522cd55cc3d7 locationcentre/lcserver/src/lcserverengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locationcentre/lcserver/src/lcserverengine.cpp Tue Feb 02 00:16:03 2010 +0200 @@ -0,0 +1,704 @@ +/* +* 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: Location Centre Server Engine Object. +* +*/ + + +// SYSTEM INCLUDES +#include +#include + +// USER INCLUDES +#include "lcserverengine.h" +#include "lcregistry.h" +#include "lcserverengineobserver.h" +#include "lcserverinterface.h" +#include "lcdebug.h" + +// CONSTANT DEFINTIONS +const TUint32 KUidMaxValue = 0xFFFFFFFF; + +// ----- Member funtions for CLcServerEngine --------------------------------- + +// --------------------------------------------------------------------------- +// CLcServerEngine::CLcServerEngine +// --------------------------------------------------------------------------- +// +CLcServerEngine::CLcServerEngine( MLcServerEngineObserver& aObserver ) + :iObserver( aObserver ) + { + // C++ Default constructor. No allocations or functions which can Leave + // should be called from here. + } + +// --------------------------------------------------------------------------- +// CLcServerEngine::~CLcServerEngine +// --------------------------------------------------------------------------- +// +CLcServerEngine::~CLcServerEngine() + { + // C++ Destructor. Free all resources associated with this class. + + // Complete any outstanding messages if they exist and free all the + // associated resources + while ( iMessageArray.Count()) + { + // Extract the IPC message handle from the Array + RMessage2* message = iMessageArray[0]; + iMessageArray.Remove( 0 ); + + // Service the Request. + message->Complete( KErrServerTerminated ); + + // Free the message structure + delete message; + } + iMessageArray.ResetAndDestroy(); + iMessageArray.Close(); + + // Delete the Location Centre Registry + delete iRegistry; + } + +// --------------------------------------------------------------------------- +// CLcServerEngine* CLcServerEngine::NewL +// --------------------------------------------------------------------------- +// +CLcServerEngine* CLcServerEngine::NewL( MLcServerEngineObserver& aObserver ) + { + CLcServerEngine* self = NewLC( aObserver ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CLcServerEngine* CLcServerEngine::NewLC +// --------------------------------------------------------------------------- +// +CLcServerEngine* CLcServerEngine::NewLC( MLcServerEngineObserver& aObserver ) + { + // Symbian Two phased constructor. Leaves the object on the Clean-up + // stack. + CLcServerEngine* self = new ( ELeave )CLcServerEngine( aObserver ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::ConstructL +// --------------------------------------------------------------------------- +// +void CLcServerEngine::ConstructL() + { + // Create the Location Centre Registry + iRegistry = CLcRegistry::NewL( *this ); + + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::ConstructL +// --------------------------------------------------------------------------- +// +void CLcServerEngine::DoServiceL( const RMessage2& aMessage ) + { + // We cannot store the reference to the RMessage2 object passed but + // need to create a new instance and copy the contents for all + // furture purposes + RMessage2* message = new RMessage2; + *message = aMessage; + + // Append the message to the Queue. All messages will be serviced later + // in a generic manner. + User::LeaveIfError( iMessageArray.Append( message )); + + if ( !iRegistryUnderUpdate ) + { + // The registry is consistent. So the message can be handled immediately. + ServiceRequests(); + } + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::RegistryUnderUpdation +// --------------------------------------------------------------------------- +// +void CLcServerEngine::RegistryUnderUpdation() + { + DEBUG( "+ CLcServerEngine::RegistryUnderUpdation") + + // Set the Registry update flag. This would prevent the Engine from + // performing any operation until the updation completes. + iRegistryUnderUpdate = ETrue; + + DEBUG( "- CLcServerEngine::RegistryUnderUpdation") + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::RegistryUpdated +// --------------------------------------------------------------------------- +// +void CLcServerEngine::RegistryUpdated() + { + DEBUG( "+ CLcServerEngine::RegistryUpdated") + + // Reset the Registry Update flag. Now the Registry is consistent and + // the Engine can service any requestsy + iRegistryUnderUpdate = EFalse; + + // Serve all the outstanding Location Requests. + ServiceRequests(); + + // Notify the Engine Observer about the changes to the Registry. + iObserver.LcRegistryUpdated(); + + DEBUG( "- CLcServerEngine::RegistryUpdated") + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::ServiceRequests +// --------------------------------------------------------------------------- +// +void CLcServerEngine::ServiceRequests() + { + // Service all outstanding LC requests. + while ( iMessageArray.Count()) + { + // Extract the IPC message handle from the Array + RMessage2* message = iMessageArray[0]; + iMessageArray.Remove( 0 ); + + // Service the Request. + TRAPD( error, ServiceRequestL(*message)); + + DEBUG1( "ServiceRequest Error %d", error ) + + // Complete the request with the error code. + message->Complete( error ); + + // Free the message structure + delete message; + } + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::ServiceRequestL +// --------------------------------------------------------------------------- +// +void CLcServerEngine::ServiceRequestL( RMessage2& aMessage ) + { + // Set the Current requestor's SID + iCurrentRequestorSid = aMessage.SecureId(); + + switch( aMessage.Function()) + { + case ELcFilteredAppsBufferLength: + case ELcFilteredApps: + { + // Getting the Application buffer length and Getting the list of applications + // have similar functionality. Only the last portion of the code changes. + // Hence, both the requests will be handled similarly with the necessary + // differentiation at the end. + + // Create the package buffer for obtaining the filter conditions + TPckgBuf< TLcLocationAppFilter > filterBuf; + + // Read the filter contents + User::LeaveIfError( aMessage.Read( 0, filterBuf )); + + RLcIpcAppInfoArray appArray; + CleanupClosePushL( appArray ); + + // Filter Location based Applications based on the Filter + // conditions + GetFilteredAppsL( filterBuf(), appArray ); + + // Now for the differentiation + if ( aMessage.Function() == ELcFilteredAppsBufferLength ) + { + // Write the Length Value into a buffer + CBufFlat* lengthBuffer = CBufFlat::NewL( sizeof( TUint32 )); + CleanupStack::PushL( lengthBuffer ); + RBufWriteStream lengthWrite( *lengthBuffer, 0 ); + CleanupClosePushL( lengthWrite ); + lengthWrite.WriteInt32L( appArray.BufferLength()); + CleanupStack::PopAndDestroy(); // lengthWrite + + // Write the Buffer back to the IPC message + TPtr8 ptr( lengthBuffer->Ptr(0)); + User::LeaveIfError( aMessage.Write( 1, ptr )); + + // Pop and destroy the length buffer + CleanupStack::PopAndDestroy( lengthBuffer ); + } + else + { + // Create the buffer for packing the Application Information + // structures and pack the contents into this buffer + CBufFlat* buffer = CBufFlat::NewL( appArray.BufferLength() ); + CleanupStack::PushL( buffer ); + RBufWriteStream writeStream( *buffer, 0 ); + CleanupClosePushL( writeStream ); + appArray.ExternalizeL( writeStream ); + CleanupStack::PopAndDestroy(); // writeStream + + // Write the buffer back to the IPC message. + TPtr8 ptr( buffer->Ptr(0)); + User::LeaveIfError( aMessage.Write( 1, ptr )); + + // Pop and destroy the app buffer + CleanupStack::PopAndDestroy( buffer ); + } + + // Reset and Destroy the Contents of the Application info + // array + CleanupStack::PopAndDestroy( &appArray ); + break; + } + case ELcSpecifiedAppsBufferLength: + case ELcSpecifiedApps: + { + // Getting the Application buffer length and Getting the list of applications + // have similar functionality. Only the last portion of the code changes. + // Hence, both the requets will be handled similarly with the necessary + // differentiation at the end. + + // Obtain the array of Applications which need to be used for + // filtering. + + // Read the Descriptor from the IPC arguments + TInt desLength = aMessage.GetDesLength( 0 ); + // Allocate the id Array buffer + CBufFlat* idArrayBuf = CBufFlat::NewL( desLength ); + CleanupStack::PushL( idArrayBuf ); + idArrayBuf->ResizeL( desLength ); + + TPtr8 idArrayPtr( idArrayBuf->Ptr(0)); + + // Now read the descriptor finally + User::LeaveIfError( aMessage.Read( 0, idArrayPtr )); + + // Create a Read buffer stream to read the App Ids + RBufReadStream appReadStream( *idArrayBuf, 0 ); + CleanupClosePushL( appReadStream ); + + RLcIpcAppIdArray idArray; + CleanupStack::PushL( TCleanupItem( RLcIpcAppIdArray::ResetAndDestroyIdArray, &idArray )); + + // Internalize the structure to obtain the Actual list of Ids + idArray.InternalizeL( appReadStream ); + + + RLcIpcAppInfoArray appArray; + CleanupClosePushL( appArray ); + + // Read the second paramte to determine whether the list specified needs to be + // included or excluded + TBool includeFlag = aMessage.Int1(); + if ( includeFlag ) + { + GetSpecifiedAppsL( idArray, appArray ); + } + else + { + GetWithoutSpecifiedAppsL( idArray, appArray ); + } + + if ( aMessage.Function() == ELcSpecifiedAppsBufferLength ) + { + // Write the Length Value into a buffer + CBufFlat* lengthBuffer = CBufFlat::NewL( sizeof( TUint32 )); + CleanupStack::PushL( lengthBuffer ); + + RBufWriteStream lengthWrite( *lengthBuffer, 0 ); + CleanupClosePushL( lengthWrite ); + lengthWrite.WriteInt32L( appArray.BufferLength()); + CleanupStack::PopAndDestroy(); // lengthWrite + + // Write the Buffer back to the IPC message + TPtr8 ptr( lengthBuffer->Ptr(0)); + User::Leave( aMessage.Write( 2, ptr )); + + // Pop and destroy the Length buffer + CleanupStack::PopAndDestroy( lengthBuffer ); + } + else + { + // Create the buffer for packing the Application Information + // structures and pack the contents into this buffer + CBufFlat* buffer = CBufFlat::NewL( appArray.BufferLength() ); + CleanupStack::PushL( buffer ); + + RBufWriteStream writeStream( *buffer, 0 ); + CleanupClosePushL( writeStream ); + appArray.ExternalizeL( writeStream ); + CleanupStack::PopAndDestroy(); // writeStream + + // Write the buffer back to the IPC message. + TPtr8 ptr( buffer->Ptr(0)); + User::Leave( aMessage.Write( 2, ptr )); + + // Pop and destroy the app buffer + CleanupStack::PopAndDestroy( buffer ); + } + + // We can also destroy the App id array buffer and Read streams + CleanupStack::PopAndDestroy( 4, idArrayBuf ); + + break; + } + case ELcAppInfoLength: + { + DEBUG( "+ CLcServerEngine::ServiceRequestL, ELcAppInfoLength ") + + // Read the Descriptor from the IPC arguments + TInt desLength = aMessage.GetDesLength( 0 ); + + // Obtain the Application Identifier + HBufC* identifier = HBufC::NewLC( desLength ); + TPtr des(identifier->Des()); + aMessage.Read( 0, des ); + + // Obtain the Location based Application for this identifer + CLcBasicAppInfo* appInfo = NULL; + User::LeaveIfError( iRegistry->GetApplicationInfo( *identifier, appInfo )); + + // Pack the Length field into the Second argument + CBufFlat* lengthBuffer = CBufFlat::NewL( sizeof( TUint32 )); + CleanupStack::PushL( lengthBuffer ); + + RBufWriteStream lengthWrite( *lengthBuffer, 0 ); + CleanupClosePushL( lengthWrite ); + lengthWrite.WriteInt32L( appInfo->BufferLength()); + CleanupStack::PopAndDestroy(); // lengthWrite + + // Write the Buffer back to the IPC message + TPtr8 ptr( lengthBuffer->Ptr(0)); + User::LeaveIfError( aMessage.Write( 1, ptr )); + + // Pop and destroy the Length buffer + CleanupStack::PopAndDestroy( 2, identifier ); + + DEBUG( "- CLcServerEngine::ServiceRequestL, ELcAppInfoLength ") + + break; + } + case ELcAppInfo: + { + DEBUG( "+ CLcServerEngine::ServiceRequestL, ELcAppInfo ") + + // Read the Descriptor from the IPC arguments + TInt desLength = aMessage.GetDesLength( 0 ); + + // Obtain the Application Identifier + HBufC* identifier = HBufC::NewLC( desLength ); + TPtr des(identifier->Des()); + aMessage.Read(0, des); + + // Obtain the Location based Application for this identifer + CLcBasicAppInfo* appInfo = NULL; + User::LeaveIfError( iRegistry->GetApplicationInfo( *identifier, appInfo )); + + // Create the buffer for packing the Application Information + // structure and pack the contents into this buffer + CBufFlat* buffer = CBufFlat::NewL( appInfo->BufferLength()); + CleanupStack::PushL( buffer ); + + RBufWriteStream writeStream( *buffer, 0 ); + CleanupClosePushL( writeStream ); + appInfo->ExternalizeL( writeStream ); + CleanupStack::PopAndDestroy(); // writeStream + + // Write the buffer back to the IPC message. + TPtr8 ptr( buffer->Ptr(0)); + User::LeaveIfError( aMessage.Write( 1, ptr )); + + // Pop and destroy the App info buffer + CleanupStack::PopAndDestroy( 2, identifier ); + + DEBUG( "- CLcServerEngine::ServiceRequestL, ELcAppInfo ") + + break; + } + default: + { + DEBUG( "CLcServerEngine::ServiceRequestL, KErrNotSupported ") + User::Leave( KErrNotSupported ); + break; + } + } + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::GetFilteredApps +// --------------------------------------------------------------------------- +// +void CLcServerEngine::GetFilteredAppsL( + TLcLocationAppFilter& aAppFilter, + RLcIpcAppInfoArray& aFilteredAppArray ) + { + DEBUG( "+ CLcServerEngine::GetFilteredAppsL") + + // Obtain the current list of Location based Applications from the + // Location Centre registry. Incase, the application satisfies the + // filter conditions, then the application is appended to the list. + + RPointerArray appInfoArray; + User::LeaveIfError( iRegistry->GetAllRegisteredAppsList( appInfoArray )); + + TInt count = appInfoArray.Count(); + + // Parse through the array list for each item + for ( TInt i = 0; i < count; i++ ) + { + // Obtain the element at the position 'i' + CLcAppInfo* element = appInfoArray[i]; + + if ( element->ApplicationType() == ELcNativeApplication && + IsSameSID( element->ApplicationData())) + { + continue; + } + + // Check for the filtering conditions. Here we can check for the System + // filters and Application filters simultaneously. The code seems + // pretty lengthy owing to many accessor methods but retained it here + // instead of using too many local variables. + if ( Compare( aAppFilter.SystemCharacteristics(), + element->SystemCharacteristics(), + aAppFilter.SysCharFilterConfiguration()) && + Compare( aAppFilter.ApplicationCharacteristics(), + element->ApplicationCharacteristics(), + aAppFilter.AppCharFilterConfiguration())) + { + // The filter characteristics have matched. So append the element + // to the Array + + // Ignoring the Append error. Incase there is an error then the + // element would not be appened. + User::LeaveIfError( aFilteredAppArray.Append( element )); + } + } + appInfoArray.Reset(); + appInfoArray.Close(); + + DEBUG1( "App Count : %d", aFilteredAppArray.Count()) + DEBUG( "- CLcServerEngine::GetFilteredAppsL") + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::GetSpecifiedAppsL +// --------------------------------------------------------------------------- +// +void CLcServerEngine::GetSpecifiedAppsL( + RLcIpcAppIdArray& aSpecifedApps, + RLcIpcAppInfoArray& aSpecifiedAppArray ) + { + // Obtain the current list of Location based Applications from the + // Location Centre registry. Incase, the application satisfies the + // filter conditions, then the application is appended to the list. + RPointerArray appInfoArray; + User::LeaveIfError( iRegistry->GetAllRegisteredAppsList( appInfoArray )); + TInt count = appInfoArray.Count(); + + // Parse through the array list for each item + for ( TInt i = 0; i < count; i++ ) + { + // Obtain the element at the position 'i' + CLcAppInfo* element = appInfoArray[i]; + + if ( element->ApplicationType() == ELcNativeApplication && + IsSameSID( element->ApplicationData())) + { + continue; + } + + // Check for the filtering conditions + for ( TInt j = 0; j < aSpecifedApps.Count(); j++ ) + { + // Obtain the current identifier + HBufC* identifier = aSpecifedApps[j]; + + // Check if the current App info's id is the same as this identifer + // If Yes, then append it and go to the next element. + if ( !identifier->Des().Compare( element->Id())) + { + // Ignoring the Append error. Incase there is an error then the + // element would not be appened. + User::LeaveIfError( aSpecifiedAppArray.Append( element )); + } + } + // Small optimization check to see if the number of elements that have + // been added are equal to the the number of elements in the App id + // array. If yes, we can stop the checking. + if ( aSpecifiedAppArray.Count() == aSpecifedApps.Count() ) + { + break; + } + } + appInfoArray.Reset(); + appInfoArray.Close(); + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::GetWithoutSpecifiedAppsL +// --------------------------------------------------------------------------- +// +void CLcServerEngine::GetWithoutSpecifiedAppsL( + RLcIpcAppIdArray& aSpecifedApps, + RLcIpcAppInfoArray& aSpecifiedAppArray ) + { + // Obtain the current list of Location based Applications from the + // Location Centre registry. Incase, the application satisfies the + // filter conditions, then the application is appended to the list. + + RPointerArray appInfoArray; + User::LeaveIfError( iRegistry->GetAllRegisteredAppsList( appInfoArray )); + TInt count = appInfoArray.Count(); + + // Parse through the array list for each item + for ( TInt i = 0; i < appInfoArray.Count(); i++ ) + { + // Obtain the element at the position 'i' + CLcAppInfo* element = appInfoArray[i]; + + if ( element->ApplicationType() == ELcNativeApplication && + IsSameSID( element->ApplicationData())) + { + continue; + } + + // Boolean flag to check whether an element exists or not. + TBool append = ETrue; + + // Check for the filtering conditions + for ( TInt j = 0; j < aSpecifedApps.Count(); j++ ) + { + // Obtain the current identifier + HBufC* identifier = aSpecifedApps[j]; + + // Check if the current App info's id is the same as this identifer + // If Yes, then append it and go to the next element. + if ( !identifier->Des().Compare( element->Id())) + { + // Incase, the element being compared in the list is requested + // then set the flag and break the switch + append = EFalse; + break; + } + } + + if ( append ) + { + // Ignoring the Append error. Incase there is an error then the + // element would not be appened. + User::LeaveIfError( aSpecifiedAppArray.Append( element )); + } + } + appInfoArray.Reset(); + appInfoArray.Close(); + } + +// --------------------------------------------------------------------------- +// void CLcServerEngine::Compare +// --------------------------------------------------------------------------- +// +TBool CLcServerEngine::Compare( TUint32 aFilter, + TUint32 aFiltertoCompare, + TInt aFilterConfig ) + { + // Here, + // aFilter - Filter passed by the Client Application + // aFiltertoCompare - Filter of the Location based Application + + // If no filter configurations are set then there will be no need to + // proceed with checking. The Locaiton based Application must always be + // included. Hence, return True. + if ( !aFilter ) + { + return ETrue; + } + + // Proceed for the Actual checking. + + // Set the default value to EFalse to enable pessimistic match. + TBool ret = EFalse; + + switch( aFilterConfig ) + { + case TLcLocationAppFilter::EFilterStrict: + { + // Strict Filtering needs to be applied. So here we just have to + // compare the values and then return True only if there is an + // exact match + if ( aFilter == aFiltertoCompare ) + { + ret = ETrue; + } + break; + } + case TLcLocationAppFilter::EFilterInclusive: + { + // The Location based Application must have all the characteristics + // passed by the Client application. It can have any additonal + // characteristic too. + if (( aFilter & aFiltertoCompare ) == aFilter ) + { + ret = ETrue; + } + break; + } + case TLcLocationAppFilter::EFilterExclusive: + { + // The filtering should be such that there should be no match + // between the requested character set and the one specified for the + // Location based Application. + if ( !( aFilter & aFiltertoCompare )) + { + ret = ETrue; + } + break; + } + default: + { + break; + } + } + return ret; + } + +// --------------------------------------------------------------------------- +// TBool CLcServerEngine::IsSameSID +// --------------------------------------------------------------------------- +// +TBool CLcServerEngine::IsSameSID( const TDesC& aAppSid ) + { + // Since the request is for a Native S60 application, the Identifer + // contains an UID. Obtain it using Lexer + TLex lexer( aAppSid ); + TUint32 uidValue; + + if ( lexer.BoundedVal( uidValue, EHex, KUidMaxValue ) || + uidValue != iCurrentRequestorSid ) + { + return EFalse; + } + else + { + return ETrue; + } + } + +// End of File