Add support for add-on based on preview of platforms.
diff --git a/anttasks/src/com/android/ant/SetupTask.java b/anttasks/src/com/android/ant/SetupTask.java
index f79f381..04afba7 100644
--- a/anttasks/src/com/android/ant/SetupTask.java
+++ b/anttasks/src/com/android/ant/SetupTask.java
@@ -22,6 +22,7 @@
 import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
 import com.android.sdklib.internal.project.ProjectProperties;
 import com.android.sdklib.xml.AndroidXPathFactory;
+import com.android.sdklib.xml.ManifestConstants;
 
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
@@ -225,8 +226,10 @@
 
             XPath xPath = AndroidXPathFactory.newXPath();
 
-            String value = xPath.evaluate("/manifest/uses-sdk/@" +
-                    AndroidXPathFactory.DEFAULT_NS_PREFIX + ":minSdkVersion",
+            String value = xPath.evaluate("/" + ManifestConstants.NODE_MANIFEST +"/" +
+                    ManifestConstants.NODE_USES_SDK + "/@" +
+                    AndroidXPathFactory.DEFAULT_NS_PREFIX + ":" +
+                    ManifestConstants.ATTRIBUTE_MIN_SDK_VERSION,
                     new InputSource(new FileInputStream(manifest)));
 
             if (codename.equals(value) == false) {
diff --git a/eclipse/changes.txt b/eclipse/changes.txt
index ecb1f15..cd2736a 100644
--- a/eclipse/changes.txt
+++ b/eclipse/changes.txt
@@ -1,6 +1,7 @@
 0.9.2:
 - New wizard to create Android JUnit Test Projects.
-
+- New AVD wizard.
+- SDK Updater
 
 0.9.1:
 - Added an AVD creation wizard to ADT. It is automatically displayed during a launch if no compatible AVDs are found.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 406285a..b3635fc 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -97,8 +97,11 @@
  com.android.sdklib.internal.project;x-friends:="com.android.ide.eclipse.tests",
  com.android.sdklib.internal.repository;x-friends:="com.android.ide.eclipse.tests",
  com.android.sdklib.repository;x-friends:="com.android.ide.eclipse.tests",
+ com.android.sdklib.xml;x-friends:="com.android.ide.eclipse.tests",
  com.android.sdkstats;x-friends:="com.android.ide.eclipse.tests",
  com.android.sdkuilib.internal.repository;x-friends:="com.android.ide.eclipse.tests",
+ com.android.sdkuilib.internal.repository.icons;x-friends:="com.android.ide.eclipse.tests",
+ com.android.sdkuilib.internal.tasks;x-friends:="com.android.ide.eclipse.tests",
  com.android.sdkuilib.internal.widgets;x-friends:="com.android.ide.eclipse.tests",
  com.android.sdkuilib.repository;x-friends:="com.android.ide.eclipse.tests"
 
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/PreCompilerBuilder.java
index c7fd289..2ba0b03 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/PreCompilerBuilder.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/PreCompilerBuilder.java
@@ -27,6 +27,7 @@
 import com.android.sdklib.AndroidVersion;
 import com.android.sdklib.IAndroidTarget;
 import com.android.sdklib.SdkConstants;
+import com.android.sdklib.xml.ManifestConstants;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
@@ -332,7 +333,7 @@
                         // integer minSdk when the target is a preview => fatal error
                         String msg = String.format(
                                 "Platform %1$s is a preview and requires appication manifests to set %2$s to '%3$s'",
-                                codename, AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION,
+                                codename, ManifestConstants.ATTRIBUTE_MIN_SDK_VERSION,
                                 codename);
                         AdtPlugin.printErrorToConsole(project, msg);
                         BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
@@ -355,7 +356,7 @@
                         // platform is not a preview => fatal error
                         String msg = String.format(
                                 "Manifest attribute '%1$s' is set to '%2$s'. Integer is expected.",
-                                AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION, codename);
+                                ManifestConstants.ATTRIBUTE_MIN_SDK_VERSION, codename);
                         AdtPlugin.printErrorToConsole(project, msg);
                         BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
                                 IMarker.SEVERITY_ERROR);
@@ -364,7 +365,7 @@
                         // platform and manifest codenames don't match => fatal error.
                         String msg = String.format(
                                 "Value of manifest attribute '%1$s' does not match platform codename '%2$s'",
-                                AndroidManifestParser.ATTRIBUTE_MIN_SDK_VERSION, codename);
+                                ManifestConstants.ATTRIBUTE_MIN_SDK_VERSION, codename);
                         AdtPlugin.printErrorToConsole(project, msg);
                         BaseProjectHelper.addMarker(manifest, AdtConstants.MARKER_ADT, msg,
                                 IMarker.SEVERITY_ERROR);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidManifestParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidManifestParser.java
index d5fd4e7..10e727c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidManifestParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidManifestParser.java
@@ -20,6 +20,7 @@
 import com.android.ide.eclipse.adt.AndroidConstants;
 import com.android.ide.eclipse.adt.internal.project.XmlErrorHandler.XmlErrorListener;
 import com.android.sdklib.SdkConstants;
+import com.android.sdklib.xml.ManifestConstants;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarker;
@@ -47,26 +48,6 @@
 
 public class AndroidManifestParser {
 
-    private final static String ATTRIBUTE_PACKAGE = "package"; //$NON-NLS-1$
-    private final static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
-    private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
-    private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
-    public final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
-    private final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
-    private final static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$
-    private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
-    private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
-    private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
-    private final static String NODE_SERVICE = "service"; //$NON-NLS-1$
-    private final static String NODE_RECEIVER = "receiver"; //$NON-NLS-1$
-    private final static String NODE_PROVIDER = "provider"; //$NON-NLS-1$
-    private final static String NODE_INTENT = "intent-filter"; //$NON-NLS-1$
-    private final static String NODE_ACTION = "action"; //$NON-NLS-1$
-    private final static String NODE_CATEGORY = "category"; //$NON-NLS-1$
-    private final static String NODE_USES_SDK = "uses-sdk"; //$NON-NLS-1$
-    private final static String NODE_INSTRUMENTATION = "instrumentation"; //$NON-NLS-1$
-    private final static String NODE_USES_LIBRARY = "uses-library"; //$NON-NLS-1$
-
     private final static int LEVEL_MANIFEST = 0;
     private final static int LEVEL_APPLICATION = 1;
     private final static int LEVEL_ACTIVITY = 2;
@@ -304,50 +285,55 @@
                     String value;
                     switch (mValidLevel) {
                         case LEVEL_MANIFEST:
-                            if (NODE_MANIFEST.equals(localName)) {
+                            if (ManifestConstants.NODE_MANIFEST.equals(localName)) {
                                 // lets get the package name.
-                                mPackage = getAttributeValue(attributes, ATTRIBUTE_PACKAGE,
+                                mPackage = getAttributeValue(attributes,
+                                        ManifestConstants.ATTRIBUTE_PACKAGE,
                                         false /* hasNamespace */);
                                 mValidLevel++;
                             }
                             break;
                         case LEVEL_APPLICATION:
-                            if (NODE_APPLICATION.equals(localName)) {
-                                value = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
+                            if (ManifestConstants.NODE_APPLICATION.equals(localName)) {
+                                value = getAttributeValue(attributes,
+                                        ManifestConstants.ATTRIBUTE_PROCESS,
                                         true /* hasNamespace */);
                                 if (value != null) {
                                     addProcessName(value);
                                 }
 
-                                value = getAttributeValue(attributes, ATTRIBUTE_DEBUGGABLE,
+                                value = getAttributeValue(attributes,
+                                        ManifestConstants.ATTRIBUTE_DEBUGGABLE,
                                         true /* hasNamespace*/);
                                 if (value != null) {
                                     mDebuggable = Boolean.parseBoolean(value);
                                 }
 
                                 mValidLevel++;
-                            } else if (NODE_USES_SDK.equals(localName)) {
+                            } else if (ManifestConstants.NODE_USES_SDK.equals(localName)) {
                                 mApiLevelRequirement = getAttributeValue(attributes,
-                                        ATTRIBUTE_MIN_SDK_VERSION, true /* hasNamespace */);
-                            } else if (NODE_INSTRUMENTATION.equals(localName)) {
+                                        ManifestConstants.ATTRIBUTE_MIN_SDK_VERSION,
+                                        true /* hasNamespace */);
+                            } else if (ManifestConstants.NODE_INSTRUMENTATION.equals(localName)) {
                                 processInstrumentationNode(attributes);
                             }
                             break;
                         case LEVEL_ACTIVITY:
-                            if (NODE_ACTIVITY.equals(localName)) {
+                            if (ManifestConstants.NODE_ACTIVITY.equals(localName)) {
                                 processActivityNode(attributes);
                                 mValidLevel++;
-                            } else if (NODE_SERVICE.equals(localName)) {
+                            } else if (ManifestConstants.NODE_SERVICE.equals(localName)) {
                                 processNode(attributes, AndroidConstants.CLASS_SERVICE);
                                 mValidLevel++;
-                            } else if (NODE_RECEIVER.equals(localName)) {
+                            } else if (ManifestConstants.NODE_RECEIVER.equals(localName)) {
                                 processNode(attributes, AndroidConstants.CLASS_BROADCASTRECEIVER);
                                 mValidLevel++;
-                            } else if (NODE_PROVIDER.equals(localName)) {
+                            } else if (ManifestConstants.NODE_PROVIDER.equals(localName)) {
                                 processNode(attributes, AndroidConstants.CLASS_CONTENTPROVIDER);
                                 mValidLevel++;
-                            } else if (NODE_USES_LIBRARY.equals(localName)) {
-                                value = getAttributeValue(attributes, ATTRIBUTE_NAME,
+                            } else if (ManifestConstants.NODE_USES_LIBRARY.equals(localName)) {
+                                value = getAttributeValue(attributes,
+                                        ManifestConstants.ATTRIBUTE_NAME,
                                         true /* hasNamespace */);
                                 if (value != null) {
                                     mLibraries.add(value);
@@ -356,24 +342,27 @@
                             break;
                         case LEVEL_INTENT_FILTER:
                             // only process this level if we are in an activity
-                            if (mCurrentActivity != null && NODE_INTENT.equals(localName)) {
+                            if (mCurrentActivity != null &&
+                                    ManifestConstants.NODE_INTENT.equals(localName)) {
                                 mCurrentActivity.resetIntentFilter();
                                 mValidLevel++;
                             }
                             break;
                         case LEVEL_CATEGORY:
                             if (mCurrentActivity != null) {
-                                if (NODE_ACTION.equals(localName)) {
+                                if (ManifestConstants.NODE_ACTION.equals(localName)) {
                                     // get the name attribute
-                                    String action = getAttributeValue(attributes, ATTRIBUTE_NAME,
+                                    String action = getAttributeValue(attributes,
+                                            ManifestConstants.ATTRIBUTE_NAME,
                                             true /* hasNamespace */);
                                     if (action != null) {
                                         mCurrentActivity.setHasAction(true);
                                         mCurrentActivity.setHasMainAction(
                                                 ACTION_MAIN.equals(action));
                                     }
-                                } else if (NODE_CATEGORY.equals(localName)) {
-                                    String category = getAttributeValue(attributes, ATTRIBUTE_NAME,
+                                } else if (ManifestConstants.NODE_CATEGORY.equals(localName)) {
+                                    String category = getAttributeValue(attributes,
+                                            ManifestConstants.ATTRIBUTE_NAME,
                                             true /* hasNamespace */);
                                     if (CATEGORY_LAUNCHER.equals(category)) {
                                         mCurrentActivity.setHasLauncherCategory(true);
@@ -473,13 +462,14 @@
          */
         private void processActivityNode(Attributes attributes) {
             // lets get the activity name, and add it to the list
-            String activityName = getAttributeValue(attributes, ATTRIBUTE_NAME,
+            String activityName = getAttributeValue(attributes, ManifestConstants.ATTRIBUTE_NAME,
                     true /* hasNamespace */);
             if (activityName != null) {
                 activityName = combinePackageAndClassName(mPackage, activityName);
 
                 // get the exported flag.
-                String exportedStr = getAttributeValue(attributes, ATTRIBUTE_EXPORTED, true);
+                String exportedStr = getAttributeValue(attributes,
+                        ManifestConstants.ATTRIBUTE_EXPORTED, true);
                 boolean exported = exportedStr == null ||
                         exportedStr.toLowerCase().equals("true"); // $NON-NLS-1$
                 mCurrentActivity = new Activity(activityName, exported);
@@ -495,7 +485,7 @@
                 mCurrentActivity = null;
             }
 
-            String processName = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
+            String processName = getAttributeValue(attributes, ManifestConstants.ATTRIBUTE_PROCESS,
                     true /* hasNamespace */);
             if (processName != null) {
                 addProcessName(processName);
@@ -510,7 +500,7 @@
          */
         private void processNode(Attributes attributes, String superClassName) {
             // lets get the class name, and check it if required.
-            String serviceName = getAttributeValue(attributes, ATTRIBUTE_NAME,
+            String serviceName = getAttributeValue(attributes, ManifestConstants.ATTRIBUTE_NAME,
                     true /* hasNamespace */);
             if (serviceName != null) {
                 serviceName = combinePackageAndClassName(mPackage, serviceName);
@@ -520,7 +510,7 @@
                 }
             }
 
-            String processName = getAttributeValue(attributes, ATTRIBUTE_PROCESS,
+            String processName = getAttributeValue(attributes, ManifestConstants.ATTRIBUTE_PROCESS,
                     true /* hasNamespace */);
             if (processName != null) {
                 addProcessName(processName);
@@ -534,11 +524,13 @@
          */
         private void processInstrumentationNode(Attributes attributes) {
             // lets get the class name, and check it if required.
-            String instrumentationName = getAttributeValue(attributes, ATTRIBUTE_NAME,
+            String instrumentationName = getAttributeValue(attributes,
+                    ManifestConstants.ATTRIBUTE_NAME,
                     true /* hasNamespace */);
             if (instrumentationName != null) {
                 String instrClassName = combinePackageAndClassName(mPackage, instrumentationName);
-                String targetPackage = getAttributeValue(attributes, ATTRIBUTE_TARGET_PACKAGE,
+                String targetPackage = getAttributeValue(attributes,
+                        ManifestConstants.ATTRIBUTE_TARGET_PACKAGE,
                         true /* hasNamespace */);
                 mInstrumentations.add(new Instrumentation(instrClassName, targetPackage));
                 if (mMarkErrors) {
diff --git a/scripts/plugin.prop b/scripts/plugin.prop
index 99dba4a..cda5d01 100644
--- a/scripts/plugin.prop
+++ b/scripts/plugin.prop
@@ -1,4 +1,4 @@
 # begin plugin.prop
-plugin.version=0.9.0
+plugin.version=0.9.1
 plugin.platform=android
 # end plugin.prop
\ No newline at end of file
diff --git a/sdkmanager/app/src/com/android/sdkmanager/Main.java b/sdkmanager/app/src/com/android/sdkmanager/Main.java
index aab8066..11fc508 100644
--- a/sdkmanager/app/src/com/android/sdkmanager/Main.java
+++ b/sdkmanager/app/src/com/android/sdkmanager/Main.java
@@ -425,7 +425,7 @@
                 if (target.getDescription() != null) {
                     mSdkLog.printf("     Description: %s\n", target.getDescription());
                 }
-                mSdkLog.printf("     Based on Android %s (API level %d)\n",
+                mSdkLog.printf("     Based on Android %s (API level %s)\n",
                         target.getVersionName(), target.getVersion().getApiString());
 
                 // display the optional libraries.
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
index a4b50ed..293d66a 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
@@ -32,7 +32,7 @@
      * String to compute hash for add-on targets.
      * Format is vendor:name:apiVersion
      * */
-    private final static String ADD_ON_FORMAT = "%s:%s:%d"; //$NON-NLS-1$
+    private final static String ADD_ON_FORMAT = "%s:%s:%s"; //$NON-NLS-1$
 
     private final static class OptionalLibrary implements IOptionalLibrary {
         private final String mJarName;
@@ -218,25 +218,20 @@
             return true;
         }
 
-        // if the receiver has no optional library, then anything with api version number >= to
-        // the receiver is compatible.
-        if (mLibraries.length == 0) {
-            return target.getVersion().getApiLevel() >= getVersion().getApiLevel();
+        // if the receiver has optional libraries, then the target is only compatible if the
+        // vendor and name are the same
+        if (mLibraries.length != 0 &&
+                (mVendor.equals(target.getVendor()) == false ||
+                        mName.equals(target.getName()) == false)) {
+            return false;
         }
 
-        // Otherwise, target is only compatible if the vendor and name are equals with the api
-        // number greater or equal (ie target is a newer version of this add-on).
-        if (target.isPlatform() == false) {
-            return (mVendor.equals(target.getVendor()) && mName.equals(target.getName()) &&
-                    target.getVersion().getApiLevel() >= getVersion().getApiLevel());
-        }
-
-        return false;
+        return mBasePlatform.equals(target);
     }
 
     public String hashString() {
         return String.format(ADD_ON_FORMAT, mVendor, mName,
-                mBasePlatform.getVersion().getApiLevel());
+                mBasePlatform.getVersion().getApiString());
     }
 
     @Override
@@ -250,10 +245,10 @@
             AddOnTarget addon = (AddOnTarget)obj;
 
             return mVendor.equals(addon.mVendor) && mName.equals(addon.mName) &&
-                mBasePlatform.getVersion().getApiLevel() == addon.mBasePlatform.getVersion().getApiLevel();
+                mBasePlatform.getVersion().equals(addon.mBasePlatform.getVersion());
         }
 
-        return super.equals(obj);
+        return false;
     }
 
     /*
@@ -267,17 +262,25 @@
             return +1;
         }
 
-        // vendor
+        // compare vendor
         int value = mVendor.compareTo(target.getVendor());
 
-        // name
+        // if same vendor, compare name
         if (value == 0) {
             value = mName.compareTo(target.getName());
         }
 
-        // api version
+        // if same vendor/name, compare version
         if (value == 0) {
-            value = getVersion().getApiLevel() - target.getVersion().getApiLevel();
+            if (getVersion().isPreview() == true) {
+                value = target.getVersion().isPreview() == true ?
+                        getVersion().getApiString().compareTo(target.getVersion().getApiString()) :
+                        +1; // put the preview at the end.
+            } else {
+                value = target.getVersion().isPreview() == true ?
+                        -1 : // put the preview at the end :
+                        getVersion().getApiLevel() - target.getVersion().getApiLevel();
+            }
         }
 
         return value;
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java
index ad4782f..61b348a 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java
@@ -172,12 +172,17 @@
             }
 
         } else if (obj instanceof String) {
+            // if we have a code name, this must match.
+            if (mCodename != null) {
+                return mCodename.equals((String)obj);
+            }
+
+            // else we try to convert to a int and compare to the api level
             try {
                 int value = Integer.parseInt((String)obj);
                 return value == mApiLevel;
             } catch (NumberFormatException e) {
-                // not a number? compare to the code name
-                return obj.equals(mCodename);
+                // not a number? we'll return false below.
             }
         }
 
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
index 911d379..0481d4c 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
@@ -26,8 +26,7 @@
  */
 final class PlatformTarget implements IAndroidTarget {
     /** String used to get a hash to the platform target */
-    private final static String PLATFORM_HASH_API_LEVEL = "android-%d";
-    private final static String PLATFORM_HASH_CODENAME = "android-%s";
+    private final static String PLATFORM_HASH = "android-%s";
 
     private final static String PLATFORM_VENDOR = "Android Open Source Project";
 
@@ -199,9 +198,9 @@
         }
 
         // if the platform has a codename (ie it's a preview of an upcoming platform), then
-        // both platform must be exactly identical.
+        // both platforms must be exactly identical.
         if (mVersion.getCodename() != null) {
-            return equals(target);
+            return mVersion.equals(target.getVersion());
         }
 
         // target is compatible wit the receiver as long as its api version number is greater or
@@ -210,11 +209,7 @@
     }
 
     public String hashString() {
-        if (mVersion.getCodename() != null) {
-            return String.format(PLATFORM_HASH_CODENAME, mVersion.getCodename());
-        }
-
-        return String.format(PLATFORM_HASH_API_LEVEL, mVersion.getApiLevel());
+        return String.format(PLATFORM_HASH, mVersion.getApiString());
     }
 
     @Override
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
index 7df2512..f23208a 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
@@ -448,31 +448,20 @@
                     displayAddonManifestError(log, addon.getName(), ADDON_API);
                     return null;
                 } else {
-                    try {
-                        int apiValue = Integer.parseInt(api);
-                        for (IAndroidTarget target : targetList) {
-                            if (target.isPlatform() && target.getVersion().equals(apiValue)) {
-                                baseTarget = (PlatformTarget)target;
-                                break;
-                            }
+                    // Look for a platform that has a matching api level or codename.
+                    for (IAndroidTarget target : targetList) {
+                        if (target.isPlatform() && target.getVersion().equals(api)) {
+                            baseTarget = (PlatformTarget)target;
+                            break;
                         }
+                    }
 
-                        if (baseTarget == null) {
-                            if (log != null) {
-                                log.error(null,
-                                        "Ignoring add-on '%1$s': Unable to find base platform with API level %2$d",
-                                        addon.getName(), apiValue);
-                            }
-
-                            return null;
-                        }
-                    } catch (NumberFormatException e) {
-                        // looks like apiNumber does not parse to a number.
+                    if (baseTarget == null) {
                         // Ignore this add-on.
                         if (log != null) {
                             log.error(null,
-                                    "Ignoring add-on '%1$s': %2$s is not a valid number in %3$s.",
-                                    addon.getName(), ADDON_API, SdkConstants.FN_BUILD_PROP);
+                                    "Ignoring add-on '%1$s': Unable to find base platform with API level '%2$s'",
+                                    addon.getName(), api);
                         }
                         return null;
                     }
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
index b69ae0e..79b55e3 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
@@ -74,10 +74,12 @@
         super(source, packageNode, licenses);

         mVendor   = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_VENDOR);

         mName     = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_NAME);

-        mVersion = new AndroidVersion(

-                XmlParserUtils.getXmlInt   (packageNode, SdkRepository.NODE_API_LEVEL, 0),

-                null); // add-ons on platform previews is not supported, so the codename is always

-                       // null in this case.

+        int apiLevel = XmlParserUtils.getXmlInt   (packageNode, SdkRepository.NODE_API_LEVEL, 0);

+        String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_CODENAME);

+        if (codeName.length() == 0) {

+            codeName = null;

+        }

+        mVersion = new AndroidVersion(apiLevel, codeName);

 

         mLibs = parseLibs(XmlParserUtils.getFirstChild(packageNode, SdkRepository.NODE_LIBS));

     }

@@ -181,10 +183,10 @@
     /** Returns a short description for an {@link IDescription}. */

     @Override

     public String getShortDescription() {

-        return String.format("%1$s by %2$s for Android API %3$d",

+        return String.format("%1$s by %2$s for Android API %3$s",

                 getName(),

                 getVendor(),

-                mVersion.getApiLevel());

+                mVersion.getApiString());

     }

 

     /** Returns a long description for an {@link IDescription}. */

@@ -229,7 +231,8 @@
         String name = suggestedDir;

 

         if (suggestedDir == null || suggestedDir.length() == 0) {

-            name = String.format("addon-%s-%s-%d", getName(), getVendor(), mVersion.getApiLevel()); //$NON-NLS-1$

+            name = String.format("addon-%s-%s-%s", getName(), getVendor(), //$NON-NLS-1$

+                    mVersion.getApiString());

             name = name.toLowerCase();

             name = name.replaceAll("[^a-z0-9_-]+", "_");      //$NON-NLS-1$ //$NON-NLS-2$

             name = name.replaceAll("_+", "_");                //$NON-NLS-1$ //$NON-NLS-2$

@@ -271,7 +274,7 @@
         String newId  = newPkg.getName() + "+" + newPkg.getVendor();  //$NON-NLS-1$

 

         return thisId.equalsIgnoreCase(newId) &&

-                mVersion.getApiLevel() == newPkg.getVersion().getApiLevel() &&

+                mVersion.equals(newPkg.getVersion()) &&

                 newPkg.getRevision() > this.getRevision();

     }

 }

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java
index c73eef6..ca78b0b 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java
@@ -212,7 +212,7 @@
                         null,                       //source

                         props,                      //properties

                         0,                          //apiLevel

-                        null,                       // codename

+                        null,                       //codename

                         0,                          //revision

                         null,                       //license

                         null,                       //description

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository.xsd b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository.xsd
index 291e57d..a697c83 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository.xsd
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository.xsd
@@ -86,6 +86,8 @@
                             <xsd:element name="vendor"    type="xsd:normalizedString" />
                             <!-- The Android API Level for the add-on. An int > 0. -->
                             <xsd:element name="api-level" type="xsd:positiveInteger"  />
+                            <!-- The optional codename for this add-on, if it's a preview. -->
+                            <xsd:element name="codename"  type="xsd:string" minOccurs="0" />
 
                             <!-- The revision, an int > 0, incremented each time a new
                                  package is generated. -->
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/ManifestConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/ManifestConstants.java
new file mode 100644
index 0000000..2e20f02
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/ManifestConstants.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 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.xml;
+
+/**
+ * Constants for nodes and attributes of the AndroidManifest.xml file.
+ *
+ */
+public final class ManifestConstants {
+
+    public final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
+    public final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
+    public final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
+    public final static String NODE_SERVICE = "service"; //$NON-NLS-1$
+    public final static String NODE_RECEIVER = "receiver"; //$NON-NLS-1$
+    public final static String NODE_PROVIDER = "provider"; //$NON-NLS-1$
+    public final static String NODE_INTENT = "intent-filter"; //$NON-NLS-1$
+    public final static String NODE_ACTION = "action"; //$NON-NLS-1$
+    public final static String NODE_CATEGORY = "category"; //$NON-NLS-1$
+    public final static String NODE_USES_SDK = "uses-sdk"; //$NON-NLS-1$
+    public final static String NODE_INSTRUMENTATION = "instrumentation"; //$NON-NLS-1$
+    public final static String NODE_USES_LIBRARY = "uses-library"; //$NON-NLS-1$
+
+    public final static String ATTRIBUTE_PACKAGE = "package"; //$NON-NLS-1$
+    public final static String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$
+    public final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
+    public final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
+    public final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
+    public final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
+    public final static String ATTRIBUTE_EXPORTED = "exported"; //$NON-NLS-1$
+}