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