uiacceltk/hitchcock/goommonitor/src/goommemorymonitor.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/goommonitor/src/goommemorymonitor.cpp	Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,646 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Main classes for Graphics Out of Memory Monitor
+*
+*/
+
+
+#define USE_ASYNCYH_NOTIFICATIONS
+
+
+#include <hal.h>
+#include <libc/string.h>
+#include <UikonInternalPSKeys.h>
+
+//TODO: to be removed for wk44 onwards, should use only <EGL/egl.h> which is already included in goommemorymonitor.h
+#ifdef USE_ASYNCYH_NOTIFICATIONS
+#include <EGL/egl.h>
+#else // use local 
+#include "eglext.h"
+#endif
+
+#include "goommemorymonitor.h"
+#include "goommonitorplugin.h"
+#include "goomconfig.h"
+#include "goommemorymonitorserver.h"
+#include "goomconfigparser.h"
+#include "goomactionlist.h"
+#include "goomlog.h"
+#include "goomtraces.h"
+#include "goomwserveventreceiver.h"
+#include "goomconstants.hrh"
+#include "goomrunpluginconfig.h"
+#include "goomapplicationconfig.h"
+#include "goomcloseappconfig.h"
+#include <goommonitorsession.h>
+#ifdef USE_ASYNCYH_NOTIFICATIONS 
+#include "goomthresholdcrossedao.inl"
+#endif
+
+// ======================================================================
+// class CMemoryMonitor
+// ======================================================================
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CMemoryMonitor* CMemoryMonitor::NewL()
+    { // static
+    FUNC_LOG;
+
+    CMemoryMonitor* self = new(ELeave) CMemoryMonitor();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CMemoryMonitor::CMemoryMonitor()
+    {
+    FUNC_LOG;
+
+    SetGMemoryMonitorTls(this);
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+CMemoryMonitor::~CMemoryMonitor()
+    {
+    FUNC_LOG;
+
+    delete iServer;
+    delete iWservEventReceiver;
+    iFs.Close();
+    iWs.Close();
+
+    delete iGOomWindowGroupList;
+
+    delete iGOomActionList;
+
+    delete iConfig;
+ 
+ #ifdef USE_ASYNCYH_NOTIFICATIONS    
+    delete iMemAllocationsGrowing;
+    delete iMemAllocationsGoingDown;
+ #endif
+    
+    eglTerminate(eglGetDisplay(EGL_DEFAULT_DISPLAY));
+
+#ifdef _DEBUG
+    delete iLogger;
+#endif
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CMemoryMonitor::ConstructL()
+    {
+    FUNC_LOG;
+	
+	    //Initialize EGL extension for memory data
+
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    EGLint major, minor;
+    eglInitialize(dpy, &major, &minor);
+	
+    /*
+     ** Search for extName in the extensions string.  Use of strstr()
+     ** is not sufficient because extension names can be prefixes of
+     ** other extension names.  Could use strtok() but the constant
+     ** string returned by glGetString can be in read-only memory.
+     */
+    TBool extensionFound = EFalse;
+    char *p = (char *) eglQueryString(dpy,EGL_EXTENSIONS);
+    char *end;
+    int extNameLen;
+
+    extNameLen = strlen("EGL_NOK_resource_profiling");
+    end = p + strlen(p);
+
+    while (p < end) 
+        {
+        int n = strcspn(p, " ");
+        if ((extNameLen == n) && (strncmp("EGL_NOK_resource_profiling", p, n) == 0)) 
+            {
+            extensionFound = ETrue;
+            break;
+            }
+        p += (n + 1);
+        }
+  
+    if (!extensionFound)
+        {
+        TRACES("EGL_NOK_resource_profiling not found from EGL_EXTENSIONS");
+        }
+    // okay, let's fetch the function ptr to our profiling functions
+    eglQueryProfilingData = (NOK_resource_profiling)eglGetProcAddress("eglQueryProfilingDataNOK");
+    if (!eglQueryProfilingData)
+        {
+        TRACES("eglQueryProfilingDataNOK not found via eglGetProcAddress()");
+        User::Leave(KErrNotSupported);
+        }
+	
+    User::LeaveIfError(iWs.Connect());
+    iWs.ComputeMode(RWsSession::EPriorityControlDisabled); 
+    
+    iGOomWindowGroupList = CGOomWindowGroupList::NewL(iWs);
+
+    iConfig = CGOomConfig::NewL();
+
+    iServer = CMemoryMonitorServer::NewL(*this);
+    
+   // Load up threshold & OOM app lists from resource.
+    User::LeaveIfError(iFs.Connect());
+
+    CGOomConfigParser* oomConfigParser = new (ELeave) CGOomConfigParser(*iConfig, iFs);
+    CleanupStack::PushL(oomConfigParser);
+    oomConfigParser->ParseL();
+    CleanupStack::PopAndDestroy(oomConfigParser);
+
+    iGOomActionList = CGOomActionList::NewL(*this, *iServer, iWs, *iConfig);
+
+#ifdef _DEBUG
+    iLogger = CGOomLogger::NewL(iWs, iFs);
+#endif
+
+    // Get the thresholds based on the current foreground app and the config
+    RefreshThresholds();
+    
+    iWservEventReceiver = new(ELeave) CWservEventReceiver(*this, iWs);
+    iWservEventReceiver->ConstructL();
+    }
+
+const CGOomGlobalConfig& CMemoryMonitor::GlobalConfig()
+    {
+    CMemoryMonitor* globalMemoryMonitor = static_cast<CMemoryMonitor*>(Dll::Tls());
+    return globalMemoryMonitor->iConfig->GlobalConfig();
+    }
+
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+void CMemoryMonitor::FreeMemThresholdCrossedL(TInt /*aAction*/, TInt aThreshold)
+    {
+    FUNC_LOG;
+    // keep only one notification active at a moment
+#ifdef USE_ASYNCYH_NOTIFICATIONS 
+    if (aThreshold == EGL_PROF_TOTAL_MEMORY_USAGE_GT_NOK)
+        {
+        TRACES("FreeMemThresholdCrossedL : EGL_PROF_TOTAL_MEMORY_USAGE_GT_NOK");
+        iMemAllocationsGrowing->Stop();
+        iMemAllocationsGoingDown->Continue();
+        }
+    else
+        {
+        TRACES("FreeMemThresholdCrossedL : EGL_PROF_TOTAL_MEMORY_USAGE_LT_NOK");
+        iMemAllocationsGrowing->Continue();
+        iMemAllocationsGoingDown->Stop();            
+        }    
+#endif
+
+    StartFreeSomeRamL(iGoodThreshold);
+    if (aThreshold == EGL_PROF_TOTAL_MEMORY_USAGE_LT_NOK)
+        {
+        TInt current = GetFreeMemory();
+        if(current >= iGoodThreshold  && (!NeedToPostponeMemGood()))
+            {
+            TRACES("FreeMemThresholdCrossedL : calling MemoryGOOD");
+            iGOomActionList->MemoryGood();
+            }
+        }
+    }
+
+void CMemoryMonitor::HandleFocusedWgChangeL(TInt aForegroundAppUid)
+    {
+    FUNC_LOG;
+    
+    TRACES1("CMemoryMonitor::HandleFocusedWgChangeL Foregroundapp id = %x", aForegroundAppUid);
+    
+    if(aForegroundAppUid == 0)
+        {
+        return;
+        }
+    iForegroundAppUid = aForegroundAppUid;    
+
+    // Refresh the low and good memory thresholds as they may have changed due to the new foreground application
+    RefreshThresholds(aForegroundAppUid);
+    // Not very elegant, now we poll on each window group change
+    // Should have better trigger e.g. from window server 
+#ifndef USE_ASYNCYH_NOTIFICATIONS  
+    TInt current = GetFreeMemory();
+    if (current < iLowThreshold)
+        {
+        StartFreeSomeRamL(iGoodThreshold);
+        }  
+    else if(current >= iGoodThreshold)
+        {
+        iGOomActionList->MemoryGood();
+        }
+#endif
+     }
+
+void CMemoryMonitor::StartFreeSomeRamL(TInt aTargetFree, TInt aMaxPriority) // The maximum priority of action to run
+    {
+    FUNC_LOG;
+
+    TRACES2("MemoryMonitor::StartFreeSomeRamL: aTargetFree = %d, iCurrentTarget = %d", aTargetFree, iCurrentTarget);
+
+    // Update the target if new target is higher. If the target is lower than the current target and memory
+    // is currently being freed then we do not want to reduce the amount of memory this operation frees.
+    if (aTargetFree > iCurrentTarget)
+        iCurrentTarget = aTargetFree;
+
+    // check if there is enough free memory already.
+    TInt freeMemory;
+    TBool freeMemoryAboveCurrentTarget = FreeGraphicsMemoryAboveThresholdL(freeMemory);
+
+    TRACES2("MemoryMonitor::StartFreeSomeRamL freeMemoryAboveTarget = %d, freeMemory = %d", freeMemoryAboveCurrentTarget, freeMemory);
+
+    if (freeMemoryAboveCurrentTarget)
+        {
+        ResetTargets();
+        /*if(freeMemory >= iGoodThreshold && !NeedToPostponeMemGood())
+            {
+                iGOomActionList->MemoryGood();
+            }
+        */
+        iServer->CloseAppsFinished(freeMemory, ETrue);
+        return;
+        }
+
+    // update wg list only when actually about to use it 
+    //iGOomWindowGroupList->Refresh();
+
+#ifdef _DEBUG
+    iLogger->StartL();
+#endif
+
+    // Build the list of memory freeing actions
+    iGOomActionList->BuildPluginActionListL(*iGOomWindowGroupList, *iConfig);
+
+    //iGOomActionList->SetCurrentTarget(aTargetFree);
+    iGOomActionList->SetCurrentTarget(iCurrentTarget);
+
+    // Run the memory freeing actions
+    iGOomActionList->FreeMemory(aMaxPriority);
+    }
+
+void CMemoryMonitor::RunCloseAppActions(TInt aMaxPriority)
+    {
+    FUNC_LOG;
+    // Build the list of memory freeing actions (by killing apps)
+    iGOomActionList->BuildKillAppActionListL(*iGOomWindowGroupList, *iConfig);
+    iGOomActionList->FreeMemory(aMaxPriority);
+    }
+
+// ---------------------------------------------------------
+// This function attempts to free enough RAM to leave the target amount of space free.
+// This function could take a substantial time to return as it may have to close a number
+// of applications, and each will be given a timeout of KAPPEXITTIMEOUT.
+// ---------------------------------------------------------
+//
+void CMemoryMonitor::StartFreeSomeRamL(TInt aTargetFree)
+    {
+    FUNC_LOG;
+
+    StartFreeSomeRamL(aTargetFree, KGOomPriorityInfinate - 1);
+    }
+
+void CMemoryMonitor::RequestFreeMemoryL(TInt aTargetFree, TBool aUseAbsolute)
+    {
+    FUNC_LOG;
+
+    StartFreeSomeRamL(aUseAbsolute?aTargetFree:(aTargetFree + iLowThreshold), KGOomPriorityInfinate - 1);
+    }
+
+void CMemoryMonitor::FreeOptionalRamL(TInt aTargetFree, TInt aPluginId, TBool aUseAbsolute) // The ID of the plugin that will clear up the allocation, used to determine the priority of the allocation
+    {
+    FUNC_LOG;
+
+    // Calculate the priority of the allocation (the priority of the plugin that will clear it up - 1)
+    TInt priorityOfAllocation = iConfig->GetPluginConfig(aPluginId).CalculatePluginPriority(*iGOomWindowGroupList) - 1;
+    StartFreeSomeRamL(aUseAbsolute?aTargetFree:(aTargetFree + iGoodThreshold), priorityOfAllocation);
+    }
+
+// Does the EGL extension return the amount of memory in bits?
+// If yes, int is clearly not enough
+// Note that this function reserves memory so it can fail if the "standard" memory
+// gets full.
+TBool CMemoryMonitor::FreeGraphicsMemoryAboveThresholdL(TInt& aCurrentFreeMemory)
+    {
+    FUNC_LOG;
+    
+    TInt current = GetFreeMemory();
+    User::LeaveIfError(current);
+    aCurrentFreeMemory = current;
+    
+    return (current >= iCurrentTarget);
+    }
+
+// ---------------------------------------------------------
+//
+// ---------------------------------------------------------
+//
+
+void CMemoryMonitor::AppNotExiting(TInt aWgId)
+    {
+    FUNC_LOG;
+
+    iGOomActionList->AppNotExiting(aWgId);
+    }
+
+
+void CMemoryMonitor::RefreshThresholds(TInt aForegroundAppUid)
+    {
+    FUNC_LOG;    
+    
+    TInt origGood = iGoodThreshold;
+    TInt origLow = iLowThreshold;
+    
+    // Calculate the desired good threshold, this could be the globally configured value...
+    iGoodThreshold = CMemoryMonitor::GlobalConfig().iGoodRamThreshold;
+    iLowThreshold = CMemoryMonitor::GlobalConfig().iLowRamThreshold;
+    iCurrentTarget = iGoodThreshold;
+        
+    TRACES2("CMemoryMonitor::RefreshThresholds: Global Good Threshold = %d, Global Low Threshold = %d", iGoodThreshold, iLowThreshold);
+
+    // The global value can be overridden by an app specific value
+    // Find the application config entry for the foreground application
+    if (aForegroundAppUid == KErrNotFound)
+        {
+        return;
+        }     
+                
+    // If this application configuration overrides the good_ram_threshold then set it
+    if (iConfig->GetApplicationConfig(aForegroundAppUid).iGoodRamThreshold != KGOomThresholdUnset)
+        {
+        iGoodThreshold = iConfig->GetApplicationConfig(aForegroundAppUid).iGoodRamThreshold;
+        TRACES2("CMemoryMonitor::RefreshThresholds: For foreground app %x, Good Threshold = %d", aForegroundAppUid, iGoodThreshold);
+        }
+    
+    // If this application configuration overrides the low_ram_threshold then set it
+    if (iConfig->GetApplicationConfig(aForegroundAppUid).iLowRamThreshold != KGOomThresholdUnset)
+        {
+        iLowThreshold = iConfig->GetApplicationConfig(aForegroundAppUid).iLowRamThreshold;
+        TRACES2("CMemoryMonitor::RefreshThresholds: For foreground app %x, Low Threshold = %d", aForegroundAppUid, iLowThreshold);
+        }
+    
+    // If this application configuration overrides the good_ram_threshold then set it
+    if (iConfig->GetApplicationConfig(aForegroundAppUid).iTargetFree != KGOomThresholdUnset)
+        {
+        iCurrentTarget = iConfig->GetApplicationConfig(aForegroundAppUid).iTargetFree;
+        TRACES2("CMemoryMonitor::RefreshThresholds: For foreground app %x, Target Free on Startup = %d", aForegroundAppUid, iCurrentTarget);
+        }
+    
+    iGOomActionList->SetCurrentTarget(iCurrentTarget);
+    
+#ifdef USE_ASYNCYH_NOTIFICATIONS 
+
+    // if allocation should fail, threshold should not naturally be set
+    if (!iMemAllocationsGrowing)
+        {
+        TRAP_IGNORE(iMemAllocationsGrowing = CreateThresholdCrossedThreadL(*this, EGL_PROF_TOTAL_MEMORY_USAGE_GT_NOK, iLowThreshold))
+        origLow = iLowThreshold; // do not reset
+        }
+    if (!iMemAllocationsGoingDown)
+        {
+        TRAP_IGNORE(iMemAllocationsGoingDown = CreateThresholdCrossedThreadL(*this, EGL_PROF_TOTAL_MEMORY_USAGE_LT_NOK, iGoodThreshold))
+        origGood = iGoodThreshold; // do not reset
+        }
+        
+    TBool releaseClient = ETrue;
+
+    // update thresholds only if they really change
+    if (origGood != iGoodThreshold)
+        {
+        iMemAllocationsGoingDown->SetThreshold(iGoodThreshold);
+        }
+    
+    if ( origLow != iLowThreshold)
+        {
+        // need to synchronously check whether client should wait
+        // memory to be released
+        if(GetFreeMemory() <= iLowThreshold )    
+            {
+            releaseClient = EFalse;
+            }
+        iMemAllocationsGrowing->SetThreshold(iLowThreshold);
+        }
+
+   TRACES3("CMemoryMonitor::RefreshThresholds: releaseClient: %d For foreground app 0x%x, Active client = 0x%x",releaseClient, aForegroundAppUid, ActiveClientId());
+        
+   if (releaseClient && ActiveClientId() == iForegroundAppUid)
+        {
+        iServer->CloseAppsFinished(0, ETrue);    
+        }     
+#endif
+   
+   TRACES2("CMemoryMonitor::RefreshThresholds: Current Good Threshold = %d, Current Low Threshold = %d", iGoodThreshold, iLowThreshold);
+    }
+
+void CMemoryMonitor::ResetTargets(TInt aTarget)
+    {
+    FUNC_LOG;
+
+    //we reset the target when a memory free operation completes, to deal with the case
+    //where the operation was initiated with a target larger than the current good threshold
+    iCurrentTarget = aTarget;
+    iGOomActionList->SetCurrentTarget(iCurrentTarget);
+    }
+
+void CMemoryMonitor::SetPriorityBusy(TInt aWgId)
+    {
+    FUNC_LOG;
+    
+    TRACES2("Received SetPriorityBusy for appid = %x, wgid = %d", iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue), aWgId);
+    iGOomWindowGroupList->SetPriorityBusy(aWgId);
+    AppClosePriorityChanged(aWgId, RGOomMonitorSession::EGOomPriorityBusy);
+    }
+
+void CMemoryMonitor::SetPriorityNormal(TInt aWgId)
+    {
+    FUNC_LOG;
+
+    iGOomWindowGroupList->SetPriorityNormal(aWgId);
+    AppClosePriorityChanged(aWgId, RGOomMonitorSession::EGOomPriorityNormal);
+    }
+
+void CMemoryMonitor::SetPriorityHigh(TInt aWgId)
+    {
+    FUNC_LOG;
+    
+    iGOomWindowGroupList->SetPriorityHigh(aWgId);
+    AppClosePriorityChanged(aWgId, RGOomMonitorSession::EGOomPriorityHigh);
+    }
+
+TInt CMemoryMonitor::GetFreeMemory()
+    {
+	FUNC_LOG;
+    if (!eglQueryProfilingData)
+        {
+    	TRACES("EGL_NOK_resource_profiling not available");
+	    return 0;
+        }
+    EGLint data_count;
+    EGLint* prof_data;
+    TInt i(0);
+    TInt totalMem(0);
+    TInt totalUsed(0);
+	EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+	/* Find out how much profiling data is available */
+	eglQueryProfilingData(dpy, EGL_PROF_QUERY_GLOBAL_BIT_NOK | EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
+							NULL, 0, &data_count);
+
+	TRACES1("eglQueryProfilingData - data size: %d", data_count);
+
+
+	/* Allocate room for the profiling data */
+	prof_data = (EGLint*)User::Alloc(data_count * sizeof(EGLint));
+	if (prof_data == NULL)
+	    {
+    	TRACES1("eglQueryProfilingData - could not alloc: %d", data_count * sizeof(EGLint));	
+		return KErrNoMemory;
+        }
+
+	/* Retrieve the profiling data */
+	eglQueryProfilingData(dpy,
+							 EGL_PROF_QUERY_GLOBAL_BIT_NOK |
+							 EGL_PROF_QUERY_MEMORY_USAGE_BIT_NOK,
+							 prof_data,
+							 data_count,
+							 &data_count);
+
+	/* Iterate over the returned data */
+	while (i < data_count)
+		{
+		TRACES2("EGL_NOK_resource_profiling - index: %d data: %d", i, prof_data[i]);
+		
+		switch (prof_data[i++])
+			{
+			case EGL_PROF_USED_MEMORY_NOK:
+				{
+				totalUsed = prof_data[i++];
+				TRACES1("EGL_NOK_resource_profiling - total Used: %d", totalUsed);
+
+				break;
+				}
+			case EGL_PROF_TOTAL_MEMORY_NOK:
+				{
+				totalMem = prof_data[i++];
+				TRACES1("EGL_NOK_resource_profiling - total Mem: %d", totalMem);
+				break;
+				}
+		    case EGL_PROF_PROCESS_ID_NOK:
+                {
+                if (sizeof(EGLNativeProcessIdTypeNOK) == 8)
+                    {
+                    i+=2;
+                    }
+                else
+                    {
+                    i++;
+                    }
+                break;
+                }
+            case EGL_PROF_PROCESS_USED_PRIVATE_MEMORY_NOK:
+            case EGL_PROF_PROCESS_USED_SHARED_MEMORY_NOK:
+			default:
+				{
+                i++;
+				break;
+				}
+			}
+		}
+
+	/* Free allocated memory */
+	User::Free(prof_data);
+	
+	 
+    if ((totalMem-totalUsed) < 0)
+	    {
+	    return 0;
+	    }
+    return totalMem - totalUsed;
+    }
+
+void CMemoryMonitor::DoPostponedMemoryGood()
+    {
+    FUNC_LOG;
+    TInt current = GetFreeMemory();
+    if(current >= iGoodThreshold  && (!NeedToPostponeMemGood()))
+        {
+        TRACES("DoPostponedMemoryGood calling MemoryGOOD");
+        iGOomActionList->MemoryGood();
+        }
+    }    
+
+
+void CMemoryMonitor::AppClosePriorityChanged(TInt aWgId, TInt aPriority)
+    {
+    FUNC_LOG;
+    CGOomCloseAppConfig* appCloseConfig = NULL;
+    
+    TRACES1("CMemoryMonitor::AppClosePriorityChanged wgid %d", aWgId);
+    
+    switch(aPriority)
+    {
+    case RGOomMonitorSession::EGOomPriorityBusy:
+        appCloseConfig = iConfig->GetApplicationConfig(KGOomBusyAppId).GetAppCloseConfig();
+        TRACES("CMemoryMonitor::AppClosePriorityChanged BUSY");
+        break;
+    case RGOomMonitorSession::EGOomPriorityHigh:
+        appCloseConfig = iConfig->GetApplicationConfig(KGOomHighPriorityAppId).GetAppCloseConfig();
+        TRACES("CMemoryMonitor::AppClosePriorityChanged HIGH");
+        break;
+    default:
+        appCloseConfig = iConfig->GetApplicationConfig(aWgId).GetAppCloseConfig();
+        TRACES("CMemoryMonitor::AppClosePriorityChanged NORMAL");
+    }
+        
+    if (appCloseConfig)
+        {  
+        TInt32 appId = iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue);
+        TInt wgIndex=iGOomWindowGroupList->GetIndexFromAppId(appId);
+        
+        TRACES2("CMemoryMonitor::AppClosePriorityChanged wgindex %d, appid %x", wgIndex, appId);
+        
+        if(wgIndex>=0)
+            {
+            TRACES2("CMemoryMonitor::AppClosePriorityChanged Setting Priority for app %x, wgid %d", appId, aWgId);
+            TUint priority = appCloseConfig->CalculateCloseAppPriority(*iGOomWindowGroupList, wgIndex);
+            iGOomActionList->SetPriority(wgIndex, priority);
+            }
+        else
+            {
+            TRACES1("CMemoryMonitor::AppClosePriorityChanged Could not find wgid %d in windogouplist", aWgId);
+            }
+        }
+    else
+        {
+        TRACES("CMemoryMonitor::AppClosePriorityChanged appCloseConfig not found");
+        }
+    }
+
+CGOomWindowGroupList * CMemoryMonitor::GetWindowGroupList() const
+{
+    return iGOomWindowGroupList; 
+}