camerauis/cameraapp/generic/src/CamDocument.cpp
branchRCL_3
changeset 24 bac7acad7cb3
parent 0 1ddebce53859
equal deleted inserted replaced
23:61bc0f252b2b 24:bac7acad7cb3
       
     1 /*
       
     2 * Copyright (c) 2007 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:  Document class for Camera Application*
       
    15 */
       
    16 
       
    17 #include "camlogging.h"
       
    18 #include "CamLogger.h"
       
    19 
       
    20 #ifdef _DEBUG
       
    21 #include <e32debug.h>
       
    22 
       
    23 
       
    24 //#define _AO_TRACKING
       
    25 #ifdef _AO_TRACKING
       
    26 
       
    27 static void ReplaceCurrentASL();
       
    28 static void RestoreCurrentAS();
       
    29 
       
    30 class CFilterScheduler;
       
    31 
       
    32 class CFilterInfo : public CBase
       
    33     {
       
    34     friend class CFilterScheduler;
       
    35 
       
    36 public:
       
    37     static CFilterInfo* NewL();
       
    38 
       
    39 protected:
       
    40     struct CFilterStruct
       
    41         {
       
    42         CFilterStruct(CActive* aActiveAddPointer, char* aActiveLogInfo,
       
    43                 CFilterStruct* aLink);
       
    44         CActive *iActiveAddPointer;
       
    45         char *iActiveLogInfo;
       
    46         CFilterStruct *iLink;
       
    47         };
       
    48 
       
    49 protected:
       
    50     CFilterInfo();
       
    51     void ConstructL();
       
    52     void AddInfoL(CActive* aActiveAddPointer, char* aActiveLogInfo,
       
    53             CFilterStruct * &aLink);
       
    54     char* FindInfo(CActive *);
       
    55     ~CFilterInfo();
       
    56 protected:
       
    57     struct CFilterStruct *iFiSHead;
       
    58 
       
    59     };
       
    60 
       
    61 class CFilterScheduler : public CActiveScheduler
       
    62     {
       
    63     friend void ReplaceCurrentASL();
       
    64     friend void RestoreCurrentAS();
       
    65 
       
    66 public:
       
    67     static CFilterScheduler* NewL();
       
    68 private:
       
    69     static CActiveScheduler* iSavedFS;
       
    70 public:
       
    71     using CActiveScheduler::Start;
       
    72     // It is used as a hook, which makes possible to collect meaningful
       
    73     // information about every active object
       
    74     virtual TInt Extension_(TUint aUid, TAny*& a0, TAny* a1);
       
    75 protected:
       
    76     void ConstructL();
       
    77     CFilterScheduler();
       
    78     ~CFilterScheduler();
       
    79 
       
    80     void DebugPrint();
       
    81     char* FindInfo(CActive *);
       
    82     // it has to default to CActiveScheduler implementations  
       
    83     virtual void WaitForAnyRequest();
       
    84     // it has to default to CActiveScheduler implementations
       
    85     virtual void Error(TInt aError) const;
       
    86     // It has to be implemented since this is a concrete class
       
    87     virtual void OnStarting()
       
    88         {
       
    89         }
       
    90     virtual void OnStopping()
       
    91         {
       
    92         }
       
    93     virtual void Reserved_1()
       
    94         {
       
    95         }
       
    96     virtual void Reserved_2()
       
    97         {
       
    98         }
       
    99 private:
       
   100     CFilterInfo *iFilterInfo;
       
   101     };
       
   102 
       
   103 CActiveScheduler* CFilterScheduler::iSavedFS= NULL;
       
   104 
       
   105 CFilterInfo* CFilterInfo::NewL()
       
   106     {
       
   107     CFilterInfo* self = new( ELeave ) CFilterInfo();
       
   108     CleanupStack::PushL(self);
       
   109     self->ConstructL();
       
   110     CleanupStack::Pop(self);
       
   111     return self;
       
   112     }
       
   113 
       
   114 void CFilterInfo::AddInfoL(CActive* aActiveAddPointer, char* aActiveLogInfo,
       
   115         CFilterInfo::CFilterStruct* &aLink)
       
   116     {
       
   117     PRINT( _L("Camera => CFilterInfo::AddInfoL") );
       
   118     CFilterStruct *pFiS = new( ELeave ) CFilterStruct( aActiveAddPointer,
       
   119             aActiveLogInfo, aLink );
       
   120     pFiS->iLink = aLink;
       
   121     aLink = pFiS;
       
   122     }
       
   123 
       
   124 char* CFilterInfo::FindInfo(CActive *aActive)
       
   125     {
       
   126     char *pInfo = (char *)NULL;
       
   127     CFilterStruct *pFiS = iFiSHead;
       
   128     while (pFiS != NULL)
       
   129         {
       
   130         if (pFiS->iActiveAddPointer == aActive)
       
   131             {
       
   132             pInfo = pFiS->iActiveLogInfo;
       
   133             break;
       
   134             }
       
   135         pFiS = pFiS->iLink;
       
   136         }
       
   137     return pInfo;
       
   138     }
       
   139 
       
   140 CFilterInfo::CFilterStruct::CFilterStruct(CActive* aActiveAddPointer,
       
   141         char* aActiveLogInfo, CFilterInfo::CFilterStruct* aLink)
       
   142     {
       
   143     iActiveAddPointer = aActiveAddPointer;
       
   144     iActiveLogInfo = aActiveLogInfo;
       
   145     iLink = aLink;
       
   146     }
       
   147 
       
   148 void CFilterInfo::ConstructL()
       
   149     {
       
   150     }
       
   151 
       
   152 CFilterInfo::CFilterInfo()
       
   153     {
       
   154     iFiSHead = NULL;
       
   155     }
       
   156 
       
   157 CFilterInfo::~CFilterInfo()
       
   158     {
       
   159     }
       
   160 
       
   161 CFilterScheduler* CFilterScheduler::NewL()
       
   162     {
       
   163     CFilterScheduler* self = new( ELeave ) CFilterScheduler();
       
   164     CleanupStack::PushL(self);
       
   165     self->ConstructL();
       
   166     CleanupStack::Pop(self);
       
   167     return self;
       
   168     }
       
   169 
       
   170 void ReplaceCurrentASL()
       
   171     {
       
   172     CFilterScheduler *fSH = CFilterScheduler::NewL();
       
   173     //if (fSH != NULL)
       
   174     CFilterScheduler::iSavedFS = CActiveScheduler::Replace(fSH);
       
   175     }
       
   176 
       
   177 void RestoreCurrentAS()
       
   178     {
       
   179 
       
   180     if (CFilterScheduler::iSavedFS != NULL)
       
   181         {
       
   182         CActiveScheduler *iFS =
       
   183                 CActiveScheduler::Replace(CFilterScheduler::iSavedFS);
       
   184         delete iFS;
       
   185         }
       
   186 
       
   187     }
       
   188 
       
   189 TInt CFilterScheduler::Extension_(TUint aUid, TAny*& a0, TAny* a1)
       
   190     {
       
   191     if (aUid == 0)
       
   192         {
       
   193         TRAPD( rr, iFilterInfo->AddInfoL( (CActive *)a0, (char *)a1,
       
   194                         iFilterInfo->iFiSHead ) );
       
   195         return rr;
       
   196         }
       
   197     return KErrExtensionNotSupported;;
       
   198     }
       
   199 
       
   200 void CFilterScheduler::WaitForAnyRequest()
       
   201     {
       
   202     // Here is the printout at every wait
       
   203     DebugPrint();
       
   204     if (iSavedFS)
       
   205         iSavedFS->WaitForAnyRequest();
       
   206     else
       
   207         User::WaitForAnyRequest();
       
   208     }
       
   209 
       
   210 void CFilterScheduler::Error(TInt aError) const
       
   211     {
       
   212     if (iSavedFS)
       
   213         iSavedFS->Error(aError);
       
   214     }
       
   215 
       
   216 CFilterScheduler::CFilterScheduler()
       
   217     {
       
   218     }
       
   219 
       
   220 CFilterScheduler::~CFilterScheduler()
       
   221     {
       
   222     iSavedFS = NULL;
       
   223     }
       
   224 
       
   225 void CFilterScheduler::ConstructL()
       
   226     {
       
   227     /* iActive = CFilterActive::NewL( this ); */
       
   228     iFilterInfo = CFilterInfo::NewL();
       
   229     }
       
   230 
       
   231 char* CFilterScheduler::FindInfo(CActive * aA)
       
   232     {
       
   233     char *pFI= NULL;
       
   234     if (iFilterInfo)
       
   235         pFI = iFilterInfo->FindInfo(aA);
       
   236     return pFI;
       
   237     }
       
   238 
       
   239 void CFilterScheduler::DebugPrint()
       
   240     {
       
   241     RDebug::Print( _L( " Camera => CFilterScheduler::DebugPrint" ));
       
   242     TDblQueIter<CActive> q(iActiveQ);
       
   243     q.SetToFirst();
       
   244     while (q != NULL)
       
   245         {
       
   246         CActive *pR = q++;
       
   247         /* TInt pri = pR->iLink.iPriority; */
       
   248         TInt pri = pR->Priority();
       
   249         TInt stat = pR->iStatus.Int(); // TRequestStatus
       
   250         // find active objects identification string otherwise
       
   251         // print it's address
       
   252         char *pText = FindInfo(pR);
       
   253 
       
   254         if (pR->IsActive() )
       
   255             {
       
   256             if (stat == KRequestPending)
       
   257                 {
       
   258                 // active, pending
       
   259                 if (pText)
       
   260                     RDebug::Printf(
       
   261                             "Camera: CFilterScheduler::DebugPrint: %s - active/pending - priority: %d - req status: %d",
       
   262                             pText, pri, stat);
       
   263                 else
       
   264                     RDebug::Printf(
       
   265                             "Camera: CFilterScheduler::DebugPrint: %x - active/pending - priority: %d - req status: %d",
       
   266                             (TInt)pR, pri, stat);
       
   267                 }
       
   268             else
       
   269                 {
       
   270                 // active, not pending
       
   271                 if (pText)
       
   272                     RDebug::Printf(
       
   273                             "Camera: CFilterScheduler::DebugPrint: %s - active/not pending - priority: %d - req status: %d",
       
   274                             pText, pri, stat);
       
   275                 else
       
   276                     RDebug::Printf(
       
   277                             "Camera: CFilterScheduler::DebugPrint: %x - active/not pending - priority: %d - req status: %d",
       
   278                             (TInt)pR, pri, stat);
       
   279                 }
       
   280             }
       
   281         else
       
   282             {
       
   283             // not active
       
   284             if (pText)
       
   285                 RDebug::Printf(
       
   286                         "Camera: CFilterScheduler::DebugPrint: %s - not active: priority: %d - req status: %x",
       
   287                         pText, pri, stat);
       
   288             else
       
   289                 RDebug::Printf(
       
   290                         "Camera: CFilterScheduler::DebugPrint: %x - not active: priority: %d - req status: %x",
       
   291                         (TInt)pR, pri, stat);
       
   292             }
       
   293         }
       
   294     RDebug::Print( _L( "Camera <= CFilterScheduler::DebugPrint" ));
       
   295     }
       
   296 #endif // _AO_TRACKING
       
   297 #endif // _DEBUG
       
   298 // INCLUDE FILES
       
   299 #include "CamAppUi.h"
       
   300 #include "CamDocument.h"
       
   301 #include "CamPerformance.h"
       
   302 #include "CamAppController.h"
       
   303 
       
   304 #ifdef _DEBUG
       
   305 // These are used for memory allocation tracing.
       
   306 #undef _MEMORY_TRACKING
       
   307 //#define _MEMORY_TRACKING
       
   308 #ifdef _MEMORY_TRACKING
       
   309 #include <e32panic.h>
       
   310 
       
   311 
       
   312 // stores the last RDebug::Print or RDebug::Printf calls
       
   313 // string from cameraapp code if SInUse was ETrue
       
   314 static char *sLastHeapContext = NULL;
       
   315 // controls the context taking if it is EFalse sLastHeapContext is not updated
       
   316 // used also by RTraceAllocator::Alloc, Free, Realloc etc.
       
   317 static TBool sInUse = EFalse;
       
   318 
       
   319 // forward declaration for friend statements.
       
   320 class PtrAssocArray;
       
   321 class RTraceAllocator;
       
   322 
       
   323 
       
   324 // class which stores heap context info
       
   325 // per allocation
       
   326 // every allocation will have one entry in the hash table
       
   327 class AllocHeapContext
       
   328     {
       
   329     // added as friend for writing less set/get methods
       
   330     friend class PtrAssocArray;
       
   331 public:
       
   332     AllocHeapContext(TAny* aPtr, TInt aSize, char* aText1,
       
   333             AllocHeapContext *aNext = NULL);
       
   334     ~AllocHeapContext();
       
   335 protected:
       
   336     // stored pointer of the allocation  
       
   337     TAny* iPtr;
       
   338     // stored size of the allocation
       
   339     TInt iSize;
       
   340     // context string of the allocation, collected from
       
   341     // RDebug::Print, RDebug::Printf calls
       
   342     char* iText1;
       
   343     // link field to the next context if they are more with same hash value
       
   344     // in PtrAssocArray then they can be linked into a single linked list
       
   345     AllocHeapContext *iNext;
       
   346     };
       
   347 
       
   348 // class which stores the hash table
       
   349 class PtrAssocArray
       
   350     {
       
   351 public:
       
   352     // constructor takes a Heap to use for allocations and deallocations done by
       
   353     // this class,
       
   354     // Note: For not perturbing normal allocation/deallocation a separate heap is
       
   355     // used for internal needs. 
       
   356     PtrAssocArray(RHeap *aHeap);
       
   357     ~PtrAssocArray();
       
   358     // insert an element into the list
       
   359     // return KErrArgument if aAHC == NULL
       
   360     // otherwise KErrNone
       
   361     TInt Insert(AllocHeapContext* aAHC);
       
   362     // find an element in the list
       
   363     // return NULL pointer if cannot find, this means
       
   364     // also the case if aPtr == NULL  
       
   365     AllocHeapContext *Find(TAny *aPtr);
       
   366     // removes an element from the list
       
   367     // if aPtr == NULL does nothing and returns KErrArgument.
       
   368     // Returns KErrNotFound and does nothnig if cannot find it.
       
   369     // In normal case return KErrNone.
       
   370     TInt Remove(TAny *aPtr);
       
   371     // Prints the elements in the list
       
   372     void PrintLeaks();
       
   373     // cleans the list. It could be used if implemented for restarting
       
   374     // leak search from a certain point onward.
       
   375     // Note: only the list elements are cleaned, for real deallocation purposes
       
   376     // it cannot be used as this system doesn't offers a reference counting of
       
   377     // the pointer. It still can be used even that idea for debugging.  
       
   378     void CleanTables();
       
   379 protected:
       
   380     // the hash function itself,
       
   381     // simply takes the middle 2 bytes of a 4 byte unsigned,
       
   382     // to which the pointer is converted  
       
   383     TUint Hash(TAny *aPtr);
       
   384     // internal structures for has array entries
       
   385     // iInfo points
       
   386     struct AssocHashTbl
       
   387         {
       
   388         AllocHeapContext* iInfo;
       
   389         };
       
   390     // the hash array
       
   391     AssocHashTbl iAHT[65536];
       
   392     // pointer to iOwnHeap of
       
   393     RHeap *iHeap;
       
   394     };
       
   395 
       
   396 // the allocator class
       
   397 class RTraceAllocator : public RAllocator
       
   398     {
       
   399 public:
       
   400     // return current heap, just utility  
       
   401     static RTraceAllocator* OwnAllocator()
       
   402         {
       
   403         RTraceAllocator& currentHeap = (RTraceAllocator &)User::Heap();
       
   404         return &currentHeap;
       
   405         }
       
   406     // Simple utility function for getting a size of a char*
       
   407     // User::StringLength looks similar,
       
   408     // but this return 0 if aStr == NULL.
       
   409     static TUint StrSize(char * aStr);
       
   410     // stores the current heap for calls forwarding to that ones
       
   411     // implementation
       
   412     RTraceAllocator(RHeap *aCurrentHeap);
       
   413     // destructor sets sInUse to EFalse as iOwnHeap is not available any
       
   414     // more
       
   415     ~RTraceAllocator()
       
   416         {
       
   417         iOwnHeap->Close();
       
   418         sInUse = EFalse;
       
   419         }
       
   420 
       
   421     // These virtuals needs to be overwritten
       
   422     // there functionality is documented by Symbian
       
   423     virtual TAny* Alloc(TInt aSize);
       
   424     virtual void Free(TAny* aPtr);
       
   425     virtual TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode = 0);
       
   426     virtual TInt AllocLen(const TAny* aCell) const;
       
   427     virtual TInt Compress();
       
   428     virtual void Reset();
       
   429     virtual TInt AllocSize(TInt& aTotalAllocSize) const;
       
   430     virtual TInt Available(TInt& aBiggestBlock) const;
       
   431     virtual TInt DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL);
       
   432     // print entries in hash table, it is just a proxy method 
       
   433     void PrintLeaks()
       
   434         {
       
   435         iAHM->PrintLeaks();
       
   436         }
       
   437     // clean the tables it is just a proxy
       
   438     void CleanTables()
       
   439         {
       
   440         iAHM->CleanTables();
       
   441         }
       
   442     // frees memory from own heap
       
   443     void FreeOwn(TAny* aPtr)
       
   444         {
       
   445         iOwnHeap->Free(aPtr);
       
   446         }
       
   447     // allocates from own heap and fills with 0
       
   448     TAny* AllocZOwn(TInt aSize)
       
   449         {
       
   450         return iOwnHeap->AllocZ(aSize);
       
   451         }
       
   452     // returns the saved heap
       
   453     RHeap* SavedHeap()
       
   454         {
       
   455         return iHeap;
       
   456         }
       
   457 
       
   458 protected:
       
   459     // the original heap of the application, which does the real
       
   460     // allocation. All allocations are deferred to it  
       
   461     RHeap* iHeap;
       
   462     // A heap for own allocations, different than the one used by
       
   463     // cameraapp process 
       
   464     RHeap* iOwnHeap;
       
   465     // pointer to the hash table
       
   466     PtrAssocArray* iAHM;
       
   467     };
       
   468 
       
   469 
       
   470 #if defined( _UNICODE )
       
   471 
       
   472 // just, because they are needed
       
   473 class TestOverflowTruncate : public TDes16Overflow
       
   474     {
       
   475 public:
       
   476     virtual void Overflow(TDes16& /* aDes */)
       
   477         {
       
   478         }
       
   479     ;
       
   480     };
       
   481 
       
   482 #else
       
   483 
       
   484 class TestOverflowTruncate : public TDes8Overflow
       
   485     {
       
   486 public:
       
   487     virtual void Overflow(TDes8 &aDes)
       
   488         {};
       
   489     };
       
   490 
       
   491 #endif
       
   492 
       
   493 // just, because they are needed
       
   494 class TestOverflowTruncate8 : public TDes8Overflow
       
   495     {
       
   496 public:
       
   497     virtual void Overflow(TDes8& /*aDes*/)
       
   498         {
       
   499         }
       
   500     };
       
   501 
       
   502 
       
   503 // RDebug::Print is overwritten, because it is used
       
   504 EXPORT_C TInt RDebug::Print( TRefByValue<const TDesC> aFmt,... )
       
   505     {
       
   506     TestOverflowTruncate overflow;
       
   507     VA_LIST list;
       
   508     VA_START(list,aFmt);
       
   509     TBuf<0x100> buf;
       
   510     buf.AppendFormatList( aFmt, list, &overflow );
       
   511 #ifdef _UNICODE
       
   512     TPtr8 p( buf.Collapse() );
       
   513 
       
   514     // remember it
       
   515     char *context = ( char *)p.Ptr();
       
   516     if( sInUse )
       
   517         {
       
   518         if( sLastHeapContext )
       
   519             {
       
   520             //free it  
       
   521             RTraceAllocator::OwnAllocator()->FreeOwn( sLastHeapContext );
       
   522             sLastHeapContext = NULL;
       
   523             }
       
   524 
       
   525         sLastHeapContext = (char *)RTraceAllocator::OwnAllocator()->AllocZOwn( 0x100 );
       
   526         memcpy( sLastHeapContext, context, 0x100 );
       
   527         }
       
   528     // instead of Exec::DebugPrint((TAny*)&p, 0);
       
   529     // RawPrint is used
       
   530     // it could have been this hacked to, but it is not seen necessary
       
   531     // as recording context from Printf/Print seen as enough
       
   532     RDebug::RawPrint( p );
       
   533 #else
       
   534     TPtr8 p( buf );
       
   535     // rember it
       
   536     sLastHeapContext = ( char *)p;
       
   537     RDebug::RawPrint( p );
       
   538 #endif
       
   539     return 0;
       
   540     }
       
   541 
       
   542 EXPORT_C void RDebug::Printf( const char* aFmt, ... )
       
   543     {
       
   544     TestOverflowTruncate8 overflow;
       
   545     VA_LIST list;
       
   546     VA_START( list,aFmt );
       
   547     TPtrC8 fmt( (const TText8*)aFmt );
       
   548     TBuf8<0x100> buf;
       
   549     buf.AppendFormatList(fmt, list, &overflow );
       
   550     TPtrC8 p( buf /* (TUint8 *)(buf.Ptr()), 0x100 */);
       
   551 
       
   552     // rember it
       
   553     char *context = ( char *)p.Ptr();
       
   554     if( sInUse )
       
   555         {
       
   556         if( sLastHeapContext )
       
   557             {
       
   558             //free it
       
   559             RTraceAllocator::OwnAllocator()->FreeOwn( sLastHeapContext );
       
   560             sLastHeapContext = NULL;
       
   561             }
       
   562         sLastHeapContext = (char *)RTraceAllocator::OwnAllocator()->AllocZOwn( 0x100 );
       
   563         memcpy( sLastHeapContext, context, 0x100 );
       
   564         }
       
   565 
       
   566     RDebug::RawPrint( p );
       
   567     }
       
   568 
       
   569 // If some custom print wanted RawPrint could be hacked,
       
   570 // just added for completness
       
   571 #if 0
       
   572 EXPORT_C void RDebug::RawPrint( const TDesC8& aDes )
       
   573     {
       
   574     // Exec::DebugPrint( ( TAny* )&aDes, 1 );
       
   575     // above should be replaced by custom print
       
   576     }
       
   577 
       
   578 EXPORT_C void RDebug::RawPrint( const TDesC16& aDes )
       
   579     {
       
   580     TBuf8<0x100> aDes8;
       
   581     if( aDes.Length()>0x100 )
       
   582         {
       
   583         TPtrC ptr( aDes.Ptr(), 0x100 );
       
   584         aDes8.Copy( ptr );
       
   585         }
       
   586     else
       
   587     aDes8.Copy(aDes);
       
   588     // Exec::DebugPrint((TAny*)&aDes8, 1);
       
   589     // above should be replaced by custom print
       
   590     }
       
   591 #endif
       
   592 
       
   593 AllocHeapContext::AllocHeapContext(TAny* aPtr, TInt aSize, char* aText1,
       
   594         AllocHeapContext *aNext)
       
   595     {
       
   596     iPtr = aPtr;
       
   597     iSize = aSize;
       
   598 
       
   599     // but we need to copy here  
       
   600     if (aText1 == NULL)
       
   601         {
       
   602         iText1 = NULL;
       
   603         }
       
   604     else
       
   605         {
       
   606         iText1 = (char *)RTraceAllocator::OwnAllocator()->AllocZOwn( 0x100);
       
   607         if (iText1 != NULL)
       
   608             memcpy(iText1, aText1, 0x100);
       
   609         else
       
   610             {
       
   611             // just for testing
       
   612             // in this case 
       
   613             // there is no space to store additional info
       
   614             iText1 = iText1;
       
   615             }
       
   616         }
       
   617 
       
   618     iNext = aNext;
       
   619     }
       
   620 
       
   621 AllocHeapContext::~AllocHeapContext()
       
   622     {
       
   623     if (iText1)
       
   624         {
       
   625         RTraceAllocator::OwnAllocator()->FreeOwn(iText1);
       
   626         iText1 = NULL;
       
   627         }
       
   628     }
       
   629 
       
   630 PtrAssocArray::PtrAssocArray(RHeap *aHeap)
       
   631     {
       
   632     iHeap = aHeap; //points to in Traceallocator iOwnHeap
       
   633     // not necessary to fill with NULL pointers, as RHeap::Allocz 
       
   634     // does the job already 
       
   635     for (TUint i = 0; i < 65535; i++)
       
   636         {
       
   637         iAHT[i].iInfo = NULL;
       
   638         }
       
   639     }
       
   640 
       
   641 PtrAssocArray::~PtrAssocArray()
       
   642     {
       
   643     }
       
   644 
       
   645 // insert an element into the list
       
   646 TInt PtrAssocArray::Insert(AllocHeapContext* aAHC)
       
   647     {
       
   648     if ( !aAHC)
       
   649         {
       
   650         return KErrArgument;
       
   651         }
       
   652 
       
   653     TUint hashVal = Hash(aAHC->iPtr);
       
   654     // no collision, add to the table
       
   655     if (iAHT[hashVal].iInfo == NULL)
       
   656         {
       
   657         iAHT[hashVal].iInfo = aAHC;
       
   658         }
       
   659     // collision, insert at the beginning of linked list.
       
   660     else
       
   661         {
       
   662         aAHC->iNext = iAHT[hashVal].iInfo;
       
   663         iAHT[hashVal].iInfo = aAHC;
       
   664         }
       
   665     return KErrNone;
       
   666     }
       
   667 
       
   668 TUint PtrAssocArray::Hash(TAny *aPtr)
       
   669     {
       
   670     TUint val = (TUint)aPtr;
       
   671     // take the middle part as hash value 65536 
       
   672     // different values
       
   673     val = (val & 0x00FFFF00 ) >> 8;
       
   674     return val;
       
   675     }
       
   676 
       
   677 // find an element in the list
       
   678 AllocHeapContext *PtrAssocArray::Find(TAny *aPtr)
       
   679     {
       
   680     if ( !aPtr)
       
   681         return NULL;
       
   682     TUint hashVal = Hash(aPtr);
       
   683     AllocHeapContext *ptr = iAHT[hashVal].iInfo;
       
   684     if (ptr != NULL)
       
   685         {
       
   686         do
       
   687             {
       
   688             if (ptr->iPtr != aPtr)
       
   689                 {
       
   690                 ptr = ptr->iNext;
       
   691                 continue;
       
   692                 }
       
   693             else
       
   694                 {
       
   695                 return ptr;
       
   696                 }
       
   697             }
       
   698         while (ptr);
       
   699         }
       
   700     return NULL;
       
   701     }
       
   702 
       
   703 // remove an element from the list
       
   704 TInt PtrAssocArray::Remove(TAny *aPtr)
       
   705     {
       
   706     if ( !aPtr)
       
   707         return KErrArgument;
       
   708     TUint hashVal = Hash(aPtr);
       
   709     AllocHeapContext *ptr = iAHT[hashVal].iInfo;
       
   710     if (ptr != NULL)
       
   711         {
       
   712         AllocHeapContext *prevPtr= NULL;
       
   713         do
       
   714             {
       
   715             if (ptr->iPtr != aPtr)
       
   716                 {
       
   717                 prevPtr = ptr;
       
   718                 ptr = ptr->iNext;
       
   719                 continue;
       
   720                 }
       
   721             else
       
   722                 {
       
   723                 // found, we should unlink and free memory          
       
   724                 if (prevPtr)
       
   725                     {
       
   726                     prevPtr->iNext = ptr->iNext;
       
   727                     }
       
   728                 else
       
   729                     {
       
   730                     //This is first element in linked list.
       
   731                     if (ptr->iNext==NULL)
       
   732                         {
       
   733                         //List should cleared only if this is last element
       
   734                         iAHT[hashVal].iInfo = NULL;
       
   735                         }
       
   736                     else
       
   737                         {
       
   738                         iAHT[hashVal].iInfo = ptr->iNext;
       
   739                         }
       
   740                     }
       
   741                 // call destructor
       
   742                 ptr->AllocHeapContext::~AllocHeapContext();
       
   743                 // deallocate
       
   744                 iHeap->Free(ptr);
       
   745 
       
   746                 return KErrNone;
       
   747                 }
       
   748             }
       
   749         while (ptr);
       
   750         }
       
   751     return KErrNotFound;
       
   752     }
       
   753 
       
   754 void PtrAssocArray::PrintLeaks()
       
   755     {
       
   756     for (TUint i = 0; i < 65536; i++)
       
   757         {
       
   758         AllocHeapContext *ptr = iAHT[i].iInfo;
       
   759         if ( !ptr)
       
   760             continue;
       
   761         do
       
   762             {
       
   763             if (ptr->iText1 != NULL)
       
   764                 RDebug::Printf(
       
   765                         "Camera:PrintLeaks ptr: %x, size: %d, context: %s",
       
   766                         ptr->iPtr, ptr->iSize, ptr->iText1);
       
   767             else
       
   768                 RDebug::Printf(
       
   769                         "Camera:PrintLeaks ptr: %x, size: %d, context: <<NO CONTEXT>>",
       
   770                         ptr->iPtr, ptr->iSize);
       
   771             ptr = ptr->iNext;
       
   772             }
       
   773         while (ptr);
       
   774         }
       
   775     }
       
   776 
       
   777 void PtrAssocArray::CleanTables()
       
   778     {
       
   779     // Not really necessary to implement
       
   780 
       
   781     // disable code below
       
   782     // by replacing #if 1 by #if 0
       
   783 #if 1
       
   784     for (TUint i = 0; i < 65536; i++)
       
   785         {
       
   786         AllocHeapContext *ptr = iAHT[i].iInfo;
       
   787         if ( !ptr)
       
   788             {
       
   789             //Don't continue...
       
   790             continue;
       
   791             }
       
   792         // deallocate the list    
       
   793         AllocHeapContext *nextPtr= NULL;
       
   794         while (ptr) //Is this ever true? 
       
   795             {
       
   796             nextPtr = ptr->iNext;
       
   797             // call destructor
       
   798             ptr->AllocHeapContext::~AllocHeapContext();
       
   799             // deallocate
       
   800             iHeap->Free(ptr);
       
   801             ptr = nextPtr;
       
   802             }
       
   803         }
       
   804 #endif    
       
   805     }
       
   806 
       
   807 
       
   808 
       
   809 RTraceAllocator::RTraceAllocator(RHeap *aCurrentHeap)
       
   810     {
       
   811     iHeap = aCurrentHeap;
       
   812     iOwnHeap = UserHeap::ChunkHeap( NULL, 1024 * 64, 1024*1024 * 2);
       
   813     iAHM = (PtrAssocArray *)iOwnHeap->AllocZ(sizeof(PtrAssocArray));
       
   814     ::new(iAHM) PtrAssocArray( iOwnHeap );
       
   815     sInUse = ETrue;
       
   816     }
       
   817 
       
   818 TAny* RTraceAllocator::Alloc(TInt aSize)
       
   819     {
       
   820     TAny *tmp = iHeap->Alloc(aSize);
       
   821 
       
   822     sInUse = EFalse;
       
   823     RDebug::Printf("Camera: RTraceAllocator::Alloc %x, %d", ( TUint32 )tmp,
       
   824             aSize);
       
   825     sInUse = ETrue;
       
   826   
       
   827     if (tmp)
       
   828         {
       
   829   
       
   830     AllocHeapContext* ahc = (AllocHeapContext*) ( iOwnHeap->AllocZ(sizeof(AllocHeapContext)) ); 
       
   831         // text from last debug print is added
       
   832         // it can be extended to add more. Timing information for example.
       
   833         ::new(ahc) AllocHeapContext( tmp, aSize, sLastHeapContext );
       
   834         iAHM->Insert(ahc);
       
   835         }
       
   836     else
       
   837         {
       
   838         // can be commented out this, if failed allocations are not interesting
       
   839         // RDebug::Printf("M:Alloc %x, %d", (TUint32) tmp, aSize);
       
   840         }
       
   841     return tmp;
       
   842     }
       
   843 
       
   844 
       
   845 void RTraceAllocator::Free(TAny* aPtr)
       
   846     {
       
   847     if (aPtr)
       
   848         {
       
   849         iAHM->Remove(aPtr);
       
   850         sInUse = EFalse;
       
   851         RDebug::Printf("RTraceAllocator::Free %x", ( TUint32 ) aPtr );
       
   852         sInUse = ETrue;
       
   853         iHeap->Free(aPtr);
       
   854         }
       
   855     }
       
   856 
       
   857 
       
   858 TAny* RTraceAllocator::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode)
       
   859     {
       
   860     TAny *tmp= NULL;
       
   861 
       
   862     if (aPtr == NULL)
       
   863         {
       
   864         if (aMode != ENeverMove)
       
   865             {
       
   866             tmp = RTraceAllocator::Alloc(aSize);
       
   867 
       
   868             sInUse = EFalse;
       
   869             RDebug::Printf("M:Realloc %x %x %d %x", (TUint32) tmp, aPtr,
       
   870                     aSize, aMode);
       
   871             sInUse = ETrue;
       
   872             return tmp;
       
   873             }
       
   874         else
       
   875             {
       
   876             // Now we are allocating a block which should never move...
       
   877             // Call below could panic USER:42
       
   878             tmp = iHeap->ReAlloc(aPtr, aSize, aMode);
       
   879 
       
   880             sInUse = EFalse;
       
   881             RDebug::Printf("M:Realloc %x %x %d %x", (TUint32) tmp, aPtr,
       
   882                     aSize, aMode);
       
   883             sInUse = ETrue;
       
   884 
       
   885             if (tmp)
       
   886                 {
       
   887             AllocHeapContext *ahc = (AllocHeapContext*) ( iOwnHeap->AllocZ(sizeof(AllocHeapContext)) );
       
   888                 // not yet handled if this kind of allocation above fails !
       
   889                 // Add last debug print...
       
   890                 ::new(ahc) AllocHeapContext( tmp, aSize, sLastHeapContext );
       
   891                 iAHM->Insert(ahc);
       
   892                 }
       
   893             return tmp;
       
   894             }
       
   895         }
       
   896 
       
   897     //aPtr is not NULL. So it is real reallocation or accidentally
       
   898     //pointing a cell -> PANIC
       
   899     tmp = iHeap->ReAlloc(aPtr, aSize, aMode);
       
   900 
       
   901     sInUse = EFalse;
       
   902     RDebug::Printf("M:Realloc %x %x %d %x", (TUint32) tmp, aPtr, aSize, aMode);
       
   903     sInUse = ETrue;
       
   904 
       
   905     if (tmp)
       
   906         {
       
   907         // Check if information of old allocation has been stored.
       
   908         if (iAHM->Find(aPtr) != NULL)
       
   909             {
       
   910             // remove the info
       
   911             iAHM->Remove(aPtr);
       
   912             }
       
   913         // store new information
       
   914       AllocHeapContext *ahc = (AllocHeapContext*) ( iOwnHeap->AllocZ(sizeof(AllocHeapContext)) );
       
   915         // not yet handled if this kind of allocation above fails !
       
   916         ::new(ahc) AllocHeapContext( tmp, aSize, sLastHeapContext );
       
   917         iAHM->Insert(ahc);
       
   918         }
       
   919 
       
   920     return tmp;
       
   921     }
       
   922 
       
   923 TInt RTraceAllocator::AllocLen(const TAny* aCell) const
       
   924     {
       
   925     // Printing commented out because it cause big delay
       
   926     // when exiting application.
       
   927     /*
       
   928      sInUse = EFalse;
       
   929      RDebug::Printf( "Camera: RTraceAllocator::AllocLen" );
       
   930      sInUse = ETrue;
       
   931      */
       
   932     return iHeap->AllocLen(aCell);
       
   933     }
       
   934 
       
   935 TInt RTraceAllocator::Compress()
       
   936     {
       
   937     sInUse = EFalse;
       
   938     RDebug::Printf("Camera: RTraceAllocator::Compress");
       
   939     sInUse = ETrue;
       
   940     //This doesn't require AllocHeapContext or iAHM because
       
   941     //Compress doesn't affect sizes of allocated area.
       
   942     return iHeap->Compress();
       
   943     }
       
   944 
       
   945 void RTraceAllocator::Reset()
       
   946     {
       
   947     sInUse = EFalse;
       
   948     RDebug::Printf("Camera: RTraceAllocator::Reset");
       
   949     sInUse = ETrue;
       
   950     //This should also sync iAHM because otherwise iAHM is showing
       
   951     //freed cells as allocated. Currently not implemented.
       
   952     return iHeap->Reset();
       
   953     }
       
   954 
       
   955 TInt RTraceAllocator::AllocSize(TInt& aTotalAllocSize) const
       
   956     {
       
   957     sInUse = EFalse;
       
   958     RDebug::Printf("Camera: RTraceAllocator::AllocSize %d", aTotalAllocSize);
       
   959     sInUse = ETrue;
       
   960     return iHeap->AllocSize(aTotalAllocSize);
       
   961     }
       
   962 
       
   963 TInt RTraceAllocator::Available(TInt& aBiggestBlock) const
       
   964     {
       
   965     TInt t = iHeap->Available(aBiggestBlock);
       
   966     sInUse = EFalse;
       
   967     RDebug::Printf("Camera: RTraceAllocator::Available %d %d", aBiggestBlock,
       
   968             t);
       
   969     sInUse = ETrue;
       
   970     return t;
       
   971     }
       
   972 
       
   973 TInt RTraceAllocator::DebugFunction(TInt /* aFunc */, TAny* /* a1 */, TAny* /* a2 */)
       
   974     {
       
   975     sInUse = EFalse;
       
   976     RDebug::Printf("Camera: RTraceAllocator::DebugFunction");
       
   977     sInUse = ETrue;
       
   978     return 0;
       
   979     }
       
   980 
       
   981 #endif //_MEMORY_TRACKING
       
   982 #endif //_DEBUG
       
   983 
       
   984 // ============================ MEMBER FUNCTIONS ===============================
       
   985 
       
   986 // -----------------------------------------------------------------------------
       
   987 // CCamDocument::NewL
       
   988 // Two-phased constructor.
       
   989 // -----------------------------------------------------------------------------
       
   990 //
       
   991 CCamDocument* CCamDocument::NewL( CEikApplication& aApp )
       
   992     {
       
   993     CCamDocument* self = NewLC( aApp );
       
   994     CleanupStack::Pop( self );
       
   995     return self;
       
   996     }
       
   997 
       
   998 // -----------------------------------------------------------------------------
       
   999 // CCamDocument::NewLC
       
  1000 // Two-phased constructor.
       
  1001 // -----------------------------------------------------------------------------
       
  1002 //
       
  1003 CCamDocument* CCamDocument::NewLC( CEikApplication& aApp )
       
  1004     {
       
  1005     CCamDocument* self = new( ELeave ) CCamDocument( aApp );
       
  1006     CleanupStack::PushL( self );
       
  1007     self->ConstructL();
       
  1008     return self;
       
  1009     }
       
  1010 
       
  1011     
       
  1012 // Destructor
       
  1013 CCamDocument::~CCamDocument()
       
  1014     {
       
  1015     PRINT( _L("Camera => ~CCamDocument") );
       
  1016 #ifdef CAMERAAPP_PERF_LOG_TRACES	
       
  1017     // Shutdown end event cannot be logged to memory logger
       
  1018     PERF_EVENT_END_TRACE( EPerfEventApplicationShutdown );
       
  1019 #endif	
       
  1020 
       
  1021     delete iController;
       
  1022 
       
  1023     // print leaks info
       
  1024 
       
  1025 #ifdef _DEBUG
       
  1026   
       
  1027 #ifdef _MEMORY_TRACKING
       
  1028     RTraceAllocator& alloc = (RTraceAllocator &)User::Heap();
       
  1029     alloc.PrintLeaks();
       
  1030     alloc.CleanTables();
       
  1031     User::SwitchHeap(alloc.SavedHeap() );
       
  1032     alloc.Close();
       
  1033     delete &alloc;
       
  1034 #endif //_MEMORY_TRACKING
       
  1035 #ifdef _AO_TRACKING
       
  1036     // restoring the original scheduler
       
  1037     RestoreCurrentAS();
       
  1038 #endif // _AO_TRACKING
       
  1039 #endif //_DEBUG
       
  1040     PRINT( _L("Camera <= ~CCamDocument") );
       
  1041     }
       
  1042 
       
  1043 // -----------------------------------------------------------------------------
       
  1044 // CCamDocument::CreateAppUiL
       
  1045 // Create the application user interface, and return a pointer to it
       
  1046 // the framework takes ownership of this object
       
  1047 // -----------------------------------------------------------------------------
       
  1048 //
       
  1049 CEikAppUi* CCamDocument::CreateAppUiL()
       
  1050     {
       
  1051 #ifdef _DEBUG
       
  1052 #ifdef _AO_TRACKING
       
  1053     // replacing the scheduler
       
  1054     ReplaceCurrentASL();
       
  1055 #endif // _AO_TRACKING
       
  1056 #endif // _DEBUG
       
  1057     return new( ELeave ) CCamAppUi( *iController ); 
       
  1058     }
       
  1059 
       
  1060 // -----------------------------------------------------------------------------
       
  1061 // CCamDocument::CCamDocument
       
  1062 // C++ default constructor can NOT contain any code, that
       
  1063 // might leave.
       
  1064 // -----------------------------------------------------------------------------
       
  1065 //
       
  1066 CCamDocument::CCamDocument( CEikApplication& aApp )  
       
  1067     : CAknDocument( aApp ) 
       
  1068     {
       
  1069     // No implementation required
       
  1070     }
       
  1071 
       
  1072 // -----------------------------------------------------------------------------
       
  1073 // CCamDocument::ConstructL
       
  1074 // Symbian 2nd phase constructor can leave.
       
  1075 // -----------------------------------------------------------------------------
       
  1076 //
       
  1077 void CCamDocument::ConstructL()
       
  1078     {
       
  1079 #ifdef _DEBUG
       
  1080 #ifdef _MEMORY_TRACKING
       
  1081     // New heap for memory leak information.
       
  1082      RHeap& currentHeap = User::Heap();
       
  1083      RTraceAllocator *alloc = new RTraceAllocator( &currentHeap );
       
  1084      if( alloc )
       
  1085        User::SwitchHeap( alloc );
       
  1086      //End of memoryleak heap replacer.    
       
  1087 #endif //_MEMORY_TRACKING
       
  1088 #endif //_DEBUG
       
  1089     
       
  1090     PERF_EVENT_START_L1( EPerfEventAppFirstStartup );	
       
  1091     // Create the controller.
       
  1092     iController = CCamAppController::NewL();
       
  1093     }
       
  1094 
       
  1095 //  End of File