DeviceInfoPlugin.java :  » UnTagged » android-analyzer » org » androidanalyzer » plugins » device » Android Open Source

Android Open Source » UnTagged » android analyzer 
android analyzer » org » androidanalyzer » plugins » device » DeviceInfoPlugin.java
package org.androidanalyzer.plugins.device;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.androidanalyzer.Constants;
import org.androidanalyzer.core.Data;
import org.androidanalyzer.core.utils.Logger;
import org.androidanalyzer.plugins.AbstractPlugin;

import android.os.Build;

/**
 * DeviceInfoPlugin is used to gather information about general device properties
 * like the device manufacturer and model, branding (if any) and a rich set of 
 * firmware details, like the firmware, kernel and baseband versions, bootloader, etc.
 * 
 * @author Tsvetan Nachev
 *
 */
public class DeviceInfoPlugin extends AbstractPlugin {

  /*
   * Static plugin metadata constants
   */

  private static final String BOOTLOADER_FIELD = "BOOTLOADER";
  private static final String HARDWARE_FIELD = "HARDWARE";
  private static final String MANUFACTURER_FIELD = "MANUFACTURER";
  private static final String PLUGIN_VERSION = "1.0.0";
  private static final String PLUGIN_VENDOR = "ProSyst Software GmbH";
  private static final long PLUGIN_TIMEOUT = 0;
  private static final String PLUGIN_NAME = "Device Info Plugin";
  private static final String PLUGIN_DESCRIPTION = "Collects data on general device properties";
  private static final String TAG = "Analyzer-DeviceInfoPlugin";
  /**
   * Holds the plugin status. Default value is passed. If error retrieving any of plugin properties occur,
   * status is set to indicate the error
   */
  private String status = Constants.METADATA_PLUGIN_STATUS_PASSED;
  
  /**
   * Root node
   */
  private static final String DEVICE_NODE = "Device";

  /**
   * 1st level node
   */
  private static final String PRODUCT_NODE = "Product";

  /**
   * 1st level node
   */
  private static final String FIRMWARE_NODE = "Firmware";
  
  /**
   * 2nd level product key
   */
  private static final String MANUFACTURER_NAME = "Manufacturer name";

  /**
   * 2nd level product key
   */  
  private static final String DEVICE_MODEL = "Device model";

  /**
   * 2nd level product key
   */
  private static final String DEVICE_BRAND = "Device brand";
  
  /**
   * 2nd level firmware key
   */
  private static final String HARDWARE_NAME = "Hardware name";
  
  /**
   * 2nd level firmware key
   */
  private static final String FIRMWARE_VERSION = "Firmware version";
  
  /**
   * 2nd level firmware key
   */
  private static final String FIRMWARE_CONFIGURATION_VERSION = "Firmware configuration version";
  
  /**
   * 2nd level firmware key
   */
  private static final String KERNEL_VERSION_RAW = "Kernel version raw";
  
  /**
   * 2nd level firmware key
   */
  private static final String KERNEL_VERSION = "Kernel version";
  
  /**
   * 2nd level firmware key
   */
  private static final String BASEBAND_VERSION = "Baseband version";
  
  /**
   * 2nd level firmware key
   */
  private static final String BASEBAND_CONFIGURATION_VERSION = "Baseband configuration version";
  
  /**
   * 2nd level firmware key
   */
  private static final String BUILD_NUMBER = "Build number";
  
  /**
   * 2nd level firmware key
   */
  private static final String BUILD_FINGERPRINT = "Build fingerprint";
  
  /**
   * 2nd level firmware key
   */
  private static final String BOOTLOADER_VERSION = "Bootloader version";
  
  private static final String KERNEL_FORMAT_REGEXP = "\\w+\\s+" + /* ignore: Linux */
                                               "\\w+\\s+" + /* ignore: version */
                                               "([^\\s]+)\\s+" + /* group 1: 2.6.22-omap1 */
                                               "\\(([^\\s@]+(?:@[^\\s.]+)?)[^)]*\\)\\s+" + /* group 2: (xxxxxx@xxxxx.constant) */
                                               "\\((?:[^(]*\\([^)]*\\))?[^)]*\\)\\s+" + /* ignore: (gcc ..) */
                                               "([^\\s]+)\\s+" + /* group 3: #26 */
                                               "(?:PREEMPT\\s+)?" + /* ignore: PREEMPT (optional) */
                                               "(.+)"; /* group 4: date */
  
  private static final String KERNEL_SOURCE = "/proc/version";
  
  private static final String BUILD_PROPERTIES_FILE = "/system/build.prop";
  
  private static final String BASEBAND_VERSION_PROP = "gsm.version.baseband";
  
  /**
   * Optional (found on Motorola Milestone)
   */
  private static final String BASEBAND_CONFIGURATION_VERSION_PROP = "ro.gsm.flexversion";
  
  private static final String FIRMWARE_CONFIGURATION_VERSION_PROP = "ro.build.config.version";
  
  private static final String FIRMWARE_BUILD_FINGERPRINT_PROP = "ro.build.fingerprint";
  
  private static boolean readPropsFromFile = false;
  
  private Properties buildProps;

  @Override
  protected Data getData() {
    Data device = new Data();
    try {
      device.setName(DEVICE_NODE);
    } catch (Exception e) {
      Logger.ERROR(TAG, "Error creating device node: "+e.getMessage(), e);
      status = "Could not create Device root node";
      return null;
    }
    ArrayList<Data> subnodes = new ArrayList<Data>();
    try {
      Data product = new Data();
      product.setName(PRODUCT_NODE);
      ArrayList<Data> productData = readProductData();
      addToParent(product, productData);
      subnodes.add(product);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error creating product subnodes: "+t.getMessage(), t);
      status = "Could not create Product subnode";
    }
    try {
      Data firmware = new Data();
      firmware.setName(FIRMWARE_NODE);
      ArrayList<Data> firmwareData = readFirmwareData();
      addToParent(firmware, firmwareData);
      subnodes.add(firmware);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error creating firmware subnodes: "+t.getMessage(), t);
      status = "Could not create Firmware subnode";
    }
    addToParent(device, subnodes);
    return device;
  }

  @Override
  protected String getPluginClassName() {
    return DeviceInfoPlugin.class.getName();
  }

  @Override
  public String getPluginDescription() {
    return PLUGIN_DESCRIPTION;
  }

  @Override
  public String getPluginName() {
    return PLUGIN_NAME;
  }

  @Override
  protected String getPluginStatus() {
    return status;
  }

  @Override
  public long getPluginTimeout() {
    return PLUGIN_TIMEOUT;
  }

  @Override
  public String getPluginVendor() {
    return PLUGIN_VENDOR;
  }

  @Override
  public String getPluginVersion() {
    return PLUGIN_VERSION;
  }

  @Override
  public boolean isPluginUIRequired() {
    return false;
  }

  @Override
  protected void stopDataCollection() {
    Logger.DEBUG(TAG, "Stopping data collection");
    this.stopSelf();
  }
  
  private String getDeviceManufacturer() {
    String mfg = Constants.NODE_VALUE_UNKNOWN;
    try {
      // using reflection
      Field manufacturerField = Build.class.getDeclaredField(MANUFACTURER_FIELD);
      manufacturerField.setAccessible(true);
      Object myManufacturer = manufacturerField.get(null);
      // value = android.os.Build.MANUFACTURER
      mfg = String.valueOf(myManufacturer);
    } catch (Exception ex) {
      mfg = Build.PRODUCT;
      Logger.WARNING(TAG, "Could not get Manufacturer!" + ex.getMessage(), ex);
    }
    return mfg;
  }  
  
  private Data getDeviceHardware() {
    Data bData = new Data();
    try {
      bData.setName(HARDWARE_NAME);
      if (isApiAvailable(8)) {
        String hardware = Constants.NODE_VALUE_UNKNOWN;
        Field hwField = Build.class.getDeclaredField(HARDWARE_FIELD);
        hwField.setAccessible(true);
        Object myHardware = hwField.get(null);
        hardware = String.valueOf(myHardware);
        bData.setValue(hardware);
      } else {
        bData.setValue(Constants.NODE_STATUS_FAILED_UNAVAILABLE_API);
        bData.setStatus(Constants.NODE_STATUS_FAILED);
        bData.setValueType(Constants.NODE_VALUE_TYPE_STRING);
      }
    } catch (Throwable t) {
      Logger.WARNING(TAG, "Could not get Hardware: "+t.getMessage(), t);
    }
    return bData;
  }
  
  private Data getDeviceBootloader() {
    Data bData = new Data();
    try {
      bData.setName(BOOTLOADER_VERSION);
      if (isApiAvailable(8)) {
        String bootloader = Constants.NODE_VALUE_UNKNOWN;
        Field hwField = Build.class.getDeclaredField(BOOTLOADER_FIELD);
        hwField.setAccessible(true);
        Object myHardware = hwField.get(null);
        bootloader = String.valueOf(myHardware);
        bData.setValue(bootloader);
      } else {
        bData.setValue(Constants.NODE_STATUS_FAILED_UNAVAILABLE_API);
        bData.setStatus(Constants.NODE_STATUS_FAILED);
        bData.setValueType(Constants.NODE_VALUE_TYPE_STRING);
      }
    } catch (Throwable t) {
      Logger.WARNING(TAG, "Could not get Bootloader: "+t.getMessage(), t);
    }
    return bData;
  }
  
  private boolean isApiAvailable(int since) {
    return getAPIVersion() >= since;
  }
  
  private ArrayList<Data> readFirmwareData() {
    ArrayList<Data> firmware = new ArrayList<Data>();
    try {
      Data fwVersion = new Data();
      fwVersion.setName(FIRMWARE_VERSION);
      fwVersion.setValue(android.os.Build.VERSION.RELEASE);
      firmware.add(fwVersion);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading device firmware version: "+t.getMessage(), t);
      status = "Could not create firmware version node";
    }
    try {
      Data fwConfigVersion = new Data();
      fwConfigVersion.setName(FIRMWARE_CONFIGURATION_VERSION);
      String value = getSystemProperty(FIRMWARE_CONFIGURATION_VERSION_PROP);
      if (value == null || value.length() == 0) {
        fwConfigVersion.setValue(Constants.NODE_STATUS_FAILED_UNAVAILABLE_VALUE);
        fwConfigVersion.setStatus(Constants.NODE_STATUS_FAILED);
        fwConfigVersion.setValueType(Constants.NODE_VALUE_TYPE_STRING);
      } else {
        fwConfigVersion.setValue(value);
      }
      firmware.add(fwConfigVersion);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading firmware cofiguration version: "+t.getMessage(), t);
      status = "Could not create firmware configuration version node";
    }
    String kernelRawVersion = readKernelVersionRaw();
    try {
      Data kernelRaw = new Data();
      kernelRaw.setName(KERNEL_VERSION_RAW);
      kernelRaw.setValue(kernelRawVersion);
      firmware.add(kernelRaw);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading kernel raw version: "+t.getMessage(), t);
      status = "Could not create kernel raw version node";
    }
    try {
      Data kernel = new Data();
      kernel.setName(KERNEL_VERSION);
      kernel.setValue(formatKernelVersion(kernelRawVersion));
      firmware.add(kernel);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error formatting kernel version: "+t.getMessage(), t);
      status = "Could not create kernel version node";
    }
    try {
      Data baseband = new Data();
      baseband.setName(BASEBAND_VERSION);
      String value = getSystemProperty(BASEBAND_VERSION_PROP);
      baseband.setValue(value != null && value.length() > 0 ? value : Constants.NODE_VALUE_UNKNOWN);
      firmware.add(baseband);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading baseband version: "+t.getMessage(), t);
      status = "Could not create baseband version node";
    }
    try {
      Data basebandConfigVersion = new Data();
      basebandConfigVersion.setName(BASEBAND_CONFIGURATION_VERSION);
      String value = getSystemProperty(BASEBAND_CONFIGURATION_VERSION_PROP);
      if (value == null || value.length() == 0) {
        basebandConfigVersion.setStatus(Constants.NODE_STATUS_FAILED);
        basebandConfigVersion.setValue(Constants.NODE_STATUS_FAILED_UNAVAILABLE_VALUE);
        basebandConfigVersion.setValueType(Constants.NODE_VALUE_TYPE_STRING);
      } else {
        basebandConfigVersion.setValue(value);
      }
      firmware.add(basebandConfigVersion);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading baseband configuration version: "+t.getMessage(), t);
      status = "Could not create baseband configuration version node";
    }
    try {
      Data build = new Data();
      build.setName(BUILD_NUMBER);
      build.setValue(android.os.Build.DISPLAY);
      firmware.add(build);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading build number: "+t.getMessage(), t);
      status = "Could not create build number node";
    }    
    try {
      Data buildFingerprint = new Data();
      buildFingerprint.setName(BUILD_FINGERPRINT);
      String value = getSystemProperty(FIRMWARE_BUILD_FINGERPRINT_PROP);
      buildFingerprint.setValue(value != null && value.length() > 0 ? value : Constants.NODE_VALUE_UNKNOWN);
      firmware.add(buildFingerprint);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading build fingerprint: "+t.getMessage(), t);
      status = "Could not create build fingerpint node";
    }    
    try {
      Data bootloader = getDeviceBootloader();
      firmware.add(bootloader);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading bootloader version: "+t.getMessage(), t);
      status = "Could not create bootloader version node";
    }    
    return firmware;
  }
  
  private ArrayList<Data> readProductData() {
    ArrayList<Data> product = new ArrayList<Data>();
    try {
      Data manufacturer = new Data();
      manufacturer.setName(MANUFACTURER_NAME);
      manufacturer.setValue(getDeviceManufacturer());
      product.add(manufacturer);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading manufacturer properties: "+t.getMessage(), t);
      status = "Could not create device manufacturer node";
    }
    try {
      Data model = new Data();
      model.setName(DEVICE_MODEL);
      model.setValue(android.os.Build.MODEL);
      product.add(model);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading device model: "+t.getMessage(), t);
      status = "Could not create device model node";
    }
    try {
      Data brand = new Data();
      brand.setName(DEVICE_BRAND);
      brand.setValue(android.os.Build.BRAND);
      product.add(brand);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading device brand: "+t.getMessage(), t);
      status = "Could not create device brand node";
    }
    try {
      Data hardware = getDeviceHardware();
      product.add(hardware);
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading device hardware name: "+t.getMessage(), t);
      status = "Could not create device hardware node";
    }    
    return product;
  }

  private String getSystemProperty(String propKey) {
    String value = null;
    if (readPropsFromFile) {
      if (buildProps == null) {
        buildProps = new Properties();
        try {
          buildProps.load(new FileInputStream(BUILD_PROPERTIES_FILE));
        } catch (IOException e) {
          Logger.DEBUG(TAG, "Could not read build.prop file !", e);
        }
      }
      value = buildProps.getProperty(propKey);
    } else {
      try {
        Class sysPropClass = Class.forName("android.os.SystemProperties");
        Method getMethod = sysPropClass.getMethod("get", String.class);
        value = (String) getMethod.invoke(sysPropClass.newInstance(), propKey);
      } catch (Exception e) {
        Logger.DEBUG(TAG, "Could not get systemProperty : " + propKey, e);
      }
    }
    Logger.DEBUG(TAG, "system prop  " + propKey + " = " + value);
    return value;
  }
  
  private String readKernelVersionRaw() {
    String kernelVersionRaw = Constants.NODE_VALUE_UNKNOWN;
    try {
      BufferedReader bReader = new BufferedReader(new FileReader(KERNEL_SOURCE), 256);
      try {
        kernelVersionRaw = bReader.readLine();
      } finally {
        bReader.close();
      }
    } catch (Throwable t) {
      Logger.ERROR(TAG, "Error reading raw kernel version: "+t.getMessage(), t);
    }
    return kernelVersionRaw;
  }
  
  private String formatKernelVersion(String raw) {
    if (raw != null && raw.length() > 0 && !Constants.NODE_VALUE_UNKNOWN.equals(raw)) {
      try {
        Pattern p = Pattern.compile(KERNEL_FORMAT_REGEXP);
        Matcher m = p.matcher(raw);
        if (!m.matches()) {
          Logger.DEBUG(TAG, "Regex did not match on /proc/version: "+raw);
          return raw;
        } else if (m.groupCount() < 4) {
          Logger.DEBUG(TAG, "Regex returned only "+m.groupCount()+ "groups");
          return raw;
        } else {
          return (new StringBuilder(m.group(1)).append("\n").
                                    append(m.group(2)).append(" ").
                                    append(m.group(3)).append("\n").
                                    append(m.group(4))).toString();
        }
      } catch (Throwable t) {
        Logger.ERROR(TAG, "Error formatting raw kernel version: "+t.getMessage(), t);
      }      
    }
    return raw;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.