--- /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<TFeatureEntry> 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<TFeatureEntry> pckgBack( featBack );
+ TPckgC<TInt> 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<TFeatureEntry> 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<TFeatureEntry> pckgBack( temp[i] );
+ aMessage.WriteL( 1, pckgBack, offset );
+ }
+ CleanupStack::PopAndDestroy( &temp );
+
+ // Write number of found entries back to client
+ TPckgC<TInt> resPckg( responseCount );
+ aMessage.WriteL( 2, resPckg );
+
+ break;
+ }
+
+ case EFeatMgrNumberOfSupportedFeatures:
+ {
+ TInt count = iRegistry.NumberOfSupportedFeatures();
+ TPckgC<TInt> 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<TUid> 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<TInt> 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<TInt> resPckg( getIdErr );
+ aMessage.WriteL( 1, resPckg );
+
+ break;
+ }
+
+ case EFeatMgrAddFeature:
+ {
+ if( getIdErr == KErrNone)
+ {
+ TFeatureEntry feature;
+ TPckg<TFeatureEntry> pckg( feature );
+ aMessage.ReadL( 0, pckg );
+ TFeatureServerEntry feat( feature );
+ getIdErr = iRegistry.AddFeature( feat, processId );
+ }
+ TPckgC<TInt> resPckg( getIdErr );
+ aMessage.WriteL( 1, resPckg );
+
+ break;
+ }
+
+ case EFeatMgrDeleteFeature:
+ {
+ if( getIdErr == KErrNone)
+ {
+ TUid feature = TUid::Uid(aMessage.Int0());
+ getIdErr = iRegistry.DeleteFeature( feature, processId );
+ }
+ TPckgC<TInt> 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<TInt> 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<TInt> 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<TUid> pckg( feature );
+ TInt offset = i * sizeof(TUid);
+ aMessage.ReadL( 1, pckg, offset );
+ err = iNotifyFeatures.Append( feature );
+ if( err != KErrNone )
+ {
+ break;
+ }
+ }
+ }
+
+ TPckgC<TInt> 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<TInt> resPckg( err );
+ aMessage.WriteL( 1, resPckg );
+
+ break;
+ }
+
+ case EFeatMgrReqNotifyCancelAll:
+ {
+ iNotifyFeatures.Reset();
+ if( iNotifyMessage.IsNull() == EFalse )
+ {
+ iNotifyMessage.Complete( KErrCancel );
+ }
+ TPckgC<TInt> resPckg( KErrNone );
+ aMessage.WriteL( 0, resPckg );
+
+ break;
+ }
+
+ case EFeatMgrSWIStart:
+ {
+ if( getIdErr == KErrNone)
+ {
+ getIdErr = iRegistry.SWIStart(processId);
+ }
+ TPckgC<TInt> resPckg( getIdErr );
+ aMessage.WriteL( 0, resPckg );
+
+ break;
+ }
+
+ case EFeatMgrSWIEnd:
+ {
+ if( getIdErr == KErrNone)
+ {
+ getIdErr = iRegistry.SWIEnd(processId);
+ }
+ TPckgC<TInt> 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<TInt> resPckg( count );
+ aMessage.WriteL( 0, resPckg );
+
+ break;
+ }
+
+ // returns the number of allocated heap cells
+ case EFeatMgrCountAllocCells:
+ {
+ TInt count = User::CountAllocCells();
+ TPckgC<TInt> 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<TInt> 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