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