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 
5 #include "chrome/browser/chromeos/policy/status_collector/device_status_collector.h"
6 
7 #include <sys/types.h>
8 #include <unistd.h>
9 
10 #include <stddef.h>
11 #include <stdint.h>
12 
13 #include <algorithm>
14 #include <cstdio>
15 #include <limits>
16 #include <set>
17 #include <sstream>
18 #include <utility>
19 
20 #include "base/bind.h"
21 #include "base/callback_helpers.h"
22 #include "base/feature_list.h"
23 #include "base/files/file_enumerator.h"
24 #include "base/files/file_util.h"
25 #include "base/format_macros.h"
26 #include "base/logging.h"
27 #include "base/memory/ref_counted.h"
28 #include "base/memory/scoped_refptr.h"
29 #include "base/optional.h"
30 #include "base/posix/eintr_wrapper.h"
31 #include "base/sequenced_task_runner.h"
32 #include "base/stl_util.h"
33 #include "base/strings/string_number_conversions.h"
34 #include "base/strings/string_util.h"
35 #include "base/strings/stringprintf.h"
36 #include "base/strings/utf_string_conversions.h"
37 #include "base/system/sys_info.h"
38 #include "base/task/post_task.h"
39 #include "base/task/task_traits.h"
40 #include "base/task/thread_pool.h"
41 #include "base/threading/sequenced_task_runner_handle.h"
42 #include "base/values.h"
43 #include "base/version.h"
44 #include "chrome/browser/browser_process.h"
45 #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager.h"
46 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
47 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
48 #include "chrome/browser/chromeos/crostini/crostini_reporting_util.h"
49 #include "chrome/browser/chromeos/crostini/crostini_util.h"
50 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
51 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
52 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
53 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
54 #include "chrome/browser/chromeos/policy/device_local_account.h"
55 #include "chrome/browser/chromeos/policy/status_collector/enterprise_activity_storage.h"
56 #include "chrome/browser/chromeos/policy/status_collector/interval_map.h"
57 #include "chrome/browser/chromeos/policy/status_collector/status_collector_state.h"
58 #include "chrome/browser/chromeos/profiles/profile_helper.h"
59 #include "chrome/browser/chromeos/settings/cros_settings.h"
60 #include "chrome/browser/crash_upload_list/crash_upload_list.h"
61 #include "chrome/browser/policy/profile_policy_connector.h"
62 #include "chrome/browser/profiles/profile_manager.h"
63 #include "chrome/common/channel_info.h"
64 #include "chrome/common/chrome_features.h"
65 #include "chrome/common/pref_names.h"
66 #include "chromeos/audio/cras_audio_handler.h"
67 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
68 #include "chromeos/dbus/cryptohome/rpc.pb.h"
69 #include "chromeos/dbus/cryptohome/tpm_util.h"
70 #include "chromeos/dbus/dbus_thread_manager.h"
71 #include "chromeos/dbus/power_manager/idle.pb.h"
72 #include "chromeos/dbus/update_engine_client.h"
73 #include "chromeos/dbus/util/version_loader.h"
74 #include "chromeos/disks/disk_mount_manager.h"
75 #include "chromeos/login/login_state/login_state.h"
76 #include "chromeos/network/device_state.h"
77 #include "chromeos/network/network_handler.h"
78 #include "chromeos/network/network_state.h"
79 #include "chromeos/network/network_state_handler.h"
80 #include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
81 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
82 #include "chromeos/settings/cros_settings_names.h"
83 #include "chromeos/settings/timezone_settings.h"
84 #include "chromeos/system/statistics_provider.h"
85 #include "components/arc/arc_service_manager.h"
86 #include "components/arc/mojom/enterprise_reporting.mojom.h"
87 #include "components/arc/session/arc_bridge_service.h"
88 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
89 #include "components/policy/core/common/cloud/cloud_policy_util.h"
90 #include "components/policy/proto/device_management_backend.pb.h"
91 #include "components/prefs/pref_change_registrar.h"
92 #include "components/prefs/pref_registry_simple.h"
93 #include "components/prefs/pref_service.h"
94 #include "components/user_manager/user.h"
95 #include "components/user_manager/user_manager.h"
96 #include "components/user_manager/user_type.h"
97 #include "components/version_info/version_info.h"
98 #include "content/public/browser/browser_thread.h"
99 #include "content/public/browser/gpu_data_manager.h"
100 #include "extensions/browser/extension_registry.h"
101 #include "extensions/common/extension.h"
102 #include "gpu/config/gpu_info.h"
103 #include "gpu/ipc/common/memory_stats.h"
104 #include "storage/browser/file_system/external_mount_points.h"
105 #include "third_party/cros_system_api/dbus/service_constants.h"
106 #include "ui/display/display.h"
107 #include "ui/display/screen.h"
108 #include "ui/gfx/geometry/rect.h"
109 
110 using base::Time;
111 using base::TimeDelta;
112 
113 namespace em = enterprise_management;
114 
115 namespace {
116 // How many seconds of inactivity triggers the idle state.
117 const int kIdleStateThresholdSeconds = 300;
118 
119 // How much time in the past to store active periods for.
120 constexpr TimeDelta kMaxStoredPastActivityInterval = TimeDelta::FromDays(30);
121 
122 // How much time in the future to store active periods for.
123 constexpr TimeDelta kMaxStoredFutureActivityInterval = TimeDelta::FromDays(2);
124 
125 // How often, in seconds, to sample the hardware resource usage.
126 const unsigned int kResourceUsageSampleIntervalSeconds = 120;
127 
128 // The location we read our CPU statistics from.
129 const char kProcStat[] = "/proc/stat";
130 
131 // The location we read our CPU temperature and channel label from.
132 const char kHwmonDir[] = "/sys/class/hwmon/";
133 const char kDeviceDir[] = "device";
134 const char kHwmonDirectoryPattern[] = "hwmon*";
135 const char kCPUTempFilePattern[] = "temp*_input";
136 
137 // The location where storage device statistics are read from.
138 const char kStorageInfoPath[] = "/var/log/storage_info.txt";
139 
140 // The location where stateful partition info is read from.
141 const char kStatefulPartitionPath[] = "/home/.shadow";
142 
143 // TODO(b/144081278): Remove when resolved.
144 // Debug values for cases when firmware version is not present.
145 const char kFirmwareFileEmpty[] = "FirmwareFileEmpty";
146 const char kFirmwareFileNotRead[] = "FirmwareFileNotRead";
147 const char kFirmwareNotInitialized[] = "FirmwareNotInitialized";
148 const char kFirmwareNotParsed[] = "FirmwareNotParsed";
149 // File to look for firmware number in.
150 const char kPathFirmware[] = "/var/log/bios_info.txt";
151 
152 // O°C in deciKelvin.
153 const unsigned int kZeroCInDeciKelvin = 2731;
154 
155 // The duration for crash report collection.
156 constexpr TimeDelta kCrashReportInfoDuration = TimeDelta::FromDays(1);
157 
158 // The sources of crash report leads to device restart.
159 const char kCrashReportSourceKernel[] = "kernel";
160 const char kCrashReportSourceEC[] = "embedded-controller";
161 
162 // The maximum number of crash report entries to be read.
163 // According to the official document, the crash reporter uploads no more than
164 // 24 MB (compressed) or 32 reports (whichever comes last) in any 24 hour
165 // window. Therefore, it looks safe to set max size as 100 here.
166 const int kCrashReportEntryMaxSize = 100;
167 
168 // Helper function (invoked via blocking pool) to fetch information about
169 // mounted disks.
GetVolumeInfo(const std::vector<std::string> & mount_points)170 std::vector<em::VolumeInfo> GetVolumeInfo(
171     const std::vector<std::string>& mount_points) {
172   std::vector<em::VolumeInfo> result;
173   for (const std::string& mount_point : mount_points) {
174     base::FilePath mount_path(mount_point);
175 
176     // Non-native file systems do not have a mount point in the local file
177     // system. However, it's worth checking here, as it's easier than checking
178     // earlier which mount point is local, and which one is not.
179     if (mount_point.empty() || !base::PathExists(mount_path))
180       continue;
181 
182     int64_t free_size = base::SysInfo::AmountOfFreeDiskSpace(mount_path);
183     int64_t total_size = base::SysInfo::AmountOfTotalDiskSpace(mount_path);
184     if (free_size < 0 || total_size < 0) {
185       LOG(ERROR) << "Unable to get volume status for " << mount_point;
186       continue;
187     }
188     em::VolumeInfo info;
189     info.set_volume_id(mount_point);
190     info.set_storage_total(total_size);
191     info.set_storage_free(free_size);
192     result.push_back(info);
193   }
194   return result;
195 }
196 
197 // Reads the first CPU line from /proc/stat. Returns an empty string if
198 // the cpu data could not be read.
199 // The format of this line from /proc/stat is:
200 //
201 //   cpu  user_time nice_time system_time idle_time
202 //
203 // where user_time, nice_time, system_time, and idle_time are all integer
204 // values measured in jiffies from system startup.
ReadCPUStatistics()205 std::string ReadCPUStatistics() {
206   std::string contents;
207   if (base::ReadFileToString(base::FilePath(kProcStat), &contents)) {
208     size_t eol = contents.find("\n");
209     if (eol != std::string::npos) {
210       std::string line = contents.substr(0, eol);
211       if (line.compare(0, 4, "cpu ") == 0)
212         return line;
213     }
214     // First line should always start with "cpu ".
215     NOTREACHED() << "Could not parse /proc/stat contents: " << contents;
216   }
217   LOG(WARNING) << "Unable to read CPU statistics from " << kProcStat;
218   return std::string();
219 }
220 
221 // Read system temperature sensor data into |out_contents| from
222 //
223 // |sensor_dir|/temp*_input
224 //
225 // which contains millidegree Celsius temperature and
226 //
227 // |sensor_dir|/temp*_label or
228 // |sensor_dir|/name
229 //
230 // which contains an appropriate label name for the given sensor.
231 // Returns |true| iff there was at least one sensor value in given |sensor_dir|.
ReadTemperatureSensorInfo(const base::FilePath & sensor_dir,std::vector<em::CPUTempInfo> * out_contents)232 bool ReadTemperatureSensorInfo(const base::FilePath& sensor_dir,
233                                std::vector<em::CPUTempInfo>* out_contents) {
234   bool has_data = false;
235 
236   base::FileEnumerator enumerator(
237       sensor_dir, false, base::FileEnumerator::FILES, kCPUTempFilePattern);
238   for (base::FilePath temperature_path = enumerator.Next();
239        !temperature_path.empty(); temperature_path = enumerator.Next()) {
240     // Get appropriate temp*_label file.
241     std::string label_path = temperature_path.MaybeAsASCII();
242     if (label_path.empty()) {
243       LOG(WARNING) << "Unable to parse a path to temp*_input file as ASCII";
244       continue;
245     }
246     base::ReplaceSubstringsAfterOffset(&label_path, 0, "input", "label");
247     base::FilePath name_path = sensor_dir.Append("name");
248 
249     // Get the label describing this temperature. Use temp*_label
250     // if present, fall back on name file or blank.
251     std::string label;
252     if (base::PathExists(base::FilePath(label_path))) {
253       base::ReadFileToString(base::FilePath(label_path), &label);
254     } else if (base::PathExists(base::FilePath(name_path))) {
255       base::ReadFileToString(name_path, &label);
256     } else {
257       label = std::string();
258     }
259 
260     // Read temperature in millidegree Celsius.
261     std::string temperature_string;
262     int32_t temperature = 0;
263     if (base::ReadFileToString(temperature_path, &temperature_string) &&
264         sscanf(temperature_string.c_str(), "%d", &temperature) == 1) {
265       has_data = true;
266       // CPU temp in millidegree Celsius to Celsius
267       temperature /= 1000;
268 
269       em::CPUTempInfo info;
270       info.set_cpu_label(label);
271       info.set_cpu_temp(temperature);
272       out_contents->push_back(info);
273     } else {
274       LOG(WARNING) << "Unable to read CPU temp from "
275                    << temperature_path.MaybeAsASCII();
276     }
277   }
278   return has_data;
279 }
280 
281 // Read system temperature sensors from
282 //
283 // /sys/class/hwmon/hwmon*/(device/)?
ReadCPUTempInfo()284 std::vector<em::CPUTempInfo> ReadCPUTempInfo() {
285   std::vector<em::CPUTempInfo> contents;
286   // Get directories /sys/class/hwmon/hwmon*
287   base::FileEnumerator hwmon_enumerator(base::FilePath(kHwmonDir), false,
288                                         base::FileEnumerator::DIRECTORIES,
289                                         kHwmonDirectoryPattern);
290   for (base::FilePath hwmon_path = hwmon_enumerator.Next(); !hwmon_path.empty();
291        hwmon_path = hwmon_enumerator.Next()) {
292     // Get temp*_input files in hwmon*/ and hwmon*/device/
293     base::FilePath device_path = hwmon_path.Append(kDeviceDir);
294     if (base::PathExists(device_path)) {
295       // We might have hwmon*/device/, but sensor values are still in hwmon*/
296       if (!ReadTemperatureSensorInfo(device_path, &contents)) {
297         ReadTemperatureSensorInfo(hwmon_path, &contents);
298       }
299     } else {
300       ReadTemperatureSensorInfo(hwmon_path, &contents);
301     }
302   }
303   return contents;
304 }
305 
306 // If |contents| contains |prefix| followed by a hex integer, parses the hex
307 // integer of specified length and returns it.
308 // Otherwise, returns base::nullopt.
ExtractHexIntegerAfterPrefix(base::StringPiece contents,base::StringPiece prefix,size_t hex_number_length)309 base::Optional<int> ExtractHexIntegerAfterPrefix(base::StringPiece contents,
310                                                  base::StringPiece prefix,
311                                                  size_t hex_number_length) {
312   size_t prefix_position = contents.find(prefix);
313   if (prefix_position == std::string::npos)
314     return base::nullopt;
315   if (prefix_position + prefix.size() + hex_number_length >= contents.size())
316     return base::nullopt;
317   int parsed_number;
318   if (!base::HexStringToInt(
319           contents.substr(prefix_position + prefix.size(), hex_number_length),
320           &parsed_number)) {
321     return base::nullopt;
322   }
323   return parsed_number;
324 }
325 
326 // Read life time estimation value for eMMC from data generated by
327 // chromeos_disk_metrics. The data is stored in format:
328 // [DEVICE_LIFE_TIME_EST_TYP_[AB]: 0xXX]
329 // where A, B indicate the area of MMC being assesed(SLC and MLC), XX -- hex
330 // integer representing wear out of selected area.
331 // reference: e.MMC Device Health Report
332 // https://www.micron.com/products/managed-nand/emmc/emmc-software
ReadDiskLifeTimeEstimation()333 em::DiskLifetimeEstimation ReadDiskLifeTimeEstimation() {
334   em::DiskLifetimeEstimation est;
335   std::string contents;
336   const std::string pattern_slc = "[DEVICE_LIFE_TIME_EST_TYP_A: 0x";
337   const std::string pattern_mlc = "[DEVICE_LIFE_TIME_EST_TYP_B: 0x";
338   if (!base::ReadFileToStringWithMaxSize(
339           base::FilePath(kStorageInfoPath), &contents,
340           40000)) {  // max size in case somebody tackles with the file
341     return est;
342   }
343   auto slc_est = ExtractHexIntegerAfterPrefix(contents, pattern_slc, 2);
344   if (slc_est)
345     est.set_slc(slc_est.value());
346   auto mlc_est = ExtractHexIntegerAfterPrefix(contents, pattern_mlc, 2);
347   if (mlc_est)
348     est.set_mlc(mlc_est.value());
349   return est;
350 }
351 
352 // Read stateful partition info for user data.
ReadStatefulPartitionInfo()353 em::StatefulPartitionInfo ReadStatefulPartitionInfo() {
354   em::StatefulPartitionInfo spi;
355   const base::FilePath statefulPartitionPath(kStatefulPartitionPath);
356   const int64_t available_space =
357       base::SysInfo::AmountOfFreeDiskSpace(statefulPartitionPath);
358   const int64_t total_space =
359       base::SysInfo::AmountOfTotalDiskSpace(statefulPartitionPath);
360 
361   if (available_space == -1) {
362     LOG(ERROR) << "ReadStatefulPartitionInfo failed fetching available space.";
363     return spi;
364   }
365 
366   if (total_space == -1) {
367     LOG(ERROR) << "ReadStatefulPartitionInfo failed fetching total space.";
368     return spi;
369   }
370 
371   spi.set_available_space(available_space);
372   spi.set_total_space(total_space);
373   return spi;
374 }
375 
376 // Collects all the display related information.
GetDisplayStatus(em::GraphicsStatus * graphics_status)377 void GetDisplayStatus(em::GraphicsStatus* graphics_status) {
378   const std::vector<display::Display> displays =
379       display::Screen::GetScreen()->GetAllDisplays();
380   for (const auto& display : displays) {
381     em::DisplayInfo* display_info = graphics_status->add_displays();
382     display_info->set_resolution_width(display.GetSizeInPixel().width());
383     display_info->set_resolution_height(display.GetSizeInPixel().height());
384     display_info->set_refresh_rate(display.display_frequency());
385     display_info->set_is_internal(display.IsInternal());
386   }
387 }
388 
389 // Makes the requested |gpu_memory_stats| available. Collects the other required
390 // graphics properties next. Finally, calls |callback|.
OnVideoMemoryUsageStatsUpdate(policy::DeviceStatusCollector::GraphicsStatusReceiver callback,std::unique_ptr<em::GraphicsStatus> graphics_status,const gpu::VideoMemoryUsageStats & gpu_memory_stats)391 void OnVideoMemoryUsageStatsUpdate(
392     policy::DeviceStatusCollector::GraphicsStatusReceiver callback,
393     std::unique_ptr<em::GraphicsStatus> graphics_status,
394     const gpu::VideoMemoryUsageStats& gpu_memory_stats) {
395   auto* gpu_data_manager = content::GpuDataManager::GetInstance();
396   gpu::GPUInfo gpu_info = gpu_data_manager->GetGPUInfo();
397   // Adapter information
398   em::GraphicsAdapterInfo* graphics_info = graphics_status->mutable_adapter();
399   graphics_info->set_name(gpu_info.gpu.device_string);
400   graphics_info->set_driver_version(gpu_info.gpu.driver_version);
401   graphics_info->set_device_id(gpu_info.gpu.device_id);
402   graphics_info->set_system_ram_usage(gpu_memory_stats.bytes_allocated);
403 
404   std::move(callback).Run(*graphics_status);
405 }
406 
407 // Fetches display-related and graphics-adapter information.
FetchGraphicsStatus(policy::DeviceStatusCollector::GraphicsStatusReceiver callback)408 void FetchGraphicsStatus(
409     policy::DeviceStatusCollector::GraphicsStatusReceiver callback) {
410   std::unique_ptr<em::GraphicsStatus> graphics_status =
411       std::make_unique<em::GraphicsStatus>();
412   GetDisplayStatus(graphics_status.get());
413   auto* gpu_data_manager = content::GpuDataManager::GetInstance();
414   gpu_data_manager->RequestVideoMemoryUsageStatsUpdate(
415       base::BindOnce(&OnVideoMemoryUsageStatsUpdate, std::move(callback),
416                      std::move(graphics_status)));
417 }
418 
ReadAndroidStatus(const policy::StatusCollector::AndroidStatusReceiver & receiver)419 bool ReadAndroidStatus(
420     const policy::StatusCollector::AndroidStatusReceiver& receiver) {
421   auto* const arc_service_manager = arc::ArcServiceManager::Get();
422   if (!arc_service_manager)
423     return false;
424   auto* const instance_holder =
425       arc_service_manager->arc_bridge_service()->enterprise_reporting();
426   if (!instance_holder)
427     return false;
428   auto* const instance =
429       ARC_GET_INSTANCE_FOR_METHOD(instance_holder, GetStatus);
430   if (!instance)
431     return false;
432   instance->GetStatus(receiver);
433   return true;
434 }
435 
436 // Converts the given GetTpmStatusReply to TpmStatusInfo.
GetTpmStatusReplyToTpmStatusInfo(const base::Optional<cryptohome::BaseReply> & reply)437 policy::TpmStatusInfo GetTpmStatusReplyToTpmStatusInfo(
438     const base::Optional<cryptohome::BaseReply>& reply) {
439   policy::TpmStatusInfo tpm_status_info;
440 
441   if (!reply.has_value()) {
442     LOG(ERROR) << "GetTpmStatus call failed with empty reply.";
443     return tpm_status_info;
444   }
445   if (reply->has_error() &&
446       reply->error() != cryptohome::CRYPTOHOME_ERROR_NOT_SET) {
447     LOG(ERROR) << "GetTpmStatus failed with error: " << reply->error();
448     return tpm_status_info;
449   }
450   if (!reply->HasExtension(cryptohome::GetTpmStatusReply::reply)) {
451     LOG(ERROR)
452         << "GetTpmStatus failed with no GetTpmStatusReply extension in reply.";
453     return tpm_status_info;
454   }
455 
456   auto reply_proto = reply->GetExtension(cryptohome::GetTpmStatusReply::reply);
457 
458   tpm_status_info.enabled = reply_proto.enabled();
459   tpm_status_info.owned = reply_proto.owned();
460   tpm_status_info.initialized = reply_proto.initialized();
461   tpm_status_info.attestation_prepared = reply_proto.attestation_prepared();
462   tpm_status_info.attestation_enrolled = reply_proto.attestation_enrolled();
463   tpm_status_info.dictionary_attack_counter =
464       reply_proto.dictionary_attack_counter();
465   tpm_status_info.dictionary_attack_threshold =
466       reply_proto.dictionary_attack_threshold();
467   tpm_status_info.dictionary_attack_lockout_in_effect =
468       reply_proto.dictionary_attack_lockout_in_effect();
469   tpm_status_info.dictionary_attack_lockout_seconds_remaining =
470       reply_proto.dictionary_attack_lockout_seconds_remaining();
471   tpm_status_info.boot_lockbox_finalized = reply_proto.boot_lockbox_finalized();
472 
473   return tpm_status_info;
474 }
475 
ReadTpmStatus(policy::DeviceStatusCollector::TpmStatusReceiver callback)476 void ReadTpmStatus(policy::DeviceStatusCollector::TpmStatusReceiver callback) {
477   // D-Bus calls are allowed only on the UI thread.
478   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
479   chromeos::CryptohomeClient::Get()->GetTpmStatus(
480       cryptohome::GetTpmStatusRequest(),
481       base::BindOnce(
482           [](policy::DeviceStatusCollector::TpmStatusReceiver callback,
483              base::Optional<cryptohome::BaseReply> reply) {
484             std::move(callback).Run(GetTpmStatusReplyToTpmStatusInfo(reply));
485           },
486           std::move(callback)));
487 }
488 
GetPlatformVersion()489 base::Version GetPlatformVersion() {
490   return base::Version(base::SysInfo::OperatingSystemVersion());
491 }
492 
493 // Helper routine to convert from Shill-provided signal strength (percent)
494 // to dBm units expected by server.
ConvertWifiSignalStrength(int signal_strength)495 int ConvertWifiSignalStrength(int signal_strength) {
496   // Shill attempts to convert WiFi signal strength from its internal dBm to a
497   // percentage range (from 0-100) by adding 120 to the raw dBm value,
498   // and then clamping the result to the range 0-100 (see
499   // shill::WiFiService::SignalToStrength()).
500   //
501   // To convert back to dBm, we subtract 120 from the percentage value to yield
502   // a clamped dBm value in the range of -119 to -20dBm.
503   //
504   // TODO(atwilson): Tunnel the raw dBm signal strength from Shill instead of
505   // doing the conversion here so we can report non-clamped values
506   // (crbug.com/463334).
507   DCHECK_GT(signal_strength, 0);
508   DCHECK_LE(signal_strength, 100);
509   return signal_strength - 120;
510 }
511 
IsKioskApp()512 bool IsKioskApp() {
513   return chromeos::LoginState::Get()->GetLoggedInUserType() ==
514          chromeos::LoginState::LOGGED_IN_USER_KIOSK_APP;
515 }
516 
517 // Utility method to turn cpu_temp_fetcher_ to OnceCallback
InvokeCpuTempFetcher(policy::DeviceStatusCollector::CPUTempFetcher fetcher)518 std::vector<em::CPUTempInfo> InvokeCpuTempFetcher(
519     policy::DeviceStatusCollector::CPUTempFetcher fetcher) {
520   return fetcher.Run();
521 }
522 
523 // Utility method to complete information for a reported Crostini App.
524 // Returns whether all required App information could be retrieved or not.
AddCrostiniAppInfo(const guest_os::GuestOsRegistryService::Registration & registration,em::CrostiniApp * const app)525 bool AddCrostiniAppInfo(
526     const guest_os::GuestOsRegistryService::Registration& registration,
527     em::CrostiniApp* const app) {
528   app->set_app_name(registration.Name());
529   const base::Time last_launch_time = registration.LastLaunchTime();
530   if (!last_launch_time.is_null()) {
531     app->set_last_launch_time_window_start_timestamp(
532         crostini::GetThreeDayWindowStart(last_launch_time).ToJavaTime());
533   }
534 
535   if (registration.app_id() == crostini::kCrostiniTerminalSystemAppId) {
536     app->set_app_type(em::CROSTINI_APP_TYPE_TERMINAL);
537     // We do not log package information if the App is the terminal:
538     return true;
539   }
540   app->set_app_type(em::CROSTINI_APP_TYPE_INTERACTIVE);
541 
542   const std::string& package_id = registration.PackageId();
543   if (package_id.empty())
544     return true;
545 
546   const std::vector<std::string> package_info = base::SplitString(
547       package_id, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
548 
549   // The package identifier is in the form of a semicolon delimited string of
550   // the format: name;version;arch;data (see cicerone_service.proto)
551   if (package_info.size() != 4) {
552     LOG(ERROR) << "Package id has the wrong format: " << package_id;
553     return false;
554   }
555 
556   app->set_package_name(package_info[0]);
557   app->set_package_version(package_info[1]);
558 
559   return true;
560 }
561 
562 // Utility method to add a list of installed Crostini Apps to Crostini status
AddCrostiniAppListForProfile(Profile * const profile,em::CrostiniStatus * const crostini_status)563 void AddCrostiniAppListForProfile(Profile* const profile,
564                                   em::CrostiniStatus* const crostini_status) {
565   const std::map<std::string, guest_os::GuestOsRegistryService::Registration>&
566       registered_apps =
567           guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile)
568               ->GetRegisteredApps(guest_os::GuestOsRegistryService::VmType::
569                                       ApplicationList_VmType_TERMINA);
570   for (const auto& pair : registered_apps) {
571     const std::string& registered_app_id = pair.first;
572     const guest_os::GuestOsRegistryService::Registration& registration =
573         pair.second;
574     em::CrostiniApp* const app = crostini_status->add_installed_apps();
575     if (!AddCrostiniAppInfo(registration, app)) {
576       LOG(ERROR) << "Could not retrieve all required information for "
577                     "registered app_id: "
578                  << registered_app_id;
579     }
580   }
581 }
582 
583 // Reads content of firmware file.
584 // Returns pair of the firmware version and fetch error if not fetched.
585 // TODO(b/144081278): Just call chromeos::version_loader::ParseFirmware() when
586 // it's resolved.
ReadFirmwareVersion()587 std::pair<std::string, std::string> ReadFirmwareVersion() {
588   std::string firmware;
589   std::string contents;
590   const base::FilePath file_path(kPathFirmware);
591   if (!base::ReadFileToString(file_path, &contents))
592     return {firmware, kFirmwareFileNotRead};
593   if (contents.empty())
594     return {firmware, kFirmwareFileEmpty};
595   firmware = chromeos::version_loader::ParseFirmware(contents);
596   if (firmware.empty())
597     return {firmware, kFirmwareNotParsed};
598   return {firmware, std::string()};
599 }
600 
GetCrashReportUploadStatus(UploadList::UploadInfo::State state)601 em::CrashReportInfo::CrashReportUploadStatus GetCrashReportUploadStatus(
602     UploadList::UploadInfo::State state) {
603   switch (state) {
604     case UploadList::UploadInfo::State::NotUploaded:
605       return em::CrashReportInfo::UPLOAD_STATUS_NOT_UPLOADED;
606     case UploadList::UploadInfo::State::Pending:
607       return em::CrashReportInfo::UPLOAD_STATUS_PENDING;
608     case UploadList::UploadInfo::State::Pending_UserRequested:
609       return em::CrashReportInfo::UPLOAD_STATUS_PENDING_USER_REQUESTED;
610     case UploadList::UploadInfo::State::Uploaded:
611       return em::CrashReportInfo::UPLOAD_STATUS_UPLOADED;
612     default:
613       return em::CrashReportInfo::UPLOAD_STATUS_UNKNOWN;
614   }
615 
616   NOTREACHED();
617 }
618 
619 // Filter the loaded crash reports.
620 // - the |upload_time| should be with last 24 hours.
621 // - the |source| should be 'kernel' or 'embedded-controller'.
CrashReportsLoaded(scoped_refptr<UploadList> upload_list,policy::DeviceStatusCollector::CrashReportInfoReceiver callback)622 void CrashReportsLoaded(
623     scoped_refptr<UploadList> upload_list,
624     policy::DeviceStatusCollector::CrashReportInfoReceiver callback) {
625   std::vector<UploadList::UploadInfo> uploads;
626   upload_list->GetUploads(kCrashReportEntryMaxSize, &uploads);
627 
628   const Time end_time = Time::Now();
629   const Time start_time = end_time - kCrashReportInfoDuration;
630 
631   std::vector<em::CrashReportInfo> contents;
632   for (const UploadList::UploadInfo& crash_report : uploads) {
633     if (crash_report.upload_time >= start_time &&
634         crash_report.upload_time < end_time &&
635         (crash_report.source == kCrashReportSourceKernel ||
636          crash_report.source == kCrashReportSourceEC)) {
637       em::CrashReportInfo info;
638       info.set_remote_id(crash_report.upload_id);
639       info.set_capture_timestamp(crash_report.capture_time.ToJavaTime());
640       info.set_cause(crash_report.source);
641       info.set_upload_status(GetCrashReportUploadStatus(crash_report.state));
642       contents.push_back(info);
643     }
644   }
645 
646   std::move(callback).Run(contents);
647 }
648 
649 // Read the crash reports stored in the uploads.log file.
ReadCrashReportInfo(policy::DeviceStatusCollector::CrashReportInfoReceiver callback)650 void ReadCrashReportInfo(
651     policy::DeviceStatusCollector::CrashReportInfoReceiver callback) {
652   scoped_refptr<UploadList> upload_list = CreateCrashUploadList();
653   upload_list->Load(
654       base::BindOnce(CrashReportsLoaded, upload_list, std::move(callback)));
655 }
656 
657 }  // namespace
658 
659 namespace policy {
660 
661 class DeviceStatusCollectorState : public StatusCollectorState {
662  public:
DeviceStatusCollectorState(const scoped_refptr<base::SequencedTaskRunner> task_runner,const StatusCollectorCallback & response)663   explicit DeviceStatusCollectorState(
664       const scoped_refptr<base::SequencedTaskRunner> task_runner,
665       const StatusCollectorCallback& response)
666       : StatusCollectorState(task_runner, response) {}
667 
668   // Queues an async callback to query disk volume information.
SampleVolumeInfo(const DeviceStatusCollector::VolumeInfoFetcher & volume_info_fetcher)669   void SampleVolumeInfo(
670       const DeviceStatusCollector::VolumeInfoFetcher& volume_info_fetcher) {
671     // Create list of mounted disk volumes to query status.
672     std::vector<storage::MountPoints::MountPointInfo> external_mount_points;
673     storage::ExternalMountPoints::GetSystemInstance()->AddMountPointInfosTo(
674         &external_mount_points);
675 
676     std::vector<std::string> mount_points;
677     for (const auto& info : external_mount_points)
678       mount_points.push_back(info.path.value());
679 
680     for (const auto& mount_info :
681          chromeos::disks::DiskMountManager::GetInstance()->mount_points()) {
682       // Extract a list of mount points to populate.
683       mount_points.push_back(mount_info.first);
684     }
685 
686     // Call out to the blocking pool to sample disk volume info.
687     base::ThreadPool::PostTaskAndReplyWithResult(
688         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
689         base::BindOnce(volume_info_fetcher, mount_points),
690         base::BindOnce(&DeviceStatusCollectorState::OnVolumeInfoReceived,
691                        this));
692   }
693 
694   // Queues an async callback to query CPU temperature information.
SampleCPUTempInfo(const DeviceStatusCollector::CPUTempFetcher & cpu_temp_fetcher)695   void SampleCPUTempInfo(
696       const DeviceStatusCollector::CPUTempFetcher& cpu_temp_fetcher) {
697     // Call out to the blocking pool to sample CPU temp.
698     base::ThreadPool::PostTaskAndReplyWithResult(
699         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
700         base::BindOnce(cpu_temp_fetcher),
701         base::BindOnce(&DeviceStatusCollectorState::OnCPUTempInfoReceived,
702                        this));
703   }
704 
FetchAndroidStatus(const StatusCollector::AndroidStatusFetcher & android_status_fetcher)705   bool FetchAndroidStatus(
706       const StatusCollector::AndroidStatusFetcher& android_status_fetcher) {
707     return android_status_fetcher.Run(
708         base::Bind(&DeviceStatusCollectorState::OnAndroidInfoReceived, this));
709   }
710 
FetchTpmStatus(const DeviceStatusCollector::TpmStatusFetcher & tpm_status_fetcher)711   void FetchTpmStatus(
712       const DeviceStatusCollector::TpmStatusFetcher& tpm_status_fetcher) {
713     tpm_status_fetcher.Run(
714         base::BindOnce(&DeviceStatusCollectorState::OnTpmStatusReceived, this));
715   }
716 
FetchCrosHealthdData(const policy::DeviceStatusCollector::CrosHealthdDataFetcher & cros_healthd_data_fetcher,bool report_system_info,bool report_vpd_info)717   void FetchCrosHealthdData(
718       const policy::DeviceStatusCollector::CrosHealthdDataFetcher&
719           cros_healthd_data_fetcher,
720       bool report_system_info,
721       bool report_vpd_info) {
722     cros_healthd_data_fetcher.Run(
723         CrosHealthdCollectionMode::kFull,
724         base::BindOnce(&DeviceStatusCollectorState::OnCrosHealthdDataReceived,
725                        this, report_system_info, report_vpd_info));
726   }
727 
FetchEMMCLifeTime(const policy::DeviceStatusCollector::EMMCLifetimeFetcher & emmc_lifetime_fetcher)728   void FetchEMMCLifeTime(
729       const policy::DeviceStatusCollector::EMMCLifetimeFetcher&
730           emmc_lifetime_fetcher) {
731     // Call out to the blocking pool to read disklifetimeestimation.
732     base::ThreadPool::PostTaskAndReplyWithResult(
733         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
734         base::BindOnce(emmc_lifetime_fetcher),
735         base::BindOnce(&DeviceStatusCollectorState::OnEMMCLifetimeReceived,
736                        this));
737   }
738 
FetchStatefulPartitionInfo(const policy::DeviceStatusCollector::StatefulPartitionInfoFetcher & stateful_partition_info_fetcher)739   void FetchStatefulPartitionInfo(
740       const policy::DeviceStatusCollector::StatefulPartitionInfoFetcher&
741           stateful_partition_info_fetcher) {
742     // Call out to the blocking pool to read stateful partition information.
743     base::ThreadPool::PostTaskAndReplyWithResult(
744         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
745         base::BindOnce(stateful_partition_info_fetcher),
746         base::BindOnce(
747             &DeviceStatusCollectorState::OnStatefulPartitionInfoReceived,
748             this));
749   }
750 
FetchGraphicsStatus(const policy::DeviceStatusCollector::GraphicsStatusFetcher & graphics_status_fetcher)751   void FetchGraphicsStatus(
752       const policy::DeviceStatusCollector::GraphicsStatusFetcher&
753           graphics_status_fetcher) {
754     graphics_status_fetcher.Run(base::BindOnce(
755         &DeviceStatusCollectorState::OnGraphicsStatusReceived, this));
756   }
757 
FetchCrashReportInfo(const policy::DeviceStatusCollector::CrashReportInfoFetcher & crash_report_fetcher)758   void FetchCrashReportInfo(
759       const policy::DeviceStatusCollector::CrashReportInfoFetcher&
760           crash_report_fetcher) {
761     crash_report_fetcher.Run(base::BindOnce(
762         &DeviceStatusCollectorState::OnCrashReportInfoReceived, this));
763   }
764 
765  private:
766   ~DeviceStatusCollectorState() override = default;
767 
OnVolumeInfoReceived(const std::vector<em::VolumeInfo> & volume_info)768   void OnVolumeInfoReceived(const std::vector<em::VolumeInfo>& volume_info) {
769     response_params_.device_status->clear_volume_infos();
770     for (const em::VolumeInfo& info : volume_info)
771       *response_params_.device_status->add_volume_infos() = info;
772   }
773 
OnCPUTempInfoReceived(const std::vector<em::CPUTempInfo> & cpu_temp_info)774   void OnCPUTempInfoReceived(
775       const std::vector<em::CPUTempInfo>& cpu_temp_info) {
776     // Only one of OnCrosHealthdDataReceived or OnCPUTempInfoReceived should be
777     // called.
778     DCHECK_EQ(response_params_.device_status->cpu_temp_infos_size(), 0);
779 
780     DLOG_IF(WARNING, cpu_temp_info.empty())
781         << "Unable to read CPU temp information.";
782     base::Time timestamp = base::Time::Now();
783     for (const em::CPUTempInfo& info : cpu_temp_info) {
784       auto* new_info = response_params_.device_status->add_cpu_temp_infos();
785       *new_info = info;
786       new_info->set_timestamp(timestamp.ToJavaTime());
787     }
788   }
789 
OnAndroidInfoReceived(const std::string & status,const std::string & droid_guard_info)790   void OnAndroidInfoReceived(const std::string& status,
791                              const std::string& droid_guard_info) {
792     em::AndroidStatus* const android_status =
793         response_params_.session_status->mutable_android_status();
794     android_status->set_status_payload(status);
795     android_status->set_droid_guard_info(droid_guard_info);
796   }
797 
OnTpmStatusReceived(const TpmStatusInfo & tpm_status_struct)798   void OnTpmStatusReceived(const TpmStatusInfo& tpm_status_struct) {
799     // Make sure we edit the state on the right thread.
800     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
801     em::TpmStatusInfo* const tpm_status_proto =
802         response_params_.device_status->mutable_tpm_status_info();
803 
804     tpm_status_proto->set_enabled(tpm_status_struct.enabled);
805     tpm_status_proto->set_owned(tpm_status_struct.owned);
806     tpm_status_proto->set_tpm_initialized(tpm_status_struct.initialized);
807     tpm_status_proto->set_attestation_prepared(
808         tpm_status_struct.attestation_prepared);
809     tpm_status_proto->set_attestation_enrolled(
810         tpm_status_struct.attestation_enrolled);
811     tpm_status_proto->set_dictionary_attack_counter(
812         tpm_status_struct.dictionary_attack_counter);
813     tpm_status_proto->set_dictionary_attack_threshold(
814         tpm_status_struct.dictionary_attack_threshold);
815     tpm_status_proto->set_dictionary_attack_lockout_in_effect(
816         tpm_status_struct.dictionary_attack_lockout_in_effect);
817     tpm_status_proto->set_dictionary_attack_lockout_seconds_remaining(
818         tpm_status_struct.dictionary_attack_lockout_seconds_remaining);
819     tpm_status_proto->set_boot_lockbox_finalized(
820         tpm_status_struct.boot_lockbox_finalized);
821   }
822 
823   // Stores the contents of |probe_result| and |samples| to |response_params_|.
OnCrosHealthdDataReceived(bool report_system_info,bool report_vpd_info,chromeos::cros_healthd::mojom::TelemetryInfoPtr probe_result,const base::circular_deque<std::unique_ptr<SampledData>> & samples)824   void OnCrosHealthdDataReceived(
825       bool report_system_info,
826       bool report_vpd_info,
827       chromeos::cros_healthd::mojom::TelemetryInfoPtr probe_result,
828       const base::circular_deque<std::unique_ptr<SampledData>>& samples) {
829     namespace cros_healthd = chromeos::cros_healthd::mojom;
830     // Make sure we edit the state on the right thread.
831     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
832 
833     // Only one of OnCrosHealthdDataReceived or OnCPUTempInfoReceived should be
834     // called.
835     DCHECK_EQ(response_params_.device_status->cpu_temp_infos_size(), 0);
836 
837     // Store CPU measurement samples.
838     for (const std::unique_ptr<SampledData>& sample_data : samples) {
839       for (auto kv : sample_data->cpu_samples) {
840         response_params_.device_status->mutable_cpu_temp_infos()->Add(
841             std::move(kv.second));
842       }
843     }
844 
845     if (probe_result.is_null())
846       return;
847 
848     // Process NonRemovableBlockDeviceResult.
849     const auto& block_device_result = probe_result->block_device_result;
850     if (!block_device_result.is_null()) {
851       switch (block_device_result->which()) {
852         case cros_healthd::NonRemovableBlockDeviceResult::Tag::ERROR: {
853           LOG(ERROR) << "cros_healthd: Error getting block device info: "
854                      << block_device_result->get_error()->msg;
855           break;
856         }
857 
858         case cros_healthd::NonRemovableBlockDeviceResult::Tag::
859             BLOCK_DEVICE_INFO: {
860           em::StorageStatus* const storage_status_out =
861               response_params_.device_status->mutable_storage_status();
862           for (const auto& storage :
863                block_device_result->get_block_device_info()) {
864             em::DiskInfo* const disk_info_out = storage_status_out->add_disks();
865             disk_info_out->set_serial(base::NumberToString(storage->serial));
866             disk_info_out->set_manufacturer(
867                 base::NumberToString(storage->manufacturer_id));
868             disk_info_out->set_model(storage->name);
869             disk_info_out->set_type(storage->type);
870             disk_info_out->set_size(storage->size);
871             disk_info_out->set_bytes_read_since_last_boot(
872                 storage->bytes_read_since_last_boot);
873             disk_info_out->set_bytes_written_since_last_boot(
874                 storage->bytes_written_since_last_boot);
875             disk_info_out->set_read_time_seconds_since_last_boot(
876                 storage->read_time_seconds_since_last_boot);
877             disk_info_out->set_write_time_seconds_since_last_boot(
878                 storage->write_time_seconds_since_last_boot);
879             disk_info_out->set_io_time_seconds_since_last_boot(
880                 storage->io_time_seconds_since_last_boot);
881             const auto& discard_time =
882                 storage->discard_time_seconds_since_last_boot;
883             if (!discard_time.is_null()) {
884               disk_info_out->set_discard_time_seconds_since_last_boot(
885                   discard_time->value);
886             }
887 
888             // vendor_id
889             const auto& vendor_id = storage->vendor_id;
890             switch (vendor_id->which()) {
891               case chromeos::cros_healthd::mojom::BlockDeviceVendor::Tag::
892                   NVME_SUBSYSTEM_VENDOR:
893                 disk_info_out->set_nvme_subsystem_vendor(
894                     vendor_id->get_nvme_subsystem_vendor());
895                 break;
896               case chromeos::cros_healthd::mojom::BlockDeviceVendor::Tag::
897                   EMMC_OEMID:
898                 disk_info_out->set_emmc_oemid(vendor_id->get_emmc_oemid());
899                 break;
900               case chromeos::cros_healthd::mojom::BlockDeviceVendor::Tag::OTHER:
901                 disk_info_out->set_other_vendor(vendor_id->get_other());
902                 break;
903             }
904 
905             // product_id
906             const auto& product_id = storage->product_id;
907             switch (product_id->which()) {
908               case chromeos::cros_healthd::mojom::BlockDeviceProduct::Tag::
909                   NVME_SUBSYSTEM_DEVICE:
910                 disk_info_out->set_nvme_subsystem_device(
911                     product_id->get_nvme_subsystem_device());
912                 break;
913               case chromeos::cros_healthd::mojom::BlockDeviceProduct::Tag::
914                   EMMC_PNM:
915                 disk_info_out->set_emmc_pnm(product_id->get_emmc_pnm());
916                 break;
917               case chromeos::cros_healthd::mojom::BlockDeviceProduct::Tag::
918                   OTHER:
919                 disk_info_out->set_other_product(product_id->get_other());
920                 break;
921             }
922 
923             // revision
924             const auto& revision = storage->revision;
925             switch (revision->which()) {
926               case chromeos::cros_healthd::mojom::BlockDeviceRevision::Tag::
927                   NVME_PCIE_REV:
928                 disk_info_out->set_nvme_hardware_rev(
929                     revision->get_nvme_pcie_rev());
930                 break;
931               case chromeos::cros_healthd::mojom::BlockDeviceRevision::Tag::
932                   EMMC_PRV:
933                 disk_info_out->set_emmc_hardware_rev(revision->get_emmc_prv());
934                 break;
935               case chromeos::cros_healthd::mojom::BlockDeviceRevision::Tag::
936                   OTHER:
937                 disk_info_out->set_other_hardware_rev(revision->get_other());
938                 break;
939             }
940 
941             // firmware version
942             const auto& fw_version = storage->firmware_version;
943             switch (fw_version->which()) {
944               case chromeos::cros_healthd::mojom::BlockDeviceFirmware::Tag::
945                   NVME_FIRMWARE_REV:
946                 disk_info_out->set_nvme_firmware_rev(
947                     fw_version->get_nvme_firmware_rev());
948                 break;
949               case chromeos::cros_healthd::mojom::BlockDeviceFirmware::Tag::
950                   EMMC_FWREV:
951                 disk_info_out->set_emmc_firmware_rev(
952                     fw_version->get_emmc_fwrev());
953                 break;
954               case chromeos::cros_healthd::mojom::BlockDeviceFirmware::Tag::
955                   OTHER:
956                 disk_info_out->set_other_firmware_rev(fw_version->get_other());
957                 break;
958             }
959 
960             switch (storage->purpose) {
961               case chromeos::cros_healthd::mojom::StorageDevicePurpose::
962                   kUnknown:
963                 disk_info_out->set_purpose(em::DiskInfo::PURPOSE_UNKNOWN);
964                 break;
965               case chromeos::cros_healthd::mojom::StorageDevicePurpose::
966                   kBootDevice:
967                 disk_info_out->set_purpose(em::DiskInfo::PURPOSE_BOOT);
968                 break;
969               case chromeos::cros_healthd::mojom::StorageDevicePurpose::
970                   kSwapDevice:
971                 disk_info_out->set_purpose(em::DiskInfo::PURPOSE_SWAP);
972                 break;
973             }
974           }
975           break;
976         }
977       }
978     }
979 
980     // Process BatteryResult.
981     const auto& battery_result = probe_result->battery_result;
982     if (!battery_result.is_null()) {
983       switch (battery_result->which()) {
984         case cros_healthd::BatteryResult::Tag::ERROR: {
985           LOG(ERROR) << "cros_healthd: Error getting battery info: "
986                      << battery_result->get_error()->msg;
987           break;
988         }
989 
990         case cros_healthd::BatteryResult::Tag::BATTERY_INFO: {
991           const auto& battery_info = battery_result->get_battery_info();
992           // Device does not have a battery.
993           if (battery_info.is_null())
994             break;
995 
996           em::PowerStatus* const power_status_out =
997               response_params_.device_status->mutable_power_status();
998           em::BatteryInfo* const battery_info_out =
999               power_status_out->add_batteries();
1000           battery_info_out->set_serial(battery_info->serial_number);
1001           battery_info_out->set_manufacturer(battery_info->vendor);
1002           battery_info_out->set_cycle_count(battery_info->cycle_count);
1003           battery_info_out->set_technology(battery_info->technology);
1004           // Convert Ah to mAh:
1005           battery_info_out->set_design_capacity(
1006               std::lround(battery_info->charge_full_design * 1000));
1007           battery_info_out->set_full_charge_capacity(
1008               std::lround(battery_info->charge_full * 1000));
1009           // Convert V to mV:
1010           battery_info_out->set_design_min_voltage(
1011               std::lround(battery_info->voltage_min_design * 1000));
1012           if (battery_info->manufacture_date) {
1013             battery_info_out->set_manufacture_date(
1014                 battery_info->manufacture_date.value());
1015           }
1016 
1017           for (const std::unique_ptr<SampledData>& sample_data : samples) {
1018             auto it =
1019                 sample_data->battery_samples.find(battery_info->model_name);
1020             if (it != sample_data->battery_samples.end())
1021               battery_info_out->add_samples()->CheckTypeAndMergeFrom(
1022                   it->second);
1023           }
1024           break;
1025         }
1026       }
1027     }
1028 
1029     // Process CpuResult.
1030     const auto& cpu_result = probe_result->cpu_result;
1031     if (!cpu_result.is_null()) {
1032       switch (cpu_result->which()) {
1033         case cros_healthd::CpuResult::Tag::ERROR: {
1034           LOG(ERROR) << "cros_healthd: Error getting CPU info: "
1035                      << cpu_result->get_error()->msg;
1036           break;
1037         }
1038 
1039         case cros_healthd::CpuResult::Tag::CPU_INFO: {
1040           const auto& cpu_info = cpu_result->get_cpu_info();
1041 
1042           if (cpu_info.is_null()) {
1043             LOG(ERROR) << "Null CpuInfo from cros_healthd";
1044             break;
1045           }
1046 
1047           long clock_ticks_per_second = sysconf(_SC_CLK_TCK);
1048           if (clock_ticks_per_second == -1 || clock_ticks_per_second == 0) {
1049             LOG(ERROR) << "Failed getting number of clock ticks per second";
1050             break;
1051           }
1052 
1053           em::GlobalCpuInfo* const global_cpu_info_out =
1054               response_params_.device_status->mutable_global_cpu_info();
1055           global_cpu_info_out->set_num_total_threads(
1056               cpu_info->num_total_threads);
1057 
1058           for (const auto& physical_cpu : cpu_info->physical_cpus) {
1059             if (physical_cpu.is_null())
1060               continue;
1061 
1062             em::CpuInfo* const cpu_info_out =
1063                 response_params_.device_status->add_cpu_info();
1064             if (physical_cpu->model_name)
1065               cpu_info_out->set_model_name(physical_cpu->model_name.value());
1066             cpu_info_out->set_architecture(
1067                 static_cast<em::CpuInfo::Architecture>(cpu_info->architecture));
1068 
1069             for (const auto& logical_cpu : physical_cpu->logical_cpus) {
1070               if (logical_cpu.is_null())
1071                 continue;
1072 
1073               em::LogicalCpuInfo* const logical_cpu_info_out =
1074                   cpu_info_out->add_logical_cpus();
1075               logical_cpu_info_out->set_scaling_max_frequency_khz(
1076                   logical_cpu->scaling_max_frequency_khz);
1077               logical_cpu_info_out->set_scaling_current_frequency_khz(
1078                   logical_cpu->scaling_current_frequency_khz);
1079               logical_cpu_info_out->set_idle_time_seconds(
1080                   logical_cpu->idle_time_user_hz / clock_ticks_per_second);
1081 
1082               if (!cpu_info_out->has_max_clock_speed_khz()) {
1083                 cpu_info_out->set_max_clock_speed_khz(
1084                     logical_cpu->max_clock_speed_khz);
1085               }
1086 
1087               for (const auto& c_state : logical_cpu->c_states) {
1088                 if (c_state.is_null())
1089                   continue;
1090 
1091                 em::CpuCStateInfo* const c_state_info_out =
1092                     logical_cpu_info_out->add_c_states();
1093                 c_state_info_out->set_name(c_state->name);
1094                 c_state_info_out->set_time_in_state_since_last_boot_us(
1095                     c_state->time_in_state_since_last_boot_us);
1096               }
1097             }
1098           }
1099           break;
1100         }
1101       }
1102     }
1103 
1104     // Process TimezoneResult.
1105     const auto& timezone_result = probe_result->timezone_result;
1106     if (!timezone_result.is_null()) {
1107       switch (timezone_result->which()) {
1108         case cros_healthd::TimezoneResult::Tag::ERROR: {
1109           LOG(ERROR) << "cros_healthd: Error getting timezone info: "
1110                      << timezone_result->get_error()->msg;
1111           break;
1112         }
1113 
1114         case cros_healthd::TimezoneResult::Tag::TIMEZONE_INFO: {
1115           const auto& timezone_info = timezone_result->get_timezone_info();
1116           em::TimezoneInfo* const timezone_info_out =
1117               response_params_.device_status->mutable_timezone_info();
1118           timezone_info_out->set_posix(timezone_info->posix);
1119           timezone_info_out->set_region(timezone_info->region);
1120           break;
1121         }
1122       }
1123     }
1124 
1125     // Process MemoryResult.
1126     const auto& memory_result = probe_result->memory_result;
1127     if (!memory_result.is_null()) {
1128       switch (memory_result->which()) {
1129         case cros_healthd::MemoryResult::Tag::ERROR: {
1130           LOG(ERROR) << "cros_healthd: Error getting memory info: "
1131                      << memory_result->get_error()->msg;
1132           break;
1133         }
1134 
1135         case cros_healthd::MemoryResult::Tag::MEMORY_INFO: {
1136           const auto& memory_info = memory_result->get_memory_info();
1137           em::MemoryInfo* const memory_info_out =
1138               response_params_.device_status->mutable_memory_info();
1139           memory_info_out->set_total_memory_kib(memory_info->total_memory_kib);
1140           memory_info_out->set_free_memory_kib(memory_info->free_memory_kib);
1141           memory_info_out->set_available_memory_kib(
1142               memory_info->available_memory_kib);
1143           memory_info_out->set_page_faults_since_last_boot(
1144               memory_info->page_faults_since_last_boot);
1145           break;
1146         }
1147       }
1148     }
1149 
1150     // Process BacklightResult.
1151     const auto& backlight_result = probe_result->backlight_result;
1152     if (!backlight_result.is_null()) {
1153       switch (backlight_result->which()) {
1154         case cros_healthd::BacklightResult::Tag::ERROR: {
1155           LOG(ERROR) << "cros_healthd: Error getting backlight info: "
1156                      << backlight_result->get_error()->msg;
1157           break;
1158         }
1159 
1160         case cros_healthd::BacklightResult::Tag::BACKLIGHT_INFO: {
1161           for (const auto& backlight : backlight_result->get_backlight_info()) {
1162             em::BacklightInfo* const backlight_info_out =
1163                 response_params_.device_status->add_backlight_info();
1164             backlight_info_out->set_path(backlight->path);
1165             backlight_info_out->set_max_brightness(backlight->max_brightness);
1166             backlight_info_out->set_brightness(backlight->brightness);
1167           }
1168           break;
1169         }
1170       }
1171     }
1172 
1173     // Process FanResult.
1174     const auto& fan_result = probe_result->fan_result;
1175     if (!fan_result.is_null()) {
1176       switch (fan_result->which()) {
1177         case cros_healthd::FanResult::Tag::ERROR: {
1178           LOG(ERROR) << "cros_healthd: Error getting fan info: "
1179                      << fan_result->get_error()->msg;
1180           break;
1181         }
1182 
1183         case cros_healthd::FanResult::Tag::FAN_INFO: {
1184           for (const auto& fan : fan_result->get_fan_info()) {
1185             em::FanInfo* const fan_info_out =
1186                 response_params_.device_status->add_fan_info();
1187             fan_info_out->set_speed_rpm(fan->speed_rpm);
1188           }
1189           break;
1190         }
1191       }
1192     }
1193 
1194     // Process Bluetooth result.
1195     const auto& bluetooth_result = probe_result->bluetooth_result;
1196     if (!bluetooth_result.is_null()) {
1197       switch (bluetooth_result->which()) {
1198         case cros_healthd::BluetoothResult::Tag::ERROR: {
1199           LOG(ERROR) << "cros_healthd: Error getting Bluetooth info: "
1200                      << bluetooth_result->get_error()->msg;
1201           break;
1202         }
1203 
1204         case cros_healthd::BluetoothResult::Tag::BLUETOOTH_ADAPTER_INFO: {
1205           for (const auto& adapter :
1206                bluetooth_result->get_bluetooth_adapter_info()) {
1207             em::BluetoothAdapterInfo* const adapter_info_out =
1208                 response_params_.device_status->add_bluetooth_adapter_info();
1209             adapter_info_out->set_name(adapter->name);
1210             adapter_info_out->set_address(adapter->address);
1211             adapter_info_out->set_powered(adapter->powered);
1212             adapter_info_out->set_num_connected_devices(
1213                 adapter->num_connected_devices);
1214           }
1215           break;
1216         }
1217       }
1218     }
1219 
1220     // Process SystemResult.
1221     const auto& system_result = probe_result->system_result;
1222     if (!system_result.is_null()) {
1223       switch (system_result->which()) {
1224         case cros_healthd::SystemResult::Tag::ERROR: {
1225           LOG(ERROR) << "cros_healthd: Error getting system info: "
1226                      << system_result->get_error()->msg;
1227           break;
1228         }
1229 
1230         case cros_healthd::SystemResult::Tag::SYSTEM_INFO: {
1231           const auto& system_info = system_result->get_system_info();
1232           em::SystemStatus* const system_status_out =
1233               response_params_.device_status->mutable_system_status();
1234           if (report_vpd_info) {
1235             if (system_info->first_power_date.has_value()) {
1236               system_status_out->set_first_power_date(
1237                   system_info->first_power_date.value());
1238             }
1239             if (system_info->manufacture_date.has_value()) {
1240               system_status_out->set_manufacture_date(
1241                   system_info->manufacture_date.value());
1242             }
1243             if (system_info->product_sku_number.has_value()) {
1244               system_status_out->set_vpd_sku_number(
1245                   system_info->product_sku_number.value());
1246             }
1247             system_status_out->set_vpd_serial_number(
1248                 system_info->product_serial_number);
1249           }
1250           if (report_system_info) {
1251             system_status_out->set_marketing_name(system_info->marketing_name);
1252             if (system_info->bios_version.has_value()) {
1253               system_status_out->set_bios_version(
1254                   system_info->bios_version.value());
1255             }
1256             if (system_info->board_name.has_value()) {
1257               system_status_out->set_board_name(
1258                   system_info->board_name.value());
1259             }
1260             if (system_info->board_version.has_value()) {
1261               system_status_out->set_board_version(
1262                   system_info->board_version.value());
1263             }
1264             if (system_info->chassis_type) {
1265               system_status_out->set_chassis_type(
1266                   system_info->chassis_type->value);
1267             }
1268             if (system_info->product_name.has_value()) {
1269               system_status_out->set_product_name(
1270                   system_info->product_name.value());
1271             }
1272           }
1273           break;
1274         }
1275       }
1276     }
1277   }
1278 
OnEMMCLifetimeReceived(const em::DiskLifetimeEstimation & est)1279   void OnEMMCLifetimeReceived(const em::DiskLifetimeEstimation& est) {
1280     if (!est.has_slc() && !est.has_mlc())
1281       return;
1282     em::DiskLifetimeEstimation* state =
1283         response_params_.device_status->mutable_storage_status()
1284             ->mutable_lifetime_estimation();
1285     state->CopyFrom(est);
1286   }
1287 
OnStatefulPartitionInfoReceived(const em::StatefulPartitionInfo & hdsi)1288   void OnStatefulPartitionInfoReceived(const em::StatefulPartitionInfo& hdsi) {
1289     if (!hdsi.has_available_space() && !hdsi.has_total_space())
1290       return;
1291     em::StatefulPartitionInfo* stateful_partition_info =
1292         response_params_.device_status->mutable_stateful_partition_info();
1293     DCHECK_GE(hdsi.available_space(), 0);
1294     DCHECK_GE(hdsi.total_space(), hdsi.available_space());
1295     stateful_partition_info->CopyFrom(hdsi);
1296   }
1297 
OnGraphicsStatusReceived(const em::GraphicsStatus & gs)1298   void OnGraphicsStatusReceived(const em::GraphicsStatus& gs) {
1299     *response_params_.device_status->mutable_graphics_status() = gs;
1300   }
1301 
OnCrashReportInfoReceived(const std::vector<em::CrashReportInfo> & crash_report_infos)1302   void OnCrashReportInfoReceived(
1303       const std::vector<em::CrashReportInfo>& crash_report_infos) {
1304     DCHECK(response_params_.device_status->crash_report_infos_size() == 0);
1305     for (const em::CrashReportInfo& info : crash_report_infos) {
1306       *response_params_.device_status->add_crash_report_infos() = info;
1307     }
1308   }
1309 };
1310 
1311 TpmStatusInfo::TpmStatusInfo() = default;
1312 TpmStatusInfo::TpmStatusInfo(const TpmStatusInfo&) = default;
TpmStatusInfo(bool enabled,bool owned,bool initialized,bool attestation_prepared,bool attestation_enrolled,int32_t dictionary_attack_counter,int32_t dictionary_attack_threshold,bool dictionary_attack_lockout_in_effect,int32_t dictionary_attack_lockout_seconds_remaining,bool boot_lockbox_finalized)1313 TpmStatusInfo::TpmStatusInfo(
1314     bool enabled,
1315     bool owned,
1316     bool initialized,
1317     bool attestation_prepared,
1318     bool attestation_enrolled,
1319     int32_t dictionary_attack_counter,
1320     int32_t dictionary_attack_threshold,
1321     bool dictionary_attack_lockout_in_effect,
1322     int32_t dictionary_attack_lockout_seconds_remaining,
1323     bool boot_lockbox_finalized)
1324     : enabled(enabled),
1325       owned(owned),
1326       initialized(initialized),
1327       attestation_prepared(attestation_prepared),
1328       attestation_enrolled(attestation_enrolled),
1329       dictionary_attack_counter(dictionary_attack_counter),
1330       dictionary_attack_threshold(dictionary_attack_threshold),
1331       dictionary_attack_lockout_in_effect(dictionary_attack_lockout_in_effect),
1332       dictionary_attack_lockout_seconds_remaining(
1333           dictionary_attack_lockout_seconds_remaining),
1334       boot_lockbox_finalized(boot_lockbox_finalized) {}
1335 TpmStatusInfo::~TpmStatusInfo() = default;
1336 
1337 SampledData::SampledData() = default;
1338 SampledData::~SampledData() = default;
1339 
DeviceStatusCollector(PrefService * pref_service,chromeos::system::StatisticsProvider * provider,const VolumeInfoFetcher & volume_info_fetcher,const CPUStatisticsFetcher & cpu_statistics_fetcher,const CPUTempFetcher & cpu_temp_fetcher,const AndroidStatusFetcher & android_status_fetcher,const TpmStatusFetcher & tpm_status_fetcher,const EMMCLifetimeFetcher & emmc_lifetime_fetcher,const StatefulPartitionInfoFetcher & stateful_partition_info_fetcher,const CrosHealthdDataFetcher & cros_healthd_data_fetcher,const GraphicsStatusFetcher & graphics_status_fetcher,const CrashReportInfoFetcher & crash_report_info_fetcher,base::Clock * clock)1340 DeviceStatusCollector::DeviceStatusCollector(
1341     PrefService* pref_service,
1342     chromeos::system::StatisticsProvider* provider,
1343     const VolumeInfoFetcher& volume_info_fetcher,
1344     const CPUStatisticsFetcher& cpu_statistics_fetcher,
1345     const CPUTempFetcher& cpu_temp_fetcher,
1346     const AndroidStatusFetcher& android_status_fetcher,
1347     const TpmStatusFetcher& tpm_status_fetcher,
1348     const EMMCLifetimeFetcher& emmc_lifetime_fetcher,
1349     const StatefulPartitionInfoFetcher& stateful_partition_info_fetcher,
1350     const CrosHealthdDataFetcher& cros_healthd_data_fetcher,
1351     const GraphicsStatusFetcher& graphics_status_fetcher,
1352     const CrashReportInfoFetcher& crash_report_info_fetcher,
1353     base::Clock* clock)
1354     : StatusCollector(provider, chromeos::CrosSettings::Get(), clock),
1355       pref_service_(pref_service),
1356       firmware_fetch_error_(kFirmwareNotInitialized),
1357       volume_info_fetcher_(volume_info_fetcher),
1358       cpu_statistics_fetcher_(cpu_statistics_fetcher),
1359       cpu_temp_fetcher_(cpu_temp_fetcher),
1360       android_status_fetcher_(android_status_fetcher),
1361       tpm_status_fetcher_(tpm_status_fetcher),
1362       emmc_lifetime_fetcher_(emmc_lifetime_fetcher),
1363       stateful_partition_info_fetcher_(stateful_partition_info_fetcher),
1364       cros_healthd_data_fetcher_(cros_healthd_data_fetcher),
1365       graphics_status_fetcher_(graphics_status_fetcher),
1366       crash_report_info_fetcher_(crash_report_info_fetcher),
1367       power_manager_(chromeos::PowerManagerClient::Get()),
1368       app_info_generator_(kMaxStoredPastActivityInterval, clock_) {
1369   // protected fields of `StatusCollector`.
1370   max_stored_past_activity_interval_ = kMaxStoredPastActivityInterval;
1371   max_stored_future_activity_interval_ = kMaxStoredFutureActivityInterval;
1372 
1373   // Get the task runner of the current thread, so we can queue status responses
1374   // on this thread.
1375   CHECK(base::SequencedTaskRunnerHandle::IsSet());
1376   task_runner_ = base::SequencedTaskRunnerHandle::Get();
1377 
1378   if (volume_info_fetcher_.is_null())
1379     volume_info_fetcher_ = base::Bind(&GetVolumeInfo);
1380 
1381   if (cpu_statistics_fetcher_.is_null())
1382     cpu_statistics_fetcher_ = base::Bind(&ReadCPUStatistics);
1383 
1384   if (cpu_temp_fetcher_.is_null())
1385     cpu_temp_fetcher_ = base::Bind(&ReadCPUTempInfo);
1386 
1387   if (android_status_fetcher_.is_null())
1388     android_status_fetcher_ = base::Bind(&ReadAndroidStatus);
1389 
1390   if (tpm_status_fetcher_.is_null())
1391     tpm_status_fetcher_ = base::BindRepeating(&ReadTpmStatus);
1392 
1393   if (emmc_lifetime_fetcher_.is_null())
1394     emmc_lifetime_fetcher_ = base::BindRepeating(&ReadDiskLifeTimeEstimation);
1395 
1396   if (stateful_partition_info_fetcher_.is_null())
1397     stateful_partition_info_fetcher_ = base::Bind(&ReadStatefulPartitionInfo);
1398 
1399   if (cros_healthd_data_fetcher_.is_null()) {
1400     cros_healthd_data_fetcher_ =
1401         base::BindRepeating(&DeviceStatusCollector::FetchCrosHealthdData,
1402                             weak_factory_.GetWeakPtr());
1403   }
1404 
1405   if (graphics_status_fetcher_.is_null())
1406     graphics_status_fetcher_ = base::BindRepeating(&FetchGraphicsStatus);
1407 
1408   if (crash_report_info_fetcher_.is_null())
1409     crash_report_info_fetcher_ = base::BindRepeating(&ReadCrashReportInfo);
1410 
1411   idle_poll_timer_.Start(FROM_HERE, kIdlePollInterval, this,
1412                          &DeviceStatusCollector::CheckIdleState);
1413   resource_usage_sampling_timer_.Start(
1414       FROM_HERE, TimeDelta::FromSeconds(kResourceUsageSampleIntervalSeconds),
1415       this, &DeviceStatusCollector::SampleResourceUsage);
1416 
1417   // Watch for changes to the individual policies that control what the status
1418   // reports contain.
1419   base::Closure callback = base::Bind(
1420       &DeviceStatusCollector::UpdateReportingSettings, base::Unretained(this));
1421   version_info_subscription_ = cros_settings_->AddSettingsObserver(
1422       chromeos::kReportDeviceVersionInfo, callback);
1423   activity_times_subscription_ = cros_settings_->AddSettingsObserver(
1424       chromeos::kReportDeviceActivityTimes, callback);
1425   boot_mode_subscription_ = cros_settings_->AddSettingsObserver(
1426       chromeos::kReportDeviceBootMode, callback);
1427   network_interfaces_subscription_ = cros_settings_->AddSettingsObserver(
1428       chromeos::kReportDeviceNetworkInterfaces, callback);
1429   users_subscription_ = cros_settings_->AddSettingsObserver(
1430       chromeos::kReportDeviceUsers, callback);
1431   hardware_status_subscription_ = cros_settings_->AddSettingsObserver(
1432       chromeos::kReportDeviceHardwareStatus, callback);
1433   session_status_subscription_ = cros_settings_->AddSettingsObserver(
1434       chromeos::kReportDeviceSessionStatus, callback);
1435   os_update_status_subscription_ = cros_settings_->AddSettingsObserver(
1436       chromeos::kReportOsUpdateStatus, callback);
1437   running_kiosk_app_subscription_ = cros_settings_->AddSettingsObserver(
1438       chromeos::kReportRunningKioskApp, callback);
1439   power_status_subscription_ = cros_settings_->AddSettingsObserver(
1440       chromeos::kReportDevicePowerStatus, callback);
1441   storage_status_subscription_ = cros_settings_->AddSettingsObserver(
1442       chromeos::kReportDeviceStorageStatus, callback);
1443   board_status_subscription_ = cros_settings_->AddSettingsObserver(
1444       chromeos::kReportDeviceBoardStatus, callback);
1445   cpu_info_subscription_ = cros_settings_->AddSettingsObserver(
1446       chromeos::kReportDeviceCpuInfo, callback);
1447   graphics_status_subscription_ = cros_settings_->AddSettingsObserver(
1448       chromeos::kReportDeviceGraphicsStatus, callback);
1449   timezone_info_subscription_ = cros_settings_->AddSettingsObserver(
1450       chromeos::kReportDeviceTimezoneInfo, callback);
1451   memory_info_subscription_ = cros_settings_->AddSettingsObserver(
1452       chromeos::kReportDeviceMemoryInfo, callback);
1453   backlight_info_subscription_ = cros_settings_->AddSettingsObserver(
1454       chromeos::kReportDeviceBacklightInfo, callback);
1455   crash_report_info_subscription_ = cros_settings_->AddSettingsObserver(
1456       chromeos::kReportDeviceCrashReportInfo, callback);
1457   bluetooth_info_subscription_ = cros_settings_->AddSettingsObserver(
1458       chromeos::kReportDeviceBluetoothInfo, callback);
1459   fan_info_subscription_ = cros_settings_->AddSettingsObserver(
1460       chromeos::kReportDeviceFanInfo, callback);
1461   vpd_info_subscription_ = cros_settings_->AddSettingsObserver(
1462       chromeos::kReportDeviceVpdInfo, callback);
1463   app_info_subscription_ = cros_settings_->AddSettingsObserver(
1464       chromeos::kReportDeviceAppInfo, callback);
1465   system_info_subscription_ = cros_settings_->AddSettingsObserver(
1466       chromeos::kReportDeviceSystemInfo, callback);
1467   stats_reporting_pref_subscription_ = cros_settings_->AddSettingsObserver(
1468       chromeos::kStatsReportingPref, callback);
1469 
1470   affiliated_session_service_.AddObserver(&app_info_generator_);
1471 
1472   power_manager_->AddObserver(this);
1473 
1474   // Fetch the current values of the policies.
1475   UpdateReportingSettings();
1476 
1477   // Get the OS, firmware, and TPM version info.
1478   base::ThreadPool::PostTaskAndReplyWithResult(
1479       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
1480       base::BindOnce(&chromeos::version_loader::GetVersion,
1481                      chromeos::version_loader::VERSION_FULL),
1482       base::BindOnce(&DeviceStatusCollector::OnOSVersion,
1483                      weak_factory_.GetWeakPtr()));
1484   base::ThreadPool::PostTaskAndReplyWithResult(
1485       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
1486       base::BindOnce(&ReadFirmwareVersion),
1487       base::BindOnce(&DeviceStatusCollector::OnOSFirmware,
1488                      weak_factory_.GetWeakPtr()));
1489   chromeos::tpm_util::GetTpmVersion(base::BindOnce(
1490       &DeviceStatusCollector::OnTpmVersion, weak_factory_.GetWeakPtr()));
1491 
1492   pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
1493   pref_change_registrar_->Init(pref_service_);
1494   pref_change_registrar_->Add(
1495       prefs::kReportingUsers,
1496       base::BindRepeating(&DeviceStatusCollector::ReportingUsersChanged,
1497                           weak_factory_.GetWeakPtr()));
1498 
1499   DCHECK(pref_service_->GetInitializationStatus() !=
1500          PrefService::INITIALIZATION_STATUS_WAITING);
1501   activity_storage_ = std::make_unique<EnterpriseActivityStorage>(
1502       pref_service_, prefs::kDeviceActivityTimes);
1503 }
1504 
DeviceStatusCollector(PrefService * pref_service,chromeos::system::StatisticsProvider * provider)1505 DeviceStatusCollector::DeviceStatusCollector(
1506     PrefService* pref_service,
1507     chromeos::system::StatisticsProvider* provider)
1508     : DeviceStatusCollector(
1509           pref_service,
1510           provider,
1511           DeviceStatusCollector::VolumeInfoFetcher(),
1512           DeviceStatusCollector::CPUStatisticsFetcher(),
1513           DeviceStatusCollector::CPUTempFetcher(),
1514           StatusCollector::AndroidStatusFetcher(),
1515           DeviceStatusCollector::TpmStatusFetcher(),
1516           DeviceStatusCollector::EMMCLifetimeFetcher(),
1517           DeviceStatusCollector::StatefulPartitionInfoFetcher(),
1518           DeviceStatusCollector::CrosHealthdDataFetcher(),
1519           DeviceStatusCollector::GraphicsStatusFetcher(),
1520           DeviceStatusCollector::CrashReportInfoFetcher()) {}
1521 
~DeviceStatusCollector()1522 DeviceStatusCollector::~DeviceStatusCollector() {
1523   power_manager_->RemoveObserver(this);
1524   affiliated_session_service_.RemoveObserver(&app_info_generator_);
1525 }
1526 
1527 // static
1528 constexpr base::TimeDelta DeviceStatusCollector::kIdlePollInterval;
1529 
1530 // static
RegisterPrefs(PrefRegistrySimple * registry)1531 void DeviceStatusCollector::RegisterPrefs(PrefRegistrySimple* registry) {
1532   registry->RegisterDictionaryPref(prefs::kDeviceActivityTimes);
1533 }
1534 
CheckIdleState()1535 void DeviceStatusCollector::CheckIdleState() {
1536   ProcessIdleState(ui::CalculateIdleState(kIdleStateThresholdSeconds));
1537 }
1538 
UpdateReportingSettings()1539 void DeviceStatusCollector::UpdateReportingSettings() {
1540   // Attempt to fetch the current value of the reporting settings.
1541   // If trusted values are not available, register this function to be called
1542   // back when they are available.
1543   if (chromeos::CrosSettingsProvider::TRUSTED !=
1544       cros_settings_->PrepareTrustedValues(
1545           base::BindOnce(&DeviceStatusCollector::UpdateReportingSettings,
1546                          weak_factory_.GetWeakPtr()))) {
1547     return;
1548   }
1549 
1550   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceVersionInfo,
1551                                   &report_version_info_)) {
1552     report_version_info_ = true;
1553   }
1554   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceActivityTimes,
1555                                   &report_activity_times_)) {
1556     report_activity_times_ = true;
1557   }
1558   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceBootMode,
1559                                   &report_boot_mode_)) {
1560     report_boot_mode_ = true;
1561   }
1562   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceSessionStatus,
1563                                   &report_kiosk_session_status_)) {
1564     report_kiosk_session_status_ = true;
1565   }
1566   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceNetworkInterfaces,
1567                                   &report_network_interfaces_)) {
1568     report_network_interfaces_ = true;
1569   }
1570   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceUsers,
1571                                   &report_users_)) {
1572     report_users_ = true;
1573   }
1574   const bool already_reporting_hardware_status = report_hardware_status_;
1575   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceHardwareStatus,
1576                                   &report_hardware_status_)) {
1577     report_hardware_status_ = true;
1578   }
1579   if (!cros_settings_->GetBoolean(chromeos::kReportDevicePowerStatus,
1580                                   &report_power_status_)) {
1581     report_power_status_ = false;
1582   }
1583   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceStorageStatus,
1584                                   &report_storage_status_)) {
1585     report_storage_status_ = false;
1586   }
1587   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceBoardStatus,
1588                                   &report_board_status_)) {
1589     report_board_status_ = false;
1590   }
1591   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceCpuInfo,
1592                                   &report_cpu_info_)) {
1593     report_cpu_info_ = false;
1594   }
1595   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceGraphicsStatus,
1596                                   &report_graphics_status_)) {
1597     report_graphics_status_ = false;
1598   }
1599   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceTimezoneInfo,
1600                                   &report_timezone_info_)) {
1601     report_timezone_info_ = false;
1602   }
1603   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceMemoryInfo,
1604                                   &report_memory_info_)) {
1605     report_memory_info_ = false;
1606   }
1607   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceBacklightInfo,
1608                                   &report_backlight_info_)) {
1609     report_backlight_info_ = false;
1610   }
1611   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceCrashReportInfo,
1612                                   &report_crash_report_info_)) {
1613     report_crash_report_info_ = false;
1614   }
1615   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceBluetoothInfo,
1616                                   &report_bluetooth_info_)) {
1617     report_bluetooth_info_ = false;
1618   }
1619   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceSystemInfo,
1620                                   &report_system_info_)) {
1621     report_system_info_ = false;
1622   }
1623   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceFanInfo,
1624                                   &report_fan_info_)) {
1625     report_fan_info_ = false;
1626   }
1627   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceVpdInfo,
1628                                   &report_vpd_info_)) {
1629     report_vpd_info_ = false;
1630   }
1631   report_app_info_ = false;
1632   if (!cros_settings_->GetBoolean(chromeos::kReportDeviceAppInfo,
1633                                   &report_app_info_)) {
1634     report_app_info_ = false;
1635   }
1636   app_info_generator_.OnReportingChanged(report_app_info_);
1637   if (!cros_settings_->GetBoolean(chromeos::kStatsReportingPref,
1638                                   &stat_reporting_pref_)) {
1639     stat_reporting_pref_ = false;
1640   }
1641 
1642   if (!report_hardware_status_) {
1643     ClearCachedResourceUsage();
1644   } else if (!already_reporting_hardware_status) {
1645     // Turning on hardware status reporting - fetch an initial sample
1646     // immediately instead of waiting for the sampling timer to fire.
1647     SampleResourceUsage();
1648   }
1649 
1650   // Os update status and running kiosk app reporting are disabled by default.
1651   if (!cros_settings_->GetBoolean(chromeos::kReportOsUpdateStatus,
1652                                   &report_os_update_status_)) {
1653     report_os_update_status_ = false;
1654   }
1655   if (!cros_settings_->GetBoolean(chromeos::kReportRunningKioskApp,
1656                                   &report_running_kiosk_app_)) {
1657     report_running_kiosk_app_ = false;
1658   }
1659 }
1660 
ClearCachedResourceUsage()1661 void DeviceStatusCollector::ClearCachedResourceUsage() {
1662   resource_usage_.clear();
1663   last_cpu_active_ = 0;
1664   last_cpu_idle_ = 0;
1665 }
1666 
ProcessIdleState(ui::IdleState state)1667 void DeviceStatusCollector::ProcessIdleState(ui::IdleState state) {
1668   // Do nothing if device activity reporting is disabled.
1669   if (!report_activity_times_)
1670     return;
1671 
1672   Time now = clock_->Now();
1673 
1674   // For kiosk apps we report total uptime instead of active time.
1675   if (state == ui::IDLE_STATE_ACTIVE || IsKioskApp()) {
1676     std::string user_email = GetUserForActivityReporting();
1677     // If it's been too long since the last report, or if the activity is
1678     // negative (which can happen when the clock changes), assume a single
1679     // interval of activity.
1680     TimeDelta active_seconds = now - last_idle_check_;
1681     Time start;
1682     if (active_seconds < base::TimeDelta::FromSeconds(0) ||
1683         active_seconds >= 2 * kIdlePollInterval || last_idle_check_.is_null()) {
1684       start = now - kIdlePollInterval;
1685     } else {
1686       start = last_idle_check_;
1687     }
1688     activity_storage_->AddActivityPeriod(start, now, user_email);
1689 
1690     activity_storage_->PruneActivityPeriods(
1691         now, max_stored_past_activity_interval_,
1692         max_stored_future_activity_interval_);
1693   }
1694   last_idle_check_ = now;
1695 }
1696 
PowerChanged(const power_manager::PowerSupplyProperties & prop)1697 void DeviceStatusCollector::PowerChanged(
1698     const power_manager::PowerSupplyProperties& prop) {
1699   if (!power_status_callback_.is_null())
1700     std::move(power_status_callback_).Run(prop);
1701 }
1702 
SampleResourceUsage()1703 void DeviceStatusCollector::SampleResourceUsage() {
1704   // Results must be written in the creation thread since that's where they
1705   // are read from in the Get*StatusAsync methods.
1706   DCHECK(thread_checker_.CalledOnValidThread());
1707 
1708   // If hardware reporting has been disabled, do nothing here.
1709   if (!report_hardware_status_)
1710     return;
1711 
1712   // Call out to the blocking pool to sample CPU stats.
1713   base::ThreadPool::PostTaskAndReplyWithResult(
1714       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
1715       base::BindOnce(cpu_statistics_fetcher_),
1716       base::BindOnce(&DeviceStatusCollector::ReceiveCPUStatistics,
1717                      weak_factory_.GetWeakPtr()));
1718 }
1719 
ReceiveCPUStatistics(const std::string & stats)1720 void DeviceStatusCollector::ReceiveCPUStatistics(const std::string& stats) {
1721   int cpu_usage_percent = 0;
1722   if (stats.empty()) {
1723     DLOG(WARNING) << "Unable to read CPU statistics";
1724   } else {
1725     // Parse the data from /proc/stat, whose format is defined at
1726     // https://www.kernel.org/doc/Documentation/filesystems/proc.txt.
1727     //
1728     // The CPU usage values in /proc/stat are measured in the imprecise unit
1729     // "jiffies", but we just care about the relative magnitude of "active" vs
1730     // "idle" so the exact value of a jiffy is irrelevant.
1731     //
1732     // An example value for this line:
1733     //
1734     // cpu 123 456 789 012 345 678
1735     //
1736     // We only care about the first four numbers: user_time, nice_time,
1737     // sys_time, and idle_time.
1738     uint64_t user = 0, nice = 0, system = 0, idle = 0;
1739     int vals = sscanf(stats.c_str(),
1740                       "cpu %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &user,
1741                       &nice, &system, &idle);
1742     DCHECK_EQ(4, vals);
1743 
1744     // The values returned from /proc/stat are cumulative totals, so calculate
1745     // the difference between the last sample and this one.
1746     uint64_t active = user + nice + system;
1747     uint64_t total = active + idle;
1748     uint64_t last_total = last_cpu_active_ + last_cpu_idle_;
1749     DCHECK_GE(active, last_cpu_active_);
1750     DCHECK_GE(idle, last_cpu_idle_);
1751     DCHECK_GE(total, last_total);
1752 
1753     if ((total - last_total) > 0) {
1754       cpu_usage_percent =
1755           (100 * (active - last_cpu_active_)) / (total - last_total);
1756     }
1757     last_cpu_active_ = active;
1758     last_cpu_idle_ = idle;
1759   }
1760 
1761   DCHECK_LE(cpu_usage_percent, 100);
1762 
1763   // This timestamp is used in both ResourceUsage and SampledData for CPU
1764   // termporary, which is expected to be same according to existing
1765   // implementation.
1766   const base::Time timestamp = base::Time::Now();
1767 
1768   ResourceUsage usage = {cpu_usage_percent,
1769                          base::SysInfo::AmountOfAvailablePhysicalMemory(),
1770                          timestamp};
1771 
1772   resource_usage_.push_back(usage);
1773 
1774   // If our cache of samples is full, throw out old samples to make room for new
1775   // sample.
1776   if (resource_usage_.size() > kMaxResourceUsageSamples)
1777     resource_usage_.pop_front();
1778 
1779   std::unique_ptr<SampledData> sample = std::make_unique<SampledData>();
1780   sample->timestamp = timestamp;
1781 
1782   if (report_power_status_) {
1783     cros_healthd_data_fetcher_.Run(CrosHealthdCollectionMode::kBattery,
1784                                    base::DoNothing());
1785   } else {
1786     base::ThreadPool::PostTaskAndReplyWithResult(
1787         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
1788         base::BindOnce(&InvokeCpuTempFetcher, cpu_temp_fetcher_),
1789         base::BindOnce(&DeviceStatusCollector::ReceiveCPUTemperature,
1790                        weak_factory_.GetWeakPtr(), std::move(sample),
1791                        SamplingCallback()));
1792   }
1793 }
1794 
SampleProbeData(std::unique_ptr<SampledData> sample,SamplingProbeResultCallback callback,chromeos::cros_healthd::mojom::TelemetryInfoPtr result)1795 void DeviceStatusCollector::SampleProbeData(
1796     std::unique_ptr<SampledData> sample,
1797     SamplingProbeResultCallback callback,
1798     chromeos::cros_healthd::mojom::TelemetryInfoPtr result) {
1799   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1800 
1801   if (result.is_null())
1802     return;
1803 
1804   const auto& battery_result = result->battery_result;
1805   if (!battery_result.is_null()) {
1806     if (battery_result->is_error()) {
1807       LOG(ERROR) << "cros_healthd: Error getting battery info: "
1808                  << battery_result->get_error()->msg;
1809     } else if (!battery_result->get_battery_info().is_null()) {
1810       const auto& battery = battery_result->get_battery_info();
1811       enterprise_management::BatterySample battery_sample;
1812       battery_sample.set_timestamp(sample->timestamp.ToJavaTime());
1813       // Convert V to mV:
1814       battery_sample.set_voltage(std::lround(battery->voltage_now * 1000));
1815       // Convert Ah to mAh:
1816       battery_sample.set_remaining_capacity(
1817           std::lround(battery->charge_now * 1000));
1818       // Convert A to mA:
1819       battery_sample.set_current(std::lround(battery->current_now * 1000));
1820       battery_sample.set_status(battery->status);
1821       // Convert 0.1 Kelvin to Celsius:
1822       if (battery->temperature) {
1823         battery_sample.set_temperature(
1824             (battery->temperature->value - kZeroCInDeciKelvin) / 10);
1825       }
1826       sample->battery_samples[battery->model_name] = battery_sample;
1827     }
1828   }
1829 
1830   SamplingCallback completion_callback;
1831   if (!callback.is_null()) {
1832     completion_callback =
1833         base::BindOnce(std::move(callback), std::move(result));
1834   }
1835 
1836   // PowerManagerClient::Observer::PowerChanged can be called as a result of
1837   // power_manager_->RequestStatusUpdate() as well as for other reasons,
1838   // so we store power_status_callback_ here instead of triggering
1839   // SampleDischargeRate from PowerChanged().
1840   DCHECK(power_status_callback_.is_null());  // Previous sampling is completed.
1841 
1842   power_status_callback_ = base::BindOnce(
1843       &DeviceStatusCollector::SampleDischargeRate, weak_factory_.GetWeakPtr(),
1844       std::move(sample), std::move(completion_callback));
1845   power_manager_->RequestStatusUpdate();
1846 }
1847 
SampleDischargeRate(std::unique_ptr<SampledData> sample,SamplingCallback callback,const power_manager::PowerSupplyProperties & prop)1848 void DeviceStatusCollector::SampleDischargeRate(
1849     std::unique_ptr<SampledData> sample,
1850     SamplingCallback callback,
1851     const power_manager::PowerSupplyProperties& prop) {
1852   if (prop.has_battery_discharge_rate()) {
1853     int discharge_rate_mW =
1854         static_cast<int>(prop.battery_discharge_rate() * 1000);
1855     for (auto it = sample->battery_samples.begin();
1856          it != sample->battery_samples.end(); it++) {
1857       it->second.set_discharge_rate(discharge_rate_mW);
1858     }
1859   }
1860 
1861   if (prop.has_battery_percent() && prop.battery_percent() >= 0) {
1862     int percent = static_cast<int>(prop.battery_percent());
1863     for (auto it = sample->battery_samples.begin();
1864          it != sample->battery_samples.end(); it++) {
1865       it->second.set_charge_rate(percent);
1866     }
1867   }
1868 
1869   base::ThreadPool::PostTaskAndReplyWithResult(
1870       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
1871       base::BindOnce(&InvokeCpuTempFetcher, cpu_temp_fetcher_),
1872       base::BindOnce(&DeviceStatusCollector::ReceiveCPUTemperature,
1873                      weak_factory_.GetWeakPtr(), std::move(sample),
1874                      std::move(callback)));
1875 }
1876 
ReceiveCPUTemperature(std::unique_ptr<SampledData> sample,SamplingCallback callback,std::vector<em::CPUTempInfo> measurements)1877 void DeviceStatusCollector::ReceiveCPUTemperature(
1878     std::unique_ptr<SampledData> sample,
1879     SamplingCallback callback,
1880     std::vector<em::CPUTempInfo> measurements) {
1881   auto timestamp = sample->timestamp.ToJavaTime();
1882   for (const auto& measurement : measurements) {
1883     sample->cpu_samples[measurement.cpu_label()] = measurement;
1884     sample->cpu_samples[measurement.cpu_label()].set_timestamp(timestamp);
1885   }
1886   AddDataSample(std::move(sample), std::move(callback));
1887 }
1888 
AddDataSample(std::unique_ptr<SampledData> sample,SamplingCallback callback)1889 void DeviceStatusCollector::AddDataSample(std::unique_ptr<SampledData> sample,
1890                                           SamplingCallback callback) {
1891   sampled_data_.push_back(std::move(sample));
1892 
1893   // If our cache of samples is full, throw out old samples to make room for new
1894   // sample.
1895   if (sampled_data_.size() > kMaxResourceUsageSamples)
1896     sampled_data_.pop_front();
1897   // We have two code paths that end here. One is regular sampling, that does
1898   // not have final callback, and full report request, that would use callback
1899   // to receive ProbeResponse.
1900   if (!callback.is_null())
1901     std::move(callback).Run();
1902 }
1903 
FetchCrosHealthdData(CrosHealthdCollectionMode mode,CrosHealthdDataReceiver callback)1904 void DeviceStatusCollector::FetchCrosHealthdData(
1905     CrosHealthdCollectionMode mode,
1906     CrosHealthdDataReceiver callback) {
1907   using chromeos::cros_healthd::mojom::ProbeCategoryEnum;
1908 
1909   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1910   std::vector<ProbeCategoryEnum> categories_to_probe;
1911   SamplingProbeResultCallback completion_callback;
1912   switch (mode) {
1913     case CrosHealthdCollectionMode::kFull: {
1914       if (report_vpd_info_ || report_system_info_)
1915         categories_to_probe.push_back(ProbeCategoryEnum::kSystem);
1916       if (report_storage_status_) {
1917         categories_to_probe.push_back(
1918             ProbeCategoryEnum::kNonRemovableBlockDevices);
1919       }
1920       if (report_power_status_)
1921         categories_to_probe.push_back(ProbeCategoryEnum::kBattery);
1922       if (report_cpu_info_)
1923         categories_to_probe.push_back(ProbeCategoryEnum::kCpu);
1924       if (report_timezone_info_)
1925         categories_to_probe.push_back(ProbeCategoryEnum::kTimezone);
1926       if (report_memory_info_)
1927         categories_to_probe.push_back(ProbeCategoryEnum::kMemory);
1928       if (report_backlight_info_)
1929         categories_to_probe.push_back(ProbeCategoryEnum::kBacklight);
1930       if (report_fan_info_)
1931         categories_to_probe.push_back(ProbeCategoryEnum::kFan);
1932       if (report_bluetooth_info_)
1933         categories_to_probe.push_back(ProbeCategoryEnum::kBluetooth);
1934 
1935       completion_callback =
1936           base::BindOnce(&DeviceStatusCollector::OnProbeDataFetched,
1937                          weak_factory_.GetWeakPtr(), std::move(callback));
1938       break;
1939     }
1940     case CrosHealthdCollectionMode::kBattery: {
1941       categories_to_probe.push_back(ProbeCategoryEnum::kBattery);
1942       break;
1943     }
1944   }
1945 
1946   auto sample = std::make_unique<SampledData>();
1947   sample->timestamp = base::Time::Now();
1948 
1949   chromeos::cros_healthd::ServiceConnection::GetInstance()->ProbeTelemetryInfo(
1950       categories_to_probe,
1951       base::BindOnce(&DeviceStatusCollector::SampleProbeData,
1952                      weak_factory_.GetWeakPtr(), std::move(sample),
1953                      std::move(completion_callback)));
1954 }
1955 
OnProbeDataFetched(CrosHealthdDataReceiver callback,chromeos::cros_healthd::mojom::TelemetryInfoPtr reply)1956 void DeviceStatusCollector::OnProbeDataFetched(
1957     CrosHealthdDataReceiver callback,
1958     chromeos::cros_healthd::mojom::TelemetryInfoPtr reply) {
1959   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1960   std::move(callback).Run(std::move(reply), sampled_data_);
1961 }
1962 
ShouldFetchCrosHealthdData() const1963 bool DeviceStatusCollector::ShouldFetchCrosHealthdData() const {
1964   return report_vpd_info_ || report_power_status_ || report_storage_status_ ||
1965          report_cpu_info_ || report_timezone_info_ || report_memory_info_ ||
1966          report_backlight_info_ || report_fan_info_ || report_bluetooth_info_ ||
1967          report_system_info_;
1968 }
1969 
ReportingUsersChanged()1970 void DeviceStatusCollector::ReportingUsersChanged() {
1971   std::vector<std::string> reporting_users;
1972   for (auto& value :
1973        pref_service_->GetList(prefs::kReportingUsers)->GetList()) {
1974     if (value.is_string())
1975       reporting_users.push_back(value.GetString());
1976   }
1977 
1978   activity_storage_->FilterActivityPeriodsByUsers(reporting_users);
1979 }
1980 
GetUserForActivityReporting() const1981 std::string DeviceStatusCollector::GetUserForActivityReporting() const {
1982   // Primary user is used as unique identifier of a single session, even for
1983   // multi-user sessions.
1984   const user_manager::User* const primary_user =
1985       user_manager::UserManager::Get()->GetPrimaryUser();
1986   if (!primary_user || !primary_user->HasGaiaAccount())
1987     return std::string();
1988 
1989   // Report only affiliated users for enterprise reporting.
1990   std::string primary_user_email = primary_user->GetAccountId().GetUserEmail();
1991   if (!chromeos::ChromeUserManager::Get()->ShouldReportUser(
1992           primary_user_email)) {
1993     return std::string();
1994   }
1995   return primary_user_email;
1996 }
1997 
IncludeEmailsInActivityReports() const1998 bool DeviceStatusCollector::IncludeEmailsInActivityReports() const {
1999   // Including the users' email addresses in enterprise reporting depends on the
2000   // |kReportDeviceUsers| preference.
2001   return report_users_;
2002 }
2003 
GetActivityTimes(em::DeviceStatusReportRequest * status)2004 bool DeviceStatusCollector::GetActivityTimes(
2005     em::DeviceStatusReportRequest* status) {
2006   // If user reporting is off, data should be aggregated per day.
2007   // Signed-in user is reported in non-enterprise reporting.
2008   activity_storage_->RemoveOverlappingActivityPeriods();
2009   auto activity_times = activity_storage_->GetFilteredActivityPeriods(
2010       !IncludeEmailsInActivityReports());
2011 
2012   bool anything_reported = false;
2013   for (const auto& activity_pair : activity_times) {
2014     const auto& user_email = activity_pair.first;
2015     const auto& activity_periods = activity_pair.second;
2016 
2017     for (const auto& activity_period : activity_periods) {
2018       // This is correct even when there are leap seconds, because when a leap
2019       // second occurs, two consecutive seconds have the same timestamp.
2020       int64_t end_timestamp =
2021           activity_period.start_timestamp() + Time::kMillisecondsPerDay;
2022 
2023       em::ActiveTimePeriod* active_period = status->add_active_periods();
2024       em::TimePeriod* period = active_period->mutable_time_period();
2025       period->set_start_timestamp(activity_period.start_timestamp());
2026       period->set_end_timestamp(end_timestamp);
2027       active_period->set_active_duration(activity_period.end_timestamp() -
2028                                          activity_period.start_timestamp());
2029       // Report user email only if users reporting is turned on.
2030       if (!user_email.empty()) {
2031         active_period->set_user_email(user_email);
2032       }
2033       if (last_reported_end_timestamp_ < end_timestamp) {
2034         last_reported_end_timestamp_ = end_timestamp;
2035       }
2036       anything_reported = true;
2037     }
2038   }
2039   return anything_reported;
2040 }
2041 
GetVersionInfo(em::DeviceStatusReportRequest * status)2042 bool DeviceStatusCollector::GetVersionInfo(
2043     em::DeviceStatusReportRequest* status) {
2044   status->set_os_version(os_version_);
2045   status->set_browser_version(version_info::GetVersionNumber());
2046   status->set_channel(ConvertToProtoChannel(chrome::GetChannel()));
2047 
2048   // TODO(b/144081278): Remove when resolved.
2049   // When firmware version is not fetched, report error instead.
2050   status->set_firmware_version(
2051       !firmware_version_.empty() ? firmware_version_ : firmware_fetch_error_);
2052 
2053   em::TpmVersionInfo* const tpm_version_info =
2054       status->mutable_tpm_version_info();
2055   tpm_version_info->set_family(tpm_version_info_.family);
2056   tpm_version_info->set_spec_level(tpm_version_info_.spec_level);
2057   tpm_version_info->set_manufacturer(tpm_version_info_.manufacturer);
2058   tpm_version_info->set_tpm_model(tpm_version_info_.tpm_model);
2059   tpm_version_info->set_firmware_version(tpm_version_info_.firmware_version);
2060   tpm_version_info->set_vendor_specific(tpm_version_info_.vendor_specific);
2061 
2062   return true;
2063 }
2064 
GetWriteProtectSwitch(em::DeviceStatusReportRequest * status)2065 bool DeviceStatusCollector::GetWriteProtectSwitch(
2066     em::DeviceStatusReportRequest* status) {
2067   std::string firmware_write_protect;
2068   if (!statistics_provider_->GetMachineStatistic(
2069           chromeos::system::kFirmwareWriteProtectCurrentKey,
2070           &firmware_write_protect)) {
2071     // TODO(crbug.com/1123153): Remove logging after the bug is fixed.
2072     LOG(WARNING) << "Missing "
2073                  << chromeos::system::kFirmwareWriteProtectCurrentKey
2074                  << " statistics";
2075     return false;
2076   }
2077   // TODO(crbug.com/1123153): Remove logging after the bug is fixed.
2078   LOG(WARNING) << "Statistics "
2079                << chromeos::system::kFirmwareWriteProtectCurrentKey << ": "
2080                << firmware_write_protect;
2081 
2082   if (firmware_write_protect ==
2083       chromeos::system::kFirmwareWriteProtectCurrentValueOff) {
2084     status->set_write_protect_switch(false);
2085   } else if (firmware_write_protect ==
2086              chromeos::system::kFirmwareWriteProtectCurrentValueOn) {
2087     status->set_write_protect_switch(true);
2088   } else {
2089     return false;
2090   }
2091   return true;
2092 }
2093 
GetNetworkInterfaces(em::DeviceStatusReportRequest * status)2094 bool DeviceStatusCollector::GetNetworkInterfaces(
2095     em::DeviceStatusReportRequest* status) {
2096   // Maps shill device type strings to proto enum constants.
2097   static const struct {
2098     const char* type_string;
2099     em::NetworkInterface::NetworkDeviceType type_constant;
2100   } kDeviceTypeMap[] = {
2101       {
2102           shill::kTypeEthernet,
2103           em::NetworkInterface::TYPE_ETHERNET,
2104       },
2105       {
2106           shill::kTypeWifi,
2107           em::NetworkInterface::TYPE_WIFI,
2108       },
2109       {
2110           shill::kTypeCellular,
2111           em::NetworkInterface::TYPE_CELLULAR,
2112       },
2113   };
2114 
2115   // Maps shill device connection status to proto enum constants.
2116   static const struct {
2117     const char* state_string;
2118     em::NetworkState::ConnectionState state_constant;
2119   } kConnectionStateMap[] = {
2120       {shill::kStateIdle, em::NetworkState::IDLE},
2121       {shill::kStateCarrier, em::NetworkState::CARRIER},
2122       {shill::kStateAssociation, em::NetworkState::ASSOCIATION},
2123       {shill::kStateConfiguration, em::NetworkState::CONFIGURATION},
2124       {shill::kStateReady, em::NetworkState::READY},
2125       {shill::kStatePortal, em::NetworkState::PORTAL},
2126       {shill::kStateNoConnectivity, em::NetworkState::PORTAL},
2127       {shill::kStateRedirectFound, em::NetworkState::PORTAL},
2128       {shill::kStatePortalSuspected, em::NetworkState::PORTAL},
2129       {shill::kStateOffline, em::NetworkState::OFFLINE},
2130       {shill::kStateOnline, em::NetworkState::ONLINE},
2131       {shill::kStateDisconnect, em::NetworkState::DISCONNECT},
2132       {shill::kStateFailure, em::NetworkState::FAILURE},
2133       {shill::kStateActivationFailure, em::NetworkState::ACTIVATION_FAILURE},
2134   };
2135 
2136   chromeos::NetworkStateHandler::DeviceStateList device_list;
2137   chromeos::NetworkStateHandler* network_state_handler =
2138       chromeos::NetworkHandler::Get()->network_state_handler();
2139   network_state_handler->GetDeviceList(&device_list);
2140 
2141   bool anything_reported = false;
2142   chromeos::NetworkStateHandler::DeviceStateList::const_iterator device;
2143   for (device = device_list.begin(); device != device_list.end(); ++device) {
2144     // Determine the type enum constant for |device|.
2145     size_t type_idx = 0;
2146     for (; type_idx < base::size(kDeviceTypeMap); ++type_idx) {
2147       if ((*device)->type() == kDeviceTypeMap[type_idx].type_string)
2148         break;
2149     }
2150 
2151     // If the type isn't in |kDeviceTypeMap|, the interface is not relevant for
2152     // reporting. This filters out VPN devices.
2153     if (type_idx >= base::size(kDeviceTypeMap))
2154       continue;
2155 
2156     em::NetworkInterface* interface = status->add_network_interfaces();
2157     interface->set_type(kDeviceTypeMap[type_idx].type_constant);
2158     if (!(*device)->mac_address().empty())
2159       interface->set_mac_address((*device)->mac_address());
2160     if (!(*device)->meid().empty())
2161       interface->set_meid((*device)->meid());
2162     if (!(*device)->imei().empty())
2163       interface->set_imei((*device)->imei());
2164     if (!(*device)->path().empty())
2165       interface->set_device_path((*device)->path());
2166     anything_reported = true;
2167   }
2168 
2169   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
2170   const user_manager::User* const primary_user = user_manager->GetPrimaryUser();
2171   // Don't write network state for unaffiliated users or when no user is signed
2172   // in.
2173   if (!primary_user || !primary_user->IsAffiliated()) {
2174     return anything_reported;
2175   }
2176 
2177   // Walk the various networks and store their state in the status report.
2178   chromeos::NetworkStateHandler::NetworkStateList state_list;
2179   network_state_handler->GetNetworkListByType(
2180       chromeos::NetworkTypePattern::Default(),
2181       true,   // configured_only
2182       false,  // visible_only
2183       0,      // no limit to number of results
2184       &state_list);
2185 
2186   for (const chromeos::NetworkState* state : state_list) {
2187     // Determine the connection state and signal strength for |state|.
2188     em::NetworkState::ConnectionState connection_state_enum =
2189         em::NetworkState::UNKNOWN;
2190     const std::string connection_state_string(state->connection_state());
2191     for (size_t i = 0; i < base::size(kConnectionStateMap); ++i) {
2192       if (connection_state_string == kConnectionStateMap[i].state_string) {
2193         connection_state_enum = kConnectionStateMap[i].state_constant;
2194         break;
2195       }
2196     }
2197 
2198     // Copy fields from NetworkState into the status report.
2199     em::NetworkState* proto_state = status->add_network_states();
2200     proto_state->set_connection_state(connection_state_enum);
2201     anything_reported = true;
2202 
2203     // Report signal strength for wifi connections.
2204     if (state->type() == shill::kTypeWifi) {
2205       // If shill has provided a signal strength, convert it to dBm and store it
2206       // in the status report. A signal_strength() of 0 connotes "no signal"
2207       // rather than "really weak signal", so we only report signal strength if
2208       // it is non-zero.
2209       if (state->signal_strength()) {
2210         proto_state->set_signal_strength(
2211             ConvertWifiSignalStrength(state->signal_strength()));
2212       }
2213     }
2214 
2215     if (!state->device_path().empty())
2216       proto_state->set_device_path(state->device_path());
2217 
2218     std::string ip_address = state->GetIpAddress();
2219     if (!ip_address.empty())
2220       proto_state->set_ip_address(ip_address);
2221 
2222     std::string gateway = state->GetGateway();
2223     if (!gateway.empty())
2224       proto_state->set_gateway(gateway);
2225   }
2226   return anything_reported;
2227 }
2228 
GetUsers(em::DeviceStatusReportRequest * status)2229 bool DeviceStatusCollector::GetUsers(em::DeviceStatusReportRequest* status) {
2230   const user_manager::UserList& users =
2231       chromeos::ChromeUserManager::Get()->GetUsers();
2232 
2233   bool anything_reported = false;
2234   for (auto* user : users) {
2235     // Only users with gaia accounts (regular) are reported.
2236     if (!user->HasGaiaAccount())
2237       continue;
2238 
2239     em::DeviceUser* device_user = status->add_users();
2240     if (chromeos::ChromeUserManager::Get()->ShouldReportUser(
2241             user->GetAccountId().GetUserEmail())) {
2242       device_user->set_type(em::DeviceUser::USER_TYPE_MANAGED);
2243       device_user->set_email(user->GetAccountId().GetUserEmail());
2244     } else {
2245       device_user->set_type(em::DeviceUser::USER_TYPE_UNMANAGED);
2246       // Do not report the email address of unmanaged users.
2247     }
2248     anything_reported = true;
2249   }
2250   return anything_reported;
2251 }
2252 
GetHardwareStatus(scoped_refptr<DeviceStatusCollectorState> state)2253 bool DeviceStatusCollector::GetHardwareStatus(
2254     scoped_refptr<DeviceStatusCollectorState> state) {
2255   em::DeviceStatusReportRequest* status =
2256       state->response_params().device_status.get();
2257 
2258   // Sample disk volume info in a background thread.
2259   state->SampleVolumeInfo(volume_info_fetcher_);
2260 
2261   // Add CPU utilization and free RAM. Note that these stats are sampled in
2262   // regular intervals. Unlike CPU temp and volume info these are not one-time
2263   // sampled values, hence the difference in logic.
2264   status->set_system_ram_total(base::SysInfo::AmountOfPhysicalMemory());
2265   status->clear_cpu_utilization_infos();
2266   status->clear_system_ram_free_infos();
2267 
2268   // TODO(anqing): remove these two cleanup operations after fields
2269   // 'system_ram_free_samples' and 'cpu_utilization_pct_samples' are deprecated.
2270   status->clear_system_ram_free_samples();
2271   status->clear_cpu_utilization_pct_samples();
2272 
2273   for (const ResourceUsage& usage : resource_usage_) {
2274     const int64_t usage_timestamp = usage.timestamp.ToJavaTime();
2275 
2276     em::CpuUtilizationInfo* cpu_utilization_info =
2277         status->add_cpu_utilization_infos();
2278     cpu_utilization_info->set_cpu_utilization_pct(usage.cpu_usage_percent);
2279     cpu_utilization_info->set_timestamp(usage_timestamp);
2280 
2281     em::SystemFreeRamInfo* system_ram_free_info =
2282         status->add_system_ram_free_infos();
2283     system_ram_free_info->set_size_in_bytes(usage.bytes_of_ram_free);
2284     system_ram_free_info->set_timestamp(usage_timestamp);
2285 
2286     // TODO(anqing): remove these two assignment operations after fields
2287     // 'system_ram_free_samples' and 'cpu_utilization_pct_samples' are
2288     // deprecated.
2289     status->add_cpu_utilization_pct_samples(usage.cpu_usage_percent);
2290     status->add_system_ram_free_samples(usage.bytes_of_ram_free);
2291   }
2292 
2293   // Get the current device sound volume level.
2294   chromeos::CrasAudioHandler* audio_handler = chromeos::CrasAudioHandler::Get();
2295   status->set_sound_volume(audio_handler->GetOutputVolumePercent());
2296 
2297   // Fetch TPM status information on a background thread.
2298   state->FetchTpmStatus(tpm_status_fetcher_);
2299 
2300   // clear
2301   status->clear_cpu_temp_infos();
2302 
2303   if (report_storage_status_)
2304     state->FetchEMMCLifeTime(emmc_lifetime_fetcher_);
2305 
2306   if (ShouldFetchCrosHealthdData()) {
2307     state->FetchCrosHealthdData(cros_healthd_data_fetcher_, report_system_info_,
2308                                 report_vpd_info_);
2309   } else {
2310     // Sample CPU temperature in a background thread.
2311     state->SampleCPUTempInfo(cpu_temp_fetcher_);
2312   }
2313 
2314   // Fetch Stateful Partition Information on a background thread.
2315   state->FetchStatefulPartitionInfo(stateful_partition_info_fetcher_);
2316 
2317   return true;
2318 }
2319 
GetOsUpdateStatus(em::DeviceStatusReportRequest * status)2320 bool DeviceStatusCollector::GetOsUpdateStatus(
2321     em::DeviceStatusReportRequest* status) {
2322   const base::Version platform_version(GetPlatformVersion());
2323   if (!platform_version.IsValid())
2324     return false;
2325 
2326   const std::string required_platform_version_string =
2327       chromeos::KioskAppManager::Get()
2328           ->GetAutoLaunchAppRequiredPlatformVersion();
2329   em::OsUpdateStatus* os_update_status = status->mutable_os_update_status();
2330 
2331   const update_engine::StatusResult update_engine_status =
2332       chromeos::DBusThreadManager::Get()
2333           ->GetUpdateEngineClient()
2334           ->GetLastStatus();
2335 
2336   base::Optional<base::Version> required_platform_version;
2337 
2338   if (required_platform_version_string.empty()) {
2339     // If this is non-Kiosk session, the OS is considered as up-to-date if the
2340     // status of UpdateEngineClient is idle.
2341     if (update_engine_status.current_operation() ==
2342         update_engine::Operation::IDLE)
2343       required_platform_version = base::Version(platform_version);
2344   } else {
2345     // If this is Kiosk session, |required_platform_version| can be searched
2346     // from the KioskAppClient instance.
2347     required_platform_version = base::Version(required_platform_version_string);
2348     os_update_status->set_new_required_platform_version(
2349         required_platform_version->GetString());
2350   }
2351 
2352   // Get last reboot timestamp.
2353   const base::Time last_reboot_timestamp =
2354       base::Time::Now() - base::SysInfo::Uptime();
2355 
2356   os_update_status->set_last_reboot_timestamp(
2357       last_reboot_timestamp.ToJavaTime());
2358 
2359   // Get last check timestamp.
2360   // As the timestamp precision return from UpdateEngine is in seconds (see
2361   // time_t). It should be converted to milliseconds before being reported.
2362   const base::Time last_checked_timestamp =
2363       base::Time::FromTimeT(update_engine_status.last_checked_time());
2364 
2365   os_update_status->set_last_checked_timestamp(
2366       last_checked_timestamp.ToJavaTime());
2367 
2368   if (required_platform_version &&
2369       platform_version == *required_platform_version) {
2370     os_update_status->set_update_status(em::OsUpdateStatus::OS_UP_TO_DATE);
2371     return true;
2372   }
2373 
2374   if (update_engine_status.current_operation() ==
2375           update_engine::Operation::DOWNLOADING ||
2376       update_engine_status.current_operation() ==
2377           update_engine::Operation::VERIFYING ||
2378       update_engine_status.current_operation() ==
2379           update_engine::Operation::FINALIZING) {
2380     os_update_status->set_update_status(
2381         em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_IN_PROGRESS);
2382     os_update_status->set_new_platform_version(
2383         update_engine_status.new_version());
2384   } else if (update_engine_status.current_operation() ==
2385              update_engine::Operation::UPDATED_NEED_REBOOT) {
2386     os_update_status->set_update_status(
2387         em::OsUpdateStatus::OS_UPDATE_NEED_REBOOT);
2388     // Note the new_version could be a dummy "0.0.0.0" for some edge cases,
2389     // e.g. update engine is somehow restarted without a reboot.
2390     os_update_status->set_new_platform_version(
2391         update_engine_status.new_version());
2392   } else {
2393     os_update_status->set_update_status(
2394         em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_NOT_STARTED);
2395   }
2396 
2397   return true;
2398 }
2399 
GetRunningKioskApp(em::DeviceStatusReportRequest * status)2400 bool DeviceStatusCollector::GetRunningKioskApp(
2401     em::DeviceStatusReportRequest* status) {
2402   // Must be on creation thread since some stats are written to in that thread
2403   // and accessing them from another thread would lead to race conditions.
2404   DCHECK(thread_checker_.CalledOnValidThread());
2405 
2406   std::unique_ptr<const DeviceLocalAccount> account =
2407       GetAutoLaunchedKioskSessionInfo();
2408   // Only generate running kiosk app reports if we are in an auto-launched kiosk
2409   // session.
2410   if (!account)
2411     return false;
2412 
2413   em::AppStatus* running_kiosk_app = status->mutable_running_kiosk_app();
2414   if (account->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP) {
2415     running_kiosk_app->set_app_id(account->kiosk_app_id);
2416 
2417     const std::string app_version = GetAppVersion(account->kiosk_app_id);
2418     if (app_version.empty()) {
2419       DLOG(ERROR) << "Unable to get version for extension: "
2420                   << account->kiosk_app_id;
2421     } else {
2422       running_kiosk_app->set_extension_version(app_version);
2423     }
2424 
2425     chromeos::KioskAppManager::App app_info;
2426     if (chromeos::KioskAppManager::Get()->GetApp(account->kiosk_app_id,
2427                                                  &app_info)) {
2428       running_kiosk_app->set_required_platform_version(
2429           app_info.required_platform_version);
2430     }
2431   } else if (account->type == policy::DeviceLocalAccount::TYPE_ARC_KIOSK_APP) {
2432     // Use package name as app ID for ARC Kiosks.
2433     running_kiosk_app->set_app_id(account->arc_kiosk_app_info.package_name());
2434   } else if (account->type == policy::DeviceLocalAccount::TYPE_WEB_KIOSK_APP) {
2435     running_kiosk_app->set_app_id(account->web_kiosk_app_info.url());
2436   } else {
2437     NOTREACHED();
2438   }
2439   return true;
2440 }
2441 
GetGraphicsStatus(scoped_refptr<DeviceStatusCollectorState> state)2442 bool DeviceStatusCollector::GetGraphicsStatus(
2443     scoped_refptr<DeviceStatusCollectorState> state) {
2444   // Fetch Graphics status on a background thread.
2445   state->FetchGraphicsStatus(graphics_status_fetcher_);
2446 
2447   return true;
2448 }
2449 
GetCrashReportInfo(scoped_refptr<DeviceStatusCollectorState> state)2450 bool DeviceStatusCollector::GetCrashReportInfo(
2451     scoped_refptr<DeviceStatusCollectorState> state) {
2452   state->FetchCrashReportInfo(crash_report_info_fetcher_);
2453 
2454   return true;
2455 }
2456 
GetStatusAsync(const StatusCollectorCallback & response)2457 void DeviceStatusCollector::GetStatusAsync(
2458     const StatusCollectorCallback& response) {
2459   last_requested_ = clock_->Now();
2460 
2461   app_info_generator_.OnWillReport();
2462 
2463   // Must be on creation thread since some stats are written to in that thread
2464   // and accessing them from another thread would lead to race conditions.
2465   DCHECK(thread_checker_.CalledOnValidThread());
2466   // Some of the data we're collecting is gathered in background threads.
2467   // This object keeps track of the state of each async request.
2468   scoped_refptr<DeviceStatusCollectorState> state(
2469       new DeviceStatusCollectorState(task_runner_, response));
2470   // Gather device status (might queue some async queries)
2471   GetDeviceStatus(state);
2472 
2473   // Gather session status (might queue some async queries)
2474   GetSessionStatus(state);
2475 
2476   // If there are no outstanding async queries, e.g. from GetHardwareStatus(),
2477   // the destructor of |state| calls |response|. If there are async queries, the
2478   // queries hold references to |state|, so that |state| is only destroyed when
2479   // the last async query has finished.
2480 }
2481 
GetDeviceStatus(scoped_refptr<DeviceStatusCollectorState> state)2482 void DeviceStatusCollector::GetDeviceStatus(
2483     scoped_refptr<DeviceStatusCollectorState> state) {
2484   em::DeviceStatusReportRequest* status =
2485       state->response_params().device_status.get();
2486   bool anything_reported = false;
2487 
2488   if (report_activity_times_)
2489     anything_reported |= GetActivityTimes(status);
2490 
2491   if (report_version_info_)
2492     anything_reported |= GetVersionInfo(status);
2493 
2494   if (report_boot_mode_) {
2495     base::Optional<std::string> boot_mode =
2496         StatusCollector::GetBootMode(statistics_provider_);
2497     if (boot_mode) {
2498       status->set_boot_mode(*boot_mode);
2499       anything_reported = true;
2500     }
2501   }
2502 
2503   if (report_network_interfaces_)
2504     anything_reported |= GetNetworkInterfaces(status);
2505 
2506   if (report_users_)
2507     anything_reported |= GetUsers(status);
2508 
2509   if (report_hardware_status_) {
2510     anything_reported |= GetHardwareStatus(state);
2511     anything_reported |= GetWriteProtectSwitch(status);
2512   }
2513 
2514   if (report_os_update_status_)
2515     anything_reported |= GetOsUpdateStatus(status);
2516 
2517   if (report_running_kiosk_app_)
2518     anything_reported |= GetRunningKioskApp(status);
2519 
2520   if (report_graphics_status_)
2521     anything_reported |= GetGraphicsStatus(state);
2522 
2523   if (report_crash_report_info_ && stat_reporting_pref_)
2524     anything_reported |= GetCrashReportInfo(state);
2525 
2526   // Wipe pointer if we didn't actually add any data.
2527   if (!anything_reported)
2528     state->response_params().device_status.reset();
2529 }
2530 
GetSessionStatusForUser(scoped_refptr<DeviceStatusCollectorState> state,em::SessionStatusReportRequest * status,const user_manager::User * user)2531 bool DeviceStatusCollector::GetSessionStatusForUser(
2532     scoped_refptr<DeviceStatusCollectorState> state,
2533     em::SessionStatusReportRequest* status,
2534     const user_manager::User* user) {
2535   Profile* const profile =
2536       chromeos::ProfileHelper::Get()->GetProfileByUser(user);
2537   if (!profile)
2538     return false;
2539 
2540   bool anything_reported_user = false;
2541 
2542   const bool report_android_status =
2543       profile->GetPrefs()->GetBoolean(prefs::kReportArcStatusEnabled);
2544   if (report_android_status)
2545     anything_reported_user |= GetAndroidStatus(status, state);
2546 
2547   const bool report_crostini_usage = profile->GetPrefs()->GetBoolean(
2548       crostini::prefs::kReportCrostiniUsageEnabled);
2549   if (report_crostini_usage)
2550     anything_reported_user |= GetCrostiniUsage(status, profile);
2551 
2552   if (anything_reported_user && !user->IsDeviceLocalAccount())
2553     status->set_user_dm_token(GetDMTokenForProfile(profile));
2554 
2555   // Time zone is not reported in enterprise reports.
2556 
2557   return anything_reported_user;
2558 }
2559 
GetSessionStatus(scoped_refptr<DeviceStatusCollectorState> state)2560 void DeviceStatusCollector::GetSessionStatus(
2561     scoped_refptr<DeviceStatusCollectorState> state) {
2562   em::SessionStatusReportRequest* status =
2563       state->response_params().session_status.get();
2564   bool anything_reported = false;
2565 
2566   user_manager::UserManager* user_manager = user_manager::UserManager::Get();
2567   const user_manager::User* const primary_user = user_manager->GetPrimaryUser();
2568 
2569   if (report_kiosk_session_status_)
2570     anything_reported |= GetKioskSessionStatus(status);
2571 
2572   // Only report affiliated users' data in enterprise reporting. Note that
2573   // device-local accounts are also affiliated. Currently we only report for the
2574   // primary user.
2575   if (primary_user && primary_user->IsAffiliated()) {
2576     anything_reported |= GetSessionStatusForUser(state, status, primary_user);
2577   }
2578 
2579   // |app_infos|
2580   const auto app_infos = app_info_generator_.Generate();
2581   anything_reported |= app_infos.has_value();
2582   if (app_infos) {
2583     *status->mutable_app_infos() = {app_infos.value().begin(),
2584                                     app_infos.value().end()};
2585   }
2586 
2587   // Wipe pointer if we didn't actually add any data.
2588   if (!anything_reported)
2589     state->response_params().session_status.reset();
2590 }
2591 
GetKioskSessionStatus(em::SessionStatusReportRequest * status)2592 bool DeviceStatusCollector::GetKioskSessionStatus(
2593     em::SessionStatusReportRequest* status) {
2594   std::unique_ptr<const DeviceLocalAccount> account =
2595       GetAutoLaunchedKioskSessionInfo();
2596   if (!account)
2597     return false;
2598 
2599   // Get the account ID associated with this user.
2600   status->set_device_local_account_id(account->account_id);
2601   em::AppStatus* app_status = status->add_installed_apps();
2602   if (account->type == policy::DeviceLocalAccount::TYPE_KIOSK_APP) {
2603     app_status->set_app_id(account->kiosk_app_id);
2604 
2605     // Look up the app and get the version.
2606     const std::string app_version = GetAppVersion(account->kiosk_app_id);
2607     if (app_version.empty()) {
2608       DLOG(ERROR) << "Unable to get version for extension: "
2609                   << account->kiosk_app_id;
2610     } else {
2611       app_status->set_extension_version(app_version);
2612     }
2613   } else if (account->type == policy::DeviceLocalAccount::TYPE_ARC_KIOSK_APP) {
2614     // Use package name as app ID for ARC Kiosks.
2615     app_status->set_app_id(account->arc_kiosk_app_info.package_name());
2616   } else if (account->type == policy::DeviceLocalAccount::TYPE_WEB_KIOSK_APP) {
2617     app_status->set_app_id(account->web_kiosk_app_info.url());
2618   } else {
2619     NOTREACHED();
2620   }
2621 
2622   return true;
2623 }
2624 
GetAndroidStatus(em::SessionStatusReportRequest * status,const scoped_refptr<DeviceStatusCollectorState> & state)2625 bool DeviceStatusCollector::GetAndroidStatus(
2626     em::SessionStatusReportRequest* status,
2627     const scoped_refptr<DeviceStatusCollectorState>& state) {
2628   return state->FetchAndroidStatus(android_status_fetcher_);
2629 }
2630 
GetCrostiniUsage(em::SessionStatusReportRequest * status,Profile * profile)2631 bool DeviceStatusCollector::GetCrostiniUsage(
2632     em::SessionStatusReportRequest* status,
2633     Profile* profile) {
2634   if (!profile->GetPrefs()->HasPrefPath(
2635           crostini::prefs::kCrostiniLastLaunchTimeWindowStart)) {
2636     return false;
2637   }
2638 
2639   em::CrostiniStatus* const crostini_status = status->mutable_crostini_status();
2640   const int64_t last_launch_time_window_start = profile->GetPrefs()->GetInt64(
2641       crostini::prefs::kCrostiniLastLaunchTimeWindowStart);
2642   const std::string& termina_version = profile->GetPrefs()->GetString(
2643       crostini::prefs::kCrostiniLastLaunchTerminaComponentVersion);
2644   crostini_status->set_last_launch_time_window_start_timestamp(
2645       last_launch_time_window_start);
2646   crostini_status->set_last_launch_vm_image_version(termina_version);
2647 
2648   if (profile->GetPrefs()->GetBoolean(crostini::prefs::kCrostiniEnabled) &&
2649       base::FeatureList::IsEnabled(
2650           features::kCrostiniAdditionalEnterpriseReporting)) {
2651     const std::string& vm_kernel_version = profile->GetPrefs()->GetString(
2652         crostini::prefs::kCrostiniLastLaunchTerminaKernelVersion);
2653     crostini_status->set_last_launch_vm_kernel_version(vm_kernel_version);
2654 
2655     AddCrostiniAppListForProfile(profile, crostini_status);
2656   }
2657 
2658   return true;
2659 }
2660 
GetAppVersion(const std::string & kiosk_app_id)2661 std::string DeviceStatusCollector::GetAppVersion(
2662     const std::string& kiosk_app_id) {
2663   Profile* const profile = chromeos::ProfileHelper::Get()->GetProfileByUser(
2664       user_manager::UserManager::Get()->GetActiveUser());
2665   const extensions::ExtensionRegistry* const registry =
2666       extensions::ExtensionRegistry::Get(profile);
2667   const extensions::Extension* const extension = registry->GetExtensionById(
2668       kiosk_app_id, extensions::ExtensionRegistry::EVERYTHING);
2669   if (!extension)
2670     return std::string();
2671   return extension->VersionString();
2672 }
2673 
2674 // TODO(crbug.com/827386): move public API methods above private ones after
2675 // common methods are extracted.
OnSubmittedSuccessfully()2676 void DeviceStatusCollector::OnSubmittedSuccessfully() {
2677   activity_storage_->TrimActivityPeriods(last_reported_end_timestamp_,
2678                                          std::numeric_limits<int64_t>::max());
2679   app_info_generator_.OnReportedSuccessfully(last_requested_);
2680 }
2681 
ShouldReportActivityTimes() const2682 bool DeviceStatusCollector::ShouldReportActivityTimes() const {
2683   return report_activity_times_;
2684 }
ShouldReportNetworkInterfaces() const2685 bool DeviceStatusCollector::ShouldReportNetworkInterfaces() const {
2686   return report_network_interfaces_;
2687 }
ShouldReportUsers() const2688 bool DeviceStatusCollector::ShouldReportUsers() const {
2689   return report_users_;
2690 }
ShouldReportHardwareStatus() const2691 bool DeviceStatusCollector::ShouldReportHardwareStatus() const {
2692   return report_hardware_status_;
2693 }
ShouldReportCrashReportInfo() const2694 bool DeviceStatusCollector::ShouldReportCrashReportInfo() const {
2695   return report_crash_report_info_ && stat_reporting_pref_;
2696 }
ShouldReportAppInfoAndActivity() const2697 bool DeviceStatusCollector::ShouldReportAppInfoAndActivity() const {
2698   return report_app_info_;
2699 }
2700 
OnOSVersion(const std::string & version)2701 void DeviceStatusCollector::OnOSVersion(const std::string& version) {
2702   os_version_ = version;
2703 }
2704 
OnOSFirmware(std::pair<const std::string &,const std::string &> version)2705 void DeviceStatusCollector::OnOSFirmware(
2706     std::pair<const std::string&, const std::string&> version) {
2707   firmware_version_ = version.first;
2708   firmware_fetch_error_ = version.second;
2709 }
2710 
OnTpmVersion(const chromeos::CryptohomeClient::TpmVersionInfo & tpm_version_info)2711 void DeviceStatusCollector::OnTpmVersion(
2712     const chromeos::CryptohomeClient::TpmVersionInfo& tpm_version_info) {
2713   tpm_version_info_ = tpm_version_info;
2714 }
2715 
2716 }  // namespace policy
2717