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