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