1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21 */
22
23 namespace juce
24 {
25
26 //==============================================================================
27 namespace AndroidStatsHelpers
28 {
29 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
30 STATICMETHOD (getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;")
31
32 DECLARE_JNI_CLASS (SystemClass, "java/lang/System")
33 #undef JNI_CLASS_MEMBERS
34
35 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
36 STATICMETHOD (getDefault, "getDefault", "()Ljava/util/Locale;") \
37 METHOD (getCountry, "getCountry", "()Ljava/lang/String;") \
38 METHOD (getLanguage, "getLanguage", "()Ljava/lang/String;")
39
40 DECLARE_JNI_CLASS (JavaLocale, "java/util/Locale")
41 #undef JNI_CLASS_MEMBERS
42
getSystemProperty(const String & name)43 static String getSystemProperty (const String& name)
44 {
45 return juceString (LocalRef<jstring> ((jstring) getEnv()->CallStaticObjectMethod (SystemClass,
46 SystemClass.getProperty,
47 javaString (name).get())));
48 }
49
getLocaleValue(bool isRegion)50 static String getLocaleValue (bool isRegion)
51 {
52 auto* env = getEnv();
53 LocalRef<jobject> locale (env->CallStaticObjectMethod (JavaLocale, JavaLocale.getDefault));
54
55 auto stringResult = isRegion ? env->CallObjectMethod (locale.get(), JavaLocale.getCountry)
56 : env->CallObjectMethod (locale.get(), JavaLocale.getLanguage);
57
58 return juceString (LocalRef<jstring> ((jstring) stringResult));
59 }
60
getAndroidOsBuildValue(const char * fieldName)61 static String getAndroidOsBuildValue (const char* fieldName)
62 {
63 return juceString (LocalRef<jstring> ((jstring) getEnv()->GetStaticObjectField (
64 AndroidBuild, getEnv()->GetStaticFieldID (AndroidBuild, fieldName, "Ljava/lang/String;"))));
65 }
66 }
67
68 //==============================================================================
getOperatingSystemType()69 SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
70 {
71 return Android;
72 }
73
getOperatingSystemName()74 String SystemStats::getOperatingSystemName()
75 {
76 return "Android " + AndroidStatsHelpers::getSystemProperty ("os.version");
77 }
78
getDeviceDescription()79 String SystemStats::getDeviceDescription()
80 {
81 return AndroidStatsHelpers::getAndroidOsBuildValue ("MODEL")
82 + "-" + AndroidStatsHelpers::getAndroidOsBuildValue ("SERIAL");
83 }
84
getDeviceManufacturer()85 String SystemStats::getDeviceManufacturer()
86 {
87 return AndroidStatsHelpers::getAndroidOsBuildValue ("MANUFACTURER");
88 }
89
isOperatingSystem64Bit()90 bool SystemStats::isOperatingSystem64Bit()
91 {
92 #if JUCE_64BIT
93 return true;
94 #else
95 return false;
96 #endif
97 }
98
getCpuVendor()99 String SystemStats::getCpuVendor()
100 {
101 return AndroidStatsHelpers::getSystemProperty ("os.arch");
102 }
103
getCpuModel()104 String SystemStats::getCpuModel()
105 {
106 return readPosixConfigFileValue ("/proc/cpuinfo", "Hardware");
107 }
108
getCpuSpeedInMegahertz()109 int SystemStats::getCpuSpeedInMegahertz()
110 {
111 int maxFreqKHz = 0;
112
113 for (int i = 0; i < getNumCpus(); ++i)
114 {
115 int freqKHz = File ("/sys/devices/system/cpu/cpu" + String(i) + "/cpufreq/cpuinfo_max_freq")
116 .loadFileAsString()
117 .getIntValue();
118
119 maxFreqKHz = jmax (freqKHz, maxFreqKHz);
120 }
121
122 return maxFreqKHz / 1000;
123 }
124
getMemorySizeInMegabytes()125 int SystemStats::getMemorySizeInMegabytes()
126 {
127 #if __ANDROID_API__ >= 9
128 struct sysinfo sysi;
129
130 if (sysinfo (&sysi) == 0)
131 return static_cast<int> ((sysi.totalram * sysi.mem_unit) / (1024 * 1024));
132 #endif
133
134 return 0;
135 }
136
getPageSize()137 int SystemStats::getPageSize()
138 {
139 return static_cast<int> (sysconf (_SC_PAGESIZE));
140 }
141
142 //==============================================================================
getLogonName()143 String SystemStats::getLogonName()
144 {
145 if (const char* user = getenv ("USER"))
146 return CharPointer_UTF8 (user);
147
148 if (struct passwd* const pw = getpwuid (getuid()))
149 return CharPointer_UTF8 (pw->pw_name);
150
151 return {};
152 }
153
getFullUserName()154 String SystemStats::getFullUserName()
155 {
156 return getLogonName();
157 }
158
getComputerName()159 String SystemStats::getComputerName()
160 {
161 char name [256] = { 0 };
162 if (gethostname (name, sizeof (name) - 1) == 0)
163 return name;
164
165 return {};
166 }
167
168
getUserLanguage()169 String SystemStats::getUserLanguage() { return AndroidStatsHelpers::getLocaleValue (false); }
getUserRegion()170 String SystemStats::getUserRegion() { return AndroidStatsHelpers::getLocaleValue (true); }
getDisplayLanguage()171 String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getUserRegion(); }
172
173 //==============================================================================
initialise()174 void CPUInformation::initialise() noexcept
175 {
176 numPhysicalCPUs = numLogicalCPUs = jmax ((int) 1, (int) android_getCpuCount());
177
178 auto cpuFamily = android_getCpuFamily();
179 auto cpuFeatures = android_getCpuFeatures();
180
181 if (cpuFamily == ANDROID_CPU_FAMILY_X86 || cpuFamily == ANDROID_CPU_FAMILY_X86_64)
182 {
183 hasMMX = hasSSE = hasSSE2 = (cpuFamily == ANDROID_CPU_FAMILY_X86_64);
184
185 hasSSSE3 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_SSSE3) != 0);
186 hasSSE41 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_SSE4_1) != 0);
187 hasSSE42 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_SSE4_2) != 0);
188 hasAVX = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_AVX) != 0);
189 hasAVX2 = ((cpuFeatures & ANDROID_CPU_X86_FEATURE_AVX2) != 0);
190
191 // Google does not distinguish between MMX, SSE, SSE2, SSE3 and SSSE3. So
192 // I assume (and quick Google searches seem to confirm this) that there are
193 // only devices out there that either support all of this or none of this.
194 if (hasSSSE3)
195 hasMMX = hasSSE = hasSSE2 = hasSSE3 = true;
196 }
197 else if (cpuFamily == ANDROID_CPU_FAMILY_ARM)
198 {
199 hasNeon = ((cpuFeatures & ANDROID_CPU_ARM_FEATURE_NEON) != 0);
200 }
201 else if (cpuFamily == ANDROID_CPU_FAMILY_ARM64)
202 {
203 // all arm 64-bit cpus have neon
204 hasNeon = true;
205 }
206 }
207
208 //==============================================================================
juce_millisecondsSinceStartup()209 uint32 juce_millisecondsSinceStartup() noexcept
210 {
211 timespec t;
212 clock_gettime (CLOCK_MONOTONIC, &t);
213
214 return static_cast<uint32> (t.tv_sec) * 1000U + static_cast<uint32> (t.tv_nsec) / 1000000U;
215 }
216
getHighResolutionTicks()217 int64 Time::getHighResolutionTicks() noexcept
218 {
219 timespec t;
220 clock_gettime (CLOCK_MONOTONIC, &t);
221
222 return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);
223 }
224
getHighResolutionTicksPerSecond()225 int64 Time::getHighResolutionTicksPerSecond() noexcept
226 {
227 return 1000000; // (microseconds)
228 }
229
getMillisecondCounterHiRes()230 double Time::getMillisecondCounterHiRes() noexcept
231 {
232 return (double) getHighResolutionTicks() * 0.001;
233 }
234
setSystemTimeToThisTime() const235 bool Time::setSystemTimeToThisTime() const
236 {
237 jassertfalse;
238 return false;
239 }
240
241 } // namespace juce
242