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