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