xref: /aosp_15_r20/external/cronet/components/metrics/ui/screen_info_metrics_provider.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 The Chromium Authors
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 "components/metrics/ui/screen_info_metrics_provider.h"
6 
7 #include <algorithm>
8 
9 #include "build/build_config.h"
10 #include "third_party/metrics_proto/system_profile.pb.h"
11 #include "ui/display/display.h"
12 #include "ui/display/screen.h"
13 
14 #if BUILDFLAG(IS_WIN)
15 #include <windows.h>
16 #endif
17 
18 namespace metrics {
19 
20 #if BUILDFLAG(IS_WIN)
21 
22 namespace {
23 
24 struct ScreenDPIInformation {
25   double max_dpi_x;
26   double max_dpi_y;
27 };
28 
29 // Called once for each connected monitor.
GetMonitorDPICallback(HMONITOR,HDC hdc,LPRECT,LPARAM dwData)30 BOOL CALLBACK GetMonitorDPICallback(HMONITOR, HDC hdc, LPRECT, LPARAM dwData) {
31   const double kMillimetersPerInch = 25.4;
32   ScreenDPIInformation* screen_info =
33       reinterpret_cast<ScreenDPIInformation*>(dwData);
34   // Size of screen, in mm.
35   DWORD size_x = GetDeviceCaps(hdc, HORZSIZE);
36   DWORD size_y = GetDeviceCaps(hdc, VERTSIZE);
37   double dpi_x = (size_x > 0) ?
38       GetDeviceCaps(hdc, HORZRES) / (size_x / kMillimetersPerInch) : 0;
39   double dpi_y = (size_y > 0) ?
40       GetDeviceCaps(hdc, VERTRES) / (size_y / kMillimetersPerInch) : 0;
41   screen_info->max_dpi_x = std::max(dpi_x, screen_info->max_dpi_x);
42   screen_info->max_dpi_y = std::max(dpi_y, screen_info->max_dpi_y);
43   return TRUE;
44 }
45 
WriteScreenDPIInformationProto(SystemProfileProto::Hardware * hardware)46 void WriteScreenDPIInformationProto(SystemProfileProto::Hardware* hardware) {
47   HDC desktop_dc = GetDC(nullptr);
48   if (desktop_dc) {
49     ScreenDPIInformation si = {0, 0};
50     if (EnumDisplayMonitors(desktop_dc, nullptr, GetMonitorDPICallback,
51                             reinterpret_cast<LPARAM>(&si))) {
52       hardware->set_max_dpi_x(si.max_dpi_x);
53       hardware->set_max_dpi_y(si.max_dpi_y);
54     }
55     ReleaseDC(GetDesktopWindow(), desktop_dc);
56   }
57 }
58 
59 }  // namespace
60 
61 #endif  // BUILDFLAG(IS_WIN)
62 
ScreenInfoMetricsProvider()63 ScreenInfoMetricsProvider::ScreenInfoMetricsProvider() {
64 }
65 
~ScreenInfoMetricsProvider()66 ScreenInfoMetricsProvider::~ScreenInfoMetricsProvider() {
67 }
68 
ProvideSystemProfileMetrics(SystemProfileProto * system_profile_proto)69 void ScreenInfoMetricsProvider::ProvideSystemProfileMetrics(
70     SystemProfileProto* system_profile_proto) {
71   // This may be called before the screen info has been initialized, such as
72   // when the persistent system profile gets filled in initially.
73   const std::optional<gfx::Size> display_size = GetScreenSize();
74   if (!display_size.has_value())
75     return;
76 
77   SystemProfileProto::Hardware* hardware =
78       system_profile_proto->mutable_hardware();
79 
80   hardware->set_primary_screen_width(display_size->width());
81   hardware->set_primary_screen_height(display_size->height());
82   hardware->set_primary_screen_scale_factor(GetScreenDeviceScaleFactor());
83   hardware->set_screen_count(GetScreenCount());
84 
85 #if BUILDFLAG(IS_WIN)
86   WriteScreenDPIInformationProto(hardware);
87 #endif
88 }
89 
GetScreenSize() const90 std::optional<gfx::Size> ScreenInfoMetricsProvider::GetScreenSize() const {
91   auto* screen = display::Screen::GetScreen();
92   if (!screen)
93     return std::nullopt;
94   return std::make_optional(screen->GetPrimaryDisplay().GetSizeInPixel());
95 }
96 
GetScreenDeviceScaleFactor() const97 float ScreenInfoMetricsProvider::GetScreenDeviceScaleFactor() const {
98   return display::Screen::GetScreen()
99       ->GetPrimaryDisplay()
100       .device_scale_factor();
101 }
102 
GetScreenCount() const103 int ScreenInfoMetricsProvider::GetScreenCount() const {
104   return display::Screen::GetScreen()->GetNumDisplays();
105 }
106 
107 }  // namespace metrics
108