UIDevice+YYAdd.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. //
  2. // UIDevice+YYAdd.m
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 13/4/3.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import "UIDevice+YYAdd.h"
  12. #include <sys/socket.h>
  13. #include <sys/sysctl.h>
  14. #include <net/if.h>
  15. #include <net/if_dl.h>
  16. #include <mach/mach.h>
  17. #include <arpa/inet.h>
  18. #include <ifaddrs.h>
  19. #import "YYKitMacro.h"
  20. #import "NSString+YYAdd.h"
  21. YYSYNTH_DUMMY_CLASS(UIDevice_YYAdd)
  22. @implementation UIDevice (YYAdd)
  23. + (double)systemVersion {
  24. static double version;
  25. static dispatch_once_t onceToken;
  26. dispatch_once(&onceToken, ^{
  27. version = [UIDevice currentDevice].systemVersion.doubleValue;
  28. });
  29. return version;
  30. }
  31. - (BOOL)isPad {
  32. static dispatch_once_t one;
  33. static BOOL pad;
  34. dispatch_once(&one, ^{
  35. pad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
  36. });
  37. return pad;
  38. }
  39. - (BOOL)isSimulator {
  40. #if TARGET_OS_SIMULATOR
  41. return YES;
  42. #else
  43. return NO;
  44. #endif
  45. }
  46. - (BOOL)isJailbroken {
  47. if ([self isSimulator]) return NO; // Dont't check simulator
  48. // iOS9 URL Scheme query changed ...
  49. // NSURL *cydiaURL = [NSURL URLWithString:@"cydia://package"];
  50. // if ([[UIApplication sharedApplication] canOpenURL:cydiaURL]) return YES;
  51. NSArray *paths = @[@"/Applications/Cydia.app",
  52. @"/private/var/lib/apt/",
  53. @"/private/var/lib/cydia",
  54. @"/private/var/stash"];
  55. for (NSString *path in paths) {
  56. if ([[NSFileManager defaultManager] fileExistsAtPath:path]) return YES;
  57. }
  58. FILE *bash = fopen("/bin/bash", "r");
  59. if (bash != NULL) {
  60. fclose(bash);
  61. return YES;
  62. }
  63. NSString *path = [NSString stringWithFormat:@"/private/%@", [NSString stringWithUUID]];
  64. if ([@"test" writeToFile : path atomically : YES encoding : NSUTF8StringEncoding error : NULL]) {
  65. [[NSFileManager defaultManager] removeItemAtPath:path error:nil];
  66. return YES;
  67. }
  68. return NO;
  69. }
  70. #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
  71. - (BOOL)canMakePhoneCalls {
  72. __block BOOL can;
  73. static dispatch_once_t onceToken;
  74. dispatch_once(&onceToken, ^{
  75. can = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]];
  76. });
  77. return can;
  78. }
  79. #endif
  80. - (NSString *)ipAddressWithIfaName:(NSString *)name {
  81. if (name.length == 0) return nil;
  82. NSString *address = nil;
  83. struct ifaddrs *addrs = NULL;
  84. if (getifaddrs(&addrs) == 0) {
  85. struct ifaddrs *addr = addrs;
  86. while (addr) {
  87. if ([[NSString stringWithUTF8String:addr->ifa_name] isEqualToString:name]) {
  88. sa_family_t family = addr->ifa_addr->sa_family;
  89. switch (family) {
  90. case AF_INET: { // IPv4
  91. char str[INET_ADDRSTRLEN] = {0};
  92. inet_ntop(family, &(((struct sockaddr_in *)addr->ifa_addr)->sin_addr), str, sizeof(str));
  93. if (strlen(str) > 0) {
  94. address = [NSString stringWithUTF8String:str];
  95. }
  96. } break;
  97. case AF_INET6: { // IPv6
  98. char str[INET6_ADDRSTRLEN] = {0};
  99. inet_ntop(family, &(((struct sockaddr_in6 *)addr->ifa_addr)->sin6_addr), str, sizeof(str));
  100. if (strlen(str) > 0) {
  101. address = [NSString stringWithUTF8String:str];
  102. }
  103. }
  104. default: break;
  105. }
  106. if (address) break;
  107. }
  108. addr = addr->ifa_next;
  109. }
  110. }
  111. freeifaddrs(addrs);
  112. return address;
  113. }
  114. - (NSString *)ipAddressWIFI {
  115. return [self ipAddressWithIfaName:@"en0"];
  116. }
  117. - (NSString *)ipAddressCell {
  118. return [self ipAddressWithIfaName:@"pdp_ip0"];
  119. }
  120. typedef struct {
  121. uint64_t en_in;
  122. uint64_t en_out;
  123. uint64_t pdp_ip_in;
  124. uint64_t pdp_ip_out;
  125. uint64_t awdl_in;
  126. uint64_t awdl_out;
  127. } yy_net_interface_counter;
  128. static uint64_t yy_net_counter_add(uint64_t counter, uint64_t bytes) {
  129. if (bytes < (counter % 0xFFFFFFFF)) {
  130. counter += 0xFFFFFFFF - (counter % 0xFFFFFFFF);
  131. counter += bytes;
  132. } else {
  133. counter = bytes;
  134. }
  135. return counter;
  136. }
  137. static uint64_t yy_net_counter_get_by_type(yy_net_interface_counter *counter, YYNetworkTrafficType type) {
  138. uint64_t bytes = 0;
  139. if (type & YYNetworkTrafficTypeWWANSent) bytes += counter->pdp_ip_out;
  140. if (type & YYNetworkTrafficTypeWWANReceived) bytes += counter->pdp_ip_in;
  141. if (type & YYNetworkTrafficTypeWIFISent) bytes += counter->en_out;
  142. if (type & YYNetworkTrafficTypeWIFIReceived) bytes += counter->en_in;
  143. if (type & YYNetworkTrafficTypeAWDLSent) bytes += counter->awdl_out;
  144. if (type & YYNetworkTrafficTypeAWDLReceived) bytes += counter->awdl_in;
  145. return bytes;
  146. }
  147. static yy_net_interface_counter yy_get_net_interface_counter() {
  148. static dispatch_semaphore_t lock;
  149. static NSMutableDictionary *sharedInCounters;
  150. static NSMutableDictionary *sharedOutCounters;
  151. static dispatch_once_t onceToken;
  152. dispatch_once(&onceToken, ^{
  153. sharedInCounters = [NSMutableDictionary new];
  154. sharedOutCounters = [NSMutableDictionary new];
  155. lock = dispatch_semaphore_create(1);
  156. });
  157. yy_net_interface_counter counter = {0};
  158. struct ifaddrs *addrs;
  159. const struct ifaddrs *cursor;
  160. if (getifaddrs(&addrs) == 0) {
  161. cursor = addrs;
  162. dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
  163. while (cursor) {
  164. if (cursor->ifa_addr->sa_family == AF_LINK) {
  165. const struct if_data *data = cursor->ifa_data;
  166. NSString *name = cursor->ifa_name ? [NSString stringWithUTF8String:cursor->ifa_name] : nil;
  167. if (name) {
  168. uint64_t counter_in = ((NSNumber *)sharedInCounters[name]).unsignedLongLongValue;
  169. counter_in = yy_net_counter_add(counter_in, data->ifi_ibytes);
  170. sharedInCounters[name] = @(counter_in);
  171. uint64_t counter_out = ((NSNumber *)sharedOutCounters[name]).unsignedLongLongValue;
  172. counter_out = yy_net_counter_add(counter_out, data->ifi_obytes);
  173. sharedOutCounters[name] = @(counter_out);
  174. if ([name hasPrefix:@"en"]) {
  175. counter.en_in += counter_in;
  176. counter.en_out += counter_out;
  177. } else if ([name hasPrefix:@"awdl"]) {
  178. counter.awdl_in += counter_in;
  179. counter.awdl_out += counter_out;
  180. } else if ([name hasPrefix:@"pdp_ip"]) {
  181. counter.pdp_ip_in += counter_in;
  182. counter.pdp_ip_out += counter_out;
  183. }
  184. }
  185. }
  186. cursor = cursor->ifa_next;
  187. }
  188. dispatch_semaphore_signal(lock);
  189. freeifaddrs(addrs);
  190. }
  191. return counter;
  192. }
  193. - (uint64_t)getNetworkTrafficBytes:(YYNetworkTrafficType)types {
  194. yy_net_interface_counter counter = yy_get_net_interface_counter();
  195. return yy_net_counter_get_by_type(&counter, types);
  196. }
  197. - (NSString *)machineModel {
  198. static dispatch_once_t one;
  199. static NSString *model;
  200. dispatch_once(&one, ^{
  201. size_t size;
  202. sysctlbyname("hw.machine", NULL, &size, NULL, 0);
  203. char *machine = malloc(size);
  204. sysctlbyname("hw.machine", machine, &size, NULL, 0);
  205. model = [NSString stringWithUTF8String:machine];
  206. free(machine);
  207. });
  208. return model;
  209. }
  210. - (NSString *)machineModelName {
  211. static dispatch_once_t one;
  212. static NSString *name;
  213. dispatch_once(&one, ^{
  214. NSString *model = [self machineModel];
  215. if (!model) return;
  216. NSDictionary *dic = @{
  217. @"Watch1,1" : @"Apple Watch 38mm",
  218. @"Watch1,2" : @"Apple Watch 42mm",
  219. @"Watch2,3" : @"Apple Watch Series 2 38mm",
  220. @"Watch2,4" : @"Apple Watch Series 2 42mm",
  221. @"Watch2,6" : @"Apple Watch Series 1 38mm",
  222. @"Watch1,7" : @"Apple Watch Series 1 42mm",
  223. @"iPod1,1" : @"iPod touch 1",
  224. @"iPod2,1" : @"iPod touch 2",
  225. @"iPod3,1" : @"iPod touch 3",
  226. @"iPod4,1" : @"iPod touch 4",
  227. @"iPod5,1" : @"iPod touch 5",
  228. @"iPod7,1" : @"iPod touch 6",
  229. @"iPhone1,1" : @"iPhone 1G",
  230. @"iPhone1,2" : @"iPhone 3G",
  231. @"iPhone2,1" : @"iPhone 3GS",
  232. @"iPhone3,1" : @"iPhone 4 (GSM)",
  233. @"iPhone3,2" : @"iPhone 4",
  234. @"iPhone3,3" : @"iPhone 4 (CDMA)",
  235. @"iPhone4,1" : @"iPhone 4S",
  236. @"iPhone5,1" : @"iPhone 5",
  237. @"iPhone5,2" : @"iPhone 5",
  238. @"iPhone5,3" : @"iPhone 5c",
  239. @"iPhone5,4" : @"iPhone 5c",
  240. @"iPhone6,1" : @"iPhone 5s",
  241. @"iPhone6,2" : @"iPhone 5s",
  242. @"iPhone7,1" : @"iPhone 6 Plus",
  243. @"iPhone7,2" : @"iPhone 6",
  244. @"iPhone8,1" : @"iPhone 6s",
  245. @"iPhone8,2" : @"iPhone 6s Plus",
  246. @"iPhone8,4" : @"iPhone SE",
  247. @"iPhone9,1" : @"iPhone 7",
  248. @"iPhone9,2" : @"iPhone 7 Plus",
  249. @"iPhone9,3" : @"iPhone 7",
  250. @"iPhone9,4" : @"iPhone 7 Plus",
  251. @"iPad1,1" : @"iPad 1",
  252. @"iPad2,1" : @"iPad 2 (WiFi)",
  253. @"iPad2,2" : @"iPad 2 (GSM)",
  254. @"iPad2,3" : @"iPad 2 (CDMA)",
  255. @"iPad2,4" : @"iPad 2",
  256. @"iPad2,5" : @"iPad mini 1",
  257. @"iPad2,6" : @"iPad mini 1",
  258. @"iPad2,7" : @"iPad mini 1",
  259. @"iPad3,1" : @"iPad 3 (WiFi)",
  260. @"iPad3,2" : @"iPad 3 (4G)",
  261. @"iPad3,3" : @"iPad 3 (4G)",
  262. @"iPad3,4" : @"iPad 4",
  263. @"iPad3,5" : @"iPad 4",
  264. @"iPad3,6" : @"iPad 4",
  265. @"iPad4,1" : @"iPad Air",
  266. @"iPad4,2" : @"iPad Air",
  267. @"iPad4,3" : @"iPad Air",
  268. @"iPad4,4" : @"iPad mini 2",
  269. @"iPad4,5" : @"iPad mini 2",
  270. @"iPad4,6" : @"iPad mini 2",
  271. @"iPad4,7" : @"iPad mini 3",
  272. @"iPad4,8" : @"iPad mini 3",
  273. @"iPad4,9" : @"iPad mini 3",
  274. @"iPad5,1" : @"iPad mini 4",
  275. @"iPad5,2" : @"iPad mini 4",
  276. @"iPad5,3" : @"iPad Air 2",
  277. @"iPad5,4" : @"iPad Air 2",
  278. @"iPad6,3" : @"iPad Pro (9.7 inch)",
  279. @"iPad6,4" : @"iPad Pro (9.7 inch)",
  280. @"iPad6,7" : @"iPad Pro (12.9 inch)",
  281. @"iPad6,8" : @"iPad Pro (12.9 inch)",
  282. @"AppleTV2,1" : @"Apple TV 2",
  283. @"AppleTV3,1" : @"Apple TV 3",
  284. @"AppleTV3,2" : @"Apple TV 3",
  285. @"AppleTV5,3" : @"Apple TV 4",
  286. @"i386" : @"Simulator x86",
  287. @"x86_64" : @"Simulator x64",
  288. };
  289. name = dic[model];
  290. if (!name) name = model;
  291. });
  292. return name;
  293. }
  294. - (NSDate *)systemUptime {
  295. NSTimeInterval time = [[NSProcessInfo processInfo] systemUptime];
  296. return [[NSDate alloc] initWithTimeIntervalSinceNow:(0 - time)];
  297. }
  298. - (int64_t)diskSpace {
  299. NSError *error = nil;
  300. NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
  301. if (error) return -1;
  302. int64_t space = [[attrs objectForKey:NSFileSystemSize] longLongValue];
  303. if (space < 0) space = -1;
  304. return space;
  305. }
  306. - (int64_t)diskSpaceFree {
  307. NSError *error = nil;
  308. NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
  309. if (error) return -1;
  310. int64_t space = [[attrs objectForKey:NSFileSystemFreeSize] longLongValue];
  311. if (space < 0) space = -1;
  312. return space;
  313. }
  314. - (int64_t)diskSpaceUsed {
  315. int64_t total = self.diskSpace;
  316. int64_t free = self.diskSpaceFree;
  317. if (total < 0 || free < 0) return -1;
  318. int64_t used = total - free;
  319. if (used < 0) used = -1;
  320. return used;
  321. }
  322. - (int64_t)memoryTotal {
  323. int64_t mem = [[NSProcessInfo processInfo] physicalMemory];
  324. if (mem < -1) mem = -1;
  325. return mem;
  326. }
  327. - (int64_t)memoryUsed {
  328. mach_port_t host_port = mach_host_self();
  329. mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
  330. vm_size_t page_size;
  331. vm_statistics_data_t vm_stat;
  332. kern_return_t kern;
  333. kern = host_page_size(host_port, &page_size);
  334. if (kern != KERN_SUCCESS) return -1;
  335. kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
  336. if (kern != KERN_SUCCESS) return -1;
  337. return page_size * (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count);
  338. }
  339. - (int64_t)memoryFree {
  340. mach_port_t host_port = mach_host_self();
  341. mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
  342. vm_size_t page_size;
  343. vm_statistics_data_t vm_stat;
  344. kern_return_t kern;
  345. kern = host_page_size(host_port, &page_size);
  346. if (kern != KERN_SUCCESS) return -1;
  347. kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
  348. if (kern != KERN_SUCCESS) return -1;
  349. return vm_stat.free_count * page_size;
  350. }
  351. - (int64_t)memoryActive {
  352. mach_port_t host_port = mach_host_self();
  353. mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
  354. vm_size_t page_size;
  355. vm_statistics_data_t vm_stat;
  356. kern_return_t kern;
  357. kern = host_page_size(host_port, &page_size);
  358. if (kern != KERN_SUCCESS) return -1;
  359. kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
  360. if (kern != KERN_SUCCESS) return -1;
  361. return vm_stat.active_count * page_size;
  362. }
  363. - (int64_t)memoryInactive {
  364. mach_port_t host_port = mach_host_self();
  365. mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
  366. vm_size_t page_size;
  367. vm_statistics_data_t vm_stat;
  368. kern_return_t kern;
  369. kern = host_page_size(host_port, &page_size);
  370. if (kern != KERN_SUCCESS) return -1;
  371. kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
  372. if (kern != KERN_SUCCESS) return -1;
  373. return vm_stat.inactive_count * page_size;
  374. }
  375. - (int64_t)memoryWired {
  376. mach_port_t host_port = mach_host_self();
  377. mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
  378. vm_size_t page_size;
  379. vm_statistics_data_t vm_stat;
  380. kern_return_t kern;
  381. kern = host_page_size(host_port, &page_size);
  382. if (kern != KERN_SUCCESS) return -1;
  383. kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
  384. if (kern != KERN_SUCCESS) return -1;
  385. return vm_stat.wire_count * page_size;
  386. }
  387. - (int64_t)memoryPurgable {
  388. mach_port_t host_port = mach_host_self();
  389. mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
  390. vm_size_t page_size;
  391. vm_statistics_data_t vm_stat;
  392. kern_return_t kern;
  393. kern = host_page_size(host_port, &page_size);
  394. if (kern != KERN_SUCCESS) return -1;
  395. kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
  396. if (kern != KERN_SUCCESS) return -1;
  397. return vm_stat.purgeable_count * page_size;
  398. }
  399. - (NSUInteger)cpuCount {
  400. return [NSProcessInfo processInfo].activeProcessorCount;
  401. }
  402. - (float)cpuUsage {
  403. float cpu = 0;
  404. NSArray *cpus = [self cpuUsagePerProcessor];
  405. if (cpus.count == 0) return -1;
  406. for (NSNumber *n in cpus) {
  407. cpu += n.floatValue;
  408. }
  409. return cpu;
  410. }
  411. - (NSArray *)cpuUsagePerProcessor {
  412. processor_info_array_t _cpuInfo, _prevCPUInfo = nil;
  413. mach_msg_type_number_t _numCPUInfo, _numPrevCPUInfo = 0;
  414. unsigned _numCPUs;
  415. NSLock *_cpuUsageLock;
  416. int _mib[2U] = { CTL_HW, HW_NCPU };
  417. size_t _sizeOfNumCPUs = sizeof(_numCPUs);
  418. int _status = sysctl(_mib, 2U, &_numCPUs, &_sizeOfNumCPUs, NULL, 0U);
  419. if (_status)
  420. _numCPUs = 1;
  421. _cpuUsageLock = [[NSLock alloc] init];
  422. natural_t _numCPUsU = 0U;
  423. kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &_numCPUsU, &_cpuInfo, &_numCPUInfo);
  424. if (err == KERN_SUCCESS) {
  425. [_cpuUsageLock lock];
  426. NSMutableArray *cpus = [NSMutableArray new];
  427. for (unsigned i = 0U; i < _numCPUs; ++i) {
  428. Float32 _inUse, _total;
  429. if (_prevCPUInfo) {
  430. _inUse = (
  431. (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER])
  432. + (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM])
  433. + (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE])
  434. );
  435. _total = _inUse + (_cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE] - _prevCPUInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]);
  436. } else {
  437. _inUse = _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] + _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] + _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE];
  438. _total = _inUse + _cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE];
  439. }
  440. [cpus addObject:@(_inUse / _total)];
  441. }
  442. [_cpuUsageLock unlock];
  443. if (_prevCPUInfo) {
  444. size_t prevCpuInfoSize = sizeof(integer_t) * _numPrevCPUInfo;
  445. vm_deallocate(mach_task_self(), (vm_address_t)_prevCPUInfo, prevCpuInfoSize);
  446. }
  447. return cpus;
  448. } else {
  449. return nil;
  450. }
  451. }
  452. @end