001package com.pi4j.system.impl; 002 003/* 004 * #%L 005 * ********************************************************************** 006 * ORGANIZATION : Pi4J 007 * PROJECT : Pi4J :: Java Library (Core) 008 * FILENAME : DefaultSystemInfoProvider.java 009 * 010 * This file is part of the Pi4J project. More information about 011 * this project can be found here: https://www.pi4j.com/ 012 * ********************************************************************** 013 * %% 014 * Copyright (C) 2012 - 2019 Pi4J 015 * %% 016 * This program is free software: you can redistribute it and/or modify 017 * it under the terms of the GNU Lesser General Public License as 018 * published by the Free Software Foundation, either version 3 of the 019 * License, or (at your option) any later version. 020 * 021 * This program is distributed in the hope that it will be useful, 022 * but WITHOUT ANY WARRANTY; without even the implied warranty of 023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 024 * GNU General Lesser Public License for more details. 025 * 026 * You should have received a copy of the GNU General Lesser Public 027 * License along with this program. If not, see 028 * <http://www.gnu.org/licenses/lgpl-3.0.html>. 029 * #L% 030 */ 031 032import com.pi4j.system.SystemInfoProvider; 033import com.pi4j.util.ExecUtil; 034import com.pi4j.util.StringUtil; 035 036import java.io.BufferedReader; 037import java.io.FileReader; 038import java.io.IOException; 039import java.security.AccessController; 040import java.security.PrivilegedAction; 041import java.util.ArrayList; 042import java.util.HashMap; 043import java.util.List; 044import java.util.Map; 045 046/** 047 * Abstract base implementation of the SystemInfoProvider interface. 048 * This base impl includes support for all common method across all 049 * the supported platforms. 050 */ 051public abstract class DefaultSystemInfoProvider extends SystemInfoProviderBase implements SystemInfoProvider { 052 053 private static Map<String, String> cpuInfo; 054 055 /** 056 * This method will read and parse the '/proc/cpuinfo' into a collection of properties. 057 * 058 * @param target 059 * @return 060 * @throws IOException 061 * @throws InterruptedException 062 * @throws UnsupportedOperationException 063 */ 064 protected String getCpuInfo(String target) throws IOException, InterruptedException, UnsupportedOperationException { 065 // if the CPU data has not been previously acquired, then acquire it now 066 if (cpuInfo == null) { 067 cpuInfo = new HashMap<>(); 068 069 try(BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"))) { 070 for(String line; (line = br.readLine()) != null; ) { 071 String parts[] = line.split(":", 2); 072 if (parts.length >= 2 && !parts[0].trim().isEmpty() && !parts[1].trim().isEmpty()) { 073 String cpuKey = parts[0].trim(); 074 cpuInfo.put(cpuKey, parts[1].trim()); 075 } 076 } 077 } 078 } 079 if (cpuInfo.containsKey(target)) { 080 return cpuInfo.get(target); 081 } 082 throw new UnsupportedOperationException("Invalid target: " + target); 083 } 084 085 /* 086 * this method will to obtain the version info string from the 'bash' program 087 * (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system) 088 */ 089 protected String getBashVersionInfo() { 090 String versionInfo = ""; 091 try { 092 String result[] = ExecUtil.execute("bash --version"); 093 for(String line : result) { 094 if(!line.isEmpty()) { 095 versionInfo = line; // return only first output line of version info 096 break; 097 } 098 } 099 } 100 catch (IOException|InterruptedException ioe) { ioe.printStackTrace(); } 101 return versionInfo; 102 } 103 104 /* 105 * this method will determine if a specified tag exists from the elf info in the '/proc/self/exe' program 106 * (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system) 107 */ 108 protected boolean hasReadElfTag(String tag) { 109 String tagValue = getReadElfTag(tag); 110 return (tagValue != null && !tagValue.isEmpty()); 111 } 112 113 /* 114 * this method will obtain a specified tag value from the elf info in the '/proc/self/exe' program 115 * (this method is used to help determine the HARD-FLOAT / SOFT-FLOAT ABI of the system) 116 */ 117 protected String getReadElfTag(String tag) { 118 String tagValue = null; 119 try { 120 String result[] = ExecUtil.execute("/usr/bin/readelf -A /proc/self/exe"); 121 if(result != null){ 122 for(String line : result) { 123 line = line.trim(); 124 if (line.startsWith(tag) && line.contains(":")) { 125 String lineParts[] = line.split(":", 2); 126 if(lineParts.length > 1) 127 tagValue = lineParts[1].trim(); 128 break; 129 } 130 } 131 } 132 } 133 catch (IOException|InterruptedException ioe) { ioe.printStackTrace(); } 134 return tagValue; 135 } 136 137 protected List<Long> getMemory() throws IOException, InterruptedException { 138 // Memory information is in the form 139 // root@mypi:/home/pi# free -b 140 // total used free shared buffers cached 141 // Mem: 459771904 144654336 315117568 0 21319680 63713280 142 // -/+ buffers/cache: 59621376 400150528 143 // Swap: 104853504 0 104853504 144 List<Long> values = new ArrayList<>(); 145 String result[] = ExecUtil.execute("free -b"); 146 if(result != null){ 147 for(String line : result) { 148 if(line.startsWith("Mem:")){ 149 String parts[] = line.split(" "); 150 for(String part : parts){ 151 part = part.trim(); 152 if(!part.isEmpty() && !part.equalsIgnoreCase("Mem:")){ 153 values.add(new Long(part)); 154 } 155 } 156 } 157 } 158 } 159 return values; 160 } 161 162 @Override 163 public String getProcessor() throws IOException, InterruptedException, UnsupportedOperationException { 164 return getCpuInfo("processor"); 165 } 166 167 @Override 168 public String getBogoMIPS() throws IOException, InterruptedException, UnsupportedOperationException { 169 return getCpuInfo("BogoMIPS"); 170 } 171 172 @Override 173 public String[] getCpuFeatures() throws IOException, InterruptedException, UnsupportedOperationException { 174 return getCpuInfo("Features").split(" "); 175 } 176 177 @Override 178 public String getCpuImplementer() throws IOException, InterruptedException, UnsupportedOperationException { 179 return getCpuInfo("CPU implementer"); 180 } 181 182 @Override 183 public String getCpuArchitecture() throws IOException, InterruptedException, UnsupportedOperationException { 184 return getCpuInfo("CPU architecture"); 185 } 186 187 @Override 188 public String getCpuVariant() throws IOException, InterruptedException, UnsupportedOperationException { 189 return getCpuInfo("CPU variant"); 190 } 191 192 @Override 193 public String getCpuPart() throws IOException, InterruptedException, UnsupportedOperationException { 194 return getCpuInfo("CPU part"); 195 } 196 197 @Override 198 public String getCpuRevision() throws IOException, InterruptedException, UnsupportedOperationException { 199 return getCpuInfo("CPU revision"); 200 } 201 202 @Override 203 public String getHardware() throws IOException, InterruptedException, UnsupportedOperationException { 204 return getCpuInfo("Hardware"); 205 } 206 207 @Override 208 public String getRevision() throws IOException, InterruptedException, UnsupportedOperationException { 209 return getCpuInfo("Revision"); 210 } 211 212 @Override 213 public String getSerial() throws IOException, InterruptedException, UnsupportedOperationException { 214 return getCpuInfo("Serial"); 215 } 216 217 @Override 218 public String getOsName() throws UnsupportedOperationException { 219 return System.getProperty("os.name"); 220 } 221 222 @Override 223 public String getOsVersion() throws UnsupportedOperationException { 224 return System.getProperty("os.version"); 225 } 226 227 @Override 228 public String getOsArch() throws UnsupportedOperationException { 229 return System.getProperty("os.arch"); 230 } 231 232 @Override 233 public String getJavaVendor() throws UnsupportedOperationException { 234 return System.getProperty("java.vendor"); 235 } 236 237 @Override 238 public String getJavaVendorUrl() throws UnsupportedOperationException { 239 return System.getProperty("java.vendor.url"); 240 } 241 242 @Override 243 public String getJavaVersion() throws UnsupportedOperationException { 244 return System.getProperty("java.version"); 245 } 246 247 @Override 248 public String getJavaVirtualMachine() throws UnsupportedOperationException { 249 return System.getProperty("java.vm.name"); 250 } 251 252 @Override 253 public String getJavaRuntime() throws UnsupportedOperationException { 254 return AccessController.doPrivileged(new PrivilegedAction<String>() { 255 public String run() { 256 return System.getProperty("java.runtime.name"); 257 } 258 }); 259 } 260 261 /* 262 * this method was partially derived from :: (project) jogamp / (developer) sgothel 263 * https://github.com/sgothel/gluegen/blob/master/src/java/jogamp/common/os/PlatformPropsImpl.java#L160 264 * https://github.com/sgothel/gluegen/blob/master/LICENSE.txt 265 */ 266 @Override 267 public boolean isHardFloatAbi() throws UnsupportedOperationException { 268 return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 269 private final String[] gnueabihf = new String[] { "gnueabihf", "armhf" }; 270 public Boolean run() { 271 return ( StringUtil.contains(System.getProperty("sun.boot.library.path"), gnueabihf) || 272 StringUtil.contains(System.getProperty("java.library.path"), gnueabihf) || 273 StringUtil.contains(System.getProperty("java.home"), gnueabihf) || 274 getBashVersionInfo().contains("gnueabihf") || 275 hasReadElfTag("Tag_ABI_HardFP_use")); 276 } } ); 277 } 278 279 @Override 280 public long getMemoryTotal() throws IOException, InterruptedException, UnsupportedOperationException { 281 List<Long> values = getMemory(); 282 if(!values.isEmpty() && values.size() > 0){ 283 return values.get(0); // total memory value is in first position 284 } 285 throw new UnsupportedOperationException(); 286 } 287 288 @Override 289 public long getMemoryUsed() throws IOException, InterruptedException, UnsupportedOperationException { 290 List<Long> values = getMemory(); 291 if(!values.isEmpty() && values.size() > 1){ 292 return values.get(1); // used memory value is in second position 293 } 294 throw new UnsupportedOperationException(); 295 } 296 297 @Override 298 public long getMemoryFree() throws IOException, InterruptedException, UnsupportedOperationException { 299 List<Long> values = getMemory(); 300 if(!values.isEmpty() && values.size() > 2){ 301 return values.get(2); // free memory value is in third position 302 } 303 throw new UnsupportedOperationException(); 304 } 305 306 @Override 307 public long getMemoryShared() throws IOException, InterruptedException, UnsupportedOperationException { 308 List<Long> values = getMemory(); 309 if(!values.isEmpty() && values.size() > 3){ 310 return values.get(3); // shared memory value is in fourth position 311 } 312 throw new UnsupportedOperationException(); 313 } 314 315 @Override 316 public long getMemoryBuffers() throws IOException, InterruptedException, UnsupportedOperationException { 317 List<Long> values = getMemory(); 318 if(!values.isEmpty() && values.size() > 4){ 319 return values.get(4); // buffers memory value is in fifth position 320 } 321 throw new UnsupportedOperationException(); 322 } 323 324 @Override 325 public long getMemoryCached() throws IOException, InterruptedException, UnsupportedOperationException { 326 List<Long> values = getMemory(); 327 if(!values.isEmpty() && values.size() > 5){ 328 return values.get(5); // cached memory value is in sixth position 329 } 330 throw new UnsupportedOperationException(); 331 } 332 333/** 334 * The following commented out methods are implemented in the platform specific providers, if supported 335 */ 336// public String getModelName() throws IOException, InterruptedException, UnsupportedOperationException { 337// public static String getOsFirmwareBuild() throws IOException, InterruptedException { 338// public String getOsFirmwareDate() throws IOException, InterruptedException, ParseException, UnsupportedOperationException { 339// public SystemInfo.BoardType getBoardType() throws IOException, InterruptedException, UnsupportedOperationException { 340// public float getCpuTemperature() throws IOException, InterruptedException, NumberFormatException, UnsupportedOperationException { 341// public float getCpuVoltage() throws IOException, InterruptedException, NumberFormatException, UnsupportedOperationException { 342// public float getMemoryVoltageSDRam_C() throws IOException, InterruptedException, NumberFormatException, UnsupportedOperationException { 343// public float getMemoryVoltageSDRam_I() throws IOException, InterruptedException, NumberFormatException, UnsupportedOperationException { 344// public float getMemoryVoltageSDRam_P() throws IOException, InterruptedException, NumberFormatException, UnsupportedOperationException { 345// public boolean getCodecH264Enabled() throws IOException, InterruptedException, UnsupportedOperationException { 346// public boolean getCodecMPG2Enabled() throws IOException, InterruptedException, UnsupportedOperationException { 347// public boolean getCodecWVC1Enabled() throws IOException, InterruptedException, UnsupportedOperationException { 348// public long getClockFrequencyArm() throws IOException, InterruptedException, UnsupportedOperationException { 349// public long getClockFrequencyCore() throws IOException, InterruptedException, UnsupportedOperationException { 350// public long getClockFrequencyH264() throws IOException, InterruptedException, UnsupportedOperationException { 351// public long getClockFrequencyISP() throws IOException, InterruptedException, UnsupportedOperationException { 352// public long getClockFrequencyV3D() throws IOException, InterruptedException, UnsupportedOperationException { 353// public long getClockFrequencyUART() throws IOException, InterruptedException, UnsupportedOperationException { 354// public long getClockFrequencyPWM() throws IOException, InterruptedException, UnsupportedOperationException { 355// public long getClockFrequencyEMMC() throws IOException, InterruptedException, UnsupportedOperationException { 356// public long getClockFrequencyPixel() throws IOException, InterruptedException, UnsupportedOperationException { 357// public long getClockFrequencyVEC() throws IOException, InterruptedException, UnsupportedOperationException { 358// public long getClockFrequencyHDMI() throws IOException, InterruptedException, UnsupportedOperationException { 359// public long getClockFrequencyDPI() throws IOException, InterruptedException, UnsupportedOperationException { 360}