memory_details_android.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright (c) 2012 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. #include "chrome/browser/memory_details.h"
  5. #include <memory>
  6. #include <set>
  7. #include <string>
  8. #include <vector>
  9. #include "base/bind.h"
  10. #include "base/process/process_iterator.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "base/threading/scoped_blocking_call.h"
  13. #include "chrome/common/chrome_constants.h"
  14. #include "chrome/grit/chromium_strings.h"
  15. #include "content/public/browser/browser_task_traits.h"
  16. #include "content/public/browser/browser_thread.h"
  17. #include "content/public/common/process_type.h"
  18. #include "ui/base/l10n/l10n_util.h"
  19. using base::ProcessEntry;
  20. using base::ProcessId;
  21. namespace {
  22. // A helper for |CollectProcessData()| to include the chrome sandboxed
  23. // processes in android which are not running as a child of the browser
  24. // process.
  25. void AddNonChildChromeProcesses(
  26. std::vector<ProcessMemoryInformation>* processes) {
  27. base::ProcessIterator process_iter(NULL);
  28. while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
  29. const std::vector<std::string>& cmd_args = process_entry->cmd_line_args();
  30. if (cmd_args.empty() ||
  31. cmd_args[0].find(chrome::kHelperProcessExecutableName) ==
  32. std::string::npos) {
  33. continue;
  34. }
  35. ProcessMemoryInformation info;
  36. info.pid = process_entry->pid();
  37. processes->push_back(info);
  38. }
  39. }
  40. // For each of the pids, collect memory information about that process
  41. // and append a record to |out|.
  42. void GetProcessDataMemoryInformation(
  43. const std::set<ProcessId>& pids, ProcessData* out) {
  44. for (std::set<ProcessId>::const_iterator i = pids.begin(); i != pids.end();
  45. ++i) {
  46. ProcessMemoryInformation pmi;
  47. pmi.pid = *i;
  48. pmi.num_processes = 1;
  49. base::ProcessId current_pid = base::GetCurrentProcId();
  50. if (pmi.pid == current_pid)
  51. pmi.process_type = content::PROCESS_TYPE_BROWSER;
  52. else
  53. pmi.process_type = content::PROCESS_TYPE_UNKNOWN;
  54. std::unique_ptr<base::ProcessMetrics> metrics(
  55. base::ProcessMetrics::CreateProcessMetrics(*i));
  56. // TODO(ssid): Reading "/proc/fd" only works for current process. For child
  57. // processes, the values need to be computed by the process itself.
  58. if (pmi.pid == current_pid) {
  59. pmi.num_open_fds = metrics->GetOpenFdCount();
  60. pmi.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
  61. }
  62. out->processes.push_back(pmi);
  63. }
  64. }
  65. // Find all children of the given process.
  66. void GetAllChildren(const std::vector<ProcessEntry>& processes,
  67. const std::set<ProcessId>& roots,
  68. std::set<ProcessId>* out) {
  69. *out = roots;
  70. std::set<ProcessId> wavefront;
  71. for (std::set<ProcessId>::const_iterator i = roots.begin(); i != roots.end();
  72. ++i) {
  73. wavefront.insert(*i);
  74. }
  75. while (wavefront.size()) {
  76. std::set<ProcessId> next_wavefront;
  77. for (std::vector<ProcessEntry>::const_iterator i = processes.begin();
  78. i != processes.end(); ++i) {
  79. if (wavefront.count(i->parent_pid())) {
  80. out->insert(i->pid());
  81. next_wavefront.insert(i->pid());
  82. }
  83. }
  84. wavefront.clear();
  85. wavefront.swap(next_wavefront);
  86. }
  87. }
  88. } // namespace
  89. MemoryDetails::MemoryDetails() {
  90. }
  91. ProcessData* MemoryDetails::ChromeBrowser() {
  92. return &process_data_[0];
  93. }
  94. void MemoryDetails::CollectProcessData(
  95. const std::vector<ProcessMemoryInformation>& chrome_processes) {
  96. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  97. base::BlockingType::WILL_BLOCK);
  98. std::vector<ProcessMemoryInformation> all_processes(chrome_processes);
  99. AddNonChildChromeProcesses(&all_processes);
  100. std::vector<ProcessEntry> processes;
  101. base::ProcessIterator process_iter(NULL);
  102. while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
  103. processes.push_back(*process_entry);
  104. }
  105. std::set<ProcessId> roots;
  106. roots.insert(base::GetCurrentProcId());
  107. for (std::vector<ProcessMemoryInformation>::const_iterator
  108. i = all_processes.begin(); i != all_processes.end(); ++i) {
  109. roots.insert(i->pid);
  110. }
  111. std::set<ProcessId> current_browser_processes;
  112. GetAllChildren(processes, roots, &current_browser_processes);
  113. ProcessData current_browser;
  114. GetProcessDataMemoryInformation(current_browser_processes, &current_browser);
  115. current_browser.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
  116. current_browser.process_name =
  117. base::ASCIIToUTF16(chrome::kBrowserProcessExecutableName);
  118. process_data_.push_back(current_browser);
  119. // Finally return to the browser thread.
  120. content::GetUIThreadTaskRunner({})->PostTask(
  121. FROM_HERE,
  122. base::BindOnce(&MemoryDetails::CollectChildInfoOnUIThread, this));
  123. }