memspy/Engine/Source/Helpers/MemSpyEngineHelperFbServ.cpp
changeset 51 98307c651589
parent 42 0ff24a8f6ca2
child 52 c2f44e33b468
equal deleted inserted replaced
42:0ff24a8f6ca2 51:98307c651589
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <memspy/engine/memspyenginehelperfbserv.h>
       
    19 
       
    20 // System includes
       
    21 #include <s32mem.h>
       
    22 #include <f32file.h>
       
    23 #include <e32rom.h>
       
    24 
       
    25 // Driver includes
       
    26 #include <memspy/driver/memspydriverclient.h>
       
    27 
       
    28 // User includes
       
    29 #include <memspy/engine/memspyengine.h>
       
    30 #include <memspy/engine/memspyengineutils.h>
       
    31 #include <memspy/engine/memspyengineoutputsink.h>
       
    32 #include <memspy/engine/memspyengineobjectprocess.h>
       
    33 #include <memspy/engine/memspyengineobjectthread.h>
       
    34 #include <memspy/engine/memspyengineobjectcontainer.h>
       
    35 
       
    36 // Literal constants
       
    37 _LIT( KMemSpyEngineFBServComma, ", " );
       
    38 _LIT( KMemSpyEngineFBServExportFileName, "Image_%08x_%02d_bpp_(%d x %d).bmp");
       
    39 _LIT( KMemSpyEngineFBSLargeChunkName, "FbsLargeChunk" );
       
    40 _LIT( KMemSpyEngineFBSSharedChunkName, "FbsSharedChunk" );
       
    41 
       
    42 
       
    43 CMemSpyEngineHelperFbServ::CMemSpyEngineHelperFbServ( CMemSpyEngine& aEngine )
       
    44 :   iEngine( aEngine )
       
    45     {
       
    46     }
       
    47 
       
    48 
       
    49 CMemSpyEngineHelperFbServ::~CMemSpyEngineHelperFbServ()
       
    50     {
       
    51     iEngine.Driver().WalkHeapClose();
       
    52     }
       
    53 
       
    54 
       
    55 void CMemSpyEngineHelperFbServ::ConstructL()
       
    56     {
       
    57     }
       
    58 
       
    59 
       
    60 CMemSpyEngineHelperFbServ* CMemSpyEngineHelperFbServ::NewL( CMemSpyEngine& aEngine )
       
    61     {
       
    62     CMemSpyEngineHelperFbServ* self = new(ELeave) CMemSpyEngineHelperFbServ( aEngine );
       
    63     CleanupStack::PushL( self );
       
    64     self->ConstructL();
       
    65     CleanupStack::Pop( self );
       
    66     return self;
       
    67     }
       
    68 
       
    69 
       
    70 TBool CMemSpyEngineHelperFbServ::IsLargeBitmapChunk( const TMemSpyDriverChunkInfo& aChunkInfo )
       
    71     {
       
    72     TBool ret = EFalse;
       
    73     //
       
    74     if  ( aChunkInfo.iType == EMemSpyDriverChunkTypeGlobal )
       
    75         {
       
    76         ret = ( aChunkInfo.iName.FindF( KMemSpyEngineFBSLargeChunkName ) >= 0 );
       
    77         }
       
    78     //
       
    79     return ret;
       
    80     }
       
    81 
       
    82 
       
    83 TBool CMemSpyEngineHelperFbServ::IsSharedBitmapChunk( const TMemSpyDriverChunkInfo& aChunkInfo )
       
    84     {
       
    85     TBool ret = EFalse;
       
    86     //
       
    87     if  ( aChunkInfo.iType == EMemSpyDriverChunkTypeGlobal )
       
    88         {
       
    89         ret = ( aChunkInfo.iName.FindF( KMemSpyEngineFBSSharedChunkName ) >= 0 );
       
    90         }
       
    91     //
       
    92     return ret;
       
    93     }
       
    94 
       
    95 
       
    96 EXPORT_C void CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL( RArray<TInt>& aHandles )
       
    97     {
       
    98     TInt fontConCount = 0;
       
    99     TInt bitmapConCount =0;
       
   100     //RArray<TInt> dirtyHandles;
       
   101     //CleanupClosePushL( dirtyHandles );
       
   102     GetArrayOfBitmapHandlesL( aHandles, bitmapConCount, fontConCount );
       
   103     //CleanupStack::PopAndDestroy( &dirtyHandles );
       
   104     }
       
   105 
       
   106 
       
   107 void CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL( RArray<TInt>& aHandles, TInt& aBitmapConCount, TInt& aFontConCount )
       
   108     {
       
   109     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - START") );
       
   110     CMemSpyThread& fbServThread = IdentifyFbServThreadL();
       
   111 
       
   112     // Suspend the process
       
   113     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - got FBServ thread, suspending it..."));
       
   114     iEngine.ProcessSuspendLC( fbServThread.Process().Id() );
       
   115 
       
   116     // Get the heap cell data for the correct object (CFbTop)
       
   117     TAny* cellAddress = NULL;
       
   118     HBufC8* cellData = LocateCFbTopHeapCellDataLC( fbServThread, cellAddress );
       
   119     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - got CFbTop cell data: %d bytes", cellData->Length()));
       
   120 
       
   121     // Work out the offset to the bitmap address handles array
       
   122     const TUint offsetBitmapCon = OffsetToCObjectConBitmapCon();
       
   123     const TUint offsetFontCon = OffsetToCObjectConFontCon();
       
   124     const TUint offsetHandleArray = OffsetToBitmapHandleArray();
       
   125     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - offsetBitmapCon:   %d", offsetBitmapCon ));
       
   126     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - offsetFontCon:     %d", offsetFontCon ));
       
   127     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - offsetHandleArray: %d", offsetHandleArray ));
       
   128 
       
   129     // Create stream for reading heap data (makes life a bit easier).
       
   130     RDesReadStream stream( *cellData );
       
   131     CleanupClosePushL( stream );
       
   132     
       
   133     // We need to skip over the preamble to the start of the actual data.
       
   134     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - skipping %d bytes [to start of bitmap con]...", offsetBitmapCon ));
       
   135     (void) stream.ReadL( offsetBitmapCon ); // skip this much
       
   136 
       
   137     // Read CFbTop::iBitmapCon cell address
       
   138     TAny* cellAddresBitmapCon = reinterpret_cast<TAny*>( stream.ReadUint32L() );
       
   139     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - cellAddresBitmapCon: 0x%08x", cellAddresBitmapCon ));
       
   140     TInt bitmapConAllocated = 0;
       
   141     RArray<TAny*> bitmapConAddresses;
       
   142     CleanupClosePushL( bitmapConAddresses );
       
   143     ReadCObjectConInfoL( cellAddresBitmapCon, bitmapConAddresses, aBitmapConCount, bitmapConAllocated );
       
   144     CleanupStack::PopAndDestroy( &bitmapConAddresses );
       
   145 
       
   146     // Read CFbTop::iFontCon cell address
       
   147     TAny* cellAddresFontCon = reinterpret_cast<TAny*>( stream.ReadUint32L() );
       
   148     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - cellAddresFontCon: 0x%08x", cellAddresFontCon ));
       
   149     TInt fontConAllocated = 0;
       
   150     RArray<TAny*> fontConAddresses;
       
   151     CleanupClosePushL( fontConAddresses );
       
   152     ReadCObjectConInfoL( cellAddresFontCon, fontConAddresses, aFontConCount, fontConAllocated );
       
   153     CleanupStack::PopAndDestroy( &fontConAddresses );
       
   154 
       
   155     // Skip forwards to the bitmap handle array info
       
   156     const TUint skipRemaining = ( offsetHandleArray - offsetFontCon );
       
   157     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - skipRemaining: %d", skipRemaining ));
       
   158     (void) stream.ReadL( skipRemaining ); // skip this much
       
   159 
       
   160     // The layout of RPointerArrayBase is as follows:
       
   161     //
       
   162     //  TInt iCount;
       
   163 	//  TAny** iEntries;
       
   164 	//  TInt iAllocated;
       
   165 	//  TInt iGranularity;
       
   166 	//  TInt iSpare1;
       
   167 	//  TInt iSpare2;
       
   168 
       
   169     // Now read the next 4 bytes. This is the number of allocated array entries.
       
   170     const TInt arrayEntryCount = stream.ReadInt32L();
       
   171     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - arrayEntryCount: %d", arrayEntryCount ));
       
   172 
       
   173     // The next four bytes are the address of the cell we are interested in.
       
   174     cellAddress = reinterpret_cast<TAny*>( stream.ReadUint32L() );
       
   175     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - cellAddress: 0x%08x", cellAddress ));
       
   176     
       
   177     // The next four bytes are the allocated count
       
   178     const TInt arrayAlloctedCount = stream.ReadInt32L();
       
   179     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - arrayAlloctedCount: %d", arrayAlloctedCount ));
       
   180     
       
   181     // Validate
       
   182     if  ( arrayEntryCount > arrayAlloctedCount || arrayEntryCount < 0 || arrayAlloctedCount < 0 )
       
   183         {
       
   184         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - invalid array details => Leave with KErrCorrupt"));
       
   185         User::Leave( KErrCorrupt );
       
   186         }
       
   187     
       
   188     // Clean up - don't need this data anymore. Real data is in another cell
       
   189     CleanupStack::PopAndDestroy( 2, cellData );  // stream & cellData
       
   190 
       
   191     // Now obtain the heap cell data for the actual array itself.
       
   192     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - trying to find bitmap array data..."));
       
   193     cellData = LocateBitmapArrayHeapCellDataLC( cellAddress, arrayAlloctedCount );
       
   194     
       
   195     // Parse the cell data in order to obtain the bitmap handles.
       
   196     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - trying to extract bitmap handles..."));
       
   197     ParseCellDataAndExtractHandlesL( *cellData, aHandles, arrayEntryCount );
       
   198     
       
   199     // Tidy up
       
   200     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - resuming process..."));
       
   201     CleanupStack::PopAndDestroy( cellData );
       
   202  
       
   203     // Close heap walker & resume process
       
   204     iEngine.Driver().WalkHeapClose();
       
   205     CleanupStack::PopAndDestroy();
       
   206     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetArrayOfBitmapHandlesL() - END"));
       
   207     }
       
   208 
       
   209 
       
   210 void CMemSpyEngineHelperFbServ::GetBitmapInfoL( TInt aHandle, TMemSpyEngineFBServBitmapInfo& aInfo )
       
   211     {
       
   212     CFbsBitmap* bitmap = GetBitmapInfoLC( aHandle, aInfo );
       
   213     CleanupStack::PopAndDestroy( bitmap );
       
   214     }
       
   215  
       
   216 
       
   217 CFbsBitmap* CMemSpyEngineHelperFbServ::GetBitmapInfoLC( TInt aHandle, TMemSpyEngineFBServBitmapInfo& aInfo )
       
   218     {
       
   219     CFbsBitmap* bitmap = new(ELeave) CFbsBitmap();
       
   220     CleanupStack::PushL( bitmap );
       
   221     const TInt error = bitmap->Duplicate( aHandle );
       
   222     User::LeaveIfError( error );
       
   223 
       
   224     // Basic info from bitmap itself
       
   225     aInfo.iHandle = aHandle;
       
   226     aInfo.iDisplayMode = bitmap->DisplayMode();
       
   227 
       
   228     // Extended info comes from header
       
   229     const SEpocBitmapHeader header( bitmap->Header() );
       
   230     
       
   231     aInfo.iSizeInPixels = header.iSizeInPixels;
       
   232     aInfo.iCompressionType = header.iCompression;
       
   233     aInfo.iColor = header.iColor;
       
   234     aInfo.iBitsPerPixel = header.iBitsPerPixel;
       
   235     aInfo.iSizeInBytes = header.iBitmapSize;
       
   236 
       
   237     // Flags
       
   238     aInfo.iFlags = TMemSpyEngineFBServBitmapInfo::EFlagsNone;
       
   239     if  ( bitmap->IsRomBitmap() )
       
   240         {
       
   241         aInfo.iFlags |= TMemSpyEngineFBServBitmapInfo::EFlagsIsRomBitmap;
       
   242         }
       
   243      if  ( bitmap->IsLargeBitmap() )
       
   244         {
       
   245         aInfo.iFlags |= TMemSpyEngineFBServBitmapInfo::EFlagsIsLarge;
       
   246         }
       
   247     if  ( bitmap->IsCompressedInRAM() )
       
   248         {
       
   249         aInfo.iFlags |= TMemSpyEngineFBServBitmapInfo::EFlagsIsCompressedInRam;
       
   250         }
       
   251     else
       
   252         {
       
   253         // Can only do this if not compressed
       
   254         if  ( bitmap->IsMonochrome() )
       
   255              {
       
   256              aInfo.iFlags |= TMemSpyEngineFBServBitmapInfo::EFlagsIsMonochrome;
       
   257              }
       
   258         }
       
   259  
       
   260     return bitmap;
       
   261     }
       
   262 
       
   263 
       
   264 CMemSpyThread& CMemSpyEngineHelperFbServ::IdentifyFbServThreadL()
       
   265     {
       
   266     _LIT(KFbServThreadName, "FbServ::!Fontbitmapserver");
       
   267     //
       
   268     CMemSpyThread* thread = NULL;
       
   269     CMemSpyProcess* process = NULL;
       
   270 
       
   271     // Get the fbserv thread object
       
   272     CMemSpyEngineObjectContainer& container = iEngine.Container();
       
   273     User::LeaveIfError( container.ProcessAndThreadByFullName( KFbServThreadName, process, thread ) );
       
   274     //
       
   275     return *thread;
       
   276     }
       
   277 
       
   278 
       
   279 HBufC8* CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC( CMemSpyThread& aFbServThread, TAny*& aCellAddress )
       
   280     {
       
   281     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - START"));
       
   282 
       
   283     // We'll start looking for the CFbTop object at cell index 0, then we'll
       
   284     // continue to a maximum of cell index 10. These are not actual allocation
       
   285     // numbers, they are just cell indicies within FBServ's heap.
       
   286     // Realistically, the cell should be the 7th.
       
   287     const TInt KFbServWillingToStartAtCellIndex = 0;
       
   288     const TInt KFbServWillingToSearchUntilCellIndex = 10;
       
   289 
       
   290     // We know the size of the cell is pretty big, since it contains a large 
       
   291     // hash-map object (4096 elements by default, 4 bytes big => 16k). We'll
       
   292     // not try to retrieve more than 18k of data.
       
   293     const TInt KFbServExpectedMinimumCellSize = 14*1024;
       
   294     const TInt KFbServExpectedMaximumCellSize = 18*1024;
       
   295 
       
   296     // This is what we'll return, if we find it...
       
   297     aCellAddress = NULL;
       
   298     HBufC8* heapCellData = NULL;
       
   299 
       
   300     // Get the heap info - we need this for verification purposes
       
   301     TMemSpyHeapInfo info;
       
   302     TInt err = iEngine.Driver().GetHeapInfoUser( info, aFbServThread.Id() );
       
   303     if ( err == KErrNone && info.Type() == TMemSpyHeapInfo::ETypeUnknown )
       
   304         {
       
   305         err = KErrNotSupported;
       
   306         }
       
   307     User::LeaveIfError( err );
       
   308 
       
   309     // Now walk the heap!
       
   310     err = iEngine.Driver().WalkHeapInit( aFbServThread.Id() );
       
   311     if  ( err == KErrNone )
       
   312         {
       
   313         TMemSpyDriverCellType cellType;
       
   314         TAny* cellAddress;
       
   315         TInt cellLength;
       
   316         TInt cellNestingLevel;
       
   317         TInt cellAllocationNumber;
       
   318         TInt cellHeaderSize;
       
   319         TAny* cellPayloadAddress;
       
   320         //
       
   321         for( TInt cellIndex = KFbServWillingToStartAtCellIndex; err == KErrNone && cellIndex < KFbServWillingToSearchUntilCellIndex; cellIndex++ )
       
   322             {
       
   323             err = iEngine.Driver().WalkHeapNextCell( aFbServThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   324             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - cellIndex[%d] err: %d, cellLength: %d, cellAllocationNumber: %d, cellType: %d", cellIndex, err, cellLength, cellAllocationNumber, cellType));
       
   325 
       
   326             if  ( err == KErrNone && (cellType & EMemSpyDriverAllocatedCellMask))
       
   327                 {
       
   328                 // We know we are looking for a relatively large *allocated* cell.
       
   329                 if  ( cellLength >= KFbServExpectedMinimumCellSize && cellLength <= KFbServExpectedMaximumCellSize )
       
   330                     {
       
   331                     const TInt payloadLength = cellLength;
       
   332 
       
   333                     // This is *probably* the right cell. Let's get the data and check.
       
   334                     HBufC8* data = HBufC8::NewLC( payloadLength );
       
   335                     TPtr8 pData( data->Des() );
       
   336                     //
       
   337                     err = iEngine.Driver().WalkHeapReadCellData( cellAddress, pData, payloadLength );
       
   338                     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - data fetch returned error: %d", err));
       
   339 
       
   340                     if  ( err == KErrNone )
       
   341                         {
       
   342                         //_LIT(KHeapDumpDataFormat, "%S");
       
   343                         //iEngine.Sink().OutputBinaryDataL( KHeapDumpDataFormat, pData.Ptr(), (const TUint8*) cellAddress, pData.Length() );
       
   344                     
       
   345                         // Check the data
       
   346                         const TUint heapMaxSize = info.AsRHeap().MetaData().iMaxHeapSize;
       
   347                         const TUint heapBaseAddress = (TUint) info.AsRHeap().MetaData().ChunkBaseAddress();
       
   348                         const TBool correctHeapCellLocated = VerifyCorrectHeapCellL( *data, cellAddress, cellPayloadAddress, heapBaseAddress, heapMaxSize );
       
   349                         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - verified: %d", correctHeapCellLocated));
       
   350 
       
   351                         if  ( correctHeapCellLocated )
       
   352                             {
       
   353                             aCellAddress = cellAddress;
       
   354                             heapCellData = data;
       
   355                             CleanupStack::Pop( data );
       
   356                             break;
       
   357                             }
       
   358                         else
       
   359                             {
       
   360                             // Not the right cell. Keep going...
       
   361                             CleanupStack::PopAndDestroy( data );
       
   362                             }
       
   363                         }
       
   364                     }
       
   365                 }
       
   366             }
       
   367 
       
   368         // NB: don't do this here - 
       
   369         // iEngine.Driver().WalkHeapClose();
       
   370         // It gets done after all reading is complete
       
   371         }
       
   372 
       
   373     if  ( heapCellData == NULL )
       
   374         {
       
   375         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - END - didn't find the right cell => KErrNotFound"));
       
   376         User::Leave( KErrNotFound );
       
   377         }
       
   378     //
       
   379     CleanupStack::PushL( heapCellData );
       
   380 
       
   381     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - END - everything okay, cell is: 0x%08x", aCellAddress));
       
   382     return heapCellData;
       
   383     }
       
   384 
       
   385 
       
   386 void CMemSpyEngineHelperFbServ::ReadCObjectConInfoL( TAny* aCellAddress, RArray<TAny*>& aContainerObjects, TInt& aCount, TInt& aAllocated )
       
   387     {
       
   388     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - START - trying cell: 0x%08x", aCellAddress ));
       
   389 
       
   390     // What we will return
       
   391     HBufC8* cellData = NULL;
       
   392     
       
   393     // Try to get info about real cell
       
   394     TMemSpyDriverCellType cellType;
       
   395     TInt cellLength;
       
   396     TInt cellNestingLevel;
       
   397     TInt cellAllocationNumber;
       
   398     TInt cellHeaderSize;
       
   399     TAny* cellPayloadAddress;
       
   400 
       
   401     // NOTE: this call may change the value of 'cellAddress'
       
   402     TInt err = iEngine.Driver().WalkHeapGetCellInfo( aCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   403     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - err: %d, cellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aCellAddress, cellLength, cellAllocationNumber, cellType));
       
   404 
       
   405 	if (err == KErrNone && (cellType & EMemSpyDriverAllocatedCellMask))
       
   406         {
       
   407         // Check that the cell size meets our expectations - it should be a CObjectCon cell.
       
   408         const TInt expectedCellSize = sizeof(CObjectCon*) + cellHeaderSize;
       
   409         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - expectedCellSize: %d, actual: %d, address: 0x%08x", expectedCellSize, cellLength, aCellAddress));
       
   410 
       
   411         if  ( expectedCellSize <= cellLength )
       
   412             {
       
   413             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - cell lengths are good, trying to get cell data..."));
       
   414 
       
   415             // Try to get real cell data        
       
   416             cellData = HBufC8::NewLC( cellLength );
       
   417             TPtr8 pData( cellData->Des() );
       
   418             //
       
   419             err = iEngine.Driver().WalkHeapReadCellData( aCellAddress, pData, cellLength );
       
   420             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - reading cell data returned error: %d", err));
       
   421             }
       
   422         else
       
   423             {
       
   424             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - not enough data -> KErrCorrupt"));
       
   425             err = KErrCorrupt;
       
   426             }
       
   427         }
       
   428     else
       
   429         {
       
   430         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - END - didn't find cell data => KErrNotFound"));
       
   431         User::Leave( KErrNotFound );
       
   432         }
       
   433 
       
   434     CObjectCon* con = CObjectCon::NewL();
       
   435     const TUint32 KExpectedObjectConVTable = *((TUint32*) con);
       
   436     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - KExpectedObjectConVTable: 0x%08x", KExpectedObjectConVTable ));
       
   437     delete con;
       
   438 
       
   439     // We should have the valid CObjectCon data now.
       
   440     RDesReadStream stream( *cellData );
       
   441     CleanupClosePushL( stream );
       
   442     
       
   443     // Read vtable
       
   444     const TUint32 vTable = stream.ReadUint32L();
       
   445     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - actual vTable: 0x%08x", vTable ));
       
   446     if  ( vTable != KExpectedObjectConVTable )
       
   447         {
       
   448         User::Leave( KErrNotFound );
       
   449         }
       
   450 
       
   451     const TInt uniqueId = stream.ReadInt32L();
       
   452     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - uniqueId: %d", uniqueId ));
       
   453 
       
   454     aCount = stream.ReadInt32L();
       
   455     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - aCount: %d", aCount ));
       
   456 
       
   457     aAllocated = stream.ReadInt32L();
       
   458     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - aAllocated: %d", aAllocated ));
       
   459 
       
   460     // This is actually CObject's iObject, i.e. CObject** iObjects.
       
   461     TAny* pObjects = reinterpret_cast< TAny*>( stream.ReadUint32L() );
       
   462     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - pObjects: 0x%08x", pObjects ));
       
   463 
       
   464     CleanupStack::PopAndDestroy( 2, cellData ); // cellData & stream
       
   465 
       
   466     // Now fetch the cell containing the CObject pointers...
       
   467     err = iEngine.Driver().WalkHeapGetCellInfo( pObjects, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   468     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - array of CObject* cell fetch err: %d, cellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aCellAddress, cellLength, cellAllocationNumber, cellType));
       
   469     User::LeaveIfError( err );
       
   470 
       
   471     const TInt expectedSize = ( aAllocated * sizeof(CObject*) ) + cellHeaderSize;
       
   472     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - expectedSize: %d, actual size: %d", expectedSize, cellLength ));
       
   473     if  ( cellLength < expectedSize )
       
   474         {
       
   475         User::Leave( KErrUnderflow );
       
   476         }
       
   477     
       
   478     // Get the data
       
   479     cellData = HBufC8::NewLC( cellLength );
       
   480     TPtr8 pData( cellData->Des() );
       
   481     err = iEngine.Driver().WalkHeapReadCellData( pObjects, pData, cellLength );
       
   482     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - reading cell data returned error: %d", err));
       
   483     User::LeaveIfError( err );
       
   484 
       
   485     // Open stream
       
   486     stream.Open( *cellData );
       
   487     CleanupClosePushL( stream );
       
   488 
       
   489     // Extract array of pointers
       
   490     for( TInt i=0; i<aCount; i++ )
       
   491         {
       
   492         TAny* objectAddress = reinterpret_cast< TAny*>( stream.ReadUint32L() );
       
   493         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - object[%04d]: 0x%08x", i, objectAddress ));
       
   494         aContainerObjects.AppendL( objectAddress );
       
   495         }
       
   496     CleanupStack::PopAndDestroy( 2, cellData ); // cellData & stream
       
   497 
       
   498     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - END" ));
       
   499     }
       
   500 
       
   501 
       
   502 HBufC8* CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC( TAny*& aArrayCellAddress, TInt aArrayAllocCount )
       
   503     {
       
   504     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - START - trying cell: 0x%08x, aArrayAllocCount: %d", aArrayCellAddress, aArrayAllocCount));
       
   505 
       
   506     // What we will return
       
   507     HBufC8* cellData = NULL;
       
   508     
       
   509     // Try to get info about real cell
       
   510     TMemSpyDriverCellType cellType;
       
   511     TInt cellLength;
       
   512     TInt cellNestingLevel;
       
   513     TInt cellAllocationNumber;
       
   514     TInt cellHeaderSize;
       
   515     TAny* cellPayloadAddress;
       
   516 
       
   517     // NOTE: this call may change the value of 'cellAddress'
       
   518     TInt err = iEngine.Driver().WalkHeapGetCellInfo( aArrayCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   519     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - err: %d, cellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aArrayCellAddress, cellLength, cellAllocationNumber, cellType));
       
   520 
       
   521     if (err == KErrNone && (cellType & EMemSpyDriverAllocatedCellMask))
       
   522         {
       
   523         // Check that the cell size meets our expectations. 
       
   524         // The cell should be a very specific length
       
   525         const TInt expectedCellSize = (sizeof(CBase*) * aArrayAllocCount) + cellHeaderSize;
       
   526         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - expectedCellSize: %d, actual: %d, address: 0x%08x", expectedCellSize, cellLength, aArrayCellAddress));
       
   527 
       
   528         if  ( expectedCellSize <= cellLength )
       
   529             {
       
   530             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - cell lengths are good, trying to get cell data..."));
       
   531 
       
   532             // Try to get real cell data        
       
   533             cellData = HBufC8::NewLC( cellLength );
       
   534             TPtr8 pData( cellData->Des() );
       
   535             //
       
   536             err = iEngine.Driver().WalkHeapReadCellData( aArrayCellAddress, pData, cellLength );
       
   537             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - reading cell data returned error: %d", err));
       
   538             }
       
   539         else
       
   540             {
       
   541             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - not enough data -> KErrCorrupt"));
       
   542             err = KErrCorrupt;
       
   543             }
       
   544         }
       
   545     //
       
   546     if  ( cellData == NULL )
       
   547         {
       
   548         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - END - didn't find cell data => KErrNotFound"));
       
   549         err = KErrNotFound;
       
   550         }
       
   551     User::LeaveIfError( err );
       
   552     //
       
   553     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - END - ok! - got %d bytes", cellData->Length() ) );
       
   554     return cellData;
       
   555     }
       
   556 
       
   557 
       
   558 void CMemSpyEngineHelperFbServ::ParseCellDataAndExtractHandlesL( const TDesC8& aData, RArray<TInt>& aHandles, TInt aArrayEntryCount )
       
   559     {
       
   560     aHandles.Reset();
       
   561     
       
   562     // Create read stream
       
   563     RDesReadStream stream( aData );
       
   564     CleanupClosePushL( stream );
       
   565     
       
   566     for( TInt i=0; i<aArrayEntryCount; i++ )
       
   567         {
       
   568         const TInt handle = stream.ReadInt32L();
       
   569         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ParseCellDataAndExtractHandlesL() - handle[%4d] = 0x%08x", i, handle));
       
   570         aHandles.AppendL( handle );
       
   571         }
       
   572     
       
   573     // Tidy up
       
   574     CleanupStack::PopAndDestroy( &stream );
       
   575     }
       
   576 
       
   577 
       
   578 TBool CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL( const TDesC8& aData, TAny* aCellAddress, TAny* aPayloadAddress, TUint aHeapStartingAddress, TUint aHeapMaxSize )
       
   579     {
       
   580     (void) aPayloadAddress;
       
   581     (void) aCellAddress;
       
   582     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - START - aDataLen: %d, aCellAddress: 0x%08x, aPayloadAddress: 0x%08x, aHeapStartingAddress: 0x%08x, aHeapSize: %d", aData.Length(), aCellAddress, aPayloadAddress, aHeapStartingAddress, aHeapMaxSize ));
       
   583 
       
   584     const TUint KFbServHeapCeilingAddress = aHeapStartingAddress + aHeapMaxSize;
       
   585 
       
   586     // Whether we can use this cell's data...
       
   587     TBool correctCell = EFalse;
       
   588 
       
   589     // We can use certain knowledge of the layout of the cell to work out
       
   590     // if we've found the right one. 
       
   591     // 
       
   592     // This is fragile because of the font and bitmap server heap layout changes 
       
   593     // significantly, then this can break.
       
   594     RDesReadStream reader( aData );
       
   595     CleanupClosePushL( reader );
       
   596 
       
   597     // Get vtable address
       
   598     TUint address = reader.ReadUint32L();
       
   599     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - suspected vtable: 0x%08x", address));
       
   600 
       
   601 #ifdef __EPOC32__
       
   602     TBool isROMAddress = EFalse;
       
   603     TInt err = User::IsRomAddress( isROMAddress, (TAny*) address );
       
   604     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - vtable (0x%08x) is in ROM: %d (error: %d)", address, isROMAddress, err));
       
   605     User::LeaveIfError( err );
       
   606 
       
   607     if  ( !isROMAddress )
       
   608         {
       
   609         // Close stream
       
   610         CleanupStack::PopAndDestroy( &reader );
       
   611 
       
   612         // VTable value should be in the ROM range.
       
   613         correctCell = EFalse;
       
   614         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - END - suspected CFbTop vTable isn't in ROM address range! - correctCell: %d", correctCell));
       
   615         return correctCell;
       
   616         }
       
   617 #else
       
   618     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - skipping vtable: 0x%08x", address));
       
   619 #endif
       
   620 
       
   621     // First real item is an RFs object instance. We can't check this
       
   622     // very easily because its an embedded object-> We must skip it
       
   623     __ASSERT_ALWAYS( sizeof(RFs) == 4, User::Invariant() );
       
   624     address = reader.ReadUint32L();
       
   625     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - skipping RFs: 0x%08x", address));
       
   626 
       
   627     // Next object is an address (CFontStore* iFontStore). We can validate this against
       
   628     // the method arguments.
       
   629     address = reader.ReadUint32L();
       
   630     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iFontStore: 0x%08x", address));
       
   631 
       
   632     if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   633         {
       
   634         // Next comes another pointer (CObjectCon* iBitmapCon)
       
   635         address = reader.ReadUint32L();
       
   636         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iBitmapCon: 0x%08x", address));
       
   637 
       
   638         if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   639             {
       
   640             // Next another pointer (CObjectCon* iFontCon)
       
   641             address = reader.ReadUint32L();
       
   642             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iFontCon: 0x%08x", address));
       
   643 
       
   644             if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   645                 {
       
   646                 // And finally, yet another pointer (RHeap* iHeap)
       
   647                 address = reader.ReadUint32L();
       
   648                 TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iHeap: 0x%08x", address));
       
   649 
       
   650                 if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   651                     {
       
   652                     // That'll do.
       
   653                     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - data seems okay!"));
       
   654                     correctCell = ETrue;
       
   655                     }
       
   656                 }
       
   657             }
       
   658         }
       
   659 
       
   660     CleanupStack::PopAndDestroy( &reader );
       
   661     //
       
   662     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - END - correctCell: %d", correctCell));
       
   663     return correctCell;
       
   664     }
       
   665 
       
   666 
       
   667 TUint CMemSpyEngineHelperFbServ::OffsetToCObjectConBitmapCon()
       
   668     {
       
   669     TUint ret = 0;
       
   670 
       
   671     // VTable
       
   672     ret += 4;
       
   673 
       
   674     // RFs
       
   675     ret += sizeof(RFs);
       
   676 
       
   677 	// CFontStore* iFontStore;
       
   678     ret += sizeof(CBase*); // best effort
       
   679 
       
   680     return ret;
       
   681     }
       
   682 
       
   683 
       
   684 TUint CMemSpyEngineHelperFbServ::OffsetToCObjectConFontCon()
       
   685     {
       
   686     TUint ret = OffsetToCObjectConBitmapCon();
       
   687 
       
   688 	// CObjectCon* iBitmapCon;
       
   689     ret += sizeof(CObjectCon*);
       
   690 
       
   691     return ret;
       
   692     }
       
   693 
       
   694 
       
   695 TUint CMemSpyEngineHelperFbServ::OffsetToBitmapHandleArray()
       
   696     {
       
   697     TUint ret = OffsetToCObjectConFontCon();
       
   698 
       
   699 	// CObjectConIx* iConIx;
       
   700     ret += sizeof(CObjectConIx*);
       
   701 
       
   702 	// RHeap* iHeap;
       
   703     ret += sizeof(RHeap*);
       
   704 
       
   705 	// RChunk iChunk
       
   706     ret += sizeof(RChunk);
       
   707 
       
   708 	// RChunk iLargeBitmapChunk
       
   709     ret += sizeof(RChunk);
       
   710 
       
   711 	// RMutex iLargeBitmapAccess
       
   712     ret += sizeof(RMutex);
       
   713 
       
   714 	// CChunkPile* iPile;
       
   715     ret += sizeof(CBase*); // best effort
       
   716 
       
   717 	// RPointerArray<HBufC> iFontNameAlias;
       
   718     ret += sizeof(RPointerArray<HBufC>);
       
   719 	
       
   720     return ret;
       
   721     }
       
   722 
       
   723 
       
   724 CMemSpyEngineHelperFbServ::CBitmapObject* CMemSpyEngineHelperFbServ::GetBitmapObjectLC( TAny* aCellAddress )
       
   725     {
       
   726     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - START - aCellAddress: 0x%08x", aCellAddress ));
       
   727 
       
   728     // What we will return
       
   729     CBitmapObject* object = new(ELeave) CBitmapObject();
       
   730     CleanupStack::PushL( object );
       
   731 
       
   732     // The data we will read
       
   733     HBufC8* cellData = NULL;
       
   734     
       
   735     // Try to get info about real cell
       
   736     TMemSpyDriverCellType cellType;
       
   737     TInt cellLength;
       
   738     TInt cellNestingLevel;
       
   739     TInt cellAllocationNumber;
       
   740     TInt cellHeaderSize;
       
   741     TAny* cellPayloadAddress;
       
   742 
       
   743     // NOTE: this call may change the value of 'cellAddress'
       
   744     TInt err = iEngine.Driver().WalkHeapGetCellInfo( aCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   745     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - err: %d, cellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aCellAddress, cellLength, cellAllocationNumber, cellType));
       
   746 
       
   747     if (err == KErrNone && (cellType & EMemSpyDriverAllocatedCellMask))
       
   748         {
       
   749         // Check that the cell size meets our expectations - it should be a CBitmapObject, but without the additional "this" pointer
       
   750         // which we have tacked onto the object.
       
   751         const TInt expectedCellSize = sizeof( CBitmapObject ) + cellHeaderSize - sizeof( CBitmapObject* );
       
   752         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - expectedCellSize: %d, actual: %d, address: 0x%08x", expectedCellSize, cellLength, aCellAddress));
       
   753 
       
   754         if  ( expectedCellSize <= cellLength )
       
   755             {
       
   756             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - cell lengths are good, trying to get cell data..."));
       
   757 
       
   758             // Try to get real cell data        
       
   759             cellData = HBufC8::NewLC( cellLength );
       
   760             TPtr8 pData( cellData->Des() );
       
   761             //
       
   762             err = iEngine.Driver().WalkHeapReadCellData( aCellAddress, pData, cellLength );
       
   763             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - reading cell data returned error: %d", err));
       
   764             }
       
   765         else
       
   766             {
       
   767             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - not enough data -> KErrCorrupt"));
       
   768             err = KErrCorrupt;
       
   769             }
       
   770         }
       
   771     else
       
   772         {
       
   773         User::Leave( KErrNotFound );
       
   774         }
       
   775 
       
   776     RDesReadStream stream( *cellData );
       
   777     CleanupClosePushL( stream );
       
   778     
       
   779     // Read vtable
       
   780     const TUint32 vTable = stream.ReadUint32L();
       
   781     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - actual vTable: 0x%08x", vTable ));
       
   782     TBool isROMAddress = EFalse;
       
   783     err = User::IsRomAddress( isROMAddress, (TAny*) vTable );
       
   784     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - vtable (0x%08x) is in ROM: %d (error: %d)", vTable, isROMAddress, err));
       
   785     User::LeaveIfError( err );
       
   786 
       
   787     // Skip CObject members
       
   788     (void) stream.ReadL( sizeof( CObject ) ); // skip this much
       
   789     object->iThisPointer = reinterpret_cast< CBitmapObject* >( cellPayloadAddress );;
       
   790     object->iTop = reinterpret_cast< CBase* >( stream.ReadUint32L() );
       
   791     object->iAddressPointer = reinterpret_cast< CBitwiseBitmap* >( stream.ReadUint32L() );
       
   792     object->iHandle = stream.ReadInt32L();
       
   793     object->iCleanBitmap = reinterpret_cast< CBitmapObject* >( stream.ReadUint32L() );
       
   794 
       
   795     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iThisPointer:    0x%08x", object->iThisPointer ));
       
   796     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iTop:            0x%08x", object->iTop ));
       
   797     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iAddressPointer: 0x%08x", object->iAddressPointer ));
       
   798     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iHandle:         0x%08x", object->iHandle ));
       
   799     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iCleanBitmap:    0x%08x", object->iCleanBitmap ));
       
   800     
       
   801     // Clean up - don't need this data anymore. Real data is in another cell
       
   802     CleanupStack::PopAndDestroy( 2, cellData );  // stream & cellData
       
   803 
       
   804     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - END - aCellAddress: 0x%08x", aCellAddress ));
       
   805     return object;
       
   806     }
       
   807 
       
   808 
       
   809 
       
   810 
       
   811 
       
   812 
       
   813 
       
   814 
       
   815 
       
   816 
       
   817 
       
   818 
       
   819 
       
   820 
       
   821 
       
   822 
       
   823 
       
   824 
       
   825 
       
   826 
       
   827 
       
   828 
       
   829 
       
   830 
       
   831 
       
   832 
       
   833 
       
   834 CMemSpyEngineFbServBitmapArray::CMemSpyEngineFbServBitmapArray( const RArray<TInt>& aBitmapHandles )
       
   835 :   CActive( CActive::EPriorityIdle ), iBitmapHandles( aBitmapHandles ), iGranularity( 0 )
       
   836     {
       
   837     CActiveScheduler::Add( this );
       
   838     }
       
   839 
       
   840 
       
   841 CMemSpyEngineFbServBitmapArray::CMemSpyEngineFbServBitmapArray( TInt aPriority, const RArray<TInt>& aBitmapHandles, MMemSpyEngineFbSerbBitmapArrayObserver& aObserver, TInt aGranularity )
       
   842 :   CActive( aPriority ), iBitmapHandles( aBitmapHandles ), iObserver( &aObserver ), iGranularity( aGranularity )
       
   843     {
       
   844     CActiveScheduler::Add( this );
       
   845     CompleteSelf();
       
   846     }
       
   847 
       
   848 
       
   849 EXPORT_C CMemSpyEngineFbServBitmapArray::~CMemSpyEngineFbServBitmapArray()
       
   850     {
       
   851     Cancel();
       
   852     //
       
   853     iBitmaps.ResetAndDestroy();
       
   854     iBitmaps.Close();
       
   855     }
       
   856 
       
   857 
       
   858 void CMemSpyEngineFbServBitmapArray::ConstructL()
       
   859     {
       
   860     if  ( !IsActive() )
       
   861         {
       
   862         // Sync construction...
       
   863         const TInt count = iBitmapHandles.Count();
       
   864         for(TInt i=0; i<count; i++ )
       
   865             {
       
   866             const TInt handle = iBitmapHandles[ i ];
       
   867             //
       
   868             TRAP_IGNORE( CreateBitmapL( handle ) );
       
   869             }
       
   870     
       
   871         SortBySizeL();
       
   872         }
       
   873     }
       
   874 
       
   875 
       
   876 EXPORT_C CMemSpyEngineFbServBitmapArray* CMemSpyEngineFbServBitmapArray::NewL( const RArray<TInt>& aBitmapHandles )
       
   877     {
       
   878     CMemSpyEngineFbServBitmapArray* self = new(ELeave) CMemSpyEngineFbServBitmapArray( aBitmapHandles );
       
   879     CleanupStack::PushL( self );
       
   880     self->ConstructL();
       
   881     CleanupStack::Pop( self );
       
   882     return self;
       
   883     }
       
   884 
       
   885 
       
   886 EXPORT_C CMemSpyEngineFbServBitmapArray* CMemSpyEngineFbServBitmapArray::NewL( TInt aPriority, const RArray<TInt>& aBitmapHandles, MMemSpyEngineFbSerbBitmapArrayObserver& aObserver, TInt aGranularity )
       
   887     {
       
   888     CMemSpyEngineFbServBitmapArray* self = new(ELeave) CMemSpyEngineFbServBitmapArray( aPriority, aBitmapHandles, aObserver, aGranularity );
       
   889     CleanupStack::PushL( self );
       
   890     self->ConstructL();
       
   891     CleanupStack::Pop( self );
       
   892     return self;
       
   893     }
       
   894 
       
   895 
       
   896 EXPORT_C TInt CMemSpyEngineFbServBitmapArray::Count() const
       
   897     {
       
   898     return iBitmaps.Count();
       
   899     }
       
   900 
       
   901 
       
   902 EXPORT_C CMemSpyEngineFbServBitmap& CMemSpyEngineFbServBitmapArray::At( TInt aIndex )
       
   903     {
       
   904     return *iBitmaps[ aIndex ];
       
   905     }
       
   906 
       
   907 
       
   908 EXPORT_C const CMemSpyEngineFbServBitmap& CMemSpyEngineFbServBitmapArray::At( TInt aIndex ) const
       
   909     {
       
   910     return *iBitmaps[ aIndex ];
       
   911     }
       
   912 
       
   913 
       
   914 EXPORT_C CMemSpyEngineFbServBitmap& CMemSpyEngineFbServBitmapArray::BitmapByHandleL( TInt aHandle )
       
   915     {
       
   916     const TInt index = BitmapIndexByHandle( aHandle );
       
   917     User::LeaveIfError( index );
       
   918     CMemSpyEngineFbServBitmap& ret = At( index );
       
   919     return ret;
       
   920     }
       
   921 
       
   922 
       
   923 EXPORT_C TInt CMemSpyEngineFbServBitmapArray::BitmapIndexByHandle( TInt aHandle ) const
       
   924     {
       
   925     TInt ret = KErrNotFound;
       
   926     //
       
   927     const TInt count = Count();
       
   928     for( TInt i=0; i<count; i++ )
       
   929         {
       
   930         const CMemSpyEngineFbServBitmap& bitmap = At( i );
       
   931         //
       
   932         if  ( bitmap.Handle() == aHandle )
       
   933             {
       
   934             ret = i;
       
   935             break;
       
   936             }
       
   937         }
       
   938     //
       
   939     return ret;
       
   940     }
       
   941 
       
   942 
       
   943 EXPORT_C TInt CMemSpyEngineFbServBitmapArray::MdcaCount() const
       
   944     {
       
   945     return Count();
       
   946     }
       
   947 
       
   948 
       
   949 EXPORT_C TPtrC CMemSpyEngineFbServBitmapArray::MdcaPoint( TInt aIndex ) const
       
   950     {
       
   951     const CMemSpyEngineFbServBitmap& bitmap = At( aIndex );
       
   952     return TPtrC( bitmap.Caption() );
       
   953     }
       
   954 
       
   955 
       
   956 void CMemSpyEngineFbServBitmapArray::RunL()
       
   957     {
       
   958     const TInt bitmapHandleCount = iBitmapHandles.Count();
       
   959     const TInt endIndex = Min( iIndex + iGranularity, bitmapHandleCount );
       
   960     //
       
   961     for( ; iIndex < endIndex; iIndex++ )
       
   962         {
       
   963         const TInt handle = iBitmapHandles[ iIndex ];
       
   964         //
       
   965         TRAP_IGNORE( CreateBitmapL( handle ) );
       
   966         }
       
   967     
       
   968     // Report progress & queue for next iteration
       
   969     MMemSpyEngineFbSerbBitmapArrayObserver::TEvent event = MMemSpyEngineFbSerbBitmapArrayObserver::EBitmapArrayConstructionComplete;
       
   970     if  ( endIndex < bitmapHandleCount )
       
   971         {
       
   972         CompleteSelf();
       
   973         event = MMemSpyEngineFbSerbBitmapArrayObserver::EBitmapItemsCreated;
       
   974         }
       
   975     else
       
   976         {
       
   977         SortBySizeL();
       
   978         }
       
   979 
       
   980     if  ( iObserver )
       
   981         {
       
   982         iObserver->HandleFbServBitmapArrayEventL( event );
       
   983         }
       
   984     }
       
   985 
       
   986 
       
   987 void CMemSpyEngineFbServBitmapArray::DoCancel()
       
   988     {
       
   989     // Nothing to do
       
   990     }
       
   991 
       
   992 
       
   993 TInt CMemSpyEngineFbServBitmapArray::RunError( TInt /*aError*/ )
       
   994     {
       
   995     return KErrNone;
       
   996     }
       
   997 
       
   998 
       
   999 void CMemSpyEngineFbServBitmapArray::CompleteSelf()
       
  1000     {
       
  1001     TRequestStatus* status = &iStatus;
       
  1002     User::RequestComplete( status, KErrNone );
       
  1003     SetActive();
       
  1004     }
       
  1005 
       
  1006 
       
  1007 void CMemSpyEngineFbServBitmapArray::CreateBitmapL( TInt aHandle )
       
  1008     {
       
  1009     CMemSpyEngineFbServBitmap* bitmap = CMemSpyEngineFbServBitmap::NewLC( aHandle );
       
  1010     iBitmaps.AppendL( bitmap );
       
  1011     CleanupStack::Pop( bitmap );
       
  1012     }
       
  1013 
       
  1014 
       
  1015 void CMemSpyEngineFbServBitmapArray::SortBySizeL()
       
  1016     {
       
  1017     TLinearOrder< CMemSpyEngineFbServBitmap > comparer( CompareBySize );
       
  1018     iBitmaps.Sort( comparer );
       
  1019     }
       
  1020 
       
  1021 
       
  1022 TInt CMemSpyEngineFbServBitmapArray::CompareBySize( const CMemSpyEngineFbServBitmap& aLeft, const CMemSpyEngineFbServBitmap& aRight )
       
  1023     {
       
  1024     TInt ret = 1;
       
  1025     //
       
  1026     if  ( aLeft.BitmapSizeInBytes() > aRight.BitmapSizeInBytes() )
       
  1027         {
       
  1028         ret = -1;
       
  1029         }
       
  1030     else if ( aLeft.BitmapSizeInBytes() == aRight.BitmapSizeInBytes() )
       
  1031         {
       
  1032         ret = 0;
       
  1033         }
       
  1034     //
       
  1035     return ret;
       
  1036     }
       
  1037 
       
  1038 
       
  1039 
       
  1040 
       
  1041 
       
  1042 
       
  1043 
       
  1044 
       
  1045 
       
  1046 
       
  1047 
       
  1048 
       
  1049 
       
  1050 
       
  1051 
       
  1052 
       
  1053 
       
  1054 
       
  1055 
       
  1056 
       
  1057 
       
  1058 
       
  1059 CMemSpyEngineFbServBitmap::CMemSpyEngineFbServBitmap()
       
  1060 :   CDesCArrayFlat( 5 )
       
  1061     {
       
  1062     }
       
  1063 
       
  1064 
       
  1065 EXPORT_C CMemSpyEngineFbServBitmap::~CMemSpyEngineFbServBitmap()
       
  1066     {
       
  1067     delete iBitmap;
       
  1068     delete iCaption;
       
  1069     }
       
  1070 
       
  1071 
       
  1072 void CMemSpyEngineFbServBitmap::ConstructL( TInt aHandle )
       
  1073     {
       
  1074     iBitmap = new(ELeave) CFbsBitmap();
       
  1075     const TInt error = iBitmap->Duplicate( aHandle );
       
  1076     User::LeaveIfError( error );
       
  1077     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1078 
       
  1079     // Prepare caption
       
  1080     _LIT( KCaptionFormat, "\t%2d bpp, %S\t\t%4d x %4d pixels" );
       
  1081     iCaption = HBufC::NewL( 128 );
       
  1082     TPtr pCaption( iCaption->Des() );
       
  1083     
       
  1084     // Create size string
       
  1085     const TMemSpySizeText size( MemSpyEngineUtils::FormatSizeText( header.iBitmapSize ) );
       
  1086     pCaption.AppendFormat( KCaptionFormat, header.iBitsPerPixel, &size, header.iSizeInPixels.iWidth, header.iSizeInPixels.iHeight );
       
  1087 
       
  1088     // Prepare items
       
  1089     PrepareItemsL();
       
  1090     }
       
  1091 
       
  1092 
       
  1093 EXPORT_C CMemSpyEngineFbServBitmap* CMemSpyEngineFbServBitmap::NewLC( TInt aHandle )
       
  1094     {
       
  1095     CMemSpyEngineFbServBitmap* self = new(ELeave) CMemSpyEngineFbServBitmap();
       
  1096     CleanupStack::PushL( self );
       
  1097     self->ConstructL( aHandle );
       
  1098     return self;
       
  1099     }
       
  1100 
       
  1101 
       
  1102 TInt CMemSpyEngineFbServBitmap::BitmapSizeInBytes() const
       
  1103     {
       
  1104     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1105     return header.iBitmapSize;
       
  1106     }
       
  1107 
       
  1108 
       
  1109 EXPORT_C const TDesC& CMemSpyEngineFbServBitmap::Caption() const
       
  1110     {
       
  1111     return *iCaption;
       
  1112     }
       
  1113 
       
  1114 
       
  1115 EXPORT_C CFbsBitmap& CMemSpyEngineFbServBitmap::Bitmap()
       
  1116     {
       
  1117     return *iBitmap;
       
  1118     }
       
  1119 
       
  1120 
       
  1121 EXPORT_C const CFbsBitmap& CMemSpyEngineFbServBitmap::Bitmap() const
       
  1122     {
       
  1123     return *iBitmap;
       
  1124     }
       
  1125 
       
  1126 
       
  1127 EXPORT_C TInt CMemSpyEngineFbServBitmap::Handle() const
       
  1128     {
       
  1129     return iBitmap->Handle();
       
  1130     }
       
  1131 
       
  1132 
       
  1133 EXPORT_C void CMemSpyEngineFbServBitmap::OutputDataL( CMemSpyEngine& aEngine ) const
       
  1134     {
       
  1135     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1136     //
       
  1137     _LIT(KMemSpyFBServHex, "0x%08x");
       
  1138     _LIT(KMemSpyFBServDecimal, "%d");
       
  1139     //
       
  1140     HBufC* columns = HBufC::NewLC( 1024 );
       
  1141     TPtr pColumns( columns->Des() );
       
  1142     //
       
  1143     pColumns.AppendFormat( KMemSpyFBServHex, Handle() );
       
  1144     pColumns.Append( KMemSpyEngineFBServComma );
       
  1145     //
       
  1146     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iBitmapSize );
       
  1147     pColumns.Append( KMemSpyEngineFBServComma );
       
  1148     //
       
  1149     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iSizeInPixels.iWidth );
       
  1150     pColumns.Append( KMemSpyEngineFBServComma );
       
  1151     //
       
  1152     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iSizeInPixels.iHeight );
       
  1153     pColumns.Append( KMemSpyEngineFBServComma );
       
  1154     //
       
  1155     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iBitsPerPixel );
       
  1156     pColumns.Append( KMemSpyEngineFBServComma );
       
  1157     //
       
  1158     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iColor );
       
  1159     pColumns.Append( KMemSpyEngineFBServComma );
       
  1160     //
       
  1161     TBuf<24> fileCompressionType;
       
  1162     GetFileCompressionTypeAsString( header.iCompression, fileCompressionType );
       
  1163     pColumns.Append( fileCompressionType );
       
  1164     pColumns.Append( KMemSpyEngineFBServComma );
       
  1165     //
       
  1166     GetExportableFileNameL( pColumns );
       
  1167     //
       
  1168     aEngine.Sink().OutputLineL( pColumns );
       
  1169     CleanupStack::PopAndDestroy( columns );
       
  1170     }
       
  1171 
       
  1172 
       
  1173 EXPORT_C void CMemSpyEngineFbServBitmap::OutputDataColumnsL( CMemSpyEngine& aEngine )
       
  1174     {
       
  1175     HBufC* columns = HBufC::NewLC( 1024 );
       
  1176     TPtr pColumns( columns->Des() );
       
  1177     //
       
  1178     _LIT(KCol1, "Handle");
       
  1179     pColumns.Append( KCol1 );
       
  1180     pColumns.Append( KMemSpyEngineFBServComma );
       
  1181     //
       
  1182     _LIT(KCol2, "Uncompressed Size (Bytes)");
       
  1183     pColumns.Append( KCol2 );
       
  1184     pColumns.Append( KMemSpyEngineFBServComma );
       
  1185     //
       
  1186     _LIT(KCol3, "Width");
       
  1187     pColumns.Append( KCol3 );
       
  1188     pColumns.Append( KMemSpyEngineFBServComma );
       
  1189     //
       
  1190     _LIT(KCol4, "Height");
       
  1191     pColumns.Append( KCol4 );
       
  1192     pColumns.Append( KMemSpyEngineFBServComma );
       
  1193     //
       
  1194     _LIT(KCol5, "BPP");
       
  1195     pColumns.Append( KCol5 );
       
  1196     pColumns.Append( KMemSpyEngineFBServComma );
       
  1197     //
       
  1198     _LIT(KCol6, "Color");
       
  1199     pColumns.Append( KCol6 );
       
  1200     pColumns.Append( KMemSpyEngineFBServComma );
       
  1201     //
       
  1202     _LIT(KCol7, "Compression");
       
  1203     pColumns.Append( KCol7 );
       
  1204     pColumns.Append( KMemSpyEngineFBServComma );
       
  1205     //
       
  1206     _LIT(KCol8, "File Name");
       
  1207     pColumns.Append( KCol8 );
       
  1208     //
       
  1209     aEngine.Sink().OutputLineL( pColumns );
       
  1210     CleanupStack::PopAndDestroy( columns );
       
  1211     }
       
  1212 
       
  1213 
       
  1214 EXPORT_C void CMemSpyEngineFbServBitmap::GetExportableFileNameL( TDes& aAppendName ) const
       
  1215     {
       
  1216     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1217 
       
  1218     // Create a filename
       
  1219     aAppendName.AppendFormat( KMemSpyEngineFBServExportFileName, Handle(), header.iBitsPerPixel, header.iSizeInPixels.iWidth, header.iSizeInPixels.iHeight );
       
  1220     }
       
  1221 
       
  1222 
       
  1223 void CMemSpyEngineFbServBitmap::GetExportableFileNameL( const TMemSpyEngineFBServBitmapInfo& aInfo, TDes& aAppendName )
       
  1224     {
       
  1225     aAppendName.AppendFormat( KMemSpyEngineFBServExportFileName, aInfo.iHandle, aInfo.iBitsPerPixel, aInfo.iSizeInPixels.iWidth, aInfo.iSizeInPixels.iHeight );
       
  1226     }
       
  1227 
       
  1228 
       
  1229 void CMemSpyEngineFbServBitmap::PrepareItemsL()
       
  1230     {
       
  1231     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1232     TBuf<256> item;
       
  1233 
       
  1234     // View bitmap (ugly, but needed by UI)
       
  1235     _LIT(KCaptionMinus2, "\tView Bitmap\t\t");
       
  1236     AppendL( KCaptionMinus2 );
       
  1237 
       
  1238     // Dimensions
       
  1239     _LIT(KCaptionMinus1, "\tDimensions\t\t%5d x %5d");
       
  1240     item.Format( KCaptionMinus1, header.iSizeInPixels.iWidth, header.iSizeInPixels.iHeight );
       
  1241     AppendL( item );
       
  1242 
       
  1243     // Handle
       
  1244     _LIT(KCaption0, "\tHandle\t\t0x%08x");
       
  1245     item.Format( KCaption0, iBitmap->Handle() );
       
  1246     AppendL( item );
       
  1247 
       
  1248     // In Rom?
       
  1249     _LIT(KCaption1, "\tIn ROM?\t\t%S");
       
  1250     _LIT(KIsRomBitmap, "Yes");
       
  1251     _LIT(KNotRomBitmap, "No");
       
  1252     if  ( iBitmap->IsRomBitmap() )
       
  1253         {
       
  1254         item.Format( KCaption1, &KIsRomBitmap );
       
  1255         }
       
  1256     else
       
  1257         {
       
  1258         item.Format( KCaption1, &KNotRomBitmap );
       
  1259         }
       
  1260     AppendL( item );
       
  1261 
       
  1262     // Bits per pixel
       
  1263     _LIT(KCaption2, "\tBits Per Pixel\t\t%2d");
       
  1264     item.Format( KCaption2, header.iBitsPerPixel );
       
  1265     AppendL( item );
       
  1266 
       
  1267     // Size of uncompressed bitmap data
       
  1268     _LIT(KCaption3, "\tUncompressed data size\t\t%S");
       
  1269     const TMemSpySizeText sizeStringUncompressed( MemSpyEngineUtils::FormatSizeText( header.iBitmapSize ) );
       
  1270     item.Format( KCaption3, &sizeStringUncompressed );
       
  1271     AppendL( item );
       
  1272 
       
  1273     // Palette entry count
       
  1274     _LIT(KCaption4, "\tNumber of palette entries\t\t%d");
       
  1275     item.Format( KCaption4, header.iPaletteEntries );
       
  1276     AppendL( item );
       
  1277 
       
  1278     // Colour
       
  1279     _LIT(KCaption5, "\tColour\t\t%d");
       
  1280     item.Format( KCaption5, header.iColor);
       
  1281     AppendL( item );
       
  1282 
       
  1283     // Palette entry count
       
  1284     _LIT(KCaption6, "\tFile compression type\t\t%S");
       
  1285     TBuf<24> fileCompressionType;
       
  1286     GetFileCompressionTypeAsString( header.iCompression, fileCompressionType );
       
  1287     item.Format( KCaption6, &fileCompressionType );
       
  1288     AppendL( item );
       
  1289     }
       
  1290 
       
  1291 
       
  1292 void CMemSpyEngineFbServBitmap::GetFileCompressionTypeAsString( TBitmapfileCompression aType, TDes& aString )
       
  1293     {
       
  1294     _LIT(KUnknown, "Unknown");
       
  1295     _LIT(KNoCompression, "None");
       
  1296     _LIT(KRLE, "RLE");
       
  1297     _LIT(KTwelveBitRLE, "12-bit RLE");
       
  1298     _LIT(KSixteenBitRLE, "16-bit RLE");
       
  1299     _LIT(KTwentyFourBitRLE, "24-bit RLE");
       
  1300     _LIT(KThirtyTwoBitRLE, "32-bit RLE");
       
  1301     //
       
  1302     switch( aType )
       
  1303         {
       
  1304     case ENoBitmapCompression:
       
  1305         aString = KNoCompression;
       
  1306         break;
       
  1307     case EByteRLECompression:
       
  1308         aString = KRLE;
       
  1309         break;
       
  1310     case ETwelveBitRLECompression:
       
  1311         aString = KTwelveBitRLE;
       
  1312         break;
       
  1313     case ESixteenBitRLECompression:
       
  1314         aString = KSixteenBitRLE;
       
  1315         break;
       
  1316     case ETwentyFourBitRLECompression:
       
  1317         aString = KTwentyFourBitRLE;
       
  1318         break;
       
  1319     case EThirtyTwoUBitRLECompression:
       
  1320         aString = KThirtyTwoBitRLE;
       
  1321         break;
       
  1322     default:
       
  1323     case ERLECompressionLast:
       
  1324         aString = KUnknown;
       
  1325         break;
       
  1326         }
       
  1327     }
       
  1328 
       
  1329 
       
  1330 
       
  1331 
       
  1332 
       
  1333 
       
  1334 
       
  1335