| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/memory/tab_manager_delegate_chromeos.h" | 5 #include "chrome/browser/memory/tab_manager_delegate_chromeos.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <map> | 10 #include <map> |
| 11 #include <string> | |
| 12 #include <vector> | 11 #include <vector> |
| 13 | 12 |
| 14 #include "ash/shell.h" | 13 #include "ash/shell.h" |
| 15 #include "base/bind.h" | 14 #include "base/bind.h" |
| 16 #include "base/command_line.h" | 15 #include "base/command_line.h" |
| 17 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
| 18 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
| 19 #include "base/memory/memory_pressure_monitor_chromeos.h" | 18 #include "base/memory/memory_pressure_monitor_chromeos.h" |
| 20 #include "base/metrics/histogram_macros.h" | 19 #include "base/metrics/histogram_macros.h" |
| 21 #include "base/process/process_handle.h" // kNullProcessHandle. | 20 #include "base/process/process_handle.h" // kNullProcessHandle. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 44 #include "content/public/browser/notification_service.h" | 43 #include "content/public/browser/notification_service.h" |
| 45 #include "content/public/browser/notification_types.h" | 44 #include "content/public/browser/notification_types.h" |
| 46 #include "content/public/browser/render_process_host.h" | 45 #include "content/public/browser/render_process_host.h" |
| 47 #include "content/public/browser/render_widget_host.h" | 46 #include "content/public/browser/render_widget_host.h" |
| 48 #include "content/public/browser/zygote_host_linux.h" | 47 #include "content/public/browser/zygote_host_linux.h" |
| 49 #include "ui/aura/window.h" | 48 #include "ui/aura/window.h" |
| 50 #include "ui/wm/public/activation_client.h" | 49 #include "ui/wm/public/activation_client.h" |
| 51 | 50 |
| 52 using base::ProcessHandle; | 51 using base::ProcessHandle; |
| 53 using base::TimeDelta; | 52 using base::TimeDelta; |
| 53 using base::TimeTicks; |
| 54 using content::BrowserThread; | 54 using content::BrowserThread; |
| 55 | 55 |
| 56 namespace memory { | 56 namespace memory { |
| 57 namespace { | 57 namespace { |
| 58 | 58 |
| 59 const char kExoShellSurfaceWindowName[] = "ExoShellSurface"; | 59 const char kExoShellSurfaceWindowName[] = "ExoShellSurface"; |
| 60 const char kArcProcessNamePrefix[] = "org.chromium.arc."; | 60 const char kArcProcessNamePrefix[] = "org.chromium.arc."; |
| 61 | 61 |
| 62 // When switching to a new tab the tab's renderer's OOM score needs to be | 62 // When switching to a new tab the tab's renderer's OOM score needs to be |
| 63 // updated to reflect its front-most status and protect it from discard. | 63 // updated to reflect its front-most status and protect it from discard. |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 } | 545 } |
| 546 candidates.emplace_back(&app); | 546 candidates.emplace_back(&app); |
| 547 } | 547 } |
| 548 | 548 |
| 549 // Sort candidates according to priority. | 549 // Sort candidates according to priority. |
| 550 std::sort(candidates.begin(), candidates.end()); | 550 std::sort(candidates.begin(), candidates.end()); |
| 551 | 551 |
| 552 return candidates; | 552 return candidates; |
| 553 } | 553 } |
| 554 | 554 |
| 555 bool TabManagerDelegate::IsRecentlyKilledArcProcess( |
| 556 const std::string& process_name, |
| 557 const TimeTicks& now) { |
| 558 const auto it = recently_killed_arc_processes_.find(process_name); |
| 559 if (it == recently_killed_arc_processes_.end()) |
| 560 return false; |
| 561 return (now - it->second) <= GetArcRespawnKillDelay(); |
| 562 } |
| 563 |
| 555 bool TabManagerDelegate::KillArcProcess(const int nspid) { | 564 bool TabManagerDelegate::KillArcProcess(const int nspid) { |
| 556 auto* arc_service_manager = arc::ArcServiceManager::Get(); | 565 auto* arc_service_manager = arc::ArcServiceManager::Get(); |
| 557 if (!arc_service_manager) | 566 if (!arc_service_manager) |
| 558 return false; | 567 return false; |
| 559 | 568 |
| 560 auto* arc_process_instance = ARC_GET_INSTANCE_FOR_METHOD( | 569 auto* arc_process_instance = ARC_GET_INSTANCE_FOR_METHOD( |
| 561 arc_service_manager->arc_bridge_service()->process(), KillProcess); | 570 arc_service_manager->arc_bridge_service()->process(), KillProcess); |
| 562 if (!arc_process_instance) | 571 if (!arc_process_instance) |
| 563 return false; | 572 return false; |
| 564 | 573 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 581 void TabManagerDelegate::LowMemoryKillImpl( | 590 void TabManagerDelegate::LowMemoryKillImpl( |
| 582 const TabStatsList& tab_list, | 591 const TabStatsList& tab_list, |
| 583 const std::vector<arc::ArcProcess>& arc_processes) { | 592 const std::vector<arc::ArcProcess>& arc_processes) { |
| 584 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 593 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 585 VLOG(2) << "LowMemoryKillImpl"; | 594 VLOG(2) << "LowMemoryKillImpl"; |
| 586 | 595 |
| 587 const std::vector<TabManagerDelegate::Candidate> candidates = | 596 const std::vector<TabManagerDelegate::Candidate> candidates = |
| 588 GetSortedCandidates(tab_list, arc_processes); | 597 GetSortedCandidates(tab_list, arc_processes); |
| 589 | 598 |
| 590 int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB(); | 599 int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB(); |
| 600 const TimeTicks now = TimeTicks::Now(); |
| 591 | 601 |
| 592 // Kill processes until the estimated amount of freed memory is sufficient to | 602 // Kill processes until the estimated amount of freed memory is sufficient to |
| 593 // bring the system memory back to a normal level. | 603 // bring the system memory back to a normal level. |
| 594 // The list is sorted by descending importance, so we go through the list | 604 // The list is sorted by descending importance, so we go through the list |
| 595 // backwards. | 605 // backwards. |
| 596 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { | 606 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { |
| 597 MEMORY_LOG(ERROR) << "Target memory to free: " << target_memory_to_free_kb | 607 MEMORY_LOG(ERROR) << "Target memory to free: " << target_memory_to_free_kb |
| 598 << " KB"; | 608 << " KB"; |
| 599 if (target_memory_to_free_kb <= 0) | 609 if (target_memory_to_free_kb <= 0) |
| 600 break; | 610 break; |
| 601 // Never kill selected tab or Android foreground app, regardless whether | 611 // Never kill selected tab or Android foreground app, regardless whether |
| 602 // they're in the active window. Since the user experience would be bad. | 612 // they're in the active window. Since the user experience would be bad. |
| 603 ProcessType process_type = it->process_type(); | 613 ProcessType process_type = it->process_type(); |
| 604 if (process_type == ProcessType::VISIBLE_APP || | 614 if (process_type == ProcessType::VISIBLE_APP || |
| 605 process_type == ProcessType::FOCUSED_APP || | 615 process_type == ProcessType::FOCUSED_APP || |
| 606 process_type == ProcessType::FOCUSED_TAB) { | 616 process_type == ProcessType::FOCUSED_TAB) { |
| 607 MEMORY_LOG(ERROR) << "Skipped killing " << *it; | 617 MEMORY_LOG(ERROR) << "Skipped killing " << *it; |
| 608 continue; | 618 continue; |
| 609 } | 619 } |
| 610 if (it->app()) { | 620 if (it->app()) { |
| 621 if (IsRecentlyKilledArcProcess(it->app()->process_name(), now)) { |
| 622 MEMORY_LOG(ERROR) << "Avoided killing " << *it << " too often"; |
| 623 continue; |
| 624 } |
| 611 int estimated_memory_freed_kb = | 625 int estimated_memory_freed_kb = |
| 612 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); | 626 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); |
| 613 if (KillArcProcess(it->app()->nspid())) { | 627 if (KillArcProcess(it->app()->nspid())) { |
| 628 recently_killed_arc_processes_[it->app()->process_name()] = now; |
| 614 target_memory_to_free_kb -= estimated_memory_freed_kb; | 629 target_memory_to_free_kb -= estimated_memory_freed_kb; |
| 615 MemoryKillsMonitor::LogLowMemoryKill("APP", estimated_memory_freed_kb); | 630 MemoryKillsMonitor::LogLowMemoryKill("APP", estimated_memory_freed_kb); |
| 616 MEMORY_LOG(ERROR) << "Killed " << *it << ", estimated " | 631 MEMORY_LOG(ERROR) << "Killed " << *it << ", estimated " |
| 617 << estimated_memory_freed_kb << " KB freed"; | 632 << estimated_memory_freed_kb << " KB freed"; |
| 618 } else { | 633 } else { |
| 619 MEMORY_LOG(ERROR) << "Failed to kill " << *it; | 634 MEMORY_LOG(ERROR) << "Failed to kill " << *it; |
| 620 } | 635 } |
| 621 } else { | 636 } else { |
| 622 int64_t tab_id = it->tab()->tab_contents_id; | 637 int64_t tab_id = it->tab()->tab_contents_id; |
| 623 // The estimation is problematic since multiple tabs may share the same | 638 // The estimation is problematic since multiple tabs may share the same |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 } | 751 } |
| 737 priority += priority_increment; | 752 priority += priority_increment; |
| 738 } | 753 } |
| 739 | 754 |
| 740 if (oom_scores_to_change.size()) | 755 if (oom_scores_to_change.size()) |
| 741 GetDebugDaemonClient()->SetOomScoreAdj( | 756 GetDebugDaemonClient()->SetOomScoreAdj( |
| 742 oom_scores_to_change, base::Bind(&OnSetOomScoreAdj)); | 757 oom_scores_to_change, base::Bind(&OnSetOomScoreAdj)); |
| 743 } | 758 } |
| 744 | 759 |
| 745 } // namespace memory | 760 } // namespace memory |
| OLD | NEW |