| // Copyright 2016 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "chrome/browser/memory/memory_kills_monitor.h" | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/metrics/histogram_functions.h" | 
 | #include "base/no_destructor.h" | 
 | #include "base/threading/platform_thread.h" | 
 | #include "chrome/browser/browser_process.h" | 
 | #include "chrome/browser/memory/memory_kills_histogram.h" | 
 | #include "chrome/browser/memory/oom_kills_monitor.h" | 
 | #include "content/public/browser/browser_thread.h" | 
 |  | 
 | namespace memory { | 
 |  | 
 | namespace { | 
 |  | 
 | MemoryKillsMonitor& GetMemoryKillsMonitorInstance() { | 
 |   static base::NoDestructor<MemoryKillsMonitor> instance; | 
 |   return *instance; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | MemoryKillsMonitor::MemoryKillsMonitor() = default; | 
 |  | 
 | MemoryKillsMonitor::~MemoryKillsMonitor() { | 
 |   NOTREACHED(); | 
 | } | 
 |  | 
 | // static | 
 | void MemoryKillsMonitor::Initialize() { | 
 |   VLOG(2) << "MemoryKillsMonitor::Initializing on " | 
 |           << base::PlatformThread::CurrentId(); | 
 |  | 
 |   DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 
 |  | 
 |   auto* login_state = ash::LoginState::Get(); | 
 |   if (login_state) | 
 |     login_state->AddObserver(&GetMemoryKillsMonitorInstance()); | 
 |   else | 
 |     LOG(ERROR) << "LoginState is not initialized"; | 
 | } | 
 |  | 
 | // static | 
 | void MemoryKillsMonitor::LogLowMemoryKill(const std::string& type, | 
 |                                           int estimated_freed_kb) { | 
 |   DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 
 |  | 
 |   GetMemoryKillsMonitorInstance().LogLowMemoryKillImpl(type, | 
 |                                                        estimated_freed_kb); | 
 | } | 
 |  | 
 | void MemoryKillsMonitor::LoggedInStateChanged() { | 
 |   VLOG(2) << "LoggedInStateChanged"; | 
 |   auto* login_state = ash::LoginState::Get(); | 
 |   if (login_state) { | 
 |     // Note: LoginState never fires a notification when logged out. | 
 |     if (login_state->IsUserLoggedIn()) { | 
 |       VLOG(2) << "User logged in"; | 
 |       StartMonitoring(); | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void MemoryKillsMonitor::StartMonitoring() { | 
 |   VLOG(2) << "Starting monitor from thread " | 
 |           << base::PlatformThread::CurrentId(); | 
 |  | 
 |   DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 
 |  | 
 |   if (monitoring_started_.IsSet()) { | 
 |     LOG(WARNING) << "Monitoring has been started"; | 
 |     return; | 
 |   } | 
 |  | 
 |   // Insert a zero kill record at the begining of each login session for easy | 
 |   // comparison to those with non-zero kill sessions. | 
 |   base::UmaHistogramCustomCounts("Memory.LowMemoryKiller.Count", 0, 1, 1000, | 
 |                                  1001); | 
 |  | 
 |   monitoring_started_.Set(); | 
 |  | 
 |   // Starts the OOM kills monitor. | 
 |   if (g_browser_process != nullptr && | 
 |       g_browser_process->local_state() != nullptr) { | 
 |     OOMKillsMonitor::GetInstance().Initialize(g_browser_process->local_state()); | 
 |   } | 
 | } | 
 |  | 
 | void MemoryKillsMonitor::LogLowMemoryKillImpl(const std::string& type, | 
 |                                               int estimated_freed_kb) { | 
 |   DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 
 |  | 
 |   if (!monitoring_started_.IsSet()) { | 
 |     LOG(WARNING) << "LogLowMemoryKill before monitoring started, " | 
 |                     "skipped this log."; | 
 |     return; | 
 |   } | 
 |  | 
 |   VLOG(1) << "LOW_MEMORY_KILL_" << type; | 
 |  | 
 |   ++low_memory_kills_count_; | 
 |   base::UmaHistogramCustomCounts("Memory.LowMemoryKiller.Count", | 
 |                                  low_memory_kills_count_, 1, 1000, 1001); | 
 |  | 
 |   base::UmaHistogramMemoryKB("Memory.LowMemoryKiller.FreedSize", | 
 |                              estimated_freed_kb); | 
 | } | 
 |  | 
 | MemoryKillsMonitor* MemoryKillsMonitor::GetForTesting() { | 
 |   return &GetMemoryKillsMonitorInstance(); | 
 | } | 
 |  | 
 | }  // namespace memory |