DeviceSettings.mm 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. #include <sys/types.h>
  2. #include <sys/sysctl.h>
  3. #include "DisplayManager.h"
  4. // ad/vendor ids
  5. #if UNITY_USES_IAD
  6. #include <AdSupport/ASIdentifierManager.h>
  7. static id QueryASIdentifierManager()
  8. {
  9. NSBundle* bundle = [NSBundle bundleWithPath: @"/System/Library/Frameworks/AdSupport.framework"];
  10. if (bundle)
  11. {
  12. [bundle load];
  13. return [NSClassFromString(@"ASIdentifierManager") performSelector: @selector(sharedManager)];
  14. }
  15. return nil;
  16. }
  17. #endif
  18. extern "C" const char* UnityAdIdentifier()
  19. {
  20. static const char* _ADID = NULL;
  21. #if UNITY_USES_IAD
  22. static const NSString* _ADIDNSString = nil;
  23. // ad id can be reset during app lifetime
  24. id manager = QueryASIdentifierManager();
  25. if (manager)
  26. {
  27. NSString* adid = [[manager performSelector: @selector(advertisingIdentifier)] UUIDString];
  28. // Do stuff to avoid UTF8String leaks. We still leak if ADID changes, but that shouldn't happen too often.
  29. if (![_ADIDNSString isEqualToString: adid])
  30. {
  31. _ADIDNSString = adid;
  32. free((void*)_ADID);
  33. _ADID = AllocCString(adid);
  34. }
  35. }
  36. #endif
  37. return _ADID;
  38. }
  39. extern "C" int UnityGetLowPowerModeEnabled()
  40. {
  41. return [[NSProcessInfo processInfo] isLowPowerModeEnabled] ? 1 : 0;
  42. }
  43. extern "C" int UnityGetWantsSoftwareDimming()
  44. {
  45. #if !PLATFORM_TVOS
  46. UIScreen* mainScreen = [UIScreen mainScreen];
  47. return mainScreen.wantsSoftwareDimming ? 1 : 0;
  48. #else
  49. return 0;
  50. #endif
  51. }
  52. extern "C" void UnitySetWantsSoftwareDimming(int enabled)
  53. {
  54. #if !PLATFORM_TVOS
  55. UIScreen* mainScreen = [UIScreen mainScreen];
  56. mainScreen.wantsSoftwareDimming = enabled;
  57. #endif
  58. }
  59. extern "C" int UnityGetIosAppOnMac()
  60. {
  61. #if (PLATFORM_IOS && defined(__IPHONE_14_0)) || (PLATFORM_TVOS && defined(__TVOS_14_0))
  62. if (@available(iOS 14, tvOS 14, *))
  63. return [[NSProcessInfo processInfo] isiOSAppOnMac] ? 1 : 0;
  64. else
  65. return 0;
  66. #else
  67. return 0;
  68. #endif
  69. }
  70. extern "C" int UnityAdTrackingEnabled()
  71. {
  72. bool _AdTrackingEnabled = false;
  73. #if UNITY_USES_IAD
  74. // ad tracking can be changed during app lifetime
  75. id manager = QueryASIdentifierManager();
  76. if (manager)
  77. _AdTrackingEnabled = [manager performSelector: @selector(isAdvertisingTrackingEnabled)];
  78. #endif
  79. return _AdTrackingEnabled ? 1 : 0;
  80. }
  81. extern "C" const char* UnityVendorIdentifier()
  82. {
  83. static const char* _VendorID = NULL;
  84. if (_VendorID == NULL)
  85. _VendorID = AllocCString([[UIDevice currentDevice].identifierForVendor UUIDString]);
  86. return _VendorID;
  87. }
  88. // UIDevice properties
  89. #define QUERY_UIDEVICE_PROPERTY(FUNC, PROP) \
  90. extern "C" const char* FUNC() \
  91. { \
  92. static const char* value = NULL; \
  93. if (value == NULL && [UIDevice instancesRespondToSelector:@selector(PROP)]) \
  94. value = AllocCString([UIDevice currentDevice].PROP); \
  95. return value; \
  96. }
  97. QUERY_UIDEVICE_PROPERTY(UnityDeviceName, name)
  98. QUERY_UIDEVICE_PROPERTY(UnitySystemName, systemName)
  99. QUERY_UIDEVICE_PROPERTY(UnitySystemVersion, systemVersion)
  100. #undef QUERY_UIDEVICE_PROPERTY
  101. // hw info
  102. extern "C" const char* UnityDeviceModel()
  103. {
  104. static const char* _DeviceModel = NULL;
  105. if (_DeviceModel == NULL)
  106. {
  107. size_t size;
  108. ::sysctlbyname("hw.machine", NULL, &size, NULL, 0);
  109. char* model = (char*)::malloc(size + 1);
  110. ::sysctlbyname("hw.machine", model, &size, NULL, 0);
  111. model[size] = 0;
  112. #if TARGET_OS_SIMULATOR
  113. if (!strncmp(model, "i386", 4) || !strncmp(model, "x86_64", 6))
  114. {
  115. NSString* simModel = [[NSProcessInfo processInfo] environment][@"SIMULATOR_MODEL_IDENTIFIER"];
  116. if ([simModel length] > 0)
  117. {
  118. _DeviceModel = AllocCString(simModel);
  119. ::free(model);
  120. return _DeviceModel;
  121. }
  122. }
  123. #endif
  124. _DeviceModel = AllocCString([NSString stringWithUTF8String: model]);
  125. ::free(model);
  126. }
  127. return _DeviceModel;
  128. }
  129. extern "C" int UnityDeviceCPUCount()
  130. {
  131. static int _DeviceCPUCount = -1;
  132. if (_DeviceCPUCount <= 0)
  133. {
  134. // maybe would be better to use HW_AVAILCPU
  135. int ctlName[] = {CTL_HW, HW_NCPU};
  136. size_t dataLen = sizeof(_DeviceCPUCount);
  137. ::sysctl(ctlName, 2, &_DeviceCPUCount, &dataLen, NULL, 0);
  138. }
  139. return _DeviceCPUCount;
  140. }
  141. extern "C" int UnityGetPhysicalMemory()
  142. {
  143. return (int)(NSProcessInfo.processInfo.physicalMemory / (1024ULL * 1024ULL));
  144. }
  145. // misc
  146. extern "C" const char* UnitySystemLanguage()
  147. {
  148. static const char* _SystemLanguage = NULL;
  149. if (_SystemLanguage == NULL)
  150. {
  151. NSArray* lang = [[NSUserDefaults standardUserDefaults] objectForKey: @"AppleLanguages"];
  152. if (lang.count > 0)
  153. _SystemLanguage = AllocCString(lang[0]);
  154. }
  155. return _SystemLanguage;
  156. }
  157. enum DeviceType : uint8_t
  158. {
  159. deviceTypeUnknown = 0,
  160. iPhone = 1,
  161. iPad = 2,
  162. iPod = 3,
  163. AppleTV = 4
  164. };
  165. struct DeviceTableEntry
  166. {
  167. DeviceType deviceType;
  168. uint8_t majorGen;
  169. uint8_t minorGenMin;
  170. uint8_t minorGenMax;
  171. DeviceGeneration device;
  172. };
  173. DeviceTableEntry DeviceTable[] =
  174. {
  175. { iPhone, 2, 1, 1, deviceiPhone3GS },
  176. { iPhone, 3, 1, 3, deviceiPhone4 },
  177. { iPhone, 4, 1, 1, deviceiPhone4S },
  178. { iPhone, 5, 3, 4, deviceiPhone5C },
  179. { iPhone, 5, 1, 2, deviceiPhone5 },
  180. { iPhone, 6, 1, 2, deviceiPhone5S },
  181. { iPhone, 7, 2, 2, deviceiPhone6 },
  182. { iPhone, 7, 1, 1, deviceiPhone6Plus },
  183. { iPhone, 8, 1, 1, deviceiPhone6S },
  184. { iPhone, 8, 2, 2, deviceiPhone6SPlus },
  185. { iPhone, 8, 4, 4, deviceiPhoneSE1Gen },
  186. { iPhone, 9, 1, 1, deviceiPhone7 },
  187. { iPhone, 9, 3, 3, deviceiPhone7 },
  188. { iPhone, 9, 2, 2, deviceiPhone7Plus },
  189. { iPhone, 9, 4, 4, deviceiPhone7Plus },
  190. { iPhone, 10, 1, 1, deviceiPhone8 },
  191. { iPhone, 10, 4, 4, deviceiPhone8 },
  192. { iPhone, 10, 2, 2, deviceiPhone8Plus },
  193. { iPhone, 10, 5, 5, deviceiPhone8Plus },
  194. { iPhone, 10, 3, 3, deviceiPhoneX },
  195. { iPhone, 10, 6, 6, deviceiPhoneX },
  196. { iPhone, 11, 8, 8, deviceiPhoneXR },
  197. { iPhone, 11, 2, 2, deviceiPhoneXS },
  198. { iPhone, 11, 4, 4, deviceiPhoneXSMax },
  199. { iPhone, 11, 6, 6, deviceiPhoneXSMax },
  200. { iPhone, 12, 1, 1, deviceiPhone11 },
  201. { iPhone, 12, 3, 3, deviceiPhone11Pro },
  202. { iPhone, 12, 5, 5, deviceiPhone11ProMax },
  203. { iPhone, 12, 8, 8, deviceiPhoneSE2Gen },
  204. { iPhone, 13, 1, 1, deviceiPhone12Mini },
  205. { iPhone, 13, 2, 2, deviceiPhone12 },
  206. { iPhone, 13, 3, 3, deviceiPhone12Pro },
  207. { iPhone, 13, 4, 4, deviceiPhone12ProMax },
  208. { iPod, 4, 1, 1, deviceiPodTouch4Gen },
  209. { iPod, 5, 1, 1, deviceiPodTouch5Gen },
  210. { iPod, 7, 1, 1, deviceiPodTouch6Gen },
  211. { iPod, 9, 1, 1, deviceiPodTouch7Gen },
  212. { iPad, 2, 5, 7, deviceiPadMini1Gen },
  213. { iPad, 4, 4, 6, deviceiPadMini2Gen },
  214. { iPad, 4, 7, 9, deviceiPadMini3Gen },
  215. { iPad, 5, 1, 2, deviceiPadMini4Gen },
  216. { iPad, 11, 1, 2, deviceiPadMini5Gen },
  217. { iPad, 2, 1, 4, deviceiPad2Gen },
  218. { iPad, 3, 1, 3, deviceiPad3Gen },
  219. { iPad, 3, 4, 6, deviceiPad4Gen },
  220. { iPad, 6, 11, 12, deviceiPad5Gen },
  221. { iPad, 7, 5, 6, deviceiPad6Gen },
  222. { iPad, 7, 11, 12, deviceiPad7Gen },
  223. { iPad, 4, 1, 3, deviceiPadAir1 },
  224. { iPad, 5, 3, 4, deviceiPadAir2 },
  225. { iPad, 11, 3, 4, deviceiPadAir3Gen },
  226. { iPad, 6, 7, 8, deviceiPadPro1Gen },
  227. { iPad, 7, 1, 2, deviceiPadPro2Gen },
  228. { iPad, 6, 3, 4, deviceiPadPro10Inch1Gen },
  229. { iPad, 7, 3, 4, deviceiPadPro10Inch2Gen },
  230. { iPad, 8, 1, 4, deviceiPadPro11Inch },
  231. { iPad, 8, 9, 10, deviceiPadPro11Inch2Gen },
  232. { iPad, 8, 5, 8, deviceiPadPro3Gen },
  233. { iPad, 8, 11, 12, deviceiPadPro4Gen },
  234. { iPad, 11, 6, 7, deviceiPad8Gen },
  235. { iPad, 13, 1, 2, deviceiPadAir4Gen },
  236. { AppleTV, 5, 3, 3, deviceAppleTV1Gen },
  237. { AppleTV, 6, 2, 2, deviceAppleTV2Gen }
  238. };
  239. extern "C" int ParseDeviceGeneration(const char* model)
  240. {
  241. DeviceType deviceType = deviceTypeUnknown;
  242. if (!strncmp(model, "iPhone", 6))
  243. {
  244. deviceType = iPhone;
  245. model += 6;
  246. }
  247. else if (!strncmp(model, "iPad", 4))
  248. {
  249. deviceType = iPad;
  250. model += 4;
  251. }
  252. else if (!strncmp(model, "iPod", 4))
  253. {
  254. deviceType = iPod;
  255. model += 4;
  256. }
  257. else if (!strncmp(model, "AppleTV", 7))
  258. {
  259. deviceType = AppleTV;
  260. model += 7;
  261. }
  262. char* endPtr;
  263. int majorGen = (int)strtol(model, &endPtr, 10);
  264. int minorGen = (int)strtol(endPtr + 1, &endPtr, 10);
  265. if (strlen(endPtr) == 0)
  266. {
  267. for (int i = 0; i < sizeof(DeviceTable) / sizeof(DeviceTable[0]); ++i)
  268. {
  269. if (deviceType != DeviceTable[i].deviceType)
  270. continue;
  271. if (majorGen != DeviceTable[i].majorGen)
  272. continue;
  273. if (minorGen < DeviceTable[i].minorGenMin || minorGen > DeviceTable[i].minorGenMax)
  274. continue;
  275. return DeviceTable[i].device;
  276. }
  277. }
  278. if (deviceType == iPhone)
  279. return deviceiPhoneUnknown;
  280. else if (deviceType == iPad)
  281. return deviceiPadUnknown;
  282. else if (deviceType == iPod)
  283. return deviceiPodTouchUnknown;
  284. return deviceUnknown;
  285. }
  286. extern "C" int UnityDeviceGeneration()
  287. {
  288. static int _DeviceGeneration = deviceUnknown;
  289. if (_DeviceGeneration == deviceUnknown)
  290. {
  291. const char* model = UnityDeviceModel();
  292. _DeviceGeneration = ParseDeviceGeneration(model);
  293. }
  294. return _DeviceGeneration;
  295. }
  296. extern "C" int UnityDeviceSupportsUpsideDown()
  297. {
  298. switch (UnityDeviceGeneration())
  299. {
  300. // devices without home button
  301. case deviceiPhoneX: case deviceiPhoneXS: case deviceiPhoneXSMax: case deviceiPhoneXR:
  302. case deviceiPhone11: case deviceiPhone11Pro: case deviceiPhone11ProMax:
  303. return 0;
  304. default:
  305. return 1;
  306. }
  307. }
  308. extern "C" int UnityDeviceSupportedOrientations()
  309. {
  310. int orientations = (1 << portrait) | (1 << landscapeLeft) | (1 << landscapeRight);
  311. if (UnityDeviceSupportsUpsideDown())
  312. orientations |= (1 << portraitUpsideDown);
  313. return orientations;
  314. }
  315. extern "C" int UnityDeviceIsStylusTouchSupported()
  316. {
  317. const int deviceGen = UnityDeviceGeneration();
  318. return (deviceGen == deviceiPadPro1Gen ||
  319. deviceGen == deviceiPadPro10Inch1Gen ||
  320. deviceGen == deviceiPadPro2Gen ||
  321. deviceGen == deviceiPadPro10Inch2Gen ||
  322. deviceGen == deviceiPadPro11Inch ||
  323. deviceGen == deviceiPadPro3Gen ||
  324. deviceGen == deviceiPad6Gen) ? 1 : 0;
  325. }
  326. extern "C" int UnityDeviceCanShowWideColor()
  327. {
  328. return [UIScreen mainScreen].traitCollection.displayGamut == UIDisplayGamutP3;
  329. }
  330. extern "C" float UnityDeviceDPI()
  331. {
  332. static float _DeviceDPI = -1.0f;
  333. if (_DeviceDPI < 0.0f)
  334. {
  335. switch (UnityDeviceGeneration())
  336. {
  337. // iPhone
  338. case deviceiPhone3GS:
  339. _DeviceDPI = 163.0f; break;
  340. case deviceiPhone4:
  341. case deviceiPhone4S:
  342. case deviceiPhone5:
  343. case deviceiPhone5C:
  344. case deviceiPhone5S:
  345. case deviceiPhone6:
  346. case deviceiPhone6S:
  347. case deviceiPhoneSE1Gen:
  348. case deviceiPhone7:
  349. case deviceiPhone8:
  350. case deviceiPhoneXR:
  351. case deviceiPhone11:
  352. case deviceiPhoneSE2Gen:
  353. _DeviceDPI = 326.0f; break;
  354. case deviceiPhone6Plus:
  355. case deviceiPhone6SPlus:
  356. case deviceiPhone7Plus:
  357. case deviceiPhone8Plus:
  358. _DeviceDPI = 401.0f; break;
  359. case deviceiPhoneX:
  360. case deviceiPhoneXS:
  361. case deviceiPhoneXSMax:
  362. case deviceiPhone11Pro:
  363. case deviceiPhone11ProMax:
  364. case deviceiPhone12ProMax:
  365. _DeviceDPI = 458.0f; break;
  366. case deviceiPhone12:
  367. case deviceiPhone12Pro:
  368. _DeviceDPI = 460.0f; break;
  369. case deviceiPhone12Mini:
  370. _DeviceDPI = 476.0f; break;
  371. // iPad
  372. case deviceiPad2Gen:
  373. _DeviceDPI = 132.0f; break;
  374. case deviceiPad3Gen:
  375. case deviceiPad4Gen: // iPad retina
  376. case deviceiPadAir1:
  377. case deviceiPadAir2:
  378. case deviceiPadAir3Gen:
  379. case deviceiPadPro1Gen:
  380. case deviceiPadPro10Inch1Gen:
  381. case deviceiPadPro2Gen:
  382. case deviceiPadPro10Inch2Gen:
  383. case deviceiPad5Gen:
  384. case deviceiPad6Gen:
  385. case deviceiPadPro11Inch:
  386. case deviceiPadPro3Gen:
  387. case deviceiPadPro11Inch2Gen:
  388. case deviceiPadPro4Gen:
  389. case deviceiPad8Gen:
  390. case deviceiPadAir4Gen:
  391. _DeviceDPI = 264.0f; break;
  392. case deviceiPad7Gen:
  393. _DeviceDPI = 326.0f; break;
  394. // iPad mini
  395. case deviceiPadMini1Gen:
  396. _DeviceDPI = 163.0f; break;
  397. case deviceiPadMini2Gen:
  398. case deviceiPadMini3Gen:
  399. case deviceiPadMini4Gen:
  400. case deviceiPadMini5Gen:
  401. _DeviceDPI = 326.0f; break;
  402. // iPod
  403. case deviceiPodTouch4Gen:
  404. case deviceiPodTouch5Gen:
  405. case deviceiPodTouch6Gen:
  406. case deviceiPodTouch7Gen:
  407. _DeviceDPI = 326.0f; break;
  408. // unknown (new) devices
  409. case deviceiPhoneUnknown:
  410. _DeviceDPI = 326.0f; break;
  411. case deviceiPadUnknown:
  412. _DeviceDPI = 264.0f; break;
  413. case deviceiPodTouchUnknown:
  414. _DeviceDPI = 326.0f; break;
  415. }
  416. // If we didn't find DPI, set it to "unknown" value.
  417. if (_DeviceDPI < 0.0f)
  418. _DeviceDPI = 0.0f;
  419. }
  420. return _DeviceDPI;
  421. }
  422. // device id with fallback for pre-ios7
  423. extern "C" const char* UnityDeviceUniqueIdentifier()
  424. {
  425. static const char* _DeviceID = NULL;
  426. if (_DeviceID == NULL)
  427. _DeviceID = UnityVendorIdentifier();
  428. return _DeviceID;
  429. }