uiacceltk/hitchcock/goommonitor/src/goomlog.cpp
changeset 0 15bf7259bb7c
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2008 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:  Logging functionality for GOOM monitor profiling
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #ifdef _DEBUG
       
    20 
       
    21 #include <hal.h>
       
    22 #include <w32std.h>
       
    23 #include <e32std.h>
       
    24 #include <apgwgnam.h>
       
    25 #include <flogger.h>
       
    26 
       
    27 #include "goomlog.h"
       
    28 
       
    29 _LIT8(KMemorySampleLoggingString, "%d");
       
    30 _LIT8(KMemorySampleLoggingSeparator, ", ");
       
    31 
       
    32 _LIT8(KCrLf, "\r\n");
       
    33 
       
    34 _LIT8(KGOomLogCancel, "Sampling triggered before previous sampling has completed. Results so far: ");
       
    35 
       
    36 _LIT(KGOomLogFile, "c:\\logs\\GOOM\\livegoommonitor.txt");
       
    37 _LIT(KGOomOldLogFile, "c:\\logs\\GOOM\\goommonitor.txt");
       
    38 
       
    39 const TInt KMaxTimeStampSize = 30;
       
    40 _LIT(KTimeStampFormat, "%F    %H:%T:%S");
       
    41 
       
    42 _LIT(KDummyWgName, "20");
       
    43 
       
    44 _LIT8(KUidPreamble, "App UIDs:");
       
    45 _LIT8(KUidFormat, " 0x%x");
       
    46 
       
    47 const TInt KPreallocatedSpaceForAppList = 50;
       
    48 
       
    49 const TInt KMaxUidBufferSize = 1024;
       
    50 
       
    51 CGOomLogger* CGOomLogger::NewL(RWsSession& aWs, RFs& aFs)
       
    52     {
       
    53     CGOomLogger* self = new (ELeave) CGOomLogger(aWs, aFs);
       
    54     CleanupStack::PushL(self);
       
    55     self->ConstructL();
       
    56     CleanupStack::Pop(self);
       
    57     return self;
       
    58     }
       
    59     
       
    60 // Start logging the available memory every n micro seconds
       
    61 // Firstly a list of the app IDs is written to the log (foreground app first)
       
    62 // Note that the log is created in memory (to a pre-allocated buffer) and flushed out after it is complete
       
    63 // the samples are saved in CSV format so that they can easily be cut and pasted to plot graphs etc.
       
    64 void CGOomLogger::StartL()
       
    65     {
       
    66     // If the log file doesn't exist then don't attempt to sample anything
       
    67     if (!iIsOpen)
       
    68         return;
       
    69     
       
    70     // If we are already active then cancel first
       
    71     if (IsActive())
       
    72         Cancel();
       
    73     
       
    74     iWriteBuffer.Zero();
       
    75     
       
    76     iStartTime.HomeTime();
       
    77     
       
    78     // Log the timestamp
       
    79     TBuf16<KMaxTimeStampSize> timeStamp;
       
    80     iStartTime.FormatL(timeStamp, KTimeStampFormat);
       
    81     TBuf8<KMaxTimeStampSize> timeStamp8;
       
    82     timeStamp8.Copy(timeStamp);
       
    83     Write(timeStamp8);
       
    84     
       
    85     // Log all of the application IDs (foreground app first, then the other apps moving towards the back)
       
    86     LogApplicationIds();
       
    87 
       
    88     // Then, record the free memory
       
    89     // Note that this is done to a buffer so as not to affect the timing too much
       
    90     LogFreeMemory();
       
    91     
       
    92     // Finally, set a timer to record the memory every n microseconds
       
    93     HighRes(KTimeBetweenMemorySamples);
       
    94     }
       
    95 
       
    96 // From CTimer / CActice
       
    97 void CGOomLogger::RunL()
       
    98     {
       
    99     TTime currentTime;
       
   100     currentTime.HomeTime();
       
   101     TTimeIntervalMicroSeconds loggingDuration = currentTime.MicroSecondsFrom(iStartTime);
       
   102     TTimeIntervalMicroSeconds samplingDuration = KSamplingDurationUint;
       
   103     if (loggingDuration > samplingDuration)
       
   104         // If we have passed the desired logging duration then write the data we have collected
       
   105         {
       
   106         Write(iWriteBuffer);
       
   107         }
       
   108     else
       
   109         {
       
   110         // If we haven't passed the desired logging duration then record the free memory
       
   111         // Note that this is recorded into a buffer and then logged later
       
   112         iWriteBuffer.Append(KMemorySampleLoggingSeparator);
       
   113         LogFreeMemory();
       
   114         
       
   115         // Wait before taking another memory sample
       
   116         HighRes(KTimeBetweenMemorySamples);
       
   117         }
       
   118     }
       
   119 
       
   120 void CGOomLogger::DoCancel()
       
   121     {
       
   122     CTimer::DoCancel();
       
   123     
       
   124     Write(KGOomLogCancel);
       
   125     Write(iWriteBuffer);
       
   126     }
       
   127 
       
   128 CGOomLogger::~CGOomLogger()
       
   129     {
       
   130     iWgIds.Close();
       
   131  // delete iWgName; // Not owned
       
   132     if (iIsOpen)
       
   133         iFile.Close();
       
   134 
       
   135     }
       
   136 
       
   137 void CGOomLogger::Write(const TDesC8& aBuffer)
       
   138     {
       
   139     if (iIsOpen)
       
   140         {
       
   141         iFile.Write(aBuffer);
       
   142     
       
   143         // Add the line break
       
   144         iFile.Write(KCrLf);
       
   145         }
       
   146     }
       
   147 
       
   148 void CGOomLogger::LogApplicationIds()
       
   149     {
       
   150     // get all window groups, with info about parents
       
   151     TInt numGroups = iWs.NumWindowGroups(0);
       
   152     TRAPD(err, iWgIds.ReserveL(numGroups));
       
   153     
       
   154     if (err != KErrNone)
       
   155         return;
       
   156     
       
   157     if (iWs.WindowGroupList(0, &iWgIds) != KErrNone)
       
   158         return;
       
   159 
       
   160     // Remove all child window groups, promote parents to foremost child position
       
   161     ColapseWindowGroupTree();
       
   162     
       
   163     // Go through each window group ID in the list, get the Uid of each app then log it
       
   164     // Start with the foreground application
       
   165     TInt index = 0;
       
   166     
       
   167     TUid uid;
       
   168     
       
   169     TBuf8<KMaxUidBufferSize> uidBuffer;
       
   170     
       
   171     uidBuffer = KUidPreamble;
       
   172     
       
   173     while (index < numGroups)
       
   174         {
       
   175         uid = GetUidFromWindowGroupId(iWgIds[index].iId);
       
   176         
       
   177         uidBuffer.AppendFormat(KUidFormat, uid.iUid);
       
   178         
       
   179         index++;
       
   180         }
       
   181     
       
   182     Write(uidBuffer);
       
   183     }
       
   184 
       
   185 void CGOomLogger::LogFreeMemory()
       
   186     {
       
   187     TMemoryInfoV1Buf meminfo;
       
   188     UserHal::MemoryInfo(meminfo);
       
   189     TInt freeMem = meminfo().iFreeRamInBytes;
       
   190 
       
   191     // Save the free memory to a descriptor which will be written later
       
   192     iWriteBuffer.AppendFormat(KMemorySampleLoggingString(), freeMem);
       
   193     }
       
   194 
       
   195 CGOomLogger::CGOomLogger(RWsSession& aWs, RFs& aFs) : CTimer(EPriorityStandard), iWs(aWs), iFs(aFs)
       
   196     {
       
   197     }
       
   198 
       
   199 void CGOomLogger::ConstructL()
       
   200     {
       
   201     CActiveScheduler::Add(this);
       
   202     
       
   203     CTimer::ConstructL();
       
   204     
       
   205     // If there is an existing log then copy it, this will be the log that can be sent to the PC
       
   206     // Without this feature then you can't get the logs off of the device because the "live" log will always be is use.
       
   207     CFileMan* fileMan = CFileMan::NewL(iFs);
       
   208     CleanupStack::PushL(fileMan);
       
   209     fileMan->Copy(KGOomLogFile, KGOomOldLogFile);
       
   210     CleanupStack::PopAndDestroy(fileMan);
       
   211     
       
   212     // Create the log file, or open it if is already exists (note that the directory must already be present
       
   213     TInt err = iFile.Create(iFs, KGOomLogFile, EFileShareAny | EFileWrite);
       
   214     if (KErrNone != err)
       
   215         {
       
   216         err = iFile.Open(iFs, KGOomLogFile, EFileShareAny | EFileWrite);
       
   217         }
       
   218     
       
   219     if (KErrNone == err)
       
   220         {
       
   221         iIsOpen = ETrue;
       
   222         
       
   223         // Append all new data to the end of the file
       
   224         TInt offset = 0;
       
   225         iFile.Seek(ESeekEnd, offset);
       
   226         }
       
   227     
       
   228     // Reserve enough space to build an app list later.
       
   229     iWgIds.ReserveL(KPreallocatedSpaceForAppList);
       
   230     // Reserve enough space for CApaWindowGroupName.
       
   231     iWgName = CApaWindowGroupName::NewL(iWs);
       
   232     iWgNameBuf = HBufC::NewL(CApaWindowGroupName::EMaxLength);
       
   233     (*iWgNameBuf) = KDummyWgName;
       
   234     iWgName->SetWindowGroupName(iWgNameBuf);    // iWgName takes ownership of iWgNameBuf*/
       
   235 
       
   236     }
       
   237 
       
   238 void CGOomLogger::ColapseWindowGroupTree()
       
   239     {
       
   240     // start from the front, wg count can reduce as loop runs
       
   241     for (TInt ii=0; ii<iWgIds.Count();)
       
   242         {
       
   243         RWsSession::TWindowGroupChainInfo& info = iWgIds[ii];
       
   244         if (info.iParentId > 0)        // wg has a parent
       
   245             {
       
   246             // Look for the parent position
       
   247             TInt parentPos = ii;        // use child pos as not-found signal
       
   248             TInt count = iWgIds.Count();
       
   249             for (TInt jj=0; jj<count; jj++)
       
   250                 {
       
   251                 if (iWgIds[jj].iId == info.iParentId)
       
   252                     {
       
   253                     parentPos = jj;
       
   254                     break;
       
   255                     }
       
   256                 }
       
   257 
       
   258             if (parentPos > ii)  // parent should be moved forward
       
   259                 {
       
   260                 iWgIds[ii] = iWgIds[parentPos];
       
   261                 iWgIds.Remove(parentPos);
       
   262                 }
       
   263             else if (parentPos < ii)  // parent is already ahead of child, remove child
       
   264                 iWgIds.Remove(ii);
       
   265             else                    // parent not found, skip
       
   266                 ii++;
       
   267             }
       
   268         else    // wg does not have a parent, skip
       
   269             ii++;
       
   270         }
       
   271     }
       
   272 
       
   273 TUid CGOomLogger::GetUidFromWindowGroupId(TInt aWgId)
       
   274     {
       
   275     // get the app's details
       
   276     TPtr wgPtr(iWgNameBuf->Des());
       
   277     
       
   278     TUid uid;
       
   279     
       
   280     TInt err = iWs.GetWindowGroupNameFromIdentifier(aWgId, wgPtr);
       
   281     
       
   282     if (KErrNone != err)
       
   283         // If there is an error then set the UID to 0;
       
   284         {
       
   285         uid.iUid = 0;
       
   286         }
       
   287     else
       
   288         {
       
   289         iWgName->SetWindowGroupName(iWgNameBuf);
       
   290         uid = iWgName->AppUid(); // This UID comes from the app, not the mmp!
       
   291         }
       
   292     
       
   293     return uid;
       
   294     }
       
   295 
       
   296 #endif //_DEBUG