Extend SystemInfo

This commit is contained in:
2021-08-02 02:26:18 +02:00
parent 2829c02762
commit 16f76fa04b
4 changed files with 659 additions and 1 deletions

View File

@@ -11,7 +11,9 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <climits>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/utsname.h>
namespace openVulkanoCpp namespace openVulkanoCpp
{ {
@@ -103,4 +105,256 @@ namespace openVulkanoCpp
Logger::PERF->error("Failed to query max application memory"); Logger::PERF->error("Failed to query max application memory");
return 0; return 0;
} }
std::string SystemInfo::GetUserName()
{
char* name = getlogin();
if (!name) return "unknown";
return name;
}
std::string SystemInfo::GetHostName()
{
char hostname[HOST_NAME_MAX + 1];
gethostname(hostname, HOST_NAME_MAX + 1);
return hostname;
}
std::string SystemInfo::GetDeviceName()
{
return GetHostName();
}
std::string SystemInfo::GetDeviceVendorName()
{
std::ifstream dmiStream("/sys/class/dmi/id/board_vendor");
if (!dmiStream)
{
Logger::PERF->error("Failed to read /sys/class/dmi/id/board_vendor");
return "Unknown";
}
std::string motherboardName;
std::getline(dmiStream, motherboardName);
return motherboardName;
}
std::string SystemInfo::GetDeviceModelName()
{
std::ifstream dmiStream("/sys/class/dmi/id/board_name");
if (!dmiStream)
{
Logger::PERF->error("Failed to read /sys/class/dmi/id/board_name");
return "Unknown";
}
std::string motherboardName;
std::getline(dmiStream, motherboardName);
return motherboardName;
}
namespace
{
struct OsInfo
{
std::string osName, osNameFormatted;
Version version;
static std::string TryRead(const std::string line, std::string_view prefix)
{
if (Utils::StartsWith(line, prefix))
{
size_t prefixLen = prefix.length();
return line.substr(prefixLen, line.length() - prefixLen - 1);
}
return "";
}
static Version ParseVersionString(char* str)
{
int ver[3];
int i = 0;
while (*str && i < 3)
{
if (isdigit(*str))
{
ver[i] = strtol(str, &str, 10);
i++;
}
else
{
str++;
}
}
return {ver[0], ver[1], ver[2], 0};
}
OsInfo() : version({0, 0, 0, 0})
{
std::ifstream osRel("/etc/os-release");
std::string versionString;
if (osRel)
{
std::string line, name, tmp;
while (std::getline(osRel, line))
{
if (!(tmp = TryRead(line, "PRETTY_NAME=\"")).empty())
{
osName = std::move(tmp);
}
else if (!(tmp = TryRead(line, "NAME=\"")).empty())
{
name = std::move(tmp);
}
else if (name.empty() && Utils::StartsWith(line, "ID=\""))
{
name = line.substr(4, line.length() - 5);
}
else if (!(tmp = TryRead(line, "BUILD_ID=\"")).empty())
{
versionString = std::move(tmp);
}
else if (!(tmp = TryRead(line, "VERSION_ID=\"")).empty())
{
versionString = std::move(tmp);
}
}
if (osName.empty()) osName = name;
osNameFormatted = osName + " " + versionString;
if (!versionString.empty()) version = ParseVersionString(versionString.data());
}
if (osName.empty() || versionString.empty())
{ // fallback to uname
struct utsname buffer;
errno = 0;
if (uname(&buffer) == 0)
{
osName = buffer.sysname;
osNameFormatted = osName + " " + buffer.release;
version = ParseVersionString(buffer.release);
return;
}
perror("uname");
}
if (osName.empty()) osName = "Linux";
if (osNameFormatted.empty()) osNameFormatted = "Linux";
}
};
OsInfo osInfo;
}
std::string SystemInfo::GetOsName()
{
return osInfo.osName;
}
Version SystemInfo::GetOsVersion()
{
return osInfo.version;
}
std::string SystemInfo::GetOsNameHumanReadable()
{
return osInfo.osNameFormatted;
}
DeviceType SystemInfo::GetDeviceType()
{
return DeviceType::PC; // TODO?
}
size_t SystemInfo::GetCpuCoreCount()
{
return 0; //TODO
}
size_t SystemInfo::GetCpuThreadCount()
{
return std::thread::hardware_concurrency();
}
int32_t SystemInfo::GetCpuTemperature()
{
std::ifstream tempFile("/sys/class/thermal/thermal_zone0/temp");
if (!tempFile)
{
Logger::PERF->error("Failed to open the temperature file");
return 20;
}
std::string tempStr;
std::getline(tempFile, tempStr);
return static_cast<int>(std::stof(tempStr) / 1000.0f);
}
CpuThermalState SystemInfo::GetCpuThermalState()
{
auto temp = GetCpuTemperature();
if (temp < 70) return CpuThermalState::Normal;
if (temp < 80) return CpuThermalState::Fair;
if (temp < 95) return CpuThermalState::Serious;
return CpuThermalState::Critical;
}
bool SystemInfo::IsDeviceInLowPowerMode()
{
return false; //TODO?
}
BatteryState SystemInfo::GetDeviceBatteryState()
{
std::ifstream powerSupplyFile("/sys/class/power_supply/BAT0/status");
if (powerSupplyFile)
{
std::string status;
std::getline(powerSupplyFile, status);
if (status == "Charging") return BatteryState::Charging;
if (status == "Not charging") return BatteryState::NotCharging;
if (status == "Full") return BatteryState::ChargingFull;
if (status == "Discharging") return BatteryState::Unplugged;
}
return BatteryState::Unavailable;
}
float SystemInfo::GetDeviceBatteryLevel()
{
std::ifstream powerSupplyFile("/sys/class/power_supply/BAT0/capacity");
if (powerSupplyFile)
{
float value;
powerSupplyFile >> value;
return value;
}
return 0;
}
void SystemInfo::EnableEnergyEvents()
{
//TODO
}
bool SystemInfo::IsMultitaskingSupported()
{
return true;
}
DeviceOrientation SystemInfo::GetDeviceOrientation()
{
return DeviceOrientation::LandscapeRight; // TODO?
}
void SystemInfo::EnableDeviceOrientationEvents()
{
//TODO?
}
InterfaceOrientation SystemInfo::GetInterfaceOrientation()
{
return InterfaceOrientation::Landscape; // TODO?
}
} }

View File

@@ -4,10 +4,26 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. * file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/ */
#include <cstddef> #include "Base/Event.hpp"
#include <string>
namespace openVulkanoCpp namespace openVulkanoCpp
{ {
struct Version
{
int major, minor, patch, build;
};
enum class DeviceType { Phone, Tablet, PC, TV, VR, Unknown };
enum class CpuThermalState { Normal, Fair, Serious, Critical };
enum class BatteryState { Unavailable, Unplugged, Charging, ChargingFull, NotCharging };
enum class DeviceOrientation { Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight, FaceUp, FaceDown, Unknown };
enum class InterfaceOrientation { Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight, Landscape = LandscapeLeft };
class SystemInfo class SystemInfo
{ {
public: public:
@@ -17,5 +33,41 @@ namespace openVulkanoCpp
static size_t GetAppVirtualMemoryMax(); static size_t GetAppVirtualMemoryMax();
static size_t GetAppRamAvailable(); static size_t GetAppRamAvailable();
static size_t GetAppRamUsed(); static size_t GetAppRamUsed();
static std::string GetUserName();
static std::string GetHostName();
static std::string GetDeviceName();
static std::string GetDeviceVendorName();
static std::string GetDeviceModelName();
static std::string GetOsName();
static Version GetOsVersion();
static std::string GetOsNameHumanReadable();
static DeviceType GetDeviceType();
static size_t GetCpuCoreCount();
static size_t GetCpuThreadCount();
static int32_t GetCpuTemperature();
static CpuThermalState GetCpuThermalState();
static bool IsDeviceInLowPowerMode();
static bool GetDeviceHasBattery() { return GetDeviceBatteryState() != BatteryState::Unavailable; }
static BatteryState GetDeviceBatteryState();
static float GetDeviceBatteryLevel();
static void EnableEnergyEvents();
/**
* Checks if device allows to run multiple applications at the same time.
* Will probably return true, for everything but smartphones.
* @return true if multiple applications can run at the same time, false if not
*/
static bool IsMultitaskingSupported();
static DeviceOrientation GetDeviceOrientation();
static void EnableDeviceOrientationEvents();
static InterfaceOrientation GetInterfaceOrientation();
static Event<> OnLowPowerModeChanged;
static Event<> OnBatteryStateChanged;
static Event<> OnBatteryLevelChanged;
static Event<> OnDeviceOrientationChanged;
}; };
} }

View File

@@ -9,6 +9,9 @@
#include <iostream> #include <iostream>
#include <Windows.h> #include <Windows.h>
#include <Psapi.h> #include <Psapi.h>
#include <Lmcons.h>
#include <Winsock.h>
#include <Winbase.h>
namespace openVulkanoCpp namespace openVulkanoCpp
{ {
@@ -79,4 +82,158 @@ namespace openVulkanoCpp
{ {
return ReadAppMemInfo(APP_MEM_TYPE::VM_MAX); return ReadAppMemInfo(APP_MEM_TYPE::VM_MAX);
} }
std::string SystemInfo::GetUserName()
{
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
return username;
}
std::string SystemInfo::GetHostName()
{
char hostname[UNLEN+1];
gethostname(hostname, UNLEN+1);
return hostname;
}
std::string SystemInfo::GetDeviceName()
{
char computerName[UNLEN+1];
DWORD computerName_len = UNLEN+1;
GetComputerNameA(computerName, &computerName_len);
return computerName;
}
std::string SystemInfo::GetDeviceVendorName()
{
return "Microsoft"; //TODO
}
std::string SystemInfo::GetDeviceModelName()
{
return "Unknown"; //TODO
}
std::string SystemInfo::GetOsName()
{
return "Windows";
}
Version SystemInfo::GetOsVersion()
{
OSVERSIONINFOEX info;
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx(&info);
return { info.dwMajorVersion, info.dwMinorVersion, 0, info.dwBuildNumber };
}
std::string SystemInfo::GetOsNameHumanReadable()
{
OSVERSIONINFOEX info;
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx(&info);
if (info.wProductType == VER_NT_WORKSTATION)
{
if (info.dwMajorVersion == 10)
return "Windows 10";
else if (info.dwMajorVersion == 6)
{
switch (info.dwMinorVersion)
{
case 0: return "Windows Vista";
case 1: return "Windows 7";
case 2: return "Windows 8";
case 3: return "Windows 8.1";
}
}
return "Windows " + std::string(info.dwMajorVersion) + "." + std::string(info.dwMinorVersion);
}
else
{
if (info.dwMajorVersion == 10)
return "Windows Server 2016";
else if (info.dwMajorVersion == 6)
{
switch (info.dwMinorVersion)
{
case 0: return "Windows Server 2008";
case 1: return "Windows Server 2008 R2";
case 2: return "Windows Server 2012";
case 3: return "Windows Server 2012 R2";
}
}
return "Windows Server " + std::string(info.dwMajorVersion) + "." + std::string(info.dwMinorVersion);
}
}
DeviceType SystemInfo::GetDeviceType()
{
return DeviceType::PC;
}
size_t SystemInfo::GetCpuCoreCount()
{
return 0; //TODO
}
size_t SystemInfo::GetCpuThreadCount()
{
return std::thread::hardware_concurrency();
}
int32_t SystemInfo::GetCpuTemperature()
{
return 0; //TODO
}
CpuThermalState SystemInfo::GetCpuThermalState()
{
return CpuThermalState::Normal;
}
bool SystemInfo::IsDeviceInLowPowerMode()
{
return false; //TODO
}
BatteryState SystemInfo::GetDeviceBatteryState()
{
return BatteryState::Unavailable; //TODO
}
float SystemInfo::GetDeviceBatteryLevel()
{
return 0; //TODO
}
void SystemInfo::EnableEnergyEvents()
{
//TODO
}
bool SystemInfo::IsMultitaskingSupported()
{
return true;
}
DeviceOrientation SystemInfo::GetDeviceOrientation()
{
return DeviceOrientation::LandscapeRight; //TODO
}
void SystemInfo::EnableDeviceOrientationEvents()
{
//TODO
}
InterfaceOrientation SystemInfo::GetInterfaceOrientation()
{
return InterfaceOrientation::Landscape; //TODO
}
} }

View File

@@ -6,13 +6,23 @@
#include "Host/SystemInfo.hpp" #include "Host/SystemInfo.hpp"
#include "Base/Logger.hpp" #include "Base/Logger.hpp"
#include <sstream>
#include <mach/mach.h> #include <mach/mach.h>
#include <os/proc.h> #include <os/proc.h>
#import <Foundation/NSProcessInfo.h> #import <Foundation/NSProcessInfo.h>
#import <UIKit/UIApplication.h>
#import <UIKit/UIDevice.h>
#import <UIKit/UIWindowScene.h>
namespace openVulkanoCpp namespace openVulkanoCpp
{ {
Event<> SystemInfo::OnLowPowerModeChanged;
Event<> SystemInfo::OnBatteryStateChanged;
Event<> SystemInfo::OnBatteryLevelChanged;
Event<> SystemInfo::OnDeviceOrientationChanged;
size_t SystemInfo::GetSystemRam() size_t SystemInfo::GetSystemRam()
{ {
return [NSProcessInfo processInfo].physicalMemory; return [NSProcessInfo processInfo].physicalMemory;
@@ -50,4 +60,189 @@ namespace openVulkanoCpp
Logger::PERF->error("Failed to read memory consumption: {}", mach_error_string(kerr)); Logger::PERF->error("Failed to read memory consumption: {}", mach_error_string(kerr));
return 0; 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()
{
return [[[UIDevice currentDevice] model] UTF8String];
}
std::string SystemInfo::GetOsName()
{
return [[[UIDevice currentDevice] systemName] UTF8String];
}
Version SystemInfo::GetOsVersion()
{
NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion;
return { static_cast<int>(osVersion.majorVersion), static_cast<int>(osVersion.minorVersion), static_cast<int>(osVersion.patchVersion), 0 };
}
std::string SystemInfo::GetOsNameHumanReadable()
{
std::stringstream name;
name << GetOsName() << ' ' << GetOsVersion().major;
return name.str();
}
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;
}
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;
}
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;
}
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;
}
}
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;
}
}
return InterfaceOrientation::Landscape;
}
} }