diff -r 185201be11b0 -r 516af714ebb4 perfsrv/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/perfsrv/memspy/Engine/Source/ClientServer/MemSpyEngineServer.cpp Fri Sep 17 08:38:31 2010 +0300 @@ -0,0 +1,1788 @@ +/* +* Copyright (c) 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 "MemSpyEngineServer.h" + +// System includes +#include +#include +#include +#include + +// User includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +inline CShutdown::CShutdown() :CTimer(-1) + { + CActiveScheduler::Add(this); + } + +inline void CShutdown::ConstructL() + { + CTimer::ConstructL(); + } + +inline void CShutdown::Start() + { + After(KMyShutdownDelay); + } + +void CShutdown::RunL() + // + // Initiate server exit when the timer expires + // + { + CActiveScheduler::Stop(); + } + +CMemSpyEngineServer::CMemSpyEngineServer( CMemSpyEngine& aEngine ) +: CServer2( EPriorityNormal ), iEngine( aEngine ) + { + } + + +CMemSpyEngineServer::~CMemSpyEngineServer() + { + } + + +void CMemSpyEngineServer::ConstructL() + { + StartL( KMemSpyServerName ); + + iShutdown.ConstructL(); + // ensure that the server still exits even if the 1st client fails to connect + iShutdown.Start(); + } + + +CMemSpyEngineServer* CMemSpyEngineServer::NewL( CMemSpyEngine& aEngine ) + { + CMemSpyEngineServer* self = new(ELeave) CMemSpyEngineServer( aEngine ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + +CSession2* CMemSpyEngineServer::NewSessionL( const TVersion& aVersion, const RMessage2& aMessage ) const + { + if ( aVersion.iMajor != KMemSpyClientServerVersion ) + { + RDebug::Printf( "[MemSpy] CMemSpyEngineSession::NewSessionL() - BAD VERSION" ); + User::Leave( KErrNotSupported ); + } + // + CMemSpyEngineSession* session = CMemSpyEngineSession::NewL( iEngine, aMessage ); + return session; + } + +void CMemSpyEngineServer::AddSession(TBool aCliRequest) + { + if (aCliRequest) + { + iCliConnected = ETrue; + } + else + { + ++iSessionCount; + } + iShutdown.Cancel(); + } + +void CMemSpyEngineServer::DropSession(TBool aCliRequest) + { + if (!aCliRequest) + { + --iSessionCount; + } + + if (iSessionCount == 0 && !iCliConnected) + { + iShutdown.Start(); + } + } + + + + + + + + + + + + + + + + + + + + + + + + +CMemSpyEngineSession::CMemSpyEngineSession( CMemSpyEngine& aEngine ) +: iEngine( aEngine ) + { + } + + +CMemSpyEngineSession::~CMemSpyEngineSession() + { +#ifdef _DEBUG + TPtrC pThreadName( KNullDesC ); + if ( iClientThreadName ) + { + pThreadName.Set( *iClientThreadName ); + } + + RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::~CMemSpyEngineSession() - DEAD SESSION - this: 0x%08x, id: %4d, name: %S"), this, iClientThreadId, iClientThreadName ); +#endif + + delete iClientThreadName; + + Server().DropSession(iIsCliRequest); + } + + +void CMemSpyEngineSession::ConstructL( const RMessage2& aMessage ) + { + RThread thread; + const TInt error = aMessage.Client( thread ); + CleanupClosePushL( thread ); + + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::ConstructL() - this: 0x%08x - opening client thread - err: %d", this, error ) ); + + User::LeaveIfError( error ); + + const TFullName threadName( thread.FullName() ); + iClientThreadName = threadName.AllocL(); + iClientThreadId = thread.Id(); + + CleanupStack::PopAndDestroy( &thread ); + + const TUid KCliUid3 = { 0x2002129D }; + iIsCliRequest = aMessage.SecureId() == TSecureId(KCliUid3); + + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ConstructL() - NEW SESSION - this: 0x%08x, id: %4d, client: %S"), this, iClientThreadId, iClientThreadName ) ); + } + +void CMemSpyEngineSession::CreateL() + { + Server().AddSession(iIsCliRequest); + } + +CMemSpyEngineSession* CMemSpyEngineSession::NewL( CMemSpyEngine& aEngine, const RMessage2& aMessage ) + { + CMemSpyEngineSession* self = new(ELeave) CMemSpyEngineSession( aEngine ); + CleanupStack::PushL( self ); + self->ConstructL( aMessage ); + CleanupStack::Pop( self ); + return self; + } + + +void CMemSpyEngineSession::ServiceL( const RMessage2& aMessage ) + { + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ServiceL() - START - this: 0x%08x, fn: 0x%08x, id: %4d, client: %S"), this, aMessage.Function(), iClientThreadId, iClientThreadName ) ); + + TRAPD( error, DoServiceL( aMessage ) ); + if ( error != KErrNone ) + { + RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ServiceL() - SERVICE ERROR - this: 0x%08x, fn: %d, err: %d, client: %S"), this, aMessage.Function(), error, iClientThreadName ); + } + + if ((aMessage.Function() & KMemSpyOpFlagsAsyncOperation) == 0 || error != KErrNone) + { + aMessage.Complete( error ); + } + + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::ServiceL() - END - this: 0x%08x, fn: 0x%08x, id: %4d, client: %S"), this, aMessage.Function(), iClientThreadId, iClientThreadName ) ); + } + +// --------------------------------------------------------- +// DoServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoServiceL( const RMessage2& aMessage ) + { + TInt function = aMessage.Function() & KMemSpyOpFlagsTypeMask; + if (function >= EMemSpyClientServerOpMarkerUiFirst && + function < EMemSpyClientServerOpMarkerUiLast) + + DoUiServiceL(aMessage); + else + DoCmdServiceL(aMessage); + } +// --------------------------------------------------------- +// DoUiServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoUiServiceL( const RMessage2& aMessage ) + { + switch (aMessage.Function() & KMemSpyOpFlagsTypeMask) + { + case EMemSpyClientServerOpGetOutputSink: + { + TMemSpySinkType sink = iEngine.SinkType(); + TPckgBuf type( sink ); + + aMessage.WriteL( 0, type ); + break; + } + case EMemSpyClientServerOpGetProcessCount: + { + aMessage.WriteL(0, TPckgBuf(iEngine.Container().Count())); + break; + } + case EMemSpyClientServerOpGetProcesses: + { + CMemSpyEngineObjectContainer& list = iEngine.Container(); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + break; + } + case EMemSpyClienServerOpGetProcessIdByName: + { + TFullName processName; + aMessage.ReadL(0, processName); + + TBool found(EFalse); + + for (TInt i=0; i= 0) + { + found = ETrue; + TPckgBuf procId(process.Id()); + aMessage.WriteL(1, procId); + } + } + + if (!found) + { + User::Leave(KErrNotFound); + } + + break; + } + case EMemSpyClientServerOpProcessSystemPermanentOrCritical: + { + TBool ret = EFalse; + TPckgBuf id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + if ( process.IsSystemPermanent() || process.IsSystemCritical() ) + { + ret = ETrue; + } + TPckgBuf retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EMemSpyClientServerOpEndProcess: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + TPckgBuf type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + switch ( type() ) + { + case ETerminate: + { + process.TerminateL(); + break; + } + case EPanic: + { + process.PanicL(); + break; + } + case EKill: + { + process.KillL(); + break; + } + } + break; + } + case EMemSpyClientServerOpSwitchToProcess: + {/* + TInt wgCount; + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + User::LeaveIfError( wgCount = wsSession.NumWindowGroups() ); + RArray wgArray; + CleanupClosePushL( wgArray ); + User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) ); + TApaTask task( wsSession ); + TBool brought( EFalse ); + TInt wgId( KErrNotFound ); + TThreadId threadId; + + TPckgBuf id; + aMessage.ReadL( 0, id ); + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess& process = container.ProcessByIdL( id() ); + + // loop trough threads in a process + for ( TInt i = 0; i < process.MdcaCount(); i++ ) + { + TInt wgCountLocal = wgCount; + + // loop trough all window groups and see if a thread id matches + while( !brought && wgCountLocal-- ) + { + wgId = wgArray[wgCountLocal].iId; + User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) ); + if ( threadId == process.At( i ).Id() ) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId ); + task.SetWgId( wgId ); + if ( !wgName->Hidden() && task.Exists() ) + { + task.BringToForeground(); + brought = ETrue; + } + CleanupStack::PopAndDestroy( wgName ); + } + } + } + + TPckgBuf ret( brought ); + aMessage.WriteL( 1, ret ); + + break;*/ + } + case EMemSpyClientServerOpGetThreadCount: + { + TPckgBuf pid; + aMessage.ReadL(1, pid); + CMemSpyProcess& process = iEngine.Container().ProcessByIdL(pid()); + aMessage.WriteL(0, TPckgBuf(process.Count())); + break; + } + case EMemSpyClientServerOpGetThreads: + { + TPckgBuf pid; + aMessage.ReadL(2, pid); + + CMemSpyProcess& list = iEngine.Container().ProcessByIdL(pid()); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for(TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + break; + } + case EMemSpyClientServerOpSetThreadPriority: + { + TPckgBuf tid; + TPckgBuf priority; + aMessage.ReadL(0, tid); + aMessage.ReadL(1, priority); + + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError(iEngine.Container().ProcessAndThreadByThreadId(tid(), process, thread)); + + if (thread) + { + thread->SetPriorityL(static_cast(priority())); + } + break; + } + case EMemSpyClientServerOpThreadSystemPermanentOrCritical: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + TBool ret = thread && ( thread->IsSystemPermanent() || thread->IsSystemCritical() ); + + TPckgBuf retBuf( ret ); + aMessage.WriteL( 1, retBuf ); + + break; + } + case EMemSpyClientServerOpEndThread: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + TPckgBuf type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + if( thread ) + { + switch ( type() ) + { + case ETerminate: + { + thread->TerminateL(); + break; + } + case EPanic: + { + thread->PanicL(); + break; + } + case EKill: + { + thread->KillL(); + break; + } + } + } + break; + } + case EMemSpyClientServerOpSwitchToThread: + { + TInt wgCount; + RWsSession wsSession; + User::LeaveIfError( wsSession.Connect() ); + CleanupClosePushL( wsSession ); + User::LeaveIfError( wgCount = wsSession.NumWindowGroups() ); + RArray wgArray; + CleanupClosePushL( wgArray ); + User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) ); + TApaTask task( wsSession ); + TBool brought( EFalse ); + TInt wgId( KErrNotFound ); + TThreadId threadId; + + TPckgBuf id; + aMessage.ReadL( 0, id ); + + // loop trough all window groups and see if a thread id matches + while( !brought && wgCount-- ) + { + wgId = wgArray[wgCount].iId; + User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) ); + if ( threadId == id() ) + { + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId ); + task.SetWgId( wgId ); + if ( !wgName->Hidden() && task.Exists() ) + { + task.BringToForeground(); + brought = ETrue; + } + CleanupStack::PopAndDestroy( wgName ); + } + } + TPckgBuf ret( brought ); + aMessage.WriteL( 1, ret ); + + break; + } + case EMemSpyClientServerOpGetInfoItemType: + { + + TPckgBuf index; + aMessage.ReadL( 0, index ); + TPckgBuf id; + aMessage.ReadL( 1, id); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; //not needed + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id(), process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + TMemSpyThreadInfoItemType retType = threadInfoContainer.Item( index() ).Type(); + + TPckgBuf ret( retType ); + aMessage.WriteL( 2, ret ); + + break; + } + case EMemSpyClientServerOpGetThreadInfoItemsCount: + { + TPckgBuf id; + aMessage.ReadL( 0, id ); + TPckgBuf type; + aMessage.ReadL( 1, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + + container.ProcessAndThreadByThreadId( id(), process, thread ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase& threadInfoItemBase = threadInfoContainer.Item( type() ); + + TInt count = threadInfoItemBase.MdcaCount(); + TPckgBuf tempret( count ); + aMessage.WriteL( 2, tempret ); + + break; + } + case EMemSpyClientServerOpGetThreadInfoItems: + { + TPckgBuf count; + aMessage.ReadL( 0, count ); + TPckgBuf id; + aMessage.ReadL( 1, id ); + TPckgBuf type; + aMessage.ReadL( 2, type ); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase& threadInfoItemBase = threadInfoContainer.Item( type() ); //get ThreadInfoItemBaseByType + + TInt itemCount = Min(count(), threadInfoItemBase.MdcaCount()); + + for( TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(3, buffer, offset); + } + aMessage.WriteL(0, count); + + break; + } + + case EMemSpyClientServerOpGetProcessIdByThreadId: + { + TPckgBuf tid; + aMessage.ReadL( 1, tid ); + + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + // + const TInt error = iEngine.Container().ProcessAndThreadByThreadId( tid(), process, thread ); + + TProcessId pid = process->Id(); + + TPckgBuf ret(pid); + aMessage.WriteL( 0, ret ); + + break; + } + + // --- KernelObjects related functions --- + case EMemSpyClientServerOpGetKernelObjectCount: + { + TInt iCount = EMemSpyDriverContainerTypeLast - EMemSpyDriverContainerTypeFirst + 1; + TPckgBuf ret( iCount ); + aMessage.WriteL(0, ret); + break; + } + case EMemSpyClientServerOpGetKernelObjects: + { + TPckgBuf count; + aMessage.ReadL(0, count); + + CMemSpyEngineGenericKernelObjectContainer* model = iEngine.HelperKernelContainers().ObjectsAllL(); //contains all the objects + CleanupStack::PushL( model ); + + for( TInt i=0, offset = 0; iAt(i).Name().Mid(1)); + TInt tabPos = name.Locate('\t'); + if (tabPos != KErrNotFound) + name.Set(name.Left(tabPos)); + + data.iName.Copy(name); + data.iType = model->At(i).Type(); + data.iCount = model->At(i).Count(); + data.iSize = model->At(i).Count() * model->At(i).Count(); + + TPckgBuf buffer(data); + aMessage.WriteL(1, buffer, offset); + } + aMessage.WriteL(0, count); + CleanupStack::PopAndDestroy( model ); + break; + } + case EMemSpyClientServerOpGetKernelObjectItemCount: + { + TPckgBuf tempType; + aMessage.ReadL(1, tempType); //get type of kernel object + TMemSpyDriverContainerType type = tempType(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( type ); + + TInt count = iObjectList->Count(); + TPckgBuf ret( count ); + aMessage.WriteL( 0, ret ); + + break; + } + case EMemSpyClientServerOpGetKernelObjectItems: + { + TPckgBuf count; + TPckgBuf tempType; + aMessage.ReadL( 0, count ); //get count of items + aMessage.ReadL(1, tempType); //get type of kernel object + TInt c = count(); + + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectList* iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( tempType() ); + + for( TInt i=0, offset = 0; iAt( i ); + + TPckgBuf buffer(data); + aMessage.WriteL(2, buffer, offset); + } + + break; + } + + case EMemSpyClientServerOpOutputAllContainerContents: + { + CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers(); + CMemSpyEngineGenericKernelObjectContainer* model = kernelContainerManager.ObjectsAllL(); + + model->OutputL( iEngine.Sink() ); + + break; + } + + case EMemSpyClientServerOpDumpKernelHeap: + { + iEngine.HelperHeap().OutputHeapDataKernelL(); + + break; + } + + case EMemSpyClientServerOpOutputInfoHandles: + { + TPckgBuf id; + aMessage.ReadL(0, id); + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + threadInfoContainer.PrintL(); + + break; + } + + case EMemSpyClientServerOpOutputAOList: + { + TPckgBuf id; + TPckgBuf type; + aMessage.ReadL(0, id); + aMessage.ReadL(1, type); + + CMemSpyEngineObjectContainer& container = iEngine.Container(); + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + User::LeaveIfError( container.ProcessAndThreadByThreadId( id() , process, thread ) ); + + CMemSpyThreadInfoContainer& threadInfoContainer = thread->InfoContainerForceSyncronousConstructionL(); + + CMemSpyThreadInfoItemBase* threadInfoItem = &threadInfoContainer.Item( type() ); + + CMemSpyThreadInfoActiveObjects* activeObjectArray = static_cast< CMemSpyThreadInfoActiveObjects* >( threadInfoItem ); + + // Begin a new data stream + _LIT( KMemSpyContext, "Active Object List - " ); + _LIT( KMemSpyFolder, "Active Objects" ); + iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder ); + + // Set prefix for overall listing + iEngine.Sink().OutputPrefixSetLC( KMemSpyContext ); + + // Create header + CMemSpyEngineActiveObjectArray::OutputDataColumnsL( iEngine ); + + // List items + const TInt count = activeObjectArray->Array().Count(); + for(TInt i=0; iArray().At( i ); + // + object.OutputDataL( iEngine ); + } + + // Tidy up + CleanupStack::PopAndDestroy(); // prefix + + // End data stream + iEngine.Sink().DataStreamEndL(); + + break; + } + + // --- Kernel Heap related functions --- + case EMemSpyClientServerOpGetHeap: + { + TMemSpyHeapInfo heapInfo; + iEngine.HelperHeap().GetHeapInfoKernelL( heapInfo ); + TMemSpyHeapData data = iEngine.HelperHeap().NewHeapRawInfo( heapInfo ); + + TPckgBuf buffer(data); + aMessage.WriteL(0, buffer); + + break; + } + + case EMemSpyClientServerOpGetServerCount: + { + CMemSpyEngineServerList* list = iEngine.HelperServer().ServerListL(); + CleanupStack::PushL(list); + // TODO: cache it between calls + aMessage.WriteL(0, TPckgBuf(list->MdcaCount())); + + CleanupStack::PopAndDestroy(list); + break; + } + // --- Servers related functions + case EMemSpyClientServerOpGetServers: + { + CMemSpyEngineServerList* list = iEngine.HelperServer().ServerListL(); + CleanupStack::PushL(list); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list->MdcaCount()); + + for(TInt i=0, offset = 0; iAt(i); + TMemSpyServerData data; + + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + TInt error = iEngine.Container().ProcessAndThreadByThreadId( server.Id(), process, thread ); + if (error == KErrNone && thread) + { + data.iId = thread->Process().Id(); + } + data.iName.Copy(server.Name().Left(KMaxFullName)); + data.iSessionCount = server.SessionCount(); + + TPckgBuf buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list->Count(); + aMessage.WriteL(0, a0); + + CleanupStack::PopAndDestroy(list); + + break; + } + + case EMemSpyClientServerOpGetSortedServers: + { + CMemSpyEngineServerList* list = iEngine.HelperServer().ServerListL(); + CleanupStack::PushL(list); + + TPckgBuf a2; + aMessage.ReadL( 2, a2 ); + + //sort the list of the servers + if( a2() == ESortServByName ) + list->SortByNameL(); + else + list->SortBySessionCountL(); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + + TInt realCount = Min(a0(), list->MdcaCount()); + + for(TInt i=0, offset = 0; iAt(i); + TMemSpyServerData data; + + data.iId = server.Id(); + data.iName.Copy(server.Name().Left(KMaxFullName)); + data.iSessionCount = server.SessionCount(); + + TPckgBuf buffer(data); + aMessage.WriteL(1, buffer, offset); + } + a0 = list->Count(); + aMessage.WriteL(0, a0); + + CleanupStack::PopAndDestroy(list); + break; + } + + case EMemSpyClientServerOpServerListOutputGeneric: + { + TPckgBuf a0; + aMessage.ReadL(0, a0); + + CMemSpyEngineServerList* list; + list = iEngine.HelperServer().ServerListL(); + CleanupStack::PushL(list); + + _LIT( KMemSpyContext, "Server List - " ); + _LIT( KMemSpyFolder, "Servers" ); + iEngine.Sink().DataStreamBeginL( KMemSpyContext, KMemSpyFolder ); + + // Set prefix for overall listing + iEngine.Sink().OutputPrefixSetLC( KMemSpyContext ); + + // Create header + CMemSpyEngineServerList::OutputDataColumnsL( iEngine, a0() ); + + // List items + const TInt count = list->Count(); + for(TInt i=0; iAt( i ); + // + server.OutputDataL( iEngine.HelperServer(), a0() ); + } + + // Tidy up + CleanupStack::PopAndDestroy(); // prefix + + // End data stream + iEngine.Sink().DataStreamEndL(); + + CleanupStack::PopAndDestroy(list); + break; + } + + case EMemSpyClientServerOpGetMemoryTrackingCycleCount: + { + TInt count = iEngine.HelperSysMemTracker().CompletedCycles().Count(); + TPckgBuf ret( count ); + aMessage.WriteL( 0, ret ); + break; + } + + case EMemSpyClientServerOpGetMemoryTrackingCycles: + { + const RPointerArray& list = iEngine.HelperSysMemTracker().CompletedCycles(); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), list.Count()); + + for (TInt i=0, offset = 0; iCycleNumber(); + data.iCaption.Copy(list[i]->Caption().Left(KMaxFullName)); + data.iTime = list[i]->Time(); + data.iFreeMemory = list[i]->MemoryFree(); + data.iMemoryDelta = list[i]->MemoryDelta(); + data.iPreviousCycleDiff = list[i]->MemoryFreePreviousCycle(); + data.iChangeCount = list[i]->ChangeCount(); + + TPckgBuf buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = list.Count(); + aMessage.WriteL(0, a0); + + break; + } + + case EMemSpyClientServerOpIsSwmtRunning: + { + TPckgBuf running(iEngine.HelperSysMemTracker().IsActive()); + aMessage.WriteL(0, running); + break; + } + + case EMemSpyClientServerOpSystemWideMemoryTrackingTimerPeriodGet: + { + // Get current config + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + TInt time = config.iTimerPeriod.Int(); + TPckgBuf tim(time); + aMessage.WriteL( 0, tim ); + break; + } + + case EMemSpyClientServerOpSystemWideMemoryTrackingCategoriesGet: + { + // Get current config + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + TInt categories = config.iEnabledCategories; + TPckgBuf ret( categories ); + aMessage.WriteL( 0, ret ); + break; + } + + case EMemSpyClientServerOpSystemWideMemoryTrackingThreadNameFilterGet: + { + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + TName threadNameFilter = config.iThreadNameFilter; + TPckgBuf name(threadNameFilter); + aMessage.WriteL( 0, name ); + + break; + } + + case EMemSpyClientServerOpSystemWideMemoryTrackingHeapDumpGet: + { + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + TBool heapDump = config.iDumpData; + TPckgBuf heap(heapDump); + aMessage.WriteL( 0, heap ); + break; + } + + case EMemSpyClientServerOpSystemWideMemoryTrackingModeGet: + { + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + TPckgBuf mod(config.iMode); + aMessage.WriteL(0, mod); + break; + } + + case EMemSpyClientServerOpNotifyDeviceWideOperationProgress: + { + if (!Server().CurrentOperationTracker()) + { + User::Leave(KErrNotReady); + } + + Server().CurrentOperationTracker()->AddNotificationL(aMessage); + break; + } + + case EMemSpyClientServerOpCancelDeviceWideOperation: + if (!Server().CurrentOperationTracker()) + { + User::Leave(KErrNotReady); + } + + Server().CurrentOperationTracker()->Cancel(); + break; + + + case EMemSpyClientServerOpGetEComCategoryCount: + aMessage.WriteL(0, TPckgBuf(iEngine.HelperECom().MdcaCount())); + break; + + + case EMemSpyClientServerOpGetEComCategories: + { + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), iEngine.HelperECom().MdcaCount()); + + for (TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(1, buffer, offset); + } + + a0 = iEngine.HelperECom().MdcaCount(); + aMessage.WriteL(0, a0); + break; + } + + case EMemSpyClientServerOpGetEComInterfaceCount: + { + TPckgBuf a1; + aMessage.ReadL(1, a1); + TInt index = a1().iUid; + + if (index < 0 || index >= iEngine.HelperECom().MdcaCount()) + { + User::Leave(KErrArgument); + } + + aMessage.WriteL(0, TPckgBuf(iEngine.HelperECom().At(index).MdcaCount())); + break; + } + + case EMemSpyClientServerOpGetEComInterfaces: + { + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), iEngine.HelperECom().MdcaCount()); + + TPckgBuf a1; + aMessage.ReadL(1, a1); + TInt categoryIndex = a1().iUid; + + if (categoryIndex < 0 || categoryIndex >= iEngine.HelperECom().MdcaCount()) + { + User::Leave(KErrArgument); + } + + CMemSpyEngineEComCategory &category = iEngine.HelperECom().At(categoryIndex); + + for (TInt i=0, offset = 0; i buffer(data); + aMessage.WriteL(2, buffer, offset); + } + + a0 = realCount; + aMessage.WriteL(0, a0); + + break; + } + + case EMemSpyClientServerOpGetEComImplementationCount: + { + TPckgBuf a1; + aMessage.ReadL(1, a1); + CMemSpyEngineEComInterface* interface = reinterpret_cast(a1().iUid); + + // TODO: check if it really is valid interface + + aMessage.WriteL(0, TPckgBuf(interface->MdcaCount())); + break; + } + + case EMemSpyClientServerOpGetEComImplementations: + { + TPckgBuf a1; + aMessage.ReadL(1, a1); + CMemSpyEngineEComInterface* interface = reinterpret_cast(a1().iUid); + + TPckgBuf a0; + aMessage.ReadL(0, a0); + TInt realCount = Min(a0(), interface->MdcaCount()); + + + for (TInt i=0, offset = 0; iAt(i).Info().DisplayName()); + data.iImplementationUid = interface->At(i).Info().ImplementationUid(); + data.iVersion = interface->At(i).Info().Version(); + data.iDataType.Copy(interface->At(i).Info().DataType()); + data.iOpaqueData.Copy(interface->At(i).Info().OpaqueData()); + data.iDrive = interface->At(i).Info().Drive(); + data.iRomOnly = interface->At(i).Info().RomOnly(); + data.iRomBased = interface->At(i).Info().RomBased(); + data.iVendorId = interface->At(i).Info().VendorId(); + data.iDisabled = interface->At(i).Info().Disabled(); + + TPckgBuf buffer(data); + aMessage.WriteL(2, buffer, offset); + } + + a0 = realCount; + aMessage.WriteL(0, a0); + + break; + } + + } + } + +// --------------------------------------------------------- +// DoCmdServiceL( const RMessage2& aMessage ) +// --------------------------------------------------------- +// +void CMemSpyEngineSession::DoCmdServiceL( const RMessage2& aMessage ) + { + TInt error = KErrNone; + + // Check function attributes + const TInt function = aMessage.Function() & KMemSpyOpFlagsTypeMask; + const TInt argSpec = aMessage.Function() & KMemSpyOpFlagsInclusionMask; + const TBool byThreadId = ( argSpec == KMemSpyOpFlagsIncludesThreadId ); + const TBool byThreadName = ( argSpec == KMemSpyOpFlagsIncludesThreadName ); + + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::DoServiceL() - START - unmodified function: 0x%08x, opCode: %d [TID: %d, TN: %d]", aMessage.Function(), function, byThreadId, byThreadName ) ); + + // Check function is supported and argument combination is valid + error = ValidateFunction( function, byThreadId, byThreadName ); + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::DoServiceL() - validation result: %d", error ) ); + + // Process function request + if ( error == KErrNone ) + { + if ( byThreadId ) + { + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::DoServiceL() - [TID] thread-specific..." ) ); + + const TThreadId threadId( aMessage.Int0() ); + HandleThreadSpecificOpL( function, threadId ); + } + else if ( byThreadName ) + { + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::DoServiceL() - [TN] thread-specific..." ) ); + + error = aMessage.GetDesLength( 0 /*slot 0*/ ); + + if ( error > 0 && error <= KMaxFullName ) + { + TFullName* threadName = new(ELeave) TFullName(); + CleanupStack::PushL( threadName ); + aMessage.ReadL( 0, *threadName ); + HandleThreadSpecificOpL( function, *threadName ); + CleanupStack::PopAndDestroy( threadName ); + } + else + { + error = KErrArgument; + } + } + else + { + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::DoServiceL() - thread-agnostic..." ) ); + + HandleThreadAgnosticOpL( function, aMessage ); + } + } + + User::LeaveIfError( error ); + + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::DoServiceL() - END" ) ); + } + + + +TInt CMemSpyEngineSession::ValidateFunction( TInt aFunction, TBool aIncludesThreadId, TBool aIncludesThreadName ) + { + TInt err = KErrNotSupported; + + // Check the operation is within op-code range + if ( aFunction >= EMemSpyClientServerOpMarkerFirst && aFunction < EMemSpyClientServerOpMarkerLast ) + { + // Check the operation doesn't include unnecessary or not supported information + const TBool includesThreadIdentifier = ( aIncludesThreadId || aIncludesThreadName ); + if ( includesThreadIdentifier && aFunction >= EMemSpyClientServerOpMarkerThreadAgnosticFirst ) + { + // Passing a thread identifier to a thread agnostic operation + err = KErrArgument; + } + else + { + err = KErrNone; + } + } + // + if ( err != KErrNone ) + { + RDebug::Printf( "[MemSpy] CMemSpyEngineSession::ValidateFunction() - function request did not validate - [withId: %d, withName: %d]", aIncludesThreadId, aIncludesThreadName ); + } + // + return err; + } + + +void CMemSpyEngineSession::HandleThreadSpecificOpL( TInt aFunction, const TThreadId& aThreadId ) + { + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - START - aFunction: %d, aThreadId: %d", aFunction, (TUint) aThreadId ) ); + + ASSERT( (TUint) aThreadId != 0 ); + TInt error = KErrNone; + + // Check if its a kernel thread identifier + const TBool isKernel = ( static_cast( aThreadId ) == KMemSpyClientServerThreadIdKernel ); + + // Treat as thread specific operation + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + if ( !isKernel ) + { + error = iEngine.Container().ProcessAndThreadByThreadId( aThreadId, process, thread ); + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - search result: %d, proc: 0x%08x, thread: 0x%08x", error, process, thread ) ); + } + else + { + // Kernel is only supported for a couple of operations + if ( aFunction == EMemSpyClientServerOpHeapInfo || aFunction == EMemSpyClientServerOpHeapData ) + { + } + else + { + TRACE( RDebug::Printf( "[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - trying to call unsupported function for kernel thread!" ) ); + error = KErrArgument; + } + } + + // Must be no error so far and we must have a valid thread & process when performing a non-kernel op + // or then if we are performing a kernel op, we don't need the thread or process. + if ( error == KErrNone && ( ( thread && process && !isKernel ) || ( isKernel ) ) ) + { +#ifdef _DEBUG + if ( thread ) + { + HBufC* threadName = thread->FullName().AllocLC(); + _LIT( KTrace2, "[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - thread: %S" ); + RDebug::Print( KTrace2, threadName ); + CleanupStack::PopAndDestroy( threadName ); + } + else if ( isKernel ) + { + _LIT( KTrace2, "[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - thread: Kernel" ); + RDebug::Print( KTrace2 ); + } +#endif + + // Got a valid thread object - now work out which operation to perform... + switch( aFunction ) + { + case EMemSpyClientServerOpSummaryInfo: + iEngine.HelperProcess().OutputProcessInfoL( *process ); + break; + case EMemSpyClientServerOpSummaryInfoDetailed: + iEngine.HelperProcess().OutputProcessInfoDetailedL( *process ); + break; + case EMemSpyClientServerOpHeapInfo: + if ( isKernel ) + { + iEngine.HelperHeap().OutputHeapInfoKernelL(); + } + else + { + iEngine.HelperHeap().OutputHeapInfoUserL( *thread ); + } + break; + case EMemSpyClientServerOpHeapCellListing: + iEngine.HelperHeap().OutputCellListingUserL( *thread ); + break; + case EMemSpyClientServerOpHeapData: + if ( isKernel ) + { + iEngine.HelperHeap().OutputHeapDataKernelL(); + } + else + { + iEngine.HelperHeap().OutputHeapDataUserL( *thread ); + } + break; + case EMemSpyClientServerOpStackInfo: + iEngine.HelperStack().OutputStackInfoL( *thread ); + break; + case EMemSpyClientServerOpStackDataUser: + iEngine.HelperStack().OutputStackDataL( *thread, EMemSpyDriverDomainUser, EFalse ); + break; + case EMemSpyClientServerOpStackDataKernel: + iEngine.HelperStack().OutputStackDataL( *thread, EMemSpyDriverDomainKernel, EFalse ); + break; + case EMemSpyClientServerOpOpenFiles: + iEngine.HelperFileSystem().ListOpenFilesL( aThreadId ); + break; + + default: + error = KErrNotSupported; + break; + } + } + + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - END - aFunction: %d, aThreadId: %d, error: %d", aFunction, (TUint) aThreadId, error ) ); + User::LeaveIfError( error ); + } + + +void CMemSpyEngineSession::HandleThreadSpecificOpL( TInt aFunction, const TDesC& aThreadName ) + { + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - START - aFunction: %d, aThreadName: %S"), aFunction, &aThreadName ) ); + // + CMemSpyProcess* process = NULL; + CMemSpyThread* thread = NULL; + TInt error = iEngine.Container().ProcessAndThreadByPartialName( aThreadName, process, thread ); + User::LeaveIfError( error ); + // + const TThreadId threadId( thread->Id() ); + HandleThreadSpecificOpL( aFunction, threadId ); + // + TRACE( RDebug::Print( _L("[MemSpy] CMemSpyEngineSession::HandleThreadSpecificOpL() - END - aFunction: %d, aThreadName: %S"), aFunction, &aThreadName ) ); + } + + +void CMemSpyEngineSession::HandleThreadAgnosticOpL( TInt aFunction, const RMessage2& aMessage ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - START" ) ); + + // + if ( aFunction == EMemSpyClientServerOpHeapInfoCompact ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapInfoCompact") ); + if (aMessage.Function() & KMemSpyOpFlagsAsyncOperation) + { + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EEntireDeviceHeapInfoCompact, aMessage); + } + else + { + iEngine.HelperHeap().OutputHeapInfoForDeviceL(); + } + } + else if ( aFunction == EMemSpyClientServerOpStackInfoCompact ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackInfoCompact") ); + if (aMessage.Function() & KMemSpyOpFlagsAsyncOperation) + { + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EEntireDeviceStackInfoCompact, aMessage); + } + else + { + iEngine.HelperStack().OutputStackInfoForDeviceL(); + } + } + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingTimerStart ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingTimerStart") ); + iEngine.HelperSysMemTracker().StartL(); + } + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingTimerStop ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingTimerStop") ); + iEngine.HelperSysMemTracker().StopL(); + } + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingReset ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingReset") ); + iEngine.HelperSysMemTracker().Reset(); + } + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingForceUpdate ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingForceUpdate") ); + iEngine.HelperSysMemTracker().CheckForChangesNowL(); + } + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingTimerPeriodSet ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingTimerPeriodSet") ); + + // Get current config + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + + // Set new timer value + config.iTimerPeriod = aMessage.Int0(); + + // And update config... which will leave if the config is invalid + iEngine.HelperSysMemTracker().SetConfigL( config ); + } + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingCategoriesSet ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingCategoriesSet") ); + // Get current config + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + + // Set new categories + config.iEnabledCategories = aMessage.Int0(); + + // And update config... which will leave if the config is invalid + iEngine.HelperSysMemTracker().SetConfigL( config ); + } + + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingThreadNameFilterSet ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSystemWideMemoryTrackingThreadNameFilterSet") ); + // Get current config + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + + // Set new filter + RBuf buf; + buf.CleanupClosePushL(); + TInt len = aMessage.GetDesLength( 0 ); + if ( len > 0 ) + { + buf.CreateL( len ); + aMessage.ReadL( 0, buf, 0 ); + config.iThreadNameFilter.Copy( buf ); + } + else + { + config.iThreadNameFilter.Zero(); + } + CleanupStack::PopAndDestroy( &buf ); + + // And update config... which will leave if the config is invalid + iEngine.HelperSysMemTracker().SetConfigL( config ); + } + else if ( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingHeapDumpSet ) + { + // Get current config + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + + // Set new Heap Dump value + config.iDumpData = aMessage.Int0(); + + // And update config... which will leave if the config is invalid + iEngine.HelperSysMemTracker().SetConfigL( config ); + } + else if( aFunction == EMemSpyClientServerOpSystemWideMemoryTrackingModeSet) + { + TMemSpyEngineHelperSysMemTrackerConfig config; + iEngine.HelperSysMemTracker().GetConfig( config ); + + TPckgBuf mode; + aMessage.ReadL( 0, mode ); + + config.iMode = mode(); + + // And update config... which will leave if the config is invalid + iEngine.HelperSysMemTracker().SetConfigL( config ); + } + + else if ( aFunction == EMemSpyClientServerOpSwitchOutputSinkTrace ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSwitchOutputSinkTrace") ); + iEngine.InstallDebugSinkL(); + } + else if ( aFunction == EMemSpyClientServerOpSwitchOutputSinkFile ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSwitchOutputSinkFile") ); + // Read file name from message. + TFileName fileName; + RBuf buf; + buf.CleanupClosePushL(); + + TInt len = aMessage.GetDesLength( 0 ); + if ( len > 0 ) + { + buf.CreateL( len ); + aMessage.ReadL( 0, buf, 0 ); + + iEngine.InstallFileSinkL( buf ); + } + else + { + iEngine.InstallFileSinkL( KNullDesC ); + } + + CleanupStack::PopAndDestroy( &buf ); + + } + else if ( aFunction == EMemSpyClientServerOpEnumerateKernelContainer ) + { + const TMemSpyDriverContainerType type = CMemSpyEngineHelperKernelContainers::MapToType( static_cast< TObjectType >( aMessage.Int0() ) ); + + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpEnumerateKernelContainer - type: %d", type ) ); + + CMemSpyEngineGenericKernelObjectList* model = iEngine.HelperKernelContainers().ObjectsForSpecificContainerL( type ); + CleanupStack::PushL( model ); + model->OutputL( iEngine.Sink() ); + CleanupStack::PopAndDestroy( model ); + } + else if ( aFunction == EMemSpyClientServerOpEnumerateKernelContainerAll ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpEnumerateKernelContainerAll") ); + CMemSpyEngineGenericKernelObjectContainer* model = iEngine.HelperKernelContainers().ObjectsAllL(); + CleanupStack::PushL( model ); + model->OutputL( iEngine.Sink() ); + CleanupStack::PopAndDestroy( model ); + } + else if ( aFunction == EMemSpyClientServerOpOpenFiles ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpOpenFiles") ); + iEngine.ListOpenFilesL(); + } + else if ( aFunction == EMemSpyClientServerOpDisableAknIconCache ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpDisableAknIconCache") ); + iEngine.HelperRAM().SetAknIconCacheStatusL( EFalse ); + } + else if ( aFunction == EMemSpyClientServerOpSummaryInfo ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSummaryInfo") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityGeneralSummary, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpSummaryInfoDetailed ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpSummaryInfoDetailed") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityGeneralDetailed, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpHeapInfo ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapInfo") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityHeapInfo, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpHeapCellListing ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapCellListing") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityHeapCellListing, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpHeapData ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpHeapData") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityHeapData, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpStackInfo ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackInfo") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityStackInfo, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpStackDataUser ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackDataUser") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityStackDataUser, aMessage); + } + else if ( aFunction == EMemSpyClientServerOpStackDataKernel ) + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - EMemSpyClientServerOpStackDataKernel") ); + StartDeviceWideOperationL(CMemSpyDeviceWideOperations::EPerEntityStackDataKernel, aMessage); + } + else + { + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - [device-wide operation] => invoking UI") ); + iEngine.NotifyClientServerOperationRequestL( aFunction ); + } + // + TRACE( RDebug::Printf("[MemSpy] CMemSpyEngineSession::HandleThreadAgnosticOpL() - END" ) ); + } + +void CMemSpyEngineSession::StartDeviceWideOperationL(CMemSpyDeviceWideOperations::TOperation aOperation, const RMessage2& aMessage) + { + if (Server().CurrentOperationTracker()) + { + User::Leave(KErrInUse); + } + + Server().SetCurrentOperationTracker(CMemSpyDwOperationTracker::NewL(aOperation, aMessage, Server())); + } + + + + + + + + + +CMemSpyDwOperationTracker* CMemSpyDwOperationTracker::NewL(CMemSpyDeviceWideOperations::TOperation aOperation, + const RMessage2& aOperationMessage, CMemSpyEngineServer& aServer) + { + CMemSpyDwOperationTracker* self = new (ELeave) CMemSpyDwOperationTracker(aOperationMessage, aServer); + CleanupStack::PushL( self ); + self->ConstructL(aOperation); + CleanupStack::Pop( self ); + return self; + } + +CMemSpyDwOperationTracker::~CMemSpyDwOperationTracker() + { + delete iOperation; + delete iPendingNotifications; + } + +CMemSpyDwOperationTracker::CMemSpyDwOperationTracker(const RMessage2& aOperationMessage, CMemSpyEngineServer& aServer) : + iOperationMessage(aOperationMessage), + iServer(aServer), + iPendingNotifications(0), + iOperation(0), + iProgress(0) + { + } + + +void CMemSpyDwOperationTracker::ConstructL(CMemSpyDeviceWideOperations::TOperation aOperation) + { + iPendingNotifications = new (ELeave) CArrayFixFlat(3); + iOperation = CMemSpyDeviceWideOperations::NewL(iServer.Engine(), *this, aOperation); + } + +void CMemSpyDwOperationTracker::AddNotificationL(const RMessage2& aMessage) + { + iPendingNotifications->AppendL(aMessage); + } + +void CMemSpyDwOperationTracker::Cancel() + { + iOperation->Cancel(); + } + +void CMemSpyDwOperationTracker::HandleDeviceWideOperationEvent(TEvent aEvent, TInt aParam1, const TDesC& aParam2) + { + switch( aEvent ) + { + case MMemSpyDeviceWideOperationsObserver::EOperationCompleted: + case MMemSpyDeviceWideOperationsObserver::EOperationCancelled: + iServer.SetCurrentOperationTracker(0); + + for (TInt i=0; iCount(); i++) + { + iPendingNotifications->At(i).Complete(KErrCancel); + } + + if (iOperationMessage.Function() & KMemSpyOpFlagsAsyncOperation) + { + iOperationMessage.Complete( + aEvent == MMemSpyDeviceWideOperationsObserver::EOperationCompleted ? KErrNone : KErrCancel); + } + + iPendingNotifications->Reset(); + + delete this; + break; + + case MMemSpyDeviceWideOperationsObserver::EOperationProgressEnd: + { + iProgress += aParam1; + for (TInt i=0; iCount(); i++) + { + TInt err; + TRAP(err, iPendingNotifications->At(i).WriteL(0, TPckgBuf( iProgress * 100 / iOperation->TotalOperationSize() ))); + TRAP(err, iPendingNotifications->At(i).WriteL(1, aParam2)); + if (err != KErrNone) + { + // TODO: iPendingProgressNotifications->At(i).Panic() + } + iPendingNotifications->At(i).Complete(KErrNone); + } + iPendingNotifications->Reset(); + break; + } + + } + + }