1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_POWER_PROCESS_POWER_COLLECTOR_H_
6#define CHROME_BROWSER_POWER_PROCESS_POWER_COLLECTOR_H_
7
8#include <map>
9
10#include "base/memory/linked_ptr.h"
11#include "base/process/process_handle.h"
12#include "base/process/process_metrics.h"
13#include "base/timer/timer.h"
14#include "components/power/origin_power_map_factory.h"
15#include "url/gurl.h"
16
17#if defined(OS_CHROMEOS)
18#include "chromeos/dbus/power_manager_client.h"
19#endif
20
21class Profile;
22
23namespace content {
24class RenderProcessHost;
25}
26
27#if defined(OS_CHROMEOS)
28namespace power_manager {
29class PowerSupplyProperties;
30}
31#endif
32
33// Manages regular updates of the profile power consumption.
34class ProcessPowerCollector
35#if defined(OS_CHROMEOS)
36    : public chromeos::PowerManagerClient::Observer
37#endif
38      {
39 public:
40  class PerProcessData {
41   public:
42    PerProcessData(scoped_ptr<base::ProcessMetrics> metrics,
43                   const GURL& origin,
44                   Profile* profile);
45    PerProcessData();
46    ~PerProcessData();
47
48    base::ProcessMetrics* metrics() const { return metrics_.get(); }
49    Profile* profile() const { return profile_; }
50    GURL last_origin() const { return last_origin_; }
51    int last_cpu_percent() const { return last_cpu_percent_; }
52    bool seen_this_cycle() const { return seen_this_cycle_; }
53    void set_last_cpu_percent(double new_cpu) { last_cpu_percent_ = new_cpu; }
54    void set_seen_this_cycle(bool seen) { seen_this_cycle_ = seen; }
55
56   private:
57    // |metrics_| holds the ProcessMetrics information for the given process.
58    scoped_ptr<base::ProcessMetrics> metrics_;
59
60    // |profile| is the profile that is visiting the |last_origin_|.
61    // It is not owned by PerProcessData.
62    Profile* profile_;
63
64    // |last_origin_| is the last origin visited by the process.
65    GURL last_origin_;
66
67    // |last_cpu_percent_| is the proportion of the CPU used since the last
68    // query.
69    double last_cpu_percent_;
70
71    // |seen_this_cycle| represents if the process still exists in this cycle.
72    // If it doesn't, we erase the PerProcessData.
73    bool seen_this_cycle_;
74
75    DISALLOW_COPY_AND_ASSIGN(PerProcessData);
76  };
77
78  // A map from all process handles to a metric.
79  typedef std::map<base::ProcessHandle, linked_ptr<PerProcessData> >
80      ProcessMetricsMap;
81  // A callback used to define mock CPU usage for testing.
82  typedef base::Callback<double(base::ProcessHandle)> CpuUsageCallback;
83
84  // On Chrome OS, can only be initialized after the DBusThreadManager has been
85  // initialized.
86  ProcessPowerCollector();
87  // On Chrome OS, can only be destroyed before DBusThreadManager is.
88  virtual ~ProcessPowerCollector();
89
90  void set_cpu_usage_callback_for_testing(const CpuUsageCallback& callback) {
91    cpu_usage_callback_ = callback;
92  }
93
94  ProcessMetricsMap* metrics_map_for_testing() { return &metrics_map_; }
95
96#if defined(OS_CHROMEOS)
97  // PowerManagerClient::Observer implementation:
98  virtual void PowerChanged(
99      const power_manager::PowerSupplyProperties& prop) OVERRIDE;
100#endif
101
102  // Begin periodically updating the power consumption numbers by profile.
103  void Initialize();
104
105  // Calls UpdatePowerConsumption() and returns the total CPU percent.
106  double UpdatePowerConsumptionForTesting();
107
108 private:
109  // Starts the timer for updating the power consumption.
110  void StartTimer();
111
112  // Calls SynchronizerProcesses() and RecordCpuUsageByOrigin() to update the
113  // |metrics_map_| and attribute power consumption. Invoked by |timer_| and as
114  // a helper method for UpdatePowerConsumptionForTesting().
115  double UpdatePowerConsumption();
116
117  // Calls UpdatePowerConsumption(). Invoked by |timer_|.
118  void HandleUpdateTimeout();
119
120  // Synchronizes the currently active processes to the |metrics_map_| and
121  // returns the total amount of cpu usage in the cycle.
122  double SynchronizeProcesses();
123
124  // Attributes the power usage to the profiles and origins using the
125  // information from SynchronizeProcesses() given a total amount
126  // of CPU used in this cycle, |total_cpu_percent|.
127  void RecordCpuUsageByOrigin(double total_cpu_percent);
128
129  // Adds the information from a given RenderProcessHost to the |metrics_map_|
130  // for a given origin. Called by SynchronizeProcesses().
131  void UpdateProcessInMap(const content::RenderProcessHost* render_process,
132                          const GURL& origin);
133
134  ProcessMetricsMap metrics_map_;
135  base::RepeatingTimer<ProcessPowerCollector> timer_;
136
137  // Callback to use to get CPU usage if set.
138  CpuUsageCallback cpu_usage_callback_;
139
140  // The factor to scale the CPU usage by.
141  double scale_factor_;
142
143  DISALLOW_COPY_AND_ASSIGN(ProcessPowerCollector);
144};
145
146#endif  // CHROME_BROWSER_POWER_PROCESS_POWER_COLLECTOR_H_
147