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