xref: /aosp_15_r20/external/cronet/base/system/sys_info_ios.mm (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1// Copyright 2012 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 "base/system/sys_info.h"
6
7#import <UIKit/UIKit.h>
8#include <mach/mach.h>
9#include <stddef.h>
10#include <stdint.h>
11#include <sys/sysctl.h>
12#include <sys/types.h>
13
14#include "base/apple/scoped_mach_port.h"
15#include "base/check_op.h"
16#include "base/no_destructor.h"
17#include "base/notreached.h"
18#include "base/numerics/safe_conversions.h"
19#include "base/posix/sysctl.h"
20#include "base/process/process_metrics.h"
21#include "base/strings/string_util.h"
22#include "base/strings/stringprintf.h"
23#include "base/strings/sys_string_conversions.h"
24#include "build/build_config.h"
25
26namespace base {
27
28#if BUILDFLAG(IS_IOS)
29namespace {
30// Accessor for storage of overridden HardwareModelName.
31std::string& GetHardwareModelNameStorage() {
32  static base::NoDestructor<std::string> instance;
33  return *instance;
34}
35}  // namespace
36#endif
37
38// static
39std::string SysInfo::OperatingSystemName() {
40  static dispatch_once_t get_system_name_once;
41  static std::string* system_name;
42  dispatch_once(&get_system_name_once, ^{
43    @autoreleasepool {
44      system_name =
45          new std::string(SysNSStringToUTF8(UIDevice.currentDevice.systemName));
46    }
47  });
48  // Examples of returned value: 'iPhone OS' on iPad 5.1.1
49  // and iPhone 5.1.1.
50  return *system_name;
51}
52
53// static
54std::string SysInfo::OperatingSystemVersion() {
55  static dispatch_once_t get_system_version_once;
56  static std::string* system_version;
57  dispatch_once(&get_system_version_once, ^{
58    @autoreleasepool {
59      system_version = new std::string(
60          SysNSStringToUTF8(UIDevice.currentDevice.systemVersion));
61    }
62  });
63  return *system_version;
64}
65
66// static
67void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
68                                            int32_t* minor_version,
69                                            int32_t* bugfix_version) {
70  NSOperatingSystemVersion version =
71      NSProcessInfo.processInfo.operatingSystemVersion;
72  *major_version = saturated_cast<int32_t>(version.majorVersion);
73  *minor_version = saturated_cast<int32_t>(version.minorVersion);
74  *bugfix_version = saturated_cast<int32_t>(version.patchVersion);
75}
76
77// static
78std::string SysInfo::OperatingSystemArchitecture() {
79#if defined(ARCH_CPU_X86)
80  return "x86";
81#elif defined(ARCH_CPU_X86_64)
82  return "x86_64";
83#elif defined(ARCH_CPU_ARMEL)
84  return "arm";
85#elif defined(ARCH_CPU_ARM64)
86  return "arm64";
87#else
88#error Unsupported CPU architecture
89#endif
90}
91
92// static
93std::string SysInfo::GetIOSBuildNumber() {
94  std::optional<std::string> build_number =
95      StringSysctl({CTL_KERN, KERN_OSVERSION});
96  return build_number.value();
97}
98
99// static
100void SysInfo::OverrideHardwareModelName(std::string name) {
101  // Normally, HardwareModelName() should not be called before overriding the
102  // value, but StartCrashController(), which eventually calls
103  // HardwareModelName(), is called before overriding the name.
104  CHECK(!name.empty());
105  GetHardwareModelNameStorage() = std::move(name);
106}
107
108// static
109uint64_t SysInfo::AmountOfPhysicalMemoryImpl() {
110  struct host_basic_info hostinfo;
111  mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
112  base::apple::ScopedMachSendRight host(mach_host_self());
113  int result = host_info(host.get(), HOST_BASIC_INFO,
114                         reinterpret_cast<host_info_t>(&hostinfo), &count);
115  if (result != KERN_SUCCESS) {
116    NOTREACHED();
117    return 0;
118  }
119  DCHECK_EQ(HOST_BASIC_INFO_COUNT, count);
120  return hostinfo.max_mem;
121}
122
123// static
124uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() {
125  SystemMemoryInfoKB info;
126  if (!GetSystemMemoryInfo(&info))
127    return 0;
128  // We should add inactive file-backed memory also but there is no such
129  // information from iOS unfortunately.
130  return checked_cast<uint64_t>(info.free + info.speculative) * 1024;
131}
132
133// static
134std::string SysInfo::CPUModelName() {
135  return StringSysctlByName("machdep.cpu.brand_string").value_or(std::string{});
136}
137
138// static
139std::string SysInfo::HardwareModelName() {
140#if TARGET_OS_SIMULATOR
141  // On the simulator, "hw.machine" returns "i386" or "x86_64" which doesn't
142  // match the expected format, so supply a fake string here.
143  const char* model = getenv("SIMULATOR_MODEL_IDENTIFIER");
144  if (model == nullptr) {
145    switch (UIDevice.currentDevice.userInterfaceIdiom) {
146      case UIUserInterfaceIdiomPhone:
147        model = "iPhone";
148        break;
149      case UIUserInterfaceIdiomPad:
150        model = "iPad";
151        break;
152      default:
153        model = "Unknown";
154        break;
155    }
156  }
157  return base::StringPrintf("iOS Simulator (%s)", model);
158#else
159  const std::string& override = GetHardwareModelNameStorage();
160  if (!override.empty()) {
161    return override;
162  }
163  // Note: This uses "hw.machine" instead of "hw.model" like the Mac code,
164  // because "hw.model" doesn't always return the right string on some devices.
165  return StringSysctl({CTL_HW, HW_MACHINE}).value_or(std::string{});
166#endif
167}
168
169// static
170SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
171  HardwareInfo info;
172  info.manufacturer = "Apple Inc.";
173  info.model = HardwareModelName();
174  DCHECK(IsStringUTF8(info.manufacturer));
175  DCHECK(IsStringUTF8(info.model));
176  return info;
177}
178
179}  // namespace base
180