Force UTF-8 encoding for SDK files.
- project .properties files - AVD ini files (<name>.ini and config.ini) - add-on manifest
This commit is contained in:
@@ -41,6 +41,11 @@ public final class SdkConstants {
|
|||||||
*/
|
*/
|
||||||
public final static int CURRENT_PLATFORM = currentPlatform();
|
public final static int CURRENT_PLATFORM = currentPlatform();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Charset for the ini file handled by the SDK.
|
||||||
|
*/
|
||||||
|
public final static String INI_CHARSET = "UTF-8";
|
||||||
|
|
||||||
/** An SDK Project's AndroidManifest.xml file */
|
/** An SDK Project's AndroidManifest.xml file */
|
||||||
public static final String FN_ANDROID_MANIFEST_XML= "AndroidManifest.xml";
|
public static final String FN_ANDROID_MANIFEST_XML= "AndroidManifest.xml";
|
||||||
/** An SDK Project's build.xml file */
|
/** An SDK Project's build.xml file */
|
||||||
|
|||||||
@@ -606,7 +606,7 @@ public final class SdkManager {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a property file and returns
|
* Parses a property file (using UTF-8 encoding) and returns
|
||||||
* @param buildProp the property file to parse
|
* @param buildProp the property file to parse
|
||||||
* @param log the ISdkLog object receiving warning/error from the parsing.
|
* @param log the ISdkLog object receiving warning/error from the parsing.
|
||||||
* @return the map of (key,value) pairs, or null if the parsing failed.
|
* @return the map of (key,value) pairs, or null if the parsing failed.
|
||||||
@@ -616,7 +616,7 @@ public final class SdkManager {
|
|||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
try {
|
try {
|
||||||
fis = new FileInputStream(buildProp);
|
fis = new FileInputStream(buildProp);
|
||||||
reader = new BufferedReader(new InputStreamReader(fis));
|
reader = new BufferedReader(new InputStreamReader(fis, SdkConstants.INI_CHARSET));
|
||||||
|
|
||||||
String line = null;
|
String line = null;
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.io.FileWriter;
|
|||||||
import java.io.FilenameFilter;
|
import java.io.FilenameFilter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -44,7 +45,7 @@ import java.util.regex.Pattern;
|
|||||||
* Android Virtual Device Manager to manage AVDs.
|
* Android Virtual Device Manager to manage AVDs.
|
||||||
*/
|
*/
|
||||||
public final class AvdManager {
|
public final class AvdManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when something is wrong with a target path.
|
* Exception thrown when something is wrong with a target path.
|
||||||
*/
|
*/
|
||||||
@@ -55,16 +56,16 @@ public final class AvdManager {
|
|||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String AVD_FOLDER_EXTENSION = ".avd";
|
public static final String AVD_FOLDER_EXTENSION = ".avd";
|
||||||
|
|
||||||
public final static String AVD_INFO_PATH = "path";
|
public final static String AVD_INFO_PATH = "path";
|
||||||
public final static String AVD_INFO_TARGET = "target";
|
public final static String AVD_INFO_TARGET = "target";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AVD/config.ini key name representing the SDK-relative path of the skin folder, if any,
|
* AVD/config.ini key name representing the SDK-relative path of the skin folder, if any,
|
||||||
* or a 320x480 like constant for a numeric skin size.
|
* or a 320x480 like constant for a numeric skin size.
|
||||||
*
|
*
|
||||||
* @see #NUMERIC_SKIN_SIZE
|
* @see #NUMERIC_SKIN_SIZE
|
||||||
*/
|
*/
|
||||||
public final static String AVD_INI_SKIN_PATH = "skin.path";
|
public final static String AVD_INI_SKIN_PATH = "skin.path";
|
||||||
@@ -79,14 +80,14 @@ public final class AvdManager {
|
|||||||
* AVD/config.ini key name representing the path to the sdcard file.
|
* AVD/config.ini key name representing the path to the sdcard file.
|
||||||
* If missing, the default name "sdcard.img" will be used for the sdcard, if there's such
|
* If missing, the default name "sdcard.img" will be used for the sdcard, if there's such
|
||||||
* a file.
|
* a file.
|
||||||
*
|
*
|
||||||
* @see #SDCARD_IMG
|
* @see #SDCARD_IMG
|
||||||
*/
|
*/
|
||||||
public final static String AVD_INI_SDCARD_PATH = "sdcard.path";
|
public final static String AVD_INI_SDCARD_PATH = "sdcard.path";
|
||||||
/**
|
/**
|
||||||
* AVD/config.ini key name representing the size of the SD card.
|
* AVD/config.ini key name representing the size of the SD card.
|
||||||
* This property is for UI purposes only. It is not used by the emulator.
|
* This property is for UI purposes only. It is not used by the emulator.
|
||||||
*
|
*
|
||||||
* @see #SDCARD_SIZE_PATTERN
|
* @see #SDCARD_SIZE_PATTERN
|
||||||
*/
|
*/
|
||||||
public final static String AVD_INI_SDCARD_SIZE = "sdcard.size";
|
public final static String AVD_INI_SDCARD_SIZE = "sdcard.size";
|
||||||
@@ -101,7 +102,7 @@ public final class AvdManager {
|
|||||||
/**
|
/**
|
||||||
* AVD/config.ini key name representing the second path where the emulator looks
|
* AVD/config.ini key name representing the second path where the emulator looks
|
||||||
* for system images. Typically this is the path to the platform system image.
|
* for system images. Typically this is the path to the platform system image.
|
||||||
*
|
*
|
||||||
* @see #AVD_INI_IMAGES_1
|
* @see #AVD_INI_IMAGES_1
|
||||||
*/
|
*/
|
||||||
public final static String AVD_INI_IMAGES_2 = "image.sysdir.2";
|
public final static String AVD_INI_IMAGES_2 = "image.sysdir.2";
|
||||||
@@ -135,7 +136,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
/** An immutable structure describing an Android Virtual Device. */
|
/** An immutable structure describing an Android Virtual Device. */
|
||||||
public static final class AvdInfo {
|
public static final class AvdInfo {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status for an {@link AvdInfo}. Indicates whether or not this AVD is valid.
|
* Status for an {@link AvdInfo}. Indicates whether or not this AVD is valid.
|
||||||
*/
|
*/
|
||||||
@@ -155,7 +156,7 @@ public final class AvdManager {
|
|||||||
/** System Image folder in config.ini doesn't exist */
|
/** System Image folder in config.ini doesn't exist */
|
||||||
ERROR_IMAGE_DIR;
|
ERROR_IMAGE_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String mName;
|
private final String mName;
|
||||||
private final String mPath;
|
private final String mPath;
|
||||||
private final String mTargetHash;
|
private final String mTargetHash;
|
||||||
@@ -164,11 +165,11 @@ public final class AvdManager {
|
|||||||
private final AvdStatus mStatus;
|
private final AvdStatus mStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new valid AVD info. Values are immutable.
|
* Creates a new valid AVD info. Values are immutable.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Such an AVD is available and can be used.
|
* Such an AVD is available and can be used.
|
||||||
* The error string is set to null.
|
* The error string is set to null.
|
||||||
*
|
*
|
||||||
* @param name The name of the AVD (for display or reference)
|
* @param name The name of the AVD (for display or reference)
|
||||||
* @param path The path to the config.ini file
|
* @param path The path to the config.ini file
|
||||||
* @param targetHash the target hash
|
* @param targetHash the target hash
|
||||||
@@ -181,11 +182,11 @@ public final class AvdManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new <em>invalid</em> AVD info. Values are immutable.
|
* Creates a new <em>invalid</em> AVD info. Values are immutable.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Such an AVD is not complete and cannot be used.
|
* Such an AVD is not complete and cannot be used.
|
||||||
* The error string must be non-null.
|
* The error string must be non-null.
|
||||||
*
|
*
|
||||||
* @param name The name of the AVD (for display or reference)
|
* @param name The name of the AVD (for display or reference)
|
||||||
* @param path The path to the config.ini file
|
* @param path The path to the config.ini file
|
||||||
* @param targetHash the target hash
|
* @param targetHash the target hash
|
||||||
@@ -212,7 +213,7 @@ public final class AvdManager {
|
|||||||
public String getPath() {
|
public String getPath() {
|
||||||
return mPath;
|
return mPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the target hash string.
|
* Returns the target hash string.
|
||||||
*/
|
*/
|
||||||
@@ -230,8 +231,8 @@ public final class AvdManager {
|
|||||||
return mStatus;
|
return mStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method that returns the .ini {@link File} for a given AVD name.
|
* Helper method that returns the .ini {@link File} for a given AVD name.
|
||||||
* @throws AndroidLocationException if there's a problem getting android root directory.
|
* @throws AndroidLocationException if there's a problem getting android root directory.
|
||||||
*/
|
*/
|
||||||
public static File getIniFile(String name) throws AndroidLocationException {
|
public static File getIniFile(String name) throws AndroidLocationException {
|
||||||
@@ -240,23 +241,23 @@ public final class AvdManager {
|
|||||||
return new File(avdRoot, name + INI_EXTENSION);
|
return new File(avdRoot, name + INI_EXTENSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the .ini {@link File} for this AVD.
|
* Returns the .ini {@link File} for this AVD.
|
||||||
* @throws AndroidLocationException if there's a problem getting android root directory.
|
* @throws AndroidLocationException if there's a problem getting android root directory.
|
||||||
*/
|
*/
|
||||||
public File getIniFile() throws AndroidLocationException {
|
public File getIniFile() throws AndroidLocationException {
|
||||||
return getIniFile(mName);
|
return getIniFile(mName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method that returns the Config {@link File} for a given AVD name.
|
* Helper method that returns the Config {@link File} for a given AVD name.
|
||||||
*/
|
*/
|
||||||
public static File getConfigFile(String path) {
|
public static File getConfigFile(String path) {
|
||||||
return new File(path, CONFIG_INI);
|
return new File(path, CONFIG_INI);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Config {@link File} for this AVD.
|
* Returns the Config {@link File} for this AVD.
|
||||||
*/
|
*/
|
||||||
public File getConfigFile() {
|
public File getConfigFile() {
|
||||||
return getConfigFile(mPath);
|
return getConfigFile(mPath);
|
||||||
@@ -268,7 +269,7 @@ public final class AvdManager {
|
|||||||
public Map<String, String> getProperties() {
|
public Map<String, String> getProperties() {
|
||||||
return mProperties;
|
return mProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the error message for the AVD or <code>null</code> if {@link #getStatus()}
|
* Returns the error message for the AVD or <code>null</code> if {@link #getStatus()}
|
||||||
* returns {@link AvdStatus#OK}
|
* returns {@link AvdStatus#OK}
|
||||||
@@ -299,7 +300,7 @@ public final class AvdManager {
|
|||||||
} catch (AndroidLocationException e) {
|
} catch (AndroidLocationException e) {
|
||||||
return "Unable to get HOME folder.";
|
return "Unable to get HOME folder.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,14 +310,14 @@ public final class AvdManager {
|
|||||||
private AvdInfo[] mBrokenAvdList;
|
private AvdInfo[] mBrokenAvdList;
|
||||||
private final SdkManager mSdk;
|
private final SdkManager mSdk;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO remove this field. Each caller should give its own logger to the methods
|
* TODO remove this field. Each caller should give its own logger to the methods
|
||||||
* here instead of relying on a global logger. Otherwise that means that each
|
* here instead of relying on a global logger. Otherwise that means that each
|
||||||
* caller needs to re-instantiate this just to change the logger, which is plain
|
* caller needs to re-instantiate this just to change the logger, which is plain
|
||||||
* ugly.
|
* ugly.
|
||||||
*
|
*
|
||||||
* We'll revisit this in the final AVD Manager UI for donut.
|
* We'll revisit this in the final AVD Manager UI for donut.
|
||||||
*/
|
*/
|
||||||
private ISdkLog mSdkLog;
|
private ISdkLog mSdkLog;
|
||||||
|
|
||||||
public AvdManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException {
|
public AvdManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException {
|
||||||
@@ -327,9 +328,9 @@ public final class AvdManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the current {@link ISdkLog}.
|
* Changes the current {@link ISdkLog}.
|
||||||
*
|
*
|
||||||
* This method should not exist. See comments for {@link #mSdkLog}.
|
* This method should not exist. See comments for {@link #mSdkLog}.
|
||||||
*
|
*
|
||||||
* @return The {@link ISdkLog} that was currently being used.
|
* @return The {@link ISdkLog} that was currently being used.
|
||||||
* @see #mSdkLog
|
* @see #mSdkLog
|
||||||
*/
|
*/
|
||||||
@@ -362,7 +363,7 @@ public final class AvdManager {
|
|||||||
list.add(avd);
|
list.add(avd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mValidAvdList = list.toArray(new AvdInfo[list.size()]);
|
mValidAvdList = list.toArray(new AvdInfo[list.size()]);
|
||||||
}
|
}
|
||||||
return mValidAvdList;
|
return mValidAvdList;
|
||||||
@@ -413,7 +414,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reloads the AVD list.
|
* Reloads the AVD list.
|
||||||
* @throws AndroidLocationException if there was an error finding the location of the
|
* @throws AndroidLocationException if there was an error finding the location of the
|
||||||
@@ -434,7 +435,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new AVD. It is expected that there is no existing AVD with this name already.
|
* Creates a new AVD. It is expected that there is no existing AVD with this name already.
|
||||||
*
|
*
|
||||||
* @param avdFolder the data folder for the AVD. It will be created as needed.
|
* @param avdFolder the data folder for the AVD. It will be created as needed.
|
||||||
* @param name the name of the AVD
|
* @param name the name of the AVD
|
||||||
* @param target the target of the AVD
|
* @param target the target of the AVD
|
||||||
@@ -444,12 +445,12 @@ public final class AvdManager {
|
|||||||
* @param hardwareConfig the hardware setup for the AVD. Can be null to use defaults.
|
* @param hardwareConfig the hardware setup for the AVD. Can be null to use defaults.
|
||||||
* @param removePrevious If true remove any previous files.
|
* @param removePrevious If true remove any previous files.
|
||||||
* @return The new {@link AvdInfo} in case of success (which has just been added to the
|
* @return The new {@link AvdInfo} in case of success (which has just been added to the
|
||||||
* internal list) or null in case of failure.
|
* internal list) or null in case of failure.
|
||||||
*/
|
*/
|
||||||
public AvdInfo createAvd(File avdFolder, String name, IAndroidTarget target,
|
public AvdInfo createAvd(File avdFolder, String name, IAndroidTarget target,
|
||||||
String skinName, String sdcard, Map<String,String> hardwareConfig,
|
String skinName, String sdcard, Map<String,String> hardwareConfig,
|
||||||
boolean removePrevious) {
|
boolean removePrevious) {
|
||||||
|
|
||||||
File iniFile = null;
|
File iniFile = null;
|
||||||
boolean needCleanup = false;
|
boolean needCleanup = false;
|
||||||
try {
|
try {
|
||||||
@@ -478,33 +479,33 @@ public final class AvdManager {
|
|||||||
// writes the userdata.img in it.
|
// writes the userdata.img in it.
|
||||||
String imagePath = target.getPath(IAndroidTarget.IMAGES);
|
String imagePath = target.getPath(IAndroidTarget.IMAGES);
|
||||||
File userdataSrc = new File(imagePath, USERDATA_IMG);
|
File userdataSrc = new File(imagePath, USERDATA_IMG);
|
||||||
|
|
||||||
if (userdataSrc.exists() == false && target.isPlatform() == false) {
|
if (userdataSrc.exists() == false && target.isPlatform() == false) {
|
||||||
imagePath = target.getParent().getPath(IAndroidTarget.IMAGES);
|
imagePath = target.getParent().getPath(IAndroidTarget.IMAGES);
|
||||||
userdataSrc = new File(imagePath, USERDATA_IMG);
|
userdataSrc = new File(imagePath, USERDATA_IMG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userdataSrc.exists() == false) {
|
if (userdataSrc.exists() == false) {
|
||||||
mSdkLog.error(null, "Unable to find a '%1$s' file to copy into the AVD folder.",
|
mSdkLog.error(null, "Unable to find a '%1$s' file to copy into the AVD folder.",
|
||||||
USERDATA_IMG);
|
USERDATA_IMG);
|
||||||
needCleanup = true;
|
needCleanup = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileInputStream fis = new FileInputStream(userdataSrc);
|
FileInputStream fis = new FileInputStream(userdataSrc);
|
||||||
|
|
||||||
File userdataDest = new File(avdFolder, USERDATA_IMG);
|
File userdataDest = new File(avdFolder, USERDATA_IMG);
|
||||||
FileOutputStream fos = new FileOutputStream(userdataDest);
|
FileOutputStream fos = new FileOutputStream(userdataDest);
|
||||||
|
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int count;
|
int count;
|
||||||
while ((count = fis.read(buffer)) != -1) {
|
while ((count = fis.read(buffer)) != -1) {
|
||||||
fos.write(buffer, 0, count);
|
fos.write(buffer, 0, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fos.close();
|
fos.close();
|
||||||
fis.close();
|
fis.close();
|
||||||
|
|
||||||
// Config file.
|
// Config file.
|
||||||
HashMap<String, String> values = new HashMap<String, String>();
|
HashMap<String, String> values = new HashMap<String, String>();
|
||||||
|
|
||||||
@@ -512,7 +513,7 @@ public final class AvdManager {
|
|||||||
needCleanup = true;
|
needCleanup = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now the skin.
|
// Now the skin.
|
||||||
if (skinName == null || skinName.length() == 0) {
|
if (skinName == null || skinName.length() == 0) {
|
||||||
skinName = target.getDefaultSkin();
|
skinName = target.getDefaultSkin();
|
||||||
@@ -545,31 +546,31 @@ public final class AvdManager {
|
|||||||
} else {
|
} else {
|
||||||
// Sdcard is possibly a size. In that case we create a file called 'sdcard.img'
|
// Sdcard is possibly a size. In that case we create a file called 'sdcard.img'
|
||||||
// in the AVD folder, and do not put any value in config.ini.
|
// in the AVD folder, and do not put any value in config.ini.
|
||||||
|
|
||||||
// First, check that it matches the pattern for sdcard size
|
// First, check that it matches the pattern for sdcard size
|
||||||
Matcher m = SDCARD_SIZE_PATTERN.matcher(sdcard);
|
Matcher m = SDCARD_SIZE_PATTERN.matcher(sdcard);
|
||||||
if (m.matches()) {
|
if (m.matches()) {
|
||||||
// create the sdcard.
|
// create the sdcard.
|
||||||
sdcardFile = new File(avdFolder, SDCARD_IMG);
|
sdcardFile = new File(avdFolder, SDCARD_IMG);
|
||||||
String path = sdcardFile.getAbsolutePath();
|
String path = sdcardFile.getAbsolutePath();
|
||||||
|
|
||||||
// execute mksdcard with the proper parameters.
|
// execute mksdcard with the proper parameters.
|
||||||
File toolsFolder = new File(mSdk.getLocation(), SdkConstants.FD_TOOLS);
|
File toolsFolder = new File(mSdk.getLocation(), SdkConstants.FD_TOOLS);
|
||||||
File mkSdCard = new File(toolsFolder, SdkConstants.mkSdCardCmdName());
|
File mkSdCard = new File(toolsFolder, SdkConstants.mkSdCardCmdName());
|
||||||
|
|
||||||
if (mkSdCard.isFile() == false) {
|
if (mkSdCard.isFile() == false) {
|
||||||
mSdkLog.error(null, "'%1$s' is missing from the SDK tools folder.",
|
mSdkLog.error(null, "'%1$s' is missing from the SDK tools folder.",
|
||||||
mkSdCard.getName());
|
mkSdCard.getName());
|
||||||
needCleanup = true;
|
needCleanup = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createSdCard(mkSdCard.getAbsolutePath(), sdcard, path) == false) {
|
if (createSdCard(mkSdCard.getAbsolutePath(), sdcard, path) == false) {
|
||||||
needCleanup = true;
|
needCleanup = true;
|
||||||
return null; // mksdcard output has already been displayed, no need to
|
return null; // mksdcard output has already been displayed, no need to
|
||||||
// output anything else.
|
// output anything else.
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a property containing the size of the sdcard for display purpose
|
// add a property containing the size of the sdcard for display purpose
|
||||||
// only when the dev does 'android list avd'
|
// only when the dev does 'android list avd'
|
||||||
values.put(AVD_INI_SDCARD_SIZE, sdcard);
|
values.put(AVD_INI_SDCARD_SIZE, sdcard);
|
||||||
@@ -592,7 +593,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
File configIniFile = new File(avdFolder, CONFIG_INI);
|
File configIniFile = new File(avdFolder, CONFIG_INI);
|
||||||
writeIniFile(configIniFile, values);
|
writeIniFile(configIniFile, values);
|
||||||
|
|
||||||
if (mSdkLog != null) {
|
if (mSdkLog != null) {
|
||||||
if (target.isPlatform()) {
|
if (target.isPlatform()) {
|
||||||
mSdkLog.printf("Created AVD '%1$s' based on %2$s\n", name, target.getName());
|
mSdkLog.printf("Created AVD '%1$s' based on %2$s\n", name, target.getName());
|
||||||
@@ -601,7 +602,7 @@ public final class AvdManager {
|
|||||||
target.getVendor());
|
target.getVendor());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the AvdInfo object, and add it to the list
|
// create the AvdInfo object, and add it to the list
|
||||||
AvdInfo newAvdInfo = new AvdInfo(name,
|
AvdInfo newAvdInfo = new AvdInfo(name,
|
||||||
avdFolder.getAbsolutePath(),
|
avdFolder.getAbsolutePath(),
|
||||||
@@ -609,7 +610,7 @@ public final class AvdManager {
|
|||||||
target, values);
|
target, values);
|
||||||
|
|
||||||
AvdInfo oldAvdInfo = getAvd(name, false /*validAvdOnly*/);
|
AvdInfo oldAvdInfo = getAvd(name, false /*validAvdOnly*/);
|
||||||
|
|
||||||
synchronized (mAllAvdList) {
|
synchronized (mAllAvdList) {
|
||||||
if (oldAvdInfo != null && removePrevious) {
|
if (oldAvdInfo != null && removePrevious) {
|
||||||
mAllAvdList.remove(oldAvdInfo);
|
mAllAvdList.remove(oldAvdInfo);
|
||||||
@@ -619,7 +620,7 @@ public final class AvdManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (removePrevious &&
|
if (removePrevious &&
|
||||||
newAvdInfo != null &&
|
newAvdInfo != null &&
|
||||||
oldAvdInfo != null &&
|
oldAvdInfo != null &&
|
||||||
!oldAvdInfo.getPath().equals(newAvdInfo.getPath())) {
|
!oldAvdInfo.getPath().equals(newAvdInfo.getPath())) {
|
||||||
mSdkLog.warning("Removing previous AVD directory at %s", oldAvdInfo.getPath());
|
mSdkLog.warning("Removing previous AVD directory at %s", oldAvdInfo.getPath());
|
||||||
@@ -643,12 +644,12 @@ public final class AvdManager {
|
|||||||
if (iniFile != null && iniFile.exists()) {
|
if (iniFile != null && iniFile.exists()) {
|
||||||
iniFile.delete();
|
iniFile.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
recursiveDelete(avdFolder);
|
recursiveDelete(avdFolder);
|
||||||
avdFolder.delete();
|
avdFolder.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,7 +669,7 @@ public final class AvdManager {
|
|||||||
assert false;
|
assert false;
|
||||||
throw new InvalidTargetPathException("Target location is not inside the SDK.");
|
throw new InvalidTargetPathException("Target location is not inside the SDK.");
|
||||||
}
|
}
|
||||||
|
|
||||||
File folder = new File(imageFullPath);
|
File folder = new File(imageFullPath);
|
||||||
if (folder.isDirectory()) {
|
if (folder.isDirectory()) {
|
||||||
String[] list = folder.list(new FilenameFilter() {
|
String[] list = folder.list(new FilenameFilter() {
|
||||||
@@ -682,36 +683,36 @@ public final class AvdManager {
|
|||||||
if (imageFullPath.charAt(0) == File.separatorChar) {
|
if (imageFullPath.charAt(0) == File.separatorChar) {
|
||||||
imageFullPath = imageFullPath.substring(1);
|
imageFullPath = imageFullPath.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return imageFullPath;
|
return imageFullPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the path to the skin, as a relative path to the SDK.
|
* Returns the path to the skin, as a relative path to the SDK.
|
||||||
*/
|
*/
|
||||||
private String getSkinRelativePath(String skinName, IAndroidTarget target) {
|
private String getSkinRelativePath(String skinName, IAndroidTarget target) {
|
||||||
// first look to see if the skin is in the target
|
// first look to see if the skin is in the target
|
||||||
|
|
||||||
String path = target.getPath(IAndroidTarget.SKINS);
|
String path = target.getPath(IAndroidTarget.SKINS);
|
||||||
File skin = new File(path, skinName);
|
File skin = new File(path, skinName);
|
||||||
|
|
||||||
if (skin.exists() == false && target.isPlatform() == false) {
|
if (skin.exists() == false && target.isPlatform() == false) {
|
||||||
target = target.getParent();
|
target = target.getParent();
|
||||||
|
|
||||||
path = target.getPath(IAndroidTarget.SKINS);
|
path = target.getPath(IAndroidTarget.SKINS);
|
||||||
skin = new File(path, skinName);
|
skin = new File(path, skinName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skin really does not exist!
|
// skin really does not exist!
|
||||||
if (skin.exists() == false) {
|
if (skin.exists() == false) {
|
||||||
mSdkLog.error(null, "Skin '%1$s' does not exist.", skinName);
|
mSdkLog.error(null, "Skin '%1$s' does not exist.", skinName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the skin path
|
// get the skin path
|
||||||
path = skin.getAbsolutePath();
|
path = skin.getAbsolutePath();
|
||||||
|
|
||||||
@@ -733,7 +734,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the ini file for an AVD.
|
* Creates the ini file for an AVD.
|
||||||
*
|
*
|
||||||
* @param name of the AVD.
|
* @param name of the AVD.
|
||||||
* @param avdFolder path for the data folder of the AVD.
|
* @param avdFolder path for the data folder of the AVD.
|
||||||
* @param target of the AVD.
|
* @param target of the AVD.
|
||||||
@@ -750,10 +751,10 @@ public final class AvdManager {
|
|||||||
|
|
||||||
return iniFile;
|
return iniFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the ini file for an AVD.
|
* Creates the ini file for an AVD.
|
||||||
*
|
*
|
||||||
* @param info of the AVD.
|
* @param info of the AVD.
|
||||||
* @throws AndroidLocationException if there's a problem getting android root directory.
|
* @throws AndroidLocationException if there's a problem getting android root directory.
|
||||||
* @throws IOException if {@link File#getAbsolutePath()} fails.
|
* @throws IOException if {@link File#getAbsolutePath()} fails.
|
||||||
@@ -772,14 +773,14 @@ public final class AvdManager {
|
|||||||
* could not be loaded due to some error. That means this method still tries to remove
|
* could not be loaded due to some error. That means this method still tries to remove
|
||||||
* the AVD ini file or its folder if it can be found. An error will be output if any of
|
* the AVD ini file or its folder if it can be found. An error will be output if any of
|
||||||
* these operations fail.
|
* these operations fail.
|
||||||
*
|
*
|
||||||
* @param avdInfo the information on the AVD to delete
|
* @param avdInfo the information on the AVD to delete
|
||||||
* @return True if the AVD was deleted with no error.
|
* @return True if the AVD was deleted with no error.
|
||||||
*/
|
*/
|
||||||
public boolean deleteAvd(AvdInfo avdInfo, ISdkLog log) {
|
public boolean deleteAvd(AvdInfo avdInfo, ISdkLog log) {
|
||||||
try {
|
try {
|
||||||
boolean error = false;
|
boolean error = false;
|
||||||
|
|
||||||
File f = avdInfo.getIniFile();
|
File f = avdInfo.getIniFile();
|
||||||
if (f != null && f.exists()) {
|
if (f != null && f.exists()) {
|
||||||
log.warning("Deleting file %1$s", f.getCanonicalPath());
|
log.warning("Deleting file %1$s", f.getCanonicalPath());
|
||||||
@@ -819,22 +820,22 @@ public final class AvdManager {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves and/or rename an existing AVD and its files.
|
* Moves and/or rename an existing AVD and its files.
|
||||||
* This also change it in the manager's list.
|
* This also change it in the manager's list.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The caller should make sure the name or path given are valid, do not exist and are
|
* The caller should make sure the name or path given are valid, do not exist and are
|
||||||
* actually different than current values.
|
* actually different than current values.
|
||||||
*
|
*
|
||||||
* @param avdInfo the information on the AVD to move.
|
* @param avdInfo the information on the AVD to move.
|
||||||
* @param newName the new name of the AVD if non null.
|
* @param newName the new name of the AVD if non null.
|
||||||
* @param paramFolderPath the new data folder if non null.
|
* @param paramFolderPath the new data folder if non null.
|
||||||
* @return True if the move succeeded or there was nothing to do.
|
* @return True if the move succeeded or there was nothing to do.
|
||||||
* If false, this method will have had already output error in the log.
|
* If false, this method will have had already output error in the log.
|
||||||
*/
|
*/
|
||||||
public boolean moveAvd(AvdInfo avdInfo, String newName, String paramFolderPath, ISdkLog log) {
|
public boolean moveAvd(AvdInfo avdInfo, String newName, String paramFolderPath, ISdkLog log) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (paramFolderPath != null) {
|
if (paramFolderPath != null) {
|
||||||
File f = new File(avdInfo.getPath());
|
File f = new File(avdInfo.getPath());
|
||||||
@@ -844,7 +845,7 @@ public final class AvdManager {
|
|||||||
avdInfo.getPath(), paramFolderPath);
|
avdInfo.getPath(), paramFolderPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update AVD info
|
// update AVD info
|
||||||
AvdInfo info = new AvdInfo(avdInfo.getName(), paramFolderPath,
|
AvdInfo info = new AvdInfo(avdInfo.getName(), paramFolderPath,
|
||||||
avdInfo.getTargetHash(), avdInfo.getTarget(), avdInfo.getProperties());
|
avdInfo.getTargetHash(), avdInfo.getTarget(), avdInfo.getProperties());
|
||||||
@@ -857,10 +858,10 @@ public final class AvdManager {
|
|||||||
if (newName != null) {
|
if (newName != null) {
|
||||||
File oldIniFile = avdInfo.getIniFile();
|
File oldIniFile = avdInfo.getIniFile();
|
||||||
File newIniFile = AvdInfo.getIniFile(newName);
|
File newIniFile = AvdInfo.getIniFile(newName);
|
||||||
|
|
||||||
log.warning("Moving '%1$s' to '%2$s'.", oldIniFile.getPath(), newIniFile.getPath());
|
log.warning("Moving '%1$s' to '%2$s'.", oldIniFile.getPath(), newIniFile.getPath());
|
||||||
if (!oldIniFile.renameTo(newIniFile)) {
|
if (!oldIniFile.renameTo(newIniFile)) {
|
||||||
log.error(null, "Failed to move '%1$s' to '%2$s'.",
|
log.error(null, "Failed to move '%1$s' to '%2$s'.",
|
||||||
oldIniFile.getPath(), newIniFile.getPath());
|
oldIniFile.getPath(), newIniFile.getPath());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -885,7 +886,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to recursively delete a folder's content (but not the folder itself).
|
* Helper method to recursively delete a folder's content (but not the folder itself).
|
||||||
*
|
*
|
||||||
* @throws SecurityException like {@link File#delete()} does if file/folder is not writable.
|
* @throws SecurityException like {@link File#delete()} does if file/folder is not writable.
|
||||||
*/
|
*/
|
||||||
public void recursiveDelete(File folder) {
|
public void recursiveDelete(File folder) {
|
||||||
@@ -902,7 +903,7 @@ public final class AvdManager {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* This lists the $HOME/.android/avd/<name>.ini files.
|
* This lists the $HOME/.android/avd/<name>.ini files.
|
||||||
* Such files are properties file than then indicate where the AVD folder is located.
|
* Such files are properties file than then indicate where the AVD folder is located.
|
||||||
*
|
*
|
||||||
* @return A new {@link File} array or null. The array might be empty.
|
* @return A new {@link File} array or null. The array might be empty.
|
||||||
* @throws AndroidLocationException if there's a problem getting android root directory.
|
* @throws AndroidLocationException if there's a problem getting android root directory.
|
||||||
*/
|
*/
|
||||||
@@ -920,7 +921,7 @@ public final class AvdManager {
|
|||||||
folder.mkdirs();
|
folder.mkdirs();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
File[] avds = folder.listFiles(new FilenameFilter() {
|
File[] avds = folder.listFiles(new FilenameFilter() {
|
||||||
public boolean accept(File parent, String name) {
|
public boolean accept(File parent, String name) {
|
||||||
if (INI_NAME_PATTERN.matcher(name).matches()) {
|
if (INI_NAME_PATTERN.matcher(name).matches()) {
|
||||||
@@ -932,14 +933,14 @@ public final class AvdManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return avds;
|
return avds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the internal list of available AVDs
|
* Computes the internal list of available AVDs
|
||||||
* @param allList the list to contain all the AVDs
|
* @param allList the list to contain all the AVDs
|
||||||
*
|
*
|
||||||
* @throws AndroidLocationException if there's a problem getting android root directory.
|
* @throws AndroidLocationException if there's a problem getting android root directory.
|
||||||
*/
|
*/
|
||||||
private void buildAvdList(ArrayList<AvdInfo> allList) throws AndroidLocationException {
|
private void buildAvdList(ArrayList<AvdInfo> allList) throws AndroidLocationException {
|
||||||
@@ -956,7 +957,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses an AVD .ini file to create an {@link AvdInfo}.
|
* Parses an AVD .ini file to create an {@link AvdInfo}.
|
||||||
*
|
*
|
||||||
* @param path The path to the AVD .ini file
|
* @param path The path to the AVD .ini file
|
||||||
* @return A new {@link AvdInfo} with an {@link AvdStatus} indicating whether this AVD is
|
* @return A new {@link AvdInfo} with an {@link AvdStatus} indicating whether this AVD is
|
||||||
* valid or not.
|
* valid or not.
|
||||||
@@ -970,7 +971,7 @@ public final class AvdManager {
|
|||||||
IAndroidTarget target = null;
|
IAndroidTarget target = null;
|
||||||
File configIniFile = null;
|
File configIniFile = null;
|
||||||
Map<String, String> properties = null;
|
Map<String, String> properties = null;
|
||||||
|
|
||||||
if (targetHash != null) {
|
if (targetHash != null) {
|
||||||
target = mSdk.getTargetFromHashString(targetHash);
|
target = mSdk.getTargetFromHashString(targetHash);
|
||||||
}
|
}
|
||||||
@@ -979,7 +980,7 @@ public final class AvdManager {
|
|||||||
if (avdPath != null) {
|
if (avdPath != null) {
|
||||||
configIniFile = new File(avdPath, CONFIG_INI);
|
configIniFile = new File(avdPath, CONFIG_INI);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configIniFile != null) {
|
if (configIniFile != null) {
|
||||||
properties = SdkManager.parsePropertyFile(configIniFile, mSdkLog);
|
properties = SdkManager.parsePropertyFile(configIniFile, mSdkLog);
|
||||||
}
|
}
|
||||||
@@ -990,7 +991,7 @@ public final class AvdManager {
|
|||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
name = matcher.group(1);
|
name = matcher.group(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the image.sysdir are valid
|
// check the image.sysdir are valid
|
||||||
boolean validImageSysdir = true;
|
boolean validImageSysdir = true;
|
||||||
if (properties != null) {
|
if (properties != null) {
|
||||||
@@ -1012,7 +1013,7 @@ public final class AvdManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AvdStatus status;
|
AvdStatus status;
|
||||||
|
|
||||||
if (avdPath == null) {
|
if (avdPath == null) {
|
||||||
status = AvdStatus.ERROR_PATH;
|
status = AvdStatus.ERROR_PATH;
|
||||||
} else if (configIniFile == null) {
|
} else if (configIniFile == null) {
|
||||||
@@ -1028,7 +1029,7 @@ public final class AvdManager {
|
|||||||
} else {
|
} else {
|
||||||
status = AvdStatus.OK;
|
status = AvdStatus.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
AvdInfo info = new AvdInfo(
|
AvdInfo info = new AvdInfo(
|
||||||
name,
|
name,
|
||||||
avdPath,
|
avdPath,
|
||||||
@@ -1036,30 +1037,31 @@ public final class AvdManager {
|
|||||||
target,
|
target,
|
||||||
properties,
|
properties,
|
||||||
status);
|
status);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a .ini file from a set of properties.
|
* Writes a .ini file from a set of properties, using UTF-8 encoding.
|
||||||
*
|
*
|
||||||
* @param iniFile The file to generate.
|
* @param iniFile The file to generate.
|
||||||
* @param values THe properties to place in the ini file.
|
* @param values THe properties to place in the ini file.
|
||||||
* @throws IOException if {@link FileWriter} fails to open, write or close the file.
|
* @throws IOException if {@link FileWriter} fails to open, write or close the file.
|
||||||
*/
|
*/
|
||||||
private static void writeIniFile(File iniFile, Map<String, String> values)
|
private static void writeIniFile(File iniFile, Map<String, String> values)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
FileWriter writer = new FileWriter(iniFile);
|
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(iniFile),
|
||||||
|
SdkConstants.INI_CHARSET);
|
||||||
|
|
||||||
for (Entry<String, String> entry : values.entrySet()) {
|
for (Entry<String, String> entry : values.entrySet()) {
|
||||||
writer.write(String.format("%1$s=%2$s\n", entry.getKey(), entry.getValue()));
|
writer.write(String.format("%1$s=%2$s\n", entry.getKey(), entry.getValue()));
|
||||||
}
|
}
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invokes the tool to create a new SD card image file.
|
* Invokes the tool to create a new SD card image file.
|
||||||
*
|
*
|
||||||
* @param toolLocation The path to the mksdcard tool.
|
* @param toolLocation The path to the mksdcard tool.
|
||||||
* @param size The size of the new SD Card, compatible with {@link #SDCARD_SIZE_PATTERN}.
|
* @param size The size of the new SD Card, compatible with {@link #SDCARD_SIZE_PATTERN}.
|
||||||
* @param location The path of the new sdcard image file to generate.
|
* @param location The path of the new sdcard image file to generate.
|
||||||
@@ -1072,7 +1074,7 @@ public final class AvdManager {
|
|||||||
command[1] = size;
|
command[1] = size;
|
||||||
command[2] = location;
|
command[2] = location;
|
||||||
Process process = Runtime.getRuntime().exec(command);
|
Process process = Runtime.getRuntime().exec(command);
|
||||||
|
|
||||||
ArrayList<String> errorOutput = new ArrayList<String>();
|
ArrayList<String> errorOutput = new ArrayList<String>();
|
||||||
ArrayList<String> stdOutput = new ArrayList<String>();
|
ArrayList<String> stdOutput = new ArrayList<String>();
|
||||||
int status = grabProcessOutput(process, errorOutput, stdOutput,
|
int status = grabProcessOutput(process, errorOutput, stdOutput,
|
||||||
@@ -1091,7 +1093,7 @@ public final class AvdManager {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// pass, print error below
|
// pass, print error below
|
||||||
}
|
}
|
||||||
|
|
||||||
mSdkLog.error(null, "Failed to create the SD card.");
|
mSdkLog.error(null, "Failed to create the SD card.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1102,7 +1104,7 @@ public final class AvdManager {
|
|||||||
* @param process The process to get the ouput from
|
* @param process The process to get the ouput from
|
||||||
* @param errorOutput The array to store the stderr output. cannot be null.
|
* @param errorOutput The array to store the stderr output. cannot be null.
|
||||||
* @param stdOutput The array to store the stdout output. cannot be null.
|
* @param stdOutput The array to store the stdout output. cannot be null.
|
||||||
* @param waitforReaders if true, this will wait for the reader threads.
|
* @param waitforReaders if true, this will wait for the reader threads.
|
||||||
* @return the process return code.
|
* @return the process return code.
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
@@ -1179,7 +1181,7 @@ public final class AvdManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an {@link AvdInfo} from the internal list.
|
* Removes an {@link AvdInfo} from the internal list.
|
||||||
*
|
*
|
||||||
* @param avdInfo The {@link AvdInfo} to remove.
|
* @param avdInfo The {@link AvdInfo} to remove.
|
||||||
* @return true if this {@link AvdInfo} was present and has been removed.
|
* @return true if this {@link AvdInfo} was present and has been removed.
|
||||||
*/
|
*/
|
||||||
@@ -1190,15 +1192,15 @@ public final class AvdManager {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates an AVD with new path to the system image folders.
|
* Updates an AVD with new path to the system image folders.
|
||||||
* @param name the name of the AVD to update.
|
* @param name the name of the AVD to update.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws AndroidLocationException
|
* @throws AndroidLocationException
|
||||||
*/
|
*/
|
||||||
public void updateAvd(String name) throws IOException, AndroidLocationException {
|
public void updateAvd(String name) throws IOException, AndroidLocationException {
|
||||||
// find the AVD to update. It should be be in the broken list.
|
// find the AVD to update. It should be be in the broken list.
|
||||||
@@ -1211,7 +1213,7 @@ public final class AvdManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avd == null) {
|
if (avd == null) {
|
||||||
// not in the broken list, just return.
|
// not in the broken list, just return.
|
||||||
mSdkLog.error(null, "There is no Android Virtual Device named '%s'.", name);
|
mSdkLog.error(null, "There is no Android Virtual Device named '%s'.", name);
|
||||||
@@ -1226,21 +1228,21 @@ public final class AvdManager {
|
|||||||
if (oldProperties != null) {
|
if (oldProperties != null) {
|
||||||
properties.putAll(oldProperties);
|
properties.putAll(oldProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvdStatus status;
|
AvdStatus status;
|
||||||
|
|
||||||
// create the path to the new system images.
|
// create the path to the new system images.
|
||||||
if (setImagePathProperties(avd.getTarget(), properties)) {
|
if (setImagePathProperties(avd.getTarget(), properties)) {
|
||||||
if (properties.containsKey(AVD_INI_IMAGES_1)) {
|
if (properties.containsKey(AVD_INI_IMAGES_1)) {
|
||||||
mSdkLog.printf("Updated '%1$s' with value '%2$s'\n", AVD_INI_IMAGES_1,
|
mSdkLog.printf("Updated '%1$s' with value '%2$s'\n", AVD_INI_IMAGES_1,
|
||||||
properties.get(AVD_INI_IMAGES_1));
|
properties.get(AVD_INI_IMAGES_1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (properties.containsKey(AVD_INI_IMAGES_2)) {
|
if (properties.containsKey(AVD_INI_IMAGES_2)) {
|
||||||
mSdkLog.printf("Updated '%1$s' with value '%2$s'\n", AVD_INI_IMAGES_2,
|
mSdkLog.printf("Updated '%1$s' with value '%2$s'\n", AVD_INI_IMAGES_2,
|
||||||
properties.get(AVD_INI_IMAGES_2));
|
properties.get(AVD_INI_IMAGES_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
status = AvdStatus.OK;
|
status = AvdStatus.OK;
|
||||||
} else {
|
} else {
|
||||||
mSdkLog.error(null, "Unable to find non empty system images folders for %1$s", name);
|
mSdkLog.error(null, "Unable to find non empty system images folders for %1$s", name);
|
||||||
@@ -1263,7 +1265,7 @@ public final class AvdManager {
|
|||||||
avd.getTarget(),
|
avd.getTarget(),
|
||||||
properties,
|
properties,
|
||||||
status);
|
status);
|
||||||
|
|
||||||
replaceAvd(avd, newAvd);
|
replaceAvd(avd, newAvd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1276,18 +1278,18 @@ public final class AvdManager {
|
|||||||
private boolean setImagePathProperties(IAndroidTarget target, Map<String, String> properties) {
|
private boolean setImagePathProperties(IAndroidTarget target, Map<String, String> properties) {
|
||||||
properties.remove(AVD_INI_IMAGES_1);
|
properties.remove(AVD_INI_IMAGES_1);
|
||||||
properties.remove(AVD_INI_IMAGES_2);
|
properties.remove(AVD_INI_IMAGES_2);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String property = AVD_INI_IMAGES_1;
|
String property = AVD_INI_IMAGES_1;
|
||||||
|
|
||||||
// First the image folders of the target itself
|
// First the image folders of the target itself
|
||||||
String imagePath = getImageRelativePath(target);
|
String imagePath = getImageRelativePath(target);
|
||||||
if (imagePath != null) {
|
if (imagePath != null) {
|
||||||
properties.put(property, imagePath);
|
properties.put(property, imagePath);
|
||||||
property = AVD_INI_IMAGES_2;
|
property = AVD_INI_IMAGES_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// If the target is an add-on we need to add the Platform image as a backup.
|
// If the target is an add-on we need to add the Platform image as a backup.
|
||||||
IAndroidTarget parent = target.getParent();
|
IAndroidTarget parent = target.getParent();
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
@@ -1296,16 +1298,16 @@ public final class AvdManager {
|
|||||||
properties.put(property, imagePath);
|
properties.put(property, imagePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need at least one path!
|
// we need at least one path!
|
||||||
return properties.containsKey(AVD_INI_IMAGES_1);
|
return properties.containsKey(AVD_INI_IMAGES_1);
|
||||||
} catch (InvalidTargetPathException e) {
|
} catch (InvalidTargetPathException e) {
|
||||||
mSdkLog.error(e, e.getMessage());
|
mSdkLog.error(e, e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces an old {@link AvdInfo} with a new one in the lists storing them.
|
* Replaces an old {@link AvdInfo} with a new one in the lists storing them.
|
||||||
* @param oldAvd the {@link AvdInfo} to remove.
|
* @param oldAvd the {@link AvdInfo} to remove.
|
||||||
|
|||||||
@@ -17,11 +17,14 @@
|
|||||||
package com.android.sdklib.internal.project;
|
package com.android.sdklib.internal.project;
|
||||||
|
|
||||||
import com.android.sdklib.IAndroidTarget;
|
import com.android.sdklib.IAndroidTarget;
|
||||||
|
import com.android.sdklib.SdkConstants;
|
||||||
import com.android.sdklib.SdkManager;
|
import com.android.sdklib.SdkManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -35,12 +38,12 @@ public final class ProjectProperties {
|
|||||||
public final static String PROPERTY_TARGET = "target";
|
public final static String PROPERTY_TARGET = "target";
|
||||||
public final static String PROPERTY_APK_CONFIGS = "apk-configurations";
|
public final static String PROPERTY_APK_CONFIGS = "apk-configurations";
|
||||||
public final static String PROPERTY_SDK = "sdk-location";
|
public final static String PROPERTY_SDK = "sdk-location";
|
||||||
|
|
||||||
public static enum PropertyType {
|
public static enum PropertyType {
|
||||||
BUILD("build.properties", BUILD_HEADER),
|
BUILD("build.properties", BUILD_HEADER),
|
||||||
DEFAULT("default.properties", DEFAULT_HEADER),
|
DEFAULT("default.properties", DEFAULT_HEADER),
|
||||||
LOCAL("local.properties", LOCAL_HEADER);
|
LOCAL("local.properties", LOCAL_HEADER);
|
||||||
|
|
||||||
private final String mFilename;
|
private final String mFilename;
|
||||||
private final String mHeader;
|
private final String mHeader;
|
||||||
|
|
||||||
@@ -48,14 +51,14 @@ public final class ProjectProperties {
|
|||||||
mFilename = filename;
|
mFilename = filename;
|
||||||
mHeader = header;
|
mHeader = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFilename() {
|
public String getFilename() {
|
||||||
return mFilename;
|
return mFilename;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static String LOCAL_HEADER =
|
private final static String LOCAL_HEADER =
|
||||||
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
||||||
"# This file is automatically generated by Android Tools.\n" +
|
"# This file is automatically generated by Android Tools.\n" +
|
||||||
"# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
|
"# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
|
||||||
"# \n" +
|
"# \n" +
|
||||||
@@ -64,7 +67,7 @@ public final class ProjectProperties {
|
|||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
private final static String DEFAULT_HEADER =
|
private final static String DEFAULT_HEADER =
|
||||||
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
||||||
"# This file is automatically generated by Android Tools.\n" +
|
"# This file is automatically generated by Android Tools.\n" +
|
||||||
"# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
|
"# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
|
||||||
"# \n" +
|
"# \n" +
|
||||||
@@ -76,7 +79,7 @@ public final class ProjectProperties {
|
|||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
private final static String BUILD_HEADER =
|
private final static String BUILD_HEADER =
|
||||||
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
||||||
"# This file is used to override default values used by the Ant build system.\n" +
|
"# This file is used to override default values used by the Ant build system.\n" +
|
||||||
"# \n" +
|
"# \n" +
|
||||||
"# This file must be checked in Version Control Systems, as it is\n" +
|
"# This file must be checked in Version Control Systems, as it is\n" +
|
||||||
@@ -95,7 +98,7 @@ public final class ProjectProperties {
|
|||||||
|
|
||||||
private final static Map<String, String> COMMENT_MAP = new HashMap<String, String>();
|
private final static Map<String, String> COMMENT_MAP = new HashMap<String, String>();
|
||||||
static {
|
static {
|
||||||
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
// 1-------10--------20--------30--------40--------50--------60--------70--------80
|
||||||
COMMENT_MAP.put(PROPERTY_TARGET,
|
COMMENT_MAP.put(PROPERTY_TARGET,
|
||||||
"# Project target.\n");
|
"# Project target.\n");
|
||||||
COMMENT_MAP.put(PROPERTY_APK_CONFIGS,
|
COMMENT_MAP.put(PROPERTY_APK_CONFIGS,
|
||||||
@@ -114,7 +117,7 @@ public final class ProjectProperties {
|
|||||||
"# For customization when using a Version Control System, please read the\n" +
|
"# For customization when using a Version Control System, please read the\n" +
|
||||||
"# header note.\n");
|
"# header note.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String mProjectFolderOsPath;
|
private final String mProjectFolderOsPath;
|
||||||
private final Map<String, String> mProperties;
|
private final Map<String, String> mProperties;
|
||||||
private final PropertyType mType;
|
private final PropertyType mType;
|
||||||
@@ -122,9 +125,9 @@ public final class ProjectProperties {
|
|||||||
/**
|
/**
|
||||||
* Loads a project properties file and return a {@link ProjectProperties} object
|
* Loads a project properties file and return a {@link ProjectProperties} object
|
||||||
* containing the properties
|
* containing the properties
|
||||||
*
|
*
|
||||||
* @param projectFolderOsPath the project folder.
|
* @param projectFolderOsPath the project folder.
|
||||||
* @param type One the possible {@link PropertyType}s.
|
* @param type One the possible {@link PropertyType}s.
|
||||||
*/
|
*/
|
||||||
public static ProjectProperties load(String projectFolderOsPath, PropertyType type) {
|
public static ProjectProperties load(String projectFolderOsPath, PropertyType type) {
|
||||||
File projectFolder = new File(projectFolderOsPath);
|
File projectFolder = new File(projectFolderOsPath);
|
||||||
@@ -139,7 +142,7 @@ public final class ProjectProperties {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges all properties from the given file into the current properties.
|
* Merges all properties from the given file into the current properties.
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -153,8 +156,8 @@ public final class ProjectProperties {
|
|||||||
* <li>The result is that this contains all the properties from default plus those
|
* <li>The result is that this contains all the properties from default plus those
|
||||||
* overridden by the build.properties file.
|
* overridden by the build.properties file.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param type One the possible {@link PropertyType}s.
|
* @param type One the possible {@link PropertyType}s.
|
||||||
* @return this object, for chaining.
|
* @return this object, for chaining.
|
||||||
*/
|
*/
|
||||||
public ProjectProperties merge(PropertyType type) {
|
public ProjectProperties merge(PropertyType type) {
|
||||||
@@ -187,7 +190,7 @@ public final class ProjectProperties {
|
|||||||
// create and return a ProjectProperties with an empty map.
|
// create and return a ProjectProperties with an empty map.
|
||||||
return new ProjectProperties(projectFolderOsPath, new HashMap<String, String>(), type);
|
return new ProjectProperties(projectFolderOsPath, new HashMap<String, String>(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a new properties. If a property with the same name already exists, it is replaced.
|
* Sets a new properties. If a property with the same name already exists, it is replaced.
|
||||||
* @param name the name of the property.
|
* @param name the name of the property.
|
||||||
@@ -196,7 +199,7 @@ public final class ProjectProperties {
|
|||||||
public void setProperty(String name, String value) {
|
public void setProperty(String name, String value) {
|
||||||
mProperties.put(name, value);
|
mProperties.put(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the target property to the given {@link IAndroidTarget} object.
|
* Sets the target property to the given {@link IAndroidTarget} object.
|
||||||
* @param target the Android target.
|
* @param target the Android target.
|
||||||
@@ -205,7 +208,7 @@ public final class ProjectProperties {
|
|||||||
assert mType == PropertyType.DEFAULT;
|
assert mType == PropertyType.DEFAULT;
|
||||||
mProperties.put(PROPERTY_TARGET, target.hashString());
|
mProperties.put(PROPERTY_TARGET, target.hashString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of a property.
|
* Returns the value of a property.
|
||||||
* @param name the name of the property.
|
* @param name the name of the property.
|
||||||
@@ -214,7 +217,7 @@ public final class ProjectProperties {
|
|||||||
public String getProperty(String name) {
|
public String getProperty(String name) {
|
||||||
return mProperties.get(name);
|
return mProperties.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a property and returns its previous value (or null if the property did not exist).
|
* Removes a property and returns its previous value (or null if the property did not exist).
|
||||||
* @param name the name of the property to remove.
|
* @param name the name of the property to remove.
|
||||||
@@ -224,17 +227,18 @@ public final class ProjectProperties {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the property file.
|
* Saves the property file, using UTF-8 encoding.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void save() throws IOException {
|
public void save() throws IOException {
|
||||||
File toSave = new File(mProjectFolderOsPath, mType.mFilename);
|
File toSave = new File(mProjectFolderOsPath, mType.mFilename);
|
||||||
|
|
||||||
FileWriter writer = new FileWriter(toSave);
|
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(toSave),
|
||||||
|
SdkConstants.INI_CHARSET);
|
||||||
|
|
||||||
// write the header
|
// write the header
|
||||||
writer.write(mType.mHeader);
|
writer.write(mType.mHeader);
|
||||||
|
|
||||||
// write the properties.
|
// write the properties.
|
||||||
for (Entry<String, String> entry : mProperties.entrySet()) {
|
for (Entry<String, String> entry : mProperties.entrySet()) {
|
||||||
String comment = COMMENT_MAP.get(entry.getKey());
|
String comment = COMMENT_MAP.get(entry.getKey());
|
||||||
@@ -245,11 +249,11 @@ public final class ProjectProperties {
|
|||||||
value = value.replaceAll("\\\\", "\\\\\\\\");
|
value = value.replaceAll("\\\\", "\\\\\\\\");
|
||||||
writer.write(String.format("%s=%s\n", entry.getKey(), value));
|
writer.write(String.format("%s=%s\n", entry.getKey(), value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the file to flush
|
// close the file to flush
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private constructor.
|
* Private constructor.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
|||||||
Reference in New Issue
Block a user