uiacceltk/hitchcock/goommonitor/src/goomactionlist.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
equal deleted inserted replaced
-1:000000000000 0:15bf7259bb7c
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Classes for executing OOM actions (e.g. closing applications and running plugins).
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <hal.h>
       
    20 #include <apgwgnam.h>
       
    21 
       
    22 #include "goommonitorplugin.h"
       
    23 #include "goommonitorplugin.hrh"
       
    24 #include "goomactionlist.h"
       
    25 #include "goomwindowgrouplist.h"
       
    26 #include "goompanic.h"
       
    27 #include "goomtraces.h"
       
    28 #include "goomconstants.hrh"
       
    29 #include "goommemorymonitor.h"
       
    30 #include "goommemorymonitorserver.h"
       
    31 #include "goomrunplugin.h"
       
    32 #include "goomcloseapp.h"
       
    33 #include "goomconfig.h"
       
    34 #include "goomactionref.h"
       
    35 #include "goomapplicationconfig.h"
       
    36 #include "goomcloseappconfig.h"
       
    37 #include "goomrunpluginconfig.h"
       
    38 
       
    39 template <class T>
       
    40 CGOomPluginList<T>::CGOomPluginList()
       
    41     {
       
    42     FUNC_LOG;
       
    43     }
       
    44 
       
    45 template <class T>
       
    46 CGOomPluginList<T>::~CGOomPluginList()
       
    47     {
       
    48     FUNC_LOG;
       
    49 
       
    50     TInt count = iPlugins.Count();
       
    51     for (TInt ii=0; ii<count; ii++)
       
    52         {
       
    53         TPlugin& plugin = iPlugins[ii];
       
    54         if (plugin.iImpl)    // only if successfully added
       
    55             REComSession::DestroyedImplementation(plugin.iDtorUid);
       
    56         }
       
    57     iPlugins.Close();
       
    58     }
       
    59 
       
    60 template <class T>
       
    61 void CGOomPluginList<T>::ConstructL(TInt aInterfaceUid)
       
    62     {
       
    63     FUNC_LOG;
       
    64 
       
    65     RImplInfoPtrArray implArray;
       
    66     CleanupClosePushL(implArray);
       
    67     REComSession::ListImplementationsL(TUid::Uid(aInterfaceUid), implArray);
       
    68 
       
    69     TInt count = implArray.Count();
       
    70     iPlugins.ReserveL(count);
       
    71 
       
    72     for (TInt ii=0; ii<count; ii++)
       
    73         {
       
    74         iPlugins.AppendL(TPlugin());
       
    75         TPlugin& plugin = iPlugins[ii];
       
    76         TUid uid(implArray[ii]->ImplementationUid());
       
    77         plugin.iImpl = static_cast<T*>(REComSession::CreateImplementationL(uid, plugin.iDtorUid, NULL));
       
    78         plugin.iUid = uid.iUid;
       
    79         }
       
    80 
       
    81     CleanupStack::PopAndDestroy(&implArray);
       
    82     }
       
    83 
       
    84 template <class T>
       
    85 CGOomPluginList<T>::TPlugin::TPlugin()
       
    86 : iImpl(0)
       
    87     {
       
    88     FUNC_LOG;
       
    89    }
       
    90 
       
    91 template <class T>
       
    92 CGOomPluginList<T>* CGOomPluginList<T>::NewL(TInt aInterfaceUid)
       
    93     {
       
    94     FUNC_LOG;
       
    95 
       
    96     CGOomPluginList* self = new (ELeave) CGOomPluginList();
       
    97     CleanupStack::PushL(self);
       
    98     self->ConstructL(aInterfaceUid);
       
    99     CleanupStack::Pop(self);
       
   100     return self;
       
   101     }
       
   102 
       
   103 CGOomActionList* CGOomActionList::NewL(CMemoryMonitor& aMonitor, CMemoryMonitorServer& aServer, RWsSession& aWs, CGOomConfig& aConfig)
       
   104     {
       
   105     FUNC_LOG;
       
   106 
       
   107     CGOomActionList* self = new (ELeave) CGOomActionList(aMonitor, aServer, aWs);
       
   108     CleanupStack::PushL(self);
       
   109     self->ConstructL(aConfig);
       
   110     CleanupStack::Pop();
       
   111     return self;
       
   112     }
       
   113 
       
   114 CGOomActionList::~CGOomActionList()
       
   115     {
       
   116     FUNC_LOG;
       
   117 
       
   118     iCloseAppActions.ResetAndDestroy();
       
   119     iCloseAppActions.Close();
       
   120     iRunPluginActions.ResetAndDestroy();
       
   121     iRunPluginActions.Close();
       
   122 
       
   123     iActionRefs.Close();
       
   124 
       
   125     delete iPluginList;
       
   126 	
       
   127     }
       
   128 
       
   129 // Creates a list of actions based on the contents of the config and the current window group list
       
   130 // Any old actions will be replaced.
       
   131 // This function may leave, however enough memory should be reserved for this process so that at least
       
   132 // some actions have been created for freeing memory, these can then be run by calling FreeMemory.
       
   133 // Note that this function will only leave in extreme circumstances, in normal usage we should have
       
   134 // enough reserved memory to build the complete action list.
       
   135 void CGOomActionList::BuildPluginActionListL(CGOomWindowGroupList& aWindowGroupList, CGOomConfig& aConfig)
       
   136     {
       
   137     FUNC_LOG;
       
   138 
       
   139     if (iFreeingMemory)
       
   140         {
       
   141         TRACES("OOMWATCHER:CGOomActionList::BuildActionListL Memory is currently being freed, do not build action list");
       
   142         TRACES2("OOMWATCHER:CGOomActionList::BuildActionListL iCurrentActionIndex = %d out of %d actions in progress", iCurrentActionIndex, iActionRefs.Count());
       
   143         return;
       
   144         }
       
   145 
       
   146     iActionRefs.Reset();
       
   147     iCurrentActionIndex = 0;
       
   148 
       
   149     TInt actionsIndex = 0;
       
   150     
       
   151     iAppsProtectedByPlugins.Reset();
       
   152     
       
   153     iRunningKillAppActions = EFalse;
       
   154     
       
   155     //
       
   156     // There is only one kind of plugin, the graphics plugin which is based on the oom plugin
       
   157 	// references to v2 plugin types removed as these are not yet used by GOOM
       
   158     // we rely on the pluginlist not having changed since construction
       
   159 
       
   160     // Go through each plugin in the plugin list, create a run-plugin action for each one
       
   161     TInt pluginIndex = iPluginList->Count();
       
   162     while (pluginIndex--)
       
   163         {
       
   164         // Get the config for this plugin
       
   165         CGOomRunPluginConfig& pluginConfig = aConfig.GetPluginConfig(iPluginList->Uid(pluginIndex));
       
   166         TInt priority = pluginConfig.CalculatePluginPriority(aWindowGroupList);
       
   167 
       
   168         TGOomSyncMode syncMode = pluginConfig.iSyncMode;
       
   169         TInt ramEstimate = pluginConfig.iRamEstimate;
       
   170 
       
   171         TActionRef::TActionType actionType;
       
   172 
       
   173         if (pluginConfig.PluginType() == EGOomAppPlugin)
       
   174             {
       
   175             actionType = TActionRef::EAppPlugin;
       
   176             }
       
   177         else
       
   178             actionType = TActionRef::ESystemPlugin;
       
   179 
       
   180         TActionRef ref = TActionRef(actionType, priority, syncMode, ramEstimate, *(iRunPluginActions[actionsIndex]), aWindowGroupList.GetIndexFromAppId(pluginConfig.TargetApp()));
       
   181         iAppsProtectedByPlugins.Append(pluginConfig.TargetApp());
       
   182         TRACES1("Creating Plugin Action Item TargetAppId %x", pluginConfig.TargetApp());
       
   183         //It is valid to have plugins with equal priority
       
   184         User::LeaveIfError(iActionRefs.InsertInOrderAllowRepeats(ref, ComparePriorities));
       
   185 
       
   186         actionsIndex++;
       
   187         }
       
   188     
       
   189     TRACES1("BuildActionListL: Action list built with %d Plugin items",iActionRefs.Count());
       
   190     }
       
   191 
       
   192 void CGOomActionList::BuildKillAppActionListL(CGOomWindowGroupList& aWindowGroupList, CGOomConfig& aConfig)
       
   193     {
       
   194     FUNC_LOG;
       
   195     
       
   196     iActionRefs.Reset();
       
   197     iCurrentActionIndex = 0;
       
   198     
       
   199     aWindowGroupList.RefreshL();
       
   200     
       
   201     iRunningKillAppActions = ETrue;
       
   202     
       
   203     if (aWindowGroupList.Count())
       
   204             {
       
   205             // Go through each item in the wglist, create an app close action for this application
       
   206             TInt wgIndex = aWindowGroupList.Count() - 1;
       
   207             
       
   208             TRACES1("BuildActionListL: Windowgroup list count %d ",aWindowGroupList.Count());
       
   209     
       
   210             // Fix for when fast swap has focus, or pen input server has put itself into the foreground:
       
   211             // the wg at index 1 should be considered as the foreground app.
       
   212             // stopIndex is calculated to take this into account.
       
   213             TUid foregroundUid = TUid::Uid(iMonitor.ForegroundAppUid());
       
   214     
       
   215             TRACES1("BuildActionListL: Foreground App %x ", foregroundUid);
       
   216             
       
   217             while (wgIndex >= 0)
       
   218                 {
       
   219                 CGOomCloseAppConfig* appCloseConfig = NULL;
       
   220     
       
   221                 CApaWindowGroupName* wgName = aWindowGroupList.WgName();
       
   222                 __ASSERT_DEBUG(wgName, GOomMonitorPanic(KInvalidWgName));
       
   223     
       
   224                 // Get the app ID for the wglist item
       
   225                 // This sets the window group name
       
   226                 TInt32 appId = aWindowGroupList.AppId(wgIndex, ETrue);
       
   227      
       
   228                 if ( !appId  || foregroundUid.iUid ==appId || wgName->IsSystem() || wgName->Hidden() || (iAppsProtectedByPlugins.Find(appId) != KErrNotFound))
       
   229                     {
       
   230                     //If the UID is NULL at this point, we assume the process is not an application
       
   231                     //and therefore is not a suitable candidate for closure.
       
   232                     //We also do not close system or hidden apps.
       
   233                     TRACES3("BuildActionListL: Not adding process to action list; UID = %x, wgIndex = %d, wgid = %d", appId, wgIndex, aWindowGroupList.WgId(wgIndex).iId);
       
   234                     TRACES3("BuildActionListL: IsSystem = %d, Hidden = %d, Foregroundapp %x", wgName->IsSystem() ? 1 : 0, wgName->Hidden() ? 1 : 0, foregroundUid);
       
   235                     }
       
   236     
       
   237                 else if (aWindowGroupList.IsBusy(wgIndex) || wgName->IsBusy())
       
   238                     // If the application has been flagged as busy then look up the configuration for busy apps in the config file
       
   239                     {
       
   240                     // Find the app close config for this app ID
       
   241                     appCloseConfig = aConfig.GetApplicationConfig(KGOomBusyAppId).GetAppCloseConfig();
       
   242                     }
       
   243                 else if (aWindowGroupList.IsDynamicHighPriority(wgIndex))
       
   244                     // If the application has been flagged as busy then look up the configuration for busy apps in the config file
       
   245                     {
       
   246                     // Find the app close config for this app ID
       
   247                     appCloseConfig = aConfig.GetApplicationConfig(KGOomHighPriorityAppId).GetAppCloseConfig();
       
   248                     }
       
   249                 else
       
   250                     // If the application hasn't been flagged as busy or high priority then look up the priority according to the config
       
   251                     {
       
   252                     // Find the app close config for this app ID
       
   253                     appCloseConfig = aConfig.GetApplicationConfig(appId).GetAppCloseConfig();
       
   254                     }
       
   255     
       
   256                 // Create the app close action and add it to the action list
       
   257                 if (appCloseConfig)
       
   258                     {
       
   259                     TUint priority = appCloseConfig->CalculateCloseAppPriority(aWindowGroupList, wgIndex);
       
   260                     TInt wgId = aWindowGroupList.WgId(wgIndex).iId;
       
   261                     TGOomSyncMode syncMode = appCloseConfig->iSyncMode;
       
   262                     TInt ramEstimate = appCloseConfig->iRamEstimate;
       
   263                     TActionRef ref = TActionRef(TActionRef::EAppClose, priority, syncMode, ramEstimate, wgId, wgIndex);
       
   264     
       
   265                     //AppClose Actions should always have a unique prioirity determined by the application's z order.
       
   266                     TInt err = iActionRefs.InsertInOrder(ref, ComparePriorities);
       
   267                     if ((err != KErrNone) && (err != KErrAlreadyExists))
       
   268                         {
       
   269                         User::Leave(err);
       
   270                         }
       
   271                     TRACES3("BuildActionListL: Adding app to action list, Uid = %x, wgId = %d, wgIndex = %d", appId, wgId, wgIndex);
       
   272                     }
       
   273     
       
   274                 wgIndex--;
       
   275                 }
       
   276             }
       
   277             
       
   278         TRACES1("BuildActionListL: Action list built with %d items",iActionRefs.Count());
       
   279     }    
       
   280 
       
   281 
       
   282 // Execute the OOM actions according to their priority
       
   283 // Run batches of OOM actions according to their sync mode
       
   284 void CGOomActionList::FreeMemory(TInt aMaxPriority)
       
   285     {
       
   286     FUNC_LOG;
       
   287 
       
   288     if (iFreeingMemory)
       
   289             {
       
   290             TRACES("OOMWATCHER:CGOomActionList::FreeMemory Memory is currently being freed, do not start any more actions");
       
   291             return;
       
   292             }
       
   293     
       
   294     iMaxPriority = aMaxPriority;
       
   295 
       
   296     TBool memoryFreeingActionRun = EFalse;
       
   297 
       
   298     // Get the configured maximum number of applications that can be closed at one time
       
   299     const CGOomGlobalConfig& globalConfig = CMemoryMonitor::GlobalConfig();
       
   300     TInt maxBatchSize = globalConfig.iMaxCloseAppBatch;
       
   301     TInt numberOfRunningActions = 0;
       
   302 
       
   303     TInt memoryEstimate = iMonitor.GetFreeMemory(); // The amount of free memory we expect to be free after the currently initiated operations
       
   304 
       
   305     while (iCurrentActionIndex < iActionRefs.Count())
       
   306         {
       
   307         if(iActionRefs[iCurrentActionIndex].Priority() > aMaxPriority)
       
   308             {
       
   309             TRACES1("Busy App wgid %d, spared by GOOM", iActionRefs[iCurrentActionIndex].WgId());
       
   310             iCurrentActionIndex++;
       
   311             continue;
       
   312             }
       
   313         
       
   314         TActionRef ref = iActionRefs[iCurrentActionIndex];
       
   315         CGOomAction* action = NULL;
       
   316         if (ref.Type() == TActionRef::EAppClose)
       
   317             {
       
   318             action = iCloseAppActions[numberOfRunningActions];
       
   319             static_cast<CGOomCloseApp*>(action)->Reconfigure(ref);
       
   320             
       
   321             //Double checking again if this app is now in foreground, if yes then we dont kill
       
   322             CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(iWs, iWs.GetFocusWindowGroup());
       
   323             RDebug::Print(wgName->WindowGroupName());
       
   324             TInt32 fgApp = wgName->AppUid().iUid;
       
   325             TInt32 appId = iMonitor.GetWindowGroupList()->AppIdfromWgId(ref.WgId(), ETrue);
       
   326             if(appId == fgApp)
       
   327                 {
       
   328                 TRACES1("Foreground App wgid %x, spared by GOOM", appId);
       
   329                 
       
   330                 iCurrentActionIndex++;
       
   331                 continue;
       
   332                 }
       
   333             }
       
   334         else
       
   335             {
       
   336             action = &(ref.RunPlugin());
       
   337             }
       
   338 
       
   339         iFreeingMemory = ETrue;
       
   340         TRACES2("CGOomActionList::FreeMemory: Running action %d which has priority %d", iCurrentActionIndex,ref.Priority());
       
   341         action->FreeMemory(iCurrentTarget - memoryEstimate);
       
   342         memoryFreeingActionRun = ETrue;
       
   343 
       
   344         // Actions with EContinueIgnoreMaxBatchSize don't add to the tally of running actions
       
   345         if (ref.SyncMode() != EContinueIgnoreMaxBatchSize)
       
   346             numberOfRunningActions++;
       
   347 
       
   348         // Update our estimate of how much RAM we think we'll have after this operation
       
   349         memoryEstimate += ref.RamEstimate();
       
   350 
       
   351         // Do we estimate that we are freeing enough memory (only applies if the sync mode is "esimtate" for this action)
       
   352         TBool estimatedEnoughMemoryFreed = EFalse;
       
   353         if ((ref.SyncMode() == EEstimate)
       
   354             && (memoryEstimate >= iCurrentTarget))
       
   355             {
       
   356             estimatedEnoughMemoryFreed = ETrue;
       
   357             }
       
   358 
       
   359         if ((ref.SyncMode() == ECheckRam)
       
   360                 || (numberOfRunningActions >= maxBatchSize)
       
   361                 || estimatedEnoughMemoryFreed
       
   362                 || globalConfig.ForceCheckAtPriority(iActionRefs[iCurrentActionIndex].Priority()))
       
   363             // If this actions requires a RAM check then wait for it to complete
       
   364             // Also force a check if we've reached the maximum number of concurrent operations
       
   365             // Also check if we estimate that we have already freed enough memory (assuming that the sync mode is "estimate"
       
   366             {
       
   367             // Return from the loop - we will be called back (in CGOomActionList::StateChanged()) when the running actions complete
       
   368             TRACES("CGOomActionList::FreeMemory: Exiting run action loop");
       
   369             return;
       
   370             }
       
   371         // ... otherwise continue running actions, don't wait for any existing ones to complete
       
   372         iCurrentActionIndex++;
       
   373         }
       
   374 
       
   375 
       
   376     if (!memoryFreeingActionRun)
       
   377         {
       
   378         // No usable memory freeing action has been found, so we give up
       
   379         TRACES("CGOomActionList::FreeMemory: No usable memory freeing action has been found");
       
   380         iMonitor.ResetTargets();
       
   381         TInt freeMemory;
       
   382         if (FreeMemoryAboveTarget(freeMemory) && !iMonitor.NeedToPostponeMemGood())
       
   383             {
       
   384             MemoryGood();
       
   385             }
       
   386         iServer.CloseAppsFinished(freeMemory, EFalse);
       
   387         }
       
   388     }
       
   389 
       
   390 // Should be called when the memory situation is good
       
   391 // It results in notifications of the good memory state to all plugins with an outstanding FreeMemory request
       
   392 void CGOomActionList::MemoryGood()
       
   393     {
       
   394     FUNC_LOG;
       
   395 
       
   396     TInt actionRefIndex = iActionRefs.Count();
       
   397 
       
   398     // Go through each of the action references, if it's a plugin action then call MemoryGood on it
       
   399     // Note that this only results in a call to the plugin if FreeMemory has been called on this plugin since that last call to MemoryGood
       
   400     while (actionRefIndex--)
       
   401         {
       
   402         if ((iActionRefs[actionRefIndex].Type() == TActionRef::EAppPlugin)
       
   403                 || (iActionRefs[actionRefIndex].Type() == TActionRef::ESystemPlugin))
       
   404             {
       
   405             iActionRefs[actionRefIndex].RunPlugin().MemoryGood();
       
   406             }
       
   407         }
       
   408     }
       
   409 
       
   410 TBool CGOomActionList::FreeMemoryAboveTarget(TInt& aFreeMemory)
       
   411     {
       
   412     FUNC_LOG;
       
   413 
       
   414     aFreeMemory = iMonitor.GetFreeMemory();
       
   415 
       
   416     TRACES1("CGOomActionList::FreeMemoryAboveTarget: Free RAM now %d",aFreeMemory);
       
   417 
       
   418     return (aFreeMemory >= iCurrentTarget);
       
   419     }
       
   420 
       
   421 TInt CGOomActionList::ComparePriorities(const TActionRef& aPos1, const TActionRef& aPos2 )
       
   422     {
       
   423     FUNC_LOG;
       
   424 
       
   425     if (aPos1.Priority()< aPos2.Priority())
       
   426         {
       
   427         return -1;
       
   428         }
       
   429     if (aPos1.Priority() > aPos2.Priority())
       
   430         {
       
   431         return 1;
       
   432         }
       
   433 
       
   434     // If priorities are equal then we use hardcoded rules to determine which one is run...
       
   435 
       
   436     // All other actions are run in preference to application closures
       
   437 	if ((aPos1.Type() != TActionRef::EAppClose)
       
   438 			&& ((aPos2.Type() == TActionRef::EAppClose)))
       
   439 		{
       
   440 		return -1;
       
   441 		}
       
   442 	if ((aPos1.Type() == TActionRef::EAppClose)
       
   443 			&& ((aPos2.Type() != TActionRef::EAppClose)))
       
   444 		{
       
   445 		return 1;
       
   446 		}
       
   447 	// If both actions are application closures then the Z order is used to determine which one to run (furthest back application will be closed first)
       
   448 	if ((aPos1.Type() == TActionRef::EAppClose)
       
   449 			&& ((aPos2.Type() == TActionRef::EAppClose)))
       
   450 		{
       
   451 		if (aPos1.WgIndex() < aPos2.WgIndex())
       
   452 			{
       
   453 			return 1;
       
   454 			}
       
   455 		else
       
   456 			{
       
   457 			return -1;
       
   458 			}
       
   459 		//Two Apps should not have equal window group indexes, we panic below if this is the case.
       
   460 		}
       
   461 
       
   462 	// Application plugins will be run in preference to system plugins
       
   463 	if ((aPos1.Type() == TActionRef::EAppPlugin)
       
   464 			&& ((aPos2.Type() == TActionRef::ESystemPlugin)))
       
   465 		{
       
   466 		return -1;
       
   467 		}
       
   468 	if ((aPos1.Type() == TActionRef::ESystemPlugin)
       
   469 			&& ((aPos2.Type() == TActionRef::EAppPlugin)))
       
   470 		{
       
   471 		return 1;
       
   472 		}
       
   473 
       
   474 	// If both actions are application plugins then the Z order of the target app is used to determine which one to run (the one with the furthest back target app will be closed first)
       
   475 	// If the target app is not running then the plugin is run in preference to target apps where the target app is running
       
   476 	if ((aPos1.Type() == TActionRef::EAppPlugin)
       
   477 			&& ((aPos2.Type() == TActionRef::EAppPlugin)))
       
   478 		{
       
   479 		// When the target app is not running then the plugin will be run ahead of plugins where the target app is running
       
   480 		if ((aPos1.WgIndex() == KAppNotInWindowGroupList) && (aPos2.WgIndex() != KAppNotInWindowGroupList))
       
   481 			{
       
   482 			return -1;
       
   483 			}
       
   484 		if ((aPos1.WgIndex() != KAppNotInWindowGroupList) && (aPos2.WgIndex() == KAppNotInWindowGroupList))
       
   485 			{
       
   486 			return 1;
       
   487 			}
       
   488 		// If the target apps for both plugins are running then compare the Z order
       
   489 		if ((aPos1.WgIndex() != KAppNotInWindowGroupList) && (aPos2.WgIndex() != KAppNotInWindowGroupList))
       
   490 			{
       
   491 			if (aPos1.WgIndex() < aPos2.WgIndex())
       
   492 				{
       
   493 				return 1;
       
   494 				}
       
   495 			else
       
   496 				{
       
   497 				return -1;
       
   498 				}
       
   499 			}
       
   500 		// If the target app for neither plugin is running then they are of equal priority
       
   501 		}
       
   502     //App Close Actions must have a unique priority.
       
   503     __ASSERT_DEBUG((aPos1.Type() != TActionRef::EAppClose) && (aPos2.Type() != TActionRef::EAppClose), GOomMonitorPanic(KAppCloseActionEqualPriorities));
       
   504     return 0;
       
   505     }
       
   506 
       
   507 void CGOomActionList::AppNotExiting(TInt aWgId)
       
   508     {
       
   509     FUNC_LOG;
       
   510 
       
   511     TInt index = iCloseAppActions.Count();
       
   512     while (index--)
       
   513         {
       
   514         CGOomCloseApp* action = iCloseAppActions[index];
       
   515         if ( (action->WgId() == aWgId) && (action->IsRunning()) )
       
   516             {
       
   517             TRACES1("CGOomCloseApp::AppNotExiting: App with window group id %d has not responded to the close event", aWgId);
       
   518             action->CloseAppEvent();
       
   519             }
       
   520         }
       
   521     }
       
   522 
       
   523 // From MGOomActionObserver
       
   524 // An action has changed state (possibly it has completed freeing memory)
       
   525 void CGOomActionList::StateChanged()
       
   526     {
       
   527     FUNC_LOG;
       
   528 
       
   529     TBool allActionsComplete = ETrue;
       
   530 
       
   531     // Note that the actions themselves are responsible for timing out if necessary.
       
   532     TInt index = iCloseAppActions.Count();
       
   533     while ((index--) && (allActionsComplete))
       
   534         {
       
   535         if (iCloseAppActions[index]->IsRunning())
       
   536             {
       
   537             TRACES1("CGOomActionList::StateChanged. CloseAppAction %d STILL RUNNING. PROBLEM !!! YOU SHOULD NEVER SEE THIS", index);
       
   538             allActionsComplete = EFalse;
       
   539             }
       
   540         }
       
   541 
       
   542     index = iRunPluginActions.Count();
       
   543     while ((index--) && (allActionsComplete))
       
   544         {
       
   545         if (iRunPluginActions[index]->IsRunning())
       
   546             {
       
   547             TRACES1("CGOomActionList::StateChanged. PluginAction %d STILL RUNNING. PROBLEM !!! YOU SHOULD NEVER SEE THIS", index);
       
   548             allActionsComplete = EFalse;
       
   549             }
       
   550         }
       
   551 
       
   552     TRACES1("CGOomActionList::StateChanged. Current Target = %d", iCurrentTarget);
       
   553     
       
   554     if (allActionsComplete)
       
   555         {
       
   556         iFreeingMemory = EFalse;
       
   557         // If all of the actions are complete then check memory and run more if necessary
       
   558         TInt freeMemory;
       
   559         TBool freeMemoryAboveTarget = FreeMemoryAboveTarget(freeMemory);
       
   560         TRACES1("CGOomActionList::StateChanged. Free Memory = %d", freeMemory);
       
   561         if (!freeMemoryAboveTarget)
       
   562             // If we are still below the good-memory-threshold then continue running actions
       
   563             {            
       
   564             TRACES2("CGOomActionList::StateChanged: Finished Action %d out of %d",iCurrentActionIndex, iActionRefs.Count());
       
   565             
       
   566             iCurrentActionIndex++;
       
   567             
       
   568             if (iCurrentActionIndex >= iActionRefs.Count())
       
   569                 {
       
   570                 if(iRunningKillAppActions)
       
   571                     {
       
   572                     iRunningKillAppActions = EFalse;
       
   573                     // There are no more actions to try, so we give up
       
   574                     TRACES1("CGOomActionList::StateChanged: All current actions complete, below good threshold with no more actions available. freeMemory=%d", freeMemory);
       
   575                     iMonitor.ResetTargets();
       
   576                     /* Do not call memory good immidiately after freeing memory for some app
       
   577                     if (freeMemory >= iCurrentTarget && !iMonitor.NeedToPostponeMemGood())
       
   578                     {                    
       
   579                     MemoryGood();
       
   580                     }
       
   581                      */
       
   582                     iServer.CloseAppsFinished(freeMemory, EFalse);
       
   583                     }
       
   584                 else
       
   585                     {
       
   586                     TRACES1("CGOomActionList::StateChanged: All current Plugin actions complete, below good threshold, Time to kill bad guys. freeMemory=%d", freeMemory);
       
   587                     iRunningKillAppActions = ETrue;
       
   588                     iMonitor.RunCloseAppActions(iMaxPriority);
       
   589                     }
       
   590                 }
       
   591             else
       
   592                 {
       
   593                 // There are still more actions to try, so we continue
       
   594                 TRACES1("CGOomActionList::StateChanged: All current actions complete, running more actions. freeMemory=%d", freeMemory);
       
   595                 FreeMemory(iMaxPriority);
       
   596                 }
       
   597             }
       
   598         else
       
   599             {
       
   600             TRACES1("CGOomActionList::StateChanged: All current actions complete, memory good. freeMemory=%d", freeMemory);
       
   601             /* Do not call memory good immidiately after freeing memory for some app
       
   602 			if(freeMemory > iMonitor.GetGoodThreshold() && !iMonitor.NeedToPostponeMemGood())
       
   603                 {
       
   604                 MemoryGood();
       
   605                 }
       
   606             */
       
   607             iRunningKillAppActions = EFalse;
       
   608             iMonitor.ResetTargets();
       
   609             iServer.CloseAppsFinished(freeMemory, ETrue);
       
   610             }
       
   611         }
       
   612 
       
   613     // If some actions are not yet in the idle state then we must continue to wait for them (they will notify us of a state change via a callback)
       
   614     }
       
   615 
       
   616 CGOomActionList::CGOomActionList(CMemoryMonitor& aMonitor, CMemoryMonitorServer& aServer, RWsSession& aWs)
       
   617     : iWs(aWs), iMonitor(aMonitor), iServer(aServer)
       
   618     {
       
   619     FUNC_LOG;
       
   620     }
       
   621 
       
   622 void CGOomActionList::ConstructL(CGOomConfig& aConfig)
       
   623     {
       
   624     FUNC_LOG;
       
   625 
       
   626     iCurrentActionIndex = 0;
       
   627     iFreeingMemory = EFalse;
       
   628 
       
   629     // Get the list of plugins available to the system
       
   630 
       
   631     iPluginList = CGOomPluginList<CGOomMonitorPlugin>::NewL(KGOomPluginInterfaceUidValue);
       
   632     // Go through each plugin in the plugin list, create a run-plugin action for each one
       
   633     TInt pluginIndex = iPluginList->Count();
       
   634     while (pluginIndex--)
       
   635         {
       
   636         // Get the config for this plugin
       
   637         CGOomRunPluginConfig& pluginConfig = aConfig.GetPluginConfig(iPluginList->Uid(pluginIndex));
       
   638 
       
   639         // Create an action acording to the config
       
   640         CGOomRunPlugin* action = CGOomRunPlugin::NewL(iPluginList->Uid(pluginIndex), pluginConfig, *this, iPluginList->Implementation(pluginIndex));
       
   641 
       
   642         iRunPluginActions.AppendL(action);
       
   643         }
       
   644 
       
   645 	//references to v2 plugin types removed as these are not yet used by GOOM
       
   646 	
       
   647     //allocate empty CGOomCloseApp objects
       
   648     TInt appCloseIndex = aConfig.GlobalConfig().iMaxCloseAppBatch;
       
   649     while (appCloseIndex--)
       
   650         {
       
   651         CGOomCloseApp* action = CGOomCloseApp::NewL(*this, iWs);
       
   652         iCloseAppActions.AppendL(action);
       
   653         }
       
   654     }
       
   655 
       
   656 void CGOomActionList::SetPriority(TInt aWgIndex, TInt aPriority)
       
   657     {
       
   658     FUNC_LOG;
       
   659 
       
   660     TInt idx = iActionRefs.Count()-1;
       
   661     while(idx >= 0)
       
   662         {
       
   663         if(iActionRefs[idx].WgIndex() == aWgIndex)
       
   664             {
       
   665             break;
       
   666             }
       
   667         idx--;
       
   668         }
       
   669     
       
   670     if(idx >= 0)
       
   671         {
       
   672         TRACES2("CGOomActionList::SetPriority Setting app wgindex %d, index %d as busy", aWgIndex, idx);
       
   673         iActionRefs[idx].SetPriority(aPriority);
       
   674         if (!iFreeingMemory)
       
   675             {
       
   676             iActionRefs.Sort(ComparePriorities);
       
   677             }
       
   678         }
       
   679     else
       
   680         {
       
   681         TRACES1("CGOomActionList::SetPriority wgindex %d not in the hitlist", aWgIndex);
       
   682         }
       
   683     }