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