| 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 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 } | 547 } |
| 548 candidates.emplace_back(&app); | 548 candidates.emplace_back(&app); |
| 549 } | 549 } |
| 550 | 550 |
| 551 // Sort candidates according to priority. | 551 // Sort candidates according to priority. |
| 552 std::sort(candidates.begin(), candidates.end()); | 552 std::sort(candidates.begin(), candidates.end()); |
| 553 | 553 |
| 554 return candidates; | 554 return candidates; |
| 555 } | 555 } |
| 556 | 556 |
| 557 bool TabManagerDelegate::IsRecentlyKilledArcProcess( |
| 558 const std::string& process_name, |
| 559 const TimeTicks& now) { |
| 560 const auto it = recently_killed_arc_processes_.find(process_name); |
| 561 if (it == recently_killed_arc_processes_.end()) |
| 562 return false; |
| 563 return (now - it->second) <= GetArcRespawnKillDelay(); |
| 564 } |
| 565 |
| 557 bool TabManagerDelegate::KillArcProcess(const int nspid) { | 566 bool TabManagerDelegate::KillArcProcess(const int nspid) { |
| 558 auto* arc_service_manager = arc::ArcServiceManager::Get(); | 567 auto* arc_service_manager = arc::ArcServiceManager::Get(); |
| 559 if (!arc_service_manager) | 568 if (!arc_service_manager) |
| 560 return false; | 569 return false; |
| 561 | 570 |
| 562 auto* arc_process_instance = ARC_GET_INSTANCE_FOR_METHOD( | 571 auto* arc_process_instance = ARC_GET_INSTANCE_FOR_METHOD( |
| 563 arc_service_manager->arc_bridge_service()->process(), KillProcess); | 572 arc_service_manager->arc_bridge_service()->process(), KillProcess); |
| 564 if (!arc_process_instance) | 573 if (!arc_process_instance) |
| 565 return false; | 574 return false; |
| 566 | 575 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 583 void TabManagerDelegate::LowMemoryKillImpl( | 592 void TabManagerDelegate::LowMemoryKillImpl( |
| 584 const TabStatsList& tab_list, | 593 const TabStatsList& tab_list, |
| 585 const std::vector<arc::ArcProcess>& arc_processes) { | 594 const std::vector<arc::ArcProcess>& arc_processes) { |
| 586 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 595 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 587 VLOG(2) << "LowMemoryKillImpl"; | 596 VLOG(2) << "LowMemoryKillImpl"; |
| 588 | 597 |
| 589 const std::vector<TabManagerDelegate::Candidate> candidates = | 598 const std::vector<TabManagerDelegate::Candidate> candidates = |
| 590 GetSortedCandidates(tab_list, arc_processes); | 599 GetSortedCandidates(tab_list, arc_processes); |
| 591 | 600 |
| 592 int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB(); | 601 int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB(); |
| 602 const TimeTicks now = TimeTicks::Now(); |
| 593 | 603 |
| 594 // Kill processes until the estimated amount of freed memory is sufficient to | 604 // Kill processes until the estimated amount of freed memory is sufficient to |
| 595 // bring the system memory back to a normal level. | 605 // bring the system memory back to a normal level. |
| 596 // The list is sorted by descending importance, so we go through the list | 606 // The list is sorted by descending importance, so we go through the list |
| 597 // backwards. | 607 // backwards. |
| 598 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { | 608 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { |
| 599 MEMORY_LOG(ERROR) << "Target memory to free: " << target_memory_to_free_kb | 609 MEMORY_LOG(ERROR) << "Target memory to free: " << target_memory_to_free_kb |
| 600 << " KB"; | 610 << " KB"; |
| 601 if (target_memory_to_free_kb <= 0) | 611 if (target_memory_to_free_kb <= 0) |
| 602 break; | 612 break; |
| 603 // Never kill selected tab or Android foreground app, regardless whether | 613 // Never kill selected tab or Android foreground app, regardless whether |
| 604 // they're in the active window. Since the user experience would be bad. | 614 // they're in the active window. Since the user experience would be bad. |
| 605 ProcessType process_type = it->process_type(); | 615 ProcessType process_type = it->process_type(); |
| 606 if (process_type == ProcessType::VISIBLE_APP || | 616 if (process_type == ProcessType::VISIBLE_APP || |
| 607 process_type == ProcessType::FOCUSED_APP || | 617 process_type == ProcessType::FOCUSED_APP || |
| 608 process_type == ProcessType::FOCUSED_TAB) { | 618 process_type == ProcessType::FOCUSED_TAB) { |
| 609 MEMORY_LOG(ERROR) << "Skipped killing " << *it; | 619 MEMORY_LOG(ERROR) << "Skipped killing " << *it; |
| 610 continue; | 620 continue; |
| 611 } | 621 } |
| 612 if (it->app()) { | 622 if (it->app()) { |
| 623 if (IsRecentlyKilledArcProcess(it->app()->process_name(), now)) { |
| 624 MEMORY_LOG(ERROR) << "Avoided killing " << *it << " too often"; |
| 625 continue; |
| 626 } |
| 613 int estimated_memory_freed_kb = | 627 int estimated_memory_freed_kb = |
| 614 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); | 628 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); |
| 615 if (KillArcProcess(it->app()->nspid())) { | 629 if (KillArcProcess(it->app()->nspid())) { |
| 630 recently_killed_arc_processes_[it->app()->process_name()] = now; |
| 616 target_memory_to_free_kb -= estimated_memory_freed_kb; | 631 target_memory_to_free_kb -= estimated_memory_freed_kb; |
| 617 MemoryKillsMonitor::LogLowMemoryKill("APP", estimated_memory_freed_kb); | 632 MemoryKillsMonitor::LogLowMemoryKill("APP", estimated_memory_freed_kb); |
| 618 MEMORY_LOG(ERROR) << "Killed " << *it << ", estimated " | 633 MEMORY_LOG(ERROR) << "Killed " << *it << ", estimated " |
| 619 << estimated_memory_freed_kb << " KB freed"; | 634 << estimated_memory_freed_kb << " KB freed"; |
| 620 } else { | 635 } else { |
| 621 MEMORY_LOG(ERROR) << "Failed to kill " << *it; | 636 MEMORY_LOG(ERROR) << "Failed to kill " << *it; |
| 622 } | 637 } |
| 623 } else { | 638 } else { |
| 624 int64_t tab_id = it->tab()->tab_contents_id; | 639 int64_t tab_id = it->tab()->tab_contents_id; |
| 625 // The estimation is problematic since multiple tabs may share the same | 640 // The estimation is problematic since multiple tabs may share the same |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 } | 753 } |
| 739 priority += priority_increment; | 754 priority += priority_increment; |
| 740 } | 755 } |
| 741 | 756 |
| 742 if (oom_scores_to_change.size()) | 757 if (oom_scores_to_change.size()) |
| 743 GetDebugDaemonClient()->SetOomScoreAdj( | 758 GetDebugDaemonClient()->SetOomScoreAdj( |
| 744 oom_scores_to_change, base::Bind(&OnSetOomScoreAdj)); | 759 oom_scores_to_change, base::Bind(&OnSetOomScoreAdj)); |
| 745 } | 760 } |
| 746 | 761 |
| 747 } // namespace memory | 762 } // namespace memory |
| OLD | NEW |