#include "platform/platform_ios.h" #include "platform/constants.hpp" #include "platform/gui_thread.hpp" #include "platform/measurement_utils.hpp" #include "platform/platform_unix_impl.hpp" #include "platform/settings.hpp" #include "coding/file_reader.hpp" #include #include #include #include #include #include #include #include #include #include #import "3party/Alohalytics/src/alohalytics_objc.h" #import #import #import #import #import #include #include #include #include Platform::Platform() { m_isTablet = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad); NSBundle * bundle = NSBundle.mainBundle; NSString * path = [bundle resourcePath]; m_resourcesDir = path.UTF8String; m_resourcesDir += "/"; NSArray * dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString * docsDir = dirPaths.firstObject; m_writableDir = docsDir.UTF8String; m_writableDir += "/"; m_settingsDir = m_writableDir; auto privatePaths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); m_privateDir = privatePaths.firstObject.UTF8String; m_privateDir += "/"; NSString * tmpDir = NSTemporaryDirectory(); if (tmpDir) m_tmpDir = tmpDir.UTF8String; else { m_tmpDir = NSHomeDirectory().UTF8String; m_tmpDir += "/tmp/"; } m_guiThread = std::make_unique(); UIDevice * device = UIDevice.currentDevice; device.batteryMonitoringEnabled = YES; NSLog(@"Device: %@, SystemName: %@, SystemVersion: %@", device.model, device.systemName, device.systemVersion); } //static void Platform::DisableBackupForFile(std::string const & filePath) { // We need to disable iCloud backup for downloaded files. // This is the reason for rejecting from the AppStore // https://developer.apple.com/library/iOS/qa/qa1719/_index.html CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, reinterpret_cast(filePath.c_str()), filePath.size(), 0); CFErrorRef err; BOOL valueRaw = YES; CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberCharType, &valueRaw); if (!CFURLSetResourcePropertyForKey(url, kCFURLIsExcludedFromBackupKey, value, &err)) NSLog(@"Error while disabling iCloud backup for file: %s", filePath.c_str()); CFRelease(value); CFRelease(url); } // static Platform::EError Platform::MkDir(std::string const & dirName) { if (::mkdir(dirName.c_str(), 0755)) return ErrnoToError(); return Platform::ERR_OK; } void Platform::GetFilesByRegExp(std::string const & directory, std::string const & regexp, FilesList & res) { pl::EnumerateFilesByRegExp(directory, regexp, res); } bool Platform::GetFileSizeByName(std::string const & fileName, uint64_t & size) const { try { return GetFileSizeByFullPath(ReadPathForFile(fileName), size); } catch (RootException const &) { return false; } } std::unique_ptr Platform::GetReader(std::string const & file, std::string const & searchScope) const { return std::make_unique(ReadPathForFile(file, searchScope), READER_CHUNK_LOG_SIZE, READER_CHUNK_LOG_COUNT); } int Platform::VideoMemoryLimit() const { return 8 * 1024 * 1024; } int Platform::PreCachingDepth() const { return 2; } std::string Platform::UniqueClientId() const { return [Alohalytics installationId].UTF8String; } std::string Platform::AdvertisingId() const { NSUUID *adId = [ASIdentifierManager sharedManager].advertisingIdentifier; return adId.UUIDString.UTF8String; } std::string Platform::MacAddress(bool md5Decoded) const { // Not implemented. UNUSED_VALUE(md5Decoded); return {}; } std::string Platform::GetMemoryInfo() const { struct task_basic_info info; mach_msg_type_number_t size = sizeof(info); kern_return_t const kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size); std::stringstream ss; if (kerr == KERN_SUCCESS) { ss << "Memory info: Resident_size = " << info.resident_size / 1024 << "KB; virtual_size = " << info.resident_size / 1024 << "KB; suspend_count = " << info.suspend_count << " policy = " << info.policy; } else { ss << "Error with task_info(): " << mach_error_string(kerr); } return ss.str(); } std::string Platform::DeviceName() const { return UIDevice.currentDevice.name.UTF8String; } std::string Platform::DeviceModel() const { utsname systemInfo; uname(&systemInfo); NSString * deviceModel = @(systemInfo.machine); if (auto m = platform::kDeviceModelsBeforeMetalDriver[deviceModel]) deviceModel = m; else if (auto m = platform::kDeviceModelsWithiOS10MetalDriver[deviceModel]) deviceModel = m; else if (auto m = platform::kDeviceModelsWithMetalDriver[deviceModel]) deviceModel = m; return deviceModel.UTF8String; } Platform::EConnectionType Platform::ConnectionStatus() { struct sockaddr_in zero; bzero(&zero, sizeof(zero)); zero.sin_len = sizeof(zero); zero.sin_family = AF_INET; SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zero); if (!reachability) return EConnectionType::CONNECTION_NONE; SCNetworkReachabilityFlags flags; bool const gotFlags = SCNetworkReachabilityGetFlags(reachability, &flags); CFRelease(reachability); if (!gotFlags || ((flags & kSCNetworkReachabilityFlagsReachable) == 0)) return EConnectionType::CONNECTION_NONE; SCNetworkReachabilityFlags userActionRequired = kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsInterventionRequired; if ((flags & userActionRequired) == userActionRequired) return EConnectionType::CONNECTION_NONE; if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) return EConnectionType::CONNECTION_WWAN; else return EConnectionType::CONNECTION_WIFI; } Platform::ChargingStatus Platform::GetChargingStatus() { switch (UIDevice.currentDevice.batteryState) { case UIDeviceBatteryStateUnknown: return Platform::ChargingStatus::Unknown; case UIDeviceBatteryStateUnplugged: return Platform::ChargingStatus::Unplugged; case UIDeviceBatteryStateCharging: case UIDeviceBatteryStateFull: return Platform::ChargingStatus::Plugged; } } uint8_t Platform::GetBatteryLevel() { auto const level = UIDevice.currentDevice.batteryLevel; ASSERT_GREATER_OR_EQUAL(level, -1.0, ()); ASSERT_LESS_OR_EQUAL(level, 1.0, ()); if (level == -1.0) return 100; auto const result = static_cast(level * 100); CHECK_LESS_OR_EQUAL(result, 100, ()); return result; } void Platform::SetupMeasurementSystem() const { auto units = measurement_utils::Units::Metric; if (settings::Get(settings::kMeasurementUnits, units)) return; BOOL const isMetric = [[[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleUsesMetricSystem] boolValue]; units = isMetric ? measurement_utils::Units::Metric : measurement_utils::Units::Imperial; settings::Set(settings::kMeasurementUnits, units); } //////////////////////////////////////////////////////////////////////// extern Platform & GetPlatform() { static Platform platform; return platform; }