1 import ABI48_0_0ExpoModulesCore
2 import UIKit
3 import MachO
4 
5 public class DeviceModule: Module {
definitionnull6   public func definition() -> ModuleDefinition {
7     Name("ExpoDevice")
8 
9     Constants([
10       "isDevice": isDevice(),
11       "brand": "Apple",
12       "manufacturer": "Apple",
13       "modelId": UIDevice.modelIdentifier,
14       "modelName": UIDevice.DeviceMap.modelName,
15       "deviceYearClass": UIDevice.DeviceMap.deviceYearClass,
16       "totalMemory": ProcessInfo.processInfo.physicalMemory,
17       "osName": UIDevice.current.systemName,
18       "osVersion": UIDevice.current.systemVersion,
19       "osBuildId": osBuildId(),
20       "osInternalBuildId": osBuildId(),
21       "deviceName": UIDevice.current.name,
22       "supportedCpuArchitectures": cpuArchitectures()
23     ])
24 
25     AsyncFunction("getDeviceTypeAsync") { () -> Int in
26       switch UIDevice.current.userInterfaceIdiom {
27       case UIUserInterfaceIdiom.phone:
28         return DeviceType.phone.rawValue
29       case UIUserInterfaceIdiom.pad:
30         return DeviceType.tablet.rawValue
31       case UIUserInterfaceIdiom.tv:
32         return DeviceType.tv.rawValue
33       default:
34         return DeviceType.unknown.rawValue
35       }
36     }
37 
38     AsyncFunction("getUptimeAsync") { () -> Double in
39       let uptimeMs: Double = ProcessInfo.processInfo.systemUptime * 1000
40 
41       return uptimeMs
42     }
43 
44     AsyncFunction("isRootedExperimentalAsync") { () -> Bool in
45       return UIDevice.current.isJailbroken
46     }
47   }
48 }
49 
isDevicenull50 func isDevice() -> Bool {
51   #if targetEnvironment(simulator)
52   return false
53   #else
54   return true
55   #endif
56 }
57 
osBuildIdnull58 func osBuildId() -> String? {
59   #if os(tvOS)
60   return nil
61   #else
62   // Credit: https://stackoverflow.com/a/65858410
63   var mib: [Int32] = [CTL_KERN, KERN_OSVERSION]
64   let namelen = UInt32(MemoryLayout.size(ofValue: mib) / MemoryLayout.size(ofValue: mib[0]))
65   var bufferSize = 0
66 
67   // Get the size for the buffer
68   sysctl(&mib, namelen, nil, &bufferSize, nil, 0)
69 
70   var buildBuffer = [UInt8](repeating: 0, count: bufferSize)
71   let result = sysctl(&mib, namelen, &buildBuffer, &bufferSize, nil, 0)
72 
73   if result >= 0 && bufferSize > 0 {
74     return String(bytesNoCopy: &buildBuffer, length: bufferSize - 1, encoding: .utf8, freeWhenDone: false)
75   }
76 
77   return nil
78   #endif
79 }
80 
cpuArchitecturesnull81 func cpuArchitectures() -> [String]? {
82   // Credit: https://stackoverflow.com/a/70134518
83   guard let archRaw = NXGetLocalArchInfo().pointee.name else {
84     return nil
85   }
86   return [String(cString: archRaw)]
87 }
88 
89 enum DeviceType: Int {
90   case unknown = 0
91   case phone = 1
92   case tablet = 2
93   case desktop = 3
94   case tv = 4
95 }
96