diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java b/tools/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java index 50fe5c6b7..5da564517 100644 --- a/tools/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java +++ b/tools/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java @@ -34,7 +34,7 @@ import java.util.Map.Entry; * To use, call {@link #parseArgs(String[])} and then * call {@link #getValue(String, String, String)}. */ -public class CommandLineProcessor { +class CommandLineProcessor { /** Internal verb name for internally hidden flags. */ public final static String GLOBAL_FLAG_VERB = "@@internal@@"; diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java index 491e61cba..623659977 100644 --- a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java +++ b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java @@ -50,6 +50,9 @@ class Main { * is actually the tools dir, in which case this is used to get the original CWD. */ private final static String WORKDIR = "com.android.sdkmanager.workdir"; + /** Value returned by {@link #resolveTargetName(String)} when the target id does not match. */ + private final static int INVALID_TARGET_ID = 0; + private final static String[] BOOLEAN_YES_REPLIES = new String[] { "yes", "y" }; private final static String[] BOOLEAN_NO_REPLIES = new String[] { "no", "n" }; @@ -260,7 +263,7 @@ class Main { */ private void createProject() { // get the target and try to resolve it. - int targetId = mSdkCommandLine.getParamTargetId(); + int targetId = resolveTargetName(mSdkCommandLine.getParamTargetId()); IAndroidTarget[] targets = mSdkManager.getTargets(); if (targetId < 1 || targetId > targets.length) { errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.", @@ -320,7 +323,7 @@ class Main { private void updateProject() { // get the target and try to resolve it. IAndroidTarget target = null; - int targetId = mSdkCommandLine.getParamTargetId(); + int targetId = resolveTargetName(mSdkCommandLine.getParamTargetId()); if (targetId >= 0) { IAndroidTarget[] targets = mSdkManager.getTargets(); if (targetId < 1 || targetId > targets.length) { @@ -412,7 +415,7 @@ class Main { int index = 1; for (IAndroidTarget target : mSdkManager.getTargets()) { - mSdkLog.printf("id: %d\n", index); + mSdkLog.printf("id: %1$d or \"%2$s\"\n", index, target.hashString()); mSdkLog.printf(" Name: %s\n", target.getName()); if (target.isPlatform()) { mSdkLog.printf(" Type: Platform\n"); @@ -557,7 +560,7 @@ class Main { */ private void createAvd() { // find a matching target - int targetId = mSdkCommandLine.getParamTargetId(); + int targetId = resolveTargetName(mSdkCommandLine.getParamTargetId()); IAndroidTarget target = null; if (targetId >= 1 && targetId <= mSdkManager.getTargets().length) { @@ -587,7 +590,9 @@ class Main { "Android Virtual Device '%s' already exists and will be replaced.", avdName); } else { - errorAndExit("Android Virtual Device '%s' already exists.", avdName); + errorAndExit("Android Virtual Device '%s' already exists.\n" + + "Use --force if you want to replace it.", + avdName); return; } } @@ -608,7 +613,7 @@ class Main { skin = null; } - if (skin != null) { + if (skin != null && target != null) { boolean valid = false; // Is it a know skin name for this target? for (String s : target.getSkins()) { @@ -640,7 +645,7 @@ class Main { } Map hardwareConfig = null; - if (target.isPlatform()) { + if (target != null && target.isPlatform()) { try { hardwareConfig = promptForHardware(target, skinHardwareConfig); } catch (IOException e) { @@ -648,11 +653,13 @@ class Main { } } + @SuppressWarnings("unused") // oldAvdInfo is never read, yet useful for debugging AvdInfo oldAvdInfo = null; if (removePrevious) { oldAvdInfo = avdManager.getAvd(avdName, false /*validAvdOnly*/); } + @SuppressWarnings("unused") // newAvdInfo is never read, yet useful for debugging AvdInfo newAvdInfo = avdManager.createAvd(avdFolder, avdName, target, @@ -979,4 +986,43 @@ class Main { mSdkLog.error(null, format, args); System.exit(1); } + + /** + * Converts a symbolic target name (such as those accepted by --target on the command-line) + * to an internal target index id. A valid target name is either a numeric target id (> 0) + * or a target hash string. + *

+ * If the given target can't be mapped, {@link #INVALID_TARGET_ID} (0) is returned. + * It's up to the caller to output an error. + *

+ * On success, returns a value > 0. + */ + private int resolveTargetName(String targetName) { + + if (targetName == null) { + return INVALID_TARGET_ID; + } + + targetName = targetName.trim(); + + // Case of an integer number + if (targetName.matches("[0-9]*")) { + try { + int n = Integer.parseInt(targetName); + return n < 1 ? INVALID_TARGET_ID : n; + } catch (NumberFormatException e) { + // Ignore. Should not happen. + } + } + + // Let's try to find a platform or addon name. + IAndroidTarget[] targets = mSdkManager.getTargets(); + for (int i = 0; i < targets.length; i++) { + if (targetName.equals(targets[i].hashString())) { + return i + 1; + } + } + + return INVALID_TARGET_ID; + } } diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java b/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java index c48a3860b..a23a65c00 100644 --- a/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java +++ b/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java @@ -23,7 +23,7 @@ import com.android.sdklib.SdkManager; /** * Specific command-line flags for the {@link SdkManager}. */ -public class SdkCommandLine extends CommandLineProcessor { +class SdkCommandLine extends CommandLineProcessor { public final static String VERB_LIST = "list"; public final static String VERB_CREATE = "create"; @@ -104,7 +104,7 @@ public class SdkCommandLine extends CommandLineProcessor { define(Mode.STRING, true, VERB_CREATE, OBJECT_AVD, "n", KEY_NAME, "Name of the new AVD", null); - define(Mode.INTEGER, true, + define(Mode.STRING, true, VERB_CREATE, OBJECT_AVD, "t", KEY_TARGET_ID, "Target id of the new AVD", null); define(Mode.STRING, false, @@ -154,7 +154,7 @@ public class SdkCommandLine extends CommandLineProcessor { VERB_CREATE, OBJECT_PROJECT, "p", KEY_PATH, "Location path of new project", null); - define(Mode.INTEGER, true, + define(Mode.STRING, true, VERB_CREATE, OBJECT_PROJECT, "t", KEY_TARGET_ID, "Target id of the new project", null); define(Mode.STRING, true, @@ -173,7 +173,7 @@ public class SdkCommandLine extends CommandLineProcessor { VERB_UPDATE, OBJECT_PROJECT, "p", KEY_PATH, "Location path of the project", null); - define(Mode.INTEGER, true, + define(Mode.STRING, true, VERB_UPDATE, OBJECT_PROJECT, "t", KEY_TARGET_ID, "Target id to set for the project", -1); @@ -196,27 +196,34 @@ public class SdkCommandLine extends CommandLineProcessor { /** Helper to retrieve the --path value. */ public String getParamLocationPath() { - return ((String) getValue(null, null, KEY_PATH)); + return (String) getValue(null, null, KEY_PATH); } - /** Helper to retrieve the --target id value. */ - public int getParamTargetId() { - return ((Integer) getValue(null, null, KEY_TARGET_ID)).intValue(); + /** + * Helper to retrieve the --target id value. + * The id is a string. It can be one of: + * - an integer, in which case it's the index of the target (cf "android list targets") + * - a symbolic name such as android-N for platforn API N + * - a symbolic add-on name such as written in the avd/*.ini files, + * e.g. "Google Inc.:Google APIs:3" + */ + public String getParamTargetId() { + return (String) getValue(null, null, KEY_TARGET_ID); } /** Helper to retrieve the --name value. */ public String getParamName() { - return ((String) getValue(null, null, KEY_NAME)); + return (String) getValue(null, null, KEY_NAME); } /** Helper to retrieve the --skin value. */ public String getParamSkin() { - return ((String) getValue(null, null, KEY_SKIN)); + return (String) getValue(null, null, KEY_SKIN); } /** Helper to retrieve the --sdcard value. */ public String getParamSdCard() { - return ((String) getValue(null, null, KEY_SDCARD)); + return (String) getValue(null, null, KEY_SDCARD); } /** Helper to retrieve the --force flag. */ @@ -228,7 +235,7 @@ public class SdkCommandLine extends CommandLineProcessor { /** Helper to retrieve the --rename value for a move verb. */ public String getParamMoveNewName() { - return ((String) getValue(VERB_MOVE, null, KEY_RENAME)); + return (String) getValue(VERB_MOVE, null, KEY_RENAME); } diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java index b23d1bd58..7b47f4acf 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java @@ -88,6 +88,16 @@ public final class SdkManager { private final String mSdkLocation; private IAndroidTarget[] mTargets; + /** + * Create a new {@link SdkManager} instance. + * External users should use {@link #createManager(String, ISdkLog)}. + * + * @param sdkLocation the location of the SDK. + */ + private SdkManager(String sdkLocation) { + mSdkLocation = sdkLocation; + } + /** * Creates an {@link SdkManager} for a given sdk location. * @param sdkLocation the location of the SDK. @@ -125,11 +135,23 @@ public final class SdkManager { /** * Returns the targets that are available in the SDK. + *

+ * The array can be empty but not null. */ public IAndroidTarget[] getTargets() { return mTargets; } + /** + * Sets the targets that are available in the SDK. + *

+ * The array can be empty but not null. + */ + private void setTargets(IAndroidTarget[] targets) { + assert targets != null; + mTargets = targets; + } + /** * Returns a target from a hash that was generated by {@link IAndroidTarget#hashString()}. * @@ -202,14 +224,6 @@ public final class SdkManager { setTargets(list.toArray(new IAndroidTarget[list.size()])); } - private SdkManager(String sdkLocation) { - mSdkLocation = sdkLocation; - } - - private void setTargets(IAndroidTarget[] targets) { - mTargets = targets; - } - /** * Loads the Platforms from the SDK. * @param location Location of the SDK