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