/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #include "Host/SystemInfo.hpp" #include "Base/Logger.hpp" #include "IosDeviceNameDecoder.hpp" #include #include #include #include #import #import #import #import namespace OpenVulkano { Event<> SystemInfo::OnLowPowerModeChanged; Event<> SystemInfo::OnBatteryStateChanged; Event<> SystemInfo::OnBatteryLevelChanged; Event<> SystemInfo::OnDeviceOrientationChanged; size_t SystemInfo::GetSystemRam() { return [NSProcessInfo processInfo].physicalMemory; } size_t SystemInfo::GetSystemRamAvailable() { return os_proc_available_memory(); } size_t SystemInfo::GetAppRamMax() { return GetAppRamAvailable() + GetAppRamUsed(); } size_t SystemInfo::GetAppVirtualMemoryMax() { return INT64_MAX; } size_t SystemInfo::GetAppRamAvailable() { return os_proc_available_memory(); } size_t SystemInfo::GetAppRamUsed() { struct task_basic_info info; mach_msg_type_number_t size = sizeof(info); kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size); if( kerr == KERN_SUCCESS ) { return info.resident_size; } Logger::PERF->error("Failed to read memory consumption: {}", mach_error_string(kerr)); return 0; } std::string SystemInfo::GetUserName() { return ""; } std::string SystemInfo::GetHostName() { return [[NSProcessInfo processInfo].hostName UTF8String]; } std::string SystemInfo::GetDeviceName() { return [[[UIDevice currentDevice] name] UTF8String]; } std::string SystemInfo::GetDeviceVendorName() { return "Apple"; } std::string SystemInfo::GetDeviceModelName() { static std::string modelName; if (modelName.empty()) { struct utsname systemInfo; uname(&systemInfo); modelName = DecodeModelString(systemInfo.machine); if (modelName.empty()) modelName = [[[UIDevice currentDevice] model] UTF8String]; } return modelName; } std::string SystemInfo::GetOsName() { return [[[UIDevice currentDevice] systemName] UTF8String]; } OsVersion SystemInfo::GetOsVersion() { NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; return { static_cast(osVersion.majorVersion), static_cast(osVersion.minorVersion), static_cast(osVersion.patchVersion), 0 }; } std::string SystemInfo::GetOsNameHumanReadable() { return fmt::format("{} {}", GetOsName(), GetOsVersion().major); } DeviceType SystemInfo::GetDeviceType() { switch ([UIDevice currentDevice].userInterfaceIdiom) { case UIUserInterfaceIdiomPhone: return DeviceType::Phone; case UIUserInterfaceIdiomPad: return DeviceType::Tablet; case UIUserInterfaceIdiomTV: return DeviceType::TV; case UIUserInterfaceIdiomMac: return DeviceType::PC; case UIUserInterfaceIdiomVision: return DeviceType::VR; default: break; } return DeviceType::Unknown; } size_t SystemInfo::GetCpuCoreCount() { return [NSProcessInfo processInfo].processorCount; } size_t SystemInfo::GetCpuThreadCount() { return [NSProcessInfo processInfo].activeProcessorCount; } int32_t SystemInfo::GetCpuTemperature() { switch([NSProcessInfo processInfo].thermalState) { case NSProcessInfoThermalStateNominal: return 20; case NSProcessInfoThermalStateFair: return 50; case NSProcessInfoThermalStateSerious: return 80; case NSProcessInfoThermalStateCritical: return 100; } return -1; } CpuThermalState SystemInfo::GetCpuThermalState() { switch([NSProcessInfo processInfo].thermalState) { case NSProcessInfoThermalStateNominal: return CpuThermalState::Normal; case NSProcessInfoThermalStateFair: return CpuThermalState::Fair; case NSProcessInfoThermalStateSerious: return CpuThermalState::Serious; case NSProcessInfoThermalStateCritical: return CpuThermalState::Critical; } return CpuThermalState::Normal; } bool SystemInfo::IsDeviceInLowPowerMode() { return [NSProcessInfo processInfo].lowPowerModeEnabled; } void SystemInfo::EnableEnergyEvents() { [[NSNotificationCenter defaultCenter] addObserverForName:NSProcessInfoPowerStateDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { SystemInfo::OnLowPowerModeChanged.NotifyAll(); }]; [[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceBatteryLevelDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { SystemInfo::OnBatteryLevelChanged.NotifyAll(); }]; [[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceBatteryStateDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { SystemInfo::OnBatteryStateChanged.NotifyAll(); }]; } BatteryState SystemInfo::GetDeviceBatteryState() { switch([UIDevice currentDevice].batteryState) { case UIDeviceBatteryStateUnplugged: return BatteryState::Unplugged; case UIDeviceBatteryStateCharging: return BatteryState::Charging; case UIDeviceBatteryStateFull: return BatteryState::ChargingFull; default: break; } return BatteryState::Unavailable; } float SystemInfo::GetDeviceBatteryLevel() { return [UIDevice currentDevice].batteryLevel; } bool SystemInfo::IsMultitaskingSupported() { return [UIDevice currentDevice].multitaskingSupported; } DeviceOrientation SystemInfo::GetDeviceOrientation() { switch([UIDevice currentDevice].orientation) { case UIDeviceOrientationPortrait: return DeviceOrientation::Portrait; case UIDeviceOrientationPortraitUpsideDown: return DeviceOrientation::PortraitUpsideDown; case UIDeviceOrientationLandscapeLeft: return DeviceOrientation::LandscapeLeft; case UIDeviceOrientationLandscapeRight: return DeviceOrientation::LandscapeRight; case UIDeviceOrientationFaceUp: return DeviceOrientation::FaceUp; case UIDeviceOrientationFaceDown: return DeviceOrientation::FaceDown; default: break; } return DeviceOrientation::Unknown; } void SystemInfo::EnableDeviceOrientationEvents() { [[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceOrientationDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { SystemInfo::OnDeviceOrientationChanged.NotifyAll(); }]; [[UIDevice currentDevice]beginGeneratingDeviceOrientationNotifications]; } InterfaceOrientation SystemInfo::GetInterfaceOrientation() { if (@available(iOS 15.0, *)) { //TODO support multi scene at some point UIInterfaceOrientation interfaceOrientation; for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { if ([scene isKindOfClass:[UIWindowScene class]]) { interfaceOrientation = ((UIWindowScene *)scene).interfaceOrientation; break; } } switch(interfaceOrientation) { case UIInterfaceOrientationPortrait: return InterfaceOrientation::Portrait; case UIInterfaceOrientationPortraitUpsideDown: return InterfaceOrientation::PortraitUpsideDown; case UIInterfaceOrientationLandscapeLeft: return InterfaceOrientation::LandscapeLeft; case UIInterfaceOrientationLandscapeRight: return InterfaceOrientation::LandscapeRight; default: break; } } else { switch(GetDeviceOrientation()) { case DeviceOrientation::Portrait: return InterfaceOrientation::Portrait; case DeviceOrientation::PortraitUpsideDown: return InterfaceOrientation::PortraitUpsideDown; case DeviceOrientation::LandscapeLeft: return InterfaceOrientation::LandscapeRight; case DeviceOrientation::LandscapeRight: return InterfaceOrientation::LandscapeLeft; default: break; } } return InterfaceOrientation::Landscape; } }