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 |
|