#include #include #include "DisplayManager.h" // ad/vendor ids #if UNITY_USES_IAD #include static id QueryASIdentifierManager() { NSBundle* bundle = [NSBundle bundleWithPath: @"/System/Library/Frameworks/AdSupport.framework"]; if (bundle) { [bundle load]; Class retClass = [bundle classNamed: @"ASIdentifierManager"]; return [retClass performSelector: @selector(sharedManager)]; } return nil; } #endif extern "C" const char* UnityAdvertisingIdentifier() { static const char* _ADID = NULL; #if UNITY_USES_IAD static const NSString* _ADIDNSString = nil; // ad id can be reset during app lifetime id manager = QueryASIdentifierManager(); if (manager) { NSString* adid = [[manager performSelector: @selector(advertisingIdentifier)] UUIDString]; // Do stuff to avoid UTF8String leaks. We still leak if ADID changes, but that shouldn't happen too often. if (![_ADIDNSString isEqualToString: adid]) { _ADIDNSString = adid; free((void*)_ADID); _ADID = AllocCString(adid); } } #endif return _ADID; } extern "C" int UnityAdvertisingTrackingEnabled() { bool _AdTrackingEnabled = false; #if UNITY_USES_IAD // ad tracking can be changed during app lifetime id manager = QueryASIdentifierManager(); if (manager) _AdTrackingEnabled = [manager performSelector: @selector(isAdvertisingTrackingEnabled)]; #endif return _AdTrackingEnabled ? 1 : 0; } extern "C" const char* UnityVendorIdentifier() { static const char* _VendorID = NULL; if (_VendorID == NULL) _VendorID = AllocCString([[UIDevice currentDevice].identifierForVendor UUIDString]); return _VendorID; } // UIDevice properties #define QUERY_UIDEVICE_PROPERTY(FUNC, PROP) \ extern "C" const char* FUNC() \ { \ static const char* value = NULL; \ if (value == NULL && [UIDevice instancesRespondToSelector:@selector(PROP)]) \ value = AllocCString([UIDevice currentDevice].PROP); \ return value; \ } QUERY_UIDEVICE_PROPERTY(UnityDeviceName, name) QUERY_UIDEVICE_PROPERTY(UnitySystemName, systemName) QUERY_UIDEVICE_PROPERTY(UnitySystemVersion, systemVersion) #undef QUERY_UIDEVICE_PROPERTY // hw info extern "C" const char* UnityDeviceModel() { static const char* _DeviceModel = NULL; if (_DeviceModel == NULL) { size_t size; ::sysctlbyname("hw.machine", NULL, &size, NULL, 0); char* model = (char*)::malloc(size + 1); ::sysctlbyname("hw.machine", model, &size, NULL, 0); model[size] = 0; _DeviceModel = AllocCString([NSString stringWithUTF8String: model]); ::free(model); } return _DeviceModel; } extern "C" int UnityDeviceCPUCount() { static int _DeviceCPUCount = -1; if (_DeviceCPUCount <= 0) { // maybe would be better to use HW_AVAILCPU int ctlName[] = {CTL_HW, HW_NCPU}; size_t dataLen = sizeof(_DeviceCPUCount); ::sysctl(ctlName, 2, &_DeviceCPUCount, &dataLen, NULL, 0); } return _DeviceCPUCount; } extern "C" int UnityGetPhysicalMemory() { return ([[NSProcessInfo processInfo] physicalMemory]) / (1024 * 1024); } // misc extern "C" const char* UnitySystemLanguage() { static const char* _SystemLanguage = NULL; if (_SystemLanguage == NULL) { NSArray* lang = [[NSUserDefaults standardUserDefaults] objectForKey: @"AppleLanguages"]; if (lang.count > 0) _SystemLanguage = AllocCString(lang[0]); } return _SystemLanguage; } extern "C" int UnityDeviceGeneration() { static int _DeviceGeneration = deviceUnknown; if (_DeviceGeneration == deviceUnknown) { const char* model = UnityDeviceModel(); if (!strcmp(model, "iPhone2,1")) _DeviceGeneration = deviceiPhone3GS; else if (!strncmp(model, "iPhone3,", 8)) _DeviceGeneration = deviceiPhone4; else if (!strncmp(model, "iPhone4,", 8)) _DeviceGeneration = deviceiPhone4S; else if (!strncmp(model, "iPhone5,", 8)) { int rev = atoi(model + 8); if (rev >= 3) _DeviceGeneration = deviceiPhone5C; // iPhone5,3 else _DeviceGeneration = deviceiPhone5; } else if (!strncmp(model, "iPhone6,", 8)) _DeviceGeneration = deviceiPhone5S; else if (!strncmp(model, "iPhone7,2", 9)) _DeviceGeneration = deviceiPhone6; else if (!strncmp(model, "iPhone7,1", 9)) _DeviceGeneration = deviceiPhone6Plus; else if (!strncmp(model, "iPhone8,1", 9)) _DeviceGeneration = deviceiPhone6S; else if (!strncmp(model, "iPhone8,2", 9)) _DeviceGeneration = deviceiPhone6SPlus; else if (!strncmp(model, "iPhone8,4", 9)) _DeviceGeneration = deviceiPhoneSE1Gen; else if (!strncmp(model, "iPhone9,1", 9) || !strncmp(model, "iPhone9,3", 9)) _DeviceGeneration = deviceiPhone7; else if (!strncmp(model, "iPhone9,2", 9) || !strncmp(model, "iPhone9,4", 9)) _DeviceGeneration = deviceiPhone7Plus; else if (!strncmp(model, "iPhone10,1", 10) || !strncmp(model, "iPhone10,4", 10)) _DeviceGeneration = deviceiPhone8; else if (!strncmp(model, "iPhone10,2", 10) || !strncmp(model, "iPhone10,5", 10)) _DeviceGeneration = deviceiPhone8Plus; else if (!strncmp(model, "iPhone10,3", 10) || !strncmp(model, "iPhone10,6", 10)) _DeviceGeneration = deviceiPhoneX; else if (!strncmp(model, "iPhone11,8", 10)) _DeviceGeneration = deviceiPhoneXR; else if (!strncmp(model, "iPhone11,2", 10)) _DeviceGeneration = deviceiPhoneXS; else if (!strncmp(model, "iPhone11,4", 10) || !strncmp(model, "iPhone11,6", 10)) _DeviceGeneration = deviceiPhoneXSMax; else if (!strncmp(model, "iPhone12,1", 11)) _DeviceGeneration = deviceiPhone11; else if (!strncmp(model, "iPhone12,3", 11)) _DeviceGeneration = deviceiPhone11Pro; else if (!strncmp(model, "iPhone12,5", 11)) _DeviceGeneration = deviceiPhone11ProMax; else if (!strcmp(model, "iPod4,1")) _DeviceGeneration = deviceiPodTouch4Gen; else if (!strncmp(model, "iPod5,", 6)) _DeviceGeneration = deviceiPodTouch5Gen; else if (!strncmp(model, "iPod7,", 6)) _DeviceGeneration = deviceiPodTouch6Gen; else if (!strncmp(model, "iPad2,", 6)) { int rev = atoi(model + 6); if (rev >= 5) _DeviceGeneration = deviceiPadMini1Gen; // iPad2,5 else _DeviceGeneration = deviceiPad2Gen; } else if (!strncmp(model, "iPad3,", 6)) { int rev = atoi(model + 6); if (rev >= 4) _DeviceGeneration = deviceiPad4Gen; // iPad3,4 else _DeviceGeneration = deviceiPad3Gen; } else if (!strncmp(model, "iPad4,", 6)) { int rev = atoi(model + 6); if (rev >= 7) _DeviceGeneration = deviceiPadMini3Gen; else if (rev >= 4) _DeviceGeneration = deviceiPadMini2Gen; // iPad4,4 else _DeviceGeneration = deviceiPadAir1; } else if (!strncmp(model, "iPad5,", 6)) { int rev = atoi(model + 6); if (rev == 1 || rev == 2) _DeviceGeneration = deviceiPadMini4Gen; else if (rev >= 3) _DeviceGeneration = deviceiPadAir2; } else if (!strncmp(model, "iPad6,", 6)) { int rev = atoi(model + 6); if (rev == 7 || rev == 8) _DeviceGeneration = deviceiPadPro1Gen; else if (rev == 3 || rev == 4) _DeviceGeneration = deviceiPadPro10Inch1Gen; else if (rev == 11 || rev == 12) _DeviceGeneration = deviceiPad5Gen; } else if (!strncmp(model, "iPad7,", 6)) { int rev = atoi(model + 6); if (rev == 1 || rev == 2) _DeviceGeneration = deviceiPadPro2Gen; else if (rev == 3 || rev == 4) _DeviceGeneration = deviceiPadPro10Inch2Gen; } else if (!strncmp(model, "iPad8,", 6)) { int rev = atoi(model + 6); if (rev >= 1 && rev <= 4) _DeviceGeneration = deviceiPadPro11Inch; else if (rev >= 5) _DeviceGeneration = deviceiPadPro3Gen; } // completely unknown hw - just determine form-factor if (_DeviceGeneration == deviceUnknown) { if (!strncmp(model, "iPhone", 6)) _DeviceGeneration = deviceiPhoneUnknown; else if (!strncmp(model, "iPad", 4)) _DeviceGeneration = deviceiPadUnknown; else if (!strncmp(model, "iPod", 4)) _DeviceGeneration = deviceiPodTouchUnknown; else _DeviceGeneration = deviceUnknown; } } return _DeviceGeneration; } extern "C" int UnityDeviceSupportsUpsideDown() { switch (UnityDeviceGeneration()) { // devices without home button case deviceiPhoneX: case deviceiPhoneXS: case deviceiPhoneXSMax: case deviceiPhoneXR: case deviceiPhone11: case deviceiPhone11Pro: case deviceiPhone11ProMax: return 0; default: return 1; } } extern "C" int UnityDeviceIsStylusTouchSupported() { int deviceGen = UnityDeviceGeneration(); return (deviceGen == deviceiPadPro1Gen || deviceGen == deviceiPadPro10Inch1Gen || deviceGen == deviceiPadPro2Gen || deviceGen == deviceiPadPro10Inch2Gen) ? 1 : 0; } extern "C" int UnityDeviceIsWideColorSupported() { UIScreen* mainScreen = [UIScreen mainScreen]; if (![mainScreen respondsToSelector: @selector(traitCollection)]) return false; UITraitCollection* traits = mainScreen.traitCollection; if (![traits respondsToSelector: @selector(displayGamut)]) return false; #if UNITY_HAS_IOSSDK_10_0 || UNITY_HAS_TVOSSDK_10_0 return traits.displayGamut == UIDisplayGamutP3; #else return false; #endif } extern "C" float UnityDeviceDPI() { static float _DeviceDPI = -1.0f; if (_DeviceDPI < 0.0f) { switch (UnityDeviceGeneration()) { // iPhone case deviceiPhone3GS: _DeviceDPI = 163.0f; break; case deviceiPhone4: case deviceiPhone4S: case deviceiPhone5: case deviceiPhone5C: case deviceiPhone5S: case deviceiPhone6: case deviceiPhone6S: case deviceiPhoneSE1Gen: case deviceiPhone7: case deviceiPhone8: case deviceiPhoneXR: case deviceiPhone11: _DeviceDPI = 326.0f; break; case deviceiPhone6Plus: case deviceiPhone6SPlus: case deviceiPhone7Plus: case deviceiPhone8Plus: _DeviceDPI = 401.0f; break; case deviceiPhoneX: case deviceiPhoneXS: case deviceiPhoneXSMax: case deviceiPhone11Pro: case deviceiPhone11ProMax: _DeviceDPI = 458.0f; break; // iPad case deviceiPad2Gen: _DeviceDPI = 132.0f; break; case deviceiPad3Gen: case deviceiPad4Gen: // iPad retina case deviceiPadAir1: case deviceiPadAir2: case deviceiPadPro1Gen: case deviceiPadPro10Inch1Gen: case deviceiPadPro2Gen: case deviceiPadPro10Inch2Gen: case deviceiPad5Gen: case deviceiPadPro11Inch: case deviceiPadPro3Gen: _DeviceDPI = 264.0f; break; // iPad mini case deviceiPadMini1Gen: _DeviceDPI = 163.0f; break; case deviceiPadMini2Gen: case deviceiPadMini3Gen: case deviceiPadMini4Gen: _DeviceDPI = 326.0f; break; // iPod case deviceiPodTouch4Gen: case deviceiPodTouch5Gen: case deviceiPodTouch6Gen: _DeviceDPI = 326.0f; break; // unknown (new) devices case deviceiPhoneUnknown: _DeviceDPI = 326.0f; break; case deviceiPadUnknown: _DeviceDPI = 264.0f; break; case deviceiPodTouchUnknown: _DeviceDPI = 326.0f; break; } // If we didn't find DPI, set it to "unknown" value. if (_DeviceDPI < 0.0f) _DeviceDPI = 0.0f; } return _DeviceDPI; } // device id with fallback for pre-ios7 extern "C" const char* UnityDeviceUniqueIdentifier() { static const char* _DeviceID = NULL; if (_DeviceID == NULL) _DeviceID = UnityVendorIdentifier(); return _DeviceID; }