perfmon/engine/src/perfmon_engine.cpp
branchRCL_3
changeset 60 6646c35e558c
parent 50 9b2cffad4b5e
equal deleted inserted replaced
50:9b2cffad4b5e 60:6646c35e558c
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0"
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description:  
       
    15  *
       
    16  */
       
    17 // INCLUDE FILES
       
    18 #include "perfmon_engine.h"
       
    19 #include "perfmon_powerlistener.h"
       
    20 #include <coeutils.h>
       
    21 #include <bautils.h>
       
    22 #include <eikenv.h>
       
    23 #include <e32hal.h>
       
    24 #include <u32std.h>
       
    25 #include <s32file.h>
       
    26 #include <akntitle.h> 
       
    27 #include <eikspane.h>
       
    28 #include <aknnotewrappers.h>
       
    29 _LIT(KDefaultLogFilePath, "c:\\data\\PerfMon.log");
       
    30 
       
    31 const TInt KCalibrationLength = 2;
       
    32 const TInt KMinimumSamplesLength = 16;
       
    33 const TInt KCPUTimeMultiplier = 1000000; // used to avoid TReal conversions
       
    34 
       
    35 const TInt KSettingsDrive = EDriveC;
       
    36 _LIT(KSettingsFileName, "perfmon_settings.ini");
       
    37 
       
    38 // --------------------------------------------------------------------------------------------
       
    39 
       
    40 TInt CPULoadCount(TAny* aPtr)
       
    41     {
       
    42     TPerfMonNOPCounter& atts = *((TPerfMonNOPCounter*) aPtr);
       
    43 
       
    44     // increase the counter
       
    45     atts.iCounterValue++;
       
    46     return 1;
       
    47     }
       
    48 
       
    49 TInt CPULoadNOPThread(TAny* aPtr)
       
    50     {
       
    51     // set the thread running in correct CPU
       
    52     TPerfMonNOPCounter& atts = *((TPerfMonNOPCounter*) aPtr);
       
    53     
       
    54     if (atts.iAmountOfCPUs > 1)
       
    55         {
       
    56         // request via HAL that the current thread will run in CPU defined in atts.iCPUNumber
       
    57         TInt err = UserSvr::HalFunction(EHalGroupKernel, 19 /*EKernelHalLockThreadToCpu*/, (TAny*) atts.iCPUNumber, 0);
       
    58 
       
    59         if (err != KErrNone)
       
    60             {
       
    61             // error, stop this thread
       
    62             return err;
       
    63             }
       
    64         }
       
    65 
       
    66     // init trap clean and install active scheduler
       
    67     CTrapCleanup* pC = CTrapCleanup::New();
       
    68     CActiveScheduler* pS = new CActiveScheduler;
       
    69     CActiveScheduler::Install(pS);
       
    70 
       
    71     // call the counter to simulate polling the null thread for cpu time
       
    72     CIdle* idle = CIdle::NewL(CActive::EPriorityStandard);
       
    73     TCallBack cb(CPULoadCount, aPtr);
       
    74     idle->Start(cb);
       
    75 
       
    76     pS->Start();
       
    77 
       
    78     delete idle;
       
    79     delete pS;
       
    80     delete pC;
       
    81 
       
    82     return KErrNone;
       
    83     }
       
    84 
       
    85 // ===================================== MEMBER FUNCTIONS =====================================
       
    86 
       
    87 CPerfMonEngine::CPerfMonEngine() :
       
    88     CActive(EPriorityUserInput)
       
    89     {
       
    90     }
       
    91 
       
    92 // --------------------------------------------------------------------------------------------
       
    93 
       
    94 void CPerfMonEngine::ConstructL()
       
    95     {
       
    96     iCurrentCPUMode = ECPUModeNotSet;
       
    97     iLogFileInitialized = EFalse;
       
    98     iAmountOfCPUs = 1;
       
    99 
       
   100     iEnv = CEikonEnv::Static();
       
   101     User::LeaveIfError(iLs.Connect());
       
   102 
       
   103     User::LeaveIfError(iTimer.CreateLocal());
       
   104     CActiveScheduler::Add(this);
       
   105     }
       
   106 
       
   107 // --------------------------------------------------------------------------------------------
       
   108 
       
   109 void CPerfMonEngine::ActivateEngineL()
       
   110     {
       
   111     // load settings
       
   112     TRAP_IGNORE(LoadSettingsL());
       
   113 
       
   114     // create data storages for the samples
       
   115     CreateSamplesDataArrayL();
       
   116 
       
   117     // set default modes
       
   118     HandleSettingsChangeL();
       
   119 
       
   120     // start sampling data immediately (jump to RunL)    
       
   121     iTimer.After(iStatus, 100);
       
   122     SetActive();
       
   123     }
       
   124 
       
   125 // --------------------------------------------------------------------------------------------
       
   126 
       
   127 void CPerfMonEngine::DeActivateEngineL()
       
   128     {
       
   129     Cancel();
       
   130 
       
   131     DeActivatePowerMonitoring();
       
   132     DeActivateCPUMonitoring();
       
   133 
       
   134     // close log file
       
   135     OpenLogFile(EFalse);
       
   136     }
       
   137 
       
   138 // --------------------------------------------------------------------------------------------
       
   139 
       
   140 CPerfMonEngine::~CPerfMonEngine()
       
   141     {
       
   142     DeActivatePowerMonitoring();
       
   143 
       
   144     if (iPowerClient != 0)
       
   145         {
       
   146         delete iPowerClient;
       
   147         iPowerClient = 0;
       
   148         }
       
   149 
       
   150     iTimer.Close();
       
   151 
       
   152     // clear data storages
       
   153     if (iSampleEntryArray)
       
   154         {
       
   155         for (TInt i = 0; i < iSampleEntryArray->Count(); i++)
       
   156             {
       
   157             delete iSampleEntryArray->At(i).iSampleDataArray;
       
   158             }
       
   159 
       
   160         delete iSampleEntryArray;
       
   161         }
       
   162 
       
   163     iLs.Close();
       
   164     }
       
   165 
       
   166 // --------------------------------------------------------------------------------------------
       
   167 
       
   168 void CPerfMonEngine::DoCancel()
       
   169     {
       
   170     iTimer.Cancel();
       
   171     }
       
   172 
       
   173 // --------------------------------------------------------------------------------------------
       
   174 
       
   175 void CPerfMonEngine::RunL()
       
   176     {
       
   177     // calculate new values 
       
   178     UpdateSamplesDataL();
       
   179 
       
   180     // log changes
       
   181     AppendLatestSamplesToLogsL();
       
   182 
       
   183     // redraw views
       
   184     SendDrawEventToContainersL();
       
   185 
       
   186     // continue
       
   187     iTimer.After(iStatus, iSettings.iHeartBeat * 1000); // convert from milliseconds to microseconds
       
   188     SetActive();
       
   189     }
       
   190 
       
   191 // --------------------------------------------------------------------------------------------
       
   192 
       
   193 void CPerfMonEngine::HandleSettingsChangeL()
       
   194     {
       
   195     // set priority of the thread
       
   196     RThread().SetPriority(SettingItemToThreadPriority(iSettings.iPriority));
       
   197 
       
   198     // init cpu monitor if setting has been changed
       
   199     if (iCurrentCPUMode != iSettings.iCPUMode)
       
   200         {
       
   201         DeActivateCPUMonitoring();
       
   202         ActivateCPUMonitoringL();
       
   203         }
       
   204 
       
   205     // Check for power setting changes every time
       
   206     if (iSettings.iPowerMonitoringEnabled == true)
       
   207         {
       
   208         ActivatePowerMonitoringL();
       
   209         }
       
   210     else
       
   211         {
       
   212         DeActivatePowerMonitoring();
       
   213         }
       
   214 
       
   215     // close log file
       
   216     OpenLogFile(EFalse);
       
   217 
       
   218     // enable log file
       
   219     if (iSettings.iLoggingEnabled && (iSettings.iLoggingMode
       
   220             == ELoggingModeLogFile || iSettings.iLoggingMode
       
   221             == ELoggingModeRDebugLogFile))
       
   222         OpenLogFile(ETrue);
       
   223     }
       
   224 
       
   225 // --------------------------------------------------------------------------------------------
       
   226 
       
   227 void CPerfMonEngine::EnableLogging(TBool aEnable)
       
   228     {
       
   229     if (aEnable)
       
   230         {
       
   231         if (iSettings.iLoggingMode == ELoggingModeLogFile
       
   232                 || iSettings.iLoggingMode == ELoggingModeRDebugLogFile)
       
   233             OpenLogFile(ETrue);
       
   234 
       
   235         iSettings.iLoggingEnabled = ETrue;
       
   236         }
       
   237     else // disable
       
   238         {
       
   239         iSettings.iLoggingEnabled = EFalse;
       
   240         OpenLogFile(EFalse);
       
   241         }
       
   242     }
       
   243 
       
   244 // --------------------------------------------------------------------------------------------
       
   245 
       
   246 void CPerfMonEngine::OpenLogFile(TBool aOpen)
       
   247     {
       
   248     // open log file for writing
       
   249     if (aOpen)
       
   250         {
       
   251         if (!iLogFileInitialized)
       
   252             {
       
   253             TInt err(KErrNone);
       
   254 
       
   255             // open the log file for writing
       
   256             if (iLogFile.Open(iEnv->FsSession(), iSettings.iLoggingFilePath,
       
   257                     EFileWrite) != KErrNone)
       
   258                 {
       
   259                 iEnv->FsSession().MkDirAll(iSettings.iLoggingFilePath);
       
   260                 err = iLogFile.Replace(iEnv->FsSession(),
       
   261                         iSettings.iLoggingFilePath, EFileWrite);
       
   262                 }
       
   263             else
       
   264                 {
       
   265                 // file opens correctly, seek to the end
       
   266                 TInt fileSize = 0;
       
   267                 iLogFile.Size(fileSize);
       
   268                 err = iLogFile.Seek(ESeekCurrent, fileSize);
       
   269                 }
       
   270 
       
   271             if (err == KErrNone)
       
   272                 {
       
   273                 iLogFileInitialized = ETrue;
       
   274                 }
       
   275             else
       
   276                 {
       
   277                 // show error
       
   278                 CAknErrorNote* note = new (ELeave) CAknErrorNote();
       
   279                 note->ExecuteLD(_L("Unable to create log file, check settings"));
       
   280                 }
       
   281             }
       
   282         }
       
   283 
       
   284     // close handle to log file
       
   285     else
       
   286         {
       
   287         if (iLogFileInitialized)
       
   288             {
       
   289             iLogFile.Flush();
       
   290             iLogFile.Close();
       
   291 
       
   292             iLogFileInitialized = EFalse;
       
   293             }
       
   294         }
       
   295     }
       
   296 
       
   297 // --------------------------------------------------------------------------------------------
       
   298 
       
   299 void CPerfMonEngine::ActivateCPUMonitoringL()
       
   300     {
       
   301     // reset counter variables
       
   302     iCPULoadCalibrating = ETrue;
       
   303     iCPULoadCalibrationCounter = 0;
       
   304     iCPULoadMaxValue = 999999999;
       
   305 
       
   306     for (TInt i=0; i<KMaxCPUs; i++)
       
   307         {
       
   308         iCPULoadPreviousValue[i] = 1;
       
   309         }
       
   310 
       
   311     // use null thread is cpu time is supported and the setting is on
       
   312     if (CPUTimeSupported() && iSettings.iCPUMode == ECPUModeCPUTime)
       
   313         {
       
   314         // try to open handle to null thread
       
   315         if (OpenHandleToNullThread())
       
   316             {
       
   317             // handle is open, get initial value for each CPU
       
   318             for (TInt i=0; i<iAmountOfCPUs; i++)
       
   319                 {
       
   320                 TTimeIntervalMicroSeconds time;
       
   321                 iNullThreads[i].GetCpuTime(time);
       
   322                 iCPULoadPreviousValue[i] = time.Int64();
       
   323                 }
       
   324 
       
   325             iPreviousTime.HomeTime();
       
   326 
       
   327             iCurrentCPUMode = ECPUModeCPUTime;
       
   328             return; // cpu time is succesfully in use
       
   329             }
       
   330         }
       
   331 
       
   332     // otherwise use normal sampling with nops
       
   333     iCurrentCPUMode = ECPUModeNotSet;
       
   334 
       
   335     // show a warning if cpu time cannot be taken in use
       
   336     if (iSettings.iCPUMode == ECPUModeCPUTime)
       
   337         {
       
   338         CAknInformationNote* note = new (ELeave) CAknInformationNote();
       
   339         note->ExecuteLD(
       
   340                 _L("CPU Time not supported in this system, using NOPs sampling"));
       
   341         }
       
   342 
       
   343     // get the amount of CPUs
       
   344     iAmountOfCPUs = GetAmountOfCPUs();
       
   345 
       
   346     // create a thread for CPU load monitoring
       
   347     for (TInt i=0; i<iAmountOfCPUs; i++)
       
   348         {
       
   349         // initialize the NOP counter variables
       
   350         iCPULoadNOPCounter[i].iCounterValue = 0;
       
   351         iCPULoadNOPCounter[i].iCPUNumber = i;
       
   352         iCPULoadNOPCounter[i].iAmountOfCPUs = iAmountOfCPUs;
       
   353 
       
   354         // create a name for the thread
       
   355         TFileName cpuLoadThreadName;
       
   356         cpuLoadThreadName.Copy(_L("PerfMonCPULoadNOPThread"));
       
   357         cpuLoadThreadName.AppendNum(i);
       
   358         
       
   359         // create the thread and resume it
       
   360         User::LeaveIfError(iCPULoadNOPThread[i].Create(cpuLoadThreadName,
       
   361                 CPULoadNOPThread, 0x1000, 0x1000, 0x100000, &iCPULoadNOPCounter[i]));
       
   362         iCPULoadNOPThread[i].SetPriority(EPriorityLess);
       
   363         iCPULoadNOPThread[i].Resume();
       
   364         }
       
   365 
       
   366     iCurrentCPUMode = ECPUModeNOPs; // NOPs taken succesfully in use
       
   367     }
       
   368 
       
   369 // --------------------------------------------------------------------------------------------
       
   370 
       
   371 TBool CPerfMonEngine::OpenHandleToNullThread()
       
   372     {
       
   373     // find the kernel process and then the null thread
       
   374     TFindProcess fp(_L("ekern.exe*"));
       
   375 
       
   376     TFullName kernelName;
       
   377     if (fp.Next(kernelName) == KErrNone)
       
   378         {
       
   379         iAmountOfCPUs = 0;
       
   380 
       
   381         // find all null threads in the system by following the order ie "Null", "Null1", "Null2", "Null3"
       
   382         for (TInt i(0); i<KMaxCPUs; i++)
       
   383             {
       
   384             // construct name of the null thread from the process name
       
   385             TFullName nullThreadName(kernelName);
       
   386             nullThreadName.Append(_L("::Null"));
       
   387             
       
   388             if (i >= 1) // add identifier for CPUs higher than zero
       
   389                 nullThreadName.AppendNum(i);
       
   390 
       
   391             TFindThread ft(nullThreadName);
       
   392             TFullName threadName;
       
   393 
       
   394             if (ft.Next(threadName) == KErrNone)
       
   395                 {
       
   396                 if (iNullThreads[i].Open(threadName) != KErrNone)
       
   397                     return EFalse;
       
   398                 
       
   399                 iAmountOfCPUs++;
       
   400                 }
       
   401             else
       
   402                 {
       
   403                 break;  // break the loop, no more matches can be found
       
   404                 }
       
   405             }
       
   406         }
       
   407 
       
   408     // process not found
       
   409     else
       
   410         return EFalse;
       
   411 
       
   412     // success!
       
   413     return ETrue;
       
   414     }
       
   415 
       
   416 // --------------------------------------------------------------------------------------------
       
   417 
       
   418 void CPerfMonEngine::DeActivateCPUMonitoring()
       
   419     {
       
   420     if (iCurrentCPUMode == ECPUModeCPUTime)
       
   421         {
       
   422         // close handles to null threads
       
   423         for (TInt i=0;i<iAmountOfCPUs;i++)
       
   424             {
       
   425             iNullThreads[i].Close();
       
   426             }
       
   427         }
       
   428 
       
   429     else if (iCurrentCPUMode == ECPUModeNOPs)
       
   430         {
       
   431         // kill the cpu load thread
       
   432         for (TInt i=0;i<iAmountOfCPUs;i++)
       
   433             {
       
   434             iCPULoadNOPThread[i].Kill(0);
       
   435             iCPULoadNOPThread[i].Close();
       
   436             }
       
   437         }
       
   438     }
       
   439 
       
   440 // --------------------------------------------------------------------------------------------
       
   441 
       
   442 TBool CPerfMonEngine::CPUTimeSupported()
       
   443     {
       
   444     TTimeIntervalMicroSeconds time;
       
   445     TInt err = RThread().GetCpuTime(time);
       
   446 
       
   447     if (err == KErrNone && time.Int64() > 0)
       
   448         return ETrue;
       
   449     else
       
   450         return EFalse;
       
   451     }
       
   452 
       
   453 // --------------------------------------------------------------------------------------------
       
   454 
       
   455 TInt CPerfMonEngine::GetAmountOfCPUs()
       
   456     {
       
   457     // query from HAL the amount of CPUs and then check it returns a valid value
       
   458     TInt amountOfCPUs = UserSvr::HalFunction(EHalGroupKernel, 16 /*EKernelHalNumLogicalCpus*/, 0, 0);
       
   459     
       
   460     if (amountOfCPUs >= 1 && amountOfCPUs <= KMaxCPUs)
       
   461         return amountOfCPUs;
       
   462     else
       
   463         return 1; // HAL may not support this feature, so just return one CPU
       
   464     }
       
   465 
       
   466 // --------------------------------------------------------------------------------------------
       
   467 
       
   468 TThreadPriority CPerfMonEngine::SettingItemToThreadPriority(TInt aIndex)
       
   469     {
       
   470     TThreadPriority threadPriority = EPriorityNull;
       
   471 
       
   472     switch (aIndex)
       
   473         {
       
   474         case EThreadPriorityTypeMuchLess:
       
   475             {
       
   476             threadPriority = EPriorityMuchLess;
       
   477             break;
       
   478             }
       
   479         case EThreadPriorityTypeLess:
       
   480             {
       
   481             threadPriority = EPriorityLess;
       
   482             break;
       
   483             }
       
   484         case EThreadPriorityTypeNormal:
       
   485             {
       
   486             threadPriority = EPriorityNormal;
       
   487             break;
       
   488             }
       
   489         case EThreadPriorityTypeMore:
       
   490             {
       
   491             threadPriority = EPriorityMore;
       
   492             break;
       
   493             }
       
   494         case EThreadPriorityTypeMuchMore:
       
   495             {
       
   496             threadPriority = EPriorityMuchMore;
       
   497             break;
       
   498             }
       
   499         case EThreadPriorityTypeRealTime:
       
   500             {
       
   501             threadPriority = EPriorityRealTime;
       
   502             break;
       
   503             }
       
   504         case EThreadPriorityTypeAbsoluteVeryLow:
       
   505             {
       
   506             threadPriority = EPriorityAbsoluteVeryLow;
       
   507             break;
       
   508             }
       
   509         case EThreadPriorityTypeAbsoluteLow:
       
   510             {
       
   511             threadPriority = EPriorityAbsoluteLow;
       
   512             break;
       
   513             }
       
   514         case EThreadPriorityTypeAbsoluteBackground:
       
   515             {
       
   516             threadPriority = EPriorityAbsoluteBackground;
       
   517             break;
       
   518             }
       
   519         case EThreadPriorityTypeAbsoluteForeground:
       
   520             {
       
   521             threadPriority = EPriorityAbsoluteForeground;
       
   522             break;
       
   523             }
       
   524         case EThreadPriorityTypeAbsoluteHigh:
       
   525             {
       
   526             threadPriority = EPriorityAbsoluteHigh;
       
   527             break;
       
   528             }
       
   529 
       
   530         default:
       
   531             {
       
   532             User::Panic(_L("Wrong tp index"), 276);
       
   533             break;
       
   534             }
       
   535         }
       
   536 
       
   537     return threadPriority;
       
   538     }
       
   539 
       
   540 // --------------------------------------------------------------------------------------------
       
   541 
       
   542 void CPerfMonEngine::CreateSamplesDataArrayL()
       
   543     {
       
   544     TInt maxSamples =
       
   545             iSettings.iMaxSamples >= KMinimumSamplesLength ? iSettings.iMaxSamples
       
   546                     : KMinimumSamplesLength;
       
   547 
       
   548     // create the data structure to store all samples
       
   549     iSampleEntryArray = new (ELeave) CSampleEntryArray(16);
       
   550 
       
   551     // set sample data array positions for each type
       
   552     iCPU0PositionInSamples = 0;
       
   553     iRAMPositionInSamples = KMaxCPUs;
       
   554     iCDrivePositionInSamples = KMaxCPUs+1;
       
   555     iPowerPositionInSamples = iCDrivePositionInSamples + ( ESourceI - ESourceC ) + 1;
       
   556 
       
   557     // add all CPU source entries
       
   558     for (TInt i=0; i<KMaxCPUs; i++)
       
   559         {
       
   560         TSampleEntry newSampleEntry;
       
   561 
       
   562         newSampleEntry.iDescription.Copy(_L("CPU"));
       
   563         newSampleEntry.iDescription.AppendNum(i);
       
   564 
       
   565         newSampleEntry.iUnitTypeShort.Copy(KNullDesC);
       
   566         newSampleEntry.iUnitTypeLong.Copy(KNullDesC);
       
   567         newSampleEntry.iDriveNumber = -1;
       
   568         newSampleEntry.iGraphColor = KRgbYellow;
       
   569         newSampleEntry.iGraphColor.SetGreen(255-i*75);
       
   570         newSampleEntry.iGraphColor.SetBlue(i*75);
       
   571 
       
   572         newSampleEntry.iSampleDataArray = new(ELeave) CSampleDataArray(maxSamples);
       
   573         iSampleEntryArray->AppendL(newSampleEntry);
       
   574         }
       
   575 
       
   576     // add RAM entry
       
   577     {
       
   578     TSampleEntry newSampleEntry;
       
   579 
       
   580     newSampleEntry.iDescription.Copy(_L("RAM"));
       
   581     newSampleEntry.iUnitTypeShort.Copy(_L("b"));
       
   582     newSampleEntry.iUnitTypeLong.Copy(_L("bytes"));
       
   583     newSampleEntry.iDriveNumber = -1;
       
   584     newSampleEntry.iGraphColor = KRgbGreen;
       
   585 
       
   586     newSampleEntry.iSampleDataArray = new(ELeave) CSampleDataArray(maxSamples);
       
   587     iSampleEntryArray->AppendL(newSampleEntry);
       
   588     }
       
   589 
       
   590     // add all disk drives
       
   591     for (TInt i=0; i<ESourceI-ESourceC+1; i++)
       
   592         {
       
   593         TSampleEntry newSampleEntry;
       
   594 
       
   595         TChar driveLetter = 'C' + i; // C is the first drive
       
   596 
       
   597         newSampleEntry.iDescription.Append(driveLetter);
       
   598         newSampleEntry.iDescription.Append(_L(":"));
       
   599         newSampleEntry.iUnitTypeShort.Copy(_L("b"));
       
   600         newSampleEntry.iUnitTypeLong.Copy(_L("bytes"));
       
   601 
       
   602         iEnv->FsSession().CharToDrive(driveLetter,
       
   603                 newSampleEntry.iDriveNumber);
       
   604 
       
   605         newSampleEntry.iGraphColor = KRgbCyan;
       
   606         newSampleEntry.iGraphColor.SetGreen(255 - (i - ESourceC) * 30);
       
   607         newSampleEntry.iGraphColor.SetRed(i * 30);
       
   608 
       
   609         newSampleEntry.iSampleDataArray = new (ELeave) CSampleDataArray(
       
   610                 maxSamples);
       
   611 
       
   612         iSampleEntryArray->AppendL(newSampleEntry);
       
   613         }
       
   614 
       
   615     // add power entry
       
   616     {
       
   617     TSampleEntry newSampleEntry;
       
   618 
       
   619     newSampleEntry.iDescription.Copy(_L("Power"));
       
   620     newSampleEntry.iUnitTypeShort.Copy(_L("mW"));
       
   621     newSampleEntry.iUnitTypeLong.Copy(_L("milliwatts"));
       
   622     newSampleEntry.iDriveNumber = -1;
       
   623     newSampleEntry.iGraphColor = KRgbRed;
       
   624 
       
   625     newSampleEntry.iSampleDataArray = new(ELeave) CSampleDataArray(maxSamples);
       
   626     iSampleEntryArray->AppendL(newSampleEntry);
       
   627     }
       
   628 
       
   629     // save current time as start time
       
   630     iStartTime.HomeTime();
       
   631     }
       
   632 
       
   633 // --------------------------------------------------------------------------------------------
       
   634 
       
   635 void CPerfMonEngine::UpdateSamplesDataL()
       
   636     {
       
   637     // reset inactivity timers
       
   638     if (iSettings.iKeepBacklightOn)
       
   639         User::ResetInactivityTime();
       
   640 
       
   641     // get current time
       
   642     TTime currentTime;
       
   643     currentTime.HomeTime();
       
   644 
       
   645     // calculate time difference
       
   646     TTimeIntervalMicroSeconds timeDeltaFromPreviousSample =
       
   647             currentTime.MicroSecondsFrom(iPreviousTime);
       
   648 
       
   649     // remember current time as previous
       
   650     iPreviousTime = currentTime;
       
   651 
       
   652     // get CPU load value for each CPU
       
   653     for (TInt i=0;i<iAmountOfCPUs;i++)
       
   654         {
       
   655         TInt64 cpuLoadDelta(0);
       
   656         TInt64 cpuLoadFree(0);
       
   657         TInt64 currentCPUValue(0);
       
   658         
       
   659         if (iCurrentCPUMode == ECPUModeCPUTime || iCurrentCPUMode == ECPUModeNOPs)
       
   660             {
       
   661             if (iCurrentCPUMode == ECPUModeCPUTime)
       
   662                 {
       
   663                 // get CPU time of null thread
       
   664                 TTimeIntervalMicroSeconds time;
       
   665                 iNullThreads[i].GetCpuTime(time);
       
   666                 currentCPUValue = time.Int64();
       
   667                 }
       
   668             else if (iCurrentCPUMode == ECPUModeNOPs)
       
   669                 {
       
   670                 // get CPU time from sampler
       
   671                 currentCPUValue = iCPULoadNOPCounter[i].iCounterValue;
       
   672                 }
       
   673 
       
   674             // get delta and store the previous value
       
   675             cpuLoadDelta = currentCPUValue - iCPULoadPreviousValue[i];
       
   676             iCPULoadPreviousValue[i] = currentCPUValue;
       
   677             
       
   678             // velocity = distance / time
       
   679             cpuLoadFree = cpuLoadDelta * KCPUTimeMultiplier / timeDeltaFromPreviousSample.Int64();
       
   680 
       
   681             // detect maximum value (this is common to all CPUs)
       
   682             if (cpuLoadFree > iCPULoadMaxValue)
       
   683                 {
       
   684                 iCPULoadMaxValue = cpuLoadFree;
       
   685                 }
       
   686             }
       
   687 
       
   688         // save cpu sample data
       
   689         TSampleData cpuSample;
       
   690         cpuSample.iFree = cpuLoadFree;
       
   691         cpuSample.iSize = iCPULoadCalibrating ? cpuLoadFree : iCPULoadMaxValue;  // if calibrating, size==free, otherwise store the correct size value
       
   692         cpuSample.iTimeFromStart = currentTime.MicroSecondsFrom(iStartTime);
       
   693 
       
   694         iSampleEntryArray->At(i).iSampleDataArray->InsertL(0, cpuSample);
       
   695         }
       
   696         
       
   697     // check calibration status, the calibration will be only done against CPU0
       
   698     if (iCPULoadCalibrating)
       
   699         {
       
   700         iCPULoadCalibrationCounter++;
       
   701         TInt64 cpuLoadSize = iSampleEntryArray->At(iCPU0PositionInSamples).iSampleDataArray->At(0).iSize;
       
   702         
       
   703         // check if need to calibrate anymore
       
   704         if (iCPULoadCalibrationCounter > KCalibrationLength)
       
   705             {
       
   706             iCPULoadCalibrating = EFalse;
       
   707             
       
   708             // from the samples, get the minimum value, and let it be the max value
       
   709             for (TInt i=0; i<iSampleEntryArray->At(0).iSampleDataArray->Count(); i++)
       
   710                 {
       
   711                 TInt64 newCPULoadMaxValue = iCPULoadMaxValue;
       
   712                 
       
   713                 if (iSampleEntryArray->At(0).iSampleDataArray->At(i).iFree < newCPULoadMaxValue)
       
   714                     {
       
   715                     newCPULoadMaxValue = iSampleEntryArray->At(0).iSampleDataArray->At(i).iFree;
       
   716                     }
       
   717                 
       
   718                 iCPULoadMaxValue = newCPULoadMaxValue;
       
   719                 }
       
   720             
       
   721             // adjust priority of the poller thread
       
   722             if (iCurrentCPUMode == ECPUModeNOPs)
       
   723                 {
       
   724                 for (TInt i=0; i<iAmountOfCPUs; i++)
       
   725                     {
       
   726                     iCPULoadNOPThread[i].SetPriority(EPriorityAbsoluteVeryLow);
       
   727                     }
       
   728                 }
       
   729 
       
   730             }
       
   731         }
       
   732 
       
   733     // get ram memory
       
   734     TMemoryInfoV1Buf ramMemory;
       
   735     UserHal::MemoryInfo(ramMemory);
       
   736 
       
   737     TSampleData memorySample;
       
   738     memorySample.iFree = ramMemory().iFreeRamInBytes;
       
   739     memorySample.iSize = ramMemory().iMaxFreeRamInBytes;
       
   740     memorySample.iTimeFromStart = currentTime.MicroSecondsFrom(iStartTime);
       
   741 
       
   742     iSampleEntryArray->At(iRAMPositionInSamples).iSampleDataArray->InsertL(0, memorySample);
       
   743     
       
   744     // all drives
       
   745     for (TInt i = iCDrivePositionInSamples; i < iPowerPositionInSamples; i++)
       
   746         {
       
   747         TSampleData driveSample;
       
   748 
       
   749         // get volume info from RFs
       
   750         TVolumeInfo volumeInfo;
       
   751         if (iEnv->FsSession().Volume(volumeInfo,
       
   752                 iSampleEntryArray->At(i).iDriveNumber) == KErrNone)
       
   753             {
       
   754             driveSample.iFree = volumeInfo.iFree;
       
   755             driveSample.iSize = volumeInfo.iSize;
       
   756             }
       
   757         else
       
   758             {
       
   759             driveSample.iFree = 0;
       
   760             driveSample.iSize = 0;
       
   761             }
       
   762 
       
   763         driveSample.iTimeFromStart = currentTime.MicroSecondsFrom(iStartTime);
       
   764 
       
   765         iSampleEntryArray->At(i).iSampleDataArray->InsertL(0, driveSample);
       
   766         }
       
   767 
       
   768     // Power data
       
   769     TSampleData powerSample;
       
   770     if (iSettings.iPowerMonitoringEnabled)
       
   771         {
       
   772         // Values in milliwatts
       
   773         powerSample.iFree = ( iPowerClient->GetMaxPower() - iPowerClient->GetPower() ) / 1000;
       
   774         powerSample.iSize = iPowerClient->GetMaxPower() / 1000;
       
   775         }
       
   776     else
       
   777         {
       
   778         powerSample.iFree = 0;
       
   779         powerSample.iSize = 0;
       
   780         }
       
   781 
       
   782     powerSample.iTimeFromStart = currentTime.MicroSecondsFrom(iStartTime);
       
   783 
       
   784     iSampleEntryArray->At(iPowerPositionInSamples).iSampleDataArray->InsertL(0, powerSample);
       
   785 
       
   786     // compress sample data arrays to save memory
       
   787     TInt curLength(iSampleEntryArray->At(0).iSampleDataArray->Count());
       
   788 
       
   789     TInt maxSamples =
       
   790             iSettings.iMaxSamples >= KMinimumSamplesLength ? iSettings.iMaxSamples
       
   791                     : KMinimumSamplesLength;
       
   792 
       
   793     if (curLength > maxSamples && curLength % 5 == 0)
       
   794         {
       
   795         for (TInt i = 0; i < iSampleEntryArray->Count(); i++)
       
   796             {
       
   797             if (SampleEntryArray()->At(i).iSampleDataArray->Count() > 0)
       
   798                 {
       
   799                 iSampleEntryArray->At(i).iSampleDataArray->ResizeL(maxSamples); // looses old samples
       
   800                 iSampleEntryArray->At(i).iSampleDataArray->Compress();
       
   801                 }
       
   802             }
       
   803         }
       
   804     }
       
   805 
       
   806 // --------------------------------------------------------------------------------------------
       
   807 
       
   808 void CPerfMonEngine::AppendLatestSamplesToLogsL()
       
   809     {
       
   810     if (iSettings.iLoggingEnabled && SampleEntryArray())
       
   811         {
       
   812         // loop all sources
       
   813         for (TInt i = 0; i < SampleEntryArray()->Count(); i++)
       
   814             {
       
   815             // check if this setting has been enabled and it has some data
       
   816             if (iSettings.iLoggingSources.iSrcEnabled[SampleEntryPosToSettingPos(i)]
       
   817                     && SampleEntryArray()->At(i).iSampleDataArray->Count() > 0)
       
   818                 {
       
   819                 // get current sample
       
   820                 TSampleData& currentSample =
       
   821                         SampleEntryArray()->At(i).iSampleDataArray->At(0);
       
   822 
       
   823                 TBuf<128> buf;
       
   824                 buf.Append(_L("PERFMON;"));
       
   825                 buf.Append(SampleEntryArray()->At(i).iDescription);
       
   826                 buf.Append(_L(";"));
       
   827                 buf.AppendNum(currentSample.iTimeFromStart.Int64());
       
   828                 buf.Append(_L(";"));
       
   829                 buf.AppendNum(currentSample.iFree);
       
   830                 buf.Append(_L(";"));
       
   831                 buf.AppendNum(currentSample.iSize);
       
   832 
       
   833                 // print to RDebug
       
   834                 if (iSettings.iLoggingMode == ELoggingModeRDebug
       
   835                         || iSettings.iLoggingMode == ELoggingModeRDebugLogFile)
       
   836                     {
       
   837                     RDebug::Print(buf);
       
   838                     }
       
   839 
       
   840                 // print to log file
       
   841                 if (iSettings.iLoggingMode == ELoggingModeLogFile
       
   842                         || iSettings.iLoggingMode == ELoggingModeRDebugLogFile)
       
   843                     {
       
   844                     buf.Append(_L("\r\n"));
       
   845 
       
   846                     TBuf8<128> buf8;
       
   847                     buf8.Copy(buf);
       
   848 
       
   849                     iLogFile.Write(buf8);
       
   850                     }
       
   851                 }
       
   852             }
       
   853         }
       
   854     }
       
   855 
       
   856 void CPerfMonEngine::LoadSettingsL()
       
   857     {
       
   858     // set defaults
       
   859     iSettings.iHeartBeat = 600;
       
   860     iSettings.iMaxSamples = 64;
       
   861     iSettings.iPriority = EThreadPriorityTypeNormal;
       
   862     iSettings.iCPUMode = ECPUModeCPUTime;
       
   863     iSettings.iKeepBacklightOn = ETrue;
       
   864 
       
   865     iSettings.iDataPopupVisibility = EDataPopupVisbilityAlwaysOn;
       
   866     iSettings.iDataPopupLocation = EDataPopupLocationTopRight;
       
   867     iSettings.iDataPopupSources.SetDefaults1();
       
   868 
       
   869     iSettings.iGraphsVerticalBarPeriod = 5;
       
   870     iSettings.iGraphsSources.SetDefaults2();
       
   871 
       
   872     iSettings.iLoggingMode = ELoggingModeRDebug;
       
   873     iSettings.iLoggingFilePath.Copy(KDefaultLogFilePath);
       
   874     iSettings.iLoggingSources.SetDefaults2();
       
   875 
       
   876     iSettings.iLoggingEnabled = EFalse;
       
   877 
       
   878     iSettings.iPowerMonitoringEnabled = ETrue;
       
   879 
       
   880     // make sure that the private path of this app in c-drive exists
       
   881     iEnv->FsSession().CreatePrivatePath(KSettingsDrive); // c:\\private\\20011385\\
       
   882     
       
   883     // handle settings always in the private directory 
       
   884     if (iEnv->FsSession().SetSessionToPrivate(KSettingsDrive) == KErrNone)
       
   885         {
       
   886         const TUid KUidPerfMon =
       
   887             {
       
   888             0x20011385
       
   889             };
       
   890         // open or create a dictionary file store
       
   891         CDictionaryFileStore* settingsStore = CDictionaryFileStore::OpenLC(
       
   892                 iEnv->FsSession(), KSettingsFileName, KUidPerfMon);
       
   893 
       
   894         LoadDFSValueL(settingsStore, KPMSettingHeartBeat, iSettings.iHeartBeat);
       
   895         LoadDFSValueL(settingsStore, KPMSettingMaxSamples,
       
   896                 iSettings.iMaxSamples);
       
   897         LoadDFSValueL(settingsStore, KPMSettingPriority, iSettings.iPriority);
       
   898         
       
   899         LoadDFSValueL(settingsStore, KPMSettingCPUMode, iSettings.iCPUMode);
       
   900         
       
   901         LoadDFSValueL(settingsStore, KPMSettingKeepBackLightOn,
       
   902                 iSettings.iKeepBacklightOn);
       
   903 
       
   904         LoadDFSValueL(settingsStore, KPMSettingDataPopupVisbility,
       
   905                 iSettings.iDataPopupVisibility);
       
   906         LoadDFSValueL(settingsStore, KPMSettingDataPopupLocation,
       
   907                 iSettings.iDataPopupLocation);
       
   908         LoadDFSValueL(settingsStore, KPMSettingDataPopupSources,
       
   909                 iSettings.iDataPopupSources);
       
   910 
       
   911         LoadDFSValueL(settingsStore, KPMSettingGraphsVerticalBarPeriod,
       
   912                 iSettings.iGraphsVerticalBarPeriod);
       
   913         LoadDFSValueL(settingsStore, KPMSettingGraphsSources,
       
   914                 iSettings.iGraphsSources);
       
   915 
       
   916         LoadDFSValueL(settingsStore, KPMSettingLoggingMode,
       
   917                 iSettings.iLoggingMode);
       
   918         LoadDFSValueL(settingsStore, KPMSettingLoggingFilePath,
       
   919                 iSettings.iLoggingFilePath);
       
   920         LoadDFSValueL(settingsStore, KPMSettingLoggingSources,
       
   921                 iSettings.iLoggingSources);
       
   922 
       
   923         LoadDFSValueL(settingsStore, KPMSettingPowerMonitoringEnabled,
       
   924                 iSettings.iPowerMonitoringEnabled);
       
   925 
       
   926         CleanupStack::PopAndDestroy(); // settingsStore
       
   927         }
       
   928     }
       
   929 
       
   930 // --------------------------------------------------------------------------------------------
       
   931 
       
   932 void CPerfMonEngine::SaveSettingsL()
       
   933     {
       
   934     // handle settings always in c:\\private\\20011385\\ 
       
   935     if (iEnv->FsSession().SetSessionToPrivate( KSettingsDrive ) == KErrNone)
       
   936         {
       
   937         // delete existing store to make sure that it is clean and not eg corrupted
       
   938         if (BaflUtils::FileExists(iEnv->FsSession(), KSettingsFileName))
       
   939             {
       
   940             iEnv->FsSession().Delete(KSettingsFileName);
       
   941             }
       
   942         const TUid KUidPerfMon =
       
   943             {
       
   944             0x20011385
       
   945             };
       
   946         // create a dictionary file store
       
   947         CDictionaryFileStore* settingsStore = CDictionaryFileStore::OpenLC(
       
   948                 iEnv->FsSession(), KSettingsFileName, KUidPerfMon);
       
   949 
       
   950         SaveDFSValueL(settingsStore, KPMSettingHeartBeat, iSettings.iHeartBeat);
       
   951         SaveDFSValueL(settingsStore, KPMSettingMaxSamples,
       
   952                 iSettings.iMaxSamples);
       
   953         SaveDFSValueL(settingsStore, KPMSettingPriority, iSettings.iPriority);
       
   954         SaveDFSValueL(settingsStore, KPMSettingCPUMode, iSettings.iCPUMode);
       
   955         SaveDFSValueL(settingsStore, KPMSettingKeepBackLightOn,
       
   956                 iSettings.iKeepBacklightOn);
       
   957 
       
   958         SaveDFSValueL(settingsStore, KPMSettingDataPopupVisbility,
       
   959                 iSettings.iDataPopupVisibility);
       
   960         SaveDFSValueL(settingsStore, KPMSettingDataPopupLocation,
       
   961                 iSettings.iDataPopupLocation);
       
   962         SaveDFSValueL(settingsStore, KPMSettingDataPopupSources,
       
   963                 iSettings.iDataPopupSources);
       
   964 
       
   965         SaveDFSValueL(settingsStore, KPMSettingGraphsVerticalBarPeriod,
       
   966                 iSettings.iGraphsVerticalBarPeriod);
       
   967         SaveDFSValueL(settingsStore, KPMSettingGraphsSources,
       
   968                 iSettings.iGraphsSources);
       
   969 
       
   970         SaveDFSValueL(settingsStore, KPMSettingLoggingMode,
       
   971                 iSettings.iLoggingMode);
       
   972         SaveDFSValueL(settingsStore, KPMSettingLoggingFilePath,
       
   973                 iSettings.iLoggingFilePath);
       
   974         SaveDFSValueL(settingsStore, KPMSettingLoggingSources,
       
   975                 iSettings.iLoggingSources);
       
   976 
       
   977         SaveDFSValueL(settingsStore, KPMSettingPowerMonitoringEnabled,
       
   978                 iSettings.iPowerMonitoringEnabled);
       
   979 
       
   980         settingsStore->CommitL();
       
   981         CleanupStack::PopAndDestroy(); // settingsStore
       
   982         }
       
   983     }
       
   984 
       
   985 // ---------------------------------------------------------------------------
       
   986 
       
   987 void CPerfMonEngine::LoadDFSValueL(CDictionaryFileStore* aDicFS,
       
   988         const TUid& aUid, TInt& aValue)
       
   989     {
       
   990     if (aDicFS->IsPresentL(aUid))
       
   991         {
       
   992         RDictionaryReadStream in;
       
   993         in.OpenLC(*aDicFS, aUid);
       
   994         aValue = in.ReadInt16L();
       
   995         CleanupStack::PopAndDestroy(); // in        
       
   996         }
       
   997     }
       
   998 
       
   999 // ---------------------------------------------------------------------------
       
  1000 
       
  1001 void CPerfMonEngine::LoadDFSValueL(CDictionaryFileStore* aDicFS,
       
  1002         const TUid& aUid, TDes& aValue)
       
  1003     {
       
  1004     if (aDicFS->IsPresentL(aUid))
       
  1005         {
       
  1006         RDictionaryReadStream in;
       
  1007         in.OpenLC(*aDicFS, aUid);
       
  1008         TInt bufLength = in.ReadInt16L(); // get length of descriptor
       
  1009         in.ReadL(aValue, bufLength); // get the descriptor itself
       
  1010         CleanupStack::PopAndDestroy(); // in
       
  1011         }
       
  1012     }
       
  1013 
       
  1014 // ---------------------------------------------------------------------------
       
  1015 
       
  1016 void CPerfMonEngine::LoadDFSValueL(CDictionaryFileStore* aDicFS,
       
  1017         const TUid& aUid, TPerfMonSources& aValue)
       
  1018     {
       
  1019     if (aDicFS->IsPresentL(aUid))
       
  1020         {
       
  1021         RDictionaryReadStream in;
       
  1022         in.OpenLC(*aDicFS, aUid);
       
  1023         TInt bufLength = in.ReadInt16L(); // get length of the array
       
  1024 
       
  1025         if (bufLength < 0 || bufLength > ESourcesLength) // check for validaty
       
  1026             User::Leave(KErrNotSupported);
       
  1027 
       
  1028         for (TInt i = 0; i < bufLength; i++) // get all items
       
  1029             aValue.iSrcEnabled[i] = in.ReadInt16L();
       
  1030 
       
  1031         CleanupStack::PopAndDestroy(); // in
       
  1032         }
       
  1033     }
       
  1034 
       
  1035 // ---------------------------------------------------------------------------
       
  1036 
       
  1037 void CPerfMonEngine::SaveDFSValueL(CDictionaryFileStore* aDicFS,
       
  1038         const TUid& aUid, const TInt& aValue)
       
  1039     {
       
  1040     RDictionaryWriteStream out;
       
  1041     out.AssignLC(*aDicFS, aUid);
       
  1042     out.WriteInt16L(aValue);
       
  1043     out.CommitL();
       
  1044     CleanupStack::PopAndDestroy(); // out
       
  1045     }
       
  1046 
       
  1047 // ---------------------------------------------------------------------------
       
  1048 
       
  1049 void CPerfMonEngine::SaveDFSValueL(CDictionaryFileStore* aDicFS,
       
  1050         const TUid& aUid, const TDes& aValue)
       
  1051     {
       
  1052     RDictionaryWriteStream out;
       
  1053     out.AssignLC(*aDicFS, aUid);
       
  1054     out.WriteInt16L(aValue.Length()); // write length of the descriptor
       
  1055     out.WriteL(aValue, aValue.Length()); // write the descriptor itself
       
  1056     out.CommitL();
       
  1057     CleanupStack::PopAndDestroy(); // out
       
  1058     }
       
  1059 
       
  1060 // ---------------------------------------------------------------------------
       
  1061 
       
  1062 void CPerfMonEngine::SaveDFSValueL(CDictionaryFileStore* aDicFS,
       
  1063         const TUid& aUid, const TPerfMonSources& aValue)
       
  1064     {
       
  1065     RDictionaryWriteStream out;
       
  1066     out.AssignLC(*aDicFS, aUid);
       
  1067 
       
  1068     out.WriteInt16L(ESourcesLength); // write length of the array
       
  1069 
       
  1070     for (TInt i = 0; i < ESourcesLength; i++) // write all items
       
  1071         out.WriteInt16L(aValue.iSrcEnabled[i]);
       
  1072 
       
  1073     out.CommitL();
       
  1074     CleanupStack::PopAndDestroy(); // out
       
  1075     }
       
  1076 
       
  1077 // ---------------------------------------------------------------------------
       
  1078 
       
  1079 void CPerfMonEngine::ActivatePowerMonitoringL()
       
  1080     {
       
  1081     if (iPowerClient == 0)
       
  1082         {
       
  1083         iPowerClient = CPerfMonPowerListener::NewL();
       
  1084         }
       
  1085 
       
  1086     // disable power monitoring if initialization fails
       
  1087     TInt err = iPowerClient->Activate();
       
  1088     if (err != KErrNone )
       
  1089         {
       
  1090         DeActivatePowerMonitoring();
       
  1091 
       
  1092         iSettings.iPowerMonitoringEnabled = EFalse;
       
  1093         }
       
  1094     }
       
  1095 
       
  1096 // ---------------------------------------------------------------------------
       
  1097 
       
  1098 void CPerfMonEngine::DeActivatePowerMonitoring()
       
  1099     {
       
  1100     if (iPowerClient != 0)
       
  1101         {
       
  1102         iPowerClient->DeActivate();
       
  1103         }
       
  1104     }
       
  1105 
       
  1106 // ---------------------------------------------------------------------------
       
  1107 
       
  1108 TInt CPerfMonEngine::SampleEntryPosToSettingPos(TInt aSampleEntryPos)
       
  1109     {
       
  1110     TInt settingPos(0); // return position of aSampleEntryPos in settings
       
  1111     
       
  1112     if (aSampleEntryPos >= iCPU0PositionInSamples && aSampleEntryPos < iRAMPositionInSamples)
       
  1113         {
       
  1114         settingPos = ESourceCPU;
       
  1115         }
       
  1116     else if (aSampleEntryPos == iRAMPositionInSamples)
       
  1117         {
       
  1118         settingPos = ESourceRAM;
       
  1119         }
       
  1120     else
       
  1121         {
       
  1122         settingPos = ESourceC + (aSampleEntryPos-iCDrivePositionInSamples);
       
  1123         }
       
  1124     
       
  1125     return settingPos;
       
  1126     }
       
  1127 
       
  1128 // End of File