diff -r 61bc0f252b2b -r bac7acad7cb3 camerauis/cameraapp/generic/src/CamDocument.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/camerauis/cameraapp/generic/src/CamDocument.cpp Wed Sep 01 12:30:54 2010 +0100 @@ -0,0 +1,1095 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Document class for Camera Application* +*/ + +#include "camlogging.h" +#include "CamLogger.h" + +#ifdef _DEBUG +#include + + +//#define _AO_TRACKING +#ifdef _AO_TRACKING + +static void ReplaceCurrentASL(); +static void RestoreCurrentAS(); + +class CFilterScheduler; + +class CFilterInfo : public CBase + { + friend class CFilterScheduler; + +public: + static CFilterInfo* NewL(); + +protected: + struct CFilterStruct + { + CFilterStruct(CActive* aActiveAddPointer, char* aActiveLogInfo, + CFilterStruct* aLink); + CActive *iActiveAddPointer; + char *iActiveLogInfo; + CFilterStruct *iLink; + }; + +protected: + CFilterInfo(); + void ConstructL(); + void AddInfoL(CActive* aActiveAddPointer, char* aActiveLogInfo, + CFilterStruct * &aLink); + char* FindInfo(CActive *); + ~CFilterInfo(); +protected: + struct CFilterStruct *iFiSHead; + + }; + +class CFilterScheduler : public CActiveScheduler + { + friend void ReplaceCurrentASL(); + friend void RestoreCurrentAS(); + +public: + static CFilterScheduler* NewL(); +private: + static CActiveScheduler* iSavedFS; +public: + using CActiveScheduler::Start; + // It is used as a hook, which makes possible to collect meaningful + // information about every active object + virtual TInt Extension_(TUint aUid, TAny*& a0, TAny* a1); +protected: + void ConstructL(); + CFilterScheduler(); + ~CFilterScheduler(); + + void DebugPrint(); + char* FindInfo(CActive *); + // it has to default to CActiveScheduler implementations + virtual void WaitForAnyRequest(); + // it has to default to CActiveScheduler implementations + virtual void Error(TInt aError) const; + // It has to be implemented since this is a concrete class + virtual void OnStarting() + { + } + virtual void OnStopping() + { + } + virtual void Reserved_1() + { + } + virtual void Reserved_2() + { + } +private: + CFilterInfo *iFilterInfo; + }; + +CActiveScheduler* CFilterScheduler::iSavedFS= NULL; + +CFilterInfo* CFilterInfo::NewL() + { + CFilterInfo* self = new( ELeave ) CFilterInfo(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CFilterInfo::AddInfoL(CActive* aActiveAddPointer, char* aActiveLogInfo, + CFilterInfo::CFilterStruct* &aLink) + { + PRINT( _L("Camera => CFilterInfo::AddInfoL") ); + CFilterStruct *pFiS = new( ELeave ) CFilterStruct( aActiveAddPointer, + aActiveLogInfo, aLink ); + pFiS->iLink = aLink; + aLink = pFiS; + } + +char* CFilterInfo::FindInfo(CActive *aActive) + { + char *pInfo = (char *)NULL; + CFilterStruct *pFiS = iFiSHead; + while (pFiS != NULL) + { + if (pFiS->iActiveAddPointer == aActive) + { + pInfo = pFiS->iActiveLogInfo; + break; + } + pFiS = pFiS->iLink; + } + return pInfo; + } + +CFilterInfo::CFilterStruct::CFilterStruct(CActive* aActiveAddPointer, + char* aActiveLogInfo, CFilterInfo::CFilterStruct* aLink) + { + iActiveAddPointer = aActiveAddPointer; + iActiveLogInfo = aActiveLogInfo; + iLink = aLink; + } + +void CFilterInfo::ConstructL() + { + } + +CFilterInfo::CFilterInfo() + { + iFiSHead = NULL; + } + +CFilterInfo::~CFilterInfo() + { + } + +CFilterScheduler* CFilterScheduler::NewL() + { + CFilterScheduler* self = new( ELeave ) CFilterScheduler(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void ReplaceCurrentASL() + { + CFilterScheduler *fSH = CFilterScheduler::NewL(); + //if (fSH != NULL) + CFilterScheduler::iSavedFS = CActiveScheduler::Replace(fSH); + } + +void RestoreCurrentAS() + { + + if (CFilterScheduler::iSavedFS != NULL) + { + CActiveScheduler *iFS = + CActiveScheduler::Replace(CFilterScheduler::iSavedFS); + delete iFS; + } + + } + +TInt CFilterScheduler::Extension_(TUint aUid, TAny*& a0, TAny* a1) + { + if (aUid == 0) + { + TRAPD( rr, iFilterInfo->AddInfoL( (CActive *)a0, (char *)a1, + iFilterInfo->iFiSHead ) ); + return rr; + } + return KErrExtensionNotSupported;; + } + +void CFilterScheduler::WaitForAnyRequest() + { + // Here is the printout at every wait + DebugPrint(); + if (iSavedFS) + iSavedFS->WaitForAnyRequest(); + else + User::WaitForAnyRequest(); + } + +void CFilterScheduler::Error(TInt aError) const + { + if (iSavedFS) + iSavedFS->Error(aError); + } + +CFilterScheduler::CFilterScheduler() + { + } + +CFilterScheduler::~CFilterScheduler() + { + iSavedFS = NULL; + } + +void CFilterScheduler::ConstructL() + { + /* iActive = CFilterActive::NewL( this ); */ + iFilterInfo = CFilterInfo::NewL(); + } + +char* CFilterScheduler::FindInfo(CActive * aA) + { + char *pFI= NULL; + if (iFilterInfo) + pFI = iFilterInfo->FindInfo(aA); + return pFI; + } + +void CFilterScheduler::DebugPrint() + { + RDebug::Print( _L( " Camera => CFilterScheduler::DebugPrint" )); + TDblQueIter q(iActiveQ); + q.SetToFirst(); + while (q != NULL) + { + CActive *pR = q++; + /* TInt pri = pR->iLink.iPriority; */ + TInt pri = pR->Priority(); + TInt stat = pR->iStatus.Int(); // TRequestStatus + // find active objects identification string otherwise + // print it's address + char *pText = FindInfo(pR); + + if (pR->IsActive() ) + { + if (stat == KRequestPending) + { + // active, pending + if (pText) + RDebug::Printf( + "Camera: CFilterScheduler::DebugPrint: %s - active/pending - priority: %d - req status: %d", + pText, pri, stat); + else + RDebug::Printf( + "Camera: CFilterScheduler::DebugPrint: %x - active/pending - priority: %d - req status: %d", + (TInt)pR, pri, stat); + } + else + { + // active, not pending + if (pText) + RDebug::Printf( + "Camera: CFilterScheduler::DebugPrint: %s - active/not pending - priority: %d - req status: %d", + pText, pri, stat); + else + RDebug::Printf( + "Camera: CFilterScheduler::DebugPrint: %x - active/not pending - priority: %d - req status: %d", + (TInt)pR, pri, stat); + } + } + else + { + // not active + if (pText) + RDebug::Printf( + "Camera: CFilterScheduler::DebugPrint: %s - not active: priority: %d - req status: %x", + pText, pri, stat); + else + RDebug::Printf( + "Camera: CFilterScheduler::DebugPrint: %x - not active: priority: %d - req status: %x", + (TInt)pR, pri, stat); + } + } + RDebug::Print( _L( "Camera <= CFilterScheduler::DebugPrint" )); + } +#endif // _AO_TRACKING +#endif // _DEBUG +// INCLUDE FILES +#include "CamAppUi.h" +#include "CamDocument.h" +#include "CamPerformance.h" +#include "CamAppController.h" + +#ifdef _DEBUG +// These are used for memory allocation tracing. +#undef _MEMORY_TRACKING +//#define _MEMORY_TRACKING +#ifdef _MEMORY_TRACKING +#include + + +// stores the last RDebug::Print or RDebug::Printf calls +// string from cameraapp code if SInUse was ETrue +static char *sLastHeapContext = NULL; +// controls the context taking if it is EFalse sLastHeapContext is not updated +// used also by RTraceAllocator::Alloc, Free, Realloc etc. +static TBool sInUse = EFalse; + +// forward declaration for friend statements. +class PtrAssocArray; +class RTraceAllocator; + + +// class which stores heap context info +// per allocation +// every allocation will have one entry in the hash table +class AllocHeapContext + { + // added as friend for writing less set/get methods + friend class PtrAssocArray; +public: + AllocHeapContext(TAny* aPtr, TInt aSize, char* aText1, + AllocHeapContext *aNext = NULL); + ~AllocHeapContext(); +protected: + // stored pointer of the allocation + TAny* iPtr; + // stored size of the allocation + TInt iSize; + // context string of the allocation, collected from + // RDebug::Print, RDebug::Printf calls + char* iText1; + // link field to the next context if they are more with same hash value + // in PtrAssocArray then they can be linked into a single linked list + AllocHeapContext *iNext; + }; + +// class which stores the hash table +class PtrAssocArray + { +public: + // constructor takes a Heap to use for allocations and deallocations done by + // this class, + // Note: For not perturbing normal allocation/deallocation a separate heap is + // used for internal needs. + PtrAssocArray(RHeap *aHeap); + ~PtrAssocArray(); + // insert an element into the list + // return KErrArgument if aAHC == NULL + // otherwise KErrNone + TInt Insert(AllocHeapContext* aAHC); + // find an element in the list + // return NULL pointer if cannot find, this means + // also the case if aPtr == NULL + AllocHeapContext *Find(TAny *aPtr); + // removes an element from the list + // if aPtr == NULL does nothing and returns KErrArgument. + // Returns KErrNotFound and does nothnig if cannot find it. + // In normal case return KErrNone. + TInt Remove(TAny *aPtr); + // Prints the elements in the list + void PrintLeaks(); + // cleans the list. It could be used if implemented for restarting + // leak search from a certain point onward. + // Note: only the list elements are cleaned, for real deallocation purposes + // it cannot be used as this system doesn't offers a reference counting of + // the pointer. It still can be used even that idea for debugging. + void CleanTables(); +protected: + // the hash function itself, + // simply takes the middle 2 bytes of a 4 byte unsigned, + // to which the pointer is converted + TUint Hash(TAny *aPtr); + // internal structures for has array entries + // iInfo points + struct AssocHashTbl + { + AllocHeapContext* iInfo; + }; + // the hash array + AssocHashTbl iAHT[65536]; + // pointer to iOwnHeap of + RHeap *iHeap; + }; + +// the allocator class +class RTraceAllocator : public RAllocator + { +public: + // return current heap, just utility + static RTraceAllocator* OwnAllocator() + { + RTraceAllocator& currentHeap = (RTraceAllocator &)User::Heap(); + return ¤tHeap; + } + // Simple utility function for getting a size of a char* + // User::StringLength looks similar, + // but this return 0 if aStr == NULL. + static TUint StrSize(char * aStr); + // stores the current heap for calls forwarding to that ones + // implementation + RTraceAllocator(RHeap *aCurrentHeap); + // destructor sets sInUse to EFalse as iOwnHeap is not available any + // more + ~RTraceAllocator() + { + iOwnHeap->Close(); + sInUse = EFalse; + } + + // These virtuals needs to be overwritten + // there functionality is documented by Symbian + virtual TAny* Alloc(TInt aSize); + virtual void Free(TAny* aPtr); + virtual TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode = 0); + virtual TInt AllocLen(const TAny* aCell) const; + virtual TInt Compress(); + virtual void Reset(); + virtual TInt AllocSize(TInt& aTotalAllocSize) const; + virtual TInt Available(TInt& aBiggestBlock) const; + virtual TInt DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL); + // print entries in hash table, it is just a proxy method + void PrintLeaks() + { + iAHM->PrintLeaks(); + } + // clean the tables it is just a proxy + void CleanTables() + { + iAHM->CleanTables(); + } + // frees memory from own heap + void FreeOwn(TAny* aPtr) + { + iOwnHeap->Free(aPtr); + } + // allocates from own heap and fills with 0 + TAny* AllocZOwn(TInt aSize) + { + return iOwnHeap->AllocZ(aSize); + } + // returns the saved heap + RHeap* SavedHeap() + { + return iHeap; + } + +protected: + // the original heap of the application, which does the real + // allocation. All allocations are deferred to it + RHeap* iHeap; + // A heap for own allocations, different than the one used by + // cameraapp process + RHeap* iOwnHeap; + // pointer to the hash table + PtrAssocArray* iAHM; + }; + + +#if defined( _UNICODE ) + +// just, because they are needed +class TestOverflowTruncate : public TDes16Overflow + { +public: + virtual void Overflow(TDes16& /* aDes */) + { + } + ; + }; + +#else + +class TestOverflowTruncate : public TDes8Overflow + { +public: + virtual void Overflow(TDes8 &aDes) + {}; + }; + +#endif + +// just, because they are needed +class TestOverflowTruncate8 : public TDes8Overflow + { +public: + virtual void Overflow(TDes8& /*aDes*/) + { + } + }; + + +// RDebug::Print is overwritten, because it is used +EXPORT_C TInt RDebug::Print( TRefByValue aFmt,... ) + { + TestOverflowTruncate overflow; + VA_LIST list; + VA_START(list,aFmt); + TBuf<0x100> buf; + buf.AppendFormatList( aFmt, list, &overflow ); +#ifdef _UNICODE + TPtr8 p( buf.Collapse() ); + + // remember it + char *context = ( char *)p.Ptr(); + if( sInUse ) + { + if( sLastHeapContext ) + { + //free it + RTraceAllocator::OwnAllocator()->FreeOwn( sLastHeapContext ); + sLastHeapContext = NULL; + } + + sLastHeapContext = (char *)RTraceAllocator::OwnAllocator()->AllocZOwn( 0x100 ); + memcpy( sLastHeapContext, context, 0x100 ); + } + // instead of Exec::DebugPrint((TAny*)&p, 0); + // RawPrint is used + // it could have been this hacked to, but it is not seen necessary + // as recording context from Printf/Print seen as enough + RDebug::RawPrint( p ); +#else + TPtr8 p( buf ); + // rember it + sLastHeapContext = ( char *)p; + RDebug::RawPrint( p ); +#endif + return 0; + } + +EXPORT_C void RDebug::Printf( const char* aFmt, ... ) + { + TestOverflowTruncate8 overflow; + VA_LIST list; + VA_START( list,aFmt ); + TPtrC8 fmt( (const TText8*)aFmt ); + TBuf8<0x100> buf; + buf.AppendFormatList(fmt, list, &overflow ); + TPtrC8 p( buf /* (TUint8 *)(buf.Ptr()), 0x100 */); + + // rember it + char *context = ( char *)p.Ptr(); + if( sInUse ) + { + if( sLastHeapContext ) + { + //free it + RTraceAllocator::OwnAllocator()->FreeOwn( sLastHeapContext ); + sLastHeapContext = NULL; + } + sLastHeapContext = (char *)RTraceAllocator::OwnAllocator()->AllocZOwn( 0x100 ); + memcpy( sLastHeapContext, context, 0x100 ); + } + + RDebug::RawPrint( p ); + } + +// If some custom print wanted RawPrint could be hacked, +// just added for completness +#if 0 +EXPORT_C void RDebug::RawPrint( const TDesC8& aDes ) + { + // Exec::DebugPrint( ( TAny* )&aDes, 1 ); + // above should be replaced by custom print + } + +EXPORT_C void RDebug::RawPrint( const TDesC16& aDes ) + { + TBuf8<0x100> aDes8; + if( aDes.Length()>0x100 ) + { + TPtrC ptr( aDes.Ptr(), 0x100 ); + aDes8.Copy( ptr ); + } + else + aDes8.Copy(aDes); + // Exec::DebugPrint((TAny*)&aDes8, 1); + // above should be replaced by custom print + } +#endif + +AllocHeapContext::AllocHeapContext(TAny* aPtr, TInt aSize, char* aText1, + AllocHeapContext *aNext) + { + iPtr = aPtr; + iSize = aSize; + + // but we need to copy here + if (aText1 == NULL) + { + iText1 = NULL; + } + else + { + iText1 = (char *)RTraceAllocator::OwnAllocator()->AllocZOwn( 0x100); + if (iText1 != NULL) + memcpy(iText1, aText1, 0x100); + else + { + // just for testing + // in this case + // there is no space to store additional info + iText1 = iText1; + } + } + + iNext = aNext; + } + +AllocHeapContext::~AllocHeapContext() + { + if (iText1) + { + RTraceAllocator::OwnAllocator()->FreeOwn(iText1); + iText1 = NULL; + } + } + +PtrAssocArray::PtrAssocArray(RHeap *aHeap) + { + iHeap = aHeap; //points to in Traceallocator iOwnHeap + // not necessary to fill with NULL pointers, as RHeap::Allocz + // does the job already + for (TUint i = 0; i < 65535; i++) + { + iAHT[i].iInfo = NULL; + } + } + +PtrAssocArray::~PtrAssocArray() + { + } + +// insert an element into the list +TInt PtrAssocArray::Insert(AllocHeapContext* aAHC) + { + if ( !aAHC) + { + return KErrArgument; + } + + TUint hashVal = Hash(aAHC->iPtr); + // no collision, add to the table + if (iAHT[hashVal].iInfo == NULL) + { + iAHT[hashVal].iInfo = aAHC; + } + // collision, insert at the beginning of linked list. + else + { + aAHC->iNext = iAHT[hashVal].iInfo; + iAHT[hashVal].iInfo = aAHC; + } + return KErrNone; + } + +TUint PtrAssocArray::Hash(TAny *aPtr) + { + TUint val = (TUint)aPtr; + // take the middle part as hash value 65536 + // different values + val = (val & 0x00FFFF00 ) >> 8; + return val; + } + +// find an element in the list +AllocHeapContext *PtrAssocArray::Find(TAny *aPtr) + { + if ( !aPtr) + return NULL; + TUint hashVal = Hash(aPtr); + AllocHeapContext *ptr = iAHT[hashVal].iInfo; + if (ptr != NULL) + { + do + { + if (ptr->iPtr != aPtr) + { + ptr = ptr->iNext; + continue; + } + else + { + return ptr; + } + } + while (ptr); + } + return NULL; + } + +// remove an element from the list +TInt PtrAssocArray::Remove(TAny *aPtr) + { + if ( !aPtr) + return KErrArgument; + TUint hashVal = Hash(aPtr); + AllocHeapContext *ptr = iAHT[hashVal].iInfo; + if (ptr != NULL) + { + AllocHeapContext *prevPtr= NULL; + do + { + if (ptr->iPtr != aPtr) + { + prevPtr = ptr; + ptr = ptr->iNext; + continue; + } + else + { + // found, we should unlink and free memory + if (prevPtr) + { + prevPtr->iNext = ptr->iNext; + } + else + { + //This is first element in linked list. + if (ptr->iNext==NULL) + { + //List should cleared only if this is last element + iAHT[hashVal].iInfo = NULL; + } + else + { + iAHT[hashVal].iInfo = ptr->iNext; + } + } + // call destructor + ptr->AllocHeapContext::~AllocHeapContext(); + // deallocate + iHeap->Free(ptr); + + return KErrNone; + } + } + while (ptr); + } + return KErrNotFound; + } + +void PtrAssocArray::PrintLeaks() + { + for (TUint i = 0; i < 65536; i++) + { + AllocHeapContext *ptr = iAHT[i].iInfo; + if ( !ptr) + continue; + do + { + if (ptr->iText1 != NULL) + RDebug::Printf( + "Camera:PrintLeaks ptr: %x, size: %d, context: %s", + ptr->iPtr, ptr->iSize, ptr->iText1); + else + RDebug::Printf( + "Camera:PrintLeaks ptr: %x, size: %d, context: <>", + ptr->iPtr, ptr->iSize); + ptr = ptr->iNext; + } + while (ptr); + } + } + +void PtrAssocArray::CleanTables() + { + // Not really necessary to implement + + // disable code below + // by replacing #if 1 by #if 0 +#if 1 + for (TUint i = 0; i < 65536; i++) + { + AllocHeapContext *ptr = iAHT[i].iInfo; + if ( !ptr) + { + //Don't continue... + continue; + } + // deallocate the list + AllocHeapContext *nextPtr= NULL; + while (ptr) //Is this ever true? + { + nextPtr = ptr->iNext; + // call destructor + ptr->AllocHeapContext::~AllocHeapContext(); + // deallocate + iHeap->Free(ptr); + ptr = nextPtr; + } + } +#endif + } + + + +RTraceAllocator::RTraceAllocator(RHeap *aCurrentHeap) + { + iHeap = aCurrentHeap; + iOwnHeap = UserHeap::ChunkHeap( NULL, 1024 * 64, 1024*1024 * 2); + iAHM = (PtrAssocArray *)iOwnHeap->AllocZ(sizeof(PtrAssocArray)); + ::new(iAHM) PtrAssocArray( iOwnHeap ); + sInUse = ETrue; + } + +TAny* RTraceAllocator::Alloc(TInt aSize) + { + TAny *tmp = iHeap->Alloc(aSize); + + sInUse = EFalse; + RDebug::Printf("Camera: RTraceAllocator::Alloc %x, %d", ( TUint32 )tmp, + aSize); + sInUse = ETrue; + + if (tmp) + { + + AllocHeapContext* ahc = (AllocHeapContext*) ( iOwnHeap->AllocZ(sizeof(AllocHeapContext)) ); + // text from last debug print is added + // it can be extended to add more. Timing information for example. + ::new(ahc) AllocHeapContext( tmp, aSize, sLastHeapContext ); + iAHM->Insert(ahc); + } + else + { + // can be commented out this, if failed allocations are not interesting + // RDebug::Printf("M:Alloc %x, %d", (TUint32) tmp, aSize); + } + return tmp; + } + + +void RTraceAllocator::Free(TAny* aPtr) + { + if (aPtr) + { + iAHM->Remove(aPtr); + sInUse = EFalse; + RDebug::Printf("RTraceAllocator::Free %x", ( TUint32 ) aPtr ); + sInUse = ETrue; + iHeap->Free(aPtr); + } + } + + +TAny* RTraceAllocator::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode) + { + TAny *tmp= NULL; + + if (aPtr == NULL) + { + if (aMode != ENeverMove) + { + tmp = RTraceAllocator::Alloc(aSize); + + sInUse = EFalse; + RDebug::Printf("M:Realloc %x %x %d %x", (TUint32) tmp, aPtr, + aSize, aMode); + sInUse = ETrue; + return tmp; + } + else + { + // Now we are allocating a block which should never move... + // Call below could panic USER:42 + tmp = iHeap->ReAlloc(aPtr, aSize, aMode); + + sInUse = EFalse; + RDebug::Printf("M:Realloc %x %x %d %x", (TUint32) tmp, aPtr, + aSize, aMode); + sInUse = ETrue; + + if (tmp) + { + AllocHeapContext *ahc = (AllocHeapContext*) ( iOwnHeap->AllocZ(sizeof(AllocHeapContext)) ); + // not yet handled if this kind of allocation above fails ! + // Add last debug print... + ::new(ahc) AllocHeapContext( tmp, aSize, sLastHeapContext ); + iAHM->Insert(ahc); + } + return tmp; + } + } + + //aPtr is not NULL. So it is real reallocation or accidentally + //pointing a cell -> PANIC + tmp = iHeap->ReAlloc(aPtr, aSize, aMode); + + sInUse = EFalse; + RDebug::Printf("M:Realloc %x %x %d %x", (TUint32) tmp, aPtr, aSize, aMode); + sInUse = ETrue; + + if (tmp) + { + // Check if information of old allocation has been stored. + if (iAHM->Find(aPtr) != NULL) + { + // remove the info + iAHM->Remove(aPtr); + } + // store new information + AllocHeapContext *ahc = (AllocHeapContext*) ( iOwnHeap->AllocZ(sizeof(AllocHeapContext)) ); + // not yet handled if this kind of allocation above fails ! + ::new(ahc) AllocHeapContext( tmp, aSize, sLastHeapContext ); + iAHM->Insert(ahc); + } + + return tmp; + } + +TInt RTraceAllocator::AllocLen(const TAny* aCell) const + { + // Printing commented out because it cause big delay + // when exiting application. + /* + sInUse = EFalse; + RDebug::Printf( "Camera: RTraceAllocator::AllocLen" ); + sInUse = ETrue; + */ + return iHeap->AllocLen(aCell); + } + +TInt RTraceAllocator::Compress() + { + sInUse = EFalse; + RDebug::Printf("Camera: RTraceAllocator::Compress"); + sInUse = ETrue; + //This doesn't require AllocHeapContext or iAHM because + //Compress doesn't affect sizes of allocated area. + return iHeap->Compress(); + } + +void RTraceAllocator::Reset() + { + sInUse = EFalse; + RDebug::Printf("Camera: RTraceAllocator::Reset"); + sInUse = ETrue; + //This should also sync iAHM because otherwise iAHM is showing + //freed cells as allocated. Currently not implemented. + return iHeap->Reset(); + } + +TInt RTraceAllocator::AllocSize(TInt& aTotalAllocSize) const + { + sInUse = EFalse; + RDebug::Printf("Camera: RTraceAllocator::AllocSize %d", aTotalAllocSize); + sInUse = ETrue; + return iHeap->AllocSize(aTotalAllocSize); + } + +TInt RTraceAllocator::Available(TInt& aBiggestBlock) const + { + TInt t = iHeap->Available(aBiggestBlock); + sInUse = EFalse; + RDebug::Printf("Camera: RTraceAllocator::Available %d %d", aBiggestBlock, + t); + sInUse = ETrue; + return t; + } + +TInt RTraceAllocator::DebugFunction(TInt /* aFunc */, TAny* /* a1 */, TAny* /* a2 */) + { + sInUse = EFalse; + RDebug::Printf("Camera: RTraceAllocator::DebugFunction"); + sInUse = ETrue; + return 0; + } + +#endif //_MEMORY_TRACKING +#endif //_DEBUG + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CCamDocument::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCamDocument* CCamDocument::NewL( CEikApplication& aApp ) + { + CCamDocument* self = NewLC( aApp ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CCamDocument::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CCamDocument* CCamDocument::NewLC( CEikApplication& aApp ) + { + CCamDocument* self = new( ELeave ) CCamDocument( aApp ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + + +// Destructor +CCamDocument::~CCamDocument() + { + PRINT( _L("Camera => ~CCamDocument") ); +#ifdef CAMERAAPP_PERF_LOG_TRACES + // Shutdown end event cannot be logged to memory logger + PERF_EVENT_END_TRACE( EPerfEventApplicationShutdown ); +#endif + + delete iController; + + // print leaks info + +#ifdef _DEBUG + +#ifdef _MEMORY_TRACKING + RTraceAllocator& alloc = (RTraceAllocator &)User::Heap(); + alloc.PrintLeaks(); + alloc.CleanTables(); + User::SwitchHeap(alloc.SavedHeap() ); + alloc.Close(); + delete &alloc; +#endif //_MEMORY_TRACKING +#ifdef _AO_TRACKING + // restoring the original scheduler + RestoreCurrentAS(); +#endif // _AO_TRACKING +#endif //_DEBUG + PRINT( _L("Camera <= ~CCamDocument") ); + } + +// ----------------------------------------------------------------------------- +// CCamDocument::CreateAppUiL +// Create the application user interface, and return a pointer to it +// the framework takes ownership of this object +// ----------------------------------------------------------------------------- +// +CEikAppUi* CCamDocument::CreateAppUiL() + { +#ifdef _DEBUG +#ifdef _AO_TRACKING + // replacing the scheduler + ReplaceCurrentASL(); +#endif // _AO_TRACKING +#endif // _DEBUG + return new( ELeave ) CCamAppUi( *iController ); + } + +// ----------------------------------------------------------------------------- +// CCamDocument::CCamDocument +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CCamDocument::CCamDocument( CEikApplication& aApp ) + : CAknDocument( aApp ) + { + // No implementation required + } + +// ----------------------------------------------------------------------------- +// CCamDocument::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CCamDocument::ConstructL() + { +#ifdef _DEBUG +#ifdef _MEMORY_TRACKING + // New heap for memory leak information. + RHeap& currentHeap = User::Heap(); + RTraceAllocator *alloc = new RTraceAllocator( ¤tHeap ); + if( alloc ) + User::SwitchHeap( alloc ); + //End of memoryleak heap replacer. +#endif //_MEMORY_TRACKING +#endif //_DEBUG + + PERF_EVENT_START_L1( EPerfEventAppFirstStartup ); + // Create the controller. + iController = CCamAppController::NewL(); + } + +// End of File