| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.sdklib.internal.avd; |
| |
| import com.android.utils.ILogger; |
| import com.google.common.base.Charsets; |
| |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.util.Map; |
| import java.util.TreeMap; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| public class HardwareProperties { |
| /** AVD/config.ini key for whether hardware buttons are present. */ |
| public static final String HW_MAINKEYS = "hw.mainKeys"; |
| |
| /** AVD/config.ini key indicating whether trackball is present. */ |
| public static final String HW_TRACKBALL = "hw.trackBall"; |
| |
| /** AVD/config.ini key indicating whether qwerty keyboard is present. */ |
| public static final String HW_KEYBOARD = "hw.keyboard"; |
| |
| /** AVD/config.ini key indicating whether dpad is present. */ |
| public static final String HW_DPAD = "hw.dPad"; |
| |
| /** AVD/config.ini key indicating whether gps is present. */ |
| public static final String HW_GPS = "hw.gps"; |
| |
| /** AVD/config.ini key indicating whether the device is running on battery. */ |
| public static final String HW_BATTERY = "hw.battery"; |
| |
| /** AVD/config.ini key indicating whether accelerometer is present. */ |
| public static final String HW_ACCELEROMETER = "hw.accelerometer"; |
| |
| /** AVD/config.ini key indicating whether gyroscope is present. */ |
| public static final String HW_ORIENTATION_SENSOR = "hw.sensors.orientation"; |
| |
| /** AVD/config.ini key indicating whether h/w mic is present. */ |
| public static final String HW_AUDIO_INPUT = "hw.audioInput"; |
| |
| /** AVD/config.ini key indicating whether sdcard is present. */ |
| public static final String HW_SDCARD = "hw.sdCard"; |
| |
| /** AVD/config.ini key for LCD density. */ |
| public static final String HW_LCD_DENSITY = "hw.lcd.density"; |
| |
| /** AVD/config.ini key indicating whether proximity sensor present. */ |
| public static final String HW_PROXIMITY_SENSOR = "hw.sensors.proximity"; |
| |
| /** AVD/config.ini key for initial device orientation. */ |
| public static final String HW_INITIAL_ORIENTATION = "hw.initialOrientation"; |
| |
| |
| private static final Pattern PATTERN_PROP = Pattern.compile( |
| "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$"); |
| |
| /** Property name in the generated avd config file; String; e.g. "hw.screen" */ |
| private static final String HW_PROP_NAME = "name"; //$NON-NLS-1$ |
| /** Property type, one of {@link HardwarePropertyType} */ |
| private static final String HW_PROP_TYPE = "type"; //$NON-NLS-1$ |
| /** Default value of the property. String matching the property type. */ |
| private static final String HW_PROP_DEFAULT = "default"; //$NON-NLS-1$ |
| /** User-visible name of the property. String. */ |
| private static final String HW_PROP_ABSTRACT = "abstract"; //$NON-NLS-1$ |
| /** User-visible description of the property. String. */ |
| private static final String HW_PROP_DESC = "description"; //$NON-NLS-1$ |
| /** Comma-separate values for a property of type "enum" */ |
| private static final String HW_PROP_ENUM = "enum"; //$NON-NLS-1$ |
| |
| public static final String BOOLEAN_YES = "yes"; |
| public static final String BOOLEAN_NO = "no"; |
| public static final Pattern DISKSIZE_PATTERN = Pattern.compile("\\d+[MK]B"); //$NON-NLS-1$ |
| |
| /** Represents the type of a hardware property value. */ |
| public enum HardwarePropertyType { |
| INTEGER ("integer", false /*isEnum*/), //$NON-NLS-1$ |
| BOOLEAN ("boolean", false /*isEnum*/), //$NON-NLS-1$ |
| DISKSIZE ("diskSize", false /*isEnum*/), //$NON-NLS-1$ |
| STRING ("string", false /*isEnum*/), //$NON-NLS-1$ |
| INTEGER_ENUM("integer", true /*isEnum*/), //$NON-NLS-1$ |
| STRING_ENUM ("string", true /*isEnum*/); //$NON-NLS-1$ |
| |
| |
| private String mName; |
| private boolean mIsEnum; |
| |
| HardwarePropertyType(String name, boolean isEnum) { |
| mName = name; |
| mIsEnum = isEnum; |
| } |
| |
| /** Returns the name of the type (e.g. "string", "boolean", etc.) */ |
| public String getName() { |
| return mName; |
| } |
| |
| /** Indicates whether this type is an enum (e.g. "enum of strings"). */ |
| public boolean isEnum() { |
| return mIsEnum; |
| } |
| |
| /** Returns the internal HardwarePropertyType object matching the given type name. */ |
| public static HardwarePropertyType getEnum(String name, boolean isEnum) { |
| for (HardwarePropertyType type : values()) { |
| if (type.mName.equals(name) && type.mIsEnum == isEnum) { |
| return type; |
| } |
| } |
| |
| return null; |
| } |
| } |
| |
| public static final class HardwareProperty { |
| private String mName; |
| private HardwarePropertyType mType; |
| /** the string representation of the default value. can be null. */ |
| private String mDefault; |
| /** the choices for an enum. Null if not an enum. */ |
| private String[] mEnum; |
| private String mAbstract; |
| private String mDescription; |
| |
| public HardwareProperty() { |
| // initialize strings to sane defaults, as not all properties will be set from |
| // the ini file |
| mName = ""; |
| mDefault = ""; |
| mAbstract = ""; |
| mDescription = ""; |
| } |
| |
| /** Returns the hardware config name of the property, e.g. "hw.screen" */ |
| public String getName() { |
| return mName; |
| } |
| |
| /** Returns the property type, one of {@link HardwarePropertyType} */ |
| public HardwarePropertyType getType() { |
| return mType; |
| } |
| |
| /** |
| * Returns the default value of the property. |
| * String matching the property type. |
| * Can be null. |
| */ |
| public String getDefault() { |
| return mDefault; |
| } |
| |
| /** Returns the user-visible name of the property. */ |
| public String getAbstract() { |
| return mAbstract; |
| } |
| |
| /** Returns the user-visible description of the property. */ |
| public String getDescription() { |
| return mDescription; |
| } |
| |
| /** Returns the possible values for an enum property. Can be null. */ |
| public String[] getEnum() { |
| return mEnum; |
| } |
| |
| public boolean isValidForUi() { |
| // don't display single string type for now. |
| return mType != HardwarePropertyType.STRING || mType.isEnum(); |
| } |
| } |
| |
| /** |
| * Parses the hardware definition file. |
| * @param file the property file to parse |
| * @param log the ILogger object receiving warning/error from the parsing. Cannot be null. |
| * @return the map of (key,value) pairs, or null if the parsing failed. |
| */ |
| public static Map<String, HardwareProperty> parseHardwareDefinitions(File file, ILogger log) { |
| BufferedReader reader = null; |
| try { |
| FileInputStream fis = new FileInputStream(file); |
| reader = new BufferedReader(new InputStreamReader(fis, Charsets.UTF_8)); |
| |
| Map<String, HardwareProperty> map = new TreeMap<String, HardwareProperty>(); |
| |
| String line = null; |
| HardwareProperty prop = null; |
| while ((line = reader.readLine()) != null) { |
| if (line.length() > 0 && line.charAt(0) != '#') { |
| Matcher m = PATTERN_PROP.matcher(line); |
| if (m.matches()) { |
| String key = m.group(1); |
| String value = m.group(2); |
| |
| if (HW_PROP_NAME.equals(key)) { |
| prop = new HardwareProperty(); |
| prop.mName = value; |
| map.put(prop.mName, prop); |
| } |
| |
| if (prop == null) { |
| log.warning("Error parsing '%1$s': missing '%2$s'", |
| file.getAbsolutePath(), HW_PROP_NAME); |
| return null; |
| } |
| |
| if (HW_PROP_TYPE.equals(key)) { |
| // Note: we don't know yet whether this type is an enum. |
| // This is indicated by the "enum = value" line that is parsed later. |
| prop.mType = HardwarePropertyType.getEnum(value, false); |
| assert (prop.mType != null); |
| } else if (HW_PROP_DEFAULT.equals(key)) { |
| prop.mDefault = value; |
| } else if (HW_PROP_ABSTRACT.equals(key)) { |
| prop.mAbstract = value; |
| } else if (HW_PROP_DESC.equals(key)) { |
| prop.mDescription = value; |
| } else if (HW_PROP_ENUM.equals(key)) { |
| if (!prop.mType.isEnum()) { |
| // Change the type to an enum, if valid. |
| prop.mType = HardwarePropertyType.getEnum(prop.mType.getName(), |
| true); |
| assert (prop.mType != null); |
| } |
| |
| // Sanitize input: trim spaces, ignore empty entries. |
| String[] v = value.split(","); |
| int n = 0; |
| for (int i = 0; i < v.length; i++) { |
| String s = v[i] = v[i].trim(); |
| if (s.length() > 0) { |
| n++; |
| } |
| } |
| prop.mEnum = new String[n]; |
| n = 0; |
| for (int i = 0; i < v.length; i++) { |
| String s = v[i]; |
| if (s.length() > 0) { |
| prop.mEnum[n++] = s; |
| } |
| } |
| } |
| } else { |
| log.warning("Error parsing '%1$s': \"%2$s\" is not a valid syntax", |
| file.getAbsolutePath(), line); |
| return null; |
| } |
| } |
| } |
| |
| return map; |
| } catch (FileNotFoundException e) { |
| // this should not happen since we usually test the file existence before |
| // calling the method. |
| // Return null below. |
| } catch (IOException e) { |
| log.warning("Error parsing '%1$s': %2$s.", file.getAbsolutePath(), |
| e.getMessage()); |
| } finally { |
| if (reader != null) { |
| try { |
| reader.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the boolean value matching the given index. |
| * This is the reverse of {@link #getBooleanValueIndex(String)}. |
| * |
| * @param index 0 or 1. |
| * @return {@link #BOOLEAN_YES} for 0 or {@link #BOOLEAN_NO} for 1. |
| * @throws IndexOutOfBoundsException if index is neither 0 nor 1. |
| */ |
| public static String getBooleanValue(int index) { |
| if (index == 0) { |
| return BOOLEAN_YES; |
| } else if (index == 1) { |
| return BOOLEAN_NO; |
| } |
| throw new IndexOutOfBoundsException("HardwareProperty boolean index must 0 (true) or 1 (false) but was " + index); |
| } |
| |
| /** |
| * Returns the index of a boolean <var>value</var>. |
| * This if the reverse of {@link #getBooleanValue(int)}. |
| * |
| * @param value Either {@link #BOOLEAN_YES} or {@link #BOOLEAN_NO}. |
| * @return 0 for {@link #BOOLEAN_YES}, 1 for {@link #BOOLEAN_NO} or -1 for anything else. |
| */ |
| public static int getBooleanValueIndex(String value) { |
| if (BOOLEAN_YES.equals(value)) { |
| return 0; |
| } else if (BOOLEAN_NO.equals(value)) { |
| return 1; |
| } |
| |
| return -1; |
| } |
| } |