memspy/Engine/Source/Helpers/MemSpyEngineHelperFbServ.cpp
changeset 0 a03f92240627
child 30 86a2e675b80a
equal deleted inserted replaced
-1:000000000000 0:a03f92240627
       
     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::ETypeRHeap )
       
   304         {
       
   305         err = KErrNotSupported;
       
   306         }
       
   307     User::LeaveIfError( err );
       
   308     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - allocated cell header length is: %d", info.AsRHeap().MetaData().HeaderSizeAllocated() ));
       
   309 
       
   310     // Now walk the heap!
       
   311     err = iEngine.Driver().WalkHeapInit( aFbServThread.Id() );
       
   312     if  ( err == KErrNone )
       
   313         {
       
   314         TMemSpyDriverCellType cellType;
       
   315         TAny* cellAddress;
       
   316         TInt cellLength;
       
   317         TInt cellNestingLevel;
       
   318         TInt cellAllocationNumber;
       
   319         TInt cellHeaderSize;
       
   320         TAny* cellPayloadAddress;
       
   321         //
       
   322         for( TInt cellIndex = KFbServWillingToStartAtCellIndex; err == KErrNone && cellIndex < KFbServWillingToSearchUntilCellIndex; cellIndex++ )
       
   323             {
       
   324             err = iEngine.Driver().WalkHeapNextCell( aFbServThread.Id(), cellType, cellAddress, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   325             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - cellIndex[%d] err: %d, cellLength: %d, cellAllocationNumber: %d, cellType: %d", cellIndex, err, cellLength, cellAllocationNumber, cellType));
       
   326 
       
   327             if  ( err == KErrNone && cellType == EMemSpyDriverGoodAllocatedCell )
       
   328                 {
       
   329                 // We know we are looking for a relatively large *allocated* cell.
       
   330                 if  ( cellLength >= KFbServExpectedMinimumCellSize && cellLength <= KFbServExpectedMaximumCellSize && cellType == EMemSpyDriverGoodAllocatedCell )
       
   331                     {
       
   332                     const TInt payloadLength = cellLength - info.AsRHeap().MetaData().HeaderSizeAllocated();
       
   333                     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - cell was long enough. Full cell len: %d, header: %d, therefore dataLen: %d", cellLength, info.AsRHeap().MetaData().HeaderSizeAllocated(), payloadLength));
       
   334 
       
   335                     // This is *probably* the right cell. Let's get the data and check.
       
   336                     HBufC8* data = HBufC8::NewLC( payloadLength );
       
   337                     TPtr8 pData( data->Des() );
       
   338                     //
       
   339                     err = iEngine.Driver().WalkHeapReadCellData( cellAddress, pData, payloadLength );
       
   340                     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - data fetch returned error: %d", err));
       
   341 
       
   342                     if  ( err == KErrNone )
       
   343                         {
       
   344                         //_LIT(KHeapDumpDataFormat, "%S");
       
   345                         //iEngine.Sink().OutputBinaryDataL( KHeapDumpDataFormat, pData.Ptr(), (const TUint8*) cellAddress, pData.Length() );
       
   346                     
       
   347                         // Check the data
       
   348                         const TUint heapSize = info.AsRHeap().ObjectData().Size();
       
   349                         const TUint heapBaseAddress = (TUint) info.AsRHeap().ObjectData().Base();
       
   350                         const TBool correctHeapCellLocated = VerifyCorrectHeapCellL( *data, cellAddress, cellPayloadAddress, heapBaseAddress, heapSize );
       
   351                         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - verified: %d", correctHeapCellLocated));
       
   352 
       
   353                         if  ( correctHeapCellLocated )
       
   354                             {
       
   355                             aCellAddress = cellAddress;
       
   356                             heapCellData = data;
       
   357                             CleanupStack::Pop( data );
       
   358                             break;
       
   359                             }
       
   360                         else
       
   361                             {
       
   362                             // Not the right cell. Keep going...
       
   363                             CleanupStack::PopAndDestroy( data );
       
   364                             }
       
   365                         }
       
   366                     }
       
   367                 }
       
   368             }
       
   369 
       
   370         // NB: don't do this here - 
       
   371         // iEngine.Driver().WalkHeapClose();
       
   372         // It gets done after all reading is complete
       
   373         }
       
   374 
       
   375     if  ( heapCellData == NULL )
       
   376         {
       
   377         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - END - didn't find the right cell => KErrNotFound"));
       
   378         User::Leave( KErrNotFound );
       
   379         }
       
   380     //
       
   381     CleanupStack::PushL( heapCellData );
       
   382 
       
   383     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - END - everything okay, cell is: 0x%08x", aCellAddress));
       
   384     return heapCellData;
       
   385     }
       
   386 
       
   387 
       
   388 void CMemSpyEngineHelperFbServ::ReadCObjectConInfoL( TAny* aCellAddress, RArray<TAny*>& aContainerObjects, TInt& aCount, TInt& aAllocated )
       
   389     {
       
   390     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - START - trying cell: 0x%08x", aCellAddress ));
       
   391 
       
   392     // What we will return
       
   393     HBufC8* cellData = NULL;
       
   394     
       
   395     // Try to get info about real cell
       
   396     TMemSpyDriverCellType cellType;
       
   397     TInt cellLength;
       
   398     TInt cellNestingLevel;
       
   399     TInt cellAllocationNumber;
       
   400     TInt cellHeaderSize;
       
   401     TAny* cellPayloadAddress;
       
   402 
       
   403     // NOTE: this call may change the value of 'cellAddress'
       
   404     TInt err = iEngine.Driver().WalkHeapGetCellInfo( aCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   405     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - err: %d, cellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aCellAddress, cellLength, cellAllocationNumber, cellType));
       
   406 
       
   407     if  ( err == KErrNone && cellType == EMemSpyDriverGoodAllocatedCell )
       
   408         {
       
   409         // Check that the cell size meets our expectations - it should be a CObjectCon cell.
       
   410         const TInt expectedCellSize = sizeof(CObjectCon*) + cellHeaderSize;
       
   411         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - expectedCellSize: %d, actual: %d, address: 0x%08x", expectedCellSize, cellLength, aCellAddress));
       
   412 
       
   413         if  ( expectedCellSize <= cellLength )
       
   414             {
       
   415             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - cell lengths are good, trying to get cell data..."));
       
   416 
       
   417             // Try to get real cell data        
       
   418             cellData = HBufC8::NewLC( cellLength );
       
   419             TPtr8 pData( cellData->Des() );
       
   420             //
       
   421             err = iEngine.Driver().WalkHeapReadCellData( aCellAddress, pData, cellLength );
       
   422             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - reading cell data returned error: %d", err));
       
   423             }
       
   424         else
       
   425             {
       
   426             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - not enough data -> KErrCorrupt"));
       
   427             err = KErrCorrupt;
       
   428             }
       
   429         }
       
   430     else
       
   431         {
       
   432         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - END - didn't find cell data => KErrNotFound"));
       
   433         User::Leave( KErrNotFound );
       
   434         }
       
   435 
       
   436     CObjectCon* con = CObjectCon::NewL();
       
   437     const TUint32 KExpectedObjectConVTable = *((TUint32*) con);
       
   438     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - KExpectedObjectConVTable: 0x%08x", KExpectedObjectConVTable ));
       
   439     delete con;
       
   440 
       
   441     // We should have the valid CObjectCon data now.
       
   442     RDesReadStream stream( *cellData );
       
   443     CleanupClosePushL( stream );
       
   444     
       
   445     // Read vtable
       
   446     const TUint32 vTable = stream.ReadUint32L();
       
   447     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - actual vTable: 0x%08x", vTable ));
       
   448     if  ( vTable != KExpectedObjectConVTable )
       
   449         {
       
   450         User::Leave( KErrNotFound );
       
   451         }
       
   452 
       
   453     const TInt uniqueId = stream.ReadInt32L();
       
   454     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - uniqueId: %d", uniqueId ));
       
   455 
       
   456     aCount = stream.ReadInt32L();
       
   457     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - aCount: %d", aCount ));
       
   458 
       
   459     aAllocated = stream.ReadInt32L();
       
   460     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - aAllocated: %d", aAllocated ));
       
   461 
       
   462     // This is actually CObject's iObject, i.e. CObject** iObjects.
       
   463     TAny* pObjects = reinterpret_cast< TAny*>( stream.ReadUint32L() );
       
   464     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - pObjects: 0x%08x", pObjects ));
       
   465 
       
   466     CleanupStack::PopAndDestroy( 2, cellData ); // cellData & stream
       
   467 
       
   468     // Now fetch the cell containing the CObject pointers...
       
   469     err = iEngine.Driver().WalkHeapGetCellInfo( pObjects, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   470     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));
       
   471     User::LeaveIfError( err );
       
   472 
       
   473     const TInt expectedSize = ( aAllocated * sizeof(CObject*) ) + cellHeaderSize;
       
   474     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - expectedSize: %d, actual size: %d", expectedSize, cellLength ));
       
   475     if  ( cellLength < expectedSize )
       
   476         {
       
   477         User::Leave( KErrUnderflow );
       
   478         }
       
   479     
       
   480     // Get the data
       
   481     cellData = HBufC8::NewLC( cellLength );
       
   482     TPtr8 pData( cellData->Des() );
       
   483     err = iEngine.Driver().WalkHeapReadCellData( pObjects, pData, cellLength );
       
   484     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - reading cell data returned error: %d", err));
       
   485     User::LeaveIfError( err );
       
   486 
       
   487     // Open stream
       
   488     stream.Open( *cellData );
       
   489     CleanupClosePushL( stream );
       
   490 
       
   491     // Extract array of pointers
       
   492     for( TInt i=0; i<aCount; i++ )
       
   493         {
       
   494         TAny* objectAddress = reinterpret_cast< TAny*>( stream.ReadUint32L() );
       
   495         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - object[%04d]: 0x%08x", i, objectAddress ));
       
   496         aContainerObjects.AppendL( objectAddress );
       
   497         }
       
   498     CleanupStack::PopAndDestroy( 2, cellData ); // cellData & stream
       
   499 
       
   500     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ReadCObjectConInfoL() - END" ));
       
   501     }
       
   502 
       
   503 
       
   504 HBufC8* CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC( TAny*& aArrayCellAddress, TInt aArrayAllocCount )
       
   505     {
       
   506     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - START - trying cell: 0x%08x, aArrayAllocCount: %d", aArrayCellAddress, aArrayAllocCount));
       
   507 
       
   508     // What we will return
       
   509     HBufC8* cellData = NULL;
       
   510     
       
   511     // Try to get info about real cell
       
   512     TMemSpyDriverCellType cellType;
       
   513     TInt cellLength;
       
   514     TInt cellNestingLevel;
       
   515     TInt cellAllocationNumber;
       
   516     TInt cellHeaderSize;
       
   517     TAny* cellPayloadAddress;
       
   518 
       
   519     // NOTE: this call may change the value of 'cellAddress'
       
   520     TInt err = iEngine.Driver().WalkHeapGetCellInfo( aArrayCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   521     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateCFbTopHeapCellDataLC() - err: %d, cellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aArrayCellAddress, cellLength, cellAllocationNumber, cellType));
       
   522 
       
   523     if  ( err == KErrNone && cellType == EMemSpyDriverGoodAllocatedCell )
       
   524         {
       
   525         // Check that the cell size meets our expectations. 
       
   526         // The cell should be a very specific length
       
   527         const TInt expectedCellSize = (sizeof(CBase*) * aArrayAllocCount) + cellHeaderSize;
       
   528         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - expectedCellSize: %d, actual: %d, address: 0x%08x", expectedCellSize, cellLength, aArrayCellAddress));
       
   529 
       
   530         if  ( expectedCellSize <= cellLength )
       
   531             {
       
   532             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - cell lengths are good, trying to get cell data..."));
       
   533 
       
   534             // Try to get real cell data        
       
   535             cellData = HBufC8::NewLC( cellLength );
       
   536             TPtr8 pData( cellData->Des() );
       
   537             //
       
   538             err = iEngine.Driver().WalkHeapReadCellData( aArrayCellAddress, pData, cellLength );
       
   539             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - reading cell data returned error: %d", err));
       
   540             }
       
   541         else
       
   542             {
       
   543             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - not enough data -> KErrCorrupt"));
       
   544             err = KErrCorrupt;
       
   545             }
       
   546         }
       
   547     //
       
   548     if  ( cellData == NULL )
       
   549         {
       
   550         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - END - didn't find cell data => KErrNotFound"));
       
   551         err = KErrNotFound;
       
   552         }
       
   553     User::LeaveIfError( err );
       
   554     //
       
   555     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::LocateBitmapArrayHeapCellDataLC() - END - ok! - got %d bytes", cellData->Length() ) );
       
   556     return cellData;
       
   557     }
       
   558 
       
   559 
       
   560 void CMemSpyEngineHelperFbServ::ParseCellDataAndExtractHandlesL( const TDesC8& aData, RArray<TInt>& aHandles, TInt aArrayEntryCount )
       
   561     {
       
   562     aHandles.Reset();
       
   563     
       
   564     // Create read stream
       
   565     RDesReadStream stream( aData );
       
   566     CleanupClosePushL( stream );
       
   567     
       
   568     for( TInt i=0; i<aArrayEntryCount; i++ )
       
   569         {
       
   570         const TInt handle = stream.ReadInt32L();
       
   571         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::ParseCellDataAndExtractHandlesL() - handle[%4d] = 0x%08x", i, handle));
       
   572         aHandles.AppendL( handle );
       
   573         }
       
   574     
       
   575     // Tidy up
       
   576     CleanupStack::PopAndDestroy( &stream );
       
   577     }
       
   578 
       
   579 
       
   580 TBool CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL( const TDesC8& aData, TAny* aCellAddress, TAny* aPayloadAddress, TUint aHeapStartingAddress, TUint aHeapSize )
       
   581     {
       
   582     (void) aPayloadAddress;
       
   583     (void) aCellAddress;
       
   584     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - START - aDataLen: %d, aCellAddress: 0x%08x, aPayloadAddress: 0x%08x, aHeapStartingAddress: 0x%08x, aHeapSize: %d", aData.Length(), aCellAddress, aPayloadAddress, aHeapStartingAddress, aHeapSize ));
       
   585 
       
   586     const TUint KFbServHeapCeilingAddress = aHeapStartingAddress + aHeapSize;
       
   587 
       
   588     // Whether we can use this cell's data...
       
   589     TBool correctCell = EFalse;
       
   590 
       
   591     // We can use certain knowledge of the layout of the cell to work out
       
   592     // if we've found the right one. 
       
   593     // 
       
   594     // This is fragile because of the font and bitmap server heap layout changes 
       
   595     // significantly, then this can break.
       
   596     RDesReadStream reader( aData );
       
   597     CleanupClosePushL( reader );
       
   598 
       
   599     // Get vtable address
       
   600     TUint address = reader.ReadUint32L();
       
   601     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - suspected vtable: 0x%08x", address));
       
   602 
       
   603 #ifdef __EPOC32__
       
   604     TBool isROMAddress = EFalse;
       
   605     TInt err = User::IsRomAddress( isROMAddress, (TAny*) address );
       
   606     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - vtable (0x%08x) is in ROM: %d (error: %d)", address, isROMAddress, err));
       
   607     User::LeaveIfError( err );
       
   608 
       
   609     if  ( !isROMAddress )
       
   610         {
       
   611         // Close stream
       
   612         CleanupStack::PopAndDestroy( &reader );
       
   613 
       
   614         // VTable value should be in the ROM range.
       
   615         correctCell = EFalse;
       
   616         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - END - suspected CFbTop vTable isn't in ROM address range! - correctCell: %d", correctCell));
       
   617         return correctCell;
       
   618         }
       
   619 #else
       
   620     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - skipping vtable: 0x%08x", address));
       
   621 #endif
       
   622 
       
   623     // First real item is an RFs object instance. We can't check this
       
   624     // very easily because its an embedded object-> We must skip it
       
   625     __ASSERT_ALWAYS( sizeof(RFs) == 4, User::Invariant() );
       
   626     address = reader.ReadUint32L();
       
   627     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - skipping RFs: 0x%08x", address));
       
   628 
       
   629     // Next object is an address (CFontStore* iFontStore). We can validate this against
       
   630     // the method arguments.
       
   631     address = reader.ReadUint32L();
       
   632     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iFontStore: 0x%08x", address));
       
   633 
       
   634     if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   635         {
       
   636         // Next comes another pointer (CObjectCon* iBitmapCon)
       
   637         address = reader.ReadUint32L();
       
   638         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iBitmapCon: 0x%08x", address));
       
   639 
       
   640         if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   641             {
       
   642             // Next another pointer (CObjectCon* iFontCon)
       
   643             address = reader.ReadUint32L();
       
   644             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iFontCon: 0x%08x", address));
       
   645 
       
   646             if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   647                 {
       
   648                 // And finally, yet another pointer (RHeap* iHeap)
       
   649                 address = reader.ReadUint32L();
       
   650                 TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - iHeap: 0x%08x", address));
       
   651 
       
   652                 if  ( address > aHeapStartingAddress && address < KFbServHeapCeilingAddress )
       
   653                     {
       
   654                     // That'll do.
       
   655                     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - data seems okay!"));
       
   656                     correctCell = ETrue;
       
   657                     }
       
   658                 }
       
   659             }
       
   660         }
       
   661 
       
   662     CleanupStack::PopAndDestroy( &reader );
       
   663     //
       
   664     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::VerifyCorrectHeapCellL() - END - correctCell: %d", correctCell));
       
   665     return correctCell;
       
   666     }
       
   667 
       
   668 
       
   669 TUint CMemSpyEngineHelperFbServ::OffsetToCObjectConBitmapCon()
       
   670     {
       
   671     TUint ret = 0;
       
   672 
       
   673     // VTable
       
   674     ret += 4;
       
   675 
       
   676     // RFs
       
   677     ret += sizeof(RFs);
       
   678 
       
   679 	// CFontStore* iFontStore;
       
   680     ret += sizeof(CBase*); // best effort
       
   681 
       
   682     return ret;
       
   683     }
       
   684 
       
   685 
       
   686 TUint CMemSpyEngineHelperFbServ::OffsetToCObjectConFontCon()
       
   687     {
       
   688     TUint ret = OffsetToCObjectConBitmapCon();
       
   689 
       
   690 	// CObjectCon* iBitmapCon;
       
   691     ret += sizeof(CObjectCon*);
       
   692 
       
   693     return ret;
       
   694     }
       
   695 
       
   696 
       
   697 TUint CMemSpyEngineHelperFbServ::OffsetToBitmapHandleArray()
       
   698     {
       
   699     TUint ret = OffsetToCObjectConFontCon();
       
   700 
       
   701 	// CObjectConIx* iConIx;
       
   702     ret += sizeof(CObjectConIx*);
       
   703 
       
   704 	// RHeap* iHeap;
       
   705     ret += sizeof(RHeap*);
       
   706 
       
   707 	// RChunk iChunk
       
   708     ret += sizeof(RChunk);
       
   709 
       
   710 	// RChunk iLargeBitmapChunk
       
   711     ret += sizeof(RChunk);
       
   712 
       
   713 	// RMutex iLargeBitmapAccess
       
   714     ret += sizeof(RMutex);
       
   715 
       
   716 	// CChunkPile* iPile;
       
   717     ret += sizeof(CBase*); // best effort
       
   718 
       
   719 	// RPointerArray<HBufC> iFontNameAlias;
       
   720     ret += sizeof(RPointerArray<HBufC>);
       
   721 	
       
   722     return ret;
       
   723     }
       
   724 
       
   725 
       
   726 CMemSpyEngineHelperFbServ::CBitmapObject* CMemSpyEngineHelperFbServ::GetBitmapObjectLC( TAny* aCellAddress )
       
   727     {
       
   728     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - START - aCellAddress: 0x%08x", aCellAddress ));
       
   729 
       
   730     // What we will return
       
   731     CBitmapObject* object = new(ELeave) CBitmapObject();
       
   732     CleanupStack::PushL( object );
       
   733 
       
   734     // The data we will read
       
   735     HBufC8* cellData = NULL;
       
   736     
       
   737     // Try to get info about real cell
       
   738     TMemSpyDriverCellType cellType;
       
   739     TInt cellLength;
       
   740     TInt cellNestingLevel;
       
   741     TInt cellAllocationNumber;
       
   742     TInt cellHeaderSize;
       
   743     TAny* cellPayloadAddress;
       
   744 
       
   745     // NOTE: this call may change the value of 'cellAddress'
       
   746     TInt err = iEngine.Driver().WalkHeapGetCellInfo( aCellAddress, cellType, cellLength, cellNestingLevel, cellAllocationNumber, cellHeaderSize, cellPayloadAddress );
       
   747     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - err: %d, cellAddress: 0x%08x, cellLength: %d, cellAllocationNumber: %d, cellType: %d", err, aCellAddress, cellLength, cellAllocationNumber, cellType));
       
   748 
       
   749     if  ( err == KErrNone && cellType == EMemSpyDriverGoodAllocatedCell )
       
   750         {
       
   751         // Check that the cell size meets our expectations - it should be a CBitmapObject, but without the additional "this" pointer
       
   752         // which we have tacked onto the object.
       
   753         const TInt expectedCellSize = sizeof( CBitmapObject ) + cellHeaderSize - sizeof( CBitmapObject* );
       
   754         TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - expectedCellSize: %d, actual: %d, address: 0x%08x", expectedCellSize, cellLength, aCellAddress));
       
   755 
       
   756         if  ( expectedCellSize <= cellLength )
       
   757             {
       
   758             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - cell lengths are good, trying to get cell data..."));
       
   759 
       
   760             // Try to get real cell data        
       
   761             cellData = HBufC8::NewLC( cellLength );
       
   762             TPtr8 pData( cellData->Des() );
       
   763             //
       
   764             err = iEngine.Driver().WalkHeapReadCellData( aCellAddress, pData, cellLength );
       
   765             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - reading cell data returned error: %d", err));
       
   766             }
       
   767         else
       
   768             {
       
   769             TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - not enough data -> KErrCorrupt"));
       
   770             err = KErrCorrupt;
       
   771             }
       
   772         }
       
   773     else
       
   774         {
       
   775         User::Leave( KErrNotFound );
       
   776         }
       
   777 
       
   778     RDesReadStream stream( *cellData );
       
   779     CleanupClosePushL( stream );
       
   780     
       
   781     // Read vtable
       
   782     const TUint32 vTable = stream.ReadUint32L();
       
   783     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - actual vTable: 0x%08x", vTable ));
       
   784     TBool isROMAddress = EFalse;
       
   785     err = User::IsRomAddress( isROMAddress, (TAny*) vTable );
       
   786     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - vtable (0x%08x) is in ROM: %d (error: %d)", vTable, isROMAddress, err));
       
   787     User::LeaveIfError( err );
       
   788 
       
   789     // Skip CObject members
       
   790     (void) stream.ReadL( sizeof( CObject ) ); // skip this much
       
   791     object->iThisPointer = reinterpret_cast< CBitmapObject* >( cellPayloadAddress );;
       
   792     object->iTop = reinterpret_cast< CBase* >( stream.ReadUint32L() );
       
   793     object->iAddressPointer = reinterpret_cast< CBitwiseBitmap* >( stream.ReadUint32L() );
       
   794     object->iHandle = stream.ReadInt32L();
       
   795     object->iCleanBitmap = reinterpret_cast< CBitmapObject* >( stream.ReadUint32L() );
       
   796 
       
   797     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iThisPointer:    0x%08x", object->iThisPointer ));
       
   798     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iTop:            0x%08x", object->iTop ));
       
   799     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iAddressPointer: 0x%08x", object->iAddressPointer ));
       
   800     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iHandle:         0x%08x", object->iHandle ));
       
   801     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - object->iCleanBitmap:    0x%08x", object->iCleanBitmap ));
       
   802     
       
   803     // Clean up - don't need this data anymore. Real data is in another cell
       
   804     CleanupStack::PopAndDestroy( 2, cellData );  // stream & cellData
       
   805 
       
   806     TRACE( RDebug::Printf("CMemSpyEngineHelperFbServ::GetBitmapObjectLC() - END - aCellAddress: 0x%08x", aCellAddress ));
       
   807     return object;
       
   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 
       
   835 
       
   836 CMemSpyEngineFbServBitmapArray::CMemSpyEngineFbServBitmapArray( const RArray<TInt>& aBitmapHandles )
       
   837 :   CActive( CActive::EPriorityIdle ), iBitmapHandles( aBitmapHandles ), iGranularity( 0 )
       
   838     {
       
   839     CActiveScheduler::Add( this );
       
   840     }
       
   841 
       
   842 
       
   843 CMemSpyEngineFbServBitmapArray::CMemSpyEngineFbServBitmapArray( TInt aPriority, const RArray<TInt>& aBitmapHandles, MMemSpyEngineFbSerbBitmapArrayObserver& aObserver, TInt aGranularity )
       
   844 :   CActive( aPriority ), iBitmapHandles( aBitmapHandles ), iObserver( &aObserver ), iGranularity( aGranularity )
       
   845     {
       
   846     CActiveScheduler::Add( this );
       
   847     CompleteSelf();
       
   848     }
       
   849 
       
   850 
       
   851 EXPORT_C CMemSpyEngineFbServBitmapArray::~CMemSpyEngineFbServBitmapArray()
       
   852     {
       
   853     Cancel();
       
   854     //
       
   855     iBitmaps.ResetAndDestroy();
       
   856     iBitmaps.Close();
       
   857     }
       
   858 
       
   859 
       
   860 void CMemSpyEngineFbServBitmapArray::ConstructL()
       
   861     {
       
   862     if  ( !IsActive() )
       
   863         {
       
   864         // Sync construction...
       
   865         const TInt count = iBitmapHandles.Count();
       
   866         for(TInt i=0; i<count; i++ )
       
   867             {
       
   868             const TInt handle = iBitmapHandles[ i ];
       
   869             //
       
   870             TRAP_IGNORE( CreateBitmapL( handle ) );
       
   871             }
       
   872     
       
   873         SortBySizeL();
       
   874         }
       
   875     }
       
   876 
       
   877 
       
   878 EXPORT_C CMemSpyEngineFbServBitmapArray* CMemSpyEngineFbServBitmapArray::NewL( const RArray<TInt>& aBitmapHandles )
       
   879     {
       
   880     CMemSpyEngineFbServBitmapArray* self = new(ELeave) CMemSpyEngineFbServBitmapArray( aBitmapHandles );
       
   881     CleanupStack::PushL( self );
       
   882     self->ConstructL();
       
   883     CleanupStack::Pop( self );
       
   884     return self;
       
   885     }
       
   886 
       
   887 
       
   888 EXPORT_C CMemSpyEngineFbServBitmapArray* CMemSpyEngineFbServBitmapArray::NewL( TInt aPriority, const RArray<TInt>& aBitmapHandles, MMemSpyEngineFbSerbBitmapArrayObserver& aObserver, TInt aGranularity )
       
   889     {
       
   890     CMemSpyEngineFbServBitmapArray* self = new(ELeave) CMemSpyEngineFbServBitmapArray( aPriority, aBitmapHandles, aObserver, aGranularity );
       
   891     CleanupStack::PushL( self );
       
   892     self->ConstructL();
       
   893     CleanupStack::Pop( self );
       
   894     return self;
       
   895     }
       
   896 
       
   897 
       
   898 EXPORT_C TInt CMemSpyEngineFbServBitmapArray::Count() const
       
   899     {
       
   900     return iBitmaps.Count();
       
   901     }
       
   902 
       
   903 
       
   904 EXPORT_C CMemSpyEngineFbServBitmap& CMemSpyEngineFbServBitmapArray::At( TInt aIndex )
       
   905     {
       
   906     return *iBitmaps[ aIndex ];
       
   907     }
       
   908 
       
   909 
       
   910 EXPORT_C const CMemSpyEngineFbServBitmap& CMemSpyEngineFbServBitmapArray::At( TInt aIndex ) const
       
   911     {
       
   912     return *iBitmaps[ aIndex ];
       
   913     }
       
   914 
       
   915 
       
   916 EXPORT_C CMemSpyEngineFbServBitmap& CMemSpyEngineFbServBitmapArray::BitmapByHandleL( TInt aHandle )
       
   917     {
       
   918     const TInt index = BitmapIndexByHandle( aHandle );
       
   919     User::LeaveIfError( index );
       
   920     CMemSpyEngineFbServBitmap& ret = At( index );
       
   921     return ret;
       
   922     }
       
   923 
       
   924 
       
   925 EXPORT_C TInt CMemSpyEngineFbServBitmapArray::BitmapIndexByHandle( TInt aHandle ) const
       
   926     {
       
   927     TInt ret = KErrNotFound;
       
   928     //
       
   929     const TInt count = Count();
       
   930     for( TInt i=0; i<count; i++ )
       
   931         {
       
   932         const CMemSpyEngineFbServBitmap& bitmap = At( i );
       
   933         //
       
   934         if  ( bitmap.Handle() == aHandle )
       
   935             {
       
   936             ret = i;
       
   937             break;
       
   938             }
       
   939         }
       
   940     //
       
   941     return ret;
       
   942     }
       
   943 
       
   944 
       
   945 EXPORT_C TInt CMemSpyEngineFbServBitmapArray::MdcaCount() const
       
   946     {
       
   947     return Count();
       
   948     }
       
   949 
       
   950 
       
   951 EXPORT_C TPtrC CMemSpyEngineFbServBitmapArray::MdcaPoint( TInt aIndex ) const
       
   952     {
       
   953     const CMemSpyEngineFbServBitmap& bitmap = At( aIndex );
       
   954     return TPtrC( bitmap.Caption() );
       
   955     }
       
   956 
       
   957 
       
   958 void CMemSpyEngineFbServBitmapArray::RunL()
       
   959     {
       
   960     const TInt bitmapHandleCount = iBitmapHandles.Count();
       
   961     const TInt endIndex = Min( iIndex + iGranularity, bitmapHandleCount );
       
   962     //
       
   963     for( ; iIndex < endIndex; iIndex++ )
       
   964         {
       
   965         const TInt handle = iBitmapHandles[ iIndex ];
       
   966         //
       
   967         TRAP_IGNORE( CreateBitmapL( handle ) );
       
   968         }
       
   969     
       
   970     // Report progress & queue for next iteration
       
   971     MMemSpyEngineFbSerbBitmapArrayObserver::TEvent event = MMemSpyEngineFbSerbBitmapArrayObserver::EBitmapArrayConstructionComplete;
       
   972     if  ( endIndex < bitmapHandleCount )
       
   973         {
       
   974         CompleteSelf();
       
   975         event = MMemSpyEngineFbSerbBitmapArrayObserver::EBitmapItemsCreated;
       
   976         }
       
   977     else
       
   978         {
       
   979         SortBySizeL();
       
   980         }
       
   981 
       
   982     if  ( iObserver )
       
   983         {
       
   984         iObserver->HandleFbServBitmapArrayEventL( event );
       
   985         }
       
   986     }
       
   987 
       
   988 
       
   989 void CMemSpyEngineFbServBitmapArray::DoCancel()
       
   990     {
       
   991     // Nothing to do
       
   992     }
       
   993 
       
   994 
       
   995 TInt CMemSpyEngineFbServBitmapArray::RunError( TInt /*aError*/ )
       
   996     {
       
   997     return KErrNone;
       
   998     }
       
   999 
       
  1000 
       
  1001 void CMemSpyEngineFbServBitmapArray::CompleteSelf()
       
  1002     {
       
  1003     TRequestStatus* status = &iStatus;
       
  1004     User::RequestComplete( status, KErrNone );
       
  1005     SetActive();
       
  1006     }
       
  1007 
       
  1008 
       
  1009 void CMemSpyEngineFbServBitmapArray::CreateBitmapL( TInt aHandle )
       
  1010     {
       
  1011     CMemSpyEngineFbServBitmap* bitmap = CMemSpyEngineFbServBitmap::NewLC( aHandle );
       
  1012     iBitmaps.AppendL( bitmap );
       
  1013     CleanupStack::Pop( bitmap );
       
  1014     }
       
  1015 
       
  1016 
       
  1017 void CMemSpyEngineFbServBitmapArray::SortBySizeL()
       
  1018     {
       
  1019     TLinearOrder< CMemSpyEngineFbServBitmap > comparer( CompareBySize );
       
  1020     iBitmaps.Sort( comparer );
       
  1021     }
       
  1022 
       
  1023 
       
  1024 TInt CMemSpyEngineFbServBitmapArray::CompareBySize( const CMemSpyEngineFbServBitmap& aLeft, const CMemSpyEngineFbServBitmap& aRight )
       
  1025     {
       
  1026     TInt ret = 1;
       
  1027     //
       
  1028     if  ( aLeft.BitmapSizeInBytes() > aRight.BitmapSizeInBytes() )
       
  1029         {
       
  1030         ret = -1;
       
  1031         }
       
  1032     else if ( aLeft.BitmapSizeInBytes() == aRight.BitmapSizeInBytes() )
       
  1033         {
       
  1034         ret = 0;
       
  1035         }
       
  1036     //
       
  1037     return ret;
       
  1038     }
       
  1039 
       
  1040 
       
  1041 
       
  1042 
       
  1043 
       
  1044 
       
  1045 
       
  1046 
       
  1047 
       
  1048 
       
  1049 
       
  1050 
       
  1051 
       
  1052 
       
  1053 
       
  1054 
       
  1055 
       
  1056 
       
  1057 
       
  1058 
       
  1059 
       
  1060 
       
  1061 CMemSpyEngineFbServBitmap::CMemSpyEngineFbServBitmap()
       
  1062 :   CDesCArrayFlat( 5 )
       
  1063     {
       
  1064     }
       
  1065 
       
  1066 
       
  1067 EXPORT_C CMemSpyEngineFbServBitmap::~CMemSpyEngineFbServBitmap()
       
  1068     {
       
  1069     delete iBitmap;
       
  1070     delete iCaption;
       
  1071     }
       
  1072 
       
  1073 
       
  1074 void CMemSpyEngineFbServBitmap::ConstructL( TInt aHandle )
       
  1075     {
       
  1076     iBitmap = new(ELeave) CFbsBitmap();
       
  1077     const TInt error = iBitmap->Duplicate( aHandle );
       
  1078     User::LeaveIfError( error );
       
  1079     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1080 
       
  1081     // Prepare caption
       
  1082     _LIT( KCaptionFormat, "\t%2d bpp, %S\t\t%4d x %4d pixels" );
       
  1083     iCaption = HBufC::NewL( 128 );
       
  1084     TPtr pCaption( iCaption->Des() );
       
  1085     
       
  1086     // Create size string
       
  1087     const TMemSpySizeText size( MemSpyEngineUtils::FormatSizeText( header.iBitmapSize ) );
       
  1088     pCaption.AppendFormat( KCaptionFormat, header.iBitsPerPixel, &size, header.iSizeInPixels.iWidth, header.iSizeInPixels.iHeight );
       
  1089 
       
  1090     // Prepare items
       
  1091     PrepareItemsL();
       
  1092     }
       
  1093 
       
  1094 
       
  1095 EXPORT_C CMemSpyEngineFbServBitmap* CMemSpyEngineFbServBitmap::NewLC( TInt aHandle )
       
  1096     {
       
  1097     CMemSpyEngineFbServBitmap* self = new(ELeave) CMemSpyEngineFbServBitmap();
       
  1098     CleanupStack::PushL( self );
       
  1099     self->ConstructL( aHandle );
       
  1100     return self;
       
  1101     }
       
  1102 
       
  1103 
       
  1104 TInt CMemSpyEngineFbServBitmap::BitmapSizeInBytes() const
       
  1105     {
       
  1106     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1107     return header.iBitmapSize;
       
  1108     }
       
  1109 
       
  1110 
       
  1111 EXPORT_C const TDesC& CMemSpyEngineFbServBitmap::Caption() const
       
  1112     {
       
  1113     return *iCaption;
       
  1114     }
       
  1115 
       
  1116 
       
  1117 EXPORT_C CFbsBitmap& CMemSpyEngineFbServBitmap::Bitmap()
       
  1118     {
       
  1119     return *iBitmap;
       
  1120     }
       
  1121 
       
  1122 
       
  1123 EXPORT_C const CFbsBitmap& CMemSpyEngineFbServBitmap::Bitmap() const
       
  1124     {
       
  1125     return *iBitmap;
       
  1126     }
       
  1127 
       
  1128 
       
  1129 EXPORT_C TInt CMemSpyEngineFbServBitmap::Handle() const
       
  1130     {
       
  1131     return iBitmap->Handle();
       
  1132     }
       
  1133 
       
  1134 
       
  1135 EXPORT_C void CMemSpyEngineFbServBitmap::OutputDataL( CMemSpyEngine& aEngine ) const
       
  1136     {
       
  1137     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1138     //
       
  1139     _LIT(KMemSpyFBServHex, "0x%08x");
       
  1140     _LIT(KMemSpyFBServDecimal, "%d");
       
  1141     //
       
  1142     HBufC* columns = HBufC::NewLC( 1024 );
       
  1143     TPtr pColumns( columns->Des() );
       
  1144     //
       
  1145     pColumns.AppendFormat( KMemSpyFBServHex, Handle() );
       
  1146     pColumns.Append( KMemSpyEngineFBServComma );
       
  1147     //
       
  1148     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iBitmapSize );
       
  1149     pColumns.Append( KMemSpyEngineFBServComma );
       
  1150     //
       
  1151     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iSizeInPixels.iWidth );
       
  1152     pColumns.Append( KMemSpyEngineFBServComma );
       
  1153     //
       
  1154     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iSizeInPixels.iHeight );
       
  1155     pColumns.Append( KMemSpyEngineFBServComma );
       
  1156     //
       
  1157     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iBitsPerPixel );
       
  1158     pColumns.Append( KMemSpyEngineFBServComma );
       
  1159     //
       
  1160     pColumns.AppendFormat( KMemSpyFBServDecimal, header.iColor );
       
  1161     pColumns.Append( KMemSpyEngineFBServComma );
       
  1162     //
       
  1163     TBuf<24> fileCompressionType;
       
  1164     GetFileCompressionTypeAsString( header.iCompression, fileCompressionType );
       
  1165     pColumns.Append( fileCompressionType );
       
  1166     pColumns.Append( KMemSpyEngineFBServComma );
       
  1167     //
       
  1168     GetExportableFileNameL( pColumns );
       
  1169     //
       
  1170     aEngine.Sink().OutputLineL( pColumns );
       
  1171     CleanupStack::PopAndDestroy( columns );
       
  1172     }
       
  1173 
       
  1174 
       
  1175 EXPORT_C void CMemSpyEngineFbServBitmap::OutputDataColumnsL( CMemSpyEngine& aEngine )
       
  1176     {
       
  1177     HBufC* columns = HBufC::NewLC( 1024 );
       
  1178     TPtr pColumns( columns->Des() );
       
  1179     //
       
  1180     _LIT(KCol1, "Handle");
       
  1181     pColumns.Append( KCol1 );
       
  1182     pColumns.Append( KMemSpyEngineFBServComma );
       
  1183     //
       
  1184     _LIT(KCol2, "Uncompressed Size (Bytes)");
       
  1185     pColumns.Append( KCol2 );
       
  1186     pColumns.Append( KMemSpyEngineFBServComma );
       
  1187     //
       
  1188     _LIT(KCol3, "Width");
       
  1189     pColumns.Append( KCol3 );
       
  1190     pColumns.Append( KMemSpyEngineFBServComma );
       
  1191     //
       
  1192     _LIT(KCol4, "Height");
       
  1193     pColumns.Append( KCol4 );
       
  1194     pColumns.Append( KMemSpyEngineFBServComma );
       
  1195     //
       
  1196     _LIT(KCol5, "BPP");
       
  1197     pColumns.Append( KCol5 );
       
  1198     pColumns.Append( KMemSpyEngineFBServComma );
       
  1199     //
       
  1200     _LIT(KCol6, "Color");
       
  1201     pColumns.Append( KCol6 );
       
  1202     pColumns.Append( KMemSpyEngineFBServComma );
       
  1203     //
       
  1204     _LIT(KCol7, "Compression");
       
  1205     pColumns.Append( KCol7 );
       
  1206     pColumns.Append( KMemSpyEngineFBServComma );
       
  1207     //
       
  1208     _LIT(KCol8, "File Name");
       
  1209     pColumns.Append( KCol8 );
       
  1210     //
       
  1211     aEngine.Sink().OutputLineL( pColumns );
       
  1212     CleanupStack::PopAndDestroy( columns );
       
  1213     }
       
  1214 
       
  1215 
       
  1216 EXPORT_C void CMemSpyEngineFbServBitmap::GetExportableFileNameL( TDes& aAppendName ) const
       
  1217     {
       
  1218     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1219 
       
  1220     // Create a filename
       
  1221     aAppendName.AppendFormat( KMemSpyEngineFBServExportFileName, Handle(), header.iBitsPerPixel, header.iSizeInPixels.iWidth, header.iSizeInPixels.iHeight );
       
  1222     }
       
  1223 
       
  1224 
       
  1225 void CMemSpyEngineFbServBitmap::GetExportableFileNameL( const TMemSpyEngineFBServBitmapInfo& aInfo, TDes& aAppendName )
       
  1226     {
       
  1227     aAppendName.AppendFormat( KMemSpyEngineFBServExportFileName, aInfo.iHandle, aInfo.iBitsPerPixel, aInfo.iSizeInPixels.iWidth, aInfo.iSizeInPixels.iHeight );
       
  1228     }
       
  1229 
       
  1230 
       
  1231 void CMemSpyEngineFbServBitmap::PrepareItemsL()
       
  1232     {
       
  1233     const SEpocBitmapHeader header( iBitmap->Header() );
       
  1234     TBuf<256> item;
       
  1235 
       
  1236     // View bitmap (ugly, but needed by UI)
       
  1237     _LIT(KCaptionMinus2, "\tView Bitmap\t\t");
       
  1238     AppendL( KCaptionMinus2 );
       
  1239 
       
  1240     // Dimensions
       
  1241     _LIT(KCaptionMinus1, "\tDimensions\t\t%5d x %5d");
       
  1242     item.Format( KCaptionMinus1, header.iSizeInPixels.iWidth, header.iSizeInPixels.iHeight );
       
  1243     AppendL( item );
       
  1244 
       
  1245     // Handle
       
  1246     _LIT(KCaption0, "\tHandle\t\t0x%08x");
       
  1247     item.Format( KCaption0, iBitmap->Handle() );
       
  1248     AppendL( item );
       
  1249 
       
  1250     // In Rom?
       
  1251     _LIT(KCaption1, "\tIn ROM?\t\t%S");
       
  1252     _LIT(KIsRomBitmap, "Yes");
       
  1253     _LIT(KNotRomBitmap, "No");
       
  1254     if  ( iBitmap->IsRomBitmap() )
       
  1255         {
       
  1256         item.Format( KCaption1, &KIsRomBitmap );
       
  1257         }
       
  1258     else
       
  1259         {
       
  1260         item.Format( KCaption1, &KNotRomBitmap );
       
  1261         }
       
  1262     AppendL( item );
       
  1263 
       
  1264     // Bits per pixel
       
  1265     _LIT(KCaption2, "\tBits Per Pixel\t\t%2d");
       
  1266     item.Format( KCaption2, header.iBitsPerPixel );
       
  1267     AppendL( item );
       
  1268 
       
  1269     // Size of uncompressed bitmap data
       
  1270     _LIT(KCaption3, "\tUncompressed data size\t\t%S");
       
  1271     const TMemSpySizeText sizeStringUncompressed( MemSpyEngineUtils::FormatSizeText( header.iBitmapSize ) );
       
  1272     item.Format( KCaption3, &sizeStringUncompressed );
       
  1273     AppendL( item );
       
  1274 
       
  1275     // Palette entry count
       
  1276     _LIT(KCaption4, "\tNumber of palette entries\t\t%d");
       
  1277     item.Format( KCaption4, header.iPaletteEntries );
       
  1278     AppendL( item );
       
  1279 
       
  1280     // Colour
       
  1281     _LIT(KCaption5, "\tColour\t\t%d");
       
  1282     item.Format( KCaption5, header.iColor);
       
  1283     AppendL( item );
       
  1284 
       
  1285     // Palette entry count
       
  1286     _LIT(KCaption6, "\tFile compression type\t\t%S");
       
  1287     TBuf<24> fileCompressionType;
       
  1288     GetFileCompressionTypeAsString( header.iCompression, fileCompressionType );
       
  1289     item.Format( KCaption6, &fileCompressionType );
       
  1290     AppendL( item );
       
  1291     }
       
  1292 
       
  1293 
       
  1294 void CMemSpyEngineFbServBitmap::GetFileCompressionTypeAsString( TBitmapfileCompression aType, TDes& aString )
       
  1295     {
       
  1296     _LIT(KUnknown, "Unknown");
       
  1297     _LIT(KNoCompression, "None");
       
  1298     _LIT(KRLE, "RLE");
       
  1299     _LIT(KTwelveBitRLE, "12-bit RLE");
       
  1300     _LIT(KSixteenBitRLE, "16-bit RLE");
       
  1301     _LIT(KTwentyFourBitRLE, "24-bit RLE");
       
  1302     _LIT(KThirtyTwoBitRLE, "32-bit RLE");
       
  1303     //
       
  1304     switch( aType )
       
  1305         {
       
  1306     case ENoBitmapCompression:
       
  1307         aString = KNoCompression;
       
  1308         break;
       
  1309     case EByteRLECompression:
       
  1310         aString = KRLE;
       
  1311         break;
       
  1312     case ETwelveBitRLECompression:
       
  1313         aString = KTwelveBitRLE;
       
  1314         break;
       
  1315     case ESixteenBitRLECompression:
       
  1316         aString = KSixteenBitRLE;
       
  1317         break;
       
  1318     case ETwentyFourBitRLECompression:
       
  1319         aString = KTwentyFourBitRLE;
       
  1320         break;
       
  1321     case EThirtyTwoUBitRLECompression:
       
  1322         aString = KThirtyTwoBitRLE;
       
  1323         break;
       
  1324     default:
       
  1325     case ERLECompressionLast:
       
  1326         aString = KUnknown;
       
  1327         break;
       
  1328         }
       
  1329     }
       
  1330 
       
  1331 
       
  1332 
       
  1333 
       
  1334 
       
  1335 
       
  1336 
       
  1337