46 #include <goommonitorsession.h> |
46 #include <goommonitorsession.h> |
47 #ifdef USE_ASYNCYH_NOTIFICATIONS |
47 #ifdef USE_ASYNCYH_NOTIFICATIONS |
48 #include "goomthresholdcrossedao.inl" |
48 #include "goomthresholdcrossedao.inl" |
49 #endif |
49 #endif |
50 |
50 |
|
51 const TInt KGoomWaitTimeToSynch = 1000000; |
|
52 |
51 // ====================================================================== |
53 // ====================================================================== |
52 // class CMemoryMonitor |
54 // class CMemoryMonitor |
53 // ====================================================================== |
55 // ====================================================================== |
54 |
56 |
55 // --------------------------------------------------------- |
57 // --------------------------------------------------------- |
182 // Get the thresholds based on the current foreground app and the config |
186 // Get the thresholds based on the current foreground app and the config |
183 RefreshThresholds(); |
187 RefreshThresholds(); |
184 |
188 |
185 iWservEventReceiver = new(ELeave) CWservEventReceiver(*this, iWs); |
189 iWservEventReceiver = new(ELeave) CWservEventReceiver(*this, iWs); |
186 iWservEventReceiver->ConstructL(); |
190 iWservEventReceiver->ConstructL(); |
|
191 |
|
192 iSynchTimer = CGOomSynchTimer::NewL(*this); |
187 } |
193 } |
188 |
194 |
189 const CGOomGlobalConfig& CMemoryMonitor::GlobalConfig() |
195 const CGOomGlobalConfig& CMemoryMonitor::GlobalConfig() |
190 { |
196 { |
191 CMemoryMonitor* globalMemoryMonitor = static_cast<CMemoryMonitor*>(Dll::Tls()); |
197 CMemoryMonitor* globalMemoryMonitor = static_cast<CMemoryMonitor*>(Dll::Tls()); |
200 void CMemoryMonitor::FreeMemThresholdCrossedL(TInt /*aAction*/, TInt aThreshold) |
206 void CMemoryMonitor::FreeMemThresholdCrossedL(TInt /*aAction*/, TInt aThreshold) |
201 { |
207 { |
202 FUNC_LOG; |
208 FUNC_LOG; |
203 // keep only one notification active at a moment |
209 // keep only one notification active at a moment |
204 #ifdef USE_ASYNCYH_NOTIFICATIONS |
210 #ifdef USE_ASYNCYH_NOTIFICATIONS |
205 if (aThreshold == EGL_PROF_TOTAL_MEMORY_USAGE_GT_NOK) |
211 |
206 { |
212 if (aThreshold == EGL_PROF_TOTAL_MEMORY_USAGE_LT_NOK) |
207 TRACES("FreeMemThresholdCrossedL : EGL_PROF_TOTAL_MEMORY_USAGE_GT_NOK"); |
213 { |
|
214 TInt current = GetFreeMemory(); |
|
215 if(current >= iGoodThreshold && (!NeedToPostponeMemGood())) |
|
216 { |
|
217 TRACES2("FreeMemThresholdCrossedL : crossed good threshold Free %d, GThresh %d, Calling MemoryGood",current, iGoodThreshold); |
|
218 iGOomActionList->MemoryGood(); |
|
219 iMemAllocationsGrowing->Continue(); |
|
220 iMemAllocationsGoingDown->Stop(); |
|
221 return; |
|
222 } |
|
223 else |
|
224 { |
|
225 TRACES3("FreeMemThresholdCrossedL : Not Calling MemoryGOOD. Free %d, GThresh %d, Handshakepending = %d",current, iGoodThreshold, NeedToPostponeMemGood()?1:0); |
|
226 //if we remain in low mem mode, we have to wait for the same trigger i.e. free mem crossing good threshold |
|
227 |
|
228 if(NeedToPostponeMemGood()) //if handshake pending |
|
229 iMemAllocationsGoingDown->Stop(); //Stop till handhsake is complete. It will be made to continue from DoPostponedMemoryGood |
|
230 else |
|
231 iMemAllocationsGoingDown->Continue(); |
|
232 } |
|
233 } |
|
234 else//if aThreshold == EGL_PROF_TOTAL_MEMORY_USAGE_GT_NOK |
|
235 { |
|
236 TRACES1("FreeMemThresholdCrossedL : crossed low threshold %d", iLowThreshold); |
208 iMemAllocationsGrowing->Stop(); |
237 iMemAllocationsGrowing->Stop(); |
209 iMemAllocationsGoingDown->Continue(); |
238 iMemAllocationsGoingDown->Continue(); |
210 } |
239 StartFreeSomeRamL(iGoodThreshold, EGOomThresholdCrossed); |
211 else |
240 } |
212 { |
|
213 TRACES("FreeMemThresholdCrossedL : EGL_PROF_TOTAL_MEMORY_USAGE_LT_NOK"); |
|
214 iMemAllocationsGrowing->Continue(); |
|
215 iMemAllocationsGoingDown->Stop(); |
|
216 } |
|
217 #endif |
241 #endif |
218 |
|
219 StartFreeSomeRamL(iGoodThreshold); |
|
220 if (aThreshold == EGL_PROF_TOTAL_MEMORY_USAGE_LT_NOK) |
|
221 { |
|
222 TInt current = GetFreeMemory(); |
|
223 if(current >= iGoodThreshold && (!NeedToPostponeMemGood())) |
|
224 { |
|
225 TRACES("FreeMemThresholdCrossedL : calling MemoryGOOD"); |
|
226 iGOomActionList->MemoryGood(); |
|
227 } |
|
228 } |
|
229 } |
242 } |
230 |
243 |
231 void CMemoryMonitor::HandleFocusedWgChangeL(TInt aForegroundAppUid) |
244 void CMemoryMonitor::HandleFocusedWgChangeL(TInt aForegroundAppUid) |
232 { |
245 { |
233 FUNC_LOG; |
246 FUNC_LOG; |
242 |
255 |
243 // Refresh the low and good memory thresholds as they may have changed due to the new foreground application |
256 // Refresh the low and good memory thresholds as they may have changed due to the new foreground application |
244 RefreshThresholds(aForegroundAppUid); |
257 RefreshThresholds(aForegroundAppUid); |
245 // Not very elegant, now we poll on each window group change |
258 // Not very elegant, now we poll on each window group change |
246 // Should have better trigger e.g. from window server |
259 // Should have better trigger e.g. from window server |
247 #ifndef USE_ASYNCYH_NOTIFICATIONS |
260 StartFreeSomeRamL(iCurrentTarget, EGOomFocusChanged); |
248 TInt current = GetFreeMemory(); |
|
249 if (current < iLowThreshold) |
|
250 { |
|
251 StartFreeSomeRamL(iGoodThreshold); |
|
252 } |
|
253 else if(current >= iGoodThreshold) |
|
254 { |
|
255 iGOomActionList->MemoryGood(); |
|
256 } |
|
257 #endif |
|
258 } |
261 } |
259 |
262 |
260 void CMemoryMonitor::StartFreeSomeRamL(TInt aTargetFree, TInt aMaxPriority) // The maximum priority of action to run |
263 void CMemoryMonitor::StartFreeSomeRamL(TInt aTargetFree, TInt aMaxPriority, TGOomTrigger aTrigger) // The maximum priority of action to run |
261 { |
264 { |
262 FUNC_LOG; |
265 FUNC_LOG; |
263 |
266 |
264 TRACES2("MemoryMonitor::StartFreeSomeRamL: aTargetFree = %d, iCurrentTarget = %d", aTargetFree, iCurrentTarget); |
267 TRACES2("MemoryMonitor::StartFreeSomeRamL: aTargetFree = %d, iCurrentTarget = %d", aTargetFree, iCurrentTarget); |
265 |
268 |
297 iGOomActionList->BuildPluginActionListL(*iGOomWindowGroupList, *iConfig); |
300 iGOomActionList->BuildPluginActionListL(*iGOomWindowGroupList, *iConfig); |
298 |
301 |
299 //iGOomActionList->SetCurrentTarget(aTargetFree); |
302 //iGOomActionList->SetCurrentTarget(aTargetFree); |
300 iGOomActionList->SetCurrentTarget(iCurrentTarget); |
303 iGOomActionList->SetCurrentTarget(iCurrentTarget); |
301 |
304 |
|
305 iTrigger = aTrigger; |
302 // Run the memory freeing actions |
306 // Run the memory freeing actions |
303 iGOomActionList->FreeMemory(aMaxPriority); |
307 iGOomActionList->FreeMemory(aMaxPriority); |
|
308 |
304 } |
309 } |
305 |
310 |
306 void CMemoryMonitor::RunCloseAppActions(TInt aMaxPriority) |
311 void CMemoryMonitor::RunCloseAppActions(TInt aMaxPriority) |
307 { |
312 { |
308 FUNC_LOG; |
313 FUNC_LOG; |
315 // This function attempts to free enough RAM to leave the target amount of space free. |
320 // This function attempts to free enough RAM to leave the target amount of space free. |
316 // This function could take a substantial time to return as it may have to close a number |
321 // This function could take a substantial time to return as it may have to close a number |
317 // of applications, and each will be given a timeout of KAPPEXITTIMEOUT. |
322 // of applications, and each will be given a timeout of KAPPEXITTIMEOUT. |
318 // --------------------------------------------------------- |
323 // --------------------------------------------------------- |
319 // |
324 // |
320 void CMemoryMonitor::StartFreeSomeRamL(TInt aTargetFree) |
325 void CMemoryMonitor::StartFreeSomeRamL(TInt aTargetFree, TGOomTrigger aTrigger) |
321 { |
326 { |
322 FUNC_LOG; |
327 FUNC_LOG; |
323 |
328 |
324 StartFreeSomeRamL(aTargetFree, KGOomPriorityInfinate - 1); |
329 StartFreeSomeRamL(aTargetFree, KGOomPriorityInfinate - 1, aTrigger); |
325 } |
330 } |
326 |
331 |
327 void CMemoryMonitor::RequestFreeMemoryL(TInt aTargetFree, TBool aUseAbsolute) |
332 void CMemoryMonitor::RequestFreeMemoryL(TInt aTargetFree, TBool aUseAbsolute) |
328 { |
333 { |
329 FUNC_LOG; |
334 FUNC_LOG; |
330 |
335 |
331 StartFreeSomeRamL(aUseAbsolute?aTargetFree:(aTargetFree + iLowThreshold), KGOomPriorityInfinate - 1); |
336 StartFreeSomeRamL(aUseAbsolute?aTargetFree:(aTargetFree + iLowThreshold), KGOomPriorityInfinate - 1, EGOomRequestMemory); |
332 } |
337 } |
333 |
338 |
334 void CMemoryMonitor::FreeOptionalRamL(TInt aTargetFree, TInt aPluginId, TBool aUseAbsolute) // The ID of the plugin that will clear up the allocation, used to determine the priority of the allocation |
339 void CMemoryMonitor::FreeOptionalRamL(TInt aTargetFree, TInt aPluginId, TBool aUseAbsolute) // The ID of the plugin that will clear up the allocation, used to determine the priority of the allocation |
335 { |
340 { |
336 FUNC_LOG; |
341 FUNC_LOG; |
337 |
342 |
338 // Calculate the priority of the allocation (the priority of the plugin that will clear it up - 1) |
343 // Calculate the priority of the allocation (the priority of the plugin that will clear it up - 1) |
339 TInt priorityOfAllocation = iConfig->GetPluginConfig(aPluginId).CalculatePluginPriority(*iGOomWindowGroupList) - 1; |
344 TInt priorityOfAllocation = iConfig->GetPluginConfig(aPluginId).CalculatePluginPriority(*iGOomWindowGroupList) - 1; |
340 StartFreeSomeRamL(aUseAbsolute?aTargetFree:(aTargetFree + iGoodThreshold), priorityOfAllocation); |
345 StartFreeSomeRamL(aUseAbsolute?aTargetFree:(aTargetFree + iGoodThreshold), priorityOfAllocation, EGOomRequestMemory); |
341 } |
346 } |
342 |
347 |
343 // Does the EGL extension return the amount of memory in bits? |
348 // Does the EGL extension return the amount of memory in bits? |
344 // If yes, int is clearly not enough |
349 // If yes, int is clearly not enough |
345 // Note that this function reserves memory so it can fail if the "standard" memory |
350 // Note that this function reserves memory so it can fail if the "standard" memory |
467 } |
472 } |
468 |
473 |
469 void CMemoryMonitor::SetPriorityBusy(TInt aWgId) |
474 void CMemoryMonitor::SetPriorityBusy(TInt aWgId) |
470 { |
475 { |
471 FUNC_LOG; |
476 FUNC_LOG; |
472 |
|
473 TRACES2("Received SetPriorityBusy for appid = %x, wgid = %d", iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue), aWgId); |
477 TRACES2("Received SetPriorityBusy for appid = %x, wgid = %d", iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue), aWgId); |
474 iGOomWindowGroupList->SetPriorityBusy(aWgId); |
478 |
475 AppClosePriorityChanged(aWgId, RGOomMonitorSession::EGOomPriorityBusy); |
479 RArray<TInt> WgIdList; |
|
480 iGOomWindowGroupList->GetAllWgIdsMatchingAppId(aWgId, WgIdList); |
|
481 |
|
482 TInt i = WgIdList.Count(); |
|
483 while(i--) |
|
484 { |
|
485 iGOomWindowGroupList->SetPriorityBusy(WgIdList[i]); |
|
486 if(iGOomActionList->IsRunningKillAppActions()) //this may be too late as killing of apps has already begun, but we might still be able to save the app |
|
487 AppClosePriorityChanged(WgIdList[i], RGOomMonitorSession::EGOomPriorityBusy); |
|
488 } |
476 } |
489 } |
477 |
490 |
478 void CMemoryMonitor::SetPriorityNormal(TInt aWgId) |
491 void CMemoryMonitor::SetPriorityNormal(TInt aWgId) |
479 { |
492 { |
480 FUNC_LOG; |
493 FUNC_LOG; |
481 |
494 TRACES2("Received SetPriorityBusy for appid = %x, wgid = %d", iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue), aWgId); |
482 iGOomWindowGroupList->SetPriorityNormal(aWgId); |
495 |
483 AppClosePriorityChanged(aWgId, RGOomMonitorSession::EGOomPriorityNormal); |
496 RArray<TInt> WgIdList; |
|
497 iGOomWindowGroupList->GetAllWgIdsMatchingAppId(aWgId, WgIdList); |
|
498 |
|
499 TInt i = WgIdList.Count(); |
|
500 while(i--) |
|
501 { |
|
502 iGOomWindowGroupList->SetPriorityNormal(WgIdList[i]); |
|
503 if(iGOomActionList->IsRunningKillAppActions()) |
|
504 AppClosePriorityChanged(WgIdList[i], RGOomMonitorSession::EGOomPriorityNormal); |
|
505 } |
484 } |
506 } |
485 |
507 |
486 void CMemoryMonitor::SetPriorityHigh(TInt aWgId) |
508 void CMemoryMonitor::SetPriorityHigh(TInt aWgId) |
487 { |
509 { |
488 FUNC_LOG; |
510 FUNC_LOG; |
489 |
511 TRACES2("Received SetPriorityBusy for appid = %x, wgid = %d", iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue), aWgId); |
490 iGOomWindowGroupList->SetPriorityHigh(aWgId); |
512 |
491 AppClosePriorityChanged(aWgId, RGOomMonitorSession::EGOomPriorityHigh); |
513 RArray<TInt> WgIdList; |
|
514 iGOomWindowGroupList->GetAllWgIdsMatchingAppId(aWgId, WgIdList); |
|
515 |
|
516 TInt i = WgIdList.Count(); |
|
517 while(i--) |
|
518 { |
|
519 iGOomWindowGroupList->SetPriorityHigh(WgIdList[i]); |
|
520 if(iGOomActionList->IsRunningKillAppActions()) |
|
521 AppClosePriorityChanged(WgIdList[i], RGOomMonitorSession::EGOomPriorityHigh); |
|
522 } |
492 } |
523 } |
493 |
524 |
494 TInt CMemoryMonitor::GetFreeMemory() |
525 TInt CMemoryMonitor::GetFreeMemory() |
495 { |
526 { |
496 FUNC_LOG; |
527 FUNC_LOG; |
584 |
615 |
585 void CMemoryMonitor::DoPostponedMemoryGood() |
616 void CMemoryMonitor::DoPostponedMemoryGood() |
586 { |
617 { |
587 FUNC_LOG; |
618 FUNC_LOG; |
588 TInt current = GetFreeMemory(); |
619 TInt current = GetFreeMemory(); |
589 if(current >= iGoodThreshold && (!NeedToPostponeMemGood())) |
620 if(current >= iGoodThreshold) |
590 { |
621 { |
591 TRACES("DoPostponedMemoryGood calling MemoryGOOD"); |
622 if(!NeedToPostponeMemGood()) |
592 iGOomActionList->MemoryGood(); |
623 { |
593 } |
624 TRACES("DoPostponedMemoryGood calling MemoryGOOD"); |
|
625 iGOomActionList->MemoryGood(); |
|
626 } |
|
627 else |
|
628 { |
|
629 iMemAllocationsGoingDown->Continue(); |
|
630 } |
|
631 } |
|
632 else |
|
633 { |
|
634 iMemAllocationsGoingDown->Continue(); |
|
635 } |
594 } |
636 } |
595 |
|
596 |
637 |
597 void CMemoryMonitor::AppClosePriorityChanged(TInt aWgId, TInt aPriority) |
638 void CMemoryMonitor::AppClosePriorityChanged(TInt aWgId, TInt aPriority) |
598 { |
639 { |
599 FUNC_LOG; |
640 FUNC_LOG; |
600 CGOomCloseAppConfig* appCloseConfig = NULL; |
641 CGOomCloseAppConfig* appCloseConfig = NULL; |
613 break; |
654 break; |
614 default: |
655 default: |
615 appCloseConfig = iConfig->GetApplicationConfig(aWgId).GetAppCloseConfig(); |
656 appCloseConfig = iConfig->GetApplicationConfig(aWgId).GetAppCloseConfig(); |
616 TRACES("CMemoryMonitor::AppClosePriorityChanged NORMAL"); |
657 TRACES("CMemoryMonitor::AppClosePriorityChanged NORMAL"); |
617 } |
658 } |
618 |
659 |
|
660 if(!appCloseConfig) |
|
661 { |
|
662 appCloseConfig = iConfig->GetApplicationConfig(KGOomDefaultAppId).GetAppCloseConfig(); |
|
663 } |
|
664 |
619 if (appCloseConfig) |
665 if (appCloseConfig) |
620 { |
666 { |
621 TInt32 appId = iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue); |
667 TInt wgIndex=iGOomWindowGroupList->GetIndexFromWgId(aWgId); |
622 TInt wgIndex=iGOomWindowGroupList->GetIndexFromAppId(appId); |
|
623 |
|
624 TRACES2("CMemoryMonitor::AppClosePriorityChanged wgindex %d, appid %x", wgIndex, appId); |
|
625 |
668 |
626 if(wgIndex>=0) |
669 if(wgIndex>=0) |
627 { |
670 { |
628 TRACES2("CMemoryMonitor::AppClosePriorityChanged Setting Priority for app %x, wgid %d", appId, aWgId); |
671 TRACES2("CMemoryMonitor::AppClosePriorityChanged Setting Priority for app %x, wgid %d", iGOomWindowGroupList->AppIdfromWgId(aWgId, ETrue), aWgId); |
629 TUint priority = appCloseConfig->CalculateCloseAppPriority(*iGOomWindowGroupList, wgIndex); |
672 TUint priority = appCloseConfig->CalculateCloseAppPriority(*iGOomWindowGroupList, wgIndex); |
630 iGOomActionList->SetPriority(wgIndex, priority); |
673 iGOomActionList->SetPriority(aWgId, priority); |
631 } |
674 } |
632 else |
675 else |
633 { |
676 { |
634 TRACES1("CMemoryMonitor::AppClosePriorityChanged Could not find wgid %d in windogouplist", aWgId); |
677 TRACES1("CMemoryMonitor::AppClosePriorityChanged Could not find wgid %d in windogouplist", aWgId); |
635 } |
678 } |
642 |
685 |
643 CGOomWindowGroupList * CMemoryMonitor::GetWindowGroupList() const |
686 CGOomWindowGroupList * CMemoryMonitor::GetWindowGroupList() const |
644 { |
687 { |
645 return iGOomWindowGroupList; |
688 return iGOomWindowGroupList; |
646 } |
689 } |
|
690 |
|
691 TBool CMemoryMonitor::IsSafeToProcessNewRequest(TUint aClientId) |
|
692 { |
|
693 FUNC_LOG; |
|
694 if(iActiveClientId == aClientId) |
|
695 { |
|
696 TRACES1("Repeated Request from %x", aClientId); |
|
697 return EFalse; |
|
698 } |
|
699 |
|
700 TUint currrentPluginRun = iGOomActionList->CurrentPluginRun(); |
|
701 if(currrentPluginRun) |
|
702 { |
|
703 if(iConfig->GetApplicationConfig(aClientId).iSkipPluginId == currrentPluginRun) |
|
704 { |
|
705 TRACES2("Request from %x cannot be served now as plugin %x is running", aClientId, currrentPluginRun); |
|
706 return EFalse; |
|
707 } |
|
708 } |
|
709 |
|
710 TRACES1("Going to process new request %d",iPostponeMemGood); |
|
711 return ETrue; |
|
712 } |
|
713 |
|
714 void CMemoryMonitor::WaitAndSynchroniseMemoryState() //this will be called after freeing memory |
|
715 { |
|
716 FUNC_LOG; |
|
717 |
|
718 switch (iTrigger) |
|
719 { |
|
720 case EGOomThresholdCrossed: |
|
721 { |
|
722 //Call memory good if we are good. |
|
723 DoPostponedMemoryGood(); |
|
724 break; |
|
725 } |
|
726 case EGOomFocusChanged: |
|
727 case EGOomRequestMemory: |
|
728 { |
|
729 //start timer |
|
730 //cancel timer if end critical allocations request |
|
731 //end critical allocations when timer expires |
|
732 if ( iSynchTimer && //exists |
|
733 !iSynchTimer->IsActive() ) // keep it simple |
|
734 { |
|
735 iSynchTimer->After(KGoomWaitTimeToSynch); |
|
736 } |
|
737 break; |
|
738 } |
|
739 } |
|
740 } |
|
741 |
|
742 void CMemoryMonitor::SynchroniseMemoryState() |
|
743 { |
|
744 FUNC_LOG; |
|
745 TInt current = GetFreeMemory(); |
|
746 if(current >= iGoodThreshold) |
|
747 { |
|
748 if(!NeedToPostponeMemGood()) |
|
749 { |
|
750 TRACES("SynchroniseMemoryState calling MemoryGOOD"); |
|
751 iGOomActionList->MemoryGood(); |
|
752 } |
|
753 else |
|
754 { |
|
755 iMemAllocationsGoingDown->Continue(); |
|
756 } |
|
757 } |
|
758 else if(current < iLowThreshold) |
|
759 { |
|
760 iMemAllocationsGrowing->Stop(); |
|
761 iMemAllocationsGoingDown->Continue(); |
|
762 } |
|
763 else |
|
764 { |
|
765 iMemAllocationsGrowing->Continue(); |
|
766 iMemAllocationsGoingDown->Continue(); |
|
767 } |
|
768 } |
|
769 |
|
770 |
|
771 CGOomSynchTimer* CGOomSynchTimer::NewL(CMemoryMonitor& aMonitor) |
|
772 { |
|
773 CGOomSynchTimer* self = new (ELeave) CGOomSynchTimer(aMonitor); |
|
774 CleanupStack::PushL(self); |
|
775 self->ConstructL(); |
|
776 CleanupStack::Pop(self); |
|
777 return self; |
|
778 } |
|
779 |
|
780 CGOomSynchTimer::CGOomSynchTimer(CMemoryMonitor& aMonitor) : CTimer(EPriorityStandard), iMonitor(aMonitor) |
|
781 { |
|
782 CActiveScheduler::Add(this); |
|
783 } |
|
784 |
|
785 void CGOomSynchTimer::RunL() |
|
786 { |
|
787 FUNC_LOG; |
|
788 iMonitor.SynchroniseMemoryState(); |
|
789 } |
|
790 |
|
791 |