diff -r 000000000000 -r 08ec8eefde2f featuremgmt/featuremgr/src/serverexe/featmgrsession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/featuremgmt/featuremgr/src/serverexe/featmgrsession.cpp Fri Jan 22 11:06:30 2010 +0200 @@ -0,0 +1,623 @@ +// Copyright (c) 2007-2009 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: +// + + + + +// INCLUDE FILES +#include "featmgrsession.h" +#include "featmgrfeatureentry.h" +#include "featmgrdebug.h" + +// CONSTANTS +const TInt CFeatMgrPendingRequest::iOffset = _FOFF( CFeatMgrPendingRequest,iLink ); + +// LOCAL CONSTANTS AND MACROS +_LIT( KPanicCategory, "FeatMgrSession" ); + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CFeatMgrSession::CFeatMgrSession +// C++ constructor +// ----------------------------------------------------------------------------- +// +CFeatMgrSession::CFeatMgrSession( CFeatMgrServer& aServer, CFeatMgrFeatureRegistry& aRegistry ) + : iFeatMgrServer( aServer ), + iRegistry( aRegistry ), + iList( CFeatMgrPendingRequest::iOffset ) + { + } + +// ----------------------------------------------------------------------------- +// CFeatMgrSession::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CFeatMgrSession* CFeatMgrSession::NewL( CFeatMgrServer& aServer, + CFeatMgrFeatureRegistry& aRegistry ) + { + FUNC_LOG + + CFeatMgrSession* self = new( ELeave ) CFeatMgrSession( aServer, aRegistry ); + + return self; + } + +#ifdef EXTENDED_FEATURE_MANAGER_TEST +void CFeatMgrSession::CreateL() + { + iFeatMgrServer.AddSession(); + } +#endif + +// --------------------------------------------------------- +// Destructor +// --------------------------------------------------------- +// +CFeatMgrSession::~CFeatMgrSession() + { + FUNC_LOG + + iNotifyFeatures.Close(); + + while ( !iList.IsEmpty() ) + { + CFeatMgrPendingRequest* pendingReq = iList.First(); + iList.Remove( *pendingReq ); + delete pendingReq; + } + + iList.Reset(); +#ifdef EXTENDED_FEATURE_MANAGER_TEST + iFeatMgrServer.DropSession(); +#endif + } + +// ----------------------------------------------------------------------------- +// CFeatMgrSession::PanicClient +// RMessage2::Panic() also completes the message. This is: +// (a) important for efficient cleanup within the kernel +// (b) a problem if the message is completed a second time +// ----------------------------------------------------------------------------- +// +void CFeatMgrSession::PanicClient( const RMessage2& aMessage, TFeatMgrPanic aPanic ) + { + INFO_LOG1( "CFeatMgrSession::PanicClient(aPanic 0x%x)", aPanic); + + aMessage.Panic( KPanicCategory, aPanic ); + } + +// ----------------------------------------------------------------------------- +// CFeatMgrSession::ServiceL +// Calls request handling functions. Also traps any leaves and signals client if +// error occurs. +// ----------------------------------------------------------------------------- +// +void CFeatMgrSession::ServiceL( const RMessage2& aMessage ) + { + FUNC_LOG + + if ( !iFeatMgrServer.PluginsReady() ) + { + INFO_LOG( "CFeatMgrSession::ServiceL() - plugins not ready" ); + iList.AddLast( *CFeatMgrPendingRequest::NewL( aMessage ) ); + } + else + { + #if defined(FEATMGR_INFO_LOG_ENABLED) + // check memory usage + TInt biggestBlock; + INFO_LOG1( "CFeatMgrSession::ServiceL() - #### Memory Available in Heap: %6d ####", + User::Heap().Available(biggestBlock) ); + INFO_LOG1( "CFeatMgrSession::ServiceL() - #### Biggest block: %6d ####", + biggestBlock ); + #endif + + TRAPD( error, DispatchMessageL( aMessage ) ); + + LOG_IF_ERROR1( error, "CFeatMgrSession::ServiceL(): Error in DispatchMessageL: %d", + error ); + + if( aMessage.Function() != EFeatMgrReqNotify ) + { + aMessage.Complete( error ); + } + } + } + +// ----------------------------------------------------------------------------- +// CFeatMgrSession::ServicePendingRequestsL +// Calls request handling functions. Also traps any leaves and signals client if +// error occurs. +// ----------------------------------------------------------------------------- +// +void CFeatMgrSession::ServicePendingRequestsL() + { + FUNC_LOG + + while ( !iList.IsEmpty() ) + { + CFeatMgrPendingRequest* pendingReq = iList.First(); + + TRAPD( error, DispatchMessageL( pendingReq->iMessage ) ); + + LOG_IF_ERROR1( error, "CFeatMgrSession::ServicePendingRequestsL(): Error in DispatchMessageL: %d", + error ); + + if( pendingReq->iMessage.Function() != EFeatMgrReqNotify ) + { + pendingReq->iMessage.Complete( error ); + } + + iList.Remove( *pendingReq ); + delete pendingReq; + } + + iList.Reset(); + } + +// ----------------------------------------------------------------------------- +// CFeatMgrSession::DispatchMessageL +// Calls matching function of CFeatMgrServer for handling the request. +// ----------------------------------------------------------------------------- +// +void CFeatMgrSession::DispatchMessageL( const RMessage2& aMessage ) + { + FUNC_LOG + + INFO_LOG1( "CFeatMgrSession::DispatchMessageL(0x%x)", aMessage.Function() ); + + TInt msgCmd = aMessage.Function(); + + // Getting the ID of the process making the calls on feature manager. This ID is used + // for the addition, deletion, setting, enabling, and disabling functions. + TUint processId = 0; // default value for a process id + TInt getIdErr = KErrGeneral; + if( msgCmd >= EFeatMgrEnableFeature && msgCmd <= EFeatMgrSWIEnd ) + { + RThread thread; + getIdErr = aMessage.Client(thread, EOwnerProcess); + if( getIdErr == KErrNone) + { + RProcess process; + getIdErr = thread.Process(process); + if( getIdErr == KErrNone) + { + TProcessId prcId = process.Id(); + processId = TUint(prcId.Id()); + } + } + } + + // Check command code and call appropriate function + switch ( msgCmd ) + { + case EFeatMgrFeatureSupported: + { + TFeatureEntry feature; + TPckg pckg( feature ); + aMessage.ReadL( 0, pckg ); + TFeatureServerEntry feat( feature ); + TInt supported = iRegistry.IsFeatureSupported( feat ); + // Construct entry for passing back to client. + TFeatureEntry featBack( feat.FeatureUid(), feat.FeatureFlags(), feat.FeatureData() ); + TPckgC pckgBack( featBack ); + TPckgC resPckg( supported ); + aMessage.WriteL( 0, pckgBack ); + aMessage.WriteL( 1, resPckg ); + + break; + } + + case EFeatMgrFeaturesSupported: + { + TInt count( aMessage.Int0() ); + TInt responseCount( 0 ); + RFeatureArray temp; + CleanupClosePushL( temp ); + temp.ReserveL( count ); + + for ( TInt i = 0; i < count; i++ ) + { + TFeatureEntry feature; + TPckg pckg( feature ); + TInt offset = i * sizeof(TFeatureEntry); + // Read feature entry and fetch entry status/data + aMessage.ReadL( 1, pckg, offset ); + TFeatureServerEntry feat( feature ); + TInt supported = iRegistry.IsFeatureSupported( feat ); + + // Non-existing and uninitialised feature entries are not returned. + if( supported != KErrNotFound && supported != KErrNotReady ) + { + responseCount++; + TFeatureEntry featBack( feat.FeatureUid(), feat.FeatureFlags(), + feat.FeatureData() ); + // Can't write to same slot before reading entries first + temp.AppendL( featBack ); + } + } + + // Write found entries back to client + for ( TInt i = 0; i < responseCount; i++ ) + { + TInt offset = i * sizeof(TFeatureEntry); + TPckgC pckgBack( temp[i] ); + aMessage.WriteL( 1, pckgBack, offset ); + } + CleanupStack::PopAndDestroy( &temp ); + + // Write number of found entries back to client + TPckgC resPckg( responseCount ); + aMessage.WriteL( 2, resPckg ); + + break; + } + + case EFeatMgrNumberOfSupportedFeatures: + { + TInt count = iRegistry.NumberOfSupportedFeatures(); + TPckgC resPckg( count ); + aMessage.WriteL( 0, resPckg ); + + break; + } + + case EFeatMgrListSupportedFeatures: + { + RFeatureUidArray supportedFeatures; + CleanupClosePushL( supportedFeatures ); + + iRegistry.SupportedFeaturesL( supportedFeatures ); + TInt count( supportedFeatures.Count() ); + + if ( aMessage.Int0() == count ) + { + for ( TInt i = 0; i < count; i++ ) + { + TPckg pckg( supportedFeatures[i] ); + TInt offset = i * sizeof(TUid); + aMessage.WriteL( 1, pckg, offset ); + } + + CleanupStack::PopAndDestroy( &supportedFeatures ); + } + else + { + CleanupStack::PopAndDestroy( &supportedFeatures ); + User::Leave( KErrServerBusy ); + } + break; + } + + case EFeatMgrEnableFeature: + { + if( getIdErr == KErrNone ) + { + TUid feature = TUid::Uid(aMessage.Int0()); + getIdErr = iRegistry.SetFeature( feature, EFeatureSupportEnable, NULL, processId ); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 1, resPckg ); + + break; + } + + case EFeatMgrDisableFeature: + { + if( getIdErr == KErrNone ) + { + TUid feature = TUid::Uid(aMessage.Int0()); + getIdErr = iRegistry.SetFeature( feature, EFeatureSupportDisable, NULL, processId ); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 1, resPckg ); + + break; + } + + case EFeatMgrAddFeature: + { + if( getIdErr == KErrNone) + { + TFeatureEntry feature; + TPckg pckg( feature ); + aMessage.ReadL( 0, pckg ); + TFeatureServerEntry feat( feature ); + getIdErr = iRegistry.AddFeature( feat, processId ); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 1, resPckg ); + + break; + } + + case EFeatMgrDeleteFeature: + { + if( getIdErr == KErrNone) + { + TUid feature = TUid::Uid(aMessage.Int0()); + getIdErr = iRegistry.DeleteFeature( feature, processId ); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 1, resPckg ); + + break; + } + + case EFeatMgrSetFeatureAndData: + { + if( getIdErr == KErrNone) + { + TUid feature = TUid::Uid(aMessage.Int0()); + TBool enable = aMessage.Int1(); + TUint32 data = aMessage.Int2(); + getIdErr = iRegistry.SetFeature( feature, enable, &data, processId ); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 3, resPckg ); + + break; + } + + case EFeatMgrSetFeatureData: + { + if( getIdErr == KErrNone) + { + TUid feature = TUid::Uid(aMessage.Int0()); + TUint32 data = aMessage.Int1(); + getIdErr = iRegistry.SetFeature( feature, EFeatureSupportUntouch, &data, processId ); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 2, resPckg ); + + break; + } + + case EFeatMgrReqNotify: + { + // When client requests notification for feature, it could be checked + // whether feature exists at all and even whether feature modifiable, + // i.e. could request ever cause notification. If this will be done, + // remember document error codes in API documentation. + + // Message is needed for later signaling of client upon feature change. + if( iNotifyMessage.IsNull() ) + { + iNotifyMessage = aMessage; + } + else + { + PanicClient( aMessage, EPanicNotifyRequest ); + } + + break; + } + + case EFeatMgrReqNotifyUids: + { + // When client requests notification for features, it could be checked + // whether features exists at all and even whether features modifiable, + // i.e. could request ever cause notification. If this will be done, + // remember document error codes in API documentation. + + TInt err( KErrNone ); + + // Fetch transfer buffer from client + TInt count( aMessage.Int0() ); + err = iNotifyFeatures.Reserve( count ); + + if( err == KErrNone ) + { + for ( TInt i = 0; i < count; i++ ) + { + TUid feature; + TPckg pckg( feature ); + TInt offset = i * sizeof(TUid); + aMessage.ReadL( 1, pckg, offset ); + err = iNotifyFeatures.Append( feature ); + if( err != KErrNone ) + { + break; + } + } + } + + TPckgC resPckg( err ); + aMessage.WriteL( 2, resPckg ); + + break; + } + + case EFeatMgrReqNotifyCancel: + { + TUid feature = TUid::Uid(aMessage.Int0()); + TInt index( iNotifyFeatures.Find( feature ) ); + TInt err( KErrNotFound ); + + if( index != KErrNotFound ) + { + err = KErrNone; + iNotifyFeatures.Remove( index ); + } + + // If no more features to be notified, complete request. + if( !iNotifyFeatures.Count() + && iNotifyMessage.IsNull() == EFalse) + { + iNotifyMessage.Complete( KErrCancel ); + } + + TPckgC resPckg( err ); + aMessage.WriteL( 1, resPckg ); + + break; + } + + case EFeatMgrReqNotifyCancelAll: + { + iNotifyFeatures.Reset(); + if( iNotifyMessage.IsNull() == EFalse ) + { + iNotifyMessage.Complete( KErrCancel ); + } + TPckgC resPckg( KErrNone ); + aMessage.WriteL( 0, resPckg ); + + break; + } + + case EFeatMgrSWIStart: + { + if( getIdErr == KErrNone) + { + getIdErr = iRegistry.SWIStart(processId); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 0, resPckg ); + + break; + } + + case EFeatMgrSWIEnd: + { + if( getIdErr == KErrNone) + { + getIdErr = iRegistry.SWIEnd(processId); + } + TPckgC resPckg( getIdErr ); + aMessage.WriteL( 0, resPckg ); + + break; + } + +#ifdef EXTENDED_FEATURE_MANAGER_TEST + // debug only API + // returns the size of the iNotifyFeatures array + case EFeatMgrNumberOfNotifyFeatures: + { + TInt count = iNotifyFeatures.Count(); + TPckgC resPckg( count ); + aMessage.WriteL( 0, resPckg ); + + break; + } + + // returns the number of allocated heap cells + case EFeatMgrCountAllocCells: + { + TInt count = User::CountAllocCells(); + TPckgC resPckg( count ); + aMessage.WriteL( 0, resPckg ); + + break; + } +#endif + + // Cannot identify the message. + default: + { + PanicClient( aMessage, EPanicIllegalArgument ); + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CFeatMgrSession::ServiceNotifications +// ----------------------------------------------------------------------------- +// +void CFeatMgrSession::ServiceNotifications( TFeatureServerEntry& aFeature, + TFeatureChangeType aType ) + { + FUNC_LOG + + if( !iNotifyMessage.IsNull() ) + { + TInt index( iNotifyFeatures.Find( aFeature.FeatureUid() ) ); + + if( index != KErrNotFound ) + { + if( aType == EFeatureFeatureDeleted ) + { + // The feature was deleted - won't have any more notifications + iNotifyFeatures.Remove(index); + } + + // Write changed feature back to client and complete request + TPckgC feature( aFeature.FeatureUid().iUid ); + TInt err( iNotifyMessage.Write( 0, feature ) ); + if( err == KErrNone ) + { + iNotifyMessage.Complete( aType ); + } + } + } + } + + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CFeatMgrPendingRequest::CFeatMgrPendingRequest +// C++ constructor +// ----------------------------------------------------------------------------- +// +CFeatMgrPendingRequest::CFeatMgrPendingRequest() + { + } + +// ----------------------------------------------------------------------------- +// CFeatMgrPendingRequest::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CFeatMgrPendingRequest* CFeatMgrPendingRequest::NewL(const RMessage2& aMessage) + { + FUNC_LOG + CFeatMgrPendingRequest* self = new (ELeave) CFeatMgrPendingRequest; + + CleanupStack::PushL( self ); + self->ConstructL( aMessage ); + CleanupStack::Pop( self ); + + return self; + } + +// --------------------------------------------------------- +// CFeatMgrPendingRequest::ConstructL +// --------------------------------------------------------- +// +void CFeatMgrPendingRequest::ConstructL(const RMessage2& aMessage) + { + iMessage = aMessage; + } + +// --------------------------------------------------------- +// Destructor +// --------------------------------------------------------- +// +CFeatMgrPendingRequest::~CFeatMgrPendingRequest() + { + FUNC_LOG + } + + +// End of File