--- a/sysresmonitoring/oommonitor/src/oommonitor.cpp Tue Feb 02 10:12:00 2010 +0200
+++ b/sysresmonitoring/oommonitor/src/oommonitor.cpp Fri Feb 19 22:58:54 2010 +0200
@@ -16,41 +16,20 @@
*/
-#include <hal.h>
-#include <s32file.h>
-#include <w32std.h>
-#include <akneiksrvc.h>
-#include <LafMemoryWatcher.rsg>
-#include <bautils.h>
-#include <apgwgnam.h>
-#include <apgtask.h>
-#include <barsc.h>
-#include <barsread2.h>
-#include <e32property.h>
-#include <UikonInternalPSKeys.h>
-#include <UiklafInternalCRKeys.h>
-
-#include <data_caging_path_literals.hrh>
#include "oommonitor.h"
-#include "oommonitorplugin.h"
-#include "oommonitorplugin.hrh"
+#include "oommemorymonitor.h"
#include "oommonitorclientserver.h"
-
-#define OOM_WATCHDOG_STATUS_IDLE -1
+#include "oomtraces.h"
-const TInt KPreallocatedSpaceForAppList = 50;
-const TInt KPluginFreeMemoryTime = 100000; // 100 milliseconds for plugins to free memory, overridden by LafMemoryWatcher.rss
+const TInt KStackSize = 0x2000;
-_LIT(KDriveZ, "z:");
-_LIT(KOOMWatcherResourceFileName, "lafmemorywatcher.rsc");
_LIT(KOOMWatcherThreadName, "OOM FW");
-_LIT(KDummyWgName, "20");
// Implements just Error() to avoid panic
-class CSimpleScheduler : public CActiveScheduler
+NONSHARABLE_CLASS(CSimpleScheduler) : public CActiveScheduler
{
void Error( TInt ) const{} // From CActiveScheduler
};
@@ -58,6 +37,8 @@
// thread function for OOM watcher
GLDEF_C TInt WatcherThreadFunction( TAny* )
{
+ FUNC_LOG;
+
TInt err( KErrNone );
CTrapCleanup* cleanup = CTrapCleanup::New();
@@ -95,12 +76,14 @@
// Creates thread for OOM watchers
EXPORT_C void CreateOOMWatcherThreadL()
{
+ FUNC_LOG;
+
RThread thread;
TInt ret = thread.Create( KOOMWatcherThreadName,
WatcherThreadFunction,
- 0x2000, // stack size
+ KStackSize, // stack size
NULL, // uses caller thread's heap
- (TAny*)NULL );
+ NULL );
if ( ret == KErrNone )
{
@@ -111,941 +94,10 @@
User::LeaveIfError( ret );
}
-
-// ======================================================================
-// class CMemoryMonitor
-// ======================================================================
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-CMemoryMonitor* CMemoryMonitor::NewL()
- { // static
- CMemoryMonitor* self = new(ELeave) CMemoryMonitor();
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop(self);
- return self;
- }
-
-CMemoryMonitor::CMemoryMonitor()
-: iRamPluginRunTime(KPluginFreeMemoryTime), iCurrentTask(iWs),
- iMemoryAboveThreshold(ETrue), iPluginMemoryGood(ETrue)
- {
- SetMemoryMonitorTls(this);
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-CMemoryMonitor::~CMemoryMonitor()
- {
- if (iWatchdogStatusSubscriber)
- {
- iWatchdogStatusSubscriber->StopSubscribe();
- }
- iWatchdogStatusProperty.Close();
- delete iWatchdogStatusSubscriber;
-
- delete iServer;
- delete iWservEventReceiver;
- delete iAppCloseTimer;
- delete iAppCloseWatcher;
- delete iOOMWatcher;
- delete iPlugins;
- iAppCloseOrderMap.Close();
- iWgIds.Close();
- delete iWgName;
- iFs.Close();
- iWs.Close();
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void CMemoryMonitor::ConstructL()
- {
- User::LeaveIfError(iWs.Connect());
-
- // Reserve enough space to build an app list later.
- iWgIds.ReserveL(KPreallocatedSpaceForAppList);
- // Reserve enough space for CApaWindowGroupName.
- iWgName = CApaWindowGroupName::NewL(iWs);
- iWgNameBuf = HBufC::NewL(CApaWindowGroupName::EMaxLength);
- (*iWgNameBuf) = KDummyWgName;
- iWgName->SetWindowGroupName(iWgNameBuf); // iWgName takes ownership of iWgNameBuf
-
- // Load up threshold & OOM app lists from resource.
- User::LeaveIfError(iFs.Connect());
-
- RResourceFile resFile;
- TFileName filename(KDriveZ);
- filename.Append(KDC_RESOURCE_FILES_DIR);
- filename.Append(KOOMWatcherResourceFileName);
- BaflUtils::NearestLanguageFile(iFs, filename);
- resFile.OpenL(iFs, filename);
- CleanupClosePushL(resFile);
-
- HBufC8* thresholds = resFile.AllocReadLC(R_APP_OOM_THRESHOLDS);
- RResourceReader theReader;
- theReader.OpenLC(*thresholds);
-
- iLowThreshold = theReader.ReadInt32L();
- iGoodThreshold = theReader.ReadInt32L();
- iMaxExitTime = theReader.ReadInt32L();
- TRAP_IGNORE(iRamPluginRunTime = theReader.ReadInt32L()); // trapped in case lafmemorywatcher.rss does not define this value
-
- CleanupStack::PopAndDestroy(&theReader);
- CleanupStack::PopAndDestroy(thresholds);
-
- // apps to close first, first app in list gets closed first
- ReadAppResourceArrayL(resFile, R_APP_OOM_EXIT_CANDIDATES, ECloseFirst, +1); // +1 means apps later in the list are closed later
- // apps to never close, all apps get order ENeverClose
- ReadAppResourceArrayL(resFile, R_APP_OOM_EXIT_NEVER, ENeverClose, 0); // 0 means that all apps get ENeverClose
- // apps to close last, first app in list gets closed last
- ReadAppResourceArrayL(resFile, R_APP_OOM_EXIT_LAST, ECloseLast, -1); // -1 means apps later in the list are closed earlier
-
- CleanupStack::PopAndDestroy(); // resFile.Close();
-
- iPlugins = new(ELeave) COomPlugins;
- iPlugins->ConstructL();
-
- TInt err = iWatchdogStatusProperty.Attach(KPSUidUikon, KUikOOMWatchdogStatus);
-#ifdef _DEBUG
- RDebug::Print(_L("xxxx KUikOOMWatchdogStatus err=%d"), err);
-#endif
- err = iWatchdogStatusProperty.Set(OOM_WATCHDOG_STATUS_IDLE);
-
- iWatchdogStatusSubscriber = new (ELeave) CSubscribeHelper(TCallBack(WatchdogStatusStatusChanged, this), iWatchdogStatusProperty);
- iWatchdogStatusSubscriber->SubscribeL();
-
- iOOMWatcher = COutOfMemoryWatcher::NewL(*this, iLowThreshold, iGoodThreshold);
- iOOMWatcher->Start();
-
- iAppCloseTimer = CAppCloseTimer::NewL(*this);
- iAppCloseWatcher = new(ELeave) CAppCloseWatcher(*this);
-
- iWservEventReceiver = new(ELeave) CWservEventReceiver(*this, iWs);
- iWservEventReceiver->ConstructL();
-
- iServer = CMemoryMonitorServer::NewL(*this);
- }
-
-void CMemoryMonitor::ReadAppResourceArrayL(RResourceFile& aResFile, TInt aResId, TInt aOrderBase, TInt aOrderInc)
- {
- // apps in this list will be ordered starting from aOrderBase
- TInt order = aOrderBase;
- // get the resource and set up the resource reader
- HBufC8* apps = aResFile.AllocReadLC(aResId);
- TResourceReader theReader;
- theReader.SetBuffer(apps);
- // go through all apps in the list
- TInt appsCount = theReader.ReadUint16();
- for (TInt ii = 0; ii < appsCount; ii++)
- {
- TInt appUid = theReader.ReadInt32();
- // insert the app UID with the appropriate order
- iAppCloseOrderMap.Insert(appUid, order);
- // change the order number as appropriate for this list
- order += aOrderInc;
- }
- CleanupStack::PopAndDestroy(apps);
- }
-
-void CMemoryMonitor::CancelAppCloseWatchers()
- {
- iAppCloserRunning = EFalse;
- iCurrentTask.SetWgId(0);
- if (iAppCloseTimer)
- iAppCloseTimer->Cancel();
- if (iAppCloseWatcher)
- iAppCloseWatcher->Cancel();
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void CMemoryMonitor::FreeMemThresholdCrossedL()
- {
- StartFreeSomeRamL(iGoodThreshold);
- }
-
-void CMemoryMonitor::HandleFocusedWgChangeL()
- {
- // The focused window group has changed.
- if (iAppCloserRunning)
- {
- // if the app closer is currently running, restart it
- RestartAppCloser();
- }
- else if (!iMemoryAboveThreshold)
- {
- // If memory is low, rescan for free memory
- StartFreeSomeRamL(iGoodThreshold);
- }
- }
-
-void CMemoryMonitor::RestartAppCloser()
- {
- CancelAppCloseWatchers();
- // StartFreeSomeRamL is trapped so that clients waiting
- // for completion will definitely receive it.
- TRAPD(err, StartFreeSomeRamL(iCurrentTarget))
- if (err != KErrNone)
- CloseAppsFinished(FreeMemoryAboveThreshold());
- }
-
-// ---------------------------------------------------------
-// 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)
- {
- // update the target if new target is higher
- if (aTargetFree > iCurrentTarget)
- iCurrentTarget = aTargetFree;
-
- // do nothing more if app closer is already running
- if (iAppCloserRunning)
- return;
-
- iCurrentTarget = aTargetFree;
-
- // check if there is enough free memory already.
- if (FreeMemoryAboveThreshold())
- {
- CloseAppsFinished(ETrue);
- return;
- }
-
- // Tell plugins to free memory
- bool pluginsToldToFreeMemory = iPluginMemoryGood;
- SetPluginMemoryGood(EFalse);
-
- // get the list of apps to free
- GetWgsToCloseL();
-
- if (pluginsToldToFreeMemory)
- {
- // Give the plugins a short time to free memory.
- // App close timer will kick off the app closer.
- iAppCloseTimer->After(iRamPluginRunTime);
- }
- else
- {
- // start closing apps
- CloseNextApp();
- }
- }
-
-void CMemoryMonitor::CloseNextApp()
- {
- if(iNextAppToClose >= 0)
- {
- // close an app, if there's an app to be closed
-#ifdef _DEBUG
- RDebug::Print(_L("OOM WATCHER: Target not achieved; continuing... Target:%d"),iCurrentTarget);
-#endif
- // CloseNextApp() may have been called by one of the event
- // watchers, cancel them all to prevent more events from the
- // last app before restarting the watchers for the new app to close
- CancelAppCloseWatchers();
- iAppCloserRunning = ETrue;
- // Set the TApaTask to the app
- iCurrentTask.SetWgId(iWgIds[iNextAppToClose].iId);
- // Start a timer and the thread watcher
- iAppCloseTimer->After(iMaxExitTime);
- iAppCloseWatcher->Start(iCurrentTask);
- // Tell the app to close
- iCurrentTask.EndTask();
- iNextAppToClose--;
- }
- else
- {
- // stop if we have no more apps
- CloseAppsFinished(EFalse);
- }
- }
-
-// handle an app closed event
-void CMemoryMonitor::CloseAppEvent()
- {
- if (FreeMemoryAboveThreshold())
- {
- // stop if we have enough memory
- CloseAppsFinished(ETrue);
- }
- else
- {
- // otherwise try to close another app
- CloseNextApp();
- }
- }
-
-// The app closer is finished
-void CMemoryMonitor::CloseAppsFinished(TBool aMemoryGood)
- {
- CancelAppCloseWatchers();
-#ifdef _DEBUG
- RDebug::Print(_L("OOM WATCHER: Final result: Target:%d Good?:%d"),iCurrentTarget,aMemoryGood);
-#endif
- iServer->CloseAppsFinished(aMemoryGood);
- // plugins can start using memory if result is good
- SetPluginMemoryGood(aMemoryGood);
- }
-
-TBool CMemoryMonitor::FreeMemoryAboveThreshold()
- {
- // may cause some extra load but allows more precise action
- User::CompressAllHeaps();
-
- TInt current = 0;
- HAL::Get( HALData::EMemoryRAMFree, current );
-
-#ifdef _DEBUG
- RDebug::Print(_L("OOM WATCHER: Free RAM now:%d "),current);
-#endif
-
- iMemoryAboveThreshold = (current >= iCurrentTarget);
- return iMemoryAboveThreshold;
- }
-
-void CMemoryMonitor::GetWgsToCloseL()
- {
- // get all window groups, with info about parents
- TInt numGroups = iWs.NumWindowGroups(0);
- iWgIds.ReserveL(numGroups);
- User::LeaveIfError(iWs.WindowGroupList(0, &iWgIds));
-
- // Remove all child window groups, promote parents to foremost child position
- ColapseWindowGroupTree();
-
- // now rearange the list so that it only contains apps to close
- // first remove the foreground window group
- iWgIds.Remove(0);
-
- // go through the list from start to end.
- // this divides the list into two sections. Apps that never
- // close move towards the end of the list, apps that will close
- // go towards the start.
- // apps to close first will be placed further back in the close list.
- TInt numAppsToClose = 0; // numAppsToClose marks the boundary between closing and non-closing apps
- TInt count = iWgIds.Count();
- for (TInt ii=0; ii<count; ii++)
- {
- ASSERT(ii >= numAppsToClose); // we are always looking at apps after the sorted section
- // get the next window group
- RWsSession::TWindowGroupChainInfo info = iWgIds[ii];
- // get the close order for the window group
- TInt closeOrder = AppCloseOrder(ii, info.iId);
- if (closeOrder == ENeverClose)
- {
- // leave apps which should not be closed in place,
- // after the last app to close.
- continue;
- }
- else
- {
- // We no longer need the parent id. Use it to store the close order, to avoid the need to allocate more array space
- info.iParentId = closeOrder;
- // remove the app from it's current position
- iWgIds.Remove(ii);
- // find the right place to insert the app (lower orders are put further back)
- TInt insertPos;
- for (insertPos = 0; insertPos < numAppsToClose; insertPos++)
- {
- // compare this close order with window groups already in the list,
- // whose close order is stored in iParentId
- if (closeOrder > iWgIds[insertPos].iParentId)
- break;
- }
- // Insert the app in the correct place
- ASSERT(insertPos <= ii && insertPos <= numAppsToClose); // apps to close are always moved to front, before the close boundary
- iWgIds.Insert(info, insertPos);
- numAppsToClose++;
- }
- }
-
- // start closing apps from the end of the list of apps to close
- iNextAppToClose = numAppsToClose - 1;
- }
-
-// Calculate the order number in which this app should be closed
-// This is based on the app's UID and its window group Z-order
-// Apps given a lower order will be closed before those with a
-// higher order.
-TInt CMemoryMonitor::AppCloseOrder(TInt aWgIndex, TInt aWgId)
- {
- // get the app's details
- TPtr wgPtr(iWgNameBuf->Des());
- if (iWs.GetWindowGroupNameFromIdentifier(aWgId, wgPtr) != KErrNone)
- return ENeverClose;
- iWgName->SetWindowGroupName(iWgNameBuf);
- TUid uid = iWgName->AppUid(); // This UID comes from the app, not the mmp!
- TInt* order = iAppCloseOrderMap.Find(uid.iUid);
-
- // The default app close order is normal with further
- // back apps getting a lower order
- TInt closeOrder = ECloseNormal - aWgIndex;
- if (order)
- {
- // Apps with a defined close order get that order.
- closeOrder = *order;
- }
- else if (uid.iUid == 0 || iWgName->IsSystem() || iWgName->Hidden() || iWgName->IsBusy())
- {
- // Apps that should never close get the ENeverClose rank
- closeOrder = ENeverClose;
- }
-
- return closeOrder;
- }
-
-void CMemoryMonitor::SetPluginMemoryGood(TBool aSetToGood)
- {
- if (aSetToGood && !iPluginMemoryGood)
- iPlugins->MemoryGood();
- else if (!aSetToGood && iPluginMemoryGood)
- iPlugins->FreeRam();
- iPluginMemoryGood = aSetToGood;
- }
-
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-TInt CMemoryMonitor::WatchdogStatusStatusChanged(TAny* aPtr)
- {
- CMemoryMonitor* self = STATIC_CAST(CMemoryMonitor*,aPtr);
- if (self)
- self->HandleWatchdogStatusCallBackL();
- return KErrNone;
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void CMemoryMonitor::HandleWatchdogStatusCallBackL()
- {
- // Someone has set the key to request some free memory.
- TInt target = 0;
- iWatchdogStatusProperty.Get(target);
-
- // Try to free the RAM.
- if (target >= 1)
- {
- iOOMWatcher->Cancel(); // Pause memory notifys.
- TRAP_IGNORE(StartFreeSomeRamL(target)); // This call could take a few seconds to do its stuff.
- iOOMWatcher->Start(); // Restarts memory monitoring.
- }
- // Set the key back to OOM_WATCHDOG_STATUS_IDLE to indicate we're done.
- iWatchdogStatusProperty.Set(OOM_WATCHDOG_STATUS_IDLE);
- }
-
-// ---------------------------------------------------------
-// Remove child window groups. Promote parent window groups forward to child position
-// ---------------------------------------------------------
-//
-void CMemoryMonitor::ColapseWindowGroupTree()
- {
- // start from the front, wg count can reduce as loop runs
- for (TInt ii=0; ii<iWgIds.Count();)
- {
- RWsSession::TWindowGroupChainInfo& info = iWgIds[ii];
- if (info.iParentId > 0) // wg has a parent
- {
- // Look for the parent position
- TInt parentPos = ii; // use child pos as not-found signal
- TInt count = iWgIds.Count();
- for (TInt jj=0; jj<count; jj++)
- {
- if (iWgIds[jj].iId == info.iParentId)
- {
- parentPos = jj;
- break;
- }
- }
-
- if (parentPos > ii) // parent should be moved forward
- {
- iWgIds[ii] = iWgIds[parentPos];
- iWgIds.Remove(parentPos);
- }
- else if (parentPos < ii) // parent is already ahead of child, remove child
- iWgIds.Remove(ii);
- else // parent not found, skip
- ii++;
- }
- else // wg does not have a parent, skip
- ii++;
- }
- }
-
-void CMemoryMonitor::AppNotExiting(TInt aWgId)
- {
- if (aWgId == iCurrentTask.WgId())
- CloseAppEvent();
- }
-
-
-// ======================================================================
-// class COutOfMemoryWatcher
-// - notifies when free memory crosses preset thresholds
-// ======================================================================
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-COutOfMemoryWatcher* COutOfMemoryWatcher::NewL(CMemoryMonitor& aMonitor, TInt aLowThreshold, TInt aGoodThreshold)
- {
- COutOfMemoryWatcher* self = new (ELeave) COutOfMemoryWatcher(aMonitor);
- CleanupStack::PushL(self);
- self->ConstructL(aLowThreshold, aGoodThreshold);
- CleanupStack::Pop(self);
- return self;
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-COutOfMemoryWatcher::~COutOfMemoryWatcher()
- {
- Cancel();
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-COutOfMemoryWatcher::COutOfMemoryWatcher(CMemoryMonitor& aMonitor)
-: CActive(CActive::EPriorityStandard),
- iLafShutdown(aMonitor)
- {
- CActiveScheduler::Add(this);
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void COutOfMemoryWatcher::ConstructL(TInt aLowThreshold, TInt aGoodThreshold)
- {
- UserSvr::SetMemoryThresholds(aLowThreshold,aGoodThreshold);
- User::LeaveIfError(iChangeNotifier.Create());
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void COutOfMemoryWatcher::Start()
- {
- if (!IsActive())
- {
- iChangeNotifier.Logon(iStatus);
- SetActive();
- }
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void COutOfMemoryWatcher::DoCancel()
- {
- iChangeNotifier.LogonCancel();
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void COutOfMemoryWatcher::RunL()
- {
- TInt status = iStatus.Int();
-
- if (status < 0)
- {
- User::Leave(status);
- }
-
- // Check for memory status change.
- if (status & EChangesFreeMemory)
- {
- iLafShutdown.FreeMemThresholdCrossedL();
- }
-
- // We are not active until FreeMemThresholdCrossedL returns.
- Start();
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-CSubscribeHelper::CSubscribeHelper(TCallBack aCallBack, RProperty& aProperty)
- : CActive(EPriorityNormal), iCallBack(aCallBack), iProperty(aProperty)
- {
- CActiveScheduler::Add(this);
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-CSubscribeHelper::~CSubscribeHelper()
- {
- Cancel();
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void CSubscribeHelper::SubscribeL()
- {
- if (!IsActive())
- {
- iProperty.Subscribe(iStatus);
- SetActive();
- }
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void CSubscribeHelper::StopSubscribe()
- {
- Cancel();
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void CSubscribeHelper::RunL()
- {
- if (iStatus.Int() == KErrNone)
- {
- iCallBack.CallBack();
- SubscribeL();
- }
- }
-
-// ---------------------------------------------------------
-//
-// ---------------------------------------------------------
-//
-void CSubscribeHelper::DoCancel()
- {
- iProperty.Cancel();
- }
-
-
-COomPlugins::COomPlugins()
- {
- }
-
-COomPlugins::~COomPlugins()
- {
- TInt count = iPlugins.Count();
- for (TInt ii=0; ii<count; ii++)
- {
- TPlugin& plugin = iPlugins[ii];
- if (plugin.iImpl) // only if successfully added
- REComSession::DestroyedImplementation(plugin.iDtorUid);
- }
- iPlugins.Close();
- }
-
-void COomPlugins::ConstructL()
- {
- RImplInfoPtrArray implArray;
- CleanupClosePushL(implArray);
- REComSession::ListImplementationsL(KOomPluginInterfaceUid, implArray);
-
- TInt count = implArray.Count();
- iPlugins.ReserveL(count);
-
- for (TInt ii=0; ii<count; ii++)
- {
- iPlugins.AppendL(TPlugin());
- TPlugin& plugin = iPlugins[ii];
- TUid uid(implArray[ii]->ImplementationUid());
- plugin.iImpl = static_cast<COomMonitorPlugin*>(REComSession::CreateImplementationL(uid, plugin.iDtorUid, NULL));
- }
-
- CleanupStack::PopAndDestroy(&implArray);
- }
-
-void COomPlugins::FreeRam()
- {
- TInt count = iPlugins.Count();
- for (TInt ii=0; ii<count; ii++)
- {
- TPlugin& plugin = iPlugins[ii];
- plugin.iImpl->FreeRam();
- }
- }
-
-void COomPlugins::MemoryGood()
- {
- TInt count = iPlugins.Count();
- for (TInt ii=0; ii<count; ii++)
- {
- TPlugin& plugin = iPlugins[ii];
- plugin.iImpl->MemoryGood();
- }
- }
-
-COomPlugins::TPlugin::TPlugin()
-: iImpl(0)
- {
- }
-
-
-CAppCloseTimer* CAppCloseTimer::NewL(CMemoryMonitor& aMonitor)
- {
- CAppCloseTimer* self = new(ELeave)CAppCloseTimer(aMonitor);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop(self);
- return self;
- }
-
-CAppCloseTimer::CAppCloseTimer(CMemoryMonitor& aMonitor)
-: CTimer(CActive::EPriorityStandard), iMonitor(aMonitor)
- {
- CActiveScheduler::Add(this);
- }
-
-void CAppCloseTimer::RunL()
- {
- iMonitor.CloseAppEvent();
- }
-
-
-
-CAppCloseWatcher::CAppCloseWatcher(CMemoryMonitor& aMonitor)
-: CActive(CActive::EPriorityStandard), iMonitor(aMonitor)
- {
- CActiveScheduler::Add(this);
- }
-
-CAppCloseWatcher::~CAppCloseWatcher()
- {
- Cancel();
- }
-
-void CAppCloseWatcher::Start(const TApaTask& aTask)
- {
- TInt err = iThread.Open(aTask.ThreadId());
- if (err == KErrNone)
- {
- iOriginalProcessPriority = iThread.ProcessPriority();
- iThread.SetProcessPriority(EPriorityForeground);
- iThread.Logon(iStatus);
- SetActive();
- }
- else
- {
- iStatus = KRequestPending;
- TRequestStatus* s = &iStatus;
- User::RequestComplete(s, err);
- SetActive();
- }
- }
-
-void CAppCloseWatcher::DoCancel()
- {
- iThread.LogonCancel(iStatus);
- iThread.SetProcessPriority(iOriginalProcessPriority);
- iThread.Close();
- }
-
-void CAppCloseWatcher::RunL()
- {
- if (iThread.Handle())
- iThread.SetProcessPriority(iOriginalProcessPriority);
- iThread.Close();
- // Experimentation shows that memory may take up to 40ms
- // to be released back to the system after app thread close.
- // Using this delay should minimise the number of apps that
- // need to be closed to recover the necessary memory.
- const TInt KAppTidyUpDelay = 40000;
- User::After(KAppTidyUpDelay);
- iMonitor.CloseAppEvent();
- }
-
-
-
-CWservEventReceiver::CWservEventReceiver(CMemoryMonitor& aMonitor, RWsSession& aWs)
-: CActive(CActive::EPriorityStandard), iMonitor(aMonitor), iWs(aWs), iWg(aWs)
- {
- CActiveScheduler::Add(this);
- }
-
-CWservEventReceiver::~CWservEventReceiver()
- {
- Cancel();
- iWg.Close();
- }
-
-void CWservEventReceiver::ConstructL()
- {
- User::LeaveIfError(iWg.Construct((TUint32)this, EFalse));
- iWg.SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront);
- iWg.EnableFocusChangeEvents();
- Queue();
- }
-
-void CWservEventReceiver::Queue()
- {
- iWs.EventReady(&iStatus);
- SetActive();
- }
-
-void CWservEventReceiver::DoCancel()
- {
- iWs.EventReadyCancel();
- }
-
-void CWservEventReceiver::RunL()
- {
- TWsEvent event;
- iWs.GetEvent(event);
- if (event.Type() == EEventFocusGroupChanged)
- iMonitor.HandleFocusedWgChangeL();
- Queue();
- }
-
-
-
-CMemoryMonitorServer* CMemoryMonitorServer::NewL(CMemoryMonitor& aMonitor)
- {
- CMemoryMonitorServer* self=new(ELeave) CMemoryMonitorServer(aMonitor);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop(self);
- return self;
- }
-
-CMemoryMonitorServer::~CMemoryMonitorServer()
- {
- }
-
-CMemoryMonitorServer::CMemoryMonitorServer(CMemoryMonitor& aMonitor)
-:CServer2(CActive::EPriorityStandard), iMonitor(aMonitor)
- {
- }
-
-void CMemoryMonitorServer::ConstructL()
- {
- StartL(KMemoryMonitorServerName);
- }
-
-CSession2* CMemoryMonitorServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const
- {
- return new(ELeave) CMemoryMonitorSession();
- }
-
-TInt CMemoryMonitorServer::RunError(TInt aError)
- {
- Message().Complete(aError);
- //
- // The leave will result in an early return from CServer::RunL(), skipping
- // the call to request another message. So do that now in order to keep the
- // server running.
- ReStart();
- return KErrNone; // handled the error fully
- }
-
-CMemoryMonitor& CMemoryMonitorServer::Monitor()
- {
- return iMonitor;
- }
-
-void CMemoryMonitorServer::CloseAppsFinished(TBool aMemoryGood)
- {
- iSessionIter.SetToFirst();
- CSession2* s;
- while ((s = iSessionIter++) != 0)
- static_cast<CMemoryMonitorSession*>(s)->CloseAppsFinished(aMemoryGood);
- }
-
-
-CMemoryMonitorSession::CMemoryMonitorSession()
- {
- }
-
-void CMemoryMonitorSession::CreateL()
- {
- }
-
-CMemoryMonitorSession::~CMemoryMonitorSession()
- {
- }
-
-CMemoryMonitorServer& CMemoryMonitorSession::Server()
- {
- return *static_cast<CMemoryMonitorServer*>(const_cast<CServer2*>(CSession2::Server()));
- }
-
-CMemoryMonitor& CMemoryMonitorSession::Monitor()
- {
- return Server().Monitor();
- }
-
-void CMemoryMonitorSession::ServiceL(const RMessage2& aMessage)
- {
- aMessage.HasCapabilityL(ECapabilityWriteDeviceData); //Leaves if client has not correct capability
- switch (aMessage.Function())
- {
- case EOomMonitorRequestFreeMemory:
- if (!iRequestFreeRam.IsNull())
- PanicClient(aMessage, EPanicRequestActive);
- // message will be completed when CloseAppsFinished() is called.
- iRequestFreeRam = aMessage;
- Monitor().StartFreeSomeRamL(aMessage.Int0());
- break;
-
- case EOomMonitorCancelRequestFreeMemory:
- if (!iRequestFreeRam.IsNull())
- iRequestFreeRam.Complete(KErrCancel);
- aMessage.Complete(KErrNone);
- break;
-
- case EOomMonitorThisAppIsNotExiting:
- Monitor().AppNotExiting(aMessage.Int0());
- aMessage.Complete(KErrNone);
- break;
-
- default:
- PanicClient(aMessage, EPanicIllegalFunction);
- break;
- }
- }
-
-void CMemoryMonitorSession::CloseAppsFinished(TBool aMemoryGood)
- {
- if (!iRequestFreeRam.IsNull())
- iRequestFreeRam.Complete(aMemoryGood ? KErrNone : KErrNoMemory);
- }
-
-
void PanicClient(const RMessagePtr2& aMessage,TOomMonitorClientPanic aPanic)
{
+ FUNC_LOG;
+
aMessage.Panic(KMemoryMonitorServerName, aPanic);
}