sysresmonitoring/oommonitor/tsrc/ut_oom_memorymonitor/src/mockoomwindowgrouplist.cpp
changeset 77 b01c07dfcf84
equal deleted inserted replaced
74:1505405bc645 77:b01c07dfcf84
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  A wrapper for the window group list, adding additional functionality required by OOM Monitor v2.
       
    15 *
       
    16 */
       
    17 
       
    18 #include <w32std.h>
       
    19 #include <e32std.h>
       
    20 #include <apgtask.h>
       
    21 #include <apgwgnam.h>
       
    22 
       
    23 #include "oomwindowgrouplist.h"
       
    24 #include "OomTraces.h"
       
    25 #include "oomconstants.hrh"
       
    26 #include "oompanic.h"
       
    27 
       
    28 #include "globaldata.h"
       
    29 #include "diclog.h"
       
    30 
       
    31 _LIT(KDummyWgName, "20");
       
    32 const TInt KPreallocatedSpaceForAppList = 50;
       
    33 
       
    34 const TUint KOomTicksPerSecond = 1000;
       
    35 
       
    36 COomWindowGroupList::TOomWindowGroupProperties::TOomWindowGroupProperties() :  iIdleTickTime(0), iDynamicPriority(EOomPriorityNormal)
       
    37     {
       
    38     FUNC_LOG;
       
    39     }
       
    40 
       
    41 // Update the list of window groups
       
    42 void COomWindowGroupList::Refresh()
       
    43     {
       
    44     TBuf<KIntValue9> buf(KWingoupListRefresh);
       
    45     DicLog::WriteLog(TUid::Uid(0x0003), buf);
       
    46         
       
    47     FUNC_LOG;
       
    48     
       
    49 #ifdef _DEBUG
       
    50     TRAPD(err, RefreshL());
       
    51     if (err)
       
    52         {
       
    53         TRACES1("COomWindowGroupList::Refresh(): RefreshL leave %d", err);
       
    54         }
       
    55 #else
       
    56     TRAP_IGNORE(RefreshL());
       
    57     // Ignore any error
       
    58     // Errors are very unlikely, the only possibility is OOM errors (which should be very unlikely due to pre-created, re-reserved lists)
       
    59     // The outcome of any error is that the most foreground operations will be missing from the list
       
    60     // meaning that they will not be considered candidates for closing
       
    61 #endif    
       
    62     }
       
    63 
       
    64 // Update the list of window groups
       
    65 // Should be called whenever the 
       
    66 void COomWindowGroupList::RefreshL()
       
    67     {
       
    68     FUNC_LOG;
       
    69 
       
    70     // Refresh window group list
       
    71     // get all window groups, with info about parents
       
    72     TInt numGroups = iWs.NumWindowGroups(0);
       
    73     iWgIds.ReserveL(numGroups);
       
    74     User::LeaveIfError(iWs.WindowGroupList(0, &iWgIds));
       
    75     
       
    76     // Remove all child window groups, promote parents to foremost child position
       
    77     CollapseWindowGroupTree();
       
    78     
       
    79     // Note the current foreground window ID (if there is one)
       
    80     TBool oldForegroundWindowExists = EFalse;
       
    81 
       
    82     TInt oldForegroundWindowId;
       
    83     if (iWgIds.Count() > 0)
       
    84         {
       
    85         oldForegroundWindowId = iWgIds[0].iId;
       
    86         oldForegroundWindowExists = ETrue;
       
    87         }    
       
    88     
       
    89     // Cleanup the idletime hash map to remove idle times for any windows that have closed
       
    90     RemovePropertiesForClosedWindowsL();
       
    91     
       
    92     // Update the idle tick on the old foreground application (which might now be in the background)
       
    93     // This will be set to the current system tick count and will be used later to determine the idle time
       
    94     if (oldForegroundWindowExists)
       
    95         {
       
    96         TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(oldForegroundWindowId);
       
    97         if (wgProperties)
       
    98             {
       
    99             wgProperties->iIdleTickTime = User::NTickCount();
       
   100             }
       
   101         
       
   102         // If there is no idle tick entry for this window ID then it will be created in the next step...
       
   103         }
       
   104     
       
   105     TInt index = iWgIds.Count();
       
   106     
       
   107     while (index--)
       
   108         {
       
   109         // See if there is a tick count entry for each window in the list
       
   110         TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(iWgIds[index].iId);
       
   111         
       
   112         if (!wgProperties)
       
   113             {
       
   114             TOomWindowGroupProperties wgProperties;
       
   115             wgProperties.iIdleTickTime = User::NTickCount();
       
   116             // If there is no idle tick entry for this window then add one
       
   117             iWgToPropertiesMapping.InsertL(iWgIds[index].iId, wgProperties);
       
   118             }
       
   119         }
       
   120     }
       
   121 
       
   122 
       
   123 
       
   124 void COomWindowGroupList::RemovePropertiesForClosedWindowsL()
       
   125     {
       
   126     FUNC_LOG;
       
   127     
       
   128     // First, clear the existing set of window IDs (it would be quicker to delete it BUT we have reserved memory for it and don't want to be allocating in low memory conditions)
       
   129     RHashSet<TInt>::TIter windowIdSetIter(iExistingWindowIds);
       
   130     while (windowIdSetIter.Next())
       
   131         {
       
   132         windowIdSetIter.RemoveCurrent();
       
   133         }
       
   134     
       
   135     // Create the set of existing window IDs (this saves expensive/repeated searching later on)
       
   136     TInt index = iWgIds.Count();
       
   137     while (index--)
       
   138         {
       
   139         iExistingWindowIds.InsertL(iWgIds[index].iId);
       
   140         }
       
   141     
       
   142     // Iterate the idle-time hash map - remove any items where the window no longer exists
       
   143     RHashMap<TInt, TOomWindowGroupProperties>::TIter wgToIdleIterator(iWgToPropertiesMapping);
       
   144     while (wgToIdleIterator.NextKey())
       
   145         {
       
   146         // If the current key (window ID) does not exist in the set then remove the idle-time as it is no longer relevant
       
   147         if (!iExistingWindowIds.Find(*(wgToIdleIterator.CurrentKey())))
       
   148                 wgToIdleIterator.RemoveCurrent();
       
   149         }
       
   150     }
       
   151 
       
   152 
       
   153 TUint COomWindowGroupList::AppId(TInt aIndex, TBool aResolveFromThread) const
       
   154     {
       
   155     FUNC_LOG;
       
   156 
       
   157     // get the app's details
       
   158     TPtr wgPtr(iWgNameBuf->Des());
       
   159     
       
   160     TUid uid;
       
   161       
       
   162     TInt wgId = iWgIds[aIndex].iId;
       
   163     
       
   164     TInt err = iWs.GetWindowGroupNameFromIdentifier(wgId, wgPtr);
       
   165     
       
   166     if (KErrNone != err)
       
   167         // If there is an error then set the UID to 0;
       
   168         {
       
   169         uid.iUid = 0;
       
   170         }
       
   171     else 
       
   172         {
       
   173         iWgName->SetWindowGroupName(iWgNameBuf); // iWgName takes ownership of iWgNameBuf
       
   174         uid = iWgName->AppUid(); // This UID comes from the app, not the mmp!
       
   175         if (aResolveFromThread && uid.iUid == 0)
       
   176             {
       
   177             TApaTask task(iWs);
       
   178             task.SetWgId(wgId);
       
   179             TThreadId threadId = task.ThreadId();
       
   180             
       
   181             TUint resolvedUid = 0;
       
   182             RThread appThread;
       
   183             TInt err = appThread.Open( threadId );
       
   184             if ( err == KErrNone )
       
   185                 {
       
   186                 resolvedUid = appThread.SecureId().iId;
       
   187                 }
       
   188             appThread.Close();
       
   189             TRACES2("COomWindowGroupList::AppId: NULL wg UID, taking from thread; resolvedUid = %x aIndex = %d", resolvedUid, aIndex);            
       
   190             return resolvedUid;               
       
   191             }
       
   192         }
       
   193     
       
   194     return uid.iUid;
       
   195     }
       
   196     
       
   197 
       
   198 TTimeIntervalSeconds COomWindowGroupList::IdleTime(TInt aIndex) const
       
   199     {
       
   200     FUNC_LOG;
       
   201 
       
   202     TUint32 currentTickCount = User::NTickCount();
       
   203         
       
   204     const TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(iWgIds[aIndex].iId);
       
   205     
       
   206     TTimeIntervalSeconds idleTime = 0;
       
   207     
       
   208     if (wgProperties)
       
   209         {
       
   210         // This should also handle the case where the current tick count has wrapped to a lower value than the idle tick time
       
   211         // It will only work if it has wrapped once, but
       
   212         TUint32 differenceBetweenTickCounts = currentTickCount - wgProperties->iIdleTickTime;
       
   213         idleTime = differenceBetweenTickCounts / KOomTicksPerSecond;
       
   214         }
       
   215     
       
   216     return idleTime;
       
   217     }
       
   218   
       
   219 
       
   220 
       
   221 void COomWindowGroupList::CollapseWindowGroupTree()
       
   222     {
       
   223     FUNC_LOG;
       
   224 
       
   225     // start from the front, wg count can reduce as loop runs
       
   226     for (TInt ii=0; ii<iWgIds.Count();)
       
   227         {
       
   228         RWsSession::TWindowGroupChainInfo& info = iWgIds[ii];
       
   229         if (info.iParentId > 0)        // wg has a parent
       
   230             {
       
   231             // Look for the parent position
       
   232             TInt parentPos = ii;        // use child pos as not-found signal
       
   233             TInt count = iWgIds.Count();
       
   234             for (TInt jj=0; jj<count; jj++)
       
   235                 {
       
   236                 if (iWgIds[jj].iId == info.iParentId)
       
   237                     {
       
   238                     parentPos = jj;
       
   239                     break;
       
   240                     }
       
   241                 }
       
   242 
       
   243             if (parentPos > ii)  // parent should be moved forward
       
   244                 {
       
   245                 iWgIds[ii] = iWgIds[parentPos];
       
   246                 iWgIds.Remove(parentPos);
       
   247                 }
       
   248             else if (parentPos < ii)  // parent is already ahead of child, remove child
       
   249                 iWgIds.Remove(ii);
       
   250             else                    // parent not found, skip
       
   251                 ii++;
       
   252             }
       
   253         else    // wg does not have a parent, skip
       
   254             ii++;
       
   255         }    
       
   256     }
       
   257 
       
   258 
       
   259 
       
   260 COomWindowGroupList::COomWindowGroupList(RWsSession& aWs) : iWs(aWs)
       
   261     {
       
   262     FUNC_LOG;
       
   263     }
       
   264 
       
   265 
       
   266 
       
   267 void COomWindowGroupList::ConstructL()
       
   268     {
       
   269     FUNC_LOG;
       
   270 
       
   271     // Reserve enough space to build an app list later.
       
   272     iWgIds.ReserveL(KPreallocatedSpaceForAppList);
       
   273     iUncollapsedWgIds.ReserveL(KPreallocatedSpaceForAppList);
       
   274     
       
   275     // Reserve enough space for the WG to idle tick mapping
       
   276     iWgToPropertiesMapping.ReserveL(KPreallocatedSpaceForAppList);
       
   277     
       
   278     // Reserve enough space for CApaWindowGroupName.
       
   279     iWgName = CApaWindowGroupName::NewL(iWs);
       
   280     iWgNameBuf = HBufC::NewL(CApaWindowGroupName::EMaxLength);
       
   281     (*iWgNameBuf) = KDummyWgName;
       
   282     iWgName->SetWindowGroupName(iWgNameBuf);    // iWgName takes ownership of iWgNameBuf
       
   283     
       
   284     RefreshL();
       
   285     }
       
   286 
       
   287 
       
   288 
       
   289 COomWindowGroupList* COomWindowGroupList::NewL(RWsSession& aWs)
       
   290     {
       
   291     FUNC_LOG;
       
   292 
       
   293     COomWindowGroupList* self = new (ELeave) COomWindowGroupList(aWs);
       
   294     CleanupStack::PushL(self);
       
   295     self->ConstructL();
       
   296     CleanupStack::Pop(self);
       
   297     return self;
       
   298     }
       
   299 
       
   300 
       
   301 
       
   302 COomWindowGroupList::~COomWindowGroupList()
       
   303     {
       
   304     FUNC_LOG;
       
   305 
       
   306     iWgIds.Close();
       
   307     iUncollapsedWgIds.Close();
       
   308     iWgToPropertiesMapping.Close();
       
   309     iExistingWindowIds.Close();
       
   310     delete iWgName;
       
   311     }
       
   312 
       
   313 
       
   314 void COomWindowGroupList::SetPriorityBusy(TInt aWgId)
       
   315     {
       
   316     DicLog::WriteIntLog(TUid::Uid(0x0006),aWgId);
       
   317     
       
   318     FUNC_LOG;
       
   319 
       
   320     Refresh();
       
   321     
       
   322     TInt parentId;
       
   323     TRAPD(err, parentId = FindParentIdL(aWgId));
       
   324     if (err)
       
   325         {
       
   326         parentId = aWgId;
       
   327         }
       
   328     
       
   329     TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(parentId);
       
   330     if (wgProperties)
       
   331         {
       
   332         wgProperties->iDynamicPriority = EOomPriorityBusy;
       
   333         }
       
   334     
       
   335     // If we can't find the window group then ignore it
       
   336     }
       
   337 
       
   338 
       
   339 TInt COomWindowGroupList::FindParentIdL(TInt aWgId)
       
   340     {
       
   341     TInt numGroups = iWs.NumWindowGroups(0);
       
   342     iUncollapsedWgIds.ReserveL(numGroups);
       
   343     User::LeaveIfError(iWs.WindowGroupList(0, &iUncollapsedWgIds));
       
   344 
       
   345     TInt parentPos = KErrNotFound;
       
   346    
       
   347     //loop through the window group list
       
   348     for (TInt i=0; i<numGroups; i++)
       
   349         {
       
   350         //find the index for the required aWgId
       
   351         if (iUncollapsedWgIds[i].iId == aWgId)
       
   352             {
       
   353             parentPos = i;
       
   354             break;
       
   355             }
       
   356         }
       
   357 
       
   358     if (parentPos >=0 )
       
   359         {
       
   360         while (iUncollapsedWgIds[parentPos].iParentId > 0)
       
   361             {
       
   362             // find the index for the parent
       
   363             for (TInt j=0; j<numGroups; j++)
       
   364                 {
       
   365                 if (iUncollapsedWgIds[j].iId == iUncollapsedWgIds[parentPos].iParentId)
       
   366                     {
       
   367                     parentPos = j;
       
   368                     break; // break out of inner loop
       
   369                     }
       
   370                 }
       
   371             }
       
   372         return iUncollapsedWgIds[parentPos].iId;
       
   373         }
       
   374     else 
       
   375         {
       
   376         return KErrNotFound;
       
   377         }
       
   378     }
       
   379 
       
   380 
       
   381 TBool COomWindowGroupList::IsBusy(TInt aWgIndex)
       
   382     {
       
   383     TBool isBusy = EFalse;
       
   384     //__ASSERT_DEBUG(aWgIndex < iWgIds.Count(), OomMonitorPanic(KWindowGroupArrayIndexOutOfBounds));    
       
   385     TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(iWgIds[aWgIndex].iId);
       
   386     if (wgProperties)
       
   387         {
       
   388         isBusy = (wgProperties->iDynamicPriority == EOomPriorityBusy);
       
   389         }
       
   390     
       
   391     return isBusy;
       
   392     }
       
   393 
       
   394 // Returns ETrue if an application has registered itself as high priority at runtime
       
   395 TBool COomWindowGroupList::IsDynamicHighPriority(TInt aWgIndex)
       
   396     {
       
   397     FUNC_LOG;
       
   398 
       
   399     TBool isHighPriority = EFalse;
       
   400     //__ASSERT_DEBUG(aWgIndex < iWgIds.Count(), OomMonitorPanic(KWindowGroupArrayIndexOutOfBounds));    
       
   401     TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(iWgIds[aWgIndex].iId);
       
   402     if (wgProperties)
       
   403         {
       
   404         isHighPriority = (wgProperties->iDynamicPriority == EOomPriorityHigh);
       
   405         }
       
   406     
       
   407     return isHighPriority;
       
   408     }
       
   409 
       
   410 CApaWindowGroupName* COomWindowGroupList::WgName() const
       
   411     {
       
   412     return iWgName;
       
   413     }
       
   414 
       
   415 void COomWindowGroupList::SetPriorityNormal(TInt aWgId)
       
   416     {
       
   417     DicLog::WriteIntLog(TUid::Uid(0x0005),aWgId);
       
   418     
       
   419     FUNC_LOG;
       
   420 
       
   421     Refresh();
       
   422     
       
   423     TInt parentId;
       
   424     TRAPD(err, parentId = FindParentIdL(aWgId));
       
   425     if (err)
       
   426         {
       
   427         parentId = aWgId;
       
   428         }
       
   429     
       
   430     TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(parentId);
       
   431     if (wgProperties)
       
   432         {
       
   433         wgProperties->iDynamicPriority = EOomPriorityNormal;
       
   434         }
       
   435     
       
   436     // If we can't find the window group then ignore it
       
   437     }
       
   438 
       
   439 
       
   440 void COomWindowGroupList::SetPriorityHigh(TInt aWgId)
       
   441     {
       
   442     DicLog::WriteIntLog(TUid::Uid(0x0004),aWgId);
       
   443     
       
   444     FUNC_LOG;
       
   445 
       
   446     Refresh();
       
   447 
       
   448     TInt parentId;
       
   449     TRAPD(err, parentId = FindParentIdL(aWgId));
       
   450     if (err)
       
   451         {
       
   452         parentId = aWgId;
       
   453         }
       
   454     
       
   455     TOomWindowGroupProperties* wgProperties = iWgToPropertiesMapping.Find(parentId);
       
   456     if (wgProperties)
       
   457         {
       
   458         wgProperties->iDynamicPriority = EOomPriorityHigh;
       
   459         }
       
   460     
       
   461     // If we can't find the window group then ignore it
       
   462     }
       
   463 
       
   464 // Find the specificed application in the window group list and return the index
       
   465 TInt COomWindowGroupList::GetIndexFromAppId(TUint aAppId) const
       
   466     {
       
   467     FUNC_LOG;
       
   468 
       
   469     TInt indexInGroupList = Count();
       
   470     TBool appFoundInWindowGroupList = EFalse;
       
   471     
       
   472     while (indexInGroupList--)
       
   473         {
       
   474         if (AppId(indexInGroupList, ETrue) == aAppId)
       
   475             {
       
   476             appFoundInWindowGroupList = ETrue;
       
   477             break;
       
   478             }
       
   479         }
       
   480     
       
   481     if (!appFoundInWindowGroupList)
       
   482         indexInGroupList = KAppNotInWindowGroupList;
       
   483 
       
   484     return indexInGroupList;
       
   485     }