217 // we can't reset action index here because plugins would miss memory good events |
217 // we can't reset action index here because plugins would miss memory good events |
218 |
218 |
219 iAppIndex = 0; |
219 iAppIndex = 0; |
220 |
220 |
221 aWindowGroupList.RefreshL(iTryOptional); |
221 aWindowGroupList.RefreshL(iTryOptional); |
222 |
222 /* |
223 for (TInt i = 0; aWindowGroupList.LowOnMemWgs(i) != KErrNotFound ; i++ ) |
223 for (TInt i = 0; aWindowGroupList.LowOnMemWgs(i) != KErrNotFound ; i++ ) |
224 { |
224 { |
225 if ( iLowOnMemWgs.Find(aWindowGroupList.LowOnMemWgs(i)) == KErrNotFound) |
225 if ( iLowOnMemWgs.Find(aWindowGroupList.LowOnMemWgs(i)) == KErrNotFound) |
226 { |
226 { |
227 iLowOnMemWgs.Append(aWindowGroupList.LowOnMemWgs(i)); |
227 iLowOnMemWgs.Append(aWindowGroupList.LowOnMemWgs(i)); |
228 } |
228 } |
229 } |
229 } |
230 |
230 */ |
231 iRunningKillAppActions = ETrue; |
231 iRunningKillAppActions = ETrue; |
|
232 |
|
233 TInt oldcount = iActionRefs.Count(); |
232 |
234 |
233 if (aWindowGroupList.Count()) |
235 if (aWindowGroupList.Count()) |
234 { |
236 { |
235 // Go through each item in the wglist, create an app close action for this application |
237 // Go through each item in the wglist, create an app close action for this application |
236 TInt wgIndex = aWindowGroupList.Count() - 1; |
238 TInt wgIndex = aWindowGroupList.Count() - 1; |
250 |
252 |
251 // Get the app ID for the wglist item |
253 // Get the app ID for the wglist item |
252 // This sets the window group name |
254 // This sets the window group name |
253 TInt32 appId = aWindowGroupList.AppId(wgIndex, ETrue); |
255 TInt32 appId = aWindowGroupList.AppId(wgIndex, ETrue); |
254 |
256 |
|
257 if(AppCloseActionAlreadyExists(aWindowGroupList, appId)) |
|
258 { |
|
259 wgIndex--; |
|
260 continue; |
|
261 } |
|
262 |
255 CApaWindowGroupName* wgName = aWindowGroupList.WgName(); |
263 CApaWindowGroupName* wgName = aWindowGroupList.WgName(); |
256 __ASSERT_DEBUG(wgName, GOomMonitorPanic(KInvalidWgName)); |
264 __ASSERT_DEBUG(wgName, GOomMonitorPanic(KInvalidWgName)); |
257 |
265 |
258 |
266 |
259 TBool skipped = EFalse; |
267 TBool skipped = EFalse; |
312 |
320 |
313 wgIndex--; |
321 wgIndex--; |
314 } |
322 } |
315 } |
323 } |
316 |
324 |
317 TRACES1("BuildActionListL: Action list built with %d items",iActionRefs.Count()); |
325 TRACES1("BuildActionListL: Action list built with %d new items",iActionRefs.Count()- oldcount); |
318 } |
326 } |
319 |
327 |
|
328 |
|
329 TBool CGOomActionList::AppCloseActionAlreadyExists(CGOomWindowGroupList& aWindowGroupList, TInt32 appId) |
|
330 { |
|
331 for(TInt i = 0 ; i < iActionRefs.Count() ; i++) |
|
332 { |
|
333 TActionRef ref = iActionRefs[i]; |
|
334 if(ref.Type() == TActionRef::EAppClose ) |
|
335 { |
|
336 if(aWindowGroupList.AppIdfromWgId(ref.WgId(), ETrue) == appId) |
|
337 return ETrue; |
|
338 } |
|
339 } |
|
340 return EFalse; |
|
341 } |
320 |
342 |
321 // Execute the OOM actions according to their priority |
343 // Execute the OOM actions according to their priority |
322 // Run batches of OOM actions according to their sync mode |
344 // Run batches of OOM actions according to their sync mode |
323 void CGOomActionList::FreeMemory(TInt aMaxPriority) |
345 void CGOomActionList::FreeMemory(TInt aMaxPriority) |
324 { |
346 { |
362 iAppIndex++; |
384 iAppIndex++; |
363 static_cast<CGOomCloseApp*>(action)->Reconfigure(ref); |
385 static_cast<CGOomCloseApp*>(action)->Reconfigure(ref); |
364 |
386 |
365 ref.iAppPlugin = action; |
387 ref.iAppPlugin = action; |
366 |
388 |
367 //Double checking again if this app is now in foreground, if yes then we dont kill |
389 TInt32 appId = iMonitor.GetWindowGroupList()->AppIdfromWgId(ref.WgId(), ETrue); |
368 CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(iWs, iWs.GetFocusWindowGroup()); |
|
369 |
390 |
370 TInt32 fgApp = wgName->AppUid().iUid; |
391 if(!IsOkToKillApp(appId)) |
371 TInt32 appId = iMonitor.GetWindowGroupList()->AppIdfromWgId(ref.WgId(), ETrue); |
|
372 |
|
373 if(appId == fgApp) |
|
374 { |
|
375 TRACES1("Foreground App wgid %x, spared by GOOM", appId); |
|
376 |
|
377 iCurrentActionIndex++; |
|
378 CleanupStack::PopAndDestroy(); |
|
379 continue; |
|
380 } |
|
381 |
|
382 //check if this is not parent of foreground app |
|
383 TBool spared = EFalse; |
|
384 TRACES1("CGOomActionList::FreeMemory - Going to kill Appid %x ",appId); |
|
385 TInt prevWgId = 0; |
|
386 while(prevWgId != KErrNotFound) |
|
387 { |
|
388 wgName->FindByAppUid(wgName->AppUid(), iWs, prevWgId); |
|
389 |
|
390 if(prevWgId == KErrNotFound) |
|
391 break; |
|
392 |
|
393 TInt parentId = 0; |
|
394 TRAPD(err, parentId = iMonitor.GetWindowGroupList()->FindParentIdL(prevWgId)); |
|
395 TRACES2("CGOomActionList::FreeMemory - Foreground App wgid %d, parent wgid %d",prevWgId, parentId); |
|
396 if( err == KErrNone && parentId != 0) |
|
397 { |
|
398 TInt32 parentAppId = iMonitor.GetWindowGroupList()->AppIdfromWgId(parentId, ETrue); |
|
399 if(parentAppId == appId) |
|
400 { |
|
401 TRACES3("Parent App %x (wgId %d), of Foreground App %x, spared by GOOM", parentAppId, parentId, fgApp); |
|
402 spared = ETrue; |
|
403 break; |
|
404 } |
|
405 } |
|
406 } |
|
407 CleanupStack::PopAndDestroy(); |
|
408 if(spared) |
|
409 { |
392 { |
410 iCurrentActionIndex++; |
393 iCurrentActionIndex++; |
411 if (iCurrentActionIndex >= iActionRefs.Count()) |
394 if (iCurrentActionIndex >= iActionRefs.Count()) |
412 { |
395 { |
413 StateChanged(); |
396 StateChanged(); |
425 iCurrentPluginRun = ref.RunPlugin().Id(); |
408 iCurrentPluginRun = ref.RunPlugin().Id(); |
426 } |
409 } |
427 |
410 |
428 iFreeingMemory = ETrue; |
411 iFreeingMemory = ETrue; |
429 TRACES2("CGOomActionList::FreeMemory: Running action %d which has priority %d", iCurrentActionIndex,ref.Priority()); |
412 TRACES2("CGOomActionList::FreeMemory: Running action %d which has priority %d", iCurrentActionIndex,ref.Priority()); |
|
413 iCurrentActionIndex++; |
430 action->FreeMemory(iCurrentTarget - memoryEstimate, iUseSwRendering); |
414 action->FreeMemory(iCurrentTarget - memoryEstimate, iUseSwRendering); |
431 iCurrentPluginRun = 0; |
415 iCurrentPluginRun = 0; |
432 memoryFreeingActionRun = ETrue; |
416 memoryFreeingActionRun = ETrue; |
433 |
417 |
434 // Actions with EContinueIgnoreMaxBatchSize don't add to the tally of running actions |
418 // Actions with EContinueIgnoreMaxBatchSize don't add to the tally of running actions |
447 } |
431 } |
448 |
432 |
449 if ((ref.SyncMode() == ECheckRam) |
433 if ((ref.SyncMode() == ECheckRam) |
450 || (numberOfRunningActions >= maxBatchSize) |
434 || (numberOfRunningActions >= maxBatchSize) |
451 || estimatedEnoughMemoryFreed |
435 || estimatedEnoughMemoryFreed |
452 || globalConfig.ForceCheckAtPriority(iActionRefs[iCurrentActionIndex].Priority())) |
436 || globalConfig.ForceCheckAtPriority(iActionRefs[iCurrentActionIndex-1].Priority())) |
453 // If this actions requires a RAM check then wait for it to complete |
437 // If this actions requires a RAM check then wait for it to complete |
454 // Also force a check if we've reached the maximum number of concurrent operations |
438 // Also force a check if we've reached the maximum number of concurrent operations |
455 // Also check if we estimate that we have already freed enough memory (assuming that the sync mode is "estimate" |
439 // Also check if we estimate that we have already freed enough memory (assuming that the sync mode is "estimate" |
456 { |
440 { |
457 // Return from the loop - we will be called back (in CGOomActionList::StateChanged()) when the running actions complete |
441 // Return from the loop - we will be called back (in CGOomActionList::StateChanged()) when the running actions complete |
458 iCurrentActionIndex++; |
|
459 TRACES("CGOomActionList::FreeMemory: Exiting run action loop"); |
442 TRACES("CGOomActionList::FreeMemory: Exiting run action loop"); |
460 return; |
443 return; |
461 } |
444 } |
462 // ... otherwise continue running actions, don't wait for any existing ones to complete |
445 // ... otherwise continue running actions, don't wait for any existing ones to complete |
463 iCurrentActionIndex++; |
|
464 |
446 |
465 if (iCurrentActionIndex >= iActionRefs.Count()) |
447 if (iCurrentActionIndex >= iActionRefs.Count()) |
466 { |
448 { |
467 StateChanged(); |
449 StateChanged(); |
468 return; |
450 return; |
484 else |
466 else |
485 { |
467 { |
486 iTryOptional = EFalse; |
468 iTryOptional = EFalse; |
487 iOptionalTried = EFalse; |
469 iOptionalTried = EFalse; |
488 TRACES("CGOomActionList::FreeMemory: No usable memory freeing action has been found"); |
470 TRACES("CGOomActionList::FreeMemory: No usable memory freeing action has been found"); |
|
471 iFreeingMemory = EFalse; |
489 iServer.CloseAppsFinished(freeMemory, EFalse); |
472 iServer.CloseAppsFinished(freeMemory, EFalse); |
490 iMonitor.WaitAndSynchroniseMemoryState(); |
473 iMonitor.WaitAndSynchroniseMemoryState(); |
491 } |
474 } |
492 } |
475 } |
|
476 } |
|
477 |
|
478 TBool CGOomActionList::IsOkToKillApp(TInt aAppId) |
|
479 { |
|
480 |
|
481 //Double checking again if this app is now in foreground, if yes then we dont kill |
|
482 TUid fgAppuid = TUid::Uid(iMonitor.ForegroundAppUid()); |
|
483 TInt32 fgApp = fgAppuid.iUid; |
|
484 TRACES1("Foreground Appuid %x", fgApp); |
|
485 |
|
486 if (aAppId == fgApp) |
|
487 { |
|
488 TRACES1("Foreground App wgid %x, spared by GOOM", aAppId); |
|
489 return EFalse; |
|
490 } |
|
491 |
|
492 //check if this is not parent of foreground app |
|
493 TBool spared = EFalse; |
|
494 TRACES2("CGOomActionList::FreeMemory - Going to kill Appid %x, Foreground app %x ", aAppId, fgApp); |
|
495 TInt prevWgId = 0; |
|
496 |
|
497 CApaWindowGroupName::FindByAppUid(fgAppuid, iWs, prevWgId); |
|
498 TInt i = 0; |
|
499 while ((prevWgId == KErrNotFound) && (i++ < 3)) //try 3 times before quiting. It takes time to get the wgid info when app is starting |
|
500 { |
|
501 TRACES1("Cannot find any more parent, trying again %d",i); |
|
502 User::After(200000); |
|
503 prevWgId = 0; |
|
504 CApaWindowGroupName::FindByAppUid(fgAppuid, iWs, prevWgId); |
|
505 } |
|
506 |
|
507 while (prevWgId != KErrNotFound) |
|
508 { |
|
509 TInt parentId = 0; |
|
510 TRAPD(err, parentId = iMonitor.GetWindowGroupList()->FindParentIdL(prevWgId)); |
|
511 TRACES3("CGOomActionList::FreeMemory - Foreground App AppId %x, wgid %d, parent wgid %d", fgApp, prevWgId, parentId); |
|
512 if (err == KErrNone && parentId > 0) |
|
513 { |
|
514 TInt32 parentAppId = iMonitor.GetWindowGroupList()->AppIdfromWgId(parentId, ETrue); |
|
515 if (parentAppId == aAppId) |
|
516 { |
|
517 TRACES3("Parent App %x (wgId %d), of Foreground App %x, spared by GOOM", parentAppId, parentId, fgApp); |
|
518 spared = ETrue; |
|
519 break; |
|
520 } |
|
521 } |
|
522 CApaWindowGroupName::FindByAppUid(fgAppuid, iWs, prevWgId); |
|
523 } |
|
524 return !spared; |
493 } |
525 } |
494 |
526 |
495 // Should be called when the memory situation is good |
527 // Should be called when the memory situation is good |
496 // It results in notifications of the good memory state to all plugins with an outstanding FreeMemory request |
528 // It results in notifications of the good memory state to all plugins with an outstanding FreeMemory request |
497 void CGOomActionList::MemoryGood() |
529 void CGOomActionList::MemoryGood() |
498 { |
530 { |
499 FUNC_LOG; |
531 FUNC_LOG; |
500 |
532 if(!ALWAYS_SW_REND) |
|
533 { |
501 TInt actionRefIndex = iActionRefs.Count(); |
534 TInt actionRefIndex = iActionRefs.Count(); |
502 |
535 |
503 // Go through each of the action references, if it's a plugin action then call MemoryGood on it |
536 // Go through each of the action references, if it's a plugin action then call MemoryGood on it |
504 // 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 |
537 // 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 |
505 while (actionRefIndex--) |
538 while (actionRefIndex--) |
508 || (iActionRefs[actionRefIndex].Type() == TActionRef::ESystemPlugin)) |
541 || (iActionRefs[actionRefIndex].Type() == TActionRef::ESystemPlugin)) |
509 { |
542 { |
510 iActionRefs[actionRefIndex].RunPlugin().MemoryGood(); |
543 iActionRefs[actionRefIndex].RunPlugin().MemoryGood(); |
511 } |
544 } |
512 } |
545 } |
513 // notify window groups which were triggered to low mem that |
546 // notify window groups which were triggered to low mem that |
|
547 iMonitor.SwitchMemMode(CMemoryMonitor::EGOomGoodMemMode); |
|
548 } |
|
549 /* |
514 TWsEvent event; |
550 TWsEvent event; |
515 event.SetType(KGoomMemoryGoodEvent); // naive |
551 event.SetType(KGoomMemoryGoodEvent); // naive |
516 |
552 |
517 for (TInt i = iLowOnMemWgs.Count()-1; i>=0; i--) |
553 for (TInt i = iLowOnMemWgs.Count()-1; i>=0; i--) |
518 { |
554 { |
519 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS |
555 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS |
520 iWs.SendEventToWindowGroup(iLowOnMemWgs[i], event); |
556 iWs.SendEventToWindowGroup(iLowOnMemWgs[i], event); |
521 #endif // #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS |
557 #endif // #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS |
522 iLowOnMemWgs.Remove(i); |
558 iLowOnMemWgs.Remove(i); |
523 } |
559 } |
|
560 */ |
524 } |
561 } |
525 |
562 |
526 TBool CGOomActionList::FreeMemoryAboveTarget(TInt& aFreeMemory) |
563 TBool CGOomActionList::FreeMemoryAboveTarget(TInt& aFreeMemory) |
527 { |
564 { |
528 FUNC_LOG; |
565 FUNC_LOG; |
670 if (!freeMemoryAboveTarget) |
707 if (!freeMemoryAboveTarget) |
671 // If we are still below the good-memory-threshold then continue running actions |
708 // If we are still below the good-memory-threshold then continue running actions |
672 { |
709 { |
673 TRACES2("CGOomActionList::StateChanged: Finished Action %d out of %d",iCurrentActionIndex, iActionRefs.Count()); |
710 TRACES2("CGOomActionList::StateChanged: Finished Action %d out of %d",iCurrentActionIndex, iActionRefs.Count()); |
674 |
711 |
675 if (iCurrentActionIndex < iActionRefs.Count()-1) |
712 if (iCurrentActionIndex < iActionRefs.Count()) |
676 { |
713 { |
677 // launch more actions, potential recursion !! |
714 // There are still more actions to try, so we continue |
678 iCurrentActionIndex++; |
715 TRACES1("CGOomActionList::StateChanged: All current actions complete, running more actions. freeMemory=%d", freeMemory); |
679 return FreeMemory(iMaxPriority); |
716 return FreeMemory(iMaxPriority); |
680 } |
717 } |
681 |
718 |
682 if(iRunningKillAppActions) |
719 if(iRunningKillAppActions) |
683 { |
720 { |
684 iRunningKillAppActions = EFalse; |
721 iRunningKillAppActions = EFalse; |
685 // There are no more actions to try, so we give up |
|
686 TRACES1("CGOomActionList::StateChanged: All current actions complete, below good threshold with no more actions available. freeMemory=%d", freeMemory); |
|
687 |
722 |
688 if (!iTryOptional && !iOptionalTried && freeMemory < 25*1024*1024 ) // magic, should read this from config |
723 if (!iTryOptional && !iOptionalTried && freeMemory < 25*1024*1024 ) // magic, should read this from config |
689 { |
724 { |
690 iTryOptional = ETrue; |
725 iTryOptional = ETrue; |
691 iOptionalTried = ETrue; |
726 iOptionalTried = ETrue; |
692 iMonitor.RunCloseAppActions(iMaxPriority); |
727 iMonitor.RunCloseAppActions(iMaxPriority); |
693 } |
728 } |
694 else |
729 else |
695 { |
730 { |
|
731 // There are no more actions to try, so we give up |
|
732 TRACES1("CGOomActionList::StateChanged: All current actions complete, below good threshold with no more actions available. freeMemory=%d", freeMemory); |
696 iTryOptional = EFalse; |
733 iTryOptional = EFalse; |
697 iServer.CloseAppsFinished(freeMemory, EFalse); |
734 iServer.CloseAppsFinished(freeMemory, EFalse); |
698 iMonitor.WaitAndSynchroniseMemoryState(); |
735 iMonitor.WaitAndSynchroniseMemoryState(); |
699 } |
736 } |
700 } |
737 } |