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