|
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 } |